Exemplo n.º 1
0
        async void TurnGreen()
        {
            if (!await ShowLoseDataWarning())
            {
                return;
            }

            try
            {
                IncrementPendingRequestCount();

                await ClearData();

                // set a goal where today is the goal end date
                var goalStartDate = DateTime.Today.Date - TimeSpan.FromDays(30);
                var goalEndDate   = DateTime.Today.Date;
                var goal          = new WeightLossGoal(goalStartDate, 240, goalEndDate, 210, WeightUnitEnum.ImperialPounds);
                await DataService.SetGoal(goal);

                await DataService.AddWeightEntry(new WeightEntry(DateTime.Today.Date, 210, WeightUnitEnum.ImperialPounds));
            }
            finally
            {
                DecrementPendingRequestCount();
            }

            Close();
        }
Exemplo n.º 2
0
        public async Task Initialize(string path)
        {
#if DEBUG
            await SimulateSlowNetworkIfEnabled();
#endif

            MockGoal = new WeightLossGoal(
                startDate: new DateTime(2016, 04, 30),
                startWeight: 225.0M,
                goalDate: new DateTime(2016, 06, 08),
                goalWeight: 215.0M, units:
                WeightUnitEnum.ImperialPounds);

            MockEntries = new List <WeightEntry>();
            MockEntries.Add(new WeightEntry(new DateTime(2016, 4, 24), 234.4M, WeightUnitEnum.ImperialPounds));
            MockEntries.Add(new WeightEntry(new DateTime(2016, 4, 25), 234.3M, WeightUnitEnum.ImperialPounds));
            MockEntries.Add(new WeightEntry(new DateTime(2016, 4, 26), 234.2M, WeightUnitEnum.ImperialPounds));
            MockEntries.Add(new WeightEntry(new DateTime(2016, 4, 27), 234.1M, WeightUnitEnum.ImperialPounds));
            MockEntries.Add(new WeightEntry(new DateTime(2016, 4, 28), 234.0M, WeightUnitEnum.ImperialPounds));
            MockEntries.Add(new WeightEntry(new DateTime(2016, 4, 29), 233.9M, WeightUnitEnum.ImperialPounds));
            MockEntries.Add(new WeightEntry(new DateTime(2016, 4, 30), 233.8M, WeightUnitEnum.ImperialPounds));
            MockEntries.Add(new WeightEntry(new DateTime(2016, 5, 1), 233.7M, WeightUnitEnum.ImperialPounds));
            MockEntries.Add(new WeightEntry(new DateTime(2016, 5, 2), 233.6M, WeightUnitEnum.ImperialPounds));
            MockEntries.Add(new WeightEntry(new DateTime(2016, 5, 3), 233.5M, WeightUnitEnum.ImperialPounds));
            MockEntries.Add(new WeightEntry(new DateTime(2016, 5, 4), 233.4M, WeightUnitEnum.ImperialPounds));
            MockEntries.Add(new WeightEntry(new DateTime(2016, 5, 5), 233.3M, WeightUnitEnum.ImperialPounds));

            HasBeenInitialized = true;
            FireUserDataUpdated();
        }
        static decimal GetGoalWeightForDate(WeightLossGoal goal, DateTime date)
        {
            // make sure we have a goal set first
            if (goal == null)
            {
                throw new InvalidOperationException($"{nameof(GetGoalWeightForDate)} was passed in a null goal.");
            }

            // if the date requested is before the goal start, then return the goal start weight
            if (date.Date <= goal.StartDate.Date)
            {
                return(goal.StartWeight);
            }

            // if the date requested is after the goal end, then return the goal end weight
            if (date.Date >= goal.GoalDate.Date)
            {
                return(goal.GoalWeight);
            }

            // NOTE:: calculation is: ((y2 - y1) / diet length in days) * days elapsed + y1
            // NOTE:: calculation is: start weight - ((start weight - end weight) / diet length in days) * days elapsed

            decimal  weightDiff = goal.StartWeight - goal.GoalWeight;
            TimeSpan duration   = goal.GoalDate.Date - goal.StartDate.Date;
            TimeSpan elapsed    = date - goal.StartDate.Date;

            var goalWeightForDate = goal.StartWeight - ((weightDiff / (decimal)duration.TotalDays) * (decimal)elapsed.TotalDays);

            return(goalWeightForDate);
        }
