public static UsageTimeInterval combine_b_end_follows_prev_end( List <UsageTimeInterval> A, List <decimal> APowers, int i, UsageTimeInterval uti_prev, decimal APowers_prev, UsageTimeInterval b, decimal bPower) { var uti_prev_start = uti_prev.TimeInterval.Start; var uti_prev_end = uti_prev.TimeInterval.End; var b_start = b.TimeInterval.Start; var b_end = b.TimeInterval.End; var uBefore = new UsageTimeInterval( new TimeInterval( uti_prev_start.Hours, uti_prev_start.Minutes, b_start.Hours, b_start.Minutes) ); A.Insert(i - 1, uBefore); A.RemoveAt(i); var uAfter = new UsageTimeInterval( new TimeInterval(b_start.Hours, b_start.Minutes, uti_prev_end.Hours, uti_prev_end.Minutes) ); A.Insert(i, uAfter); APowers.Insert(i, APowers_prev + bPower); //startup var b_trimmed = new UsageTimeInterval( new TimeInterval( uti_prev_end.Hours, uti_prev_end.Minutes, b_end.Hours, b_end.Minutes)); return(b_trimmed); }
private static void combine_b_within_prev( List <UsageTimeInterval> A, List <decimal> APowers, int i, UsageTimeInterval uti_prev, decimal APowers_prev, UsageTimeInterval b, decimal bPower) { var uti_prev_start = uti_prev.TimeInterval.Start; var uti_prev_end = uti_prev.TimeInterval.End; var b_start = b.TimeInterval.Start; var b_end = b.TimeInterval.End; var uBefore = new UsageTimeInterval( new TimeInterval( uti_prev_start.Hours, uti_prev_start.Minutes, b_start.Hours, b_start.Minutes) ); A.Insert(i - 1, uBefore); A.RemoveAt(i); if (b_end < uti_prev_end) { A.Insert(i, b); APowers.Insert(i, APowers_prev + bPower); //startup var uAfter = new UsageTimeInterval( new TimeInterval(b_end.Hours, b_end.Minutes, uti_prev_end.Hours, uti_prev_end.Minutes)); A.Insert(i + 1, uAfter); APowers.Insert(i + 1, APowers_prev); return; } }
public static UsageTimeInterval combine_b_start_precedes_curr_start( List <UsageTimeInterval> A, List <decimal> APowers, int i, UsageTimeInterval uti_curr, UsageTimeInterval b, decimal bPower) { var uti_curr_start = uti_curr.TimeInterval.Start; var uti_curr_end = uti_curr.TimeInterval.End; var b_start = b.TimeInterval.Start; var b_end = b.TimeInterval.End; APowers.Insert(i, bPower); //startup if (b_end <= uti_curr_start) { A.Insert(i, b); return(null); } // else (b_end > uti_curr_start) var uBefore = new UsageTimeInterval( new TimeInterval( b_start.Hours, b_start.Minutes, uti_curr_start.Hours, uti_curr_start.Minutes)); A.Insert(i, uBefore); var b_trimmed = new UsageTimeInterval( new TimeInterval( uti_curr_start.Hours, uti_curr_start.Minutes, b_end.Hours, b_end.Minutes)); return(b_trimmed); }
void ShouldDefaultToUsingSolarKind() { var ti = new TimeInterval(1, 0, 2, 0); var tiwk = new UsageTimeInterval(ti); Assert.Equal(UsageKind.UsingSolar, tiwk.UsageKind); }
protected override void _AddUsageInterval( int startHr, int startMin, int endHr, int endMin, UsageKind usageKind ) { var ti = new TimeInterval(startHr, startMin, endHr, endMin); // If we're trying to add a UsageInterval that's UsingSolar if (usageKind == UsageKind.UsingSolar) { // but it starts before the PeakSolarInterval start // or ends after the PeakSolarInterval end if (ti.Start < ReadOnlySiteSettings.PeakSolarInterval.Start || ti.End > ReadOnlySiteSettings.PeakSolarInterval.End) { // bad throw new TimeIntervalArgumentInvalidException("When adding a UsageTimeInterval that is UsingSolar, the start/end cannot be before/after the Site's PeakSolarInterval start/end, respectively."); } } var newUTI = new UsageTimeInterval(ti, usageKind); for (int i = 0; i < _usageIntervals.Count; ++i) { var currTI = _usageIntervals[i].TimeInterval; // So now we know that either // * We have a UsingSolar interval but it's within the // PeakSolarInterval, or // * We have an arbitrarily shaped Non-UsingSolar interval // If our new time interval starts before the current interval, if (ti.Start < currTI.Start) { // and it also ends before the current interval if (ti.End <= currTI.Start) { // Just insert it and return _usageIntervals.Insert(i, newUTI); return; } else // it ends after the current interval { throw new TimeIntervalArgumentInvalidException("It is not possible to add a new UsageTimeInterval that overlaps with an existing UsageTimeInterval."); } } // Else if our new time intervals starts in the middle of an // existing interval else if (ti.Start < currTI.End) { // bad throw new TimeIntervalArgumentInvalidException("It is not possible to add a new UsageTimeInterval that overlaps with an existing UsageTimeInterval."); } } // If we're here then we're past all the intervals. So OK to Add. _usageIntervals.Add(newUTI); }
public void ShouldAddUsageIntervalToNonEmpty( int peakStartHr, int peakStartMin, int peakEndHr, int peakEndMin, List <UsageTimeInterval> usageIntervals, UsageTimeInterval uTI, int expIdx) { var aus = new ApplianceUsageSchedule( new MockReadOnlySiteSettings( peakStartHr, peakStartMin, peakEndHr, peakEndMin ) ); foreach (var u in usageIntervals) { var t = u.TimeInterval; aus.AddUsageInterval( t.Start.Hours, t.Start.Minutes, t.End.Hours, t.End.Minutes, u.UsageKind); } var ti = uTI.TimeInterval; int startHr = ti.Start.Hours, startMin = ti.Start.Minutes; int endHr = ti.End.Hours, endMin = ti.End.Minutes; aus.AddUsageInterval(startHr, startMin, endHr, endMin, uTI.UsageKind); // Check that list has grown by one Assert.Equal(usageIntervals.Count + 1, aus.UsageIntervals.Count); // Find added element int uTI_Idx = 0; var addedUTIs = aus.UsageIntervals.Where((u, id) => { if (u.Equals(uTI)) { uTI_Idx = id; return(true); } return(false); }); // Check that added element is uTI Assert.Single(addedUTIs); // Check that uTI is added at expected idx Assert.Equal(expIdx, uTI_Idx); }
public void ShouldThrowForOverlappingInterval( int peakStartHr, int peakStartMin, int peakEndHr, int peakEndMin, List <UsageTimeInterval> usageIntervals, UsageTimeInterval uTI) { var aus = new ApplianceUsageSchedule( new MockReadOnlySiteSettings( peakStartHr, peakStartMin, peakEndHr, peakEndMin ) ); foreach (var u in usageIntervals) { var ti = u.TimeInterval; aus.AddUsageInterval( ti.Start.Hours, ti.Start.Minutes, ti.End.Hours, ti.End.Minutes, u.UsageKind); } Assert.Throws <TimeIntervalArgumentInvalidException>(() => { var ti = uTI.TimeInterval; aus.AddUsageInterval( ti.Start.Hours, ti.Start.Minutes, ti.End.Hours, ti.End.Minutes, uTI.UsageKind); }); }
protected override void _HandlePeakSolarIntervalUpdated() { var ti = ReadOnlySiteSettings.PeakSolarInterval; int startHr = ti.Start.Hours, startMin = ti.Start.Minutes; int endHr = ti.End.Hours, endMin = ti.End.Minutes; bool lowerDone = false; bool upperDone = false; for (int i = 0; i < _usageIntervals.Count; ++i) { var uTI = _usageIntervals[i].TimeInterval; var usage = _usageIntervals[i].UsageKind; // Ensure we're just dealing with solar usage intervals. if (usage != UsageKind.UsingSolar) { continue; } // If we have a solar usage interval that is completely outside // the new peak solar interval, then convert it to mains usage. if (uTI.End < ti.Start || uTI.Start > ti.End) { var newTI = new TimeInterval( uTI.Start.Hours, uTI.Start.Minutes, uTI.End.Hours, uTI.End.Minutes); _usageIntervals[i] = new UsageTimeInterval(newTI, UsageKind.UsingMains); continue; } // If we haven't trimmed the lower bound yet .. if (!lowerDone) { // .. and we have a solar usage interval starting before // the start of the peak solar interval if (uTI.Start < ti.Start) { // we gottu trim it! var newTI = new TimeInterval( startHr, startMin, uTI.End.Hours, uTI.End.Minutes ); _usageIntervals[i] = new UsageTimeInterval(newTI); // Make sure to update uTI in case the same interval is // also a candidate for upper bound trimming. uTI = newTI; // since we're storing intervals in temporal order, // we won't need to do this again. lowerDone = true; } } // If we haven't trimmed the upper bound yet .. if (!upperDone) { // .. and we have a solar usage interval starting after // the end of the peak solar interval if (uTI.End > ti.End) { // we gottu trim it! var newTI = new TimeInterval( uTI.Start.Hours, uTI.Start.Minutes, endHr, endMin ); _usageIntervals[i] = new UsageTimeInterval(newTI); // since we're storing intervals in temporal order, // we won't need to do this again. upperDone = true; } } } }
private static void CombineSolarIntervals( List <UsageTimeInterval> A, List <decimal> APowers, UsageTimeInterval b, decimal bPower, int startIdx = 0) { if (b.TimeInterval.Start == b.TimeInterval.End) { return; } if (A.Count == 0) { A.Add(b); APowers.Add(bPower); return; } // Assume A.length == APowers.length // Assume all UsageTimeIntervals in A, and b, are UsingSolars var b_start = b.TimeInterval.Start; var b_end = b.TimeInterval.End; var b_diff = b.TimeInterval.Difference; for (int i = startIdx; i < A.Count; ++i) { var uti_curr = A[i]; var uti_curr_start = uti_curr.TimeInterval.Start; var uti_curr_end = uti_curr.TimeInterval.End; var uti_curr_diff = uti_curr.TimeInterval.Difference; var APowers_curr = APowers[i]; if (b_start < uti_curr_start) { if (i > 0) { var uti_prev = A[i - 1]; var uti_prev_start = uti_prev.TimeInterval.Start; var uti_prev_end = uti_prev.TimeInterval.End; var APowers_prev = APowers[i - 1]; if (b_start < uti_prev_end) { if (b_end < uti_prev_end) { combine_b_within_prev(A, APowers, i, uti_prev, APowers_prev, b, bPower); return; } else { var b_trimmed = combine_b_end_follows_prev_end( A, APowers, i, uti_prev, APowers_prev, b, bPower); CombineSolarIntervals(A, APowers, b_trimmed, bPower, i); return; } } // else (b_start >= uti_prev_end) { var b_trimmed = combine_b_start_precedes_curr_start( A, APowers, i, uti_curr, b, bPower); if (b_trimmed != null) { CombineSolarIntervals(A, APowers, b_trimmed, bPower, i); } return; } } else // i==0 { var b_trimmed = combine_b_start_precedes_curr_start( A, APowers, 0, uti_curr, b, bPower); if (b_trimmed != null) { CombineSolarIntervals(A, APowers, b_trimmed, bPower); } return; } } else if (b_start == uti_curr_start) { APowers[i] += bPower; //startup if (b_end > uti_curr_end) { var b_trimmed = new UsageTimeInterval( new TimeInterval( uti_curr_end.Hours, uti_curr_end.Minutes, b_end.Hours, b_end.Minutes)); CombineSolarIntervals(A, APowers, b_trimmed, bPower, i); return; } else if (b_end < uti_curr_end) { A.Insert(i, b); A.RemoveAt(i + 1); A.Insert(i + 1, new UsageTimeInterval( new TimeInterval(b_end.Hours, b_end.Minutes, uti_curr_end.Hours, uti_curr_end.Minutes) )); APowers.Insert(i + 1, APowers_curr); return; } else { return; } } } //end for var lenA = A.Count; var uti_last = A.Last(); var uti_last_start = uti_last.TimeInterval.Start; var uti_last_end = uti_last.TimeInterval.End; var APowers_last = APowers[lenA - 1]; if (b_start < uti_last_end) { if (b_end < uti_last_end) { combine_b_within_prev(A, APowers, lenA, uti_last, APowers_last, b, bPower); return; } else { var b_trimmed = combine_b_end_follows_prev_end( A, APowers, lenA, uti_last, APowers_last, b, bPower); A.Add(b_trimmed); APowers.Add(bPower); return; } } else { A.Add(b); APowers.Add(bPower); } }