예제 #1
0
 public DateTime CalculateLowerCutoffTime(Goal goal, decimal oldCurrentLevel, DateTime previousDoneItTime)
 {
     var hourdecr = GoalProcessor.GetHourlyDecreaseRate(goal);
     var lowerCutoff = goal.GetLowerCutoff();
     var hours = (oldCurrentLevel - lowerCutoff) / hourdecr;
     return previousDoneItTime.AddHours(Math.Abs(Convert.ToDouble(hours)));
 }
예제 #2
0
        public void it_should_calculate_correct_hours_left_to_zero()
        {
            var now = DateTime.Now;
            var target = new GoalProcessor(now);
            var goal = new Goal() { Amount = 7, IntervalType = IntervalType.Weekly };

            // Week
            goal.DoneIts = new List<DoneIt>() { new DoneIt() { Amount = 7.01M, Date = now.AddDays(-7) } };
            var vm = target.ProcessGoal(goal);
            Assert.AreEqual(GoalStatus.OnTrack, vm.Status);

            goal.DoneIts = new List<DoneIt>(){ new DoneIt() { Amount = 6.99M, Date = now.AddDays(-7) }};
            vm = target.ProcessGoal(goal);
            Assert.AreEqual(GoalStatus.Behind, vm.Status);

            // Hour
            goal = new Goal() { Amount = 24, IntervalType = IntervalType.Dayly };
            goal.DoneIts = new List<DoneIt>() { new DoneIt() { Amount = 24.01M, Date = now.AddDays(-1) } };
            vm = target.ProcessGoal(goal);
            Assert.AreEqual(GoalStatus.OnTrack, vm.Status);

            goal.DoneIts = new List<DoneIt>() { new DoneIt() { Amount = 23.99M, Date = now.AddDays(-1) } };
            vm = target.ProcessGoal(goal);
            Assert.AreEqual(GoalStatus.Behind, vm.Status);

            // Month
            goal = new Goal() { Amount = 3, IntervalType = IntervalType.Monthly };
            goal.DoneIts = new List<DoneIt>() { new DoneIt() { Amount = 3.01M, Date = now.AddDays(-30) } };
            vm = target.ProcessGoal(goal);
            Assert.AreEqual(GoalStatus.OnTrack, vm.Status);

            goal.DoneIts = new List<DoneIt>() { new DoneIt() { Amount = 2.99M, Date = now.AddDays(-30) } };
            vm = target.ProcessGoal(goal);
            Assert.AreEqual(GoalStatus.Behind, vm.Status);
        }
예제 #3
0
        public void it_should_build_a_flat_zero_line_if_no_donits()
        {
            var now = DateTime.Now;
            var target = new GoalProcessor(now);
            var goal = new Goal() { IntervalType = IntervalType.Weekly };

            var vm= target.ProcessGoal(goal);
            Assert.AreEqual(vm.Graph.Points.Count, 2);
        }
예제 #4
0
        public void it_should_set_value_of_first_point_to_the_amount_the_first_doneit()
        {
            var now = DateTime.Now;
            var target = new GoalProcessor(now);
            var goal = new Goal() { Amount = 7, IntervalType = IntervalType.Weekly };

            goal.DoneIts = new List<DoneIt>() { new DoneIt() { Amount = 10, Date = now.AddDays(-2) } };
            var vm = target.ProcessGoal(goal);
            Assert.AreEqual(10, vm.Graph.Points.Where(p => p.Time == now.AddDays(-2).AddSeconds(1)).FirstOrDefault().Amount);
        }
