示例#1
0
 public override Time CheckOverlap(Episode episode)
 {
     Time total = Time.Zero;
     for(int i = 0; i < this.EpisodeCount; i++)
     {
         if(this.Episodes[i].StartTime <= episode.StartTime
             && this.Episodes[i].EndTime >= episode.EndTime)
         {
             // this [i] completely covers the given episode
             total += episode.Duration;
         }
         else if(this.Episodes[i].StartTime >= episode.StartTime
             && this.Episodes[i].EndTime >= episode.EndTime)
         {
             // if the episode happens before we start, but we end after
             total += episode.EndTime - this.Episodes[i].StartTime;
         }
         else if(this.Episodes[i].StartTime <= episode.StartTime
             && this.Episodes[i].EndTime <= episode.EndTime)
         {
             //if we started before this episode, but we finished first
             total += this.Episodes[i].EndTime - episode.StartTime;
         }
         else if(this.Episodes[i].StartTime >= episode.StartTime
             && this.Episodes[i].EndTime <= episode.EndTime)
         {
             // if the episode is larger and 100% covering this [i]
             total += this.Episodes[i].Duration;
         }
     }
     return total;
 }
示例#2
0
 internal TravelEpisode(int id, TimeWindow timeWindow, Episode from, Episode to, ITashaPerson owner)
     : base(timeWindow, owner)
 {
     //TODO: verify this line:
     this.ActivityType = to.ActivityType;
     //-----
     this.From = from;
     this.To = to;
 }
示例#3
0
        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!");
            }
        }
示例#4
0
文件: Schedule.cs 项目: Cocotus/XTMF
 public abstract bool TestInsert(Episode episode);
示例#5
0
文件: Schedule.cs 项目: Cocotus/XTMF
 private void IncreaseArraySize()
 {
     // if we don't have room create a new array of 2x the size
     var temp = new Episode[this.EpisodeCount * 2];
     // copy all of the old data
     Array.Copy( this.Episodes, temp, this.EpisodeCount );
     // and now use that larger array
     this.Episodes = temp;
 }
示例#6
0
 public override Time CheckOverlap(Episode episode)
 {
     throw new NotImplementedException();
 }
示例#7
0
 private bool UnableToJustMoveToInsert(Time earlyTimeBound, Episode prior, Episode middle, Episode post, Time lateTimeBound)
 {
     // if the amount of time that we have to work with is larger then we are unable to just move to insert
     return((lateTimeBound - earlyTimeBound)
            < (prior != null ? prior.Duration : Time.Zero)
            + middle.Duration
            + (post != null ? post.Duration : Time.Zero));
 }
示例#8
0
 private static void Relocate(Episode ep, Time startTime)
 {
     var dur = ep.Duration;
     ep.EndTime = (ep.StartTime = startTime) + dur;
 }
示例#9
0
 /// <summary>
 /// Run a quick check to see if it is at all possible to place all of the 3 episodes in the given time bounds
 /// </summary>
 /// <param name="earlyTimeBound">The earliest point</param>
 /// <param name="prior">the first episode in the batch (possibly null if there is no episode prior)</param>
 /// <param name="middle">the second episode in the batch</param>
 /// <param name="post">the last episode in the batch (possibly null if there is no episode post)</param>
 /// <param name="lateTimeBound">the latest point</param>
 /// <returns>If we can fit them all in properly</returns>
 private bool InitialInsertCheckPossible(Time earlyTimeBound, Episode prior, Episode middle, Episode post, Time lateTimeBound,
     ref Time travelFirst,
     ref Time travelSecond
     )
 {
     Time minPrior = Time.Zero;
     Time minMid = Tasha.Scheduler.Scheduler.PercentOverlapAllowed * middle.OriginalDuration;
     Time minPost = Time.Zero;
     if(prior != null)
     {
         minPrior = Tasha.Scheduler.Scheduler.PercentOverlapAllowed * prior.OriginalDuration;
         travelFirst = Scheduler.TravelTime(Owner, prior.Zone, middle.Zone, prior.EndTime);
     }
     else
     {
         travelFirst = Scheduler.TravelTime(Owner, Owner.Household.HomeZone, middle.Zone, middle.StartTime);
     }
     if(post != null)
     {
         minPost = Tasha.Scheduler.Scheduler.PercentOverlapAllowed * post.OriginalDuration;
         travelSecond = Scheduler.TravelTime(Owner, middle.Zone, post.Zone, middle.EndTime);
     }
     else
     {
         travelSecond = Scheduler.TravelTime(Owner, middle.Zone, Owner.Household.HomeZone, middle.EndTime);
     }
     // it is possible to fit in if the bounds are larger than the minimum size of all three episodes
     return (lateTimeBound - earlyTimeBound) >= (minPrior + minMid + minPost + travelFirst + travelSecond);
 }
