Introduction

Assignment is a pandemic simulation. It randomizes the starting condition and plays the simulation out according to the simulation parameters and shows how many people are sick at any one point. It allows the user to explore the parameters being used live.

You are provided with a partially working template and a video of how the final product will work.

You are expected to fill in the incomplete methods. You may find it helpful to create tests for each of your methods since they will be tested with a test harness. We don't provide the test harness, you must correctly interpret the JavaDoc, we won't test anything not made clear in the JavaDoc.

However, quite a few of the methods are empty so it is not working well at all.

Class Relationship

Main runs the application by building a Population and stepping the simulation each 16 milliseconds. A Population is made of Stimulants.

Files to Complete

The two classes that you must work on are,

  • Population.java: 7 methods
  • Simulant.java: 1 method (compareTo)

The description for each method is provided as JavaDoc.

You are not required to edit other files. You will be able to tell if your implementations are correct by running the main application and seeing if all the functionality is there. However, we strongly encourage you to supplement this with unit tests because it is hard to test everything via use alone.


import java.util.*;
import java.awt.geom.*;

class Population {

public ArrayList< Simulant> sims = new ArrayList< Simulant>();
public Random rand = new Random();

public Population() {
for (int i = 0; i < Main.SIMS; i++) {
sims.add(new Simulant());
}

// make the first one sick
sims.get(0).sick = 1; // to be completed
}

/**
* update an entire population for each simulant update their location and
* illness then check each pair of simulants to see if they are in touch
* with one another. If they are, they might get sick
*/
public void update() {
for (Simulant s : sims) {
s.updateLoc();
s.updateIllness();
}
// check every pair of sims to see if they are in contact, if so, pass on any sickness
for (Simulant s1 : sims) {
for (Simulant s2 : sims) {
if (s1.loc.distance(s2.loc) < Simulant.SIZE) {
s1.sick = s1.sick == 0 && s2.sick > Main.CONT_AFTER && !s1.immune && rand.nextInt(100) < Main.TRANS_RATE ? 1 : s1.sick;
s2.sick = s2.sick == 0 && s1.sick > Main.CONT_AFTER && !s2.immune && rand.nextInt(100) < Main.TRANS_RATE ? 1 : s2.sick;
}
}
}
}

/**
* @return the average of the x locations of all sick simulants answer is
* zero if no sims are sick
*/
public double averageXOfSick() {
int numSimulantsFound = 0;
double totalXLocations = 0;

for (Simulant simulant : sims) {
if (simulant.sick > 0) {
totalXLocations += simulant.loc.getX();
numSimulantsFound++;
}
}

if (numSimulantsFound == 0) {
return 0;
}

return totalXLocations / numSimulantsFound;
}

/**
* @return the average of the y locations of all sick simulants answer is
* zero if no sims are sick
*
*/
public double averageYOfSick() {
}

/**
* @return the first sim found who's is over the given point you should use
* the whole area the simulant is drawn on (i.e. center plus radius) to
* determine if the sim is at this location. Return null if no sim found.
*
*/
public Simulant simAtLocation(Point2D loc) {
}

/**
* @param sim the simulant to find in the population
* @return the simulant one index greater than the given simulant. Return
* null if `sim` not found or there is no simulant after the found one.
*
*/
public Simulant nextAfter(Simulant sim) {
}

/**
* @param sim the simulant to find in the population
* @return the simulant one index less than the given simulant. Return null
* if `sim` not found or there is no simulant before the found one.
*
*/
public Simulant prevBefore(Simulant sim) {
}

/**
* @return the total number of sick simulants
*
*/
public int numberSick() {
}

/**
* @return An array list of all the simulants sorted by "sickness". Sorting
* order is determined by the `compareTo` method on the simulants.
*
*/
public ArrayList< Simulant> sort() {
}
}

import java.awt.geom.*;
import java.util.*;

class Simulant implements Comparable< Simulant> {

public static final int SIZE = 5;
public Point2D loc;
public int sick;
public boolean immune;

private double dir;
private double speed;
public Point2D homeLoc;
public double mobility;
private Random rand;

public Simulant() {
rand = new Random();
homeLoc = new Point2D.Double(rand.nextInt(Main.WIDTH), rand.nextInt(Main.HEIGHT));
loc = new Point2D.Double(homeLoc.getX(), homeLoc.getY());
sick = 0;
immune = false;
dir = Math.random() * 2 * Math.PI;
speed = Math.random();
mobility = rand.nextInt(Main.MAX_MOVE);
}

/**
* updates the location of the simulant on each animation frame according to
* it's movement settings
*/
public void updateLoc() {
if (sick >= 0) {
Point2D nLoc = (Point2D) loc.clone();
nLoc.setLocation(nLoc.getX() + speed * Math.cos(dir),
nLoc.getY() + speed * Math.sin(dir));

if (nLoc.distance(homeLoc) > mobility || nLoc.getX() < 0 || nLoc.getY() < 0 || nLoc.getX() > Main.WIDTH || nLoc.getY() > Main.HEIGHT) {
dir = Math.random() * 2 * Math.PI;
} else {
loc = nLoc;
}
}
}

/**
* adjusts the simulant's illness status according to the rules * of the
* illness. Is asymptomatic for 240 frames, then is ill * with a 3% chance
* of dying and then is immune if they survive * to 240 frames
*
*/
public void updateIllness() {
if (sick > Main.CONT_AFTER) {
if (rand.nextInt((Main.ILL_FOR - Main.CONT_AFTER) * 100) < Main.DEATH_RATE) {
sick = -1;
}
}
if (sick > 0) {
sick++;
}
if (sick > Main.ILL_FOR) {
sick = 0;
immune = true;
}

}

/**
* compares simulants using sickness. A simulant who is earlier in their
* sickness is "less than" one later in their sickness. A simulant who is
* dead is "less than" any other. A simulant who is immune is "greater than"
* any that is sick. A simulant that has never been sick is "less than" one
* that has been sick.
*
* @return 0 if this simulant is equal to the other, less than zero if it is
* less than and greater than zero if it is greater than
*
*/
@Override
public int compareTo(Simulant other) {
}
}
Academic Honesty!
It is not our intention to break the school's academic policy. Posted solutions are meant to be used as a reference and should not be submitted as is. We are not held liable for any misuse of the solutions. Please see the frequently asked questions page for further questions and inquiries.
Kindly complete the form. Please provide a valid email address and we will get back to you within 24 hours. Payment is through PayPal, Buy me a Coffee or Cryptocurrency. We are a nonprofit organization however we need funds to keep this organization operating and to be able to complete our research and development projects.