Пример #1
0
        private bool RewardTraining(Member m, Dictionary <Guid, TrainingCourse> courses, Dictionary <Guid, ComputedTrainingAward> awards, TrainingRule rule, DateTime?completed, DateTime?expiry, string newAwardsString)
        {
            IEnumerable <string> results = newAwardsString.Split('+');
            bool awarded = false;

            foreach (string result in results)
            {
                string[] parts  = result.Split(':');
                Guid     course = new Guid(parts[0]);

                if (!courses.ContainsKey(course))
                {
                    throw new InvalidOperationException("Found bad rule: Adds course with ID" + course.ToString());
                }

                if (parts.Length > 1)
                {
                    if (parts[1] == "default")
                    {
                        if (courses[course].ValidMonths.HasValue)
                        {
                            expiry = completed.Value.AddMonths(courses[course].ValidMonths.Value);
                        }
                        else
                        {
                            expiry = null;
                        }
                    }
                    else
                    {
                        expiry = completed.Value.AddMonths(int.Parse(parts[1]));
                    }
                }


                if (awards.ContainsKey(course) && expiry > awards[course].Expiry)
                {
                    awards[course].Completed = completed;
                    awards[course].Expiry    = expiry;
                    awards[course].Rule      = rule;
                    awarded = true;
                    System.Diagnostics.Debug.WriteLineIf(m.LastName == "Kedan", string.Format("Updating existing record {0}, new expiry: {1}", courses[course].DisplayName, expiry));
                }
                else if (!awards.ContainsKey(course))
                {
                    ComputedTrainingAward newAward = new ComputedTrainingAward {
                        Course = courses[course], Member = m, Completed = completed, Expiry = expiry, Rule = rule
                    };
                    awards.Add(course, newAward);
                    this.ComputedTrainingAwards.Add(newAward);
                    awarded = true;
                    System.Diagnostics.Debug.WriteLineIf(m.LastName == "Kedan", string.Format("Add new record {0}, new expiry: {1}", courses[course].DisplayName, expiry));
                }
            }
            return(awarded);
        }
        protected bool RewardTraining(Member m, Dictionary <Guid, TrainingCourse> courses, Dictionary <Guid, ComputedTrainingAward> awards, TrainingRule rule, DateTime?completed, DateTime?expiry, string newAwardsString)
        {
            IEnumerable <string> results = newAwardsString.Split('+');
            bool awarded = false;

            foreach (string result in results)
            {
                string[] parts  = result.Split(':');
                Guid     course = new Guid(parts[0]);

                if (!courses.ContainsKey(course))
                {
                    throw new InvalidOperationException("Found bad rule: Adds course with ID" + course.ToString());
                }

                if (parts.Length > 1)
                {
                    if (parts[1] == "default")
                    {
                        if (courses[course].ValidMonths.HasValue)
                        {
                            expiry = completed.Value.AddMonths(courses[course].ValidMonths.Value);
                        }
                        else
                        {
                            expiry = null;
                        }
                    }
                    else
                    {
                        expiry = completed.Value.AddMonths(int.Parse(parts[1]));
                    }
                }


                if (awards.ContainsKey(course) && expiry > awards[course].Expiry)
                {
                    awards[course].Completed = completed;
                    awards[course].Expiry    = expiry;
                    awards[course].Rule      = rule;
                    awarded = true;
                }
                else if (!awards.ContainsKey(course))
                {
                    ComputedTrainingAward newAward = new ComputedTrainingAward {
                        Course = courses[course], Member = m, Completed = completed, Expiry = expiry, Rule = rule
                    };
                    awards.Add(course, newAward);
                    db.ComputedTrainingAwards.Add(newAward);
                    awarded = true;
                }
            }
            return(awarded);
        }
