public void Report(TextWriter writer, Conductor conductor, Patron patron)
        {
            //TODO: also putting a cap on the minutes: 23:59? see example ...
            var earliestDepartureTimeMinutes
                = DepartureTimeMinutes
                  + conductor.GetStopIntervalsMinutes(patron).Sum();

            writer.WriteLine(earliestDepartureTimeMinutes.FormatMinutes());
        }
        /// <summary>
        /// Returns whether the <paramref name="trip"/> CanBeScheduled for the
        /// <paramref name="patron"/>, taking into consideration any <paramref name="deltas"/>
        /// incurred by boarding mid-line.
        /// </summary>
        /// <param name="trip"></param>
        /// <param name="patron"></param>
        /// <param name="deltas"></param>
        /// <returns></returns>
        public static bool CanBeScheduled(this Trip trip, Patron patron, GetStopIntervalsMinutesDelegate deltas)
        {
            // Deal with these couple of obvious criteria first.
            if (trip == null || trip.Direction != patron.Direction)
                return false;

            var totalDeltaMinutes = deltas(patron).Sum();

            /* Now we can deal with the next obvious condition. Do not normalize the Patron time
             * after all. Not only is this acceptable as-is, I truly don't believe there is a way
             * for us to know otherwise; unless we wanted to incorporate actual DateTime dates
             * into the mix. */

            return trip.DepartureTimeMinutes + totalDeltaMinutes >= patron.DepartureTimeMinutes;
        }
        private void ScheduleTrip(Patron patron)
        {
            Trip last;

            /* Backfill the schedule until the Patron's request can be fulfilled,
             * if at all possible given known set of constraints. */

            while ((last = _scheduledTrips
                .Where(t => t.IsNorthbound == patron.IsNorthbound)
                .OrderBy(t => t.DepartureTimeMinutes).LastOrDefault())
                .CannotBeScheduled(patron, GetStopIntervalsMinutes))
            {
                TripConstraint constraint;

                var nextDepartureTimeMinutes = GetNextDepartureTimeMinutes(last, patron, out constraint);

                // It is not possible to fulfill the Patron's itinerary given the allowable constraints.
                if (nextDepartureTimeMinutes == null) break;

                var trip = new Trip(constraint, nextDepartureTimeMinutes.Value);

                _scheduledTrips.Add(trip);
            }

            // Because Patron may have jumped into the queue midstream.
            patron.Itinerary = _scheduledTrips.First(
                t => t.CanBeScheduled(patron, GetStopIntervalsMinutes));
        }
        // ReSharper disable SuggestBaseTypeForParameter
        /// <summary>
        /// 
        /// </summary>
        /// <param name="trip"></param>
        /// <param name="patron"></param>
        /// <param name="constraint"></param>
        /// <returns></returns>
        /// <remarks>This was another impacted area where not only calculating the desired
        /// departure time, but also knowing about the associated constraint, was desirable.</remarks>
        private int? GetNextDepartureTimeMinutes(Trip trip, Patron patron, out TripConstraint constraint)
        {
            // Should work for both Northbound (true/false), inverse of which is Southbound.
            constraint = Constraints.Single(t => t.IsNorthbound == patron.IsNorthbound);

            if (trip == null)
                return constraint.FirstDepartureTimeMinutes;

            var dtm = trip.DepartureTimeMinutes;

            // Which closing the loop the refactor should be relatively painless after all.
            var result = dtm + constraint.Frequencies.GetWaitTimeMinutes(dtm);

            return result > constraint.MaxAllowableDepartureTimeMinutes
                ? (int?) null
                : result;
        }
 /// <summary>
 /// Returns a collection of stop intervals relevant from the <paramref name="patron"/>
 /// <see cref="Patron.StopNumber"/> in the appropriate <see cref="IDirectional.IsNorthbound"/>.
 /// This is a useful callback throughout the approach.
 /// </summary>
 /// <param name="patron"></param>
 /// <returns></returns>
 internal IEnumerable<int> GetStopIntervalsMinutes(Patron patron)
 {
     // No need to subtract one here just pass the StopNumber through in either case.
     return patron.IsNorthbound
         ? StopIntervalMinutes.Take(patron.StopNumber)
         : StopIntervalMinutes.Skip(patron.StopNumber);
 }
 /// <summary>
 /// Returns whether the <paramref name="trip"/> CannotBeScheduled for the
 /// <paramref name="patron"/>, taking into consideration any <paramref name="deltas"/>
 /// incurred by boarding mid-line.
 /// </summary>
 /// <param name="trip"></param>
 /// <param name="patron"></param>
 /// <param name="deltas"></param>
 /// <returns></returns>
 public static bool CannotBeScheduled(this Trip trip, Patron patron, GetStopIntervalsMinutesDelegate deltas)
 {
     return !trip.CanBeScheduled(patron, deltas);
 }
        public void Report(TextWriter writer, Conductor conductor, Patron patron)
        {
            var earliestDepartureTimeMinutes
                = DepartureTimeMinutes
                  + conductor.GetStopIntervalsMinutes(patron).Sum();

            writer.WriteLine(earliestDepartureTimeMinutes.FormatMinutes());
        }