示例#10
0
        /// <summary>
        /// Return home from work creates a return home from work activity (return home from work may involve
        /// going to lunch at home or going to check up on something in the house during work).
        /// </summary>
        /// <param name="person"></param>
        /// <param name="schedule"></param>
        /// <param name="episode"></param>
        /// <returns></returns>
        private static bool ProcessReturnHomeFromWork(ITashaPerson person, Schedule schedule, Random random, Episode episode, int householdPD, int workPD, GenerationAdjustment[] generationAdjustments)
        {
            int freq = 0;

            //the current work schedule doesn't allow for a return from work activity
            if (episode.StartTime > Scheduler.MaxPrimeWorkStartTimeForReturnHomeFromWork ||
                episode.Duration < Scheduler.MinPrimaryWorkDurationForReturnHomeFromWork)
            {
                return(false);
            }

            //End time of work to home activity
            Time endTime = episode.EndTime + new Time(0.3f) < Scheduler.ReturnHomeFromWorkMaxEndTime ?
                           episode.EndTime + new Time(0.3f) : Scheduler.ReturnHomeFromWorkMaxEndTime;

            freq = TimeTable.GetFrequency(person, Activity.ReturnFromWork, random, 1, episode.StartTime + new Time(0.3f), endTime,
                                          householdPD, workPD, generationAdjustments);

            if (freq == 1)
            {
                IZone homeZone = person.Household.HomeZone;

                Time HalfAnHour = new Time()
                {
                    Minutes = 30
                };

                Time MaxEndTime = ((episode.EndTime - HalfAnHour) < Scheduler.ReturnHomeFromWorkMaxEndTime) ? (episode.EndTime - HalfAnHour) : Scheduler.ReturnHomeFromWorkMaxEndTime;

                Time startTime;
                if (!TimeTable.GetStartTime(person, Activity.ReturnFromWork
                                            , freq
                                            , episode.StartTime + HalfAnHour
                                            , MaxEndTime, random, out startTime))
                {
                    return(false);
                }

                Time maxDuration = new Time(Math.Min((Scheduler.ReturnHomeFromWorkMaxEndTime - Time.OneHour).ToFloat(),
                                                     (episode.EndTime - HalfAnHour - startTime).ToFloat()));

                Time duration;
                if (!TimeTable.GetDuration(person, Activity.ReturnFromWork, startTime, maxDuration, random, out duration))
                {
                    // reject
                    return(false);
                }

                Episode returnFromWorkEpisode;
                returnFromWorkEpisode = new ActivityEpisode(0,
                                                            new TimeWindow(startTime, startTime + duration), Activity.ReturnFromWork,
                                                            person);
                returnFromWorkEpisode.Zone = homeZone;
                schedule.Insert(returnFromWorkEpisode, random);
            }
            return(true);
        }
示例#11
0
        /// <summary>
        /// Secondary work creates a secondary work activity for person
        /// </summary>
        /// <param name="person"></param>
        /// <param name="schedule"></param>
        /// <param name="primaryWorkEpisode"></param>
        private static void ProcessSecondaryWork(ITashaPerson person, Schedule schedule, Random random, Episode primaryWorkEpisode, int householdPD,
                                                 int workPD, GenerationAdjustment[] generationAdjustments)
        {
            //can only work if finish primary work by 7:00PM
            if (primaryWorkEpisode.EndTime < Scheduler.SecondaryWorkThreshold)
            {
                int freq_R = 0;

                //getting earliest possible startTime
                Time HourAfterWork = primaryWorkEpisode.EndTime + Time.OneHour;
                Time MinStartTime  = HourAfterWork > Scheduler.SecondaryWorkMinStartTime ? HourAfterWork : Scheduler.SecondaryWorkMinStartTime;

                freq_R = TimeTable.GetFrequency(person, Activity.SecondaryWork, random, 10, MinStartTime, Time.EndOfDay,
                                                householdPD, workPD, generationAdjustments);

                for (int i = 0; i < freq_R; 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;

                    //getting start time and duration of secondary work
                    Time startTimeR;

                    Time durationR;

                    if (!TimeTable.GetStartTime(person, primaryWorkEpisode.ActivityType, freq_R, MinStartTime, Time.EndOfDay, random, out 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 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(0,
                                                               new TimeWindow(startTimeR, startTimeR + durationR),
                                                               Activity.SecondaryWork, person);
                    secondaryWorkEpisode.Zone = zone;
                    schedule.Insert(secondaryWorkEpisode, random);
                }
            }
        }
示例#12
0
 /// <summary>
 /// Checks to see if an episode can be inserted
 /// </summary>
 public abstract Time CheckOverlap(Episode episode);
示例#13
0
 /// <summary>
 /// Forces an episode to be inserted
 /// </summary>
 public abstract bool ForcedEpisodeInsert(Episode ep);
示例#14
0
 public abstract bool TestInsert(Episode episode);
示例#15
0
 public abstract bool Insert(Episode ep, Random random);
示例#16
0
        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 = this.InsertCase(null, ep, false);

            switch (conflict.Type)
            {
            case ScheduleConflictType.NoConflict:
            {
                this.InsertAt(ep, conflict.Position);
                return(true);
            }

            case ScheduleConflictType.Split:
            {
                if ((ep.ActivityType != Activity.WorkBasedBusiness) & (ep.ActivityType != Activity.ReturnFromWork))
                {
                    return(false);
                }
                if (this.Episodes[conflict.Position].ActivityType != Activity.PrimaryWork)
                {
                    return(false);
                }
                // Since it is a primary work episode we need to split it
                var postEp = new ActivityEpisode(0, new TimeWindow(ep.EndTime, this.Episodes[conflict.Position].EndTime), Activity.PrimaryWork,
                                                 this.Episodes[conflict.Position].Owner);
                postEp.Zone = this.Episodes[conflict.Position].Zone;
                ((Episode)this.Episodes[conflict.Position]).EndTime = ep.StartTime;
                this.InsertAt(ep, conflict.Position + 1);
                this.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)this.Episodes[conflict.Position];
                Episode middle         = ep;
                Episode post           = (Episode)((conflict.Position < this.EpisodeCount - 1)
                            ? this.Episodes[conflict.Position + 1] : null);
                if (conflict.Position >= 1)
                {
                    earlyTimeBound = this.Episodes[conflict.Position - 1].EndTime;
                }
                if (this.EpisodeCount - conflict.Position > 2)
                {
                    lateTimeBound = this.Episodes[conflict.Position + 2].StartTime;
                }
                if (this.Insert(earlyTimeBound, prior, middle, post, lateTimeBound))
                {
                    this.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 ? this.Episodes[conflict.Position - 1] : null);
                Episode middle         = ep;
                Episode post           = (Episode)this.Episodes[conflict.Position];
                if (conflict.Position >= 2)
                {
                    earlyTimeBound = this.Episodes[conflict.Position - 2].EndTime;
                }
                if (this.EpisodeCount - conflict.Position > 1)
                {
                    lateTimeBound = this.Episodes[conflict.Position + 1].StartTime;
                }
                if (this.Insert(earlyTimeBound, prior, middle, post, lateTimeBound))
                {
                    this.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)));
            }
            }
        }
