ParticipationAndSummary Summarize(Participation participation)
        {
            ParticipationAndSummary result = new ParticipationAndSummary();

            result.Participation = participation;

            ParticipationsSummary summary = new ParticipationsSummary();

            Correlator correlator = new Correlator();
            double     x          = this.GetWeight(participation.Duration);
            double     weight     = x / 2;

            correlator.Add(0, 0, weight);
            correlator.Add(x, x, weight);

            summary.Trend = correlator;

            Distribution logActiveTime = Distribution.MakeDistribution(Math.Log(participation.Duration.TotalSeconds), 0, 1);

            summary.LogActiveTime = logActiveTime;

            summary.Start = participation.StartDate;
            summary.End   = participation.EndDate;

            summary.CumulativeIntensity = participation.Duration;

            result.Summary = summary;


            return(result);
        }
        public ParticipationAndSummary Combine(ParticipationAndSummary a, ParticipationAndSummary b)
        {
            if (a == null || a.Summary.CumulativeIntensity.TotalSeconds <= 0)
            {
                return(b);
            }
            if (b == null || b.Summary.CumulativeIntensity.TotalSeconds <= 0)
            {
                return(a);
            }
            ParticipationsSummary earlier = a.Summary;
            ParticipationsSummary later   = b.Summary;

            if (earlier.Start.CompareTo(later.Start) > 0)
            {
                ParticipationsSummary temp = earlier;
                earlier = later;
                later   = temp;
            }

            ParticipationsSummary summary = new ParticipationsSummary();

            summary.CumulativeIntensity = earlier.CumulativeIntensity.Add(later.CumulativeIntensity);
            summary.Start         = earlier.Start;
            summary.End           = later.End;
            summary.LogActiveTime = earlier.LogActiveTime.Plus(later.LogActiveTime);

            // time between prev end and next start
            TimeSpan idleDuration = later.Start.Subtract(earlier.End);
            double   idleX1       = this.GetWeight(earlier.End.Subtract(earlier.Start));
            double   idleX2       = this.GetWeight(later.Start.Subtract(earlier.Start));

            double     earlierSum   = this.GetWeight(earlier.CumulativeIntensity);
            Correlator laterShifted = later.Trend.CopyAndShiftRightAndUp(idleX2, earlierSum);
            Correlator correlator   = earlier.Trend.Plus(laterShifted);

            if (idleDuration.TotalSeconds > 0)
            {
                double idleY  = earlierSum;
                double weight = this.GetWeight(idleDuration);
                correlator.Add(idleX1, idleY, weight);
                correlator.Add(idleX2, idleY, weight);
            }

            summary.Trend = correlator;


            ParticipationAndSummary result = new ParticipationAndSummary();

            result.Summary = summary;

            if (summary.Trend.Correlation < 0)
            {
                System.Diagnostics.Debug.WriteLine("illegal correlation found: " + summary.Trend.Correlation + " for Activity " + this.Owner.Name);
            }
            // not bothering to assign a Participation because nothing will need it

            return(result);
        }
        public ProgressionValue GetValueViaCorrelation(DateTime when, bool strictlyEarlier)
        {
            double   resultNumber = 0.5;
            DateTime startDate;
            // The UI for logging data improved at this date. Any earlier data isn't used for computing correlation
            DateTime changeDate = new DateTime(2015, 9, 20);

            if (when.CompareTo(changeDate) > 0)
            {
                startDate = changeDate;
            }
            else
            {
                startDate = DateTime.MinValue;
            }

            ParticipationAndSummary info = this.searchHelper.CombineBetweenKeys(startDate, true, when, !strictlyEarlier);

            if (info != null)
            {
                ParticipationsSummary summary = info.Summary;

                Correlator correlator = summary.Trend;

                double x          = this.GetWeight(when.Subtract(summary.Start));
                double predictedY = correlator.GetYForX(x);
                double actualY    = this.GetWeight(summary.CumulativeIntensity);
                double deltaY     = actualY - predictedY;
                // Ideally we'd just return deltaY, but we have to transform it into a predefined range so the interpolator can use it
                // Although it would be possible to divide by the total time elapsed, that would cause any deviation to decrease over time
                // So instead we just warp the space from (-infinity, infinity) into (0, 1)
                bool positive = true;
                if (deltaY < 0)
                {
                    deltaY  *= -1;
                    positive = false;
                }

                // rescale such that a 32 hour deviation reaches halfway to the end of the space
                resultNumber = deltaY / this.GetWeight(TimeSpan.FromHours(32));

                // rescale such that nothing escapes the end of the space
                resultNumber = 1.0 - 1.0 / (1.0 + Math.Log(1 + resultNumber));

                if (positive)
                {
                    resultNumber = (resultNumber + 1.0) / 2.0;
                }
                else
                {
                    resultNumber = (1 - resultNumber) / 2.0;
                }
            }
            return(new ProgressionValue(when, Distribution.MakeDistribution(resultNumber, 0, 0)));
        }
예제 #4
0
 public Correlator Plus(Correlator other)
 {
     return(new Correlator(this.count + other.count, this.sumXY + other.sumXY, this.xs.Plus(other.xs), this.ys.Plus(other.ys)));
 }
