class Society {
constructor(input_data, desease_data = null) {
this.pop_data = input_data;
this.historical = [];
this.historical.push(this.make_historical_entry());
for (const node of this.pop_data.nodes) {
node.status = "S";
}
if (!desease_data) {
this.desease_transmission_rate = desease_values[0][0];
this.desease_recovery_rate = desease_values[1][0];
this.desease_susceptibility_rate = desease_values[2][0];
this.desease_death_rate = desease_values[3][0];
} else {
this.desease_transmission_rate = desease_data.beta;
this.desease_recovery_rate = desease_data.gamma;
this.desease_susceptibility_rate = desease_data.theta;
this.desease_death_rate = desease_data.delta;
}
}
init(
n_infected_initial = 1,
n_immune_initial = 0,
n_immune_initial_perc = null
) {
this.pop_data.nodes = underscore.shuffle(this.pop_data.nodes);
if (n_immune_initial_perc)
n_immune_initial = n_immune_initial_perc * this.pop_data.nodes.length;
for (const i in this.pop_data.nodes) {
if (i < n_infected_initial) {
this.pop_data.nodes[i].status = "I";
} else if (i < n_infected_initial + n_immune_initial) {
this.pop_data.nodes[i].status = "R";
} else {
this.pop_data.nodes[i].status = "S";
}
}
}
data() {
return this.pop_data;
}
update() {
this.historical.push(this.make_historical_entry());
for (const node of this.pop_data.nodes) {
if (node.status == "S") {
for (const link of this.pop_data.links) {
// link has this node
if (link.source == node || link.target == node) {
const other = link.source == node ? link.target : link.source;
if (other.status == "I") {
// linked node can infect
if (Math.random() < this.desease_transmission_rate) {
node.status = "I";
}
}
}
}
} else if (node.status == "I") {
if (Math.random() < this.desease_recovery_rate) {
node.status = "R";
} else if (Math.random() < this.desease_death_rate) {
node.status = "D";
}
} else if (node.status == "R") {
if (Math.random() < this.desease_susceptibility_rate) {
node.status = "S";
}
}
}
}
make_historical_entry() {
return {
t: this.historical.length,
deaths: this.perc_deaths(),
infected: this.perc_infected()
};
}
count_susceptibles() {
return this.pop_data.nodes.reduce(
(acc, cur) => (cur.status == "S" ? acc + 1 : acc),
0
);
}
perc_infected() {
return (
this.pop_data.nodes.reduce(
(acc, cur) => (cur.status == "I" ? acc + 1 : acc),
0
) / this.pop_data.nodes.length
);
}
perc_deaths() {
return (
this.pop_data.nodes.reduce(
(acc, cur) => (cur.status == "D" ? acc + 1 : acc),
0
) / this.pop_data.nodes.length
);
}
}