// returns basically the fraction of the user's time that was spent performing that Doable recently at that date
        public ProgressionValue GetValueAt(DateTime when, bool strictlyEarlier)
        {
            // find the most recent Participation
            ListItemStats <DateTime, Participation> previousStats = this.searchHelper.FindPreviousItem(when, strictlyEarlier);
            DateTime previousEnd;

            // make sure that we have enough data
            if (previousStats == null)
            {
                previousEnd = this.Owner.DiscoveryDate;
            }
            else
            {
                // figure out whether we're in the middle of a participation or not
                Participation previousParticipation = previousStats.Value;
                previousEnd = previousParticipation.EndDate;
            }
            //int index = 2 * this.searchHelper.CountBeforeKey(when, !strictlyEarlier);
            if (previousEnd.CompareTo(when) > 0)
            {
                // we're in the middle of a participation, so the value is zero
                return(new ProgressionValue(when, new Distribution(0, 0, 1)));
            }
            // we're not in the middle of a participation, so the value is the amount of time since the last one ended
            TimeSpan         duration     = when.Subtract(previousEnd);
            Distribution     currentValue = Distribution.MakeDistribution(duration.TotalSeconds, 0, 1);
            ProgressionValue result       = new ProgressionValue(when, currentValue);

            return(result);
        }
        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);
        }
示例#3
0
        public static RatingSource FromParticipation(Participation source)
        {
            RatingSource cause = new RatingSource("Participation");

            cause.Converted = source;
            return(cause);
        }
 }                                           // the suggestion that caused this Consideration
 public void FillInFromParticipation(Participation source)
 {
     if (this.ActivityDescriptor == null)
     {
         this.ActivityDescriptor = source.ActivityDescriptor;
     }
 }
示例#5
0
 public override void PreviewParticipation(Participation newParticipation)
 {
     if (this.LatestParticipation == null || newParticipation.EndDate.CompareTo(this.LatestParticipation.EndDate) > 0)
     {
         this.LatestParticipation = newParticipation;
     }
 }
 public void RemoveParticipation(Participation participationToRemove)
 {
     // make sure that we had included it in the first place
     if (this.ShouldIncludeParticipation(participationToRemove))
     {
         this.searchHelper.Remove(participationToRemove.StartDate);
     }
 }
 public void AddParticipation(Participation newParticipation)
 {
     if (this.ShouldIncludeParticipation(newParticipation))
     {
         // Eventually, the StatList should be improved to allow intervals as keys
         // For now we allow searching for participation by start date
         this.searchHelper.Add(newParticipation.StartDate, newParticipation);
         //this.searchHelper.Add(newParticipation.EndDate, newParticipation);
     }
 }
 public void RemoveParticipation(Participation participation)
 {
     // make sure that we actually added it in the first place
     if (this.ShouldIncludeParticipation(participation))
     {
         // for now, the searchHelper identifies the item solely based on key, but it's okay, because ties are broken in a last-in-first-out manner
         DateTime startDate = participation.StartDate;
         this.searchHelper.Remove(startDate);
     }
 }
 public void AddParticipation(Participation newParticipation)
 {
     if (this.ShouldIncludeParticipation(newParticipation))
     {
         // for now, we add the participation as a single datapoint, where the key knows the start date but not the end date
         // Eventually, the StatList should be improved to allow intervals as keys
         DateTime startDate = newParticipation.StartDate;
         this.searchHelper.Add(startDate, this.Summarize(newParticipation));
     }
 }
示例#10
0
 public override void AttemptToMatch(Participation participation)
 {
     // check whether this rating might describe this participation
     if (!this.CanMatch(participation))
     {
         return;
     }
     // This rating seems to describe this participation, so fill in the corresponding data
     this.ActivityDescriptor = participation.ActivityDescriptor;
     this.Date = participation.StartDate;
     base.AttemptToMatch(participation);
 }