示例#17
0
 public override bool TestInsert(Episode episode)
 {
     throw new NotImplementedException();
 }
示例#18
0
        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;
                    }
                }
            }
        }
示例#19
0
 private static bool MiddlePostInsert(ref Time earlyTimeBound, Episode middle, Episode post, ref Time lateTimeBound, ref Time firstTime, ref Time secondTime)
 {
     Time overlap = (middle.EndTime + secondTime) - post.StartTime;
     if(overlap <= Time.Zero)
     {
         return true;
     }
     // if we can move forward, move forward
     if((middle.StartTime - firstTime) - earlyTimeBound > overlap)
     {
         Relocate(middle, (middle.StartTime - overlap));
         return true;
     }
     // if that is not enough, move as forward as we can
     Relocate(middle, (earlyTimeBound + firstTime));
     overlap = (middle.EndTime + secondTime) - post.StartTime;
     Relocate(post, (post.StartTime + overlap));
     return true;
 }
示例#20
0
        /// <summary>
        /// Return home from work creates a return home from work activity (return home from work may involve
        /// going to lunch at home or going to check up on something in the house during work).
        /// </summary>
        /// <param name="person"></param>
        /// <param name="schedule"></param>
        /// <param name="episode"></param>
        /// <returns></returns>
        private static bool ProcessReturnHomeFromWork(ITashaPerson person, Schedule schedule, Random random, Episode episode)
        {
            int freq = 0;

            //the current work schedule doesn't allow for a return from work activity
            if(episode.StartTime > Scheduler.MaxPrimeWorkStartTimeForReturnHomeFromWork
                || episode.Duration < Scheduler.MinPrimaryWorkDurationForReturnHomeFromWork)
            {
                return false;
            }

            //End time of work to home activity
            Time endTime = episode.EndTime + new Time(0.3f) < Scheduler.ReturnHomeFromWorkMaxEndTime ?
                episode.EndTime + new Time(0.3f) : Scheduler.ReturnHomeFromWorkMaxEndTime;

            freq = TimeTable.GetFrequency(person, Activity.ReturnFromWork, random, 1, episode.StartTime + new Time(0.3f), endTime);

            if(freq == 1)
            {
                IZone homeZone = person.Household.HomeZone;

                Time HalfAnHour = new Time() { Minutes = 30 };

                Time MaxEndTime = ((episode.EndTime - HalfAnHour) < Scheduler.ReturnHomeFromWorkMaxEndTime) ? (episode.EndTime - HalfAnHour) : Scheduler.ReturnHomeFromWorkMaxEndTime;

                Time startTime;
                if(!TimeTable.GetStartTime(person, Activity.ReturnFromWork
                     , freq
                     , episode.StartTime + HalfAnHour
                     , MaxEndTime, random, out startTime))
                {
                    return false;
                }

                Time maxDuration = new Time(Math.Min((Scheduler.ReturnHomeFromWorkMaxEndTime - Time.OneHour).ToFloat(),
                    (episode.EndTime - HalfAnHour - startTime).ToFloat()));

                Time duration;
                if(!TimeTable.GetDuration(person, Activity.ReturnFromWork, startTime, maxDuration, random, out duration))
                {
                    // reject
                    return false;
                }

                Episode returnFromWorkEpisode;
                returnFromWorkEpisode = new ActivityEpisode(0,
                    new TimeWindow(startTime, startTime + duration), Activity.ReturnFromWork,
                    person);
                returnFromWorkEpisode.Zone = homeZone;
                schedule.Insert(returnFromWorkEpisode, random);
            }
            return true;
        }
示例#21
0
 private bool CheckDurations(Time priorDuration, Episode prior)
 {
     if(prior != null)
     {
         return priorDuration >= prior.Duration;
     }
     return true;
 }
示例#22
0
        private bool UnableToJustMoveToInsert(Time earlyTimeBound, Episode prior, Episode middle, Episode post, Time lateTimeBound,
                                              ref Time travelFirst,
                                              ref Time travelSecond)
        {
            // if the amount of time that we have to work with is larger then we are unable to just move to insert
            var totalTime = (prior != null ? prior.Duration : Time.Zero)
                            + middle.Duration
                            + (post != null ? post.Duration : Time.Zero)
                            + travelFirst + travelSecond;
            var boundTime = (lateTimeBound - earlyTimeBound);

            return(boundTime
                   <= totalTime);
        }
示例#23
0
 private bool ShiftToInsert(ref Time earlyTimeBound, Episode prior, Episode middle, Episode post, ref Time lateTimeBound, ref Time firstTime, ref Time secondTime)
 {
     if(prior != null & post != null)
     {
         return AllThreeInsert(ref earlyTimeBound, prior, middle, post, ref lateTimeBound, ref firstTime, ref secondTime);
     }
     else if(prior != null)
     {
         return PriorMiddleInsert(ref earlyTimeBound, prior, middle, ref lateTimeBound, ref firstTime, ref secondTime);
     }
     else if(post != null)
     {
         return MiddlePostInsert(ref earlyTimeBound, middle, post, ref lateTimeBound, ref firstTime, ref secondTime);
     }
     throw new XTMFRuntimeException("Unexpected shift to insert case!");
 }
