Infectious Disease Poster Program/Data Page

From CSclasswiki
Jump to: navigation, search

Go back to: Visualizing the Transit Map of the Spread of an Infectious Disease

Run Time Testing


--Kyra Gan 17:05, 21 October 2016 (EDT)

program runtime record


Here is the recorded details of each runtime: runtime.csv

TestSimulateAll.java


1. Download TestSimulationAll.java and TestData5.csv; save them under the same directory.
2. Modify constants class.
3. Run the program from terminal(after directing to the correct folder):

  javac TestSimulationAll.java
  time java -cp . TestSimulationAll


This will give the runtime result that we desire.

This class contains all necessary subclasses:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
import java.util.Map.Entry;
/**
 * @version 10/20/2016
 * @author kyragan
 * Test total runtime for simulations
 * 
 */
public class TestSimulationAll {
	
	class Time {
		final String date; // Mon,Tu,Wed,Th,Fri,Sa,Su
		final int startT; // want them to be integer so we can take the difference later
		int endT=-1; // we set -1 to be the null case (it is going to be 0 in some case in
					// some status related classes)
		int daycount=0; //this variable is going to be used in the status hash table ONLY
						//for the purpose of clarity, we will only use day count the 
						//length between startT and endT
						//the null is 0
		List<String> DDate=Arrays.asList("Mon","Tu","Wed","Th","Fri","Sa","Su");

		Time(String date,int startT, int endT){
			this.date=date;
			this.startT=startT;
			this.endT=endT;
		}
		
		//for the student status hash table ONLY
		Time(String date, int startT){
			this.date=date;
			this.startT=startT;
		}
		
		String getDate(){
			return date;
		}
		
		int getStartT(){
			return startT;
		}
		
		int getEndT(){
			return endT;
		}
		
		int getDaycount(){
			return daycount;
		}
		
		//We are going to use the following 3 methods when simulating the virus spread
		
		void setEndT(int endT){
			this.endT=endT;
		}
		
		void setDaycount(int daycount){
			this.daycount=daycount;
		}
		
		void increaseDaycount(){
			daycount+=1;
		}
		
		//since when adding an entry in PlaceValue and StudentValue
		//we want them to be time ordered, thus we have a timeOrder calculator here
		//timeOrder= a five digit number, where the highest digit=dateIndex,
		//the next four digit is the startT. 
		int timeOrder(){
			return DDate.indexOf(date)*10000+startT;
		}
		
		int dayOfTheWeek(){
			return DDate.indexOf(date)+1;
		}
		String nextDate(){
			return DDate.get((DDate.indexOf(date)+1)%7);
		}
		
		public String toString(){
			return String.format("date=%s,startT=%d,endT=%d,daycount=%d", date,startT,endT,daycount);
		}
		
		boolean equals(Time t2){
			if(date.equals(t2.getDate())){
				if(startT==t2.getStartT()){
					if(endT==t2.getEndT()){
						if(daycount==t2.daycount){
							return true;
						}
					}
				}
			}
			return false;
		}
		
		public String toCSV(){
			return date+","+startT+","+endT+","+daycount+",";
			
		}
	}

	class StudentValue {
		ArrayList<StudentTimeEntry> STE=new ArrayList<StudentTimeEntry>();
		String houseCode;
		
		StudentValue(String houseCode){
			this.houseCode=houseCode;
		}
		StudentValue(String houseCode, StudentTimeEntry Ety){
			this.houseCode=houseCode;
			STE.add(Ety);
		}

		//when adding another time entry we want things to be ordered
		//we also want the function to return false if there is time overlap 
		boolean addSTE(StudentTimeEntry Ety){
			for(int i=0;i<STE.size();i++){
				//first we check whether the dates are the same
				if(STE.get(i).time.date.equals(Ety.time.date)){
					if(STE.get(i).time.startT<Ety.time.startT & Ety.time.startT<STE.get(i).time.endT){
						return false;
					}
					if(STE.get(i).time.startT<Ety.time.endT & Ety.time.startT<STE.get(i).time.endT){
						return false;
					}
				}
				//we want the order to be from the smallest to the biggest
				if (Ety.time.timeOrder()<STE.get(i).time.timeOrder()){
					STE.add(i,Ety);
					return true;
				}
			}
			STE.add(Ety);
			return true;
		}
		
		String getHouseCode(){
			return houseCode;
		}
		
		ArrayList<StudentTimeEntry> getSTE(){
			return STE;
		}
		String newline = System.getProperty("line.separator");
		public String toString(){
			String sv="";
			sv+=String.format("house code=%s", houseCode)+newline;
			for(int i=0;i<STE.size();i++){
				sv+=STE.get(i).toString();
			}
			return sv;
		}
	}
	class StudentTimeEntry {
		
		Time time;
		String place;
		StudentTimeEntry(Time time,String place){
			this.time=time;
			this.place=place;
		}
		
		Time getTime(){
			return time;
		}
		
		String getPlace(){
			return place;
		}
		
		String newline = System.getProperty("line.separator");
		public String toString(){
			String myste="";
			myste+=String.format("place=%s,", place);
			myste+="Time: "+ time.toString()+newline;
			return myste;
		}
		
	}
	class StatusValue {
		Status st;
		String source;
		ArrayList<Recipient> stRecpt=new ArrayList<Recipient>();
		ArrayList<String> RecipientID=new ArrayList<String>();

		StatusValue(String source,Status st){
			this.st=st;
			this.source=source;
		}

		StatusValue(String source,Status st, ArrayList<Recipient> stRecpt){
			this.st=st;
			this.source=source;
			this.stRecpt=stRecpt;
			for(int i=0;i<stRecpt.size();i++){
				ArrayList<String> myID=stRecpt.get(i).ID;
				for(int j=0;j<myID.size();j++){
					RecipientID.add(myID.get(j));
				}
			}
		}

		//objective: do not add the same recipient twice under different time
		//addrecp only apply when (st.getCurrentDate()).equals(r.getTime().getDate())
		boolean addrecp(Recipient r){
			if(!st.checkContagious()){
				return false;
			}
			if(st.CEndTimeExist()){
				return false;
			}

			if(!r.getTime().getDate().equals(st.getCurrentDate())){
				return false;
			}


			//find out whether we have overlaps 		
			for(int i=0;i<RecipientID.size();i++){
				if(r.getID().contains(RecipientID.get(i))){
					return false;
				}
			}

			//iterate through the list to see whether there is same starting time
			for(int i=0;i<stRecpt.size();i++){
				Recipient myr=stRecpt.get(i);
				if(myr.getWeek()==r.getWeek()){
					if(myr.getTime().timeOrder()==(r.getTime().timeOrder())){
						myr.addID(r.getID());

						RecipientID.addAll(r.getID());

						return true;
					}
					//want recipient also to be time ordered
					if(r.getTime().timeOrder()<myr.getTime().timeOrder()){
						stRecpt.add(i,r);

						RecipientID.addAll(r.getID());

						return true;
					}
				}
			}
			//let's see whether we will use the above part later
			stRecpt.add(r);
			RecipientID.addAll(r.getID());
			return true;
		}

		 Status getSt(){
			return st;
		}
		String getSource(){
			return source;
		}

		ArrayList<Recipient> getStRecpt(){
			return stRecpt;
		}

		ArrayList<String> getRecipientID(){
			return RecipientID;
		}

		String newline = System.getProperty("line.separator");
		public String toString(){
			String mystatusvalue="";
			mystatusvalue+=String.format("source=%s,", source)+newline;
			mystatusvalue+="status: "+st.toString()+newline;
			mystatusvalue+="recepient:"+newline;
			for(int i=0;i<stRecpt.size();i++){
				mystatusvalue+=stRecpt.get(i).toString();
			}
			return mystatusvalue;
		}
		public String toStringV2(){
			String mystatusvalue="";
			mystatusvalue+=String.format("source=%s,", source)+newline;
			mystatusvalue+="status: "+st.toString()+newline;
			mystatusvalue+="recepient:"+newline;
			for(int i=0;i<stRecpt.size();i++){
				mystatusvalue+=stRecpt.get(i).toStringV2();
			}
			return mystatusvalue;
		}
		public String toCSV(){
			String csv= source+","+RecipientID.size()+","+st.toCSV();
			for(int i=0;i<stRecpt.size();i++){
				csv+=stRecpt.get(i).toCSV();
			}
			return csv;
		}
		public String toCSVV2(){
			String csv= source+","+st.toCSV();
			for(int i=0;i<stRecpt.size();i++){
				csv+=stRecpt.get(i).toCSVV2();
			}
			return csv;
		}
		public String toCSVV3(){
			return source+","+RecipientID.size()+","+st.getinfectionDay()+",";
		}
	}
	class Status {
		int week; // we need to track when the student first get infected
					// after that, we can use the daycount variable in our Time class
		
