예제 #1
0
        public Tvqs()
        {
            var t = new DateTime(2015, 01, 01, 0, 0, 0, 0);

            Tvq20150101 = new Tvq(t, 100, Quality.Ok);
            t           = new DateTime(2015, 01, 05, 0, 0, 0, 0);
            Tvq20150105 = new Tvq(t, 105, Quality.Ok);
            t           = new DateTime(2015, 01, 10, 0, 0, 0, 0);
            Tvq20150110 = new Tvq(t, 105, Quality.Ok);
            t           = new DateTime(2015, 01, 31, 23, 59, 59);
            Tvq20150131 = new Tvq(t, 105, Quality.Ok);
            t           = new DateTime(2015, 03, 01, 0, 0, 0, 0);
            Tvq20150301 = new Tvq(t, 110, Quality.Ok);
            t           = new DateTime(2015, 06, 01, 0, 0, 0, 0);
            Tvq20150601 = new Tvq(t, 200, Quality.Ok);
            t           = new DateTime(2015, 06, 22, 0, 0, 0, 0);
            Tvq20150622 = new Tvq(t, 222, Quality.Ok);
            t           = new DateTime(2015, 06, 30, 23, 59, 59);
            Tvq20150630 = new Tvq(t, 230, Quality.Ok);
            t           = new DateTime(2015, 07, 01, 0, 0, 0, 0);
            Tvq20150701 = new Tvq(t, 300, Quality.Ok);
            t           = new DateTime(2015, 12, 1, 0, 0, 0);
            Tvq20151201 = new Tvq(t, 310, Quality.Ok);
            t           = new DateTime(2015, 12, 31, 23, 59, 59);
            Tvq20151231 = new Tvq(t, 399, Quality.Ok);
            t           = new DateTime(2016, 01, 01, 0, 0, 0, 0);
            Tvq20160101 = new Tvq(t, 400, Quality.Ok);
            t           = new DateTime(2016, 02, 01, 0, 0, 0, 0);
            Tvq20160201 = new Tvq(t, 410, Quality.Ok);
            t           = new DateTime(2016, 06, 01, 0, 0, 0, 0);
            Tvq20160601 = new Tvq(t, 500, Quality.Ok);
            t           = new DateTime(2017, 06, 01, 0, 0, 0, 0);
            Tvq20170601 = new Tvq(t, 500, Quality.Ok);
        }
예제 #2
0
        /// <summary>
        /// Splits a timeseries into possibly several with one timeseries per year.
        /// </summary>
        /// <param name="timeseries"></param>
        /// <returns></returns>
        public IList <Timeseries> SplitPerYear(Timeseries timeseries)
        {
            if (!timeseries.Any())
            {
                return(new List <Timeseries>());
            }

            var        result    = new List <Timeseries>();
            Tvq        previous  = null;
            Timeseries currentTs = null;

            foreach (var tvq in timeseries)
            {
                if (previous == null)
                {
                    currentTs = new Timeseries {
                        tvq
                    };
                    result.Add(currentTs);
                }
                else
                {
                    if (previous.Time.Year != tvq.Time.Year)
                    {
                        currentTs = new Timeseries();
                        result.Add(currentTs);
                    }
                    currentTs.Add(tvq);
                }
                previous = tvq;
            }

            return(result);
        }
예제 #3
0
        public void Apply_WhenSecondIsInterpolated_ResultIsInterpolated()
        {
            var interpolated = new Tvq(m_t0, 0, Quality.Interpolated);
            var result       = m_Delta.Apply(m_Tvq5, interpolated);

            Assert.Equal(Quality.Interpolated, result.Q);
        }
예제 #4
0
        public void Apply_WhenFirstValueIsInsidePeriod_AssumesStepwise()
        {
            // Arrange
            var tvq1 = new Tvq(
                new DateTime(2015, 01, 10, 0, 0, 0, 0),
                110,
                Quality.Ok);
            var tvq2 = new Tvq(
                new DateTime(2015, 01, 20, 0, 0, 0, 0),
                120,
                Quality.Ok);
            var ts = new Timeseries {
                tvq1, tvq2
            };

            // Act
            var t0     = new DateTime(2015, 01, 01, 0, 0, 0, 0);
            var t1     = new DateTime(2015, 01, 31, 23, 59, 59, 999);
            var result = new Average().Apply(t0, t1, ts);

            // Assert
            var area1    = tvq1.V * (tvq1.Time - t0).TotalSeconds;
            var area2    = (tvq2.Time - tvq1.Time).TotalSeconds * (tvq1.V + tvq2.V) / 2;
            var area3    = (t1 - tvq2.Time).TotalSeconds * tvq2.V;
            var expected = (area1 + area2 + area3) / (t1 - t0).TotalSeconds;

            Assert.Equal(expected, result.V);
        }