示例#11
0
 public override void AddParticipation(Participation newParticipation)
 {
     if (newParticipation.DismissedActivity)
     {
         this.complete = true;
     }
     if (newParticipation.CompletedMetric)
     {
         this.completedSuccessfully = true;
     }
     base.AddParticipation(newParticipation);
 }
        public New_ParticipationComment_Layout(Participation participation, LayoutStack layoutStack)
        {
            this.participation = participation;
            this.textBox       = new Editor();
            this.layoutStack   = layoutStack;
            Button saveButton = new Button();

            saveButton.Clicked += SaveButton_Clicked;
            GridLayout_Builder builder = new Vertical_GridLayout_Builder()
                                         .AddLayout(new TextblockLayout("Comment"))
                                         .AddLayout(new TextboxLayout(textBox))
                                         .AddLayout(new ButtonLayout(saveButton, "Save"));

            this.SubLayout = builder.BuildAnyLayout();
        }
 public void AddParticipation(Participation newParticipation)
 {
     if (this.ShouldIncludeParticipation(newParticipation))
     {
         WillingnessSummary willingness;
         if (newParticipation.Suggested)
         {
             willingness = WillingnessSummary.Prompted;
         }
         else
         {
             willingness = WillingnessSummary.Unprompted;
         }
         this.AddValue(newParticipation.StartDate, willingness);
     }
 }
 public override void PreviewParticipation(Participation newParticipation)
 {
     if (this.recomputeRatings)
     {
         if (newParticipation.Rating == null)
         {
             newParticipation.Rating = this.engine.MakeEstimatedRating(newParticipation);
         }
     }
     if (this.recomputeEfficiencies)
     {
         if (newParticipation.RelativeEfficiencyMeasurement != null)
         {
             newParticipation.setRelativeEfficiencyMeasurement(this.engine.Make_CompletionEfficiencyMeasurement(newParticipation), newParticipation.EffectivenessMeasurement.Metric);
         }
     }
 }
        public override void AttemptToMatch(Participation participation)
        {
            bool betterCanMatch = this.BetterRating.CanMatch(participation);
            bool worseCanMatch  = this.WorseRating.CanMatch(participation);

            // figure out whether the better activity or the worse activity is the one that generated this rating
            if (betterCanMatch && !worseCanMatch)
            {
                // if we get here, the better participation generated this RelativeRating
                this.BetterRating.AttemptToMatch(participation);
            }
            if (worseCanMatch && !betterCanMatch)
            {
                // if we get here, the worse participation generated this RelativeRating
                this.WorseRating.AttemptToMatch(participation);
            }
        }
示例#16
0
        public void AddParticipation(Participation newParticipation)
        {
            if (!this.updatedAfterInheritances)
            {
                this.engine.FullUpdate();
                this.updatedAfterInheritances = true;
            }
            RelativeRating newRelativeRating = newParticipation.Rating as RelativeRating;

            if (newRelativeRating != null)
            {
                RelativeRating newRating = this.AddRating(newRelativeRating);
                newParticipation.Rating = newRating;
            }
            this.PreviewParticipation(newParticipation);

            this.engine.PutParticipationInMemory(newParticipation);
            this.PostParticipation(newParticipation);
        }
        // creates the rating to assign to the given Participation
        public Rating GetRelativeRating(Engine engine, Participation participation)
        {
            // abort if null input
            double?maybeScale = this.GetRatio();

            if (maybeScale == null)
            {
                return(engine.MakeEstimatedRating(participation));
            }
            double scale = maybeScale.Value;

            if (this.latestParticipation == null)
            {
                return(null);
            }
            RelativeRating rating = engine.MakeRelativeRating(participation.ActivityDescriptor, participation.StartDate, scale, this.latestParticipation);

            return(rating);
        }
示例#18
0
 public bool CanMatch(Participation participation)
 {
     if (participation == null)
     {
         return(false);
     }
     if (this.ActivityDescriptor != null)
     {
         if (!this.ActivityDescriptor.CanMatch(participation.ActivityDescriptor))
         {
             return(false);
         }
     }
     if (this.Date != null)
     {
         if (!this.Date.Value.Equals(participation.StartDate))
         {
             return(false);
         }
     }
     return(true);
 }
