private void regenerateEntries()
        {
            List <Inheritance> unchosenInheritances          = this.findUnchosenInheritances();
            List <Inheritance> immediatelyUsableInheritances = this.selectUsableInheritances(unchosenInheritances);

            if (immediatelyUsableInheritances.Count < 1)
            {
                if (this.dismissedInheritances.Count > 0)
                {
                    this.SubLayout = new TextblockLayout("You have already accepted or dismissed all of the built-in activity inheritances. Go back to the Add Activities screen to enter your own!");
                }
                else
                {
                    this.SubLayout = new TextblockLayout("You have already accepted all of the built-in activity inheritances. Go back to the Add Activities screen to enter your own!");
                }
            }
            else
            {
                GridLayout_Builder gridBuilder = new Vertical_GridLayout_Builder().Uniform();
                LayoutChoice_Set   helpLayout  = new HelpWindowBuilder()
                                                 .AddMessage("ActivityRecommender needs to know what you like to do, for providing suggestions, autocomplete, and more.")
                                                 .AddMessage("Do you like any of the activities here?")
                                                 .AddMessage("Selecting 'I like this' on an item of the form 'child (parent)' indicates two things: A: that you believe that the child is encompassed by the parent, and B: that the child is relevant to you.")
                                                 .AddMessage("Pushing the 'I like all kinds' button is equivalent to pushing the 'I like this' button on the given activity and all of its descendants.")
                                                 .AddMessage("Pushing the 'Not Interested' button will simply hide the given activity in this screen")
                                                 .Build();

                gridBuilder.AddLayout(new TextblockLayout("Press everything you like to do! Then go back.\n" +
                                                          "" + unchosenInheritances.Count + " remaining, built-in activity ideas:", 30).AlignHorizontally(TextAlignment.Center));

                int count = 0;
                foreach (Inheritance inheritance in immediatelyUsableInheritances)
                {
                    int numDescendants = this.FindDescendants(inheritance).Count;
                    Import_SpecificActivities_Layout specific = new Import_SpecificActivities_Layout(inheritance, numDescendants);
                    specific.Dismissed      += DismissedInheritance;
                    specific.AcceptedSingle += AcceptedSingleInheritance;
                    specific.AcceptedAll    += AcceptedInheritanceRecursive;
                    gridBuilder.AddLayout(specific);
                    // Don't display too many results at once to avoid taking to long to update the screen.
                    // The user should dismiss the ones they're not interested in, anyway
                    count++;
                    if (count >= 10)
                    {
                        gridBuilder.AddLayout(new TextblockLayout("Dismiss or accept an idea to see more!"));
                        break;
                    }
                }
                gridBuilder.AddLayout(new HelpButtonLayout(helpLayout, this.layoutStack, 30));

                this.SubLayout = ScrollLayout.New(gridBuilder.Build());
            }
        }
Example #2
0
        private void showResults(Activities_HappinessContributions contributions, DateTime start, DateTime end)
        {
            // title
            string title = "" + (contributions.Best.Count + contributions.Worst.Count) + " Activities adding or subtracting the most happiness from " + start + " to " + end;

            BoundProperty_List heights = new BoundProperty_List(4);

            heights.BindIndices(1, 3);
            GridLayout grid = GridLayout.New(heights, new BoundProperty_List(1), LayoutScore.Zero);

            grid.AddLayout(new TextblockLayout(title));

            // contents
            GridLayout_Builder topBuilder = new Vertical_GridLayout_Builder().Uniform();

            // Show the top activities from best to worst
            for (int i = 0; i < contributions.Best.Count; i++)
            {
                ActivityHappinessContribution item = contributions.Best[i];
                topBuilder.AddLayout(this.renderContribution("top " + (i + 1) + ": ", item, start));
            }
            grid.AddLayout(ScrollLayout.New(topBuilder.BuildAnyLayout()));

            // Use the help button as the divider between the best and worst activities
            LayoutChoice_Set helpWindow = new HelpWindowBuilder()
                                          .AddMessage("Activities that you like more than average are accompanied by positive numbers.")
                                          .AddMessage("Activities that you like less than average are accompanied by negative numbers.")
                                          .AddMessage("Activities that you participated in for more total time are accompanied by numbers that are further from 0.")
                                          .AddMessage("Specifically, each of these numbers is calculated by looking at all of the participations in that activity during this time, " +
                                                      "computing the difference between the happiness of that participation and your overall average happiness, " +
                                                      "multiplying each by the duration of its participation, and adding up the results.")
                                          .Build();

            grid.AddLayout(new HelpButtonLayout("?", helpWindow, this.layoutStack));

            GridLayout_Builder bottomBuilder = new Vertical_GridLayout_Builder().Uniform();

            // Show the bottom activities, also from best to worst
            for (int i = contributions.Worst.Count - 1; i >= 0; i--)
            {
                bottomBuilder.AddLayout(this.renderContribution("bottom " + (i + 1) + ": ", contributions.Worst[i], start));
            }
            grid.AddLayout(bottomBuilder.BuildAnyLayout());

            this.layoutStack.AddLayout(grid, "Significant Activities");
        }