예제 #5
0
        public void Apply_WhenSecondIsSuspect_ResultIsSuspect()
        {
            var suspect = new Tvq(m_t0, 0, Quality.Suspect);
            var result  = m_Delta.Apply(m_Tvq5, suspect);

            Assert.Equal(Quality.Suspect, result.Q);
        }
예제 #6
0
        public TvqEntity(string partitionKey, Tvq tvq)
        {
            PartitionKey = partitionKey;
            RowKey       = tvq.Time.Ticks.ToString();

            V = tvq.V;
            Q = tvq.Q;
        }
예제 #7
0
        public DeltaTsOperatorTest()
        {
            m_Delta = new DeltaTsOperator();
            m_t0    = new DateTime(2015, 01, 01, 0, 0, 0, 0);
            m_t1    = new DateTime(2015, 02, 01, 0, 0, 0, 0);
            m_t2    = new DateTime(2015, 02, 02, 0, 0, 0, 0);

            m_Tvq5  = new Tvq(m_t0, 5, Quality.Ok);
            m_Tvq7  = new Tvq(m_t1, 7, Quality.Ok);
            m_Tvq11 = new Tvq(m_t2, 11, Quality.Ok);
        }
예제 #8
0
        public DeltaTvqOperatorTest()
        {
            m_Delta = new DeltaTvqOperator();

            m_t0 = new DateTime(2015, 01, 01, 0, 0, 0, 0);
            m_t1 = new DateTime(2015, 02, 01, 0, 0, 0, 0);

            m_Tvq0      = new Tvq(m_t0, 0, Quality.Ok);
            m_Tvq6k     = new Tvq(m_t0, 611000, Quality.Ok);
            m_Tvq999991 = new Tvq(m_t0, 999991, Quality.Ok);
            m_Tvq5      = new Tvq(m_t0, 5, Quality.Ok);
            m_Tvq7      = new Tvq(m_t1, 7, Quality.Ok);
            m_Tvq11     = new Tvq(m_t1, 11, Quality.Ok);
            m_Tvq999981 = new Tvq(m_t1, 999981, Quality.Ok);
        }
예제 #9
0
        public void AddRegistryEntry(Tvq tvq)
        {
            // Create the table client.
            var tableClient = m_StorageAccount.CreateCloudTableClient();

            // Create the table if it doesn't exist.
            var table = tableClient.GetTableReference("registryentries");

            table.CreateIfNotExists();

            var tvqEntity       = new TvqEntity(m_PartitionKey, tvq);
            var insertOperation = TableOperation.Insert(tvqEntity);

            // Execute the insert operation.
            table.Execute(insertOperation);
        }
예제 #10
0
        public void Apply_WhenPeriodStartIs10AndEndIs20_ResultIs15()
        {
            // Arrange
            var t0   = new DateTime(2015, 01, 01, 0, 0, 0, 0);
            var t1   = new DateTime(2015, 02, 01, 0, 0, 0, 0);
            var tvq1 = new Tvq(t0, 10, Quality.Ok);
            var tvq2 = new Tvq(t1, 20, Quality.Ok);
            var ts   = new Timeseries {
                tvq1, tvq2
            };

            // Act
            var result = new Average().Apply(t0, t1, ts);

            // Assert
            Assert.Equal(15, result.V);
        }
예제 #11
0
        public void Apply_WhenConstant10_ResultIs10()
        {
            // Arrange
            var t0   = new DateTime(2015, 01, 01, 0, 0, 0, 0);
            var t1   = new DateTime(2015, 02, 01, 0, 0, 0, 0);
            var tvq1 = new Tvq(t0, 10, Quality.Ok);
            var tvq2 = new Tvq(t1, 10, Quality.Ok);
            var ts   = new Timeseries {
                tvq1, tvq2
            };

            // Act
            var result = new Average().Apply(t0, t1, ts);

            // Assert
            Assert.Equal(10, result.V);
        }