Exemplo n.º 4
0
        async void TestLargeDataSet()
        {
            if (!await ShowLoseDataWarning())
            {
                return;
            }

            try
            {
                IncrementPendingRequestCount();

                await ClearData();

                // set goal
                var goal = new WeightLossGoal(new DateTime(2017, 1, 1), 200, new DateTime(2017, 7, 1), 200, WeightUnitEnum.ImperialPounds);
                await DataService.SetGoal(goal);

                // add some weights
                DateTime date   = new DateTime(2017, 3, 29);
                TimeSpan day    = TimeSpan.FromDays(1);
                Random   random = new Random();
                for (int i = 0; i < 1000; i++)
                {
                    date = date - day;
                    var weightEntry = new WeightEntry(date, 200 + (decimal)(random.NextDouble() * 10) - 5, WeightUnitEnum.ImperialPounds);
                    await DataService.AddWeightEntry(weightEntry);
                }
            }
            finally
            {
                DecrementPendingRequestCount();
            }

            Close();
        }
        public static InfoForToday GetTodaysDisplayInfo(WeightLossGoal goal, WeightEntry todaysWeightEntry)
        {
            var infoForToday = new InfoForToday();

            infoForToday.TodaysDisplayWeight = (todaysWeightEntry != null) ? todaysWeightEntry.ToString() : Constants.Strings.DailyInfoPage_UnknownWeight;

            if (goal == null)
            {
                infoForToday.IsEnterWeightButtonVisible = false;
                infoForToday.IsSetGoalButtonVisible     = true;
            }
            else if (todaysWeightEntry == null)
            {
                infoForToday.IsEnterWeightButtonVisible = true;
                infoForToday.IsSetGoalButtonVisible     = false;
            }

            infoForToday.TodaysMessage = GetTodaysMessageFromWeight(todaysWeightEntry, goal); // ok that either may be null

            // if they haven't set a goal, or don't have a weight today, or today is the first day of the diet, then we don't
            // want to colorize the screen or show the HowToEat information below their weight
            if (goal != null && todaysWeightEntry != null && goal.StartDate.Date != DateTime.Today.Date)
            {
                // update the window color if we have a weight for today and know their goal
                decimal goalWeightForToday = GetGoalWeightForDate(goal, DateTime.Today.Date);
                bool    onADiet            = todaysWeightEntry.Weight > goalWeightForToday;
                infoForToday.ColorToShow     = onADiet ? BaseColorEnum.Red : BaseColorEnum.Green;
                infoForToday.HowToEatMessage = onADiet ? Constants.Strings.DailyInfoPage_HowToEat_OnDiet : Constants.Strings.DailyInfoPage_HowToEat_OffDiet;
            }

            return(infoForToday);
        }