Пример #3
0
        public static CompositeTrainingStatus Compute(Member m, IEnumerable <ComputedTrainingAward> awards, IEnumerable <TrainingCourse> courses, DateTime when)
        {
            CompositeTrainingStatus result = new CompositeTrainingStatus();

            foreach (TrainingCourse course in courses)
            {
                TrainingStatus status = new TrainingStatus {
                    CourseId = course.Id, CourseName = course.DisplayName, Expires = null, Status = ExpirationFlags.Unknown
                };

                bool mustHave               = m.IsTrainingRequired(course);
                bool keepCurrent            = m.ShouldKeepCourseCurrent(course);
                ComputedTrainingAward award = awards.Where(f => f.Course.Id == course.Id).FirstOrDefault();
                if (award == null)
                {
                    // No record - member has not completed the training
                    status.Status = mustHave ? ExpirationFlags.Missing : ExpirationFlags.NotNeeded;
                }
                else if ((course.ValidMonths ?? 0) == 0)
                {
                    // A record without an expiration
                    status.Status    = ExpirationFlags.Complete;
                    status.Completed = award.Completed;
                }
                else
                {
                    // A record that has an expiration

                    status.Expires   = award.Expiry;
                    status.Completed = award.Completed;
                    status.Status    = (mustHave && keepCurrent)
                                     ? ((award.Expiry < when) ? ExpirationFlags.Expired : ExpirationFlags.NotExpired)
                                     : ExpirationFlags.Complete;
                }
                result.Expirations.Add(course.Id, status);

                // Ugh. Now we get to perpetuate a hack for a change in requirements for crime scene with a period when we ignored expired crime scene.
                if (!(course.DisplayName == "Crime Scene" && status.Expires > new DateTime(2007, 03, 01) && when > new DateTime(2010, 6, 3) && when < new DateTime(2010, 11, 12)))
                {
                    result.IsGood = result.IsGood && ((status.Status & ExpirationFlags.Okay) == ExpirationFlags.Okay);
                }
            }
            return(result);
        }
Пример #4
0
        private bool RewardTraining(Member m, Dictionary<Guid, TrainingCourse> courses, Dictionary<Guid, ComputedTrainingAward> awards, TrainingRule rule, DateTime? completed, DateTime? expiry, string newAwardsString)
        {
            IEnumerable<string> results = newAwardsString.Split('+');
              bool awarded = false;

              foreach (string result in results)
              {
            string[] parts = result.Split(':');
            Guid course = new Guid(parts[0]);

            if (!courses.ContainsKey(course))
            {
              throw new InvalidOperationException("Found bad rule: Adds course with ID" + course.ToString());
            }

            if (parts.Length > 1)
            {
              if (parts[1] == "default")
              {
            if (courses[course].ValidMonths.HasValue)
            {
              expiry = completed.Value.AddMonths(courses[course].ValidMonths.Value);
            }
            else
            {
              expiry = null;
            }
              }
              else
              {
            expiry = completed.Value.AddMonths(int.Parse(parts[1]));
              }
            }

            if (awards.ContainsKey(course) && expiry > awards[course].Expiry)
            {
              awards[course].Completed = completed;
              awards[course].Expiry = expiry;
              awards[course].Rule = rule;
              awarded = true;
              System.Diagnostics.Debug.WriteLineIf(m.LastName == "Kedan", string.Format("Updating existing record {0}, new expiry: {1}", courses[course].DisplayName, expiry));
            }
            else if (!awards.ContainsKey(course))
            {
              ComputedTrainingAward newAward = new ComputedTrainingAward { Course = courses[course], Member = m, Completed = completed, Expiry = expiry, Rule = rule };
              awards.Add(course, newAward);
              this.ComputedTrainingAwards.Add(newAward);
              awarded = true;
              System.Diagnostics.Debug.WriteLineIf(m.LastName == "Kedan", string.Format("Add new record {0}, new expiry: {1}", courses[course].DisplayName, expiry));
            }
              }
              return awarded;
        }
