示例#1
0
        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);
        }
示例#2
0
        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;
            }
        }
示例#3
0
        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);
        }
示例#6
0
        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);
        }
示例#7
0
        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;
                    }
                }
            }
        }
示例#9
0
        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);
            }
        }