Exemplo n.º 6
0
        public async Task <bool> SetGoal(WeightLossGoal weightLossGoal)
        {
#if DEBUG
            await SimulateSlowNetworkIfEnabled();
#endif

            MockGoal = weightLossGoal;
            FireUserDataUpdated();

            return(true);
        }
        // NOTE:: either of the parameters could be null if they are not yet entered
        static string GetTodaysMessageFromWeight(WeightEntry todaysEntry, WeightLossGoal goal)
        {
            // if they haven't set a goal
            if (goal == null)
            {
                return(Constants.Strings.DailyInfoPage_TodaysMessage_NoGoal);
            }

            // if they started the goal today
            if (goal.StartDate.Date == DateTime.Today.Date)
            {
                return(Constants.Strings.DailyInfoPage_TodaysMessage_NewGoal);
            }

            // if they haven't entered today's weight yet
            if (todaysEntry == null)
            {
                return(Constants.Strings.DailyInfoPage_TodaysMessage_NoWeightToday);
            }

            decimal todaysGoalWeight = GetGoalWeightForDate(goal, DateTime.Today.Date);
            int     daysToGo         = (int)(Math.Floor((goal.GoalDate.Date - DateTime.Today.Date).TotalDays));

            // they have reached their goal weight (could be before or after the goal date, we show same message either way)
            if (todaysEntry.Weight <= goal.GoalWeight)
            {
                return(Constants.Strings.DailyInfoPage_GoalEnd_Success);
            }

            // they've reached the goal date, show success/failure
            if (daysToGo <= 0)
            {
                return((todaysEntry.Weight <= todaysGoalWeight) ?
                       Constants.Strings.DailyInfoPage_GoalEnd_Success :
                       Constants.Strings.DailyInfoPage_GoalEnd_Failure);
            }

            // they are still working towards a goal, show a summary of their progress
            var amountLost      = goal.StartWeight - todaysEntry.Weight;
            var amountRemaining = Math.Max(todaysEntry.Weight - goal.GoalWeight, 0); // prevent from going negative
            int daysSinceStart  = (int)(Math.Floor((DateTime.Today.Date - goal.StartDate.Date).TotalDays));

            // ex: You have [lost/gained] [XX.X] [pounds/kilograms] since starting on your current goal [XX] days ago. You have [XX] days left to lose a remaining [XX.X] pounds. [You can do it!/Keep up the good work!]
            // NOTE: we don't want to say "-1.2 gained" so we always make sure what we display is positive
            string gainedLost = (amountLost < 0) ? Constants.Strings.DailyInfoPage_Summary_Gained : Constants.Strings.DailyInfoPage_Summary_Lost;
            string endingText = (todaysEntry.Weight <= todaysGoalWeight) ? Constants.Strings.DailyInfoPage_SummaryEnding_OnTrack : Constants.Strings.DailyInfoPage_SummaryEnding_OffTrack;

            return(string.Format(Constants.Strings.DailyInfoPage_ProgressSummary,
                                 gainedLost, Math.Abs(amountLost), Constants.Strings.Common_WeightUnit, daysSinceStart,
                                 daysToGo, amountRemaining, endingText));
        }
        async Task <bool> ShowWelcomeFlowIfNeeded()
        {
            // check if they have seen the getting started flow yet or don't have a goal
            WeightLossGoal existingGoal = null;

            try
            {
                IncrementPendingRequestCount();

                existingGoal = await DataService.GetGoal();
            }
            catch (Exception ex)
            {
                AnalyticsService.TrackFatalError($"{nameof(ShowWelcomeFlowIfNeeded)} - an exception occurred.", ex);
                // NOTE:: not showing an error here as this is not in response to user action. potentially should show a non-intrusive error banner
                return(false);
            }
            finally
            {
                DecrementPendingRequestCount(); // hide loading
            }

            bool showGettingStartedFlow = (existingGoal == null && !SettingsService.HasDismissedStartupView);

#if DEBUG
            if (Constants.App.DEBUG_AlwaysShowGettingStarted)
#pragma warning disable CS0162 // Unreachable code detected
            {
                showGettingStartedFlow = true;
            }
#pragma warning restore CS0162 // Unreachable code detected
#endif

            if (showGettingStartedFlow)
            {
                AnalyticsService.TrackEvent(Constants.Analytics.DailyInfoCategory, Constants.Analytics.DailyInfo_LaunchingGettingStarted, 1);

                SettingsService.HasDismissedStartupView = true; // don't put them in this flow again

                await Task.Delay(500);                          // slight delay before fly-up modal so they see the context of the app before it appears

                await NavigationService.NavigateAsync($"{nameof(NavigationPage)}/{nameof(GettingStartedPage)}", useModalNavigation : true);

                return(true);
            }

            return(false);
        }
        public static bool WeightMetGoalOnDate(WeightLossGoal goal, DateTime dt, decimal weightOnDate)
        {
            if (goal == null)
            {
                return(false);
            }

            if (weightOnDate == decimal.MinValue)
            {
                return(false);
            }

            var goalWeightForDate = GetGoalWeightForDate(goal, dt.Date);

            return(weightOnDate <= goalWeightForDate);
        }
        async void TestEndingAGoal()
        {
            if (!await ShowLoseDataWarning())
            {
                return;
            }

            try
            {
                IncrementPendingRequestCount();

                await ClearData();

                // set a goal where today is the goal end date
                var goalStartDate = DateTime.Today.Date - TimeSpan.FromDays(30);
                var goalEndDate   = DateTime.Today.Date;
                var goal          = new WeightLossGoal(goalStartDate, 240, goalEndDate, 210);
                await DataService.SetGoal(goal);

                // add some weights
                await DataService.AddWeightEntry(new WeightEntry(goalStartDate + TimeSpan.FromDays(5), 235));

                await DataService.AddWeightEntry(new WeightEntry(goalStartDate + TimeSpan.FromDays(10), 230));

                await DataService.AddWeightEntry(new WeightEntry(goalStartDate + TimeSpan.FromDays(15), 225));

                await DataService.AddWeightEntry(new WeightEntry(goalStartDate + TimeSpan.FromDays(20), 220));

                await DataService.AddWeightEntry(new WeightEntry(goalStartDate + TimeSpan.FromDays(25), 215));
            }
            finally
            {
                DecrementPendingRequestCount();
            }

            Close();
        }