예제 #12
0
        public ActionResult SubmitRegisterEntry(RegisterEntryModel model)
        {
            bool     ok;
            DateTime t;
            int      v;

            ok = DateTime.TryParse(model.DateString, out t);
            if (!ok)
            {
                ViewBag.Title    = "Fel vid registrering";
                ViewBag.SubTitle = "Datum kunde ej tolkas";
                return(View(model));
            } // TODO better error handling

            ok = int.TryParse(model.RegisterValue, out v);
            if (!ok)
            {
                ViewBag.Title    = "Fel vid registrering";
                ViewBag.SubTitle = "Mätarställning kunde ej tolkas";
                return(View(model));
            } // TODO better error handling

            var now     = DateTime.Now;
            var isToday =
                t.Year == now.Year &&
                t.Month == now.Month &&
                t.Day == now.Day;

            if (isToday)
            {
                t = now;
            }

            var tvq = new Tvq(t, v, Quality.Ok);

            var repo = GetRegistryEntryRepo();

            repo.AddRegistryEntry(tvq);

            ViewBag.Title    = "Mätarställning registrerad";
            ViewBag.SubTitle = "Mätarställningen blev registrerad";
            return(View(model));
        }
예제 #13
0
        public Task <AddRegistryEntryResult> Handle(AddRegistryEntryCommand request, CancellationToken cancellationToken)
        {
            DateTime t;
            var      ok = DateTime.TryParse(request.Model.DateString, out t);

            if (!ok)
            {
                return(Task.FromResult(new AddRegistryEntryResult(false, "Datum kunde ej tolkas")));
            } // TODO better error handling

            int v;

            ok = int.TryParse(request.Model.RegisterValue, out v);
            if (!ok)
            {
                return(Task.FromResult(new AddRegistryEntryResult(false, "Mätarställning kunde ej tolkas")));
            } // TODO better error handling

            var now     = DateTime.Now;
            var isToday =
                t.Year == now.Year &&
                t.Month == now.Month &&
                t.Day == now.Day;

            var isMidnight = t.Hour == 0 && t.Minute == 0;

            if (isToday && isMidnight)
            {
                t = now;
            }

            var tvq = new Tvq(t, v, Quality.Ok);

            var repo = new RegistryEntryRepoFactory().GetRegistryEntryRepo(request.IdentityName);

            repo.AddRegistryEntry(tvq);
            var result = new AddRegistryEntryResult();

            return(Task.FromResult(result));
        }
예제 #14
0
        public Tvq Apply(Tvq o1, Tvq o2)
        {
            var v = o2.V - o1.V;

            var isRollover = v <0 &&
                                o1.V> RolloverThresholdUpper &&
                             o2.V < RolloverThresholdLower;

            if (isRollover)
            {
                v = Rollover - o1.V + o2.V;
            }
            else if (v < 0 &&
                     o1.V > RolloverThresholdLower &&
                     o2.V < RolloverThresholdLower)
            {
                v = 0;
            }
            else if (Math.Abs(o2.V) < 1e-9) // The meter value is zero => new meter installed
            {
                v = 0;                      // Assume zero consumption. Requires meter reading just before switch so as not to lose consumption.
            }


            var q = Quality.Ok;

            if (o1.Q == Quality.Suspect || o2.Q == Quality.Suspect)
            {
                q = Quality.Suspect;
            }
            else if (o1.Q == Quality.Interpolated || o2.Q == Quality.Interpolated)
            {
                q = Quality.Interpolated;
            }

            return(new Tvq(o2.Time, v, q));
        }