Example #3
0
        public FullscreenDateEntryView(string title, List <DateCharacter> dateFormat, LayoutStack layoutStack)
        {
            this.dateFormat = dateFormat;

            this.dateLayout = new TextblockLayout("");
            this.nowLayout  = new TextblockLayout("");

            dateLayout.ScoreIfEmpty = true;
            GridLayout mainGrid = GridLayout.New(new BoundProperty_List(4), new BoundProperty_List(1), LayoutScore.Zero);

            mainGrid.AddLayout(nowLayout);
            mainGrid.AddLayout(new TextblockLayout("Enter " + title + ":"));
            mainGrid.AddLayout(dateLayout);

            GridLayout buttonGrid = GridLayout.New(BoundProperty_List.Uniform(4), BoundProperty_List.Uniform(3), LayoutScore.Zero);

            buttonGrid.AddLayout(this.makeButtonNumber(1));
            buttonGrid.AddLayout(this.makeButtonNumber(2));
            buttonGrid.AddLayout(this.makeButtonNumber(3));

            buttonGrid.AddLayout(this.makeButtonNumber(4));
            buttonGrid.AddLayout(this.makeButtonNumber(5));
            buttonGrid.AddLayout(this.makeButtonNumber(6));

            buttonGrid.AddLayout(this.makeButtonNumber(7));
            buttonGrid.AddLayout(this.makeButtonNumber(8));
            buttonGrid.AddLayout(this.makeButtonNumber(9));

            LayoutChoice_Set helpWindow = new HelpWindowBuilder()
                                          .AddMessage("This screen enables you to enter " + title + " using the format " + this.getDateFormatString() + ".")
                                          .AddMessage("Press the backspace button (the '<-') to remove any incorrect characters (it will remove several at a time).")
                                          .AddMessage("Then use the keypad to enter new digits to use in the date/time.")
                                          .AddMessage("Filler characters like '-', 'T', and ':' will be automatically added for you.")
                                          .AddMessage("Press your device's Back button when finished.")
                                          .Build();

            buttonGrid.AddLayout(new HelpButtonLayout(helpWindow, layoutStack));
            buttonGrid.AddLayout(this.makeButtonNumber(0));
            buttonGrid.AddLayout(this.makeBackspaceButton());

            mainGrid.AddLayout(buttonGrid);
            this.DateText = DateText;

            this.SubLayout = mainGrid;
        }
        private LayoutChoice_Set make_helpButton(LayoutStack layoutStack)
        {
            LayoutChoice_Set helpDetails = new HelpWindowBuilder()
                                           .AddMessage("Use this screen to start an experiment.")
                                           .AddMessage("These experiments somewhat randomize the order in which you participate in certain activities, which allows you to compare your efficiency " +
                                                       "across those participations.")
                                           .AddMessage("For example, if on some nights you go to bed early and on other nights you go to bed late, experimentation can enable ActivityRecommender " +
                                                       "to measure how sleep affects your ability to quickly you get your work done.")
                                           .AddMessage("This is possible even if you don't have any two tasks of the same difficulty, because by randomizing the ordering of the tasks, after taking " +
                                                       "enough measurements, the random variations in difficulty should eventually approximately cancel each other out.")
                                           .AddMessage("What you should do first is to push each of the Suggest buttons, to create some experiment options.")
                                           .AddMessage("(You can customize the suggestions via the other fields, if you like.)")
                                           .AddMessage("Next, determine whether any of the provided suggestions are any that you are unwilling to attempt " +
                                                       "doing right now.")
                                           .AddMessage("(Note that it's ok if they're too difficult to finish in one sitting; you just need to be willing to make an attempt.)")
                                           .AddMessage("If there are any you are unwilling to attempt right now, then press the coresponding X button.")
                                           .AddMessage("Then, replace the dismissed suggestions with new suggestions, and repeat until you're satisfied.")
                                           .AddMessage("Note that like the usual suggestions screen, ActivityRecommender might make the same suggestions a few times if it's confident in its " +
                                                       "suggestion, so you may have to dismiss the same suggestion several times if you're sure that you don't want it.")
                                           .AddMessage("If you can't find " + this.numChoices + " suggestions that you're satisfied with, then at this point it's still ok to go back.")
                                           .AddMessage("Once you're satisfied with the given candidates, accept the experiment.")
                                           .AddMessage("One of the visible tasks will then be chosen randomly, and you will be instructed to work on that task until you either complete it or you " +
                                                       "give up.")
                                           .AddMessage("Note that it's very important to focus on this task so ActivityRecommender can have accurate data about how much time you actually spent on it.")
                                           .AddMessage("As a result, ActivityRecommender will not allow you to dismiss the resultant suggestion; you will have to attempt to work on it.")
                                           .AddMessage("On subsequent experiments, you may also notice that when you are deciding which activities to choose from, some of the boxes may " +
                                                       "allow you to type in exactly which activity you want to do, and some only say 'Suggest'. You're only allowed to directly enter an average of " +
                                                       "one activity suggestion per experiment (but you may cancel suggestions as many times as you want (but this may take longer)); the more " +
                                                       "activity names that you directly choose this time, the fewer that you will be allowed to directly choose next time. This is done to prevent you " +
                                                       "from accidentally ordering activities in a way such that ActivityRecommender can't analyze efficiency trends over long periods of time.")
                                           // Specifically, we want to prevent the user from finishing all of their post-tasks before creating enough new pre-tasks
                                           .AddMessage("Ready? Go!")
                                           .AddLayout(new CreditsButtonBuilder(layoutStack)
                                                      .AddContribution(ActRecContributor.CORY_JALBERT, new System.DateTime(2017, 12, 14), "Suggested adding the ability to quantify more things about yourself than just happiness")
                                                      .AddContribution(ActRecContributor.ANNI_ZHANG, new System.DateTime(2019, 11, 2), "Pointed out that the experiment screen crashed for new users")
                                                      // TODO: move this contribution inside the experiment difficulty selection screen?
                                                      .AddContribution(ActRecContributor.ANNI_ZHANG, new System.DateTime(2019, 11, 28), "Discussed the experiment difficulty selection screen and the addition of the 2*A difficulty entry")
                                                      .Build()
                                                      )
                                           .Build();

            return(new HelpButtonLayout("Important Instructions", helpDetails, layoutStack));
        }
        public MetricEditingLayout(ActivityDatabase activityDatabase, LayoutStack layoutStack)
        {
            this.activityDatabase = activityDatabase;
            this.nameBox          = new ActivityNameEntryBox("Activity", activityDatabase, layoutStack);
            Button okButton = new Button();

            okButton.Clicked       += OkButton_Clicked;
            this.metricBox          = new TitledTextbox("Metric Name");
            this.errorMessageHolder = new TextblockLayout();

            LayoutChoice_Set helpWindow = new HelpWindowBuilder()
                                          .AddMessage("This screen lets you add a Metric to an existing activity (metrics are required for running experiments).")
                                          .AddMessage("A metric is a way of measuring how well a participation accomplishes a goal.")
                                          .AddMessage("At the moment, ActivityRecommender only supports adding Metrics that classify a participation as a success or failure.")
                                          .AddMessage("(You record the success/failure status when you record having participated in the Activity)")
                                          .AddMessage("For example, if you have an Activity named Making Food, one possible metric would be 'Make 1 gallon of smoothie'.")
                                          .AddMessage("Alternatively, if you have a computer game you'd like to beat, another possible metric would be 'Beat 1 Level'.")
                                          .AddMessage("The reason you might want to create a Metric is to allow ActivityRecommender to know it can measure your effectiveness on this task.")
                                          .AddMessage("Any Activity with a Metric is eligible to take part in effectiveness experiments.")
                                          .AddMessage("Also note that any Activity of type ToDo already starts with a built-in metric, which is to complete the ToDo.")
                                          .AddMessage("Also note that any Activity that is a Problem or inherits from a Problem will receive a metric, which is to solve the Problem.")
                                          .Build();

            GridLayout mainGrid = GridLayout.New(new BoundProperty_List(4), new BoundProperty_List(1), LayoutScore.Zero);

            mainGrid.AddLayout(new TextblockLayout("Add Metric to Existing Activity"));
            mainGrid.AddLayout(new TextblockLayout("Metrics are required before running an experiment (and measuring your efficiency).", 12));
            mainGrid.AddLayout(this.errorMessageHolder);

            GridLayout bottomGrid = GridLayout.New(BoundProperty_List.Uniform(2), BoundProperty_List.Uniform(2), LayoutScore.Zero);

            bottomGrid.AddLayout(this.metricBox);
            bottomGrid.AddLayout(this.nameBox);
            bottomGrid.AddLayout(new ButtonLayout(okButton, "OK"));
            bottomGrid.AddLayout(new HelpButtonLayout(helpWindow, layoutStack));

            mainGrid.AddLayout(bottomGrid);

            this.SubLayout = mainGrid;
        }
        private ParticipationFeedback computeFeedback(Activity chosenActivity, DateTime startDate, DateTime endDate)
        {
            if (this.demanded_nextParticipationActivity != null)
            {
                if (!this.demanded_nextParticipationActivity.Matches(chosenActivity))
                {
                    string summary = "THE IRE OF THE EXPERIMENT GODS RAINS ON YOU AND YOUR BROKEN PROMISES";
                    string details = "You previously initiated an experiment where you promised that you would be willing to do " +
                                     this.demanded_nextParticipationActivity.ActivityName + ". Instead you did " + chosenActivity.Name + ". If you " +
                                     "don't follow through on your promises, then your data might be skewed in strange ways. For example, it's possible that " +
                                     "in the evening that you may choose to skip doing difficult tasks and save them for the morning. This could cause you to " +
                                     "take more time working on any individual task in the morning than in the evening, which could incorrectly suggest that " +
                                     "your efficiency is lower in the morning than in the evening.";
                    return(new ParticipationFeedback(chosenActivity, summary, false, new TextblockLayout(details)));
                }
                return(null); // no feedback for experiments
            }
            ParticipationFeedback standardFeedback = this.engine.computeStandardParticipationFeedback(chosenActivity, startDate, endDate);

            if (standardFeedback != null)
            {
                return(standardFeedback);
            }
            if (this.activityDatabase.RootActivity.NumParticipations < 20)
            {
                string summary = "You're off to a good start!";

                LayoutChoice_Set detailedLayout = new HelpWindowBuilder()
                                                  .AddMessage("Participation Feedback!")
                                                  .AddMessage("After you've entered enough data, the button on the previous screen will give you feedback about how you will feel about what you are doing.")
                                                  .AddMessage("(This may take a couple of days and requires that you give some ratings too, in the box on the left)")
                                                  .AddMessage("I have 128 different feedback messages that I know how to give!")
                                                  .AddMessage("When you press the feedback button, you will see a more detailed analysis on this screen.")
                                                  .AddMessage("Isn't that cool?")
                                                  .Build();

                return(new ParticipationFeedback(chosenActivity, summary, null, detailedLayout));
            }
            return(null);
        }