Exemplo n.º 11
0
        public async Task <bool> SetGoal(WeightLossGoal weightLossGoal)
        {
#if DEBUG
            await SimulateSlowNetworkIfEnabled();
#endif

            // delete anything existing goal
            if (!await RemoveGoal())
            {
                FireUserDataUpdated();
                return(false);
            }

            var result = await _connection.InsertAsync(weightLossGoal);

            if (result != 1)
            {
                FireUserDataUpdated();
                return(false);
            }

            FireUserDataUpdated();
            return(true);
        }
        void RefreshGraphDataModel(List <WeightEntry> entries, WeightLossGoal goal)
        {
            // TODO:: FUTURE:: does all of this have to be done for each refresh? could the axis's be re-used and just
            // have the data points repopulated?
            var      dateRange      = WeightLogicHelpers.GetGraphDateRange(entries);
            DateTime dateRangeStart = dateRange.Item1;
            DateTime dateRangeEnd   = dateRange.Item2;

            var     weightRange    = WeightLogicHelpers.GetMinMaxWeightRange(goal, entries, dateRangeStart, dateRangeEnd);
            decimal minGraphWeight = weightRange.Item1;
            decimal maxGraphWeight = weightRange.Item2;

            // OxyPlot
            var plotModel = new PlotModel(); //  { Title = "OxyPlot Demo" };

            plotModel.IsLegendVisible     = false;
            plotModel.PlotAreaBorderColor = GRID_LINES_COLOR_BORDER;

            // NOTE:: it is assumed the date will always be the first axes in the AxisChanged wiring/un-wiring as that is used
            // to adjust line markers to show months instead of weeks at a certain zoom level

            // XAxis - dates
            plotModel.Axes.Add(
                new DateTimeAxis
            {
                Position           = AxisPosition.Bottom,
                Minimum            = DateTimeAxis.ToDouble(dateRangeStart),
                Maximum            = DateTimeAxis.ToDouble(dateRangeEnd),
                AxislineColor      = OxyColors.White,
                TicklineColor      = OxyColors.White,
                MajorGridlineColor = GRID_LINES_COLOR_MAJOR,
                MinorGridlineColor = GRID_LINES_COLOR_MINOR,
                AxislineStyle      = LineStyle.Solid,
                TextColor          = OxyColors.White,
                TickStyle          = TickStyle.Outside,
                MajorGridlineStyle = LineStyle.Solid,
                MinorGridlineStyle = LineStyle.Solid,
                MinorIntervalType  = DateTimeIntervalType.Days,
                IntervalType       = DateTimeIntervalType.Days,
                MinorStep          = WeekScale_MinorStep,
                MajorStep          = WeekScale_MajorStep,                     // a week
                StringFormat       = WeekScale_AxisFormat,                    // TODO:: FUTURE:: make swap for some cultures?
                IsZoomEnabled      = true,
                MinimumRange       = Constants.App.Graph_MinDateRangeVisible, // closest zoom in shows at least 5 days
                MaximumRange       = Constants.App.Graph_MaxDateRangeVisible, // furthest zoom out shows at most 1 year
            });

            // YAxis - weights
            plotModel.Axes.Add(
                new LinearAxis
            {
                Position           = AxisPosition.Left,
                Minimum            = (double)minGraphWeight,
                Maximum            = (double)maxGraphWeight,
                AxislineColor      = OxyColors.White,
                TicklineColor      = OxyColors.White,
                MajorGridlineColor = GRID_LINES_COLOR_MAJOR,
                MinorGridlineColor = GRID_LINES_COLOR_MINOR,
                AxislineStyle      = LineStyle.Solid,
                TextColor          = OxyColors.White,
                TickStyle          = TickStyle.Outside,
                MajorGridlineStyle = LineStyle.Solid,
                MinorGridlineStyle = LineStyle.Solid,
                MinorStep          = 1,
                MajorStep          = 5,
                IsZoomEnabled      = true,
                MinimumRange       = Constants.App.Graph_MinWeightRangeVisible, // closest zoom in shows at least 5 pounds
                MaximumRange       = Constants.App.Graph_MaxWeightRangeVisible  // furthest zoom out shows at most 100 pounds
            });

            var series1 = new LineSeries
            {
                MarkerType            = MarkerType.Circle,
                MarkerSize            = 4,
                MarkerStroke          = OxyColors.White,
                MarkerFill            = OxyColors.White,
                StrokeThickness       = 4,
                MarkerStrokeThickness = 1,
                Color = OxyColors.White
            };

            foreach (var entry in entries)
            {
                series1.Points.Add(new DataPoint(DateTimeAxis.ToDouble(entry.Date), Decimal.ToDouble(entry.Weight)));
            }

            plotModel.Series.Clear();
            plotModel.Series.Add(series1);

            // setup goal line
            if (goal != null)
            {
                var series2 = new LineSeries
                {
                    MarkerType = MarkerType.None,
                    LineStyle  = LineStyle.Dash,
                    Color      = OxyColors.White
                };

                // diet line

                // we want to extend the goal line at least 30 days past the end of the goal and extend it further if they are already past
                // the goal date (ex: they are 90 days past goal end date and just using the line for maintenance)
                var goalExtendedDate = goal.GoalDate + TimeSpan.FromDays(30);
                if (DateTime.Today.Date > goalExtendedDate)
                {
                    goalExtendedDate = DateTime.Today.Date + TimeSpan.FromDays(30);
                }

                series2.Points.Add(new DataPoint(DateTimeAxis.ToDouble(goal.StartDate - TimeSpan.FromDays(30)), (double)goal.StartWeight));
                series2.Points.Add(new DataPoint(DateTimeAxis.ToDouble(goal.StartDate), (double)goal.StartWeight));
                series2.Points.Add(new DataPoint(DateTimeAxis.ToDouble(goal.GoalDate), (double)goal.GoalWeight));
                series2.Points.Add(new DataPoint(DateTimeAxis.ToDouble(goalExtendedDate), (double)goal.GoalWeight));

                plotModel.Series.Add(series2);
            }

            UnwireDateAxisChangedEvent(); // unwire any previous event handlers for axis zoom changing
            PlotModel = plotModel;
            PlotModel.Axes[0].AxisChanged += DateAxis_Changed;
        }
        async void Save()
        {
            AnalyticsService.TrackEvent(Constants.Analytics.SetGoalCategory, Constants.Analytics.SetGoal_SavedGoal, 1);

            // convert entered value to a valid weight
            decimal startWeight, goalWeight;

            if (!decimal.TryParse(StartWeight, out startWeight) || !decimal.TryParse(GoalWeight, out goalWeight))
            {
                // show error about invalid value if we can't convert the entered value to a decimal
                await DialogService.DisplayAlertAsync(Constants.Strings.SetGoalPage_InvalidWeight_Title,
                                                      Constants.Strings.SetGoalPage_InvalidWeight_Message,
                                                      Constants.Strings.GENERIC_OK);

                return;
            }

            // give warning if goal weight is greater than start weight
            // NOTE:: we don't prevent this scenario as I have had friends intentionally use the previous version of line diet for
            // tracking weight gain during pregnancy or muscle building - so we just give a warning. We also don't prevent equal
            // start and goal weights in case they just want a line to show a maintenance weight they are trying to stay at
            if (goalWeight > startWeight)
            {
                await DialogService.DisplayAlertAsync(Constants.Strings.SetGoalPage_GoalWeightGreaterThanStartWeight_Title,
                                                      Constants.Strings.SetGoalpage_GoalWeightGreaterThanStartWeight_Message,
                                                      Constants.Strings.GENERIC_OK);
            }

            try
            {
                IncrementPendingRequestCount();

                // see if they've entered a different weight already for this date, if so warn them about it being updated
                var existingWeight = await DataService.GetWeightEntryForDate(StartDate);

                if (existingWeight != null)
                {
                    if (existingWeight.Weight != startWeight)
                    {
                        // show warning that an existing entry will be updated (is actually deleted and re-added), allow them to cancel
                        var result = await DialogService.DisplayAlertAsync(Constants.Strings.Common_UpdateExistingWeight_Title,
                                                                           string.Format(Constants.Strings.Common_UpdateExistingWeight_Message, existingWeight.Weight, StartDate, startWeight),
                                                                           Constants.Strings.GENERIC_OK,
                                                                           Constants.Strings.GENERIC_CANCEL);

                        // if they canceled the dialog then return without changing anything
                        if (!result)
                        {
                            return;
                        }
                    }

                    // remove existing weight
                    if (!await DataService.RemoveWeightEntryForDate(StartDate))
                    {
                        AnalyticsService.TrackError($"{nameof(Save)} - Error when trying to remove existing weight entry for start date");

                        await DialogService.DisplayAlertAsync(Constants.Strings.Common_SaveError,
                                                              Constants.Strings.SetGoalPage_Save_RemoveExistingWeightFailed_Message, Constants.Strings.GENERIC_OK);

                        return;
                    }
                }

                var addStartWeightResult = await DataService.AddWeightEntry(new WeightEntry(StartDate, startWeight));

                if (!addStartWeightResult)
                {
                    AnalyticsService.TrackError($"{nameof(Save)} - Error when trying to add weight entry for start date");

                    await DialogService.DisplayAlertAsync(Constants.Strings.Common_SaveError,
                                                          Constants.Strings.SetGoalPage_Save_AddingWeightFailed_Message, Constants.Strings.GENERIC_OK);

                    return;
                }

                var weightLossGoal = new WeightLossGoal(StartDate, startWeight, GoalDate.Date, goalWeight);
                if (!await DataService.SetGoal(weightLossGoal))
                {
                    AnalyticsService.TrackError($"{nameof(Save)} - Error when trying to save new weight loss goal");

                    await DialogService.DisplayAlertAsync(Constants.Strings.Common_SaveError,
                                                          Constants.Strings.SetGoalPage_Save_AddingGoalFailed_Message, Constants.Strings.GENERIC_OK);

                    return;
                }

                await NavigationService.GoBackAsync(useModalNavigation : true);
            }
            catch (Exception ex)
            {
                AnalyticsService.TrackFatalError($"{nameof(Save)} - an exception occurred.", ex);

                await DialogService.DisplayAlertAsync(Constants.Strings.Common_SaveError,
                                                      Constants.Strings.SetGoalPage_Save_Exception_Message, Constants.Strings.GENERIC_OK);
            }
            finally
            {
                DecrementPendingRequestCount();
            }
        }
