/* Epidemic Simulator * Author: Douglas Jones * Status: MP1 solution; it works, but it is full of bugs. * Version: 9/16/2020 */ import java.util.LinkedList; import java.util.Iterator; import java.util.Scanner; import java.util.Random; import java.io.File; import java.io.FileNotFoundException; // Utility classes /** * People occupy places * @see Place */ class Person { // instance variables private final Place home; public final String name; // the collection of all instances private static final LinkedList allPeople = new LinkedList (); /** The only constructor * the person is constructed with a home */ public Person( Place h ) { name = super.toString(); home = h; h.addResident( this ); allPeople.add( this ); // this is the only place items are added! } /** Primarily for debugging * @return textual name and home of this person */ public String toString() { return name + " " + home.name; } /** Allow outsiders to iterate over all people * @return an iterator over people */ public static Iterator iterator() { return allPeople.iterator(); } } /** * Places are occupied by people * @see Person */ class Place { // instance variables public final String name; private final LinkedList residents = new LinkedList (); // the collection of all instances private static final LinkedList allPlaces = new LinkedList (); /** The only constructor for Place * Places are constructed with no occupants */ public Place() { name = super.toString(); allPlaces.add( this ); } /** Add a resident to a place * Should only be called from the person constructor * @param r a Person, the new resident */ public void addResident( Person r ) { residents.add( r ); // BUG -- check to see if the person already lives there? } /** Primarily for debugging * @return textual name and residents of the place */ public String toString() { String res = name; for (Person p: residents) { res = res + " " + p.name; } return res; } /** Allow outsiders to iterate over all places * @return an iterator over places */ public static Iterator iterator() { return allPlaces.iterator(); } } /** * Main class builds model and will someday simulate it * @see Person * @see Place */ public class Epidemic { /** Read the simulation parameters and build a community that they describe * Called only from the main method. */ private static void readCommunity( Scanner sc ) { // BUG -- is this the right place for the simulation parameters? int pop = -1; /* the target population */ int house = -1; /* the target household size average */ int var = -1; /* the target household size variation */ // everything has a default value // BUG -- these defaults all indicate failure to initialize while (sc.hasNext()) { // until the input file is finished String command = sc.next(); if ("pop".equals( command )) { // BUG -- what if the population was already set? // BUG -- what if there is no integer? pop = sc.nextInt(); // BUG -- what if there is no semicolon? sc.next( ";" ); } else if ("house".equals( command )) { // BUG -- what if the size was already set? // BUG -- what if there is no integer? house = sc.nextInt(); // BUG -- what if there is no comma? sc.next( "," ); // BUG -- what if there is no integer? var = sc.nextInt(); // BUG -- what if there is no semicolon? sc.next( ";" ); } else { System.out.println( "unknown command: " + command + "\n" ); } } // BUG -- no attempt to abort the following if key values not set! // now create the population // BUG -- should the following be a separate method, buildCommunity? { // must always have a home available as we create people int currentHomeCapacity = 0; Place currentHome = null; // need a source of random numbers // BUG -- does this go here? Random rand = new Random(); for (int i = 1; i <= pop; i++) { // create the population if (currentHomeCapacity < 1) { // must create a new home currentHome = new Place(); currentHomeCapacity = rand.nextInt( 2*var + 1 ) + house - var; } new Person( currentHome ); currentHomeCapacity = currentHomeCapacity - 1; } } } /** Output the community * Called only from the main method. * This code exists only for debugging. */ private static void writeCommunity() { System.out.println( "People" ); // Note: Not required in assignment for (Iterator i = Person.iterator(); i.hasNext(); ){ System.out.println( i.next().toString() ); } System.out.println( "Places" ); // Note: Not required in assignment for (Iterator i = Place.iterator(); i.hasNext(); ){ System.out.println( i.next().toString() ); } } /** The main method * This handles the command line arguments. * If the args are OK, it calls other methods to build and test a model. */ public static void main( String[] args ) { if (args.length < 1) { System.out.println( "Missing file name argument\n" ); } else try { readCommunity( new Scanner( new File( args[0] ) ) ); writeCommunity(); // BUG -- this is just for debugging // BUG -- need to actually add simulation code here } catch ( FileNotFoundException e) { System.out.println( "Can't open file: " + args[0] + "\n" ); } } }