JavaScript Pandemic Simulator

A SIR model simulator using p5.js library

Lorenzo Felletti
The Startup
5 min readMay 5, 2020

--

Covid-19 spread map
Photo by Giacomo Carra on Unsplash

Being forced at home due to Italy’s lockdown, I had to find something to do, then finally someone gave me the idea: why don’t you create a SIR Model simulator? He was suggesting to create something like the simulations you can find here. The idea was interesting, so I decided to give it a try (here’s the final result, and here’s the code).

Final result (as of 05–05–2020, may change a bit in the future…or may not (: )

All I knew when I started were HTML, CSS, and JavaScript basics, and I mean the very basics. So with a little knowledge and a lot of time, I started to search how to make animations in JS.

The implementation

Choosing the right library

With ‘right’ I honestly mean ‘simple for me’ library. After a lot of research, that went from trying to handle an HTML canvas or SVG without any library to the famous D3.js, to other libraries I don’t even remember their name, I finally came up with p5.js and decided I would be using it. That was because there are a lot of useful examples of it, but above all, because I find it to be pretty straightforward and easy to use.

The animation

The animation would have been as simple as that:

  • some balls are moving in a canvas
  • the balls can be in one of the three SIR states (yellow for the S, red for the I, green for the R)
  • whenever an Infectious ball touches a Susceptible one, there is a certain probability that the latter also becomes Infectious
  • after a given amount of time, the Infectious balls change their status and become Recovered (i.e. healed from the disease and now immune to it).

I also wanted some settable parameters: the population size, the infection probability, the recovery time, and the balls’ speed.

The difficult part was to detect the collision between the balls and to calculate their speed after the collision. Luckily, I found this p5 example which creates exactly some moving balls and implements collision detection. I started with it as a base and then adapted it to my use case. I also tried to improve the performances where I had the occasion (for example, I’m comparing the balls distances squared, so the browser doesn’t have to do the square root over and over again).

For the customizable parameters, I added a form from where to take the input parameters.

The form

The most difficult part of making the form was to make it intuitive and aesthetically pleasing. To achieve this, I decided to opt for ranges to tweak the parameters. Although ranges make it difficult to set a particular value, it’s way easier to set one as you don’t need to type any value, and they also offer an easier way to handle the input check as values are all in the specified range, and you don’t need to alert the users of which values are allowed and which are not.

When the first version was finished, I wanted to add a way to restart the animation with the current parameters’ values, so I added a ‘restart’ button. Later I decided to add a reset button too, which restart the animation resetting the parameters to the default values.

What I’ve learned

I won’t write much about the code (if any) since you can find it on GitHub, as I want to tell you some interesting things that I’ve learned in developing this simulation.

When you start coding without a plan, often then adding features or fixing bugs becomes very hard.

The first thing I’ve learned is that often if you just start coding without much of a plan, it turns out that adding the most trivial features or fixing the most simple bug can become very hard.

As an example, when I decided to add the reset button (after I already had added the restart one) I had to completely rethink how those parameters were passed to the animation and how to reuse the same event handler both to restart and to reset the animation, since the operation is essentially the same, just the parameters I have to pass are different. Some problems were to think about who should have kept those default values, and after some time I decided that it should have been a simulation responsibility, so I created a handler that was used for every form operations and just sends an empty argument to the animation reset function — that is not a function that handles the reset button only, but every time the simulation has to restart — and all the unset parameters are set to default.

Trust in your capabilities

Another thing I learned, and want to share with you, is that sometimes you have to trust in your capabilities and try to solve a problem, or adding a feature, developing it all by yourself instead of trying to find a framework or library that implements it, for at least two reasons:

  1. you can learn a lot by doing something all by yourself
  2. it could turn out that the time you will spend to learn how to use a library to do only a particular thing is way more (and less useful) than the time you will spend implementing or fixing something all by yourself.

Trying to fix bugs or errors improves stimulates creativity

Yet another important thing I’ve learned is that doing errors and trying to fix them as you progress with your journey as a developer stimulate a lot your creativity, and over time your skills will dramatically improve with this trial & error approach. You will also be much more motivated than following an online tutorial, guide, or whatever, just to learn something new.

Always try to improve your code writing skills

The last thing I want to share with you is this: when you develop, always try to find if there is a more elegant way to do the same thing you’ve implemented. Over time, try as much as you can to learn new, and hopefully more efficient, ways to solve the exact same problem, don’t stick with your usual ways of thinking, coding, and even debugging (I admit, I’m a bit lazy on this last one) because this will put more “strings to your bow” and in new situations, you could switch through more ways to solve a problem and appropriately chose the more efficient one. I’m not only talking about syntactical constructs, but also patterns and whatever else gives you the chance to opt for multiple ways of doing it.

Conclusion

Testing IRL your knowledge puts you in front of the eternal challenge of turning theory into practice

In conclusion, I find that working on a project is a huge motivation for me to learn than just study for the sake of knowledge (even if this is extremely important, I’m not saying the opposite). Testing ‘in real life’ your knowledge is always a good thing and puts you in front of the eternal challenge of turning theory into practice.

--

--