Exemplo n.º 14
0
        async void Save()
        {
            AnalyticsService.TrackEvent(Constants.Analytics.SetGoalCategory, Constants.Analytics.SetGoal_SavedGoal, 1);

            // convert entered value to a valid weight
            bool    parsedWeightFields = true;
            decimal startWeight        = 0;
            decimal goalWeight         = 0;

            if (ShowStonesEntryFields)
            {
                var startWeightStoneFields = GetStartWeightInStones();
                var goalWeightStoneFields  = GetGoalWeightInStones();

                if (startWeightStoneFields == null || goalWeightStoneFields == null)
                {
                    parsedWeightFields = false;
                }
                else
                {
                    startWeight = startWeightStoneFields.ToPoundsDecimal();
                    goalWeight  = goalWeightStoneFields.ToPoundsDecimal();
                }
            }
            else
            {
                if (!decimal.TryParse(StartWeight, NumberStyles.AllowDecimalPoint, CultureInfo.CurrentCulture, out startWeight) ||
                    !decimal.TryParse(GoalWeight, NumberStyles.AllowDecimalPoint, CultureInfo.CurrentCulture, out goalWeight))
                {
                    parsedWeightFields = false;
                }
            }

            if (!parsedWeightFields)
            {
                // show error about invalid value if we can't convert the entered value to a decimal
                await DialogService.DisplayAlertAsync(Constants.Strings.SetGoalPage_InvalidWeight_Title,
                                                      Constants.Strings.SetGoalPage_InvalidWeight_Message,
                                                      Constants.Strings.Generic_OK);

                return;
            }

            // give warning if goal weight is greater than start weight
            // NOTE:: we don't prevent this scenario as I have had friends intentionally use the previous version of line diet for
            // tracking weight gain during pregnancy or muscle building - so we just give a warning. We also don't prevent equal
            // start and goal weights in case they just want a line to show a maintenance weight they are trying to stay at
            if (goalWeight > startWeight)
            {
                // TODO:: analytics
                var result = await DialogService.DisplayAlertAsync(Constants.Strings.SetGoalPage_GoalWeightGreaterThanStartWeight_Title,
                                                                   Constants.Strings.SetGoalpage_GoalWeightGreaterThanStartWeight_Message,
                                                                   Constants.Strings.Generic_OK, Constants.Strings.Generic_Cancel);

                if (!result)
                {
                    return;
                }
            }

            try
            {
                IncrementPendingRequestCount();

                // see if they've entered a different weight already for this date, if so warn them about it being updated
                var existingEntry = await DataService.GetWeightEntryForDate(StartDate);

                if (existingEntry != null)
                {
                    if (existingEntry.Weight != startWeight)
                    {
                        // show different message for stones/pounds
                        string warningMessage;
                        if (ShowStonesEntryFields)
                        {
                            var existingWeightInStones = existingEntry.Weight.ToStonesAndPounds();
                            var startWeightInStones    = startWeight.ToStonesAndPounds();

                            warningMessage = string.Format(Constants.Strings.Common_UpdateExistingWeight_Message,
                                                           string.Format(Constants.Strings.Common_Stones_WeightFormat, existingWeightInStones.Stones, existingWeightInStones.Pounds),
                                                           StartDate,
                                                           string.Format(Constants.Strings.Common_Stones_WeightFormat, startWeightInStones.Stones, startWeightInStones.Pounds));
                        }
                        else
                        {
                            warningMessage = string.Format(Constants.Strings.Common_UpdateExistingWeight_Message, existingEntry.Weight, StartDate, startWeight);
                        }

                        // show warning that an existing entry will be updated (is actually deleted and re-added), allow them to cancel
                        var result = await DialogService.DisplayAlertAsync(Constants.Strings.Common_UpdateExistingWeight_Title, warningMessage,
                                                                           Constants.Strings.Generic_OK,
                                                                           Constants.Strings.Generic_Cancel);

                        // if they canceled the dialog then return without changing anything
                        if (!result)
                        {
                            return;
                        }
                    }

                    // remove existing weight
                    if (!await DataService.RemoveWeightEntryForDate(StartDate))
                    {
                        AnalyticsService.TrackError($"{nameof(Save)} - Error when trying to remove existing weight entry for start date");

                        await DialogService.DisplayAlertAsync(Constants.Strings.Common_SaveError,
                                                              Constants.Strings.SetGoalPage_Save_RemoveExistingWeightFailed_Message, Constants.Strings.Generic_OK);

                        return;
                    }
                }

                var addStartWeightResult = await DataService.AddWeightEntry(new WeightEntry(StartDate, startWeight, SettingsService.WeightUnit));

                if (!addStartWeightResult)
                {
                    AnalyticsService.TrackError($"{nameof(Save)} - Error when trying to add weight entry for start date");

                    await DialogService.DisplayAlertAsync(Constants.Strings.Common_SaveError,
                                                          Constants.Strings.SetGoalPage_Save_AddingWeightFailed_Message, Constants.Strings.Generic_OK);

                    return;
                }

                var weightLossGoal = new WeightLossGoal(StartDate, startWeight, GoalDate.Date, goalWeight, SettingsService.WeightUnit);
                if (!await DataService.SetGoal(weightLossGoal))
                {
                    AnalyticsService.TrackError($"{nameof(Save)} - Error when trying to save new weight loss goal");

                    await DialogService.DisplayAlertAsync(Constants.Strings.Common_SaveError,
                                                          Constants.Strings.SetGoalPage_Save_AddingGoalFailed_Message, Constants.Strings.Generic_OK);

                    return;
                }

                await NavigationService.GoBackAsync(useModalNavigation : true);
            }
            catch (Exception ex)
            {
                AnalyticsService.TrackFatalError($"{nameof(Save)} - an exception occurred.", ex);

                await DialogService.DisplayAlertAsync(Constants.Strings.Common_SaveError,
                                                      Constants.Strings.SetGoalPage_Save_Exception_Message, Constants.Strings.Generic_OK);
            }
            finally
            {
                DecrementPendingRequestCount();
            }
        }
