/// <summary> /// Secondary work creates a secondary work activity for person /// </summary> /// <param name="person"></param> /// <param name="schedule"></param> /// <param name="random"></param> /// <param name="primaryWorkEpisode"></param> /// <param name="householdPD"></param> /// <param name="workPD"></param> /// <param name="generationAdjustments"></param> private static void ProcessSecondaryWork(ITashaPerson person, Schedule schedule, Random random, Episode primaryWorkEpisode, int householdPD, int workPD, GenerationAdjustment[] generationAdjustments) { if (random == null) { throw new ArgumentNullException(nameof(random)); } //can only work if finish primary work by 7:00PM if (primaryWorkEpisode.EndTime < Scheduler.SecondaryWorkThreshold) { int freqR; //getting earliest possible startTime Time hourAfterWork = primaryWorkEpisode.EndTime + Time.OneHour; Time minStartTime = hourAfterWork > Scheduler.SecondaryWorkMinStartTime ? hourAfterWork : Scheduler.SecondaryWorkMinStartTime; freqR = TimeTable.GetFrequency(person, Activity.SecondaryWork, random, 10, minStartTime, Time.EndOfDay, householdPD, workPD, generationAdjustments); for (int i = 0; i < freqR; i++) { //zone same as work zone IZone zone = primaryWorkEpisode.Zone.ZoneNumber == Scheduler.Tasha.ZoneSystem.RoamingZoneNumber ? Scheduler.LocationChoiceModel.GetLocationHomeBased(Activity.SecondaryWork, person.Household.HomeZone, random) : primaryWorkEpisode.Zone; if (!TimeTable.GetStartTime(person, primaryWorkEpisode.ActivityType, freqR, minStartTime, Time.EndOfDay, random, out Time startTimeR)) { //TODO: We might want to reconsider this, skipping instead of just throwing an exception //throw new XTMFRuntimeException("Unable to find a start time for a primary work episode"); return; } if (!TimeTable.GetDuration(person, Activity.SecondaryWork, startTimeR, Time.EndOfDay - startTimeR, random, out Time durationR)) { //throw new XTMFRuntimeException("Unable to find a duration for a primary work episode"); return; } //inserting secondary work into schedule Episode secondaryWorkEpisode; secondaryWorkEpisode = new ActivityEpisode(new TimeWindow(startTimeR, startTimeR + durationR), Activity.SecondaryWork, person) { Zone = zone }; schedule.Insert(secondaryWorkEpisode, random); } } }
private static void ProcessWorkAtHome(ITashaPerson person, Schedule workSchedule, Random random, int householdPD, int workPD, GenerationAdjustment[] generationAdjustments) { int freq_A = TimeTable.GetFrequency(person, Activity.WorkAtHomeBusiness, random, householdPD, workPD, generationAdjustments); Time duration, startTime; for (int i = 0; i < freq_A; i++) { bool success = false; short attempt = 0; while (!success && (attempt < Scheduler.EpisodeSchedulingAttempts)) { if (!TimeTable.GetStartTime(person, Activity.WorkAtHomeBusiness, freq_A, random, out startTime)) { success = false; attempt++; continue; } if (!TimeTable.GetDuration(person, Activity.WorkAtHomeBusiness, startTime, Time.EndOfDay - startTime, random, out duration)) { success = false; attempt++; continue; } Time endTime = startTime + duration; SchedulerHousehold.CheckAndUpdateLatestWorkingTime(person.Household, endTime); Episode wahBusinessEpisode; wahBusinessEpisode = new ActivityEpisode(0, new TimeWindow(startTime, endTime), Activity.WorkAtHomeBusiness, person); if (!workSchedule.Insert(wahBusinessEpisode, random)) { success = false; attempt++; } else { success = true; } } } }
private static void ProcessWorkBusiness(ITashaPerson person, Schedule workSchedule, Random random, Episode primWorkEpisode, int householdPD, int workPD, GenerationAdjustment[] generationAdjustments) { Time startTimeB; Time durationB; Time startTime = primWorkEpisode.StartTime; Time endTime = primWorkEpisode.EndTime; int freq = TimeTable.GetFrequency(person, Activity.WorkBasedBusiness, random, Scheduler.MaxFrequency, startTime, endTime, householdPD, workPD, generationAdjustments); for (int i = 0; i < freq; i++) { var attempt = 0; while (attempt < Scheduler.EpisodeSchedulingAttempts) { attempt++; if (!TimeTable.GetStartTime(person, Activity.WorkBasedBusiness, freq, startTime, endTime, random, out startTimeB)) { continue; } if (!TimeTable.GetDuration(person, Activity.WorkBasedBusiness, startTimeB, endTime - startTimeB, random, out durationB)) { continue; } Episode businessEpisode; businessEpisode = new ActivityEpisode(0, new TimeWindow(startTimeB, startTimeB + durationB), Activity.WorkBasedBusiness, person); if (workSchedule.Insert(businessEpisode, random)) { break; } } } }
private static bool GenerateWorkEpisodes(this ITashaHousehold household, Random random, GenerationAdjustment[] generationAdjustments) { var householdPD = household.HomeZone.PlanningDistrict; foreach (ITashaPerson person in household.Persons) { // people need to be older than "11" to be allowed to work if (person.Age < Scheduler.MinimumWorkingAge) { continue; } // Check to see if they are in a regular job type case Project workProject = person.GetWorkProject(); Schedule workSchedule = workProject.Schedule; if ((person.Occupation == Occupation.NotEmployed) | (person.Occupation == Occupation.Unknown)) { continue; } if (((person.EmploymentStatus == TTSEmploymentStatus.FullTime) | (person.EmploymentStatus == TTSEmploymentStatus.PartTime))) { var empZone = person.EmploymentZone; int workPD = empZone == null ? 0 : empZone.PlanningDistrict; if (person.EmploymentZone == null) { //continue; throw new XTMFRuntimeException(TashaRuntime, "There was a person whom had no employment zone however was a full-time/part-time worker!"); } //Employment zone doesn't exist so generate our own based on distributions if (person.EmploymentZone.ZoneNumber == TashaRuntime.ZoneSystem.RoamingZoneNumber) { GenerateWorkBusinessEpisode(person, workSchedule, random, householdPD, workPD, generationAdjustments); continue; } int freq = TimeTable.GetFrequency(person, Activity.PrimaryWork, random, householdPD, workPD, generationAdjustments); if (freq <= 0) { continue; } Time startTime = Time.Zero; Time duration = Time.Zero; bool success = false; for (int i = 0; i < freq; i++) { for (int attempts = 0; attempts < Scheduler.EpisodeSchedulingAttempts; attempts++) { // If we use an and here the compiler can't prove that we assign to duration if (!TimeTable.GetStartTime(person, Activity.PrimaryWork, freq, random, out startTime)) { continue; } if (TimeTable.GetDuration(person, Activity.PrimaryWork, startTime, random, out duration)) { // if we got the duration, success lets continue on success = true; break; } } // if we were unable to get a duration if (!success) { // try the next person continue; } Time endTime = startTime + duration; CheckAndUpdateLatestWorkingTime(person.Household, endTime); Episode primWorkEpisode; primWorkEpisode = new ActivityEpisode(new TimeWindow(startTime, endTime), Activity.PrimaryWork, person) { Zone = person.EmploymentZone }; if (!workSchedule.Insert(primWorkEpisode, random) && i == 0) { throw new XTMFRuntimeException(TashaRuntime, "Failed to insert the primary work episode into the work project!"); } //set up work business activities ProcessWorkBusiness(person, workSchedule, random, primWorkEpisode, householdPD, workPD, generationAdjustments); //set up secondary work activities ProcessSecondaryWork(person, workSchedule, random, primWorkEpisode, householdPD, workPD, generationAdjustments); //set up return home from work activities ProcessReturnHomeFromWork(person, workSchedule, random, primWorkEpisode, householdPD, workPD, generationAdjustments); } } // Check to see if they work from home else if (person.Age >= 19 && ((person.EmploymentStatus == TTSEmploymentStatus.WorkAtHome_FullTime) | (person.EmploymentStatus == TTSEmploymentStatus.WorkAtHome_PartTime))) { ProcessWorkAtHome(person, workSchedule, random, householdPD, householdPD, generationAdjustments); } // If they don't work, just continue on } return(true); }
private static bool GenerateSchoolEpisodes(this ITashaHousehold household, Random random, GenerationAdjustment[] generationAdjustments) { var householdPD = household.HomeZone.PlanningDistrict; foreach (ITashaPerson person in household.Persons) { if (person.StudentStatus == StudentStatus.FullTime || person.StudentStatus == StudentStatus.PartTime) { if (person.Age >= 11) { var empZone = person.EmploymentZone; int workPD = empZone == null ? 0 : empZone.PlanningDistrict; var freq = TimeTable.GetFrequency(person, Activity.School, random, householdPD, workPD, generationAdjustments); //if there is a school activity generated for (int i = 0; i < freq; i++) { bool success = false; short attempt = 0; int maxAttempts = Scheduler.EpisodeSchedulingAttempts; while (!success && (attempt < maxAttempts)) { attempt++; //get start time end time and duration if (!TimeTable.GetStartTime(person, Activity.School, random, out Time startTime)) { continue; } if (!TimeTable.GetDuration(person, Activity.School, startTime, random, out Time duration)) { continue; } if (duration != Time.Zero) // no valid duration { var endTime = startTime + duration; if (endTime > Time.EndOfDay + TashaRuntime.EndOfDay + Time.OneQuantum) { continue; } //instantiate temporary school episode; Schedule schoolSchedule; Episode schoolEpisode; schoolEpisode = new ActivityEpisode(new TimeWindow(startTime, startTime + duration), Activity.School, person) { Zone = person.SchoolZone ?? person.Household.HomeZone }; Project schoolProject = person.GetSchoolProject(); schoolSchedule = schoolProject.Schedule; success = schoolSchedule.Insert(schoolEpisode, random); } } } } else if (person.Age >= 6) { //this child is in kindergarten //generate random number between 0 and 1 Time startTime, endTime; startTime = Scheduler.SchoolMorningStart; endTime = Scheduler.SchoolAfternoonEnd; Schedule schoolSchedule; Episode schoolEpisode; schoolEpisode = new ActivityEpisode(new TimeWindow(startTime, endTime), Activity.School, person) { Zone = person.SchoolZone ?? person.Household.HomeZone }; Project schoolProject = person.GetSchoolProject(); schoolSchedule = schoolProject.Schedule; schoolSchedule.Insert(schoolEpisode, random); } else if (person.Age == 5) { //this child is in kindergarten //generate random number between 0 and 1 int randNum = random.Next(0, 1); Time startTime, endTime; if (randNum <= 0.5) //morning shift { //morning shift startTime = Scheduler.SchoolMorningStart; endTime = Scheduler.SchoolMorningEnd; } else { //afternoon shift startTime = Scheduler.SchoolAfternoonStart; endTime = Scheduler.SchoolAfternoonEnd; } Schedule schoolSchedule; Episode schoolEpisode; schoolEpisode = new ActivityEpisode(new TimeWindow(startTime, endTime), Activity.School, person) { Zone = person.SchoolZone ?? person.Household.HomeZone }; Project schoolProject = person.GetSchoolProject(); schoolSchedule = schoolProject.Schedule; schoolSchedule.Insert(schoolEpisode, random); } } } return(true); }
private static bool GenerateJointOtherEpisodes(this ITashaHousehold household, Random random, GenerationAdjustment[] generationAdjustments) { var householdPD = household.HomeZone.PlanningDistrict; //make sure there at least 2 people and one adult if ((household.Persons.Length >= 2) & (household.NumberOfAdults > 0)) { int freqJ = TimeTable.GetFrequency(household, Activity.JointOther, random, householdPD, 0, generationAdjustments); int numEpisodeAdults = Distribution.GetNumAdultsJointEpisode(household, random, Activity.JointOther); for (int i = 0; i < freqJ; i++) { bool success = false; int attempt = 0; while (!success && attempt < Scheduler.EpisodeSchedulingAttempts) { if (!TimeTable.GetStartTime(household, Activity.JointOther, freqJ, random, out Time startTime)) { attempt++; continue; } if (!TimeTable.GetDuration(household, Activity.JointOther, startTime, random, out Time duration)) { attempt++; continue; } if (duration == Time.Zero || startTime == Time.Zero) { attempt++; } else { Time endTime = startTime + duration; List <ITashaPerson> availableAdults = new List <ITashaPerson>(); foreach (ITashaPerson person in household.Persons) { Time workSchoolStartTime = SchedulerPerson.GetWorkSchoolStartTime(person); Time workSchoolEndTime = SchedulerPerson.GetWorkSchoolEndTime(person); bool available = false; if (workSchoolStartTime > endTime || workSchoolEndTime < startTime || workSchoolStartTime == Time.Zero) { available = true; } if (person.Age >= 16 && available) { availableAdults.Add(person); } } if (availableAdults.Count >= numEpisodeAdults && availableAdults.Count > 0) { Episode jointOtherEpisode; var owner = availableAdults[0]; jointOtherEpisode = new ActivityEpisode(new TimeWindow(startTime, endTime), Activity.JointOther, owner); for (int j = 0; j < numEpisodeAdults; j++) { jointOtherEpisode.AddPerson(availableAdults[j]); } Project jointOtherProject = household.GetJointOtherProject(); Schedule jointOtherSchedule = jointOtherProject.Schedule; bool inserted = jointOtherSchedule.Insert(jointOtherEpisode, random); success = true; if (!inserted) { success = false; attempt++; } } else { attempt++; } } } } } return(true); }
private static bool GenerateJointMarketEpisodes(this ITashaHousehold household, Random random, GenerationAdjustment[] generationAdjustment) { var householdPD = household.HomeZone.PlanningDistrict; // initialize available adults var availableAdults = new List <ITashaPerson>(household.Persons.Length); // We can only do this with households with more than one person if (household.Persons.Length >= 2 && household.NumberOfAdults > 0) { // Figure out how many times this home is going to go on a joint market trip int howManyTimes = TimeTable.GetFrequency(household, Activity.JointMarket, random, householdPD, 0, generationAdjustment); // Processes each of those trips for (int i = 0; i < howManyTimes; i++) { int numEpisodeAdults = Distribution.GetNumAdultsJointEpisode(household, random, Activity.JointMarket); bool success = false; // continue to try until either we get it to work or we fail to schedule this episode for (int attempt = 0; !success && attempt < Scheduler.EpisodeSchedulingAttempts; attempt++) { if (!TimeTable.GetStartTime(household, Activity.JointMarket, random, out Time startTime)) { continue; } if (!TimeTable.GetDuration(household, Activity.JointMarket, startTime, random, out Time duration)) { continue; } // Now that we have our start time and duration, compute our end time Time endTime = startTime + duration; if (availableAdults.Count > 0) { availableAdults.Clear(); } Time workSchoolStartTime, workSchoolEndTime; bool available; foreach (var person in household.Persons) { workSchoolStartTime = SchedulerPerson.GetWorkSchoolStartTime(person); workSchoolEndTime = SchedulerPerson.GetWorkSchoolEndTime(person); // this person is available if available = (workSchoolStartTime > endTime) | (workSchoolEndTime < startTime) | (workSchoolStartTime == Time.Zero); if (person.Age >= 16 && available) { availableAdults.Add(person); } } if ((availableAdults.Count > 0) & (availableAdults.Count >= numEpisodeAdults)) { Episode jointMarketEpisode; jointMarketEpisode = new ActivityEpisode(new TimeWindow(startTime, endTime), Activity.JointMarket, availableAdults[0]); foreach (ITashaPerson adult in availableAdults) { jointMarketEpisode.AddPerson(adult); } Project jointMarketProject = household.GetJointMarketProject(); Schedule jointMarketSchedule = jointMarketProject.Schedule; bool insert = jointMarketSchedule.Insert(jointMarketEpisode, random); success = insert; } } } } return(true); }
private static bool GenerateIndividualOtherEpisodes(this ITashaHousehold household, Random random, GenerationAdjustment[] generationAdjustments) { int householdPD = household.HomeZone.PlanningDistrict; foreach (var person in household.Persons) { if (!person.Child) { var empZone = person.EmploymentZone; int workPD = empZone == null ? 0 : empZone.PlanningDistrict; int freqO = TimeTable.GetFrequency(person, Activity.IndividualOther, random, householdPD, workPD, generationAdjustments); int outerAttempts = 0; for (int i = 0; i < freqO; i++) { bool success = false; for (int attempt = 0; !success && (attempt < Scheduler.EpisodeSchedulingAttempts); attempt++) { if (!TimeTable.GetStartTime(person, Activity.IndividualOther, freqO, random, out Time startTimeO)) { continue; } if (!TimeTable.GetDuration(person, Activity.IndividualOther, startTimeO, random, out Time durationO)) { continue; } var endTime = startTimeO + durationO; if (endTime > Time.EndOfDay + TashaRuntime.EndOfDay + Time.OneQuantum) { continue; } Episode otherEpisode; otherEpisode = new ActivityEpisode(new TimeWindow(startTimeO, endTime), Activity.IndividualOther, person); Project workProject = person.GetWorkProject(); Schedule workProjSchedule = workProject.Schedule; Project schoolProject = person.GetSchoolProject(); Schedule schoolProjSchedule = schoolProject.Schedule; Time overlap = workProjSchedule.CheckOverlap(otherEpisode) + schoolProjSchedule.CheckOverlap(otherEpisode); float percentOverlap = overlap / durationO; if (percentOverlap < Scheduler.PercentOverlapAllowed || attempt == Scheduler.EpisodeSchedulingAttempts - 1) { Project otherProject = person.GetOtherProject(); Schedule otherSchedule = otherProject.Schedule; if (otherSchedule.Insert(otherEpisode, random)) { //inserted ok success = true; } } } if ((outerAttempts++) < Scheduler.EpisodeSchedulingAttempts && !success) { i = -1; Project otherProject = person.GetOtherProject(); Schedule otherSchedule = otherProject.Schedule; otherSchedule.Clear(); } } } } return(true); }
private static bool GenerateIndividualMarketEpisodes(this ITashaHousehold household, Random random, GenerationAdjustment[] generationAdjustments) { int householdPD = household.HomeZone.PlanningDistrict; foreach (var person in household.Persons) { if (!person.Child) { var empZone = person.EmploymentZone; int workPD = empZone == null ? 0 : empZone.PlanningDistrict; int freqI = TimeTable.GetFrequency(person, Activity.Market, random, householdPD, workPD, generationAdjustments); int outerAttempts = 0; for (int j = 0; j < freqI; ++j) { bool success = false; for (int attempt = 0; attempt < Scheduler.EpisodeSchedulingAttempts && !success; attempt++) { if (!TimeTable.GetStartTime(person, Activity.Market, random, out Time startTime)) { continue; } if (!TimeTable.GetDuration(person, Activity.Market, startTime, random, out Time duration)) { continue; } var endTime = startTime + duration; if (endTime > Time.EndOfDay + TashaRuntime.EndOfDay + Time.OneQuantum) { continue; } //instantiate a temporary individual market episode on the heap space and store pointer in p_marketEpisode var window = new TimeWindow(startTime, startTime + duration); Episode marketEpisode = new ActivityEpisode(window, Activity.Market, person); Project workProject = person.GetWorkProject(); Schedule workProjSchedule = workProject.Schedule; Project schoolProject = person.GetSchoolProject(); Schedule schoolProjSchedule = schoolProject.Schedule; Time overlap = workProjSchedule.CheckOverlap(marketEpisode) + schoolProjSchedule.CheckOverlap(marketEpisode); float percentOverlap = overlap / duration; if (percentOverlap < Scheduler.PercentOverlapAllowed || attempt == Scheduler.EpisodeSchedulingAttempts - 1) { Project marketProject = person.GetMarketProject(); Schedule marketSchedule = marketProject.Schedule; if (marketSchedule.Insert(marketEpisode, random)) { //inserted ok success = true; } } } if ((outerAttempts++) < Scheduler.EpisodeSchedulingAttempts && !success) { j = -1; Project marketProject = person.GetMarketProject(); Schedule marketSchedule = marketProject.Schedule; marketSchedule.Clear(); } } } } return(true); }