private ApplicableMinAndMax GetMinAndMaxHoursForVisitStartingAt(DateTime startTime) { double min = Double.MinValue; double max = Double.MaxValue; //Check to see what is already filled double minHoursUnfilled = Double.MaxValue; Console.Out.WriteLine(" Applicable Buckets: "); foreach (SwimTimeRuleBucket ctrb in ruleBucketTree) { if (RuleAppliesToThisVisit(startTime, ctrb)) { ApplicableMinAndMax temp2 = ctrb.GetMinAndMaxHoursForVisitStartingAt(startTime); Console.Out.WriteLine(" " + temp2); if (temp2 != null) { min = Math.Max(min, temp2.GetMinimumVisitLengthInHoursThatCounts()); max = Math.Min(max, temp2.GetMaximumHoursAllowedInThisTimePeriod()); } Console.Out.WriteLine(" " + ctrb); double hoursUnfilled = ctrb.GetHowManyHoursUnfilled(); //hoursUnfilled = Math.Max(0.0, hoursUnfilled); Console.Out.WriteLine(" Hours unfilled: " + hoursUnfilled); minHoursUnfilled = Math.Min(minHoursUnfilled, hoursUnfilled); Console.Out.WriteLine(" Min Hours unfilled: " + minHoursUnfilled); } }//end foreach max = Math.Min(max, minHoursUnfilled); return(new ApplicableMinAndMax(min, max)); }
public WINTER_2012_SwimTimeRuleProcessor(IList <ISwimTimeRule> theRules) { if (theRules == null) { throw new ArgumentException("Cannot have a null list of rules"); } this.ruleBucketTree = new List <SwimTimeRuleBucket>(); IList <ISwimTimeRule> rulesDecomposedIntoDiscreteTimePeriods = new List <ISwimTimeRule>(); foreach (ISwimTimeRule aRule in theRules) { if (Math.Sqrt(aRule.GetRuleRepeatabilityPeriodInHours() * aRule.GetRuleRepeatabilityPeriodInHours()) <= 1.0 / 60.0)//Rules less than 1 minute in repeatability are considered constant rules { rulesDecomposedIntoDiscreteTimePeriods.Add(aRule); } else//repeated rule, so explcitly make it a concrete one { DateTime startDate;//When the rule starts DateTime endDate; //When the rule ends DateTime repDate; //The "zero" date; the repition period "hops" forwards from this date. double repPeriod; ISwimTimeRule temp; ApplicableMinAndMax ruleMinAndMax = aRule.GetMinAndMaxHours(); startDate = aRule.GetAbsoluteStartingDate(); endDate = aRule.GetAbsoluteEndingDate(); repDate = aRule.GetRuleStartDate(); repPeriod = aRule.GetRuleRepeatabilityPeriodInHours(); DateTime hopDate = repDate; while (hopDate < startDate)//The hop date could be "funky"; move it forward until it is inside the time period we care about. { hopDate = hopDate.Add(TimeSpan.FromHours(repPeriod)); } DateTime currentConcreteRuleStartDate = startDate; DateTime currentConcreteRuleEndDate = (hopDate < endDate) ? hopDate : endDate; while (currentConcreteRuleStartDate < endDate) { temp = SwimTimeRuleFactory.CreateSwimTimeRule(ruleMinAndMax.GetMinimumVisitLengthInHoursThatCounts(), ruleMinAndMax.GetMaximumHoursAllowedInThisTimePeriod(), currentConcreteRuleStartDate, currentConcreteRuleEndDate); rulesDecomposedIntoDiscreteTimePeriods.Add(temp); //Now move forward one repition period currentConcreteRuleStartDate = currentConcreteRuleEndDate; hopDate = hopDate.Add(TimeSpan.FromHours(repPeriod)); currentConcreteRuleEndDate = (hopDate < endDate) ? hopDate : endDate; } } } SwimTimeRuleBucket tempBucket; foreach (ISwimTimeRule decoRules in rulesDecomposedIntoDiscreteTimePeriods) { tempBucket = new SwimTimeRuleBucket(decoRules); ruleBucketTree.Add(tempBucket); } }
public SwimTimeRuleProcessingInformation ProcessMultipleVisits(IList <SwimTimeVisit> validAndInvalidVisits) { if (validAndInvalidVisits == null) { throw new ArgumentException("Cannot handle a null list of visits"); } if (this.ruleBucketTree.Count == 0) { string tempReason = "No rules"; if (validAndInvalidVisits.Count == 0) { tempReason += " or visits"; } tempReason += "."; return(new SwimTimeRuleProcessingInformation(0.0, 0.0, tempReason)); } IList <SwimTimeVisit> validVisitsOnly = new List <SwimTimeVisit>(); //Strip out invalid visits foreach (var aVisit in validAndInvalidVisits) { if (aVisit.GetWasAValidCheckout()) { validVisitsOnly.Add(aVisit); } } validVisitsOnly = OrderValidVisitsAscendingByStartDate(validVisitsOnly); double validTime = 0.0; double invalidTime = 0.0; double actualTimeAdded; ZeroOutRuleBucketTree();//Even though it was probably cleared before, make sure it is cleared now before using it. Console.Out.WriteLine("The entire bucket tree:"); Console.Out.WriteLine("-------------------------------------"); PrintOutRuleBucketTree(false); Console.Out.WriteLine("-------------------------------------"); Console.Out.WriteLine(); Console.Out.WriteLine(); Console.Out.WriteLine("Processing visits"); Console.Out.WriteLine("-------------------------------------"); foreach (var aVisit in validVisitsOnly) { ApplicableMinAndMax applicableMinAndMax = GetMinAndMaxHoursForVisitStartingAt(aVisit.GetStartDateTime()); Console.Out.WriteLine(); Console.Out.WriteLine("Visit: " + aVisit); Console.Out.WriteLine("Applicable min and max: " + applicableMinAndMax); if (aVisit.GetWasAValidCheckout() && VisitStartedWithinARulePeriod(aVisit)) { double visitElapsedTime = aVisit.GetElapsedTime(); if (visitElapsedTime >= applicableMinAndMax.GetMinimumVisitLengthInHoursThatCounts()) { actualTimeAdded = Math.Min(visitElapsedTime, applicableMinAndMax.GetMaximumHoursAllowedInThisTimePeriod()); validTime += actualTimeAdded; invalidTime += visitElapsedTime - actualTimeAdded; FillRuleBucketTree(actualTimeAdded, aVisit.GetStartDateTime()); PrintOutRuleBucketTree(true); } } }//end visit Console.Out.WriteLine("-------------------------------------"); Console.Out.WriteLine("END Processing visits"); ZeroOutRuleBucketTree();//Cleans up the tree for reuse next time. return(new SwimTimeRuleProcessingInformation(validTime, invalidTime, "")); }