示例#24
0
文件: Schedule.cs 项目: Cocotus/XTMF
        /// <summary>
        /// Insert into our array data structure
        /// </summary>
        /// <param name="ep">The episode you want to insert</param>
        /// <param name="pos">The position you want to insert it into</param>
        public void InsertAt(Episode ep, int pos)
        {
            // if we are not adding it to the end
            if ( ( pos < 0 ) | ( pos > this.EpisodeCount ) )
            {
                throw new XTMFRuntimeException( "Tried to insert into an schedule at position " + pos
                    + " where there are currently " + this.EpisodeCount + " episodes." );
            }

            if ( this.EpisodeCount + 1 >= this.Episodes.Length )
            {
                // if we are assigning to the end, but it isn't large enough, expand
                IncreaseArraySize();
            }

            if ( pos != this.EpisodeCount )
            {
                Array.Copy( this.Episodes, pos, this.Episodes, pos + 1, this.EpisodeCount - pos );
            }
            // take ownership of the episode
            ep.ContainingSchedule = this;
            this.Episodes[pos] = ep;
            this.EpisodeCount++;

            CheckEpisodeIntegrity();
        }
示例#25
0
        /// <summary>
        /// Secondary work creates a secondary work activity for person
        /// </summary>
        /// <param name="person"></param>
        /// <param name="schedule"></param>
        /// <param name="primaryWorkEpisode"></param>
        private static void ProcessSecondaryWork(ITashaPerson person, Schedule schedule, Random random, Episode primaryWorkEpisode)
        {
            //can only work if finish primary work by 7:00PM
            if(primaryWorkEpisode.EndTime < Scheduler.SecondaryWorkThreshold)
            {
                int freq_R = 0;

                //getting earliest possible startTime
                Time HourAfterWork = primaryWorkEpisode.EndTime + Time.OneHour;
                Time MinStartTime = HourAfterWork > Scheduler.SecondaryWorkMinStartTime ? HourAfterWork : Scheduler.SecondaryWorkMinStartTime;

                freq_R = TimeTable.GetFrequency(person, Activity.SecondaryWork, random, 10, MinStartTime, Time.EndOfDay);

                for(int i = 0; i < freq_R; 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;

                    //getting start time and duration of secondary work
                    Time startTimeR;

                    Time durationR;

                    if(!TimeTable.GetStartTime(person, primaryWorkEpisode.ActivityType, freq_R, MinStartTime, Time.EndOfDay, random, out 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 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(0,
                        new TimeWindow(startTimeR, startTimeR + durationR),
                        Activity.SecondaryWork, person);
                    secondaryWorkEpisode.Zone = zone;
                    schedule.Insert(secondaryWorkEpisode, random);
                }
            }
        }
示例#26
0
        /// <summary>
        /// Run a quick check to see if it is at all possible to place all of the 3 episodes in the given time bounds
        /// </summary>
        /// <param name="earlyTimeBound">The earliest point</param>
        /// <param name="prior">the first episode in the batch (possibly null if there is no episode prior)</param>
        /// <param name="middle">the second episode in the batch</param>
        /// <param name="post">the last episode in the batch (possibly null if there is no episode post)</param>
        /// <param name="lateTimeBound">the latest point</param>
        /// <returns>If we can fit them all in properly</returns>
        private bool InitialInsertCheckPossible(Time earlyTimeBound, Episode prior, Episode middle, Episode post, Time lateTimeBound)
        {
            Time minPrior = (prior != null ? Tasha.Scheduler.Scheduler.PercentOverlapAllowed * prior.OriginalDuration : Time.Zero);
            Time minMid   = Tasha.Scheduler.Scheduler.PercentOverlapAllowed * middle.OriginalDuration;
            Time minPost  = (post != null ? Tasha.Scheduler.Scheduler.PercentOverlapAllowed * post.OriginalDuration : Time.Zero);

            // it is possible to fit in if the bounds are larger than the minimum size of all three episodes
            return((lateTimeBound - earlyTimeBound) >= (minPrior + minMid + minPost));
        }
示例#27
0
文件: Schedule.cs 项目: Cocotus/XTMF
 public abstract bool Insert(Episode ep, Random random);
示例#28
0
        private static void ProcessWorkBusiness(ITashaPerson person, Schedule workSchedule, Random random, Episode primWorkEpisode)
        {
            Time startTimeB;
            Time durationB;
            Time startTime = primWorkEpisode.StartTime;
            Time endTime = primWorkEpisode.EndTime;

            int freq = TimeTable.GetFrequency(person, Activity.WorkBasedBusiness, random, Scheduler.MaxFrequency, startTime, endTime);
            for(int i = 0; i < freq; i++)
            {
                var attempt = 0;
                bool success = false;
                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))
                    {
                        success = true;
                        break;
                    }
                }
            }
        }
示例#29
0
文件: Schedule.cs 项目: Cocotus/XTMF
        public ConflictReport InsertCase(ITashaPerson owner, Episode ep, bool travelTime)
        {
            ConflictReport report;
            report.Type = ScheduleConflictType.NoConflict;
            report.Position = this.EpisodeCount;

            for ( int i = 0; i < this.EpisodeCount; i++ )
            {
                if ( this.Episodes[i].EndTime + this.Episodes[i].TravelTime < ep.StartTime ) continue;
                Time epEnd = ep.EndTime;
                Time ithEnd = this.Episodes[i].EndTime;
                if ( travelTime )
                {
                    ep.TravelTime = ( this.EpisodeCount - 1 > i ) ?
                        Scheduler.TravelTime( owner, ep.Zone, this.Episodes[i + 1].Zone, ep.EndTime ) : Time.Zero;
                    epEnd += ep.TravelTime;
                    ithEnd += this.Episodes[i].TravelTime;
                }
                report.Position = i;
                // Check for Complete overlap of the ith position
                if ( this.Episodes[i].StartTime >= ep.StartTime && ( epEnd >= ithEnd || ep.EndTime >= this.Episodes[i].EndTime ) )
                {
                    report.Type = ScheduleConflictType.CompleteOverlap;
                }
                else if ( this.EpisodeCount - 1 > i && this.Episodes[i + 1].StartTime >= ep.StartTime && epEnd >= this.Episodes[i + 1].EndTime )
                {
                    report.Type = ScheduleConflictType.CompleteOverlap;
                }
                else if ( this.Episodes[i].StartTime < ep.StartTime && ep.EndTime < this.Episodes[i].EndTime )
                {
                    report.Type = ScheduleConflictType.Split;
                }
                else if ( this.Episodes[i].StartTime >= ep.StartTime && ep.EndTime < this.Episodes[i].EndTime )
                {
                    report.Type = ScheduleConflictType.Prior;
                }
                else if ( this.Episodes[i].StartTime < ep.StartTime && ep.EndTime >= this.Episodes[i].EndTime )
                {
                    report.Type = ScheduleConflictType.Posterior;
                }
                break;
            }
            return report; // There is no conflict
        }