示例#19
0
        public override void PreviewParticipation(Participation newParticipation)
        {
            logCounter++;
            // resolve some parameters
            Activity activity = this.activityDatabase.ResolveDescriptor(newParticipation.ActivityDescriptor);
            DateTime when     = newParticipation.StartDate;

            if (logCounter % 1000 == 0)
            {
                this.log("Processing participation at " + when + " for " + activity.Name);
            }
            ParticipationFeedback feedbackObject = this.engine.computeStandardParticipationFeedback(activity, when, newParticipation.EndDate);

            if (feedbackObject != null)
            {
                // remove the number
                string fullFeedback = feedbackObject.Summary;
                string feedback     = this.stripLeadingNumbers(fullFeedback);

                // save into this.feedbacks
                string prefix = "Feedback at " + when + " for " + activity + ":";
                //this.log(this.padColumn(prefix) + " " + fullFeedback);
                if (!this.feedbacks.ContainsKey(feedback))
                {
                    this.feedbacks[feedback] = new Dictionary <Activity, int>();
                }
                Dictionary <Activity, int> counts = feedbacks[feedback];
                if (!counts.ContainsKey(activity))
                {
                    counts[activity] = 0;
                }
                counts[activity]++;
            }
            // call parent class
            base.PreviewParticipation(newParticipation);
        }
        public override RelativeRating ProcessRating(RelativeRating newRating)
        {
            if (!this.recomputeRatings)
            {
                return(newRating);
            }
            System.Diagnostics.Debug.WriteLine("Adding rating with date " + ((DateTime)newRating.FirstRating.Date).ToString());

            AbsoluteRating otherRating = newRating.FirstRating;
            AbsoluteRating thisRating  = newRating.SecondRating;

            if (newRating.Source != null)
            {
                Participation  participation = newRating.Source.ConvertedAsParticipation;
                RelativeRating rawRating     = participation.Rating as RelativeRating;
                if (rawRating.BetterRating.Date == null && rawRating.WorseRating.Date != null)
                {
                    // This one is BetterRating
                    thisRating  = newRating.BetterRating;
                    otherRating = newRating.WorseRating;
                }
                else
                {
                    // This one is WorseRating
                    thisRating  = newRating.WorseRating;
                    otherRating = newRating.BetterRating;
                }
            }

            if (newRating.RawScoreScale == null)
            {
                // The relative rating simply said "activity X is better than Y"
                // We might as well assign the same scale that the previous algorithm had computed
                double scale = thisRating.Score / otherRating.Score;
                newRating.RawScoreScale = scale;
            }

            Participation otherParticipation = null;

            if (otherRating.Source != null)
            {
                otherParticipation = otherRating.Source.ConvertedAsParticipation;
            }
            Participation thisParticipation = null;

            if (thisRating.Source != null)
            {
                thisParticipation = thisRating.Source.ConvertedAsParticipation;
            }
            if (otherParticipation != null && thisParticipation != null)
            {
                RelativeRating modifiedRating = this.engine.MakeRelativeRating(thisParticipation.ActivityDescriptor, thisParticipation.StartDate, newRating.RawScoreScale.Value, otherParticipation);
                if (modifiedRating.BetterRating.ActivityDescriptor != null)
                {
                    if (!modifiedRating.BetterRating.ActivityDescriptor.CanMatch(newRating.BetterRating.ActivityDescriptor))
                    {
                        throw new Exception("Internal error: RatingRenormalizer swapped ratings while rewriting them");
                    }
                }
                if (modifiedRating.WorseRating.ActivityDescriptor != null)
                {
                    if (!modifiedRating.WorseRating.ActivityDescriptor.CanMatch(newRating.WorseRating.ActivityDescriptor))
                    {
                        throw new Exception("Internal error: RatingRenormalizer swapped ratings while rewriting them");
                    }
                }
                if (modifiedRating.BetterRating.ActivityDescriptor == null && modifiedRating.WorseRating.ActivityDescriptor == null)
                {
                    throw new Exception("Internal error: RatingRenormalizer created rating that does not specify an activity");
                }
                return(modifiedRating);
            }
            return(newRating);
        }
 public Participation Combine(Participation participation1, Participation participation2)
 {
     // we don't actually care about conglomerations of Participations so this function can return anything
     return(this.Default());
 }
示例#22
0
 public virtual void PostParticipation(Participation newParticipation)
 {
 }
示例#23
0
 public virtual void PreviewParticipation(Participation newParticipation)
 {
 }
 // tells whether we care about this participation at all
 public bool ShouldIncludeParticipation(Participation newParticipation)
 {
     return(true);
 }
示例#25
0
        public override void PostParticipation(Participation newParticipation)
        {
            string text = this.textConverter.ConvertToString(newParticipation);

            this.addText(text);
        }