Example #7
0
        private void update()
        {
            if (this.protoActivity_database.Count < 3)
            {
                HelpWindowBuilder builder = new HelpWindowBuilder();
                int numMissing            = 3 - this.protoActivity_database.Count;
                if (this.protoActivity_database.Count > 0)
                {
                    builder.AddMessage("Not enough protoactivities! Still need " + numMissing + " more.");
                }

                builder.AddMessage("This screen will allow you to browse your ProtoActivities once you enter some.")
                .AddMessage("A ProtoActivity is a note where you brainstorm ideas, and which you may later promote into an Activity if you like.")
                .AddMessage("While you browse ProtoActivities in this screen, you will compare which ones you like more and which ones you like less " +
                            "(you will still be able to edit them, too). This allows ActivityRecommender to show you ideas that you like more often.")
                .AddMessage("This is a super easy way to save hundreds of ideas for later!")
                .AddMessage("To create a ProtoActivity, go back to the previous screen.");
                this.SubLayout = builder.Build();
            }
            else
            {
                List <ProtoActivity_EstimatedInterest> top_protoActivities = this.protoActivity_database.GetMostInteresting(2);
                this.SubLayout = this.multiActivitiesLayout;
                double numProtos = this.protoActivity_database.Count;
                this.titleLayout.setText("Protoactivity Tournament: compare 2");
                this.titleLayout.AlignHorizontally(TextAlignment.Center);

                int    numBrowses           = this.computeNumBrowses();
                double numBrowsesPerProto   = numBrowses / numProtos;
                string browsesPerProto_text = Math.Round(numBrowsesPerProto, 3).ToString();
                this.numBrowsesPerProtoactivity_Layout.setText(browsesPerProto_text + " browses per proto\n(" + numBrowses + " browses,\n" + numProtos + " protos)");

                this.setActivity1(top_protoActivities[0]);
                this.setActivity2(top_protoActivities[1]);
            }
        }