示例#30
0
        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!");
            }
        }
示例#31
0
文件: Schedule.cs 项目: Cocotus/XTMF
 private static void StoreEpisode(Episode e, StringBuilder builder)
 {
     builder.Append( "Activity -> " );
     builder.Append( e.ActivityType.ToString() );
     builder.Append( ", Start -> " );
     builder.Append( e.StartTime.ToString() );
     builder.Append( ", End -> " );
     builder.Append( e.EndTime.ToString() );
     builder.Append( ", TT -> " );
     builder.Append( e.TravelTime.ToString() );
 }
示例#32
0
 public override bool TestInsert(Episode episode)
 {
     throw new NotImplementedException();
 }
示例#33
0
文件: Schedule.cs 项目: Cocotus/XTMF
 /// <summary>
 /// Checks to see if an episode can be inserted
 /// </summary>
 public abstract Time CheckOverlap(Episode episode);
示例#34
0
        private static bool MiddlePostInsert(ref Time earlyTimeBound, Episode middle, Episode post, ref Time lateTimeBound, ref Time firstTime, ref Time secondTime)
        {
            Time overlap = (middle.EndTime + secondTime) - post.StartTime;

            if (overlap <= Time.Zero)
            {
                return(true);
            }
            // if we can move forward, move forward
            if ((middle.StartTime - firstTime) - earlyTimeBound > overlap)
            {
                Relocate(middle, (middle.StartTime - overlap));
                return(true);
            }
            // if that is not enough, move as forward as we can
            Relocate(middle, (earlyTimeBound + firstTime));
            overlap = (middle.EndTime + secondTime) - post.StartTime;
            Relocate(post, (post.StartTime + overlap));
            return(true);
        }
示例#35
0
        public override bool Insert(Episode ep, Random random)
        {
            IZone zone = null;
            ep.ContainingSchedule = this;
            // if we are generating locations now is the time to do it
            if(random != null)
            {
                zone = Tasha.Scheduler.Scheduler.LocationChoiceModel.GetLocation(ep, random);
                // if we can not find a zone, then this episode is infeasible
                if(zone == null)
                {
                    return false;
                }

            }
            return Insert(ep, zone);
        }
示例#36
0
        private static bool PriorMiddleInsert(ref Time earlyTimeBound, Episode prior, Episode middle, ref Time lateTimeBound, ref Time firstTime, ref Time secondTime)
        {
            Time overlap = (prior.EndTime + firstTime) - middle.StartTime;

            if (overlap <= Time.Zero)
            {
                return(true);
            }
            // if we can move back, move back
            if (lateTimeBound - (middle.EndTime + secondTime) > overlap)
            {
                Relocate(middle, (prior.EndTime + firstTime));
                return(true);
            }
            // move back as far as we can
            Relocate(middle, (lateTimeBound - middle.Duration - secondTime));
            // recalculate the overlap
            overlap = (prior.EndTime + firstTime) - middle.StartTime;
            Relocate(prior, prior.StartTime - overlap);
            return(true);
        }
示例#37
0
 private static bool FillInGaps(Episode middle, ref Time priorOverlap, ref Time postOverlap)
 {
     if(priorOverlap <= Time.Zero)
     {
         // check to see if there is enough time to move the middle closer to the prior
         if(postOverlap <= -priorOverlap)
         {
             Relocate(middle, (middle.StartTime - postOverlap));
             return true;
         }
         else
         {
             // prior overlap < 0, so just add it
             Relocate(middle, (middle.StartTime + priorOverlap));
             // subtract out the reduced time
             postOverlap += priorOverlap;
         }
     }
     if(postOverlap <= Time.Zero)
     {
         // check to see if there is enough time to move the middle closer to the prior
         if(priorOverlap <= -postOverlap)
         {
             Relocate(middle, (middle.StartTime + priorOverlap));
             return true;
         }
         else
         {
             // prior overlap < 0, so subtract it
             Relocate(middle, (middle.StartTime - postOverlap));
             // subtract out the reduced time
             priorOverlap += postOverlap;
         }
     }
     return false;
 }
示例#38
0
        private static void Relocate(Episode ep, Time startTime)
        {
            var dur = ep.Duration;

            ep.EndTime = (ep.StartTime = startTime) + dur;
        }
示例#39
0
 private static bool PriorMiddleInsert(ref Time earlyTimeBound, Episode prior, Episode middle, ref Time lateTimeBound, ref Time firstTime, ref Time secondTime)
 {
     Time overlap = (prior.EndTime + firstTime) - middle.StartTime;
     if(overlap <= Time.Zero)
     {
         return true;
     }
     // if we can move back, move back
     if(lateTimeBound - (middle.EndTime + secondTime) > overlap)
     {
         Relocate(middle, (prior.EndTime + firstTime));
         return true;
     }
     // move back as far as we can
     Relocate(middle, (lateTimeBound - middle.Duration - secondTime));
     // recalculate the overlap
     overlap = (prior.EndTime + firstTime) - middle.StartTime;
     Relocate(prior, prior.StartTime - overlap);
     return true;
 }
