package simulations
import math.random
class EpidemySimulator extends Simulator {
def randomBelow(i: Int) = (random * i).toInt
def randomTo(i: Int) = (random * (i+1)).toInt
protected[simulations] object SimConfig {
val population: Int = 300
val roomRows: Int = 8
val roomColumns: Int = 8
// to complete: additional parameters of simulation
val incubationTime = 6
val dieTime = 14
val immuneTime = 16
val healTime = 18
val prevalenceRate = 0.01
val transRate = 0.4
val dieRate = 0.25
}
import SimConfig._
val persons: List[Person] =
for {
i <- (0 until population).toList
} yield {
val p = new Person(i)
if (i < population * prevalenceRate)
p.setInfected()
p.mode()
p
}
class Person(val id: Int) {
var infected = false
var sick = false
var immune = false
var dead = false
// demonstrates random number generation
var row: Int = randomBelow(roomRows)
var col: Int = randomBelow(roomColumns)
def setInfected() {
infected = true
afterDelay(incubationTime)(setSick)
afterDelay(dieTime)(setDead)
afterDelay(immuneTime)(setImmune)
afterDelay(healTime)(setHealthy)
}
def setSick() {
sick = true
}
def setDead() {
if (random < dieRate)
dead = true
}
def setImmune() {
if (dead) return
sick = false
immune = true
}
def setHealthy() {
if (dead) return
immune = false
infected = false
}
def mode() {
val moveDelay = randomTo(5)
afterDelay(moveDelay)(move)
}
def move() {
if (dead) return
// Move to a neighbor room
val neighbors = List(((row - 1 + roomRows) % roomRows, col),
((row + 1) % roomRows, col),
(row, (col - 1 + roomColumns) % roomColumns),
(row, (col + 1) % roomColumns))
def isHealthy(room: (Int, Int)): Boolean = room match {
case (r, c) => (persons.find { p => p.row == r && p.col == c && (p.sick || p.dead) }).isEmpty
}
val candidates = neighbors filter isHealthy
if (!candidates.isEmpty) {
val candidate: (Int, Int) = candidates(randomBelow(candidates.length))
candidate match {
case (a, b) => row = a; col = b
}
}
if (!immune && !infected)
if (random < transRate)
if (!(persons.find { p => p.row == row && p.col == col && p.infected }).isEmpty)
setInfected()
mode()
}
}
}