示例#26
0
 // checks whether it's possible that this rating was generated by this participation, and if so, fills in some data for it
 public virtual void AttemptToMatch(Participation participation)
 {
     this.Source = RatingSource.FromParticipation(participation);
 }
        public Participation GetParticipation(Engine engine)
        {
            Activity activity = this.nameBox.Activity;

            if (activity == null)
            {
                return(null);
            }
            ActivityDescriptor descriptor = activity.MakeDescriptor();

            if (descriptor.ActivityName == null || descriptor.ActivityName.Length == 0)
            {
                return(null);
            }

            if (!this.startDateBox.IsDateValid())
            {
                return(null);
            }
            if (!this.endDateBox.IsDateValid())
            {
                return(null);
            }
            // If the user is trying to submit a participation with misordered dates, then point the out to them
            // Although we could've highlighted this to the user sooner, in most cases this would just distract them and they wouldn't want to think about it
            if (this.EndDate.CompareTo(this.StartDate) <= 0)
            {
                this.startDateBox.appearInvalid();
                this.endDateBox.appearInvalid();
                return(null);
            }
            // If the user tries to record having done someting in the future, that's a mistake because it hasn't happened yet
            DateTime now = DateTime.Now;

            if (this.StartDate.CompareTo(now) > 0 || this.EndDate.CompareTo(now) > 0)
            {
                return(null);
            }
            Participation participation = new Participation(this.StartDate, this.EndDate, descriptor);

            if (this.CommentText != "" && this.CommentText != null)
            {
                participation.Comment = this.CommentText;
            }

            try
            {
                Rating rating = this.ratingBox.GetRelativeRating(engine, participation);
                participation.Rating = rating;
            }
            catch (Exception)
            {
                // If the rating is invalid, then we can ignore that
            }

            Metric metric = this.Metric;

            if (metric != null)
            {
                // Record the success/failure status of the participation
                string status       = this.todoCompletionStatusPicker.SelectedItem.ToString();
                bool   successful   = (status == this.TaskCompleted_Text || status == this.ProblemComplete_Text);
                bool   closed       = (status != this.TaskIncomplete_Text && status != this.ProblemIncomplete_Text);
                double helpFraction = this.helpStatusPicker.GetHelpFraction(participation.Duration);
                participation.EffectivenessMeasurement = new CompletionEfficiencyMeasurement(metric, successful, helpFraction);
                participation.EffectivenessMeasurement.DismissedActivity = closed;
                // Notice that the Engine doesn't need us to pass in a Metric for computing the efficiency of this participation, because computing efficiency requires an experiment, and the
                // experiment already knows which metric we're using
                RelativeEfficiencyMeasurement measurement = engine.Make_CompletionEfficiencyMeasurement(participation);
                participation.EffectivenessMeasurement.Computation = measurement;
            }

            participation.Suggested = this.get_wasSuggested(participation.ActivityDescriptor);

            return(participation);
        }
        private void Update_FeedbackBlock_Text()
        {
            ParticipationFeedback participationFeedback = null;
            Activity activity = this.nameBox.Activity;

            if (activity != null && this.startDateBox.IsDateValid() && this.endDateBox.IsDateValid())
            {
                // We have a valid activity and valid dates, so give feedback about the participation
                DateTime startDate = this.startDateBox.GetDate();
                DateTime endDate   = this.endDateBox.GetDate();
                participationFeedback = this.computeFeedback(activity, startDate, endDate);
                if (participationFeedback != null)
                {
                    this.participationFeedbackButtonLayout.setText(participationFeedback.Summary);
                    bool?happySummary = participationFeedback.happySummary;
                    if (happySummary != null)
                    {
                        if (happySummary.Value == true)
                        {
                            this.participationFeedbackButtonLayout.setTextColor(Color.Green);
                        }
                        else
                        {
                            this.participationFeedbackButtonLayout.setTextColor(Color.Red);
                        }
                    }
                    else
                    {
                        this.participationFeedbackButtonLayout.resetTextColor();
                    }
                    this.promptHolder.SubLayout = this.participationFeedbackButtonLayout;
                }
                else
                {
                    this.promptHolder.SubLayout = null;
                }
            }
            else
            {
                if (this.nameBox.NameText == null || this.nameBox.NameText == "")
                {
                    // If we have no text in the activity name box, then we do have space for a response and there isn't a current activity to give feedback on
                    Participation latestParticipation = this.LatestParticipation;
                    if (latestParticipation != null && latestParticipation.RelativeEfficiencyMeasurement != null)
                    {
                        this.promptHolder.SubLayout = this.experimentFeedbackLayout;
                    }
                    else
                    {
                        // If the user has submitted a participation before, it should be fast to get a suggestion, so we do that now
                        if (this.wasEverCleared)
                        {
                            this.updateSuggestion();
                            if (this.suggestedActivityName != null)
                            {
                                this.promptHolder.SubLayout = this.suggestionsLayout;
                                this.suggestionLayout.setText("How about " + this.suggestedActivityName + "?");
                            }
                            else
                            {
                                this.promptHolder.SubLayout = null;
                            }
                        }
                        else
                        {
                            // If the user hasn't submitted a participation during this usage of ActivityRecommender yet, then it will probably be slow to get a suggestion, so we'll wait until later before showing a suggestion
                            this.promptHolder.SubLayout = null;
                        }
                    }
                }
                else
                {
                    // If we have no valid activity name but we do have some text in the name box, then we don't need to say anything
                    // The name entry box will offer autocomplete suggestions and/or help
                    this.promptHolder.SubLayout = null;
                }
            }
            // Note that this is the only method that modifies either participationFeedback or responseButtonLayout.text,
            // so we can ensure that they match
            this.participationFeedback = participationFeedback;
            this.feedbackIsUpToDate    = true;
        }