示例#40
0
        private bool AllThreeInsert(ref Time earlyTimeBound, Episode prior, Episode middle, Episode post, ref Time lateTimeBound, ref Time firstTime, ref Time secondTime)
        {
            Time priorOverlap = (prior.EndTime + firstTime) - middle.StartTime;
            Time postOverlap  = (middle.EndTime + secondTime) - post.StartTime;
            Time frontGap     = prior.StartTime - earlyTimeBound;
            Time backGap      = lateTimeBound - (post.EndTime + secondTime);

            // see if we can just fill in the gaps
            if (FillInGaps(middle, ref priorOverlap, ref postOverlap))
            {
                return(true);
            }
            // push the episodes away from the middle with a proportion to what they overlap it with
            if (priorOverlap < Time.Zero)
            {
                priorOverlap = Time.Zero;
            }
            if (postOverlap < Time.Zero)
            {
                postOverlap = Time.Zero;
            }
            // make sure that there is actually an overlap
            var overlap = priorOverlap + postOverlap;

            if (overlap == Time.Zero)
            {
                return(true);
            }
            overlap = Time.Zero;
            var  newPriorStartTime = prior.StartTime - priorOverlap;
            bool priorFailed       = false;

            if (newPriorStartTime < earlyTimeBound)
            {
                overlap           = earlyTimeBound - newPriorStartTime;
                newPriorStartTime = earlyTimeBound;
                priorFailed       = true;
            }
            var newPostStartTime = post.StartTime + postOverlap;

            if (newPostStartTime + post.Duration > lateTimeBound)
            {
                overlap         += (newPostStartTime + post.Duration) - lateTimeBound;
                newPostStartTime = lateTimeBound - post.Duration;
            }
            Relocate(prior, newPriorStartTime);
            Relocate(post, newPostStartTime);
            if (overlap == Time.Zero)
            {
                return(true);
            }
            if (priorFailed)
            {
                Relocate(middle, middle.StartTime + overlap);
                Relocate(post, middle.EndTime + secondTime);
            }
            else
            {
                Relocate(middle, middle.StartTime - overlap);
                Relocate(prior, middle.StartTime - firstTime - prior.Duration);
            }
            // Sanity Check
            if (post.EndTime > lateTimeBound)
            {
                throw new XTMFRuntimeException("We ended too late when inserting with 3 into a person schedule!\r\n"
                                               + Dump(this));
            }
            else if (prior.StartTime < earlyTimeBound)
            {
                throw new XTMFRuntimeException("We started too early when inserting with 3 into a person schedule!\r\n"
                                               + Dump(this)
                                               + "\r\nFirst Time = " + firstTime.ToString()
                                               + "\r\nSecond Time = " + secondTime.ToString());
            }
            return(true);
        }
示例#41
0
 private bool AllThreeInsert(ref Time earlyTimeBound, Episode prior, Episode middle, Episode post, ref Time lateTimeBound, ref Time firstTime, ref Time secondTime)
 {
     Time priorOverlap = (prior.EndTime + firstTime) - middle.StartTime;
     Time postOverlap = (middle.EndTime + secondTime) - post.StartTime;
     Time frontGap = prior.StartTime - earlyTimeBound;
     Time backGap = lateTimeBound - (post.EndTime + secondTime);
     // see if we can just fill in the gaps
     if(FillInGaps(middle, ref priorOverlap, ref postOverlap))
     {
         return true;
     }
     // push the episodes away from the middle with a proportion to what they overlap it with
     if(priorOverlap < Time.Zero) priorOverlap = Time.Zero;
     if(postOverlap < Time.Zero) postOverlap = Time.Zero;
     // make sure that there is actually an overlap
     var overlap = priorOverlap + postOverlap;
     if(overlap == Time.Zero) return true;
     overlap = Time.Zero;
     var newPriorStartTime = prior.StartTime - priorOverlap;
     bool priorFailed = false;
     if(newPriorStartTime < earlyTimeBound)
     {
         overlap = earlyTimeBound - newPriorStartTime;
         newPriorStartTime = earlyTimeBound;
         priorFailed = true;
     }
     var newPostStartTime = post.StartTime + postOverlap;
     if(newPostStartTime + post.Duration > lateTimeBound)
     {
         overlap += (newPostStartTime + post.Duration) - lateTimeBound;
         newPostStartTime = lateTimeBound - post.Duration;
     }
     Relocate(prior, newPriorStartTime);
     Relocate(post, newPostStartTime);
     if(overlap == Time.Zero) return true;
     if(priorFailed)
     {
         Relocate(middle, middle.StartTime + overlap);
         Relocate(post, middle.EndTime + secondTime);
     }
     else
     {
         Relocate(middle, middle.StartTime - overlap);
         Relocate(prior, middle.StartTime - firstTime - prior.Duration);
     }
     // Sanity Check
     if(post.EndTime > lateTimeBound)
     {
         throw new XTMFRuntimeException("We ended too late when inserting with 3 into a person schedule!\r\n"
             + Dump(this));
     }
     else if(prior.StartTime < earlyTimeBound)
     {
         throw new XTMFRuntimeException("We started too early when inserting with 3 into a person schedule!\r\n"
             + Dump(this)
             + "\r\nFirst Time = " + firstTime.ToString()
             + "\r\nSecond Time = " + secondTime.ToString());
     }
     return true;
 }
示例#42
0
 public override Time CheckOverlap(Episode episode)
 {
     throw new NotImplementedException();
 }