예제 #5
0
        public ActionResult Create(Goal goal)
        {
            goal.UserName = User.Identity.Name;
            if (ModelState.IsValid)
            {
                db.Goals.Add(goal);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(goal);
        }
예제 #6
0
        public void it_should_calcualte_cutofftime_correct()
        {
            var now = DateTime.Now;
            var firstDoneit = new DateTime(2012, 5, 27);
            var target = new GoalProcessor(now);
            var goal = new Goal() { Amount = 1, IntervalType = IntervalType.Dayly };

            var calculated = target.CalculateLowerCutoffTime(goal, 1, firstDoneit);
            AssertTimesAreAlmostEqual(firstDoneit.AddDays(3), calculated);

            calculated = target.CalculateLowerCutoffTime(goal, 0, now);
            AssertTimesAreAlmostEqual(now.AddDays(2), calculated);

            calculated = target.CalculateLowerCutoffTime(goal, 1M, now.AddDays(-10));
            AssertTimesAreAlmostEqual(now.AddDays(-7), calculated);
        }
예제 #7
0
        public void it_should_increase_hours_left_when_adding_a_new_doneit()
        {
            var now = DateTime.Now;
            var target = new GoalProcessor(now);

            // Week
            var goal = new Goal() { Amount = 7, IntervalType = IntervalType.Weekly };
            goal.DoneIts = new List<DoneIt>() { new DoneIt() { Amount = 3.01M, Date = now.AddDays(-7) } };
            goal.DoneIts.Add(new DoneIt() { Amount = 3, Date = now.AddDays(-4) } );
            goal.DoneIts.Add(new DoneIt() { Amount = 1, Date = now.AddDays(-1) });
            var vm = target.ProcessGoal(goal);
            Assert.AreEqual(GoalStatus.OnTrack, vm.Status);

            goal.DoneIts = new List<DoneIt>() { new DoneIt() { Amount = 2.9M, Date = now.AddDays(-7) } };
            goal.DoneIts.Add(new DoneIt() { Amount = 3, Date = now.AddDays(-4) });
            goal.DoneIts.Add(new DoneIt() { Amount = 1, Date = now.AddDays(-1) });
            vm = target.ProcessGoal(goal);
            Assert.AreEqual(GoalStatus.Behind, vm.Status);
        }
예제 #8
0
 public static decimal GetHourlyDecreaseRate(Goal goal)
 {
     decimal perHour = 0;
     switch (goal.IntervalType)
     {
         case IntervalType.Dayly:
             perHour = (decimal)goal.Amount / 24;
             break;
         case IntervalType.Weekly:
             // Number per hour
             perHour = (decimal)goal.Amount / (7 * 24);
             break;
         case IntervalType.Monthly:
             perHour = (decimal)goal.Amount / (30 * 24);
             break;
         default:
             new NotSupportedException();
             break;
     }
     return perHour;
 }
예제 #9
0
        public void it_should_show_a_stright_line_when_in_cutoff()
        {
            var now = DateTime.Now;
            var target = new GoalProcessor(now);
            var goal = new Goal() { Amount = 7, IntervalType = IntervalType.Weekly };

            // Simple one entry
            // -28,7
            // -21,0
            // -14,-7
            // -7, -14
            // -6, -14 (cutoff)
            // 0, -14 (cutoff)
            goal.DoneIts = new List<DoneIt>() {
                new DoneIt() { Amount = 7, Date = now.AddDays(-28) } ,
                new DoneIt() { Amount = 0, Date = now.AddDays(-21) } ,
                new DoneIt() { Amount = 0, Date = now.AddDays(-14) } ,
                new DoneIt() { Amount = 0, Date = now.AddDays(-7) } ,
            };
            var vm = target.ProcessGoal(goal);
            // 1: 7
            AssertPointOnGraph(vm, 0, 0, now.AddDays(-28));
            AssertPointOnGraph(vm, 1, 7, now.AddDays(-28));
            // 2: 0
            AssertPointOnGraph(vm, 2, 0, now.AddDays(-21));
            AssertPointOnGraph(vm, 3, 0, now.AddDays(-21));
            // 3: 0
            AssertPointOnGraph(vm, 4, -7, now.AddDays(-14));
            AssertPointOnGraph(vm, 5, -7, now.AddDays(-14));
            // 4: 0
            AssertPointOnGraph(vm, 6, -14, now.AddDays(-7));
            AssertPointOnGraph(vm, 7, -14, now.AddDays(-7));
            // Cutoff
            AssertPointOnGraph(vm, 8, -14, now.AddDays(-7));
            // Cutoff
            AssertPointOnGraph(vm, 9, -14, now.AddDays(-7));
            // Final
            AssertPointOnGraph(vm, 10, -14, now.AddDays(0));
        }
예제 #10
0
        public static DateTime GetDateOfLastOrFirstGraphPoint(bool isFirst, Goal goal, DateTime now)
        {
            if (isFirst)
            {
                return now.AddMonths(-4);

            }
            return now;

            var a = isFirst ? -1 : 1;
            if (goal.EvaluationType == GoalEvaluation.Countinious)
            {
                switch (goal.IntervalType)
                {
                    case IntervalType.Dayly:
                        return now.AddDays(2*a);
                    case IntervalType.Weekly:
                        return now.AddDays(7*a);
                    case IntervalType.Monthly:
                        return now.AddMonths(1*a);
                    default:
                        throw new ApplicationException("Unknown Intervaltype");
                }
            }
            else
            {
                if (isFirst)
                {
                    return goal.StartDate.HasValue ? goal.StartDate.Value : now.AddDays(-10);
                }
                else
                {
                    return goal.EndDate.HasValue ? goal.EndDate.Value : now.AddDays(10);
                }
            }
        }
예제 #11
0
        public static GraphViewModel CreateEmptyGraph(Goal goal, DateTime now)
        {
            var vm = new GraphViewModel();
            if (goal.EvaluationType == GoalEvaluation.Countinious)
            {
                var p1 = new GraphPoint { Amount = 0 };
                var p2 = new GraphPoint { Amount = 0 };
                switch (goal.IntervalType)
                {
                    case IntervalType.Dayly:
                        p1.Time = now.AddDays(-2);
                        p2.Time = now.AddDays(2);
                        break;
                    case IntervalType.Weekly:
                        p1.Time = now.AddDays(-14);
                        p2.Time = now.AddDays(7);

                        break;
                    case IntervalType.Monthly:
                        p1.Time = now.AddMonths(-2);
                        p2.Time = now.AddMonths(1);
                        break;
                    default:
                        break;
                }
                vm.Points = new List<GraphPoint> { p1, p2 };

            }
            else
            {
                var p1 = new GraphPoint { Amount = 0, Time=goal.StartDate.HasValue?goal.StartDate.Value:now };
                var p2 = new GraphPoint { Amount = 0 , Time=goal.EndDate.HasValue?goal.EndDate.Value:now};
                vm.Points = new List<GraphPoint> { p1, p2 };
            }
            return vm;
        }
예제 #12
0
        public void it_should_never_go_below_a_configurable_threshold()
        {
            var now = DateTime.Now;
            var target = new GoalProcessor(now);
            var goal = new Goal() { Amount = 7, IntervalType = IntervalType.Weekly };

            // Hour
            goal = new Goal() { Amount = 24, IntervalType = IntervalType.Dayly };
            goal.DoneIts = new List<DoneIt>() { new DoneIt() { Amount = 24.01M, Date = now.AddDays(-1) } };
            var vm = target.ProcessGoal(goal);
            Assert.AreEqual(GoalStatus.OnTrack, vm.Status);
            Assert.IsTrue(Math.Abs(vm.CurrentLevel - 0) < 0.1M);

            goal.DoneIts = new List<DoneIt>() { new DoneIt() { Amount = 23.99M, Date = now.AddDays(-1) } };
            vm = target.ProcessGoal(goal);
            Assert.AreEqual(GoalStatus.Behind, vm.Status);
            Assert.IsTrue(Math.Abs(vm.CurrentLevel - 0) < 0.1M);

            goal.DoneIts = new List<DoneIt>() { new DoneIt() { Amount = 24.01M, Date = now.AddDays(-2) } };
            vm = target.ProcessGoal(goal);
            Assert.IsTrue(Math.Abs(vm.CurrentLevel - -24) < 0.1M);

            // Hour limited by threshold (2*)
            goal.DoneIts = new List<DoneIt>() { new DoneIt() { Amount = 24.01M, Date = now.AddDays(-4) } };
            vm = target.ProcessGoal(goal);
            Assert.IsTrue(Math.Abs(vm.CurrentLevel - -48) < 0.1M);
        }
예제 #13
0
        public GoalViewModel ProcessGoal(Goal goal)
        {
            var vm = new GoalViewModel();
            vm.Status = GoalStatus.NotStarted;
            vm.Goal = goal;
            vm.Graph = new GraphViewModel();// gp.ProcessGraph(goal);
            //var timeFirstPoint = GraphProcessor.GetDateOfLastOrFirstGraphPoint(true, goal, _now);

            decimal currentLevel = 0;
            DateTime? previousDoneItTime = null;
            decimal perHour = GetHourlyDecreaseRate(goal);
            var cutoffLevel = goal.GetLowerCutoff();

            if (goal.DoneIts.Count > 0)
            {
                decimal oldCurrentLevel=0;
                foreach (var done in goal.DoneIts.OrderBy(d => d.Date))
                {
                    oldCurrentLevel = currentLevel;
                    if (previousDoneItTime == null)
                    {
                        // First doneit starts counting
                        currentLevel = done.Amount;
                        vm.Graph.AddPoint(done, oldCurrentLevel, currentLevel);
                    }
                    else
                    {
                        // Calculate current level
                        var dif = (done.Date - (DateTime)previousDoneItTime).TotalHours;
                        oldCurrentLevel = currentLevel - (perHour * Convert.ToDecimal(dif));
                        if (oldCurrentLevel < cutoffLevel)
                        {
                            // Add extra point at lower threshold
                            var cutoffTime = CalculateLowerCutoffTime(goal, currentLevel, previousDoneItTime.Value);

                            vm.Graph.Points.Add(new GraphPoint { Time = cutoffTime, Amount = 0, y = cutoffLevel });
                            oldCurrentLevel = cutoffLevel;
                        }

                        currentLevel = oldCurrentLevel + done.Amount;
                        vm.Graph.AddPoint(done, oldCurrentLevel, currentLevel);
                    }
                    previousDoneItTime = done.Date;
                }
                // Calculate current level
                var diff = (_now - (DateTime)previousDoneItTime).TotalHours;
                currentLevel -= (perHour * Convert.ToDecimal(diff));

                // Check for cutoff
                if (currentLevel < cutoffLevel)
                {
                    // Add extra point at lower threshold
                    var cutoffTime = CalculateLowerCutoffTime(goal, oldCurrentLevel, previousDoneItTime.Value);
                    vm.Graph.Points.Add(new GraphPoint { Time = cutoffTime, Amount = 0, y = cutoffLevel });
                    currentLevel = cutoffLevel;
                    vm.Cutoff = CutoffStatus.Active;
                }

                // Add current level
                vm.Graph.Points.Add(new GraphPoint { Time = _now, Amount = 0, y = currentLevel });

                vm.Status = currentLevel < 0 ? GoalStatus.Behind : GoalStatus.OnTrack;

                vm.AtZero = TimeSpan.FromHours(Convert.ToDouble(currentLevel / perHour));
                vm.CurrentLevel = currentLevel;
            }
            else
            {
                vm.Graph = GraphProcessor.CreateEmptyGraph(goal, _now);
            }

                var graph = vm.Graph;
                var first = graph.Points.OrderBy(x => x.Time).First().Time;
                var last = graph.Points.OrderBy(x => x.Time).Last().Time;
                var totalSecs = ((last - first).TotalSeconds);
                if (totalSecs > 0)
                {
                    foreach (var point in graph.Points)
                    {
                        point.x = Convert.ToDecimal((point.Time - first).TotalSeconds / totalSecs);
                    }
                }

            //GraphProcessor.CalculateXPositions(out vm);

            return vm;
        }
예제 #14
0
        public void when_no_doneits_it_should_show_status_not_started()
        {
            var target = new GoalProcessor();
            var goal = new Goal() { Amount = 7, IntervalType = IntervalType.Weekly };
            var now = DateTime.Now;

            var vm = target.ProcessGoal(goal);
            Assert.AreEqual(GoalStatus.NotStarted, vm.Status);
            //goal.DoneIts.Add(new DoneIt() { Amount = 1, Date = now.a
        }
예제 #15
0
        public void when_first_doneit_it_should_start_counting_down()
        {
            var now = DateTime.Now;
            var target = new GoalProcessor(now);
            var goal = new Goal() { Amount = 7, IntervalType = IntervalType.Weekly };

            goal.DoneIts.Add(new DoneIt() { Amount = 1, Date = now });

            var vm = target.ProcessGoal(goal);
            Assert.AreEqual(GoalStatus.OnTrack, vm.Status);
        }
예제 #16
0
        public void it_should_show_a_stright_line_when_in_cutoff2()
        {
            var now = DateTime.Now;
            var target = new GoalProcessor(now);
            var goal = new Goal() { Amount = 1, IntervalType = IntervalType.Dayly };

            // Simple one entry
            // -8,1
            goal.DoneIts = new List<DoneIt>() {
                new DoneIt() { Amount = 1, Date = now.AddDays(-10) } ,
            };
            var vm = target.ProcessGoal(goal);
            // Start 0,1
            AssertPointOnGraph(vm, 0, 0, now.AddDays(-10));
            AssertPointOnGraph(vm, 1, 1, now.AddDays(-10));
            //
            AssertPointOnGraph(vm, 2, -2, now.AddDays(-8));
            AssertPointOnGraph(vm, 3, -2, now);
        }
예제 #17
0
        public GraphViewModel ProcessGraph(Goal goal)
        {
            decimal currentLevel = 0;
            DateTime? previousDoneItTime = null;
            decimal perHour = GoalProcessor.GetHourlyDecreaseRate(goal);

            var gvm = GraphProcessor.CreateEmptyGraph(goal,_now);

            if (goal.DoneIts.Count > 0)
            {
                foreach (var done in goal.DoneIts.OrderBy(d => d.Date))
                {
                    if (previousDoneItTime == null)
                    {
                        previousDoneItTime = done.Date;
                        currentLevel = done.Amount;
                    }
                    else
                    {
                        currentLevel += done.Amount;
                    }
                    gvm.Points.Add(new GraphPoint { Amount = done.Amount, Time = done.Date });
                }
                var diff = (_now - (DateTime)previousDoneItTime).TotalHours;
                currentLevel -= (perHour * Convert.ToDecimal(diff));
                //vm.Status = currentLevel < 0 ? GoalStatus.Behind : GoalStatus.OnTrack;

                //vm.AtZero = TimeSpan.FromHours(Convert.ToDouble(currentLevel / perHour));
                //vm.CurrentLevel = currentLevel;
            }
            return gvm;
        }
예제 #18
0
 public ActionResult Edit(Goal goal)
 {
     goal.UserName = User.Identity.Name;
     if (ModelState.IsValid)
     {
         db.Entry(goal).State = EntityState.Modified;
         db.SaveChanges();
         return RedirectToAction("Index");
     }
     return View(goal);
 }
예제 #19
0
        public void it_should_start_one_interval_before_and_end_one_interval_after_if_interval()
        {
            var now = DateTime.Now;
            var target = new GoalProcessor(now);
            var goal = new Goal() { EvaluationType = GoalEvaluation.Countinious, IntervalType = IntervalType.Weekly };

            var vm = target.ProcessGoal(goal);
            Assert.AreEqual(vm.Graph.Points[0].Time, now.AddDays(-14));
            Assert.AreEqual(vm.Graph.Points[1].Time, now.AddDays(7));
            Assert.AreEqual(0, vm.Graph.Points[0].Amount);
            Assert.AreEqual(0, vm.Graph.Points[1].Amount);

            goal = new Goal() { EvaluationType = GoalEvaluation.Countinious, IntervalType = IntervalType.Monthly };
            vm = target.ProcessGoal(goal);
            Assert.AreEqual(vm.Graph.Points[0].Time, now.AddMonths(-2));
            Assert.AreEqual(vm.Graph.Points[1].Time, now.AddMonths(1));

            goal = new Goal() { EvaluationType = GoalEvaluation.Countinious, IntervalType = IntervalType.Dayly };
            vm = target.ProcessGoal(goal);
            Assert.AreEqual(vm.Graph.Points[0].Time, now.AddDays(-2));
            Assert.AreEqual(vm.Graph.Points[1].Time, now.AddDays(2));
        }
예제 #20
0
        public void it_should_start_and_end_on_specified_dates_if_timelimited()
        {
            var now = DateTime.Now;
            var target = new GoalProcessor(now);
            var goal = new Goal() { EvaluationType = GoalEvaluation.Timelimited };

            var vm = target.ProcessGoal(goal);
            Assert.AreEqual(0, vm.Graph.Points[0].Amount);
            Assert.AreEqual(0, vm.Graph.Points[1].Amount);

            goal = new Goal() { EvaluationType = GoalEvaluation.Timelimited, StartDate = now.AddDays(-10), EndDate = now.AddDays(10) };
            vm = target.ProcessGoal(goal);
            Assert.AreEqual(vm.Graph.Points[0].Time, now.AddDays(-10));
            Assert.AreEqual(vm.Graph.Points[1].Time, now.AddDays(10));
        }