예제 #15
0
        public Tvq Apply(DateTime t0, DateTime t1, Timeseries ts)
        {
            double v0      = 0;
            Tvq    current = null;
            int    i;
            int    currentIndex = 0;

            for (i = 0; i < ts.Count; i++)
            {
                currentIndex = i;
                current      = ts[currentIndex];
                v0           = current.V;
                if (current.Time >= t0)
                {
                    break;
                }
            }

            Debug.Assert(ts[currentIndex].Time >= t0);

            if (currentIndex > 0)
            {
                v0 = Tvq.CalculateValueAt(t0, ts[currentIndex - 1], ts[currentIndex]).V;
            }

            double area = 0;

            var tsHasValueWithinPeriod = current.Time <= t1;

            if (!tsHasValueWithinPeriod)
            {
                double v1 = 0;
                if (i > 0)
                {
                    v1 = Tvq.CalculateValueAt(t1, ts[currentIndex - 1], ts[currentIndex]).V;
                }
                double avg = (v0 + v1) / 2;
                return(new Tvq(t0, avg, Quality.Interpolated));
            }

            if (current != null)
            {
                var dt = (current.Time - t0).TotalSeconds;
                area = v0 * dt;
            }

            Tvq previous = null;

            for (i++; i < ts.Count; i++)
            {
                previous = current;
                current  = ts[i];
                if (current.Time > t1)
                {
                    break;
                }

                var dt           = (current.Time - previous.Time).TotalSeconds;
                var averageValue = (previous.V + current.V) / 2;
                area += averageValue * dt;
            }

            if (current.Time < t1)
            {
                var isStepwise = true;
                var valueAtT1  = isStepwise
                    ? current.V                                      // Take current value
                    : Tvq.CalculateValueAt(t1, previous, current).V; // Extrapolate linearly

                var deltaT =
                    (t1 - current.Time)
                    .TotalSeconds;
                var averageValue = (current.V + valueAtT1) / 2;
                var lastArea     = averageValue * deltaT;
                area += lastArea;
            }

            var average = area / (t1 - t0).TotalSeconds;

            return(new Tvq(t0, average, Quality.Interpolated));
        }
예제 #16
0
 private static Tvq CalculateDelta(Tvq current, Tvq previous)
 {
     return(DeltaOp.Apply(previous, current));
 }
예제 #17
0
        /// <summary>
        /// Inserts point at the specified interval by attempting to interpolate and/or
        /// extrapolate values. Useful when splitting up a period into several series
        /// and displaying calculated start/end values in a graph.
        /// </summary>
        /// <param name="ts"></param>
        /// <param name="intervalLength"></param>
        /// <returns>A new timeseries that has values at the start and end of the interval</returns>
        /// <example>
        /// TODO FB
        /// </example>
        public Timeseries InsertPoints(Timeseries ts, Interval intervalLength)
        {
            if (ReferenceEquals(ts, null))
            {
                throw new ArgumentException("ts");
            }

            var result   = new Timeseries();
            Tvq previous = null;

            for (var i = 0; i < ts.Count; i++)
            {
                var current       = ts[i];
                var isNewInterval =
                    i == 0 ||
                    previous != null && IsNewInterval(previous.Time, current.Time, intervalLength);

                //
                // Previous interval end?
                //
                var doInsertPreviousEnd = isNewInterval && previous != null;  // && not last second
                if (doInsertPreviousEnd)
                {
                    var lastSecondOfPrevious = LastSecondOfInterval(previous.Time, intervalLength);
                    var tvq = Tvq.CalculateValueAt(lastSecondOfPrevious, previous, current);
                    result.Add(tvq);
                }

                if (previous != null)
                {
                    var hasEmptyIntervalInBetween =
                        HasEmptyIntervalInBetween(previous.Time, current.Time, intervalLength);
                    var t = previous.Time;
                    while (hasEmptyIntervalInBetween)
                    {
                        t = FirstSecondOfNextInterval(t, intervalLength);
                        var tvq = Tvq.CalculateValueAt(t, previous, current);
                        result.Add(tvq);

                        var tLastSecond = LastSecondOfInterval(t, intervalLength);
                        tvq = Tvq.CalculateValueAt(tLastSecond, previous, current);
                        result.Add(tvq);

                        hasEmptyIntervalInBetween = HasEmptyIntervalInBetween(t, current.Time, intervalLength);
                    }
                }

                //
                // Current interval start?
                //
                var firstSecond = FirstSecond(current.Time, intervalLength);
                if (isNewInterval && current.Time > firstSecond)
                {
                    var newTvq = previous == null ?
                                 new Tvq(firstSecond, current.V, Quality.Interpolated) : Tvq.CalculateValueAt(firstSecond, previous, current);
                    result.Add(newTvq);
                }

                //
                // Add point
                //
                result.Add(current);

                previous = current;
            }

            if (ts.Any())
            {
                if (previous != null)
                {
                    var lastSecond = LastSecondOfInterval(previous.Time, intervalLength);

                    var iLast   = ts.Count - 1;
                    var lastTvq = ts.Last();

                    if (ts.Count <= 1 && lastTvq.Time < lastSecond)
                    {
                        var newTvq = new Tvq(lastSecond, lastTvq.V, Quality.Interpolated);
                        result.Add(newTvq);
                    }
                    else if (lastTvq.Time < lastSecond)
                    {
                        var newTvq = Tvq.CalculateValueAt(lastSecond, ts[iLast - 1], lastTvq);
                        result.Add(newTvq);
                    }
                }
            }
            return(result);
        }