示例#43
0
 private void FixDurationToInsert(ref Time earlyTimeBound, Episode prior, Episode middle, Episode post, ref Time lateTimeBound, ref Time firstTime, ref Time secondTime)
 {
     var priorDuration = Time.Zero;
     var middleDuration = middle.Duration;
     var postDuration = Time.Zero;
     // If we get here then we need to calculate the ratios and then assign the start times accordingly
     if(prior != null)
     {
         var duration = prior.Duration;
         priorDuration = prior.Duration;
         prior.StartTime = earlyTimeBound;
         prior.EndTime = earlyTimeBound + duration;
     }
     if(post != null)
     {
         var duration = post.Duration;
         postDuration = post.Duration;
         post.EndTime = lateTimeBound;
         post.StartTime = lateTimeBound - duration;
     }
     Time totalOriginalDuration = (prior != null ? prior.OriginalDuration : Time.Zero)
         + middle.OriginalDuration
         + (post != null ? post.OriginalDuration : Time.Zero);
     Time minPrior = (prior != null ? Tasha.Scheduler.Scheduler.PercentOverlapAllowed * prior.OriginalDuration : Time.Zero);
     Time minMid = Tasha.Scheduler.Scheduler.PercentOverlapAllowed * middle.OriginalDuration;
     Time minPost = (post != null ? Tasha.Scheduler.Scheduler.PercentOverlapAllowed * post.OriginalDuration : Time.Zero);
     Time remainder = (lateTimeBound - earlyTimeBound) - (minPrior + minMid + minPost + firstTime + secondTime);
     float ratioPrior = 0;
     float ratioMiddle = 0;
     if(prior != null)
     {
         ratioPrior = prior.OriginalDuration / totalOriginalDuration;
         prior.StartTime = earlyTimeBound;
         prior.EndTime = prior.StartTime + minPrior + (ratioPrior * remainder);
         middle.StartTime = prior.EndTime + firstTime;
     }
     else
     {
         middle.StartTime = earlyTimeBound + firstTime;
     }
     ratioMiddle = middle.OriginalDuration / totalOriginalDuration;
     middle.EndTime = middle.StartTime + minMid + (ratioMiddle * remainder);
     if(post != null)
     {
         // we do not need to include the ratio calculation for post since we know it needs to end at the end of the allowed time
         // and that it needs to start right after the middle
         var ratioPost = post.OriginalDuration / totalOriginalDuration;
         post.StartTime = middle.EndTime + secondTime;
         post.EndTime = lateTimeBound;
     }
 }
示例#44
0
        private void FixDurationToInsert(ref Time earlyTimeBound, Episode prior, Episode middle, Episode post, ref Time lateTimeBound, ref Time firstTime, ref Time secondTime)
        {
            var priorDuration  = Time.Zero;
            var middleDuration = middle.Duration;
            var postDuration   = Time.Zero;

            // If we get here then we need to calculate the ratios and then assign the start times accordingly
            if (prior != null)
            {
                var duration = prior.Duration;
                priorDuration   = prior.Duration;
                prior.StartTime = earlyTimeBound;
                prior.EndTime   = earlyTimeBound + duration;
            }
            if (post != null)
            {
                var duration = post.Duration;
                postDuration   = post.Duration;
                post.EndTime   = lateTimeBound;
                post.StartTime = lateTimeBound - duration;
            }
            Time totalOriginalDuration = (prior != null ? prior.OriginalDuration : Time.Zero)
                                         + middle.OriginalDuration
                                         + (post != null ? post.OriginalDuration : Time.Zero);
            Time  minPrior    = (prior != null ? Tasha.Scheduler.Scheduler.PercentOverlapAllowed * prior.OriginalDuration : Time.Zero);
            Time  minMid      = Tasha.Scheduler.Scheduler.PercentOverlapAllowed * middle.OriginalDuration;
            Time  minPost     = (post != null ? Tasha.Scheduler.Scheduler.PercentOverlapAllowed * post.OriginalDuration : Time.Zero);
            Time  remainder   = (lateTimeBound - earlyTimeBound) - (minPrior + minMid + minPost + firstTime + secondTime);
            float ratioPrior  = 0;
            float ratioMiddle = 0;

            if (prior != null)
            {
                ratioPrior       = prior.OriginalDuration / totalOriginalDuration;
                prior.StartTime  = earlyTimeBound;
                prior.EndTime    = prior.StartTime + minPrior + (ratioPrior * remainder);
                middle.StartTime = prior.EndTime + firstTime;
            }
            else
            {
                middle.StartTime = earlyTimeBound + firstTime;
            }
            ratioMiddle    = middle.OriginalDuration / totalOriginalDuration;
            middle.EndTime = middle.StartTime + minMid + (ratioMiddle * remainder);
            if (post != null)
            {
                // we do not need to include the ratio calculation for post since we know it needs to end at the end of the allowed time
                // and that it needs to start right after the middle
                var ratioPost = post.OriginalDuration / totalOriginalDuration;
                post.StartTime = middle.EndTime + secondTime;
                post.EndTime   = lateTimeBound;
            }
        }
