public override bool Insert(Episode ep, Random random) { /* This is where episodes are first put near their other common types * RULES: * 1) Unless it is a Work Business episode, we are not allowed to have a "split" conflict type * 2) We are not allowed to squish things past the threshold allowed (50% by default) */ // Learn what type of case we are going to be in ConflictReport conflict = InsertCase(null, ep, false); switch (conflict.Type) { case ScheduleConflictType.NoConflict: { InsertAt(ep, conflict.Position); return(true); } case ScheduleConflictType.Split: { if ((ep.ActivityType != Activity.WorkBasedBusiness) & (ep.ActivityType != Activity.ReturnFromWork)) { return(false); } if (Episodes[conflict.Position].ActivityType != Activity.PrimaryWork) { return(false); } // Since it is a primary work episode we need to split it var postEp = new ActivityEpisode(new TimeWindow(ep.EndTime, Episodes[conflict.Position].EndTime), Activity.PrimaryWork, Episodes[conflict.Position].Owner) { Zone = Episodes[conflict.Position].Zone }; ((Episode)Episodes[conflict.Position]).EndTime = ep.StartTime; InsertAt(ep, conflict.Position + 1); InsertAt(postEp, conflict.Position + 2); return(true); } case ScheduleConflictType.Posterior: { // the given position is the element we need to go after Time earlyTimeBound = Time.StartOfDay; Time lateTimeBound = Time.EndOfDay; Episode prior = (Episode)Episodes[conflict.Position]; Episode middle = ep; Episode post = (Episode)((conflict.Position < EpisodeCount - 1) ? Episodes[conflict.Position + 1] : null); if (conflict.Position >= 1) { earlyTimeBound = Episodes[conflict.Position - 1].EndTime; } if (EpisodeCount - conflict.Position > 2) { lateTimeBound = Episodes[conflict.Position + 2].StartTime; } if (Insert(earlyTimeBound, prior, middle, post, lateTimeBound)) { InsertAt(ep, conflict.Position + 1); return(true); } return(false); } case ScheduleConflictType.Prior: { // The given position is the element we need to go before Time earlyTimeBound = Time.StartOfDay; Time lateTimeBound = Time.EndOfDay; Episode prior = (Episode)(conflict.Position > 0 ? Episodes[conflict.Position - 1] : null); Episode middle = ep; Episode post = (Episode)Episodes[conflict.Position]; if (conflict.Position >= 2) { earlyTimeBound = Episodes[conflict.Position - 2].EndTime; } if (EpisodeCount - conflict.Position > 1) { lateTimeBound = Episodes[conflict.Position + 1].StartTime; } if (Insert(earlyTimeBound, prior, middle, post, lateTimeBound)) { InsertAt(ep, conflict.Position); return(true); } return(false); } case ScheduleConflictType.CompleteOverlap: { // There are no cases where a complete overlap is allowed return(false); } default: { // We came across a type of conflict that we do not know how to handle! throw new NotImplementedException(String.Format("This conflict type \"{0}\" has not been coded for yet!", Enum.GetName(typeof(ScheduleConflictType), conflict.Type))); } } }
public bool Insert(Episode ep, IZone location) { // you must be going somewhere if (location == null) { return(false); } ep.Zone = location; /* * This is going to be very similar to the ProjectSchedule version * The only difference is that we are going to take into account travel times */ ConflictReport conflict = InsertCase(Owner, ep, true); switch (conflict.Type) { case ScheduleConflictType.NoConflict: { InsertAt(ep, conflict.Position); return(true); } case ScheduleConflictType.CompleteOverlap: case ScheduleConflictType.Split: { // At this point work-business episodes have already been dealt with in the project schedule // Thus everything that splits an episode is in fact not allowed! return(false); } case ScheduleConflictType.Posterior: { // the given position is the element we need to go after Time earlyTimeBound = Time.StartOfDay + FirstTripTime; Time lateTimeBound = Time.EndOfDay; Episode prior = (Episode)Episodes[conflict.Position]; Episode middle = ep; Episode post = (Episode)((conflict.Position < EpisodeCount - 1) ? Episodes[conflict.Position + 1] : null); // Make sure to bound the times with the padding of the travel times required if (conflict.Position >= 1) { earlyTimeBound = Episodes[conflict.Position - 1].EndTime + Scheduler.TravelTime(Owner, Episodes[conflict.Position - 1].Zone, prior.Zone, prior.StartTime); } if (EpisodeCount - conflict.Position > 2) { lateTimeBound = Episodes[conflict.Position + 2].StartTime - Scheduler.TravelTime(Owner, post.Zone, Episodes[conflict.Position + 2].Zone, post.EndTime); } if (Insert(earlyTimeBound, prior, middle, post, lateTimeBound)) { InsertAt(ep, conflict.Position + 1); return(true); } return(false); } case ScheduleConflictType.Prior: { // The given position is the element we need to go before Time earlyTimeBound = Time.StartOfDay + FirstTripTime; Time lateTimeBound = Time.EndOfDay; Episode prior = (Episode)(conflict.Position > 0 ? Episodes[conflict.Position - 1] : null); Episode middle = ep; Episode post = (Episode)Episodes[conflict.Position]; // Make sure to bound the times with the padding of the travel times required if (conflict.Position >= 2) { earlyTimeBound = Episodes[conflict.Position - 2].EndTime + Scheduler.TravelTime(Owner, Episodes[conflict.Position - 2].Zone, prior.Zone, prior.StartTime); } if (EpisodeCount - conflict.Position > 1) { lateTimeBound = Episodes[conflict.Position + 1].StartTime - Scheduler.TravelTime(Owner, post.Zone, Episodes[conflict.Position + 1].Zone, post.EndTime); } if (Insert(earlyTimeBound, prior, middle, post, lateTimeBound)) { InsertAt(ep, conflict.Position); return(true); } return(false); } default: throw new NotImplementedException("Unknown insert conflict type!"); } }