예제 #18
0
        /// <summary>
        /// Periodizes a time series with relative consumption
        /// </summary>
        /// <param name="op"></param>
        /// <param name="ts">A time series with relative consumption, without roll over or meter change</param>
        /// <param name="interval"></param>
        /// <returns></returns>
        private Timeseries Periodize(IUnaryAggregateOperator op, Timeseries ts, Interval interval)
        {
            var result = new Timeseries();

            using (var enumerator = ts.GetEnumerator())
            {
                DateTime?intervalStart     = null;
                DateTime nextIntervalStart = DateTime.MinValue;
                var      areMoreValues     = enumerator.MoveNext();
                Tvq      currentTvq        = null;
                Tvq      previousTvq;
                Tvq      nextTvq      = enumerator.Current;
                var      doNeedToMove = true;
                double   sumForPeriod = 0;
                while (areMoreValues)
                {
                    // Setup previous, current and next if we need to
                    enumerator.MoveNext();
                    previousTvq = currentTvq;
                    currentTvq  = nextTvq;
                    nextTvq     = enumerator.Current;
                    Debug.Assert(currentTvq != null);

                    // Initialize interval
                    if (!intervalStart.HasValue)
                    {
                        intervalStart     = FirstSecond(currentTvq.Time, interval);
                        nextIntervalStart = FirstSecondOfNextInterval(intervalStart.Value, interval);
                        sumForPeriod      = 0;
                    }

                    Debug.Assert(currentTvq.Time >= intervalStart);
                    Debug.Assert(currentTvq.Time <= nextIntervalStart);

                    do  // next value may be many periods ahead
                    {
                        if (nextTvq == null)
                        {
                            if (previousTvq != null) // Prevent input with only one value from entering
                            {
                                sumForPeriod +=
                                    currentTvq.V
                                    / (currentTvq.Time - previousTvq.Time).TotalDays
                                    * (nextIntervalStart - previousTvq.Time).TotalDays; // Extrapolate consumption to end of interval
                            }

                            result.Add(new Tvq(intervalStart.Value, sumForPeriod, Quality.Interpolated));
                            sumForPeriod = 0;
                        }
                        else if (nextIntervalStart <= nextTvq.Time)
                        {
                            doNeedToMove = false;

                            sumForPeriod += currentTvq.V;

                            var remainingConsumptionBelongingToThisPeriod = nextTvq.V
                                                                            * (nextIntervalStart - currentTvq.Time).TotalDays
                                                                            / (nextTvq.Time - currentTvq.Time).TotalDays;

                            var consumptionInPeriod =
                                sumForPeriod
                                + remainingConsumptionBelongingToThisPeriod;
                            result.Add(new Tvq(intervalStart.Value, consumptionInPeriod, Quality.Interpolated));
                            sumForPeriod = -remainingConsumptionBelongingToThisPeriod - currentTvq.V; // This is how much of nextTvq.V that we already have added.

                            intervalStart     = nextIntervalStart;
                            nextIntervalStart = FirstSecondOfNextInterval(intervalStart.Value, interval);
                        }
                        else
                        {
                            sumForPeriod += currentTvq.V;
                            doNeedToMove  = true;
                        }
                    } while (!doNeedToMove);

                    areMoreValues = nextTvq != null;
                }
            }
            return(result);
        }