示例#45
0
 private bool Insert(Time earlyTimeBound, Episode prior, Episode middle, Episode post, Time lateTimeBound)
 {
     if(earlyTimeBound < Time.StartOfDay)
     {
         throw new XTMFRuntimeException("An episode had an early time bound before the start of the day!");
     }
     if(lateTimeBound > Time.EndOfDay)
     {
         throw new XTMFRuntimeException("An episode had a late time before after the end of the day!");
     }
     Time firstTime = Time.Zero;
     Time secondTime = Time.Zero;
     var priorDuration = Time.Zero;
     var middleDuration = middle.OriginalDuration;
     var postDuration = Time.Zero;
     // Do a quick check to see if it is even possible to fit everything in together
     if(!InitialInsertCheckPossible(earlyTimeBound, prior, middle, post, lateTimeBound, ref firstTime, ref secondTime))
     {
         return false;
     }
     if(firstTime < Time.Zero)
     {
         throw new XTMFRuntimeException("The First time in an insert is negative! " + firstTime.ToString() + ".  Going from " + prior.Zone.ZoneNumber.ToString() + " to " + middle.Zone.ZoneNumber.ToString() + " at " + middle.StartTime.ToString() + "!");
     }
     if(secondTime < Time.Zero)
     {
         throw new XTMFRuntimeException("The Second time in an insert is negative! " + secondTime.ToString() + ".  Going from " + middle.Zone.ZoneNumber.ToString() + " to "
             + (post == null ? Owner.Household.HomeZone.ZoneNumber : post.Zone.ZoneNumber).ToString() + " at " + (post == null ? middle.EndTime : post.StartTime).ToString() + "!");
     }
     // Assign the travel times to the episodes
     if(prior == null)
     {
         FirstTripTime = firstTime;
     }
     else
     {
         prior.TravelTime = firstTime;
         priorDuration = prior.OriginalDuration;
     }
     if(post != null)
     {
         postDuration = post.OriginalDuration;
     }
     middle.TravelTime = secondTime;
     // if we get here we know that there is a way to insert the episodes successfully
     if(UnableToJustMoveToInsert(earlyTimeBound, prior, middle, post, lateTimeBound, ref firstTime, ref secondTime))
     {
         FixDurationToInsert(ref earlyTimeBound, prior, middle, post, ref lateTimeBound, ref firstTime, ref secondTime);
     }
     else
     {
         var ret = ShiftToInsert(ref earlyTimeBound, prior, middle, post, ref lateTimeBound, ref firstTime, ref secondTime);
         return ret;
     }
     return true;
 }
示例#46
0
        /// <summary>
        /// Run a quick check to see if it is at all possible to place all of the 3 episodes in the given time bounds
        /// </summary>
        /// <param name="earlyTimeBound">The earliest point</param>
        /// <param name="prior">the first episode in the batch (possibly null if there is no episode prior)</param>
        /// <param name="middle">the second episode in the batch</param>
        /// <param name="post">the last episode in the batch (possibly null if there is no episode post)</param>
        /// <param name="lateTimeBound">the latest point</param>
        /// <returns>If we can fit them all in properly</returns>
        private bool InitialInsertCheckPossible(Time earlyTimeBound, Episode prior, Episode middle, Episode post, Time lateTimeBound,
                                                ref Time travelFirst,
                                                ref Time travelSecond
                                                )
        {
            Time minPrior = Time.Zero;
            Time minMid   = Tasha.Scheduler.Scheduler.PercentOverlapAllowed * middle.OriginalDuration;
            Time minPost  = Time.Zero;

            if (prior != null)
            {
                minPrior    = Tasha.Scheduler.Scheduler.PercentOverlapAllowed * prior.OriginalDuration;
                travelFirst = Scheduler.TravelTime(Owner, prior.Zone, middle.Zone, prior.EndTime);
            }
            else
            {
                travelFirst = Scheduler.TravelTime(Owner, Owner.Household.HomeZone, middle.Zone, middle.StartTime);
            }
            if (post != null)
            {
                minPost      = Tasha.Scheduler.Scheduler.PercentOverlapAllowed * post.OriginalDuration;
                travelSecond = Scheduler.TravelTime(Owner, middle.Zone, post.Zone, middle.EndTime);
            }
            else
            {
                travelSecond = Scheduler.TravelTime(Owner, middle.Zone, Owner.Household.HomeZone, middle.EndTime);
            }
            // it is possible to fit in if the bounds are larger than the minimum size of all three episodes
            return((lateTimeBound - earlyTimeBound) >= (minPrior + minMid + minPost + travelFirst + travelSecond));
        }
示例#47
0
 private bool UnableToJustMoveToInsert(Time earlyTimeBound, Episode prior, Episode middle, Episode post, Time lateTimeBound,
     ref Time travelFirst,
     ref Time travelSecond)
 {
     // if the amount of time that we have to work with is larger then we are unable to just move to insert
     var totalTime = (prior != null ? prior.Duration : Time.Zero)
         + middle.Duration
         + (post != null ? post.Duration : Time.Zero)
         + travelFirst + travelSecond;
     var boundTime = (lateTimeBound - earlyTimeBound);
     return boundTime
         <= totalTime;
 }
示例#48
0
 public override bool ForcedEpisodeInsert(Episode ep)
 {
     throw new NotImplementedException();
 }
示例#49
0
 public override bool ForcedEpisodeInsert(Episode ep)
 {
     throw new NotImplementedException();
 }
示例#50
0
 private bool ShiftToInsert(ref Time earlyTimeBound, Episode prior, Episode middle, Episode post, ref Time lateTimeBound, ref Time firstTime, ref Time secondTime)
 {
     if (prior != null & post != null)
     {
         return(AllThreeInsert(ref earlyTimeBound, prior, middle, post, ref lateTimeBound, ref firstTime, ref secondTime));
     }
     else if (prior != null)
     {
         return(PriorMiddleInsert(ref earlyTimeBound, prior, middle, ref lateTimeBound, ref firstTime, ref secondTime));
     }
     else if (post != null)
     {
         return(MiddlePostInsert(ref earlyTimeBound, middle, post, ref lateTimeBound, ref firstTime, ref secondTime));
     }
     throw new XTMFRuntimeException("Unexpected shift to insert case!");
 }
示例#51
0
 private static bool AddHouseholdPass(Episode ep, ref TimeWindow feasible)
 {
     // Check to find the time that everyone is available at
     foreach ( var person in ep.People )
     {
         // if we are make sure we can go to the event
         var pdata = ( person["SData"] as SchedulerPersonData );
         if ( !pdata.Schedule.CheckEpisodeInsert( ep, ref feasible ) )
         {
             // if we can not fit it in reject it
             return false;
         }
     }
     return true;
 }
示例#52
0
文件: Schedule.cs 项目: Cocotus/XTMF
 /// <summary>
 /// Forces an episode to be inserted
 /// </summary>
 public abstract bool ForcedEpisodeInsert(Episode ep);