Пример #5
0
        public List<ComputedTrainingAward[]> RecalculateTrainingAwards(IEnumerable<Member> members, DateTime time)
        {
            List<ComputedTrainingAward[]> retVal = new List<ComputedTrainingAward[]>();

              // TODO: only use the rules in effect at time 'time'
              List<TrainingRule> rules = (from r in this.TrainingRules select r).ToList();

              Dictionary<Guid, TrainingCourse> courses = (from c in this.TrainingCourses select c).ToDictionary(x => x.Id);

              foreach (Member m in members)
              {
            foreach (ComputedTrainingAward award in (from a in this.ComputedTrainingAwards where a.Member.Id == m.Id select a))
            {
              this.ComputedTrainingAwards.Remove(award);
            }

            // Sort by expiry and completed dates to handle the case of re-taking a course that doesn't expire.
            var direct = (from a in this.TrainingAward.Include("Course") where a.Member.Id == m.Id && a.Completed <= time select a)
            .OrderBy(f => f.Course.Id).ThenByDescending(f => f.Expiry).ThenByDescending(f => f.Completed);

            Dictionary<Guid, ComputedTrainingAward> awards = new Dictionary<Guid, ComputedTrainingAward>();

            Guid lastCourse = Guid.Empty;
            foreach (TrainingAward a in direct)
            {
              if (this.Entry(a).State == EntityState.Deleted)
              {
            continue;
              }

              if (a.Course.Id != lastCourse)
              {
            var ca = new ComputedTrainingAward(a);
            awards.Add(a.Course.Id, ca);
            this.ComputedTrainingAwards.Add(ca);
            lastCourse = a.Course.Id;
              }
            }

            bool awardInLoop = false;
            do
            {
              awardInLoop = false;

              foreach (TrainingRule rule in rules)
              {
            //  source>result>prerequisite
            string[] fields = rule.RuleText.Split('>');

            if (fields.Length > 2)
            {
              var prereqs = fields[2].Split('+');
              // Keep going only if /all/ of the prereqs are met by /any/ of the existing awards,
              if (!prereqs.All(f => awards.Keys.Any(g => g.ToString().Equals(f, StringComparison.OrdinalIgnoreCase))))
              {
                continue;
              }
            }

            if (fields[0].StartsWith("Mission"))
            {
              //Mission(12:%:36)
              Match match = Regex.Match(fields[0], @"Mission\((\d+):([^:]+):(\d+)\)", RegexOptions.IgnoreCase);
              if (match.Success == false)
              {
                throw new InvalidOperationException("Can't understand rule: " + fields[0]);
              }

              int requiredHours = int.Parse(match.Groups[1].Value);
              string missionType = match.Groups[2].Value;
              int monthSpan = int.Parse(match.Groups[3].Value);

              var missions = (from r in this.MissionRosters where r.Person.Id == m.Id && r.TimeIn < time select r);
              if (missionType != "%")
              {
                missions = missions.Where(x => x.Mission.MissionType.Contains(missionType));
              }
              missions = missions.OrderByDescending(x => x.TimeIn);

              double sum = 0;
              DateTime startDate = DateTime.Now;
              foreach (MissionRoster roster in missions)
              {
                if (roster.TimeIn.HasValue && (roster.InternalRole != MissionRoster.ROLE_IN_TOWN && roster.InternalRole != MissionRoster.ROLE_NO_ROLE))
                {
                  startDate = roster.TimeIn.Value;
                  sum += roster.Hours ?? 0.0;

                  if (sum > requiredHours)
                  {
                    awardInLoop |= RewardTraining(m, courses, awards, rule, startDate, startDate.AddMonths(monthSpan), fields[1]);
                    break;
                  }
                }
              }
            }
            else
            {
              //Guid? sourceCourse = fields[0].ToGuid();

              //if (sourceCourse == null)
              //{
              //    throw new InvalidOperationException("Unknown rule type: " + rule.Id);
              //}

              //if (awards.ContainsKey(sourceCourse.Value))
              //{
              //    System.Diagnostics.Debug.WriteLineIf(m.LastName == "Kedan", string.Format("Applying rule using {0}, {1}", courses[sourceCourse.Value].DisplayName, awards[sourceCourse.Value].Completed));
              //    RewardTraining(m, courses, awards, rule, awards[sourceCourse.Value].Completed, awards[sourceCourse.Value].Expiry, fields[1]);
              //}
              Guid?[] sources = fields[0].Split('+').Select(f => f.ToGuid()).ToArray();

              if (sources.Any(f => f == null))
              {
                throw new InvalidOperationException("Unknown rule type: " + rule.Id);
              }

              if (sources.All(f => awards.ContainsKey(f.Value)))
              {
                DateTime? completed = sources.Max(f => awards[f.Value].Completed);
                DateTime? expiry = null;
                if (sources.Any(f => awards[f.Value].Expiry != null))
                {
                  expiry = sources.Min(f => awards[f.Value].Expiry ?? DateTime.MaxValue);
                }
                awardInLoop |= RewardTraining(m, courses, awards, rule, completed, expiry, fields[1]);
              }
            }
              }
            } while (awardInLoop);
            retVal.Add(awards.Values.ToArray());
              }
              return retVal;
        }
