public async Task CalculatePoints_Daily_NumberOfTimes(UserHabitRecordsControllerTestData_DailyNoOfTimes testData)
        {
            var context = this.fixture.GetCurrentDataContext();
            UserHabitRecordsController control = new(context);

            // Add Habit, Habit Rule
            UserHabit habit = new UserHabit();

            habit.TargetUser       = DataSetupUtility.UserA;
            habit.ValidFrom        = new DateTime(2021, 1, 1);
            habit.ValidTo          = new DateTime(2022, 12, 31);
            habit.Name             = "Habit_Daily_1";
            habit.Category         = HabitCategory.Positive;
            habit.Comment          = habit.Name;
            habit.Frequency        = HabitFrequency.Daily;
            habit.CompleteCategory = HabitCompleteCategory.NumberOfTimes;
            context.UserHabits.Add(habit);
            context.SaveChanges();
            Int32 nNewHabitID = habit.ID;

            foreach (var rule in testData.RuleList)
            {
                rule.HabitID = habit.ID;
                context.UserHabitRules.Add(rule);
            }
            context.SaveChanges();

            // Add user record.
            foreach (DateTime dt in testData.RecordDatesList)
            {
                UserHabitRecord record = new UserHabitRecord();
                record.HabitID    = habit.ID;
                record.RecordDate = dt;
                record.Comment    = "Test1";
                var rst = control.Post(record);
                Assert.NotNull(rst);
                if (rst != null)
                {
                    CreatedODataResult <UserHabitRecord> rstrecord = (CreatedODataResult <UserHabitRecord>)rst.Result;
                    Assert.NotNull(rstrecord);
                }
            }

            // Check on DB directly
            var dbrecords = (from dbrecord in context.UserHabitRecords
                             where dbrecord.HabitID == habit.ID
                             orderby dbrecord.RecordDate ascending
                             select dbrecord).ToList();

            Assert.Equal(testData.ExpectedRecordList.Count, dbrecords.Count);

            // Ensure rule is assigned correctly
            if (testData.ExpectedRecordList.Count > 0)
            {
                foreach (var dbrecord in dbrecords)
                {
                    var ridx = testData.ExpectedRecordList.FindIndex(rd => rd.RecordDate == dbrecord.RecordDate);
                    Assert.NotEqual(-1, ridx);

                    Assert.Equal(testData.ExpectedRecordList[ridx].RuleID, dbrecord.RuleID);
                    Assert.Equal(testData.ExpectedRecordList[ridx].ContinuousCount, dbrecord.ContinuousCount);
                }
            }

            DataSetupUtility.ClearUserHabitData(context, nNewHabitID);
            context.SaveChanges();

            await context.DisposeAsync();
        }
        public async Task <IActionResult> Post([FromBody] UserHabitRecord record)
        {
            if (!ModelState.IsValid)
            {
                foreach (var value in ModelState.Values)
                {
                    foreach (var err in value.Errors)
                    {
                        System.Diagnostics.Debug.WriteLine(err.Exception?.Message);
                    }
                }

                return(BadRequest());
            }

            // Find out the matched rule
            var habits = (from habit in this._context.UserHabits where habit.ID == record.HabitID select habit).ToList <UserHabit>();

            if (habits.Count != 1)
            {
                return(BadRequest("Invalid Habit"));
            }
            // Date range for checking
            if (record.RecordDate >= habits[0].ValidTo || record.RecordDate < habits[0].ValidFrom)
            {
                return(BadRequest("Invalid time"));
            }

            DateTime dtbgn = record.RecordDate;

            switch (habits[0].Frequency)
            {
            case HabitFrequency.Weekly:
                dtbgn = HabitWeeklyTrace.getDBSelectionDate((DayOfWeek)habits[0].StartDate, record.RecordDate);
                break;

            case HabitFrequency.Monthly:
                dtbgn = HabitMonthlyTrace.getDBSelectionDate(habits[0].StartDate.Value, record.RecordDate);
                break;

            case HabitFrequency.Daily:
            default:
                dtbgn = record.RecordDate - TimeSpan.FromDays(1);
                break;
            }

            // Basic check on the record itself
            switch (habits[0].CompleteCategory)
            {
            case HabitCompleteCategory.NumberOfCount:
            {
                if (record.CompleteFact.GetValueOrDefault() <= 0)
                {
                    return(BadRequest("Record must provide complete fact"));
                }
                var checkrecord = (from dbrecord in _context.UserHabitRecords
                                   where dbrecord.RecordDate > record.RecordDate && dbrecord.HabitID == record.HabitID
                                   select dbrecord).Count();
                if (checkrecord > 0)
                {
                    return(BadRequest("Record in the past!"));
                }

                checkrecord = (from dbrecord in _context.UserHabitRecords
                               where dbrecord.RecordDate == record.RecordDate && dbrecord.HabitID == record.HabitID &&
                               dbrecord.SubID == record.SubID
                               select dbrecord).Count();
                if (checkrecord > 0)
                {
                    return(BadRequest("Conflicted Sub ID!"));
                }
            }
            break;

            case HabitCompleteCategory.NumberOfTimes:
            default:
            {
                var checkrecord = (from dbrecord in _context.UserHabitRecords
                                   where dbrecord.RecordDate >= record.RecordDate && dbrecord.HabitID == record.HabitID
                                   select dbrecord).Count();
                if (checkrecord > 0)
                {
                    return(BadRequest("Record in the past!"));
                }
            }
            break;
            }

            // Find out all rules
            var rules = (from rule in this._context.UserHabitRules
                         where rule.HabitID == record.HabitID
                         orderby rule.ContinuousRecordFrom
                         ascending select rule).ToList <UserHabitRule>();

            if (rules.Count > 0)
            {
            }
            else
            {
                return(BadRequest("No rule defined"));
            }

            // Find related records
            var oldrecords = (from dbrecord in _context.UserHabitRecords
                              where dbrecord.HabitID == record.HabitID && dbrecord.RecordDate >= dtbgn && dbrecord.RecordDate <= record.RecordDate
                              select dbrecord).ToList <UserHabitRecord>();

            record.ContinuousCount = 1; // Default is 1

            // Now calculate the rule and the points
            switch (habits[0].Frequency)
            {
            case HabitFrequency.Weekly:
            {
                HabitWeeklyTrace firstWeek  = new HabitWeeklyTrace();
                HabitWeeklyTrace secondWeek = new HabitWeeklyTrace();
                HabitWeeklyTrace.analyzeUserRecord(oldrecords, dtbgn, firstWeek, secondWeek);
                // First week
                int?firstweekrule    = firstWeek.getRuleID();
                int firstweekcontcnt = 0;
                if (firstweekrule.HasValue)
                {
                    firstweekcontcnt = firstWeek.getRuleContinuousCount().GetValueOrDefault();
                }

                // Second week
                int?secondweekrule = secondWeek.getRuleID();
                if (firstweekrule.HasValue)
                {
                    // Start since last week
                    switch (habits[0].CompleteCategory)
                    {
                    case HabitCompleteCategory.NumberOfCount:
                    {
                        int nexistcnt = secondWeek.getNumberOfCount().GetValueOrDefault();
                        if (secondweekrule.HasValue)
                        {
                            // Already has rule assigned, move the rule ID to new created one
                            var existRecord   = secondWeek.getRecordWithRule();
                            var existDBRecord = _context.UserHabitRecords
                                                .SingleOrDefaultAsync(x => x.HabitID == existRecord.HabitID && x.RecordDate == existRecord.RecordDate && x.SubID == existRecord.SubID);

                            record.RuleID          = existDBRecord.Result.RuleID;
                            record.ContinuousCount = existDBRecord.Result.ContinuousCount;

                            existDBRecord.Result.RuleID          = null;
                            existDBRecord.Result.ContinuousCount = 0;
                        }
                        else
                        {
                            if (nexistcnt + record.CompleteFact.GetValueOrDefault() >= habits[0].CompleteCondition)
                            {
                                // Workout the new rule (maybe) then
                                var ncontcnt = firstweekcontcnt + 1;
                                var ridx     = rules.FindIndex(ruleitem => ncontcnt >= ruleitem.ContinuousRecordFrom && ruleitem.ContinuousRecordTo > ncontcnt);
                                if (ridx != -1)
                                {
                                    record.ContinuousCount = ncontcnt;
                                    record.RuleID          = rules[ridx].RuleID;
                                }
                            }
                        }
                    }
                    break;

                    case HabitCompleteCategory.NumberOfTimes:
                    default:
                    {
                        int nexistcnt = secondWeek.getNumberOfTimes();
                        if (secondweekrule.HasValue)
                        {
                            // Already has rule assigned, move the rule ID to new created one
                            var existRecord   = secondWeek.getRecordWithRule();
                            var existDBRecord = _context.UserHabitRecords
                                                .SingleOrDefaultAsync(x => x.HabitID == existRecord.HabitID && x.RecordDate == existRecord.RecordDate && x.SubID == existRecord.SubID);

                            record.RuleID          = existDBRecord.Result.RuleID;
                            record.ContinuousCount = existDBRecord.Result.ContinuousCount;

                            existDBRecord.Result.RuleID          = null;
                            existDBRecord.Result.ContinuousCount = 0;
                        }
                        else
                        {
                            if (nexistcnt + 1 == habits[0].CompleteCondition)
                            {
                                // Workout the rule then
                                var ncontcnt = firstweekcontcnt + 1;
                                var ridx     = rules.FindIndex(ruleitem => ncontcnt >= ruleitem.ContinuousRecordFrom && ruleitem.ContinuousRecordTo > ncontcnt);
                                if (ridx != -1)
                                {
                                    record.ContinuousCount = ncontcnt;
                                    record.RuleID          = rules[ridx].RuleID;
                                }
                            }
                        }
                    }
                    break;
                    }
                }
                else
                {
                    // New start in this week
                    switch (habits[0].CompleteCategory)
                    {
                    case HabitCompleteCategory.NumberOfCount:
                    {
                        int nexistcnt = secondWeek.getNumberOfCount().GetValueOrDefault();
                        if (secondweekrule.HasValue)
                        {
                            // Already has rule assigned, move the rule ID to new created one
                            var existRecord   = secondWeek.getRecordWithRule();
                            var existDBRecord = _context.UserHabitRecords
                                                .SingleOrDefaultAsync(x => x.HabitID == existRecord.HabitID && x.RecordDate == existRecord.RecordDate && x.SubID == existRecord.SubID);

                            record.RuleID          = existDBRecord.Result.RuleID;
                            record.ContinuousCount = existDBRecord.Result.ContinuousCount;

                            existDBRecord.Result.RuleID          = null;
                            existDBRecord.Result.ContinuousCount = 0;
                        }
                        else
                        {
                            if (nexistcnt + record.CompleteFact.GetValueOrDefault() >= habits[0].CompleteCondition)
                            {
                                // Workout the rule then
                                var ridx = rules.FindIndex(ruleitem => record.ContinuousCount >= ruleitem.ContinuousRecordFrom && record.ContinuousCount < ruleitem.ContinuousRecordTo);
                                if (ridx != -1)
                                {
                                    record.RuleID = rules[ridx].RuleID;
                                }
                            }
                        }
                    }
                    break;

                    case HabitCompleteCategory.NumberOfTimes:
                    default:
                    {
                        int nexistcnt = secondWeek.getNumberOfTimes();
                        if (secondweekrule.HasValue)
                        {
                            // Already has rule assigned, move the rule ID to new created one
                            var existRecord   = secondWeek.getRecordWithRule();
                            var existDBRecord = _context.UserHabitRecords
                                                .SingleOrDefaultAsync(x => x.HabitID == existRecord.HabitID && x.RecordDate == existRecord.RecordDate && x.SubID == existRecord.SubID);

                            record.RuleID          = existDBRecord.Result.RuleID;
                            record.ContinuousCount = existDBRecord.Result.ContinuousCount;

                            existDBRecord.Result.RuleID          = null;
                            existDBRecord.Result.ContinuousCount = 0;
                        }
                        else
                        {
                            if (nexistcnt + 1 == habits[0].CompleteCondition)
                            {
                                // Workout the rule then
                                var ridx = rules.FindIndex(ruleitem => record.ContinuousCount >= ruleitem.ContinuousRecordFrom && record.ContinuousCount < ruleitem.ContinuousRecordTo);
                                if (ridx != -1)
                                {
                                    record.RuleID = rules[ridx].RuleID;
                                }
                            }
                        }
                    }
                    break;
                    }
                }
            }
            break;

            case HabitFrequency.Monthly:
            {
                HabitMonthlyTrace firstMonth  = new HabitMonthlyTrace();
                HabitMonthlyTrace secondMonth = new HabitMonthlyTrace();
                HabitMonthlyTrace.analyzeUserRecord(oldrecords, dtbgn, firstMonth, secondMonth);
                int?firstMonthRule      = firstMonth.getRuleID();
                int firstMonthContCount = 0;
                if (firstMonthRule.HasValue)
                {
                    firstMonthContCount = firstMonth.getRuleContinuousCount().GetValueOrDefault();
                }

                int?secondMonthRule = secondMonth.getRuleID();
                if (firstMonthRule.HasValue)
                {
                    // Start since last month
                    switch (habits[0].CompleteCategory)
                    {
                    case HabitCompleteCategory.NumberOfCount:
                    {
                        int nexistcnt = secondMonth.getNumberOfCount().GetValueOrDefault();
                        if (secondMonthRule.HasValue)
                        {
                            // Already has rule assigned, move the rule ID to new created one
                            var existRecord   = secondMonth.getRecordWithRule();
                            var existDBRecord = _context.UserHabitRecords
                                                .SingleOrDefaultAsync(x => x.HabitID == existRecord.HabitID && x.RecordDate == existRecord.RecordDate && x.SubID == existRecord.SubID);

                            record.RuleID          = existDBRecord.Result.RuleID;
                            record.ContinuousCount = existDBRecord.Result.ContinuousCount;

                            existDBRecord.Result.RuleID          = null;
                            existDBRecord.Result.ContinuousCount = 0;
                        }
                        else
                        {
                            if (nexistcnt + record.CompleteFact.GetValueOrDefault() >= habits[0].CompleteCondition)
                            {
                                // Workout the new rule (maybe) then
                                var ncontcnt = firstMonthContCount + 1;
                                var ridx     = rules.FindIndex(ruleitem => ncontcnt >= ruleitem.ContinuousRecordFrom && ruleitem.ContinuousRecordTo > ncontcnt);
                                if (ridx != -1)
                                {
                                    record.ContinuousCount = ncontcnt;
                                    record.RuleID          = rules[ridx].RuleID;
                                }
                                else
                                {
                                    record.ContinuousCount = firstMonthContCount;
                                }
                            }
                            else
                            {
                                record.ContinuousCount = firstMonthContCount;
                            }
                        }
                    }
                    break;

                    case HabitCompleteCategory.NumberOfTimes:
                    default:
                    {
                        int nexistcnt = secondMonth.getNumberOfTimes();
                        if (secondMonthRule.HasValue)
                        {
                            // Already has rule assigned, move the rule ID to new created one
                            var existRecord   = secondMonth.getRecordWithRule();
                            var existDBRecord = _context.UserHabitRecords
                                                .SingleOrDefaultAsync(x => x.HabitID == existRecord.HabitID && x.RecordDate == existRecord.RecordDate && x.SubID == existRecord.SubID);

                            record.RuleID          = existDBRecord.Result.RuleID;
                            record.ContinuousCount = existDBRecord.Result.ContinuousCount;

                            existDBRecord.Result.RuleID          = null;
                            existDBRecord.Result.ContinuousCount = 0;
                        }
                        else
                        {
                            if (nexistcnt + 1 == habits[0].CompleteCondition)
                            {
                                // Workout the rule then
                                var ncontcnt = firstMonthContCount + 1;
                                var ridx     = rules.FindIndex(ruleitem => ncontcnt >= ruleitem.ContinuousRecordFrom && ruleitem.ContinuousRecordTo > ncontcnt);
                                if (ridx != -1)
                                {
                                    record.ContinuousCount = ncontcnt;
                                    record.RuleID          = rules[ridx].RuleID;
                                }
                            }
                        }
                    }
                    break;
                    }
                }
                else
                {
                    // New start in this month
                    switch (habits[0].CompleteCategory)
                    {
                    case HabitCompleteCategory.NumberOfCount:
                    {
                        int nexistcnt = secondMonth.getNumberOfCount().GetValueOrDefault();
                        if (secondMonthRule.HasValue)
                        {
                            // Already has rule assigned, move the rule ID to new created one
                            var existRecord   = secondMonth.getRecordWithRule();
                            var existDBRecord = _context.UserHabitRecords
                                                .SingleOrDefaultAsync(x => x.HabitID == existRecord.HabitID && x.RecordDate == existRecord.RecordDate && x.SubID == existRecord.SubID);

                            record.RuleID          = existDBRecord.Result.RuleID;
                            record.ContinuousCount = existDBRecord.Result.ContinuousCount;

                            existDBRecord.Result.RuleID          = null;
                            existDBRecord.Result.ContinuousCount = 0;
                        }
                        else
                        {
                            if (nexistcnt + record.CompleteFact.GetValueOrDefault() >= habits[0].CompleteCondition)
                            {
                                // Workout the rule then
                                var ridx = rules.FindIndex(ruleitem => record.ContinuousCount >= ruleitem.ContinuousRecordFrom && record.ContinuousCount < ruleitem.ContinuousRecordTo);
                                if (ridx != -1)
                                {
                                    record.RuleID = rules[ridx].RuleID;
                                }
                            }
                        }
                    }
                    break;

                    case HabitCompleteCategory.NumberOfTimes:
                    default:
                    {
                        int nexistcnt = secondMonth.getNumberOfTimes();
                        if (secondMonthRule.HasValue)
                        {
                            // Already has rule assigned, move the rule ID to new created one
                            var existRecord   = secondMonth.getRecordWithRule();
                            var existDBRecord = _context.UserHabitRecords
                                                .SingleOrDefaultAsync(x => x.HabitID == existRecord.HabitID && x.RecordDate == existRecord.RecordDate && x.SubID == existRecord.SubID);

                            record.RuleID          = existDBRecord.Result.RuleID;
                            record.ContinuousCount = existDBRecord.Result.ContinuousCount;

                            existDBRecord.Result.RuleID          = null;
                            existDBRecord.Result.ContinuousCount = 0;
                        }
                        else
                        {
                            if (nexistcnt + 1 == habits[0].CompleteCondition)
                            {
                                // Workout the rule then
                                var ridx = rules.FindIndex(ruleitem => record.ContinuousCount >= ruleitem.ContinuousRecordFrom && record.ContinuousCount < ruleitem.ContinuousRecordTo);
                                if (ridx != -1)
                                {
                                    record.RuleID = rules[ridx].RuleID;
                                }
                                else
                                {
                                    record.ContinuousCount = 0;
                                }
                            }
                            else
                            {
                                record.ContinuousCount = 0;
                            }
                        }
                    }
                    break;
                    }
                }
            }
            break;

            case HabitFrequency.Daily:
            default:
            {
                HabitDailyTrace yesterday = new HabitDailyTrace();
                HabitDailyTrace today     = new HabitDailyTrace();
                HabitDailyTrace.analyzeUserRecord(oldrecords, dtbgn, yesterday, today);
                int?yesterdayrule    = yesterday.getRuleID();
                int yesterdaycontcnt = 0;
                if (yesterdayrule.HasValue)
                {
                    yesterdaycontcnt = yesterday.getRuleContinuousCount().GetValueOrDefault();
                }

                int?todayrule = today.getRuleID();
                if (yesterdayrule.HasValue)
                {
                    switch (habits[0].CompleteCategory)
                    {
                    case HabitCompleteCategory.NumberOfCount:
                    {
                        int nexistcnt = today.getNumberOfCount().GetValueOrDefault();
                        if (todayrule.HasValue)
                        {
                            // Already has rule assigned, move the rule ID to new created one
                            var existRecord   = today.getRecordWithRule();
                            var existDBRecord = _context.UserHabitRecords
                                                .SingleOrDefaultAsync(x => x.HabitID == existRecord.HabitID && x.RecordDate == existRecord.RecordDate && x.SubID == existRecord.SubID);

                            record.RuleID          = existDBRecord.Result.RuleID;
                            record.ContinuousCount = existDBRecord.Result.ContinuousCount;

                            existDBRecord.Result.RuleID          = null;
                            existDBRecord.Result.ContinuousCount = 0;
                        }
                        else
                        {
                            if (nexistcnt + record.CompleteFact.GetValueOrDefault() >= habits[0].CompleteCondition)
                            {
                                // Workout the new rule (maybe) then
                                var ncontcnt = yesterdaycontcnt + 1;
                                var ridx     = rules.FindIndex(ruleitem => ncontcnt >= ruleitem.ContinuousRecordFrom && ruleitem.ContinuousRecordTo > ncontcnt);
                                if (ridx != -1)
                                {
                                    record.ContinuousCount = ncontcnt;
                                    record.RuleID          = rules[ridx].RuleID;
                                }
                            }
                            else
                            {
                                record.ContinuousCount = 0;
                            }
                        }
                    }
                    break;

                    case HabitCompleteCategory.NumberOfTimes:
                    default:
                    {
                        int nexistcnt = today.getNumberOfTimes();
                        if (todayrule.HasValue)
                        {
                            // Shall never happen
                            throw new Exception("Unexpected");
                        }
                        else
                        {
                            // Workout the rule then
                            var ncontcnt = yesterdaycontcnt + 1;
                            var ridx     = rules.FindIndex(ruleitem => ncontcnt >= ruleitem.ContinuousRecordFrom && ruleitem.ContinuousRecordTo > ncontcnt);
                            if (ridx != -1)
                            {
                                record.ContinuousCount = ncontcnt;
                                record.RuleID          = rules[ridx].RuleID;
                            }
                            else
                            {
                                record.ContinuousCount = 0;
                            }
                        }
                    }
                    break;
                    }
                }
                else
                {
                    var ncontcnt = yesterdaycontcnt + 1;
                    // New start of the day
                    switch (habits[0].CompleteCategory)
                    {
                    case HabitCompleteCategory.NumberOfCount:
                    {
                        int completedFact = today.getNumberOfCount().GetValueOrDefault();
                        completedFact += record.CompleteFact.GetValueOrDefault();
                        if (completedFact >= habits[0].CompleteCondition)
                        {
                            var ridx = rules.FindIndex(ruleitem => ncontcnt >= ruleitem.ContinuousRecordFrom && ruleitem.ContinuousRecordTo > ncontcnt);
                            if (ridx != -1)
                            {
                                record.ContinuousCount = ncontcnt;
                                record.RuleID          = rules[ridx].RuleID;
                            }
                        }
                        else
                        {
                            record.ContinuousCount = 0;
                        }
                    }
                    break;

                    case HabitCompleteCategory.NumberOfTimes:
                    default:
                    {
                        // Workout the rule then
                        var ridx = rules.FindIndex(ruleitem => ncontcnt >= ruleitem.ContinuousRecordFrom && ruleitem.ContinuousRecordTo > ncontcnt);
                        if (ridx != -1)
                        {
                            record.ContinuousCount = ncontcnt;
                            record.RuleID          = rules[ridx].RuleID;
                        }
                        else
                        {
                            record.ContinuousCount = 0;
                        }
                    }
                    break;
                    }
                }
            }
            break;
            }

            // Update db
            _context.UserHabitRecords.Add(record);
            try
            {
                await _context.SaveChangesAsync();
            }
            catch (Exception exp)
            {
                System.Console.WriteLine(exp.Message);
                throw;
            }

            return(Created(record));
        }
        public async Task CalculatePoints_Weekly_NumberOfTimes(UserHabitRecordsControllerTestData_WeekNoOfTimes testData)
        {
            var context = this.fixture.GetCurrentDataContext();
            UserHabitRecordsController control = new(context);

            // Add Habit, Habit Rule
            UserHabit habit = new UserHabit();

            habit.TargetUser        = DataSetupUtility.UserA;
            habit.ValidFrom         = new DateTime(2021, 1, 1);
            habit.ValidTo           = new DateTime(2022, 12, 31);
            habit.Name              = "Habit_1";
            habit.Category          = HabitCategory.Positive;
            habit.Comment           = habit.Name;
            habit.Frequency         = HabitFrequency.Weekly;
            habit.CompleteCategory  = HabitCompleteCategory.NumberOfTimes;
            habit.CompleteCondition = testData.CompleteCondition;
            habit.StartDate         = (int)testData.Dow;
            context.UserHabits.Add(habit);
            context.SaveChanges();
            Int32 nNewHabitID = habit.ID;

            UserHabitRule rule1 = new UserHabitRule();

            rule1.HabitID = habit.ID;
            rule1.RuleID  = 1;
            rule1.ContinuousRecordFrom = 1;
            rule1.ContinuousRecordTo   = 2;
            rule1.Point = 1;
            context.UserHabitRules.Add(rule1);

            UserHabitRule rule2 = new UserHabitRule();

            rule2.HabitID = habit.ID;
            rule2.RuleID  = 2;
            rule2.ContinuousRecordFrom = 2;
            rule1.ContinuousRecordTo   = 3;
            rule2.Point = 2;
            context.UserHabitRules.Add(rule2);

            UserHabitRule rule3 = new UserHabitRule();

            rule3.HabitID = habit.ID;
            rule3.RuleID  = 3;
            rule3.ContinuousRecordFrom = 3;
            rule3.Point = 4;
            context.UserHabitRules.Add(rule3);
            context.SaveChanges();

            // Add user record.
            //Boolean lastRst = false;
            foreach (DateTime dt in testData.RecordDatesList)
            {
                UserHabitRecord record = new UserHabitRecord();
                record.HabitID    = habit.ID;
                record.RecordDate = dt;
                record.Comment    = "Test1";
                var rst = control.Post(record);
                Assert.NotNull(rst);
                if (rst != null)
                {
                    CreatedODataResult <UserHabitRecord> rstrecord = (CreatedODataResult <UserHabitRecord>)rst.Result;
                    Assert.NotNull(rstrecord);

                    //lastRst = rstrecord.Entity.RuleID.HasValue;
                }
            }

            // Check on DB directly
            var dbrecords = (from dbrecord in context.UserHabitRecords
                             where dbrecord.HabitID == habit.ID
                             select dbrecord).ToList();

            Assert.Equal(testData.RecordCount, dbrecords.Count);

            // Ensure rule is assigned correctly
            if (testData.TargetRuleDateList.Count > 0)
            {
                var rulecnt = 0;
                dbrecords.ForEach(dbr =>
                {
                    if (dbr.RuleID != null)
                    {
                        rulecnt++;

                        var ridx = testData.TargetRuleDateList.FindIndex(rd => rd.Date == dbr.RecordDate.Date);
                        Assert.NotEqual(-1, ridx);
                    }
                });
                Assert.Equal(testData.TargetRuleDateList.Count, rulecnt);
            }

            DataSetupUtility.ClearUserHabitData(context, nNewHabitID);
            context.SaveChanges();

            await context.DisposeAsync();
        }