Exemplo n.º 15
0
        // NOTE:: primarily used for screenshots, is based on specific dates
        async void TestRealDataSet()
        {
            if (!await ShowLoseDataWarning())
            {
                return;
            }

            try
            {
                IncrementPendingRequestCount();

                await ClearData();

                // set goal
                var goal = new WeightLossGoal(new DateTime(2017, 1, 1), 237.4M, new DateTime(2017, 7, 1), 200, WeightUnitEnum.ImperialPounds);
                await DataService.SetGoal(goal);

                // add some weights
                await DataService.AddWeightEntry(new WeightEntry(new DateTime(2017, 1, 1), 237.4M, WeightUnitEnum.ImperialPounds));

                await DataService.AddWeightEntry(new WeightEntry(new DateTime(2017, 1, 17), 235.2M, WeightUnitEnum.ImperialPounds));

                await DataService.AddWeightEntry(new WeightEntry(new DateTime(2017, 2, 4), 233.0M, WeightUnitEnum.ImperialPounds));

                await DataService.AddWeightEntry(new WeightEntry(new DateTime(2017, 2, 22), 230.8M, WeightUnitEnum.ImperialPounds));

                await DataService.AddWeightEntry(new WeightEntry(new DateTime(2017, 2, 27), 229.4M, WeightUnitEnum.ImperialPounds));

                await DataService.AddWeightEntry(new WeightEntry(new DateTime(2017, 2, 28), 228.6M, WeightUnitEnum.ImperialPounds));

                await DataService.AddWeightEntry(new WeightEntry(new DateTime(2017, 3, 1), 228.2M, WeightUnitEnum.ImperialPounds));

                await DataService.AddWeightEntry(new WeightEntry(new DateTime(2017, 3, 2), 227.0M, WeightUnitEnum.ImperialPounds));

                await DataService.AddWeightEntry(new WeightEntry(new DateTime(2017, 3, 3), 226.4M, WeightUnitEnum.ImperialPounds));

                await DataService.AddWeightEntry(new WeightEntry(new DateTime(2017, 3, 4), 227.0M, WeightUnitEnum.ImperialPounds));

                await DataService.AddWeightEntry(new WeightEntry(new DateTime(2017, 3, 5), 227.2M, WeightUnitEnum.ImperialPounds));

                await DataService.AddWeightEntry(new WeightEntry(new DateTime(2017, 3, 6), 226.0M, WeightUnitEnum.ImperialPounds));

                await DataService.AddWeightEntry(new WeightEntry(new DateTime(2017, 3, 7), 225.4M, WeightUnitEnum.ImperialPounds));

                await DataService.AddWeightEntry(new WeightEntry(new DateTime(2017, 3, 8), 225.4M, WeightUnitEnum.ImperialPounds));

                await DataService.AddWeightEntry(new WeightEntry(new DateTime(2017, 3, 9), 225.2M, WeightUnitEnum.ImperialPounds));

                await DataService.AddWeightEntry(new WeightEntry(new DateTime(2017, 3, 10), 225.8M, WeightUnitEnum.ImperialPounds));

                await DataService.AddWeightEntry(new WeightEntry(new DateTime(2017, 3, 11), 225.2M, WeightUnitEnum.ImperialPounds));

                await DataService.AddWeightEntry(new WeightEntry(new DateTime(2017, 3, 12), 223.8M, WeightUnitEnum.ImperialPounds));

                await DataService.AddWeightEntry(new WeightEntry(new DateTime(2017, 3, 13), 223.5M, WeightUnitEnum.ImperialPounds));

                await DataService.AddWeightEntry(new WeightEntry(new DateTime(2017, 3, 14), 223.0M, WeightUnitEnum.ImperialPounds));

                await DataService.AddWeightEntry(new WeightEntry(new DateTime(2017, 3, 15), 221.8M, WeightUnitEnum.ImperialPounds));

                await DataService.AddWeightEntry(new WeightEntry(new DateTime(2017, 3, 16), 221.6M, WeightUnitEnum.ImperialPounds));

                await DataService.AddWeightEntry(new WeightEntry(new DateTime(2017, 3, 17), 221.4M, WeightUnitEnum.ImperialPounds));
            }
            finally
            {
                DecrementPendingRequestCount();
            }

            Close();
        }
        public static Tuple <decimal, decimal> GetMinMaxWeightRange(WeightLossGoal goal, List <WeightEntry> entries, DateTime dateStart, DateTime dateEnd)
        {
            if (entries.Count == 0)
            {
                if (goal != null)
                {
                    // there should normally be at least one weight if a goal is set, there is nothing really to graph but the goal line itself
                    return(new Tuple <decimal, decimal>(goal.GoalWeight - Constants.App.Graph_GoalOnly_Padding,
                                                        goal.GoalWeight + Constants.App.Graph_GoalOnly_Padding));
                }

                // no goal set and no saved weights, so just graph a default range
                return(new Tuple <decimal, decimal>(Constants.App.Graph_WeightRange_DefaultMin, Constants.App.Graph_WeightRange_DefaultMax));
            }

            decimal minValue = decimal.MaxValue;
            decimal maxValue = decimal.MinValue;

            // if there is a goal set then we want to include that line for the date range we're looking at
            if (goal != null)
            {
                // now see if our goal is greater/less for start end dates, if so include those in the range
                decimal goalStart = GetGoalWeightForDate(goal, dateStart);
                if (goalStart != decimal.MinValue)
                {
                    if (goalStart < minValue)
                    {
                        minValue = goalStart;
                    }
                    if (goalStart > maxValue)
                    {
                        maxValue = goalStart;
                    }
                }

                decimal goalEnd = GetGoalWeightForDate(goal, dateEnd);
                if (goalEnd != decimal.MinValue)
                {
                    if (goalEnd < minValue)
                    {
                        minValue = goalEnd;
                    }
                    if (goalEnd > maxValue)
                    {
                        maxValue = goalEnd;
                    }
                }
            }

            foreach (var entry in entries)
            {
                if (entry.Weight < minValue)
                {
                    minValue = (decimal)entry.Weight;
                }
                if (entry.Weight > maxValue)
                {
                    maxValue = (decimal)entry.Weight;
                }
            }

            minValue = minValue * Constants.App.Graph_WeightRange_MinPadding;
            maxValue = maxValue * Constants.App.Graph_WeightRange_MaxPadding;

            minValue = (decimal)Math.Floor(minValue); // use whole numbers
            maxValue = (decimal)Math.Ceiling(maxValue);

            return(new Tuple <decimal, decimal>(minValue, maxValue));
        }