		//default setting of incubation and contagious stage length setting
		int incubationLimit=Constants.incubationLimit;
		int contagiousLimit=Constants.contagiousLimit;
		
		Time incubation;
		Time NullTime=new Time("a",-1,-1);
		Time contagious=NullTime;
		
		List<String> DDate=Arrays.asList("Mon","Tu","Wed","Th","Fri","Sa","Su");

		Status(Time incubation,Time contagious, int week){
			this.incubation=incubation;
			this.contagious=contagious;
			this.week=week;
		}
		
		Status(Time incubation, int week){
			this.incubation=incubation;
			this.week=week;
		}
		
		Time getIncubation(){
			return incubation;
		}
		
		Time getContagious(){
			return contagious;
		}
		
		int getWeek(){
			return week;
		}
		
		int getIncubationLimit(){
			return incubationLimit;
		}
		
		int getContagiousLimit(){
			return contagiousLimit;
		}
		
		//return the infection day of the semester
		int getinfectionDay(){
			return week*7+incubation.dayOfTheWeek();
		}

		boolean setIncubationEndTime(int endT, int daycount){
			if (incubation.getEndT()!=-1){
				return false;
			}
			incubation.setEndT(endT);
			incubation.setDaycount(daycount);
			return true;
		}
		
		
		boolean IncreaseIncubationDaycount(){
			if(IEndTimeExist()){
				return false;
			}
			if(incubation.getDaycount()<(incubationLimit-1)){
				incubation.increaseDaycount();
				return true;
			}
			if(incubation.getDaycount()==(incubationLimit-1)){
				int startT=incubation.getStartT();
				//set the incubation end time and initialize the contagious
				setIncubationEndTime(startT,incubationLimit);
				Time mycontagious=new Time(DDate.get((DDate.indexOf(incubation.getDate())
						+incubationLimit)%7),startT);
				setContagious(mycontagious);
				return true;
			}
			return false;
		}
		
		boolean setContagious(Time contagious){
			//if contagious is already initialized
			if(checkContagious()){
				return false;
			}
			this.contagious=contagious;
			return true;
		}
		

		boolean IncreaseContagiousDaycount(){
			if(!checkContagious()){
				return false;
			}
			if(CEndTimeExist()){
				return false;
			}
			if(contagious.getDaycount()<(contagiousLimit-1)){
				contagious.increaseDaycount();
				return true;
			}else{
				setContagiousEndTime(contagious.getStartT(),contagiousLimit);
				return true;
			}
		}
		
		boolean setContagiousEndTime(int endT, int daycount){
			if(!checkContagious()){
				return false;
			}
			if(CEndTimeExist()){
				return false;
			}
			contagious.setEndT(endT);
			contagious.setDaycount(daycount);
			return true;
		}
		
		boolean CEndTimeExist(){
			if(contagious.getEndT()==-1){
				return false;
			}
			return true;
		}
		
		boolean IEndTimeExist(){
			if(incubation.getEndT()==-1){
				return false;
			}
			return true;
		}
		
		//if contagious is nulltime, return false
		boolean checkContagious(){
			return !contagious.equals(NullTime);
		}
		
		//return the current date in this status according to values stored in this status
		String getCurrentDate(){
			if(!IEndTimeExist()){
				return DDate.get((DDate.indexOf(incubation.getDate())
						+incubation.getDaycount())%7);
			}
			if(!CEndTimeExist()){
				return DDate.get((DDate.indexOf(contagious.getDate())
						+contagious.getDaycount())%7);
			}
			String date=DDate.get((DDate.indexOf(contagious.getDate())
					+contagiousLimit)%7);
			return "date exit contagious: "+date+" under Remission";
		}
		
		String newline = System.getProperty("line.separator");
		public String toString(){
			String mystatus="";
			mystatus+=String.format("week=%d,", week)+newline;
			mystatus+="incubation time:"+incubation.toString()+newline;
			mystatus+="contagious time:"+contagious.toString();
			return mystatus;
		}
		
		public String toCSV(){
			return week+","+incubation.toCSV()+contagious.toCSV();
		}
	}

	class Recipient {
		int week; //keep track of the week.
		//notice here for time, all endT are null=-1!
		Time time;
		ArrayList<String> ID=new ArrayList<String>();
		String place;
		
		//we only want to initialize week and time here.
		Recipient(String place, int week, Time time){
			this.time=time;
			this.week=week;
			this.place=place;
		}
		
		Recipient(String place, int week, Time time, ArrayList<String> ID){
			this.time=time;
			this.week=week;
			this.ID=ID;
			this.place=place;
		}
		
		//allow us to add the id s separately
		boolean addID(ArrayList<String> id){
			for(int i=0;i<id.size();i++){
				if(ID.contains(id.get(i))){
					System.out.println("Recipient.addID(A<s>):let's debug");
					return false;
				}
			}
			ID.addAll(id);
			return true;
		}
		
		int getWeek(){
			return week;
		}
		
		Time getTime(){
			return time;
		}
		
		ArrayList<String> getID(){
			return ID;
		}
		
		String getPlace(){
			return place;
		}
		
		String toStringArrayList(ArrayList<String> as){
			String myarr="";
			for(int i=0;i<as.size();i++){
				myarr+=as.get(i)+"|";
			}
			return myarr;
		}
		String newline = System.getProperty("line.separator");
		
		public String toString(){
			String re="";
			re+=String.format("place=%s,week=%d,",place,week);
			re+=time.toString()+"|";
			re+=toStringArrayList(ID)+newline;
			return re;
		}
		
		public String toCSVArrayList(ArrayList<String> as){
			String a="";
			for (int i=0;i<as.size();i++){
				a+=as.get(i)+",";
			}
			return a;
		}
		
		public String toCSV(){
			return place+","+week+","+time.toCSV()+toCSVArrayList(ID);
		}
		public String toStringV2(){
			String re="";
			int day=week*7+time.dayOfTheWeek();
			re+=String.format("place=%s,day=%d,startT=%d,",place,day,time.getStartT());
			re+=toStringArrayList(ID)+newline;
			return re;
		}
		public String toCSVV2(){
			int day=week*7+time.dayOfTheWeek();
			return place+","+day+","+time.getStartT()+","+toCSVArrayList(ID);
		}
	}

	class Probability {
		Random randomGenerator = new Random();

		Probability(){

		}

		//create an integer random number generator
		int myRandn(int startRange, int EndRange){
			if(startRange!=EndRange){
				return startRange+randomGenerator.nextInt(EndRange-startRange);
			}else{
				return startRange;
			}
		}

		//this is the deterministic probability of a healthy student in a given place getting 
		//infected
		float infectionProbability(int contagiousN){
			if(Constants.infectionProbability>1){
				System.out.println("Constants.infectionProbability: probability cannot be"
						+ "greater than 1");
				System.exit(0);
			}
			float p=Constants.infectionProbability*contagiousN;
			return Math.min(1, p);
		}

		//this is the deterministic probability of a vaccinated student in a given place getting 
		//infected
		public float vaccineContagiousProbability(int contagiousN){
			if(!Constants.vaccination){
				if(Constants.vaccineContagiuosProbability>1){
					System.out.println("Constants.vaccineContagiuosProbability: probability cannot be"
							+ "greater than 1");
					System.exit(0);
				}
				float p=Constants.vaccineContagiuosProbability*contagiousN;
				return Math.min(1, p);
			}else{
				return 0;
			}
		}

		//this is the deterministic/stochastic number of healthy students getting infected in a
		// given place we use round method here
		int numberOfInfected(int contagiousN,int healthyN){
			if(!Constants.deterministic){
				float p=infectionProbability(contagiousN)*healthyN;
				p+=randomGenerator.nextGaussian()*Constants.sigma;
				return Math.min(Math.max(0, Math.round(p)), healthyN);
			}
			return Math.round(infectionProbability(contagiousN)*healthyN);
		}

		//this is the deterministic/stochastic number of not contagious vaccinated students 
		//getting infected in a given place we use round method here
		int numberOfVaccineContagious(int contagiousN,int hvaccineN){
			if(!Constants.deterministic){
				float p=vaccineContagiousProbability(contagiousN)*hvaccineN;
				p+=randomGenerator.nextGaussian()*Constants.sigma;
				return Math.min(Math.max(0, Math.round(p)), hvaccineN);
			}
			return Math.round(vaccineContagiousProbability(contagiousN)*hvaccineN) ;
		}

