COVID-19 Disease Spreading Simulation

At the moment, the world is fighting COVID-19. There have been many scientists who made simulations to demonstrate how the disease would spread. There was one simulation which I liked. It was a video in which people were put up as a dot that moved around the canvas. I want to reproduce that in JavaScript and make it tunable.




 View this in a new tab: Click Here


First, let us create a canvas div, in which all the people would exist. I am feeling a bit lazy to create a separate stylesheet. I will keep all the styles within the HTML Tags.

<div id="canvas" style="position: absolute; width: 500px; height: 500px; background: #efefef"></div>
Next, let us define a class named Person. The person starts at a random coordinate and moves in a random direction.

const maxVel = 5;
class Person{
    constructor(){
        this.div = document.createElement("div");
        this.div.style.width = "4px";
        this.div.style.height = "4px";
        this.div.style.borderRadius = "50%";
        this.div.style.background = "#000000";
        this.div.style.position = "absolute";
     
        // Init position
        this.div.style.left = Math.random() * 500;
        this.div.style.top = Math.random() * 500;
     
        // Init velocity
        this.Velx = Math.random() * maxVel;
        this.Vely = Math.random() * maxVel;
     
        document.getElementById("canvas").appendChild(this.div);
     
        this.updatePosition(this);
    }
 
    updatePosition(that){
        setInterval(function(){
            that.div.style.left = that.div.offsetLeft + that.Velx;
            that.div.style.top = that.div.offsetTop + that.Vely;
         
            if((that.div.offsetLeft >= 500 && that.Velx > 0) || (that.div.offsetLeft <= 0 && that.Velx < 0))
                that.Velx = - that.Velx;
            if((that.div.offsetTop >= 500 && that.Vely > 0) || (that.div.offsetTop <= 0 && that.Vely < 0))
                that.Vely = - that.Vely;
        },50);
    }
}
Now, if we can simply create a few objects of the class Person and watch the animation.
for(var i = 0; i < 20; i++){
    new Person();
}



Now, let's bring in the disease factor. Let us make the following assumptions:
  • If a healthy person comes close to a sick person by a certain distance, the healthy person gets infected.
  • The person has a small probability of dying at every time step.
  • After a certain amount of time, the sick person gets cured.
  • Once cured, the person shall no longer get sick ever again as the person gained immunity.
I went ahead with implementing it. It would be hard to explain everything step by step, but just have a look at the final code.

The following is the final HTML part:
<div id="canvas" style="position: absolute; width: 500px; height: 500px; background: #efefef; z-index: 900"></div>
<div style="position:absolute;z-index: 999;">
    <div id="numHealthy" style="display:block;"></div>
    <div id="numSick" style="display:block;"></div>
    <div id="numCured" style="display:block;"></div>
    <div id="numDead" style="display:block;"></div>
</div>
And the JavaScript Part:
const numInitHealthyPeople = 30;
const numInitSickPeople = 2;
const maxVel = 5;
const curePeriod = 50;
const killProbability = 0.005;
const spreadRadius = 20;
const divHealthy = document.getElementById("numHealthy");
const divSick = document.getElementById("numSick");
const divCured = document.getElementById("numCured");
const divDead = document.getElementById("numDead");
class Person{
    static allPersons = [];
    constructor(isSick = false){
        this.div = document.createElement("div");
        this.div.style.width = "4px";
        this.div.style.height = "4px";
        this.div.style.borderRadius = "50%";
        this.div.style.background = "#000000";
        this.div.style.position = "absolute";
     
        // Init position
        this.div.style.left = Math.random() * 500;
        this.div.style.top = Math.random() * 500;
     
        // Init velocity
        this.Velx = Math.random() * maxVel;
        this.Vely = Math.random() * maxVel;
     
        document.getElementById("canvas").appendChild(this.div);
     
        if(isSick){
            this.getSick(this);
        }
        this.sickDuration = 0;
        this.isCured = false;
        this.isDead = false;
     
        this.update(this);
     
        Person.allPersons.push(this);
    }
 
    update(that){
        var updateVar = setInterval(function(){
            // Position and Velocity:
            that.div.style.left = that.div.offsetLeft + that.Velx;
            that.div.style.top = that.div.offsetTop + that.Vely;
         
            if((that.div.offsetLeft >= 500 && that.Velx > 0) || (that.div.offsetLeft <= 0 && that.Velx < 0))
                that.Velx = - that.Velx;
            if((that.div.offsetTop >= 500 && that.Vely > 0) || (that.div.offsetTop <= 0 && that.Vely < 0))
                that.Vely = - that.Vely;
         
            // Receive disease if sick people nearby
            if(!(that.isCured || that.isSick)){
                for(var i = 0; i < Person.allPersons.length; i++){
                    var person2 = Person.allPersons[i];
                    // if person is nearby
                    if(person2.isSick){
                        var dist = Math.sqrt(Math.pow(that.div.offsetLeft - person2.div.offsetLeft, 2) + Math.pow(that.div.offsetTop - person2.div.offsetTop, 2));
                        if(dist < spreadRadius){
                            that.getSick(that);
                            break;
                        }
                    }
                }
            }
         
            // Sickness
            if(that.isSick){
                that.sickDuration++;
                if(that.sickDuration > curePeriod){
                    that.getCured(that);
                } else {
                    // Kill with probability:
                    if(Math.random() < killProbability){
                        that.kill(that);
                        clearInterval(updateVar);
                    }
                }
            }
            // Statistics Display:
            divHealthy.innerText = "Healthy: " + numHealthyPeople;
            divSick.innerText = "Sick: " + numSickPeople;
            divCured.innerText = "Cured: " + numCuredPeople;
            divDead.innerText = "Dead: " + numDeadPeople;
         
        },100);
    }
 
    getCured(that){
        that.isSick = false;
        that.isCured = true;
        that.div.style.background = "#00ff00";
        numCuredPeople++;
        numSickPeople--;
    }
 
    getSick(that){
        that.isSick = true;
        that.div.style.background = "#ff0000";
        numSickPeople++;
        numHealthyPeople--;
    }
 
    kill(that){
        that.div.parentElement.removeChild(that.div);
        that.isDead = true;
        numDeadPeople++;
        numSickPeople--;
    }
}
var numHealthyPeople = numInitHealthyPeople + numInitSickPeople;
var numSickPeople = 0; // get sick is called in the constructor
var numCuredPeople = 0;
var numDeadPeople = 0;
for(var i = 0; i < numInitHealthyPeople; i++){
    new Person();
}
for(var i = 0; i < numInitSickPeople; i++){
    new Person(true);
}
You can open up this code in GitHub using the following link:

https://github.com/zenineasa/DiseaseSpreadSimulator

Comments

Popular posts from this blog

Interactive Monty Hall Problem Implementation

Attempt to Draw a Clip Art of a person using JavaScript

Smart Containers - An old project during my college days that could make Amazon better