예제 #5
0
        // updates the locations at which to draw the provided points
        private void UpdateDrawing(SKCanvas canvas, SkiaSharp.SKSizeI displaySize)
        {
            canvas.Clear();
            if (this.plotRequests.Count < 1)
            {
                return;
            }

            DateTime start = DateTime.Now;

            double resolution = 1;

            // determine what domain and range we want to display
            double minimumX = this.MinX.GetValueOrDefault(this.minXPresent);
            double maximumX = this.MaxX.GetValueOrDefault(this.maxXPresent);
            double minimumY = this.MinY.GetValueOrDefault(this.minYPresent);
            double maximumY = this.MaxY.GetValueOrDefault(this.maxYPresent);

            int    i;
            double scaleX = 0;
            double scaleY = 0;

            if (maximumX > minimumX)
            {
                scaleX = displaySize.Width / (maximumX - minimumX);
            }
            if (maximumY > minimumY)
            {
                scaleY = displaySize.Height / (maximumY - minimumY);
            }

            // plot all of the provided points
            double x, y, x2, y2;

            foreach (PlotRequest plotRequest in this.plotRequests)
            {
                List <Datapoint> pointList = plotRequest.Data;

                if (pointList.Count < 1)
                {
                    continue;
                }

                x = (pointList[0].Input - minimumX) * scaleX;
                y = (maximumY - pointList[0].Output) * scaleY;

                SKPaint brush = makeBrush(plotRequest.DrawColor);
                for (i = 0; i < pointList.Count; i++)
                {
                    x2 = (pointList[i].Input - minimumX) * scaleX;
                    y2 = (maximumY - pointList[i].Output) * scaleY;

                    if (Math.Abs(x2 - x) < resolution && Math.Abs(y2 - y) < resolution)
                    {
                        continue; // skip any lines that the user won't be able to see
                    }
                    if (plotRequest.DrawData)
                    {
                        canvas.DrawLine((float)x, (float)y, (float)x2, (float)y2, brush);
                    }
                    x = x2;
                    y = y2;
                }

                if (plotRequest.Draw_RegressionLine)
                {
                    Correlator correlator = plotRequest.Correlator;
                    if (correlator.StdDevX != 0)
                    {
                        // if stdDevX == 0, we'll skip it
                        if (correlator.StdDevX != 0)
                        {
                            SKPaint correlatorBrush = makeBrush(plotRequest.RegressionLine_Color);
                            // compute the equation of the least-squares regression line
                            double correlation = correlator.Correlation;
                            // plot the least-squares regression line
                            double slope = correlator.Slope;
                            x  = minimumX;
                            y  = (x - correlator.MeanX) * slope + correlator.MeanY;
                            x2 = maximumX;
                            y2 = (x2 - correlator.MeanX) * slope + correlator.MeanY;

                            double renderX1 = (x - minimumX) * scaleX;
                            double renderY1 = (maximumY - y) * scaleY;
                            double renderX2 = (x2 - minimumX) * scaleX;
                            double renderY2 = (maximumY - y2) * scaleY;

                            double rescaleRatio;
                            // cut off the right side of the line if it goes out of bounds
                            rescaleRatio = 1;
                            if (renderY2 > displaySize.Height)
                            {
                                rescaleRatio = (displaySize.Height - renderY1) / (renderY2 - renderY1);
                            }
                            else
                            {
                                if (renderY2 < 0)
                                {
                                    rescaleRatio = (renderY1) / (renderY1 - renderY2);
                                }
                            }
                            renderY2 = renderY1 + (renderY2 - renderY1) * rescaleRatio;
                            renderX2 = renderX1 + (renderX2 - renderX1) * rescaleRatio;
                            // cut off the left side of the line if it goes out of bounds
                            rescaleRatio = 1;
                            if (renderY1 > displaySize.Height)
                            {
                                rescaleRatio = (displaySize.Height - renderY2) / (renderY1 - renderY2);
                            }
                            else
                            {
                                if (renderY1 < 0)
                                {
                                    rescaleRatio = (renderY2) / (renderY2 - renderY1);
                                }
                            }
                            renderY1 = renderY2 - (renderY2 - renderY1) * rescaleRatio;
                            renderX1 = renderX2 - (renderX2 - renderX1) * rescaleRatio;


                            canvas.DrawLine((float)renderX1, (float)renderY1, (float)renderX2, (float)renderY2, correlatorBrush);
                        }
                    }
                }
            }
            // now draw some tick marks
            if (this.XAxisSubdivisions != null)
            {
                y  = displaySize.Height - 1;
                y2 = displaySize.Height * 19 / 20;
                foreach (double tickX in this.XAxisSubdivisions)
                {
                    canvas.DrawLine((float)((tickX - minimumX) * scaleX), (float)y, (float)((tickX - minimumX) * scaleX), (float)y2, cyanBrush);
                }
            }
            if (this.YAxisSubdivisions != null)
            {
                x  = 0;
                x2 = displaySize.Width / 20;
                foreach (double tickY in this.YAxisSubdivisions)
                {
                    canvas.DrawLine((float)x, (float)((maximumY - tickY) * scaleY), (float)x2, (float)((maximumY - tickY) * scaleY), cyanBrush);
                }
            }
            // draw some axes
            canvas.DrawLine(0, 0, 0, displaySize.Height, cyanBrush);
            canvas.DrawLine(0, displaySize.Height - 1, displaySize.Width, displaySize.Height - 1, cyanBrush);

            DateTime end = DateTime.Now;

            System.Diagnostics.Debug.WriteLine("spent " + end.Subtract(start) + " in PlotView.UpdatePoints");
        }