示例#1
0
        /// <summary>
        /// Update the open attempt record if there are changes.
        /// </summary>
        /// <param name="openAttempt"></param>
        /// <param name="achievementTypeCache">The achievement type cache.</param>
        /// <param name="transaction">The financial transaction.</param>
        private void UpdateOpenAttempt(AchievementAttempt openAttempt, AchievementTypeCache achievementTypeCache, FinancialTransaction transaction)
        {
            // Validate the attribute values
            var numberToAccumulate = GetAttributeValue(achievementTypeCache, AttributeKey.NumberToAccumulate).AsInteger();

            if (numberToAccumulate <= 0)
            {
                ExceptionLogService.LogException($"{GetType().Name}.UpdateOpenAttempt cannot process because the NumberToAccumulate attribute is less than 1");
                return;
            }

            // Calculate the date range where the open attempt can be validly fulfilled
            var attributeMaxDate = GetAttributeValue(achievementTypeCache, AttributeKey.EndDateTime).AsDateTime();
            var minDate          = openAttempt.AchievementAttemptStartDateTime;
            var maxDate          = CalculateMaxDateForAchievementAttempt(minDate, attributeMaxDate);

            // Get the transaction dates
            var transactionDates = GetOrderedFinancialTransactionDatesByPerson(achievementTypeCache, transaction.AuthorizedPersonAlias.PersonId, minDate, maxDate);
            var newCount         = transactionDates.Count();

            if (newCount == 0)
            {
                return;
            }

            var lastInteractionDate = transactionDates.LastOrDefault();
            var progress            = CalculateProgress(newCount, numberToAccumulate);
            var isSuccessful        = progress >= 1m;

            openAttempt.AchievementAttemptEndDateTime = lastInteractionDate;
            openAttempt.Progress     = progress;
            openAttempt.IsClosed     = isSuccessful && !achievementTypeCache.AllowOverAchievement;
            openAttempt.IsSuccessful = isSuccessful;
        }