		/**
		 * @version 1: everyone has the same probability of affecting other people
		 * we divide the number of recipients evenly(as possible) among them
		 * I do not want to remove the student from healthy once I generate her to be infected
		 * because that will mass up with the rest of update part in WrapperStatus, thus I created a
		 * new array list called myHealthy(a deep copy) to handle to problem for now
		 * Further: we use randn function to generate the student to be infected and assign recipients
		 * to already contagious by rounds
		 */
		ArrayList<ArrayList<String>> assignRecipients(ArrayList<String> healthy,
				ArrayList<String> hvaccineID,ArrayList<String> myConID){
			int infected=numberOfInfected(myConID.size(),healthy.size());
			int infected2=numberOfVaccineContagious(myConID.size(),hvaccineID.size());
			if(infected2!=0){
				System.out.println(vaccineContagiousProbability(myConID.size())*healthy.size());
				System.out.println(Math.round(vaccineContagiousProbability(myConID.size())*healthy.size()));
			}
			ArrayList<String> myNew=new ArrayList<String>(healthy);
			ArrayList<String> myNewhv=new ArrayList<String>(hvaccineID);
			ArrayList<ArrayList<String>> result=new ArrayList<ArrayList<String>>();
			if(healthy.isEmpty()){
				return result;
			}
			/**
			if(Constants.infectionProbability==1){
				myNew.add(myConID.get(0)); //the last index of healthy will be the source
				result.add(myNew);
				return result;
			}
			 */
			if(infected==0){
				if(infected2==0){
					return result;
				}
			}
			if(infected!=0){
				for(int i=0;i<infected;i++){
					if(i<myConID.size()){// when infected<=myConID.size()
						//generated the student to be infected
						ArrayList<String> student=new ArrayList<String>();
						//System.out.println(myNew.size()+"infected"+infected);
						student.add(myNew.remove(myRandn(0,myNew.size()-1)));
						//for source myConID.get(i)
						student.add(myConID.get(i));
						result.add(student);
					}else{
						ArrayList<String> student=result.get(i%myConID.size());
						student.add(student.size()-2,myNew.remove(myRandn(0,myNew.size())));
					}
				}
			}
			if(infected2==0){
				return result;
			}
			for(int i=0;i<infected2;i++){
				if(result.size()<myConID.size()){
					ArrayList<String> student=new ArrayList<String>();
					//System.out.println(myNewhv.size()+"infected2"+infected2);
					student.add(myNewhv.remove(myRandn(0,myNewhv.size()-1)));
					//System.out.println(result.size());
					//System.out.println(i);
					student.add(myConID.get(result.size()));
					result.add(student);
				}else{
					ArrayList<String> student=result.get((i+result.size())%myConID.size());
					student.add(student.size()-2,myNewhv.remove(myRandn(0,myNewhv.size())));
				}
			}
			return result;
		}

		boolean generateVaccineID(){
			if(!Constants.file.equals("TestData5.csv")){
				return false;
			}
			//we know the last student's ID is 2624
			int number=Math.round(2624*Constants.vaccipercentage);
			ArrayList<String> ID=new ArrayList<String>();
			for(int i=0;i<2624;i++){
				ID.add(Integer.toString(i));
			}
			for(int i=0;i<number;i++){
				int myIndex=myRandn(1,ID.size());
				Constants.vaccineID.put(ID.get(myIndex), 0);
				ID.remove(myIndex);
			}
			return true;
		}
	}

	class PlaceValue {
		
		ArrayList<PlaceTimeEntry> placeEntry=new ArrayList<PlaceTimeEntry>();
		
		List<String> DDate=Arrays.asList("Mon","Tu","Wed","Th","Fri","Sa","Su"); 
		int[] NumberOfDates=new int[7];
		
		PlaceValue(){
		}
		PlaceValue(PlaceTimeEntry ety){
			placeEntry.add(ety);
			NumberOfDates[DDate.indexOf(ety.getTime().getDate())]+=1;
		}
		
		//used for updating the placeValue in the simulation part
		PlaceValue(ArrayList<PlaceTimeEntry> placeEntry){
			this.placeEntry=placeEntry;
			for(int i=0;i<placeEntry.size();i++){
				NumberOfDates[DDate.indexOf(placeEntry.get(i).getTime().getDate())]+=1;
			}
		}

		//when adding timeEntry, we are not worried about the place hash key doesn't match
		//since the logic this program will not allow that
		//thing we care about: two time Entry with the same Time but different student ID
		//since we are going to process the csv file line by line, in the target timeEntry
		//there will be a student ID ArrayList that contains only one student ID
		
		boolean addEntry(PlaceTimeEntry timeEntry){
			if(!placeEntry.contains(timeEntry)){
				//loop through the list to see whether we have the same time block under 
				//this place
				for(int i=0;i<placeEntry.size();i++){
					if(timeEntry.getTime().equals(placeEntry.get(i).getTime())){
						placeEntry.get(i).addSID(timeEntry.getStudentID());
						return true;
					}
				}
				//we also want the time entry to be ordered as in studentValue
				for(int i=0;i<placeEntry.size();i++){
					//we order from closest time to farthest 
					if (timeEntry.getTime().timeOrder()<placeEntry.get(i).getTime().timeOrder()){
						NumberOfDates[DDate.indexOf(timeEntry.getTime().getDate())]+=1;
						placeEntry.add(i,timeEntry);
						return true;
					}
				}
				NumberOfDates[DDate.indexOf(timeEntry.getTime().getDate())]+=1;
				placeEntry.add(timeEntry);
				return true;
			}else{
				//for debug
				System.out.println("PlaceValue.addEntry(): this time Entry exist");
				return false;
			}
		}
		
		ArrayList<PlaceTimeEntry> getPlaceEntry(){
			return placeEntry;
		}

		int getNumberOfDates(String date){
			return NumberOfDates[DDate.indexOf(date)];
		}
		
		int getFirstIndexOfDates(String date){
			//monday is a special case
			if(date.equals("Mon")){
				return firstIndexOfMonday();
			}
			//Tuesday to sunday case
			int number=0;
			if(getNumberOfDates(date)!=0){
				for(int i=0;i<DDate.indexOf(date);i++){
					number+=NumberOfDates[i];
				}
				return number;
			}else{
				return -1;
			}
		}
		
		int getLastIndexOfDates(String date){
			//monday is a special case
			if(date.equals("Mon")){
				return lastIndexOfMonday();
			}
			if(getNumberOfDates(date)!=0){
				return getFirstIndexOfDates(date)+getNumberOfDates(date)-1;
			}else{
				//System.out.println("PlaceValue: "+date+ " entry is not initialized, debug");
				return -1;
			}
		}
		int firstIndexOfMonday(){
			if(NumberOfDates[0]!=0){
				return 0;
			}else{
				//System.out.println("PlaceValue: Monday entry is not initialized, debug");
				return -1;
			}
		}
		int lastIndexOfMonday(){
			return NumberOfDates[0]-1;
		}
		String toStringFirstLastIndexOfDays(){
			String s="";
			for(int i=0;i<7;i++){
				String date=DDate.get(i);
				s+="the first index of "+date+" is: "+ getFirstIndexOfDates(date)+"; the last index of "
				+date+" is: "+ getLastIndexOfDates(date)+" ";
			}
			return s;
		}
		
		public String toString(){
			String mypv="";
			for (int i=0;i<placeEntry.size();i++){
				PlaceTimeEntry mypte=placeEntry.get(i);
				mypv+=mypte.toString();
			}
			return mypv;
		}

	}
	
	class PlaceTimeEntry {
		Time time;
		ArrayList<String> studentID=new ArrayList<String>();
		ArrayList<String> contagiousID=new ArrayList<String>();
		ArrayList<String> healthyID=new ArrayList<String>();
		ArrayList<String> hvaccineID=new ArrayList<String>();

		PlaceTimeEntry(Time time){
			this.time=time;
		}

		PlaceTimeEntry(Time time, String sID){
			this.time=time;
			studentID.add(sID);
			if(Constants.vaccineID.containsKey(sID)){
				hvaccineID.add(sID);
			}else{
				healthyID.add(sID);
			}
		}

		//since when only add student at the before simulation, 
		//we assume all the students are healthy, and initialize the healthy ID
		void addSID(String ID){
			if(!studentID.contains(ID)){
				studentID.add(ID);
				if(Constants.vaccineID.containsKey(ID)){
					hvaccineID.add(ID);
				}else{
					healthyID.add(ID);
				}
			}else{
				System.out.println("PlaceTimeEntry.addSID(String): ID exist, let's debug");
			}
		}
		//assume this list has only one ID (this is the only case we are going to use this function)
		void addSID(ArrayList<String> ID){
			String id=ID.get(0);
			if(!studentID.contains(id)){
				studentID.add(id);
				if(Constants.vaccineID.containsKey(id)){
					hvaccineID.add(id);
				}else{
					healthyID.add(id);
				}
			}else{
				System.out.println("PlaceTimeEntry.addSID(A<S>): ID: "+ID.get(0)+" exist, let's debug");
			}
		}