Example #8
0
        public Specify_AtLeastAsFunAs_Layout(ActivityDatabase activityDatabase, LayoutStack layoutStack)
        {
            LayoutChoice_Set helpWindow = new HelpWindowBuilder()
                                          .AddMessage("As part of making an activity request, you may specify that you want the suggested activity to be at least as fun as another activity.")
                                          .AddMessage("The reason you might do this is if you have an idea of what you might end up doing but you are hoping for ActivityRecommender to provide a better idea.")
                                          .AddMessage("If you enter an activity name into the box on this screen, then the suggestion that ActivityRecommender makes on the next screen will be " +
                                                      "one such that ActivityRecommender thinks you will have at least as much fun doing the given suggestion as you would have had doing the activity you " +
                                                      "specified on this screen.")
                                          .AddMessage("You can also specify how much fun you think you would have doing the given activity.")
                                          .AddMessage("This doesn't affect the suggestion at all, this is just for your own information.")
                                          .AddMessage("The reason you might specify how much fun you think you would have doing the given activity is that if you do end up doing the activity " +
                                                      "that you were thinking about, then you can reflect on how much fun you actually had and whether it matches how much fun you expected")
                                          .Build();
            LayoutChoice_Set helpLayout = new HelpButtonLayout(helpWindow, layoutStack);

            this.desiredActivity_box = new ActivityNameEntryBox("I want an activity at least as fun as this one:", activityDatabase, layoutStack);
            this.desiredActivity_box.Placeholder("(Optional)");
            this.desiredActivity_box.PreferSuggestibleActivities = true;

            this.estimatedRating_box = new RelativeRatingEntryView();
            this.estimatedRating_box.SetTitle("which I think will be this much fun:");

            this.SubLayout = new Vertical_GridLayout_Builder().AddLayout(helpLayout).AddLayout(this.desiredActivity_box).AddLayout(this.EstimatedRating_Box).BuildAnyLayout();
        }
        public ExperimentResultsView(Participation participation)
        {
            HelpWindowBuilder builder = new HelpWindowBuilder();

            PlannedExperiment             experiment = participation.RelativeEfficiencyMeasurement.Experiment;
            RelativeEfficiencyMeasurement earlier    = experiment.FirstParticipation.RelativeEfficiencyMeasurement;
            RelativeEfficiencyMeasurement later      = experiment.SecondParticipation.RelativeEfficiencyMeasurement;
            string earlierName = earlier.ActivityDescriptor.ActivityName;
            string laterName   = later.ActivityDescriptor.ActivityName;

            builder.AddMessage("In your experiment at " + earlier.StartDate + ", you agreed to several choices, including:");
            builder.AddMessage("A: " + earlierName);
            builder.AddMessage("B: " + laterName);

            double difficultyRatio = experiment.Earlier.DifficultyEstimate.EstimatedSuccessesPerSecond / experiment.Later.DifficultyEstimate.EstimatedSuccessesPerSecond;

            builder.AddMessage("You predicted that B would be " + this.round(difficultyRatio) + " times as difficult as A.");

            TimeSpan earlierDuration = earlier.EndDate.Subtract(earlier.StartDate);
            double   earlierMinutes  = earlierDuration.TotalMinutes;
            TimeSpan laterDuration   = later.EndDate.Subtract(later.StartDate);
            double   laterMinutes    = laterDuration.TotalMinutes;

            double earlierHelpFraction    = experiment.FirstParticipation.HelpFraction;
            string earlierHelpDescription = "";

            if (earlierHelpFraction > 0)
            {
                earlierHelpDescription = " with help, and you personally completed " + this.round(1 - earlierHelpFraction) + " of it";
            }
            builder.AddMessage("Then, you spent " + this.round(earlierDuration.TotalMinutes) + "m on A" + earlierHelpDescription);

            double laterHelpFraction    = experiment.SecondParticipation.HelpFraction;
            string laterHelpDescription = "";

            if (laterHelpFraction > 0)
            {
                laterHelpDescription = " with help, and you personally completed " + this.round(1 - laterHelpFraction) + " of it";
            }
            builder.AddMessage("Later, you spent " + this.round(laterDuration.TotalMinutes) + "m on B at " + later.StartDate + laterHelpDescription);

            double earlierTotalEffectiveness = earlier.RecomputedEfficiency.Mean * earlierMinutes / (1 - earlierHelpFraction);
            double laterTotalEffectiveness   = later.RecomputedEfficiency.Mean * laterMinutes / (1 - laterHelpFraction);

            string earlierHelpDivision = "";

            if (earlierHelpFraction > 0)
            {
                earlierHelpDivision = " / " + this.round(1 - earlierHelpFraction);
            }
            builder.AddMessage("I estimated that your efficiency on A would be about " + this.round(earlier.RecomputedEfficiency.Mean) +
                               ", making the difficulty of A be " + this.round(earlier.RecomputedEfficiency.Mean) + " * " + this.round(earlierMinutes) + "m" + earlierHelpDivision + " = " +
                               this.round(earlierTotalEffectiveness) + "m");

            builder.AddMessage("So, the difficulty of B should be " + this.round(earlierTotalEffectiveness) + "m * "
                               + this.round(difficultyRatio) + " = " + this.round(laterTotalEffectiveness) + "m");

            string laterHelpDivision = "";

            if (laterHelpFraction > 0)
            {
                laterHelpDivision = " / " + this.round(1 - laterHelpFraction);
            }
            builder.AddMessage("And your efficiency on B should be " + this.round(laterTotalEffectiveness) + "m / " +
                               this.round(laterMinutes) + "m" + laterHelpDivision + " = " + this.round(later.RecomputedEfficiency.Mean));

            builder.AddMessage("Isn't that interesting?");

            this.SubLayout = builder.Build();
        }