示例#2
0
        /// <summary>
        /// Gets the attempt from the streak.
        /// </summary>
        /// <param name="computedStreak">The computed streak.</param>
        /// <param name="targetCount">The target count.</param>
        /// <param name="isClosed">if set to <c>true</c> [is closed].</param>
        /// <returns></returns>
        private static AchievementAttempt GetAttemptFromStreak(ComputedStreak computedStreak, int targetCount, bool isClosed)
        {
            var attempt = new AchievementAttempt();

            ApplyStreakToAttempt(computedStreak, attempt, targetCount, isClosed);
            return(attempt);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="MarkEngagementResponse"/> class.
 /// </summary>
 public AttemptListItem(AchievementAttempt achievementAttempt)
 {
     AchievementAttemptId = achievementAttempt.Id;
     AchievementTypeId    = achievementAttempt.AchievementTypeId;
     AchievementTypeGuid  = achievementAttempt.AchievementType?.Guid ?? AchievementTypeCache.Get(AchievementTypeId)?.Guid;
     Progress             = achievementAttempt.Progress;
     IsComplete           = Progress >= 1;
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="PersonAchievementType"/> class.
        /// </summary>
        /// <param name="person">The person.</param>
        /// <param name="achievementType">Type of the achievement.</param>
        /// <param name="achievementAttempts">The achievement attempts.</param>
        /// <param name="justCompletedAchievementAttempt">The just completed achievement attempt.</param>
        public PersonAchievementType(Person person, AchievementTypeCache achievementType, AchievementAttempt[] achievementAttempts, AchievementAttempt justCompletedAchievementAttempt)
        {
            Person          = person;
            AchievementType = achievementType;
            JustCompletedAchievementAttempt = justCompletedAchievementAttempt;

            CurrentInProgressAchievement = achievementAttempts.Where(a => !a.IsSuccessful && !a.IsClosed).FirstOrDefault();
            AchievementAttempts          = achievementAttempts;
        }
示例#5
0
        /// <summary>
        /// Gets the attempt from the streak
        /// </summary>
        /// <param name="computedStreak">The computed streak.</param>
        /// <param name="attempt">The attempt.</param>
        /// <param name="targetCount">The target count.</param>
        /// <param name="isClosed">if set to <c>true</c> [is closed].</param>
        private static void ApplyStreakToAttempt(ComputedStreak computedStreak, AchievementAttempt attempt, int targetCount, bool isClosed)
        {
            var progress = CalculateProgress(computedStreak.Count, targetCount);

            attempt.AchievementAttemptStartDateTime = computedStreak.StartDate;
            attempt.AchievementAttemptEndDateTime   = computedStreak.EndDate;
            attempt.Progress     = progress;
            attempt.IsClosed     = isClosed;
            attempt.IsSuccessful = progress >= 1m;
        }
示例#6
0
        /// <summary>
        /// Gets the person achievement types.
        /// </summary>
        /// <param name="includeJustCompleted">if set to <c>true</c> [include just completed].</param>
        /// <returns></returns>
        public PersonAchievementType[] GetPersonAchievementTypes(bool includeJustCompleted)
        {
            // For each checkin, we only want to show one achievement per AchievementType
            // If there is one in Progress, include that
            // otherwise add the first Completed one of each AchievementType
            List <AchievementAttempt> achievementAttempts = new List <AchievementAttempt>();
            var checkinResult = this;

            if (checkinResult.InProgressAchievementAttempts?.Any() == true)
            {
                achievementAttempts.AddRange(checkinResult.InProgressAchievementAttempts);
            }

            if (checkinResult.CompletedAchievementAttempts?.Any() == true)
            {
                achievementAttempts.AddRange(checkinResult.CompletedAchievementAttempts);
            }

            if (achievementAttempts.Any() == true)
            {
                PersonAchievementType[] personAchievementTypes = achievementAttempts
                                                                 .GroupBy(a => a.AchievementTypeId)
                                                                 .Select(a =>
                {
                    var achievmentTypeId             = a.Key;
                    var achievementType              = AchievementTypeCache.Get(achievmentTypeId);
                    var person                       = checkinResult.Person.Person;
                    AchievementAttempt justCompleted = null;
                    if (includeJustCompleted)
                    {
                        justCompleted = this.JustCompletedAchievementAttempts.Where(j => j.AchievementTypeId == achievmentTypeId).FirstOrDefault();
                    }

                    return(new PersonAchievementType(person, achievementType, a.ToArray(), justCompleted));
                }).ToArray();

                return(personAchievementTypes);
            }

            return(new PersonAchievementType[0]);
        }
        /// <summary>
        /// Save the current record.
        /// </summary>
        /// <returns></returns>
        private void SaveRecord()
        {
            var attempt         = GetAttempt();
            var achievementType = GetAchievementTypeCache();

            // Add the new attempt if we are adding
            if (attempt == null)
            {
                var attemptService    = GetAttemptService();
                var achievementTypeId = achievementType == null?atpAchievementType.SelectedValue.AsInteger() : achievementType.Id;

                attempt = new AchievementAttempt
                {
                    AchievementTypeId = achievementTypeId,
                    AchieverEntityId  = nbAchieverEntityId.IntegerValue ?? 0
                };

                attemptService.Add(attempt);
            }

            var progress = tbProgress.Text.AsDecimal();

            if (attempt.Progress < 0m)
            {
                attempt.Progress = 0m;
            }

            if (attempt.Progress > 1m && !achievementType.AllowOverAchievement)
            {
                attempt.Progress = 1m;
            }

            var isSuccess = progress >= 1m;

            var startDate = dpStart.SelectedDate ?? RockDateTime.Today;
            var endDate   = dpEnd.SelectedDate;

            if (!endDate.HasValue && isSuccess && !achievementType.AllowOverAchievement)
            {
                endDate = RockDateTime.Today;
            }

            if (endDate.HasValue && endDate < startDate)
            {
                endDate = startDate;
            }

            attempt.IsClosed = (endDate.HasValue && endDate.Value < RockDateTime.Today) || (isSuccess && !achievementType.AllowOverAchievement);
            attempt.AchievementAttemptStartDateTime = startDate;
            attempt.AchievementAttemptEndDateTime   = endDate;
            attempt.Progress     = progress;
            attempt.IsSuccessful = isSuccess;

            if (!attempt.IsValid)
            {
                // Controls will render the error messages
                return;
            }

            try
            {
                var rockContext = GetRockContext();
                rockContext.SaveChanges();

                if (!attempt.IsAuthorized(Authorization.VIEW, CurrentPerson))
                {
                    attempt.AllowPerson(Authorization.VIEW, CurrentPerson, rockContext);
                }

                if (!attempt.IsAuthorized(Authorization.EDIT, CurrentPerson))
                {
                    attempt.AllowPerson(Authorization.EDIT, CurrentPerson, rockContext);
                }

                if (!attempt.IsAuthorized(Authorization.ADMINISTRATE, CurrentPerson))
                {
                    attempt.AllowPerson(Authorization.ADMINISTRATE, CurrentPerson, rockContext);
                }
            }
            catch (Exception ex)
            {
                ShowBlockException(nbEditModeMessage, ex);
                return;
            }

            // If the save was successful, reload the page using the new record Id.
            NavigateToPage(RockPage.Guid, new Dictionary <string, string> {
                { PageParameterKey.AchievementAttemptId, attempt.Id.ToString() }
            });
        }
示例#8
0
        /// <summary>
        /// Create new attempt records and return them in a list. All new attempts should be after the most recent successful attempt.
        /// </summary>
        /// <param name="achievementTypeCache">The achievement type cache.</param>
        /// <param name="streak">The streak.</param>
        /// <param name="mostRecentClosedAttempt">The most recent closed attempt.</param>
        /// <returns></returns>
        protected override List <AchievementAttempt> CreateNewAttempts(AchievementTypeCache achievementTypeCache, Streak streak, AchievementAttempt mostRecentClosedAttempt)
        {
            var rockContext       = new RockContext();
            var streakTypeService = new StreakTypeService(rockContext);
            var streakTypeCache   = StreakTypeCache.Get(streak.StreakTypeId);

            // Validate the attribute values
            var numberToAchieve = GetAttributeValue(achievementTypeCache, AttributeKey.NumberToAchieve).AsInteger();

            if (numberToAchieve <= 0)
            {
                ExceptionLogService.LogException($"StreakAchievement.CreateNewAttempts cannot process because the NumberToAchieve attribute is less than 1");
                return(null);
            }

            var attributeTimespanDays = GetAttributeValue(achievementTypeCache, AttributeKey.TimespanInDays).AsIntegerOrNull();

            if (attributeTimespanDays.HasValue && attributeTimespanDays.Value <= 0)
            {
                ExceptionLogService.LogException($"StreakAchievement.CreateNewAttempts cannot process because the TimespanInDays attribute is less than 1");
                return(null);
            }

            // Calculate the date range where new achievements can be validly found
            var attributeMinDate = GetAttributeValue(achievementTypeCache, AttributeKey.StartDateTime).AsDateTime();
            var attributeMaxDate = GetAttributeValue(achievementTypeCache, AttributeKey.EndDateTime).AsDateTime();
            var minDate          = CalculateMinDateForAchievementAttempt(streak.EnrollmentDate, mostRecentClosedAttempt, attributeMinDate, numberToAchieve);
            var maxDate          = CalculateMaxDateForAchievementAttempt(minDate, attributeMaxDate);

            // Get the max date that streaks can be broken. This is to avoid breaking streaks while people still have time to
            // engage in that day or week (because it is the current day or week)
            var maxDateForStreakBreaking = StreakTypeService.GetMaxDateForStreakBreaking(streakTypeCache);

            // Track the attempts in a list that will be returned. The int is the streak count for that attempt
            var attempts = new List <AchievementAttempt>();
            var streaks  = new List <ComputedStreak>();

            // Define what happens for each bit in the date range
            bool iterationAction(int currentUnit, DateTime currentDate, bool hasOccurrence, bool hasEngagement, bool hasExclusion)
            {
                // If there is an engagement and a timespan, then this is a possible attempt. If there is no timespan then only one
                // attempt needs to be tracked at a time
                if (hasOccurrence && hasEngagement && (attributeTimespanDays.HasValue || !streaks.Any()))
                {
                    streaks.Add(new ComputedStreak(currentDate));
                }
                else if (hasOccurrence && !hasEngagement && !hasExclusion && streaks.Any())
                {
                    // Break the streaks and close an attempt if there is an unexcused absence
                    var longestStreak = streaks.First();
                    attempts.Add(GetAttemptFromStreak(longestStreak, numberToAchieve, currentDate <= maxDateForStreakBreaking));
                    streaks.Clear();
                    return(false);
                }

                for (var i = streaks.Count - 1; i >= 0; i--)
                {
                    var computedStreak = streaks[i];

                    if (hasOccurrence && hasEngagement)
                    {
                        // Increment the streak
                        computedStreak.Count++;
                        computedStreak.EndDate = currentDate;

                        // Check for a fulfilled attempt
                        if (computedStreak.Count >= numberToAchieve)
                        {
                            streaks.Clear();

                            if (achievementTypeCache.AllowOverAchievement)
                            {
                                streaks.Add(computedStreak);
                                i = 0;
                            }
                            else
                            {
                                attempts.Add(GetAttemptFromStreak(computedStreak, numberToAchieve, !achievementTypeCache.AllowOverAchievement));
                                break;
                            }
                        }
                    }

                    // If there is a timespan and this streak is too old, then the attempt is closed
                    if (attributeTimespanDays.HasValue)
                    {
                        var inclusiveAge = (currentDate - computedStreak.StartDate).Days + 1;

                        if (inclusiveAge >= attributeTimespanDays.Value)
                        {
                            var timedOutAttempt = GetAttemptFromStreak(computedStreak, numberToAchieve, true);
                            attempts.Add(timedOutAttempt);
                            streaks.RemoveAt(i);

                            // Remove more recently started streaks that started before the next valid start date (based
                            // on the deficiency of this timed out attempt)
                            var nextValidStartDate = CalculateMinDateForAchievementAttempt(streak.EnrollmentDate, timedOutAttempt, attributeMinDate, numberToAchieve);

                            for (var j = streaks.Count - 1; j >= i; j--)
                            {
                                var moreRecentStreak = streaks[j];

                                if (moreRecentStreak.StartDate < nextValidStartDate)
                                {
                                    streaks.RemoveAt(j);
                                }
                            }
                        }
                    }
                }

                return(false);
            }

            // Iterate through the streak date for the date range specified
            streakTypeService.IterateStreakMap(streakTypeCache, streak.PersonAliasId, minDate, maxDate, iterationAction, out var errorMessage);

            if (!errorMessage.IsNullOrWhiteSpace())
            {
                ExceptionLogService.LogException($"StreakAchievement.CreateNewAttempts got an error calling StreakTypeService.IterateStreakMap: {errorMessage}");
                return(null);
            }

            // The longest leftover streak is an open attempt
            if (streaks.Any())
            {
                var longestStreak = streaks.First();
                attempts.Add(GetAttemptFromStreak(longestStreak, numberToAchieve, false));
            }

            return(attempts);
        }
示例#9
0
        /// <summary>
        /// Update the open attempt record if there are changes.
        /// </summary>
        /// <param name="openAttempt"></param>
        /// <param name="achievementTypeCache">The achievement type cache.</param>
        /// <param name="streak">The streak.</param>
        protected override void UpdateOpenAttempt(AchievementAttempt openAttempt, AchievementTypeCache achievementTypeCache, Streak streak)
        {
            var rockContext       = new RockContext();
            var streakTypeService = new StreakTypeService(rockContext);
            var streakTypeCache   = GetStreakTypeCache(achievementTypeCache);

            // Validate the attribute values
            var numberToAchieve = GetAttributeValue(achievementTypeCache, AttributeKey.NumberToAchieve).AsInteger();

            if (numberToAchieve <= 0)
            {
                ExceptionLogService.LogException($"StreakAchievement.UpdateOpenAttempt cannot process because the numberToAchieve attribute is less than 1");
                return;
            }

            var attributeTimespanDays = GetAttributeValue(achievementTypeCache, AttributeKey.TimespanInDays).AsIntegerOrNull();

            if (attributeTimespanDays.HasValue && attributeTimespanDays.Value <= 0)
            {
                ExceptionLogService.LogException($"StreakAchievement.UpdateOpenAttempt cannot process because the TimespanInDays attribute is less than 1");
                return;
            }

            // Calculate the date range where the open attempt can be validly fulfilled
            var attributeMaxDate = GetAttributeValue(achievementTypeCache, AttributeKey.EndDateTime).AsDateTime();
            var minDate          = openAttempt.AchievementAttemptStartDateTime;
            var maxDate          = CalculateMaxDateForAchievementAttempt(minDate, attributeMaxDate);

            // Get the max date that streaks can be broken. This is to avoid breaking streaks while people still have time to
            // engage in that day or week (because it is the current day or week)
            var maxDateForStreakBreaking = StreakTypeService.GetMaxDateForStreakBreaking(streakTypeCache);

            // Track the streak
            var computedStreak = new ComputedStreak(minDate)
            {
                EndDate = minDate
            };

            // Define what happens for each bit in the date range
            bool iterationAction(int currentUnit, DateTime currentDate, bool hasOccurrence, bool hasEngagement, bool hasExclusion)
            {
                var iterationCanStop = false;

                // If there is an engagement, then increment the streak
                if (hasOccurrence && hasEngagement)
                {
                    computedStreak.Count++;
                    computedStreak.EndDate = currentDate;

                    // Check for a fulfilled attempt
                    if (computedStreak.Count >= numberToAchieve)
                    {
                        ApplyStreakToAttempt(computedStreak, openAttempt, numberToAchieve, !achievementTypeCache.AllowOverAchievement);
                        iterationCanStop = !achievementTypeCache.AllowOverAchievement;
                    }
                }
                else if (hasOccurrence && !hasEngagement && !hasExclusion)
                {
                    // Break the streak and close the attempt if there is an unexcused absence
                    ApplyStreakToAttempt(computedStreak, openAttempt, numberToAchieve, currentDate <= maxDateForStreakBreaking);
                    iterationCanStop = true;
                }

                // If there is a timespan and this streak is too old, then the attempt is closed
                if (attributeTimespanDays.HasValue)
                {
                    var inclusiveAge = (currentDate - computedStreak.StartDate).Days + 1;

                    if (inclusiveAge >= attributeTimespanDays.Value)
                    {
                        ApplyStreakToAttempt(computedStreak, openAttempt, numberToAchieve, currentDate <= maxDateForStreakBreaking);
                        iterationCanStop = true;
                    }
                }

                return(iterationCanStop);
            }

            // Iterate through the streak date for the date range specified
            streakTypeService.IterateStreakMap(streakTypeCache, streak.PersonAliasId, minDate, maxDate, iterationAction, out var errorMessage);

            if (!errorMessage.IsNullOrWhiteSpace())
            {
                ExceptionLogService.LogException($"StreakAchievement.UpdateOpenAttempt got an error calling StreakTypeService.IterateStreakMap: {errorMessage}");
                return;
            }

            // If the attempt wasn't closed in the iteration, then it will remain open
            if (!openAttempt.IsClosed)
            {
                var progress = CalculateProgress(computedStreak.Count, numberToAchieve);

                openAttempt.Progress     = progress;
                openAttempt.IsSuccessful = progress >= 1m;
            }
        }
示例#10
0
        /// <summary>
        /// Create new attempt records and return them in a list. All new attempts should be after the most recent successful attempt.
        /// </summary>
        /// <param name="achievementTypeCache">The achievement type cache.</param>
        /// <param name="transaction">The financial transaction.</param>
        /// <param name="mostRecentSuccess">The most recent successful attempt.</param>
        /// <returns></returns>
        private List <AchievementAttempt> CreateNewAttempts(AchievementTypeCache achievementTypeCache, FinancialTransaction transaction, AchievementAttempt mostRecentSuccess)
        {
            // Validate the attribute values
            var numberToAccumulate = GetAttributeValue(achievementTypeCache, AttributeKey.NumberToAccumulate).AsInteger();

            if (numberToAccumulate <= 0)
            {
                ExceptionLogService.LogException($"{GetType().Name}. CreateNewAttempts cannot process because the NumberToAccumulate attribute is less than 1");
                return(null);
            }

            // Calculate the date range where new achievements can be validly found
            var attributeMinDate = GetAttributeValue(achievementTypeCache, AttributeKey.StartDateTime).AsDateTime();
            var attributeMaxDate = GetAttributeValue(achievementTypeCache, AttributeKey.EndDateTime).AsDateTime();
            var minDate          = CalculateMinDateForAchievementAttempt(DateTime.MinValue, mostRecentSuccess, attributeMinDate, numberToAccumulate);
            var maxDate          = CalculateMaxDateForAchievementAttempt(minDate, attributeMaxDate);

            // Track the attempts in a list that will be returned
            var            attempts     = new List <AchievementAttempt>();
            ComputedStreak accumulation = null;

            // Get the transaction dates and begin calculating attempts
            var transactionDates = GetOrderedFinancialTransactionDatesByPerson(achievementTypeCache, transaction.AuthorizedPersonAlias.PersonId, minDate, maxDate);

            foreach (var transactionDate in transactionDates)
            {
                if (!transactionDate.HasValue)
                {
                    // Nothing we can do without a date
                    continue;
                }

                if (accumulation == null)
                {
                    accumulation = new ComputedStreak(transactionDate.Value);
                }

                // Increment the accumulation
                accumulation.Count++;
                accumulation.EndDate = transactionDate;

                // Check for a fulfilled attempt
                if (accumulation.Count >= numberToAccumulate)
                {
                    attempts.Add(GetAttempt(accumulation, numberToAccumulate, true));

                    if (!achievementTypeCache.AllowOverAchievement)
                    {
                        accumulation = null;
                    }
                }
            }

            // The leftover accumulation is an open attempt
            if (accumulation != null)
            {
                var openAttempt = GetAttempt(accumulation, numberToAccumulate, false);
                var lastAttempt = attempts.LastOrDefault();

                if (null == lastAttempt ||
                    openAttempt.Progress != lastAttempt.Progress ||
                    openAttempt.AchievementAttemptStartDateTime != lastAttempt.AchievementAttemptStartDateTime ||
                    openAttempt.AchievementAttemptEndDateTime != lastAttempt.AchievementAttemptEndDateTime)
                {
                    attempts.Add(openAttempt);
                }
            }

            return(attempts);
        }
示例#11
0
        /// <summary>
        /// Processes the specified achievement type cache for the source entity.
        /// </summary>
        /// <param name="rockContext">The rock context.</param>
        /// <param name="achievementTypeCache">The achievement type cache.</param>
        /// <param name="sourceEntity">The source entity.</param>
        /// <returns>The set of attempts that were created or updated</returns>
        public override HashSet <AchievementAttempt> Process(RockContext rockContext, AchievementTypeCache achievementTypeCache, IEntity sourceEntity)
        {
            var step            = sourceEntity as Step;
            var updatedAttempts = new HashSet <AchievementAttempt>();

            // If we cannot link the step to a person, then there is nothing to do
            if (step == null)
            {
                return(updatedAttempts);
            }

            // If the achievement type is not active (or null) then there is nothing to do
            if (achievementTypeCache?.IsActive != true)
            {
                return(updatedAttempts);
            }

            // If there are unmet prerequisites, then there is nothing to do
            var achievementTypeService = new AchievementTypeService(rockContext);
            var unmetPrerequisites     = achievementTypeService.GetUnmetPrerequisites(achievementTypeCache.Id, step.PersonAliasId);

            if (unmetPrerequisites.Any())
            {
                return(updatedAttempts);
            }

            // Get all of the attempts for this program and achievement combo, ordered by start date DESC so that
            // the most recent attempts can be found with FirstOrDefault
            var achievementAttemptService = new AchievementAttemptService(rockContext);
            var attempts = achievementAttemptService.Queryable()
                           .Where(aa =>
                                  aa.AchievementTypeId == achievementTypeCache.Id &&
                                  aa.AchieverEntityId == step.PersonAliasId)
                           .ToList()
                           .OrderByDescending(aa => aa.AchievementAttemptStartDateTime)
                           .ToList();

            var mostRecentSuccess = attempts.FirstOrDefault(saa => saa.AchievementAttemptEndDateTime.HasValue && saa.IsSuccessful);

            // This component does not allow more than one success
            if (mostRecentSuccess != null)
            {
                return(updatedAttempts);
            }

            var currentAttempt = attempts.LastOrDefault();

            if (currentAttempt == null)
            {
                currentAttempt = new AchievementAttempt
                {
                    AchieverEntityId  = step.PersonAliasId,
                    AchievementTypeId = achievementTypeCache.Id
                };

                achievementAttemptService.Add(currentAttempt);
            }

            var attributeMinDate       = GetAttributeValue(achievementTypeCache, AttributeKey.StartDateTime).AsDateTime();
            var attributeMaxDate       = GetAttributeValue(achievementTypeCache, AttributeKey.EndDateTime).AsDateTime();
            var completedStepTypeDates = GetCompletedStepTypeDates(achievementTypeCache, step.PersonAliasId, attributeMinDate, attributeMaxDate);

            var stepProgram   = GetStepProgramCache(achievementTypeCache);
            var stepTypeCount = stepProgram.StepTypes.Count;

            var progress     = CalculateProgress(completedStepTypeDates.Count, stepTypeCount);
            var isSuccessful = progress >= 1m;

            currentAttempt.AchievementAttemptStartDateTime = completedStepTypeDates.Any() ? completedStepTypeDates.First() : RockDateTime.Today;
            currentAttempt.AchievementAttemptEndDateTime   = completedStepTypeDates.Any() ? completedStepTypeDates.Last() : RockDateTime.Today;
            currentAttempt.Progress     = progress;
            currentAttempt.IsClosed     = isSuccessful;
            currentAttempt.IsSuccessful = isSuccessful;

            return(updatedAttempts);
        }
示例#12
0
 /// <summary>
 /// Create new attempt records and return them in a list. All new attempts should be after the most recent successful attempt.
 /// </summary>
 /// <param name="achievementTypeCache">The achievement type cache.</param>
 /// <param name="streak">The streak.</param>
 /// <param name="mostRecentSuccess">The most recent successful attempt.</param>
 /// <returns></returns>
 protected abstract List <AchievementAttempt> CreateNewAttempts(AchievementTypeCache achievementTypeCache, Streak streak, AchievementAttempt mostRecentSuccess);
示例#13
0
 /// <summary>
 /// Update the open attempt record if there are changes. Be sure to close the attempt if it is no longer possible to make
 /// progress on this open attempt.
 /// </summary>
 /// <param name="openAttempt">The open attempt.</param>
 /// <param name="achievementTypeCache">The achievement type cache.</param>
 /// <param name="streak">The streak.</param>
 protected abstract void UpdateOpenAttempt(AchievementAttempt openAttempt, AchievementTypeCache achievementTypeCache, Streak streak);