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))); }
public ParticipationsSummary SummarizeParticipationsBetween(DateTime startDate, DateTime endDate) { ParticipationAndSummary result = this.searchHelper.CombineBetweenKeys(startDate, true, endDate, false); if (result == null) { ParticipationsSummary summary = new ParticipationsSummary(); summary.Start = startDate; summary.End = endDate; summary.CumulativeIntensity = new TimeSpan(); summary.LogActiveTime = Distribution.Zero; summary.Trend = new Correlator(); return(summary); } return(result.Summary); }