Пример #6
0
        public List <ComputedTrainingAward[]> RecalculateTrainingAwards(IEnumerable <Member> members, DateTime time)
        {
            List <ComputedTrainingAward[]> retVal = new List <ComputedTrainingAward[]>();

            // TODO: only use the rules in effect at time 'time'
            List <TrainingRule> rules = (from r in this.TrainingRules select r).ToList();

            Dictionary <Guid, TrainingCourse> courses = (from c in this.TrainingCourses select c).ToDictionary(x => x.Id);

            foreach (Member m in members)
            {
                foreach (ComputedTrainingAward award in (from a in this.ComputedTrainingAwards where a.Member.Id == m.Id select a))
                {
                    this.ComputedTrainingAwards.Remove(award);
                }

                // Sort by expiry and completed dates to handle the case of re-taking a course that doesn't expire.
                var direct = (from a in this.TrainingAward.Include("Course") where a.Member.Id == m.Id && a.Completed <= time select a)
                             .OrderBy(f => f.Course.Id).ThenByDescending(f => f.Expiry).ThenByDescending(f => f.Completed);

                Dictionary <Guid, ComputedTrainingAward> awards = new Dictionary <Guid, ComputedTrainingAward>();

                Guid lastCourse = Guid.Empty;
                foreach (TrainingAward a in direct)
                {
                    if (this.Entry(a).State == EntityState.Deleted)
                    {
                        continue;
                    }

                    if (a.Course.Id != lastCourse)
                    {
                        var ca = new ComputedTrainingAward(a);
                        awards.Add(a.Course.Id, ca);
                        this.ComputedTrainingAwards.Add(ca);
                        lastCourse = a.Course.Id;
                    }
                }

                bool awardInLoop = false;
                do
                {
                    awardInLoop = false;

                    foreach (TrainingRule rule in rules)
                    {
                        //  source>result>prerequisite
                        string[] fields = rule.RuleText.Split('>');

                        if (fields.Length > 2)
                        {
                            var prereqs = fields[2].Split('+');
                            // Keep going only if /all/ of the prereqs are met by /any/ of the existing awards,
                            if (!prereqs.All(f => awards.Keys.Any(g => g.ToString().Equals(f, StringComparison.OrdinalIgnoreCase))))
                            {
                                continue;
                            }
                        }

                        if (fields[0].StartsWith("Mission"))
                        {
                            //Mission(12:%:36)
                            Match match = Regex.Match(fields[0], @"Mission\((\d+):([^:]+):(\d+)\)", RegexOptions.IgnoreCase);
                            if (match.Success == false)
                            {
                                throw new InvalidOperationException("Can't understand rule: " + fields[0]);
                            }

                            int    requiredHours = int.Parse(match.Groups[1].Value);
                            string missionType   = match.Groups[2].Value;
                            int    monthSpan     = int.Parse(match.Groups[3].Value);

                            var missions = (from r in this.MissionRosters where r.Person.Id == m.Id && r.TimeIn < time select r);
                            if (missionType != "%")
                            {
                                missions = missions.Where(x => x.Mission.MissionType.Contains(missionType));
                            }
                            missions = missions.OrderByDescending(x => x.TimeIn);

                            double   sum       = 0;
                            DateTime startDate = DateTime.Now;
                            foreach (MissionRoster roster in missions)
                            {
                                if (roster.TimeIn.HasValue && (roster.InternalRole != MissionRoster.ROLE_IN_TOWN && roster.InternalRole != MissionRoster.ROLE_NO_ROLE))
                                {
                                    startDate = roster.TimeIn.Value;
                                    sum      += roster.Hours ?? 0.0;

                                    if (sum > requiredHours)
                                    {
                                        awardInLoop |= RewardTraining(m, courses, awards, rule, startDate, startDate.AddMonths(monthSpan), fields[1]);
                                        break;
                                    }
                                }
                            }
                        }
                        else
                        {
                            //Guid? sourceCourse = fields[0].ToGuid();

                            //if (sourceCourse == null)
                            //{
                            //    throw new InvalidOperationException("Unknown rule type: " + rule.Id);
                            //}

                            //if (awards.ContainsKey(sourceCourse.Value))
                            //{
                            //    System.Diagnostics.Debug.WriteLineIf(m.LastName == "Kedan", string.Format("Applying rule using {0}, {1}", courses[sourceCourse.Value].DisplayName, awards[sourceCourse.Value].Completed));
                            //    RewardTraining(m, courses, awards, rule, awards[sourceCourse.Value].Completed, awards[sourceCourse.Value].Expiry, fields[1]);
                            //}
                            Guid?[] sources = fields[0].Split('+').Select(f => f.ToGuid()).ToArray();

                            if (sources.Any(f => f == null))
                            {
                                throw new InvalidOperationException("Unknown rule type: " + rule.Id);
                            }

                            if (sources.All(f => awards.ContainsKey(f.Value)))
                            {
                                DateTime?completed = sources.Max(f => awards[f.Value].Completed);
                                DateTime?expiry    = null;
                                if (sources.Any(f => awards[f.Value].Expiry != null))
                                {
                                    expiry = sources.Min(f => awards[f.Value].Expiry ?? DateTime.MaxValue);
                                }
                                awardInLoop |= RewardTraining(m, courses, awards, rule, completed, expiry, fields[1]);
                            }
                        }
                    }
                } while (awardInLoop);
                retVal.Add(awards.Values.ToArray());
            }
            return(retVal);
        }