		//we also need to keep track of people who in the room are contagious
		boolean addConID(String ID){
			if(!contagiousID.contains(ID)){
				if(studentID.contains(ID)){
					contagiousID.add(ID);
					if(healthyID.contains(ID)){
						healthyID.remove(ID);
					}else if(hvaccineID.contains(ID)){
						hvaccineID.remove(ID);
					}
					return true;
				}
				return false;
			}else{
				return false;
			}
		}

		boolean removeConID(String ID){
			if(contagiousID.contains(ID)){
				contagiousID.remove(ID);
				return true;
			}else{
				Log.log(String.format("PlaceTimeEntry.removeConID(%s)",ID));
				System.out.println("PlaceTimeEntry.removeConID: ID doesn't exist");
				return false;
			}
		}

		//this function removes the ID from healthy once the student is infected
		boolean removeHID(String ID){
			if(healthyID.contains(ID)){
				healthyID.remove(ID);
				return true;
			}
			else{
				//mainly for debug
				//Log.log(String.format("PlaceTimeEntry.removeHID(%s)",ID));
				//Log.log("StudentID= "+PrintArrayList(studentID)+"ContagiousID= "+PrintArrayList(contagiousID)+
				//		"HealthyID= "+PrintArrayList(healthyID));
				System.out.println("PlaceTimeEntry.removeHID: ID doesn't exist");
				return false;
			}
		}
		//methods that might be useful when we are simulating later on	
		int stdNum(){
			return studentID.size();
		}

		int conNum(){
			return contagiousID.size();
		}

		int hlyNum(){
			return healthyID.size();
		}

		Time getTime(){
			return time;
		}

		ArrayList<String> getStudentID(){
			return studentID;
		}

		ArrayList<String> getContagiousID(){
			return contagiousID;
		}

		ArrayList<String> getHealthyID(){
			return healthyID;
		}

		ArrayList<String> getHvaccineID(){
			return hvaccineID;
		}
		
		String toStringArrayList(ArrayList<String> as){
			String myarr="";
			for(int i=0;i<as.size();i++){
				myarr+=as.get(i)+"|";
			}
			return myarr;
		}
		String newline = System.getProperty("line.separator");
		public String toString(){
			String pte="";
			pte+=time.toString()+"|"+newline+"studentID:"+toStringArrayList(studentID)+"|"+newline
					+"contagiousID:"+toStringArrayList(contagiousID)+"|"+newline
					+"healthyID:"+toStringArrayList(healthyID)+"|"+newline+
					"vaccineID:"+toStringArrayList(hvaccineID)+"|";
			return pte;
		}
	}
	static class Constants {
		static final int iterationPeriod=60;
		static final int incubationLimit=6;
		static final int contagiousLimit=8;
		
		static final boolean setLog=false;
		
		static final float infectionProbability= (float)(0.01);
		
		/**
		 * Def: edgeDiscountFactor=(actual time length)/target time length
		 * i.e. we do not differentiate within the edgeDicountFactor unit of days
		 */
		static final float edgeDiscountFactor=incubationLimit/2; //1;
		
		static final String file="TestData5.csv";
		static final String saveFileAs="remissionHT";
		
		
		static final boolean deterministic=true;
		static final float sigma=(float) 1; //amplitude of the stochastic noise term
		
		/**
		 * vaccination controls whether we distribute vaccines in the population
		 * the default percentage of population receive vaccines is 0.1
		 * the default probability of a vaccinated person being a carrier of the virus
		 * is 0.005, and she has the same probability of infecting other people as a 
		 * infected person
		 * vaccineID keep tracks of all the students that are vaccinated
		 * we use hashtable because containskey will be called very often, the Integer is 
		 * preserve for the probability of infecting other people or probability become 
		 * contagious (for now, it does not mean anything)
		 */
		static final boolean vaccination=false;
		static final float vaccipercentage=(float) 0.5;
		static final float vaccineContagiuosProbability=(float) 0.001;
		static Hashtable<String,Integer> vaccineID=new Hashtable<String,Integer>();

		
		/**
		 * in order to run comparison, we want to have the fisrtInKey to be the same for
		 * a series of graphs. Then we can call the following variable;
		 */
		static final boolean setFirstInKey=true;
		static final String firstInKey="82";
		
		
		/**
		 * quarantine controls whether we stop a class that contains more than 40 students
		 * note, we are not going to eliminate the contacts between students in the house
		 */
		static final boolean quarantine=false;
		static final int quarantineSize=30;
		static final boolean quarantineHouse=true;
		
		/**
		 * nodeSize is used when we are generating the dot file in ToDot class
		 */
		static final double nodeSize=0.6;
		

	}
	
	class WrapperSP {
		Hashtable<String,StudentValue> SHT;
		Hashtable<String,PlaceValue> PHT;
		ArrayList<String> sID;
		Probability prob;
		String[] date={"Mon","Tu","Wed","Th","Fri","Sa","Su"}; 

		WrapperSP(String file){
			//initialize the hash tables 
			SHT=new Hashtable<String,StudentValue>();
			//the place hash table is going to include the housing
			PHT=new Hashtable<String,PlaceValue>();
			//store all student ID so we can iterate through SHT later 
			//to find houseCode
			sID=new ArrayList<String>();
			if(Constants.vaccination){
				prob=new Probability();
				if(!prob.generateVaccineID()){
					System.out.println("WrapperStatus.Probabililty.generateVaccineID.wrong data");
					System.exit(0);
				}
			}
			try {
				parse(file);
			} catch (FileNotFoundException e) {
				// TODO Auto-generated catch block
				System.out.println("WrapperSP.WrapperSP:file not found");
			}
		}
		Hashtable<String,StudentValue> getSHT() {
			return SHT;
		}

		//clone
		/**
		public Hashtable<String,StudentValue> clone(){
			Hashtable<String,StudentValue> ht=new Hashtable<String,StudentValue>();
			for(int i=0;i<sID.size();i++){
				String key=sID.get(i);
				StudentValue sv=SHT.get(SHT);
			}
		}

		 */

		Hashtable<String,PlaceValue> getPHT() {
			return PHT;
		}
		ArrayList<String> getSID(){
			return sID;
		}

		void parse(String filename) throws FileNotFoundException {



			//objective: when reading each table line, we want to initialize 
			//both studentHashTable and PlaceHashTable so we don't need 
			//to waste the memory to store these values

			Scanner scanner = new Scanner(new File(filename));

			//read the file line by line

			while(scanner.hasNextLine()){

				//each row is corresponding to one student's schedule for one 
				//class (one ID, one place)

				String[] a=scanner.next().split(",");

				//since from each row, we have unique time entries, we can create 
				//Time time s

				if(a[0].equals("hashValue")){
					continue;
				}

				//index 1 is houseCode
				//if the student hashKey is already in the system we are NOT going 
				//to create a new studentValue, instead we want to modify the original
				//one and we are going to create one if hashKey is not in the table

				StudentValue sv;

				if(!SHT.containsKey(a[0])){
					sv=new StudentValue(a[1]);
				}else{
					sv=SHT.get(a[0]);
				}

				//updating the place hash table:
				//index 9, 10 are building, room
				//same logic as above
				//however, merge two PlaceTimeEntry is more complicated, we leave that 
				//function to placeValue add function

				PlaceValue pv;
				if(!PHT.containsKey(a[9]+a[10])){
					pv=new PlaceValue();
				}else{
					pv=PHT.get(a[9]+a[10]);
				}

				//initialize all the time blocks we can extract from our current row
				ArrayList<Time> tList=new ArrayList<Time>();
				//for each row, index 2-6 are Mon-Fri
				for(int i=2;i<7;i++){
					if (a[i].equals("1")){
						Time time=new Time(date[i-2],Integer.parseInt(a[7]),Integer.parseInt(a[8]));
						tList.add(time);
					}
				}

				//now we can generate StudentTimeEntry
				//based on the tList, we can also create PlaceTimeEntry
				for(int i=0;i<tList.size();i++){
					StudentTimeEntry ste=new StudentTimeEntry(tList.get(i),a[9]+a[10]);
					sv.addSTE(ste);

					PlaceTimeEntry pte=new PlaceTimeEntry(tList.get(i),a[0]);
					pv.addEntry(pte);
				}

				SHT.put(a[0], sv);
				//now we are down updating the student Hash Table

				//push the result to the place hash table
				PHT.put(a[9]+a[10], pv);

				//update sID list:
				if(!sID.contains(a[0])){
					sID.add(a[0]);
				}
			}
			scanner.close();
			//now we are down reading the file, we need to use our assumption to generate
			//breakfast, lunch, dinner, study time in the house

			//this part of the code is generate because the size and assumption of our baby program
			//we need a loop to literate through students' houseCode and etc

			//first we initialize all the time blocks we want to use
			ArrayList<Time> mealStuList=new ArrayList<Time>();
			int[] hourS={800,1220,1730,1900};
			int[] hourE={830,1250,1830,2100};
			//iterate through 7 days a week to generate all the meal and study blocks
			for(int i=0;i<7;i++){
				//iterate the target 4 blocks a day
				for(int j=0;j<4;j++){
					Time time=new Time(date[i],hourS[j],hourE[j]);
					mealStuList.add(time);
				}
			}

			//now let's update hv values in the PHT 
			//and sv-myste values in the SHT
			PlaceValue hv;
			for(int i=0;i<sID.size();i++){
				String housekey=SHT.get(sID.get(i)).getHouseCode();

				//get the existing student value
				StudentValue myste=SHT.get(sID.get(i));

				//generate StudentTimeEntry to update SHT
				for(int j=0;j<mealStuList.size();j++){
					StudentTimeEntry mealstu=new StudentTimeEntry(mealStuList.get(j),housekey);
					if(myste.addSTE(mealstu)){
						//then we also want to add this student to the PHT list
						if(!PHT.containsKey(housekey)){
							hv=new PlaceValue();
						}else{
							hv=PHT.get(housekey);
						}
						PlaceTimeEntry mealpte=new PlaceTimeEntry(mealStuList.get(j),sID.get(i));
						hv.addEntry(mealpte);
						PHT.put(housekey, hv);
					}
					SHT.put(sID.get(i),myste);
				}
			}
		}

		String newline = System.getProperty("line.separator");
		public String toStringSHT(){
			String hashstring="";
			for(Entry<String,StudentValue> entry : SHT.entrySet()){
				hashstring += entry.getKey() + "=" +newline
						+entry.getValue().toString();
			}
			return hashstring;  
		}
		public String toStringPHT(){
			String hashstring="";
			for(Entry<String,PlaceValue> entry : PHT.entrySet()){
				hashstring += entry.getKey() + "=" +newline
						+entry.getValue().toString();
			}
			return hashstring;  
		}
	}

	
	/**
	 * call WrapperSP to generate the student schedules
	 * use get method to get the fields in WrapperSP:
	 * sht: the student schedule hash table generated in WrapperSP
	 * pht: the place hash table generated in WrapperSP
	 * sID: all the keys of sht: is used to generated the first infected student.
	 * week: keep track of the week of the semester during the simulation
	 * daycount: keep track of the day of the week during the simulation
	 * firstInKey: the ID of the first infected student
	 */
	WrapperSP wrapper=null;
	Hashtable<String,StudentValue> sht=null;
	Hashtable<String,PlaceValue> pht=null;
	ArrayList<String> sID=null; 
	String newline = System.getProperty("line.separator");
	int week=0;
	int daycount=1;
	String firstInKey=null;


	/**
	 * call probability class to get access to the methods inside
	 */
	Probability prob=null;

	/**
	 * statusKey keeps track of all students under incubation and contagious periods
	 * contagiousKey keeps track of all students under contagious period.
	 */
	ArrayList<String> statusKey=null; 
	ArrayList<String> contagiousKey=null; 

	/**
	 * SVHT: status value hash table: store all the students who are under incubation and 
	 *       contagious periods with hashvalue: StatusValue: fields: status st, 
	 *       String source, ArrayList<Recipient> stRecpt,ArrayList<String> RecipientID
	 * RemissionHT: once a student enter the remission period, we are going to remove her
	 * 		 from the SVHT and add to ReimissionHT: this is the table we are going to at 
	 * 		 the end of the day.
	 */
	Hashtable<String,StatusValue> SVHT=null;
	Hashtable<String,StatusValue> RemissionHT=null;


	List<String> DDate=Arrays.asList("Mon","Tu","Wed","Th","Fri","Sa","Su"); 

	public TestSimulationAll(){
		prob=new Probability();
		wrapper=new WrapperSP(Constants.file);
		sht=wrapper.getSHT();
		pht=wrapper.getPHT();
		sID=wrapper.getSID();
		statusKey=new ArrayList<String>();
		contagiousKey=new ArrayList<String>();
		SVHT=new Hashtable<String,StatusValue>();
		RemissionHT=new Hashtable<String,StatusValue>();
		simulate();
	}

	public Hashtable<String,StatusValue> getSVHT(){
		return SVHT;
	}

	public int RemissionHTsize(){
		return RemissionHT.size();
	}

	// according to our data, the size of the whole population on campus is 2624
	public float percentageStudentInfected(){
		return (float)(RemissionHT.size())/2624;
	}

	public Hashtable<String,StatusValue> getRemissionHT(){
		return RemissionHT;
	}

	public Hashtable<String,StudentValue> getsht(){
		return sht;
	}

	public Hashtable<String,PlaceValue> getpht(){
		return pht;
	}

	public ArrayList<String> getContagiousKey(){
		return contagiousKey;
	}

	public void updateAll(String place, String date){
		PlaceValue mypv=pht.get(place);
		for(int i=mypv.getFirstIndexOfDates(date);i<mypv.getLastIndexOfDates(date)+1;i++){
			ArrayList<String> studentID=mypv.getPlaceEntry().get(i).getStudentID();
			ArrayList<String> contagiousID=mypv.getPlaceEntry().get(i).getContagiousID();
			ArrayList<String> healthyID=mypv.getPlaceEntry().get(i).getHealthyID();
			ArrayList<String> vaccineID=mypv.getPlaceEntry().get(i).getHvaccineID();
			for(Iterator<String> it=studentID.iterator();it.hasNext();){
				String mynext=it.next();
				if(SVHT.containsKey(mynext)){
					if(!healthyID.remove(mynext)){
						vaccineID.remove(mynext);
					}
					if(SVHT.get(mynext).getSt().checkContagious()){
						if(!contagiousID.contains(mynext)){
							contagiousID.add(mynext);
						}
					}
				}
				else if(RemissionHT.containsKey(mynext)){
					if(!healthyID.remove(mynext)){
						vaccineID.remove(mynext);
					}
					contagiousID.remove(mynext);
				}
			}
		}
	}


	//add recipient and update the SVHT
	public void addRecipient(String ID, Recipient r){
		if(!SVHT.containsKey(ID)){
			//System.out.println(ID);
			//System.out.println("well");
			//System.exit(0);
		}
		StatusValue sv=SVHT.get(ID);
		if(sv.addrecp(r)){
			String id="";
			for(int i=0;i<r.getID().size();i++){
				id+=r.getID().get(i)+",";
			}
			Log.log(ID+" infected the following people: " + id +" on "+sv.getSt().getCurrentDate());
		}else{
			System.out.println("fail to add recipients");
		}
	}


	/**
	 * generateFirstStudent : pick a random student to be infected on the first day,
	 * generate her value and add to the status table 
	 * and then get the first place she is going to be on that day, and update her status
	 * before entering the loop (starting from day one)
	 * this is the function we call we call first in the simulation function
	 */
	public boolean generateFirstStudent(){
		if(!Constants.setFirstInKey){
			//first we pick the first student to be infected
			int r=prob.myRandn(0,sID.size()-1);
			boolean run=true;
			while(run){
				firstInKey=sID.get(r);
				if(!Constants.vaccineID.containsKey(firstInKey)){
					run=false;
				}
			}
		}else{
			firstInKey=Constants.firstInKey;
		}
		//generate the first student incubation startT, data, etc

		Time t1=new Time("Mon",0000);
		Status s1=new Status(t1,week);

		//source="0" represent she is the source
		StatusValue firsv=new StatusValue("0",s1);
		//push the first value generated into the status value hash table
		SVHT.put(firstInKey,firsv);
		statusKey.add(firstInKey);

		Log.log(firstInKey+" first get infected, enter incubation period");

		return true;
	}

	/**
	 * loop through the key in the status table and get all the places these students going to be 
	 * on day j, and update these students' status on the place hash table
	 * 
	 */

	public ArrayList<String> generatePlace(){
		ArrayList<String> place=new ArrayList<String>();
		String currentDate="";

		for(int i=0;i<statusKey.size();i++){
			String key=statusKey.get(i);
			Status currentStatus=SVHT.get(key).getSt();
			//debug statement
			if(currentStatus.CEndTimeExist()){
				System.out.println("WrapperStatusV5.generatePlace(): check statuskey");
				System.exit(0);
			}

			//generate current date
			//notice for day j, all students should have the same currentDate
			if(currentDate.equals("")){
				currentDate=currentStatus.getCurrentDate();
				System.out.println("current date is: "+currentDate);
			}else{
				if (!currentDate.equals(currentStatus.getCurrentDate())){
					System.out.println("WrapperStatusV5.Simulation loop:"
							+ " wrong current date: simulation error"+
							"key="+key+"currentDate="+currentDate
							+",currentStatus.getCurrentDate()="+currentStatus.getCurrentDate());
					System.exit(0);
				}
			}

			/**
			 * generate the place list to iterate through for day j from(student i=key)
			 * and change healthyID, contagiousID list of the place according to her status
			 */
			ArrayList<StudentTimeEntry> localSTE=sht.get(key).getSTE();
			for(int index=0;index<localSTE.size();index++){
				Time localTime=localSTE.get(index).getTime();
				if(!localTime.getDate().equals(currentDate)){
					continue;
				}
				String localPlace=localSTE.get(index).getPlace();

				//first we should update those who are in remission now: move them
				//from the contagious list

				//update the all student status of the place;
				updateAll(localPlace,currentDate);


				//place is not suppose to be a long list now, so contains function
				//should be fine
				if(!place.contains(localPlace)){
					place.add(localPlace);
					//System.out.println(localPlace);
				}

			}

		}
		//add currentDate to the end of the list 
		place.add(currentDate);
		return place;
	}


	public void updatePlaceHashTableGenerateInfections(String myplace,String currentDate){
		PlaceValue mypv=pht.get(myplace);
		ArrayList<PlaceTimeEntry> currentList=mypv.getPlaceEntry();

		for(int entryindex=mypv.getFirstIndexOfDates(currentDate);
				entryindex<mypv.getLastIndexOfDates(currentDate)+1;entryindex++){
			PlaceTimeEntry myPTE=currentList.get(entryindex);
			//find the entries with the currentDate

			if(!myPTE.getTime().getDate().equals(currentDate)){
				System.out.println("WrapperStatusV5.updatePlaceHashTableGenerateInfectious: "
						+ "wrong for loop");
				System.exit(0);
			}
			if(Constants.quarantine){
				//System.out.println("quarantine");
				if(!Constants.quarantineHouse){
					if(!Character.isDigit(myplace.toCharArray()[0])){ // we use this line to differentiate
						//between regular classrooms(is String in letter and number format, but always
						//starts with letter) and houses(is a number in String format)
						if(myPTE.stdNum()>=Constants.quarantineSize){
							continue;
						}
					}
				}else{
					if(myPTE.stdNum()>=Constants.quarantineSize){
						continue;
					}
				}
			}
			//find the entries have contagious students
			ArrayList<String> myConID=myPTE.getContagiousID();
			ArrayList<String> myHealthyID=myPTE.getHealthyID();
			ArrayList<String> myHvaccineID=myPTE.getHvaccineID();
			//System.out.println(myConID.size());
			//System.out.println(myHealthyID.size());
			//System.out.println(myHvaccineID.size());
			Time mytime=myPTE.getTime();
			// if everyone in the place is already infected, we are not interested in
			//iterating through that place anymore
			updateAll(myplace,currentDate);
			if(myHealthyID.isEmpty()){
				if(myHvaccineID.isEmpty()){
					continue;
				}
			}else{

				if(myConID.isEmpty()){
					continue;
				}

				ArrayList<ArrayList<String>> result=prob.assignRecipients(myHealthyID,myHvaccineID, myConID);
				if(!result.isEmpty()){
					for(int resultIndex=0;resultIndex<result.size();resultIndex++){
						ArrayList<String> recp=result.get(resultIndex);
						String mysource=recp.remove(recp.size()-1);
						for(int recpIndex=0;recpIndex<recp.size();recpIndex++){ 
							//the last index is the source
							Time myincubation=new Time(currentDate,mytime.getStartT());
							Status mystatus=new Status(myincubation,week);
							StatusValue mysv=new StatusValue(mysource,mystatus);
							SVHT.put(recp.get(recpIndex), mysv);
							statusKey.add(recp.get(recpIndex));
							//System.out.println(SVHT.get(recp.get(recpIndex)).getSt().checkContagious());
							//System.out.println(statusKey.size());
							//System.out.println("recipient:"+recp.get(recpIndex)+";currentDate="+currentDate);
						}
						Recipient myr=new Recipient(myplace, week,mytime,recp);
						//System.out.println(recp.size());
						//System.out.println(mysource);
						addRecipient(mysource,myr);

					}

				}
			}
		}
	}


	public void simulate(){
		generateFirstStudent();

		for(int j=0;j<Constants.iterationPeriod;j++){
			//System.out.println(PrintArrayList(statusKey));
			//iterate through all the existing key in the status hash table
			ArrayList<String> place=generatePlace();
			String currentDate=place.get(place.size()-1);//the last element of the place

			Log.log("current daycount: "+daycount+"current week: "+week+"Current date: "+currentDate);

			/**
			 *now we want to generate the people infected in each place and update the tables
			 *looping through the place list to simulate the virus spread
			 *probability of getting infected if (contact==True) =1
			 */
			for(int placeindex=0;placeindex<place.size()-1;placeindex++){
				String myplace=place.get(placeindex);
				//ArrayList<PlaceTimeEntry> currentList=pht.get(myplace).getPlaceEntry();
				updatePlaceHashTableGenerateInfections(myplace, currentDate);
			}

			//increment daycount in the end
			incrementdaycount();


			//need to increment week and daycount here
			daycount+=1;
			if(daycount>7){
				week+=1;
				daycount=daycount%7;
			}
			if(statusKey.isEmpty()){
				break;
			}
		}
	}

	public void incrementdaycount(){
		//increment daycount in the end
		for (Iterator<String> it=statusKey.iterator();it.hasNext();){
			String key=it.next();
			Status currentStatus=SVHT.get(key).getSt();
			//System.out.println(key+" "+currentStatus.checkContagious());
			if(currentStatus.checkContagious()){
				//increment the daycount for contagious
				Status s=SVHT.get(key).getSt();
				s.IncreaseContagiousDaycount();
				//System.out.println(s.getCurrentDate());
				if(s.CEndTimeExist()){
					it.remove();
					Log.log(key+" recovered, enter remission period on "+s.getCurrentDate());
					contagiousKey.remove(key);
					RemissionHT.put(key, SVHT.get(key));
					SVHT.remove(key);
				}
			}else{
				Status s=SVHT.get(key).getSt();
				s.IncreaseIncubationDaycount();
				if(s.checkContagious()){
					Log.log(key+" become contagious, enter contagious period on "+s.getCurrentDate());
					contagiousKey.add(key);
				}		

			}
		}

	}


	public String toStringRemissionHT(){
		String hashstring="";
		for(Entry<String,StatusValue> entry : RemissionHT.entrySet()){
			hashstring += entry.getKey() + "=" +newline
					+entry.getValue().toString();
		}
		return hashstring;  
	}

	public String toStringRemissionHTV2(){
		String hashstring="";
		for(Entry<String,StatusValue> entry : RemissionHT.entrySet()){
			hashstring += entry.getKey() + "=" +newline
					+entry.getValue().toStringV2();
		}
		return hashstring;  
	}

	public String toCSVRemissionHT(){
		String csv="";
		for(Entry<String,StatusValue> entry : RemissionHT.entrySet()){
			csv += entry.getKey() + "," 
					+entry.getValue().toCSV()+newline;
		}
		return csv;
	}

	public String toCSVRemissionHTV2(){
		String csv="";
		for(Entry<String,StatusValue> entry : RemissionHT.entrySet()){
			csv += entry.getKey() + "," 
					+entry.getValue().toCSVV2()+newline;
		}
		return csv;
	}

	public String toCSVRemissionHTV3(){
		String csv=percentageStudentInfected()+","+newline;
		for(Entry<String,StatusValue> entry : RemissionHT.entrySet()){
			csv += entry.getKey() + "," 
					+entry.getValue().toCSVV3();
			if(Constants.vaccineID.containsKey(entry.getKey())){
				csv+="1";
			}else{
				csv+="0";
			}
			csv+=","+newline;
		}
		return csv;
	}

	/**
	 * this version gives ID, source,recipient size, week of infection, incubation, contagious, recipients(place, week, time, ID)
	 */
	public void saveCSVRemissionHT(){
		try (PrintWriter out =new PrintWriter(Constants.saveFileAs+"V1.csv")){
			out.println(toCSVRemissionHT());
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * this version gives ID, source, week of infection, incubation, contagious, recipients(place, day of the semester, startT, ID)
	 */
	public void saveCSVRemissionHTV2(){
		try (PrintWriter out =new PrintWriter(Constants.saveFileAs+"V2.csv")){
			out.println(toCSVRemissionHTV2());
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	/**
	 * this version gives ID, source, recipients size, day of the semester when infected, whether vaccinated (0-no,1-yes)
	 */
	public void saveCSVRemissionHTV3(){
		try (PrintWriter out =new PrintWriter(Constants.saveFileAs+"V3.csv")){
			out.println(toCSVRemissionHTV3());
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	/**
	 * this function test confirms the source and the recipient have contacts according 
	 * to their class schedules 
	 * 
	 */
	public boolean testRecipientContact(String key){
		ArrayList<Recipient> recptskey=RemissionHT.get(key).getStRecpt();
		if(recptskey.isEmpty()){
			return true;
		}else{
			for(int i=0;i<recptskey.size();i++){	
				Recipient r=recptskey.get(i);
				ArrayList<String> ID=r.getID();
				Time time=r.getTime();
				String date=time.getDate();
				String place=r.getPlace();
				PlaceValue mypv=pht.get(place);
				for(int placeindex=mypv.getFirstIndexOfDates(date);
						placeindex<mypv.getLastIndexOfDates(date);placeindex++){
					PlaceTimeEntry pte=mypv.getPlaceEntry().get(placeindex);
					if(pte.getTime().timeOrder()==time.timeOrder()){
						if(!pte.getStudentID().containsAll(ID)){
							return false;
						}
						break;
					}
				}
			}
			return true;
		}
	}

	/**
	 * this is the default toDot() function built in the WrapperStatus class 
	 * @return the content of the dot file 
	 */
	public String toDot(){
		// partition the whole population into two groups
		//the list who have recipients, and the one who don't
		//and we use invisibleNodes to keep track of the length of the branch
		ArrayList<String> source=new ArrayList<String>();
		ArrayList<String> invisibleNodes=new ArrayList<String>();
		//initialize invisible nodes list
		for(Entry<String,StatusValue> entry: RemissionHT.entrySet()){
			if(!entry.getValue().getSource().equals("0")){
				int currentday=entry.getValue().getSt().getinfectionDay();
				int sourceday=RemissionHT.get(entry.getValue().getSource()).getSt().getinfectionDay();
				if(currentday-sourceday>1){
					int steps=(int) ((currentday-sourceday-1)/Constants.edgeDiscountFactor);
					for(int i=0;i<steps;i++){
						invisibleNodes.add("m"+invisibleNodes.size());	
					}
				}
			}
		}

		String dot="digraph spread {"+newline+"rankdir=LR;"+newline+"root="+firstInKey+";"
				+newline+"ranksep=3.0;"
				+newline+"nodesep=2.0;"+newline+"orientation=\"landscape\";"+newline+
				firstInKey+newline;
		//first iterate through the sources
		//the size of the node reflect the number of recipient: log(1+#of recipient*0.2)
		for(Entry<String,StatusValue> entry: RemissionHT.entrySet()){
			String mysource=entry.getValue().getSource();
			if(!source.contains(mysource)){
				if(mysource.equals("0")){
					dot+=entry.getKey()+" [fillcolor=";
					if(!Constants.vaccineID.containsKey(entry.getKey())){
						dot+="coral1";
					}else{
						dot+="limegreen";
					}
					dot+=",shape=doublecircle,"+"width="+
							entry.getValue().getRecipientID().size()*0.2+
							",style=filled,"+ "fontsize=12];"+newline;
					source.add(entry.getKey());
				}
				else{
					dot+=mysource+" [fillcolor=\"";
					if(Constants.vaccineID.contains(mysource)){
						dot+="limegreen\"";
					}else{
						dot+="goldenrod1\"";
					}
					dot+=",shape=circle,"+"width="+
							//Math.log(1+RemissionHT.get(mysource).getRecipientID().size()*0.2)+
							RemissionHT.get(mysource).getRecipientID().size()*0.2+
							",style=filled,"+ "fontsize=12];"+newline;
					source.add(mysource);
				}
			}
		}
		//initialize invisible nodes
		dot+="{node[shape=point,style=invis] ";
		for(int i=0;i<invisibleNodes.size();i++){
			dot+=invisibleNodes.get(i)+" ";
		}
		dot+="}"+newline;

		//then we iterate through the keys and add edges
		for(Entry<String,StatusValue> entry: RemissionHT.entrySet()){
			String mykey=entry.getKey();
			if(!source.contains(mykey)){
				dot+=mykey+" [shape=point,fillcolor=\"";
				if(Constants.vaccineID.containsKey(mykey)){
					dot+="limegreen";
				}else{
					dot+="blueviolet";
				}
				dot+="\",width=0.2,style=filled,"
						+ "fontsize=12];"+newline;
			}
		}
		Iterator<String> it=invisibleNodes.iterator();
		for(Entry<String,StatusValue> entry: RemissionHT.entrySet()){
			String mykey=entry.getKey();
			String mysource=entry.getValue().getSource();
			if(!mysource.equals("0")){
				dot+=mysource;
				int currentday=entry.getValue().getSt().getinfectionDay();
				int sourceday=RemissionHT.get(entry.getValue().getSource()).getSt().getinfectionDay();
				int steps=(int) (currentday/Constants.edgeDiscountFactor)
						-(int) (sourceday/Constants.edgeDiscountFactor)-1;
				for(int i=0;i<steps;i++){
					dot+="->"+it.next();
				}
				dot+="->"+mykey+"[arrowsize=0.4, penwidth=1.2,color="
						+ "\"dimgray\"]"+";"+newline;
			}
		}

		dot+="}";
		return dot;
	}

	//this function writes the dot file for plotting the recipient source relationship and
	//the edge is stamped by the day of the semester
	public void saveRHTtoDotFile(){
		try (PrintWriter out =new PrintWriter(Constants.saveFileAs+"V2.dot")){
			out.println(toDot());
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	public String getFirstInKey(){
		return firstInKey;
	}

	public static void main(String[] args){
		long startTime = System.currentTimeMillis();
		Log.setEnable(Constants.setLog);
		TestSimulationAll ws=new TestSimulationAll();
		ws.saveCSVRemissionHTV3();
		System.out.println(Constants.vaccineID.size());
		System.out.println(Constants.vaccineID.containsKey("2571"));
		System.out.println(ws.getFirstInKey());
		System.out.println(ws.getSVHT().size());
		System.out.println(ws.getRemissionHT().size());
		System.out.println(ws.getsht().size());
		System.out.println(ws.getpht().size());
		long estimatedTime = System.currentTimeMillis() - startTime;
		System.out.println(estimatedTime);
		
	}

}


Files generated by TestSimulateAll.java


Simulation one
Simulation two
Simulation three
Simulation four
Simulation five

ToDotAll.java


1. save the above simulation results and ToDotAll.java to the same directory.
2. modify the file name in constants class.
3. run the following commands from terminal:

javac ToDotAll.java
time java -cp . ToDotAll


/**
 * @author kyragan
 * @version 10/20/2016
 * test runtime of ToDot.java
 */

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Map.Entry;
import java.util.NoSuchElementException;

public class ToDotAll {
	static class Constants {
		static int iterationPeriod=60;
		static int incubationLimit=6;
		static int contagiousLimit=8;
		
		public static boolean setLog=false;
		
		static float infectionProbability= (float)(0.01);
		
		/**
		 * Def: edgeDiscountFactor=(actual time length)/target time length
		 * i.e. we do not differentiate within the edgeDicountFactor unit of days
		 */
		static float edgeDiscountFactor=incubationLimit/2; //1;
		
		public static String file="TestData5.csv";
		public static String saveFileAs="remissionHT";
		
		
		public static boolean deterministic=true;
		static float sigma=(float) 1; //amplitude of the stochastic noise term
		
		/**
		 * vaccination controls whether we distribute vaccines in the population
		 * the default percentage of population receive vaccines is 0.1
		 * the default probability of a vaccinated person being a carrier of the virus
		 * is 0.005, and she has the same probability of infecting other people as a 
		 * infected person
		 * vaccineID keep tracks of all the students that are vaccinated
		 * we use hashtable because containskey will be called very often, the Integer is 
		 * preserve for the probability of infecting other people or probability become 
		 * contagious (for now, it does not mean anything)
		 */
		public static boolean vaccination=false;
		static float vaccipercentage=(float) 0.5;
		static float vaccineContagiuosProbability=(float) 0.001;
		static Hashtable<String,Integer> vaccineID=new Hashtable<String,Integer>();

		
		/**
		 * in order to run comparison, we want to have the fisrtInKey to be the same for
		 * a series of graphs. Then we can call the following variable;
		 */
		public static boolean setFirstInKey=true;
		static String firstInKey="82";
		
		
		/**
		 * quarantine controls whether we stop a class that contains more than 40 students
		 * note, we are not going to eliminate the contacts between students in the house
		 */
		public static boolean quarantine=false;
		static int quarantineSize=30;
		public static boolean quarantineHouse=true;
		
		/**
		 * nodeSize is used when we are generating the dot file in ToDot class
		 */
		static double nodeSize=0.6;
	}

	boolean radiusRatio=true;
	boolean radiusLog=false;
	Hashtable<String,ArrayList<String>> status;
	String newline = System.getProperty("line.separator");
	static String dot=null;
	String firstInKey=null;
	int maxdays=0;
	int maxsteps;
	float percentageStudentInfected;

	public ToDotAll(String file){
		//initialize the hash table 
		status=new Hashtable<String,ArrayList<String>>();
		try {
			parse(file);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			System.out.println("ToDot.ToDot:"+ file+" not found");
		}
	}

	public void setRadiusRatio(boolean ratio){
		radiusRatio=ratio;
	}

	public void setRadiusLog(boolean log){
		if(log){
			if(!radiusRatio){
				System.out.println("warning: radiusRatio false: cannot use log");
			}
		}
		radiusLog=log;
	}
	
	public void parse(String filename) throws FileNotFoundException {
		Scanner scanner = new Scanner(new File(filename));
		try{
			percentageStudentInfected=Float.valueOf(scanner.next().split(",")[0]);
		}catch(NoSuchElementException e){
			
		}
		while(scanner.hasNextLine()){

			String[] a;
			try{
				a=scanner.next().split(",");
				ArrayList<String> myvalue=new ArrayList<String>();
				myvalue.add(a[1]);//add the source index 0
				myvalue.add(a[3]);//add the day of the semester of the infection index 1
				myvalue.add(a[2]);//add the size of the direct recipients index 2
				myvalue.add(a[4]);//add the indication of vaccination index 3
				status.put(a[0], myvalue);
				if(Integer.parseInt(a[3])>maxdays){
					maxdays=Integer.parseInt(a[3]);
				}
			}catch(NoSuchElementException e){

			}
		}
		scanner.close();
	}

	public void generateDot(){
		ArrayList<String> source=new ArrayList<String>();
		ArrayList<String> invisibleNodes=new ArrayList<String>();
		//initialize invisible nodes list
		for(Entry<String,ArrayList<String>> entry: status.entrySet()){
			if(!entry.getValue().get(0).equals("0")){
				int currentday=Integer.parseInt(entry.getValue().get(1));
				int sourceday=Integer.parseInt(status.get(entry.getValue().get(0)).get(1));
				if(currentday-sourceday>1){
					int steps=(int) ((currentday-sourceday-1)/Constants.edgeDiscountFactor);
					for(int i=0;i<steps;i++){
						invisibleNodes.add("m"+invisibleNodes.size());	
					}
				}
			}else{
				firstInKey=entry.getKey();
			}
		}

		dot="digraph spread {"+newline+"graph [label=\""+percentageStudentInfected*100+
				"% student infected \", labelloc=bottom, fontsize=150];"
				+newline+"rankdir=LR;"+newline+"root="+firstInKey+";"
				+newline+"ranksep=3.0;"
				+newline+"nodesep=2.0;"+newline+
				firstInKey+newline;
		//first iterate through the sources
		//the size of the node reflect the number of recipient: sqrt(#of recipient)*Constants.nodeSize
		for(Entry<String,ArrayList<String>> entry: status.entrySet()){
			String mysource=entry.getValue().get(0);
			if(!source.contains(mysource)){
				if(mysource.equals("0")){
					dot+=entry.getKey()+" [fillcolor=";
					if(entry.getValue().get(3).equals("0")){
						dot+="coral1";
					}else{
						dot+="limegreen";
					}
					dot+= ",shape=doublecircle,"+"width=";
					if(radiusRatio){
						if(!radiusLog){
							dot+=Integer.parseInt(entry.getValue().get(2))*Constants.nodeSize;
						}else{
							dot+=Math.log(1+Integer.parseInt(entry.getValue().get(2))*Constants.nodeSize);
						}
					}else{
						dot+=Math.sqrt(Integer.parseInt(entry.getValue().get(2)))*Constants.nodeSize;
					}
					dot+=",style=filled,"+ "fontsize=12];"+newline;
					source.add(entry.getKey());
				}
				else{
					int size=Integer.parseInt(status.get(mysource).get(2));
					dot+=mysource+" [fillcolor=\"";
					if(!Constants.vaccination){
						if(!radiusRatio){
							if(size<=5){
								dot+="lightyellow1\"";
							}else if(size<=10){
								dot+="yellow1\"";
							}else if(size>10){
								dot+="goldenrod1\"";
							}
						}else{
							dot+="goldenrod1\"";
						}
					}else{
						if(status.get(mysource).get(3).equals("1")){
							dot+="limegreen\"";
						}else{
							dot+="goldenrod1\"";
						}
					}
					dot+=",shape=circle,"+"width=";
					if(radiusRatio){
						if(!radiusLog){
							dot+=Integer.parseInt(status.get(mysource).get(2))*Constants.nodeSize;
						}else{
							dot+=Math.log(1+Integer.parseInt(status.get(mysource).get(2))*Constants.nodeSize);
						}
					}else{
						dot+=Math.sqrt(size)*Constants.nodeSize;
					}
					dot+=",style=filled,"+ "fontsize=12];"+newline;
					source.add(mysource);
				}
			}
		}
		//Initialize the day scaler nodes
		maxsteps=(int)(maxdays/Constants.edgeDiscountFactor);
		dot+="{node[shape=plaintext, fontsize=16]";
		for(int i=1;i<=maxsteps;i++){
			dot+=" day"+(int)(i*Constants.edgeDiscountFactor);
		}
		dot+="}"+newline;
		//initialize invisible nodes
		dot+="{node[shape=point,style=invis] ";
		for(int i=0;i<invisibleNodes.size();i++){
			dot+=invisibleNodes.get(i)+" ";
		}
		dot+="}"+newline;

		//then we iterate through the keys and add edges
		for(Entry<String,ArrayList<String>> entry: status.entrySet()){
			String mykey=entry.getKey();
			if(!source.contains(mykey)){
				dot+=mykey+" [shape=point,fillcolor=\"";
				if(status.get(mykey).get(3).equals("1")){
					dot+="limegreen";
				}else{
					dot+="blueviolet";
				}
				dot+="\",width="+Constants.nodeSize+",style=filled,fontsize=12];"+newline;
			}
		}
		Iterator<String> it=invisibleNodes.iterator();
		for(Entry<String,ArrayList<String>> entry: status.entrySet()){
			String mykey=entry.getKey();
			String mysource=entry.getValue().get(0);
			if(!mysource.equals("0")){
				dot+=mysource;
				int currentday=Integer.parseInt(entry.getValue().get(1));
				int sourceday=Integer.parseInt(status.get(entry.getValue().get(0)).get(1));
				int steps=(int) (currentday/Constants.edgeDiscountFactor)
						-(int) (sourceday/Constants.edgeDiscountFactor)-1;
				for(int i=0;i<steps;i++){
					dot+="->"+it.next();
				}
				dot+="->"+mykey+"[arrowsize=0.4, penwidth=1.2,color="
						+ "\"dimgray\"]"+";"+newline;
			}
		}

		dot+=firstInKey+"->day"+(int)Constants.edgeDiscountFactor+"[style=bold,color=maroon3,penwidth=8]"+newline;
		for(int i=2;i<=maxsteps;i++){
			dot+="day"+(int)((i-1)*Constants.edgeDiscountFactor)+"->day"
					+(int)(i*Constants.edgeDiscountFactor)+"[style=bold,color=maroon3,penwidth=8]"+newline;
		}

		dot+="}";
	}

	public Hashtable<String,ArrayList<String>> getStatusHashtable(){
		return status;
	}
	public static void main(String[] args){
		ToDotAll mydot=new ToDotAll("remissionHTV3.csv");//Constants.saveFileAs+"V3.csv");
		mydot.setRadiusRatio(false);
		mydot.setRadiusLog(false);
		mydot.generateDot();
		try (PrintWriter out =new PrintWriter("remissionHTV3.dot")){//Constants.saveFileAs+"V2.dot")){
			out.println(dot);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}


Files generated by ToDotAll.java


graph 1.dot
graph 2.dot
graph 3.dot
graph 4.dot
graph 5.dot


Go back to: Visualizing the Transit Map of the Spread of an Infectious Disease