/// <summary> /// 时间发生改变(清除所有时间规则) /// </summary> public static void TimeChanged(string localID, ICommonDataManager CommonDataManager) { var rule = CommonDataManager.GetMixedRule(localID); var algo = CommonDataManager.GetMixedAlgoRule(localID); if (rule != null) { rule.TeacherTimes?.Clear(); rule.CourseLimits?.Clear(); rule.CourseTimes?.Clear(); rule.ArrangeContinuous?.Clear(); rule.Serialize(localID); } if (algo != null) { algo.TeacherNotAvailableTimes?.Clear(); algo.ClassHourRequiredStartingTimes?.Clear(); algo.ClassHourRequiredTimes?.Clear(); algo.ClassHoursRequiredStartingTimes?.Clear(); algo.ClassHoursRequiredTimes?.Clear(); algo.ClassHourRequiredStartingTime?.Clear(); algo.ClassHoursMaxConcurrencyInSelectedTimes?.Clear(); algo.ClassHoursOccupyMaxTimeFromSelections?.Clear(); algo.Serialize(localID); } }
public static void TeacherChanged(Models.Base.UITeacher teacher, string localID, ICommonDataManager CommonDataManager) { var rule = CommonDataManager.GetMixedRule(localID); var algo = CommonDataManager.GetMixedAlgoRule(localID); var cl = CommonDataManager.GetCLCase(localID); if (cl != null) { cl.Classes?.ForEach(c => { c.TeacherIDs?.RemoveAll(t => t.Contains(teacher.ID)); }); cl.ClassHours?.ForEach(ch => { ch.TeacherIDs?.RemoveAll(t => t.Contains(teacher.ID)); }); cl.Serialize(localID); } if (rule != null) { rule.TeacherTimes?.RemoveAll(t => t.TeacherID.Contains(teacher.ID)); rule.MaxGapsPerDay?.RemoveAll(t => t.TeacherID.Contains(teacher.ID)); rule.MaxDaysPerWeek?.RemoveAll(t => t.TeacherID.Contains(teacher.ID)); rule.MaxHoursDaily?.RemoveAll(t => t.TeacherID.Contains(teacher.ID)); rule.Serialize(localID); } if (algo != null) { algo.TeacherMaxGapsPerDays?.RemoveAll(t => t.TeacherID.Equals(teacher.ID)); algo.TeacherMaxHoursDailys?.RemoveAll(t => t.TeacherID.Equals(teacher.ID)); algo.TeacherMaxDaysPerWeeks?.RemoveAll(t => t.TeacherID.Equals(teacher.ID)); algo.TeacherNotAvailableTimes?.RemoveAll(t => t.TeacherID.Equals(teacher.ID)); algo.Serialize(localID); } }
public static void ClassHourChanged(string localID, ICommonDataManager CommonDataManager) { var rule = CommonDataManager.GetMixedRule(localID); var algo = CommonDataManager.GetMixedAlgoRule(localID); var cl = CommonDataManager.GetCLCase(localID); if (rule != null) { OSKernel.Presentation.Models.Enums.MixedRuleEnum.ClassHourSameOpen.DeleteRule(localID); rule.ClassHourSameOpens?.Clear(); rule.ClassHourAverages?.Clear(); rule.CourseTimes?.Clear(); rule.ArrangeContinuous?.Clear(); rule.AmPmClassHours?.Clear(); rule.Serialize(localID); } if (algo != null) { algo.ClassHoursSameStartingDays?.Clear(); algo.ClassHoursSameStartingTimes?.Clear(); algo.ClassHoursSameStartingHours?.Clear(); algo.TwoClassHoursContinuous?.Clear(); algo.TwoClassHoursOrdered?.Clear(); algo.TwoClassHoursGrouped?.Clear(); algo.ThreeClassHoursGrouped?.Clear(); algo.MinDaysBetweenClassHours?.Clear(); algo.ClassHourRequiredStartingTimes?.Clear(); algo.ClassHourRequiredTimes?.Clear(); algo.MaxDaysBetweenClassHours?.Clear(); algo.ClassHoursNotOverlaps?.Clear(); algo.ClassHourRequiredStartingTime?.Clear(); algo.ClassHoursMaxConcurrencyInSelectedTimes?.Clear(); algo.ClassHoursOccupyMaxTimeFromSelections?.Clear(); algo.Serialize(localID); } }
/// <summary> /// 是否可以拖拽替换 /// </summary> /// <param name="localID">本地方案ID</param> /// <param name="sourceItems">原始拖拽源</param> /// <param name="targetItems">目标拖拽源</param> /// <param name="resultModel">结果模型</param> /// <returns></returns> public static Tuple <bool, string> CanReplacePosition(string localID, List <ResultDetailModel> sourceItems, List <ResultDetailModel> targetItems, ResultModel resultModel) { ICommonDataManager commonDataManager = CacheManager.Instance.UnityContainer.Resolve <ICommonDataManager>(); var cl = commonDataManager.GetCLCase(localID); var rule = commonDataManager.GetMixedRule(localID); var algo = commonDataManager.GetMixedAlgoRule(localID); var positionsSource = GetMovablePositons(localID, sourceItems, resultModel); var positionsTarget = GetMovablePositons(localID, targetItems, resultModel); DayPeriodModel dpSource = sourceItems.FirstOrDefault().DayPeriod; DayPeriodModel dpTarget = targetItems.FirstOrDefault().DayPeriod; if (dpTarget != null && positionsSource.Item1.Exists(dp => dp.Day == dpTarget.Day && dp.PeriodName == dpTarget.PeriodName) && dpSource != null && positionsTarget.Item1.Exists(dp => dp.Day == dpSource.Day && dp.PeriodName == dpSource.PeriodName)) { return(Tuple.Create(true, string.Empty)); } else { var sourceToTargetWarning = positionsSource.Item2.Where(dp => dp.DayPeriod.Day == dpTarget.Day && dp.DayPeriod.PeriodName == dpTarget.PeriodName).ToList(); var targetToSourceWarning = positionsTarget.Item2.Where(dp => dp.DayPeriod.Day == dpSource.Day && dp.DayPeriod.PeriodName == dpSource.PeriodName).ToList(); StringBuilder sb = new StringBuilder(100); sourceToTargetWarning?.ForEach(w => { sb.AppendLine(w.WaringMessage); }); targetToSourceWarning?.ForEach(w => { sb.AppendLine(w.WaringMessage); }); return(Tuple.Create(false, sb.ToString())); } }
public static void CourseChanged(List <Models.Mixed.UICourse> courses, string localID, ICommonDataManager CommonDataManager) { var rule = CommonDataManager.GetMixedRule(localID); var algo = CommonDataManager.GetMixedAlgoRule(localID); var cl = CommonDataManager.GetCLCase(localID); if (rule != null) { courses.ForEach(c => { var classes = cl.Classes.Where(cc => cc.CourseID.Equals(c.ID))?.ToList(); classes?.ForEach(tc => { rule.CourseTimes?.RemoveAll(r => r.ClassID.Equals(tc.ID)); rule.ArrangeContinuous?.RemoveAll(r => r.ClassID.Equals(tc.ID)); rule.ClassHourAverages?.RemoveAll(r => r.ClassID.Equals(tc.ID)); rule.ClassHourSameOpens?.Clear(); }); rule.AmPmClassHours?.RemoveAll(r => r.CourseID.Equals(c.ID)); rule.CourseLimits?.RemoveAll(r => r.CourseID.Equals(c.ID)); }); } if (algo != null) { var classHours = cl.ClassHours.Where(ch => courses.Any(c => ch.CourseID.Equals(c.ID)))?.ToList(); classHours?.ForEach(ch => { algo.ClassHoursSameStartingDays?.ForEach(a => { var ids = a.ID?.ToList(); ids?.RemoveAll(ri => ri.Equals(ch.ID)); a.ID = ids?.ToArray(); }); algo.ClassHoursSameStartingDays?.RemoveAll(a => a.ID?.Count() == 0); algo.ClassHoursSameStartingTimes?.ForEach(a => { var ids = a.ID?.ToList(); ids?.RemoveAll(ri => ri.Equals(ch.ID)); a.ID = ids?.ToArray(); }); algo.ClassHoursSameStartingTimes?.RemoveAll(a => a.ID?.Count() == 0); algo.ClassHoursSameStartingHours?.ForEach(a => { var ids = a.ID?.ToList(); ids?.RemoveAll(ri => ri.Equals(ch.ID)); a.ID = ids?.ToArray(); }); algo.ClassHoursSameStartingHours?.RemoveAll(a => a.ID?.Count() == 0); algo.MinDaysBetweenClassHours?.ForEach(a => { var ids = a.ID?.ToList(); ids?.RemoveAll(ri => ri.Equals(ch.ID)); a.ID = ids?.ToArray(); }); algo.MinDaysBetweenClassHours?.RemoveAll(a => a.ID?.Count() == 0); algo.MaxDaysBetweenClassHours?.ForEach(a => { var ids = a.ID?.ToList(); ids?.RemoveAll(ri => ri.Equals(ch.ID)); a.ID = ids?.ToArray(); }); algo.MaxDaysBetweenClassHours?.RemoveAll(a => a.ID?.Count() == 0); algo.ClassHoursNotOverlaps?.ForEach(a => { var ids = a.ID?.ToList(); ids?.RemoveAll(ri => ri.Equals(ch.ID)); a.ID = ids?.ToArray(); }); algo.ClassHoursNotOverlaps?.RemoveAll(a => a.ID?.Count() == 0); algo.ClassHoursMaxConcurrencyInSelectedTimes?.ForEach(a => { var ids = a.ID?.ToList(); ids?.RemoveAll(ri => ri.Equals(ch.ID)); a.ID = ids?.ToArray(); }); algo.ClassHoursMaxConcurrencyInSelectedTimes?.RemoveAll(a => a.ID?.Count() == 0); algo.ClassHoursOccupyMaxTimeFromSelections?.ForEach(a => { var ids = a.ID?.ToList(); ids?.RemoveAll(ri => ri.Equals(ch.ID)); a.ID = ids?.ToArray(); }); algo.ClassHoursOccupyMaxTimeFromSelections?.RemoveAll(a => a.ID?.Count() == 0); algo.TwoClassHoursContinuous?.RemoveAll(r => r.FirstID.Equals(ch.ID) || r.SecondID.Equals(ch.ID)); algo.TwoClassHoursOrdered?.RemoveAll(r => r.FirstID.Equals(ch.ID) || r.SecondID.Equals(ch.ID)); algo.TwoClassHoursGrouped?.RemoveAll(r => r.FirstID.Equals(ch.ID) || r.SecondID.Equals(ch.ID)); algo.ThreeClassHoursGrouped?.RemoveAll(r => r.FirstID.Equals(ch.ID) || r.SecondID.Equals(ch.ID) || r.ThirdID.Equals(ch.ID)); algo.ClassHourRequiredStartingTimes?.RemoveAll(r => r.ID.Equals(ch.ID)); algo.ClassHourRequiredTimes?.RemoveAll(r => r.ID.Equals(ch.ID)); algo.ClassHourRequiredStartingTime?.RemoveAll(r => r.ID.Equals(ch.ID)); }); algo.Serialize(localID); } if (cl != null) { courses.ForEach(c => { cl.Courses.RemoveAll(dc => dc.ID.Equals(c.ID)); cl.Classes.RemoveAll(ch => ch.CourseID.Equals(c.ID)); cl.ClassHours.RemoveAll(ch => ch.CourseID.Equals(c.ID)); cl.Students?.ForEach(st => { st.Preselections?.RemoveAll(p => p.CourseID.Equals(c.ID)); }); }); cl.Serialize(localID); } }
private static Tuple <List <DayPeriodModel>, List <PostionWithWarningInfo> > GetMovablePositons(string localID, List <ResultDetailModel> item, ResultModel resultModel) { //可用课位,最后取反返回不可用课位 var dayPeriods = new List <DayPeriodModel>(); var notReachable = new List <PostionWithWarningInfo>(); ICommonDataManager commonDataManager = CacheManager.Instance.UnityContainer.Resolve <ICommonDataManager>(); var cl = commonDataManager.GetCLCase(localID); var rule = commonDataManager.GetMixedRule(localID); var algo = commonDataManager.GetMixedAlgoRule(localID); //获取方案可用时间 dayPeriods = cl?.Positions?.Where(p => p.IsSelected && p.Position != XYKernel.OS.Common.Enums.Position.AB && p.Position != XYKernel.OS.Common.Enums.Position.Noon && p.Position != XYKernel.OS.Common.Enums.Position.PB) ?.Select(d => d.DayPeriod)?.ToList() ?? new List <DayPeriodModel>(); //TODO: 是否基于现有模型更新结果模型中的教师信息? item?.ForEach(it => { var classHourInfo = cl.ClassHours.FirstOrDefault(c => c.ID == it.ClassHourId); string classID = classHourInfo?.ClassID ?? string.Empty; string courseID = classHourInfo?.CourseID ?? string.Empty; List <string> teachers = new List <string>(); teachers = it?.Teachers == null ? new List <string>() : it.Teachers.ToList(); //2.0 检查批量规则 - 仅查权重为高级的规则 rule?.TeacherTimes?.Where(t => t.Weight == 1 && teachers.Contains(t.TeacherID))?.ToList()?.ForEach(x => { if (x.ForbidTimes != null) { dayPeriods = TimeOperation.TimeSlotDiff(dayPeriods, x.ForbidTimes); x.ForbidTimes.ForEach(fb => { notReachable.Add(new PostionWithWarningInfo() { DayPeriod = fb, WaringMessage = $"教师在课位({TimeOperation.GetDateInfo(fb)})有禁止规则!" }); }); } if (x.MustTimes != null) { //必须时间暂不必查 } }); rule?.CourseTimes?.Where(c => c.Weight == 1 && c.ClassID == classID)?.ToList()?.ForEach(x => { if (x.ForbidTimes != null) { dayPeriods = TimeOperation.TimeSlotDiff(dayPeriods, x.ForbidTimes); x.ForbidTimes.ForEach(fb => { notReachable.Add(new PostionWithWarningInfo() { DayPeriod = fb, WaringMessage = $"课程在课位({TimeOperation.GetDateInfo(fb)})有禁止规则!" }); }); } if (x.MustTimes != null) { int classHourNumber = cl.ClassHours.Where(ch => ch.ClassID == classID && ch.CourseID == courseID).Count(); if (x.MustTimes.Count >= classHourNumber) { dayPeriods.ForEach(dp => { if (!x.MustTimes.Exists(mt => mt.Day == dp.Day && mt.PeriodName == dp.PeriodName)) { notReachable.Add(new PostionWithWarningInfo() { DayPeriod = dp, WaringMessage = "课程应先满足排到必须规则指定课位内!" }); } }); dayPeriods = TimeOperation.TimeSlotInterSect(dayPeriods, x.MustTimes); } else { List <DayPeriodModel> classHourTimes = resultModel.ResultClasses.Where(c => c.ClassID == classID) ?.SelectMany(c => c.ResultDetails) ?.Select(c => c.DayPeriod).ToList() ?? new List <DayPeriodModel>() { }; List <DayPeriodModel> classHoursInMust = TimeOperation.TimeSlotInterSect(x.MustTimes, classHourTimes); if (classHoursInMust.Count < x.MustTimes.Count) { dayPeriods.ForEach(dp => { if (!x.MustTimes.Exists(mt => mt.Day == dp.Day && mt.PeriodName == dp.PeriodName)) { notReachable.Add(new PostionWithWarningInfo() { DayPeriod = dp, WaringMessage = "课程应先满足排到必须规则指定课位内!" }); } }); dayPeriods = TimeOperation.TimeSlotInterSect(dayPeriods, x.MustTimes); } else { //如果课位在必须时间内,则只能和本班课时互换以保障课时优先在必须时间内 List <DayPeriodModel> mustTempTimes = TimeOperation.TimeSlotInterSect(x.MustTimes, new List <DayPeriodModel>() { it.DayPeriod }); if (mustTempTimes.Count == 1) { dayPeriods.ForEach(dp => { if (!classHourTimes.Exists(mt => mt.Day == dp.Day && mt.PeriodName == dp.PeriodName)) { notReachable.Add(new PostionWithWarningInfo() { DayPeriod = dp, WaringMessage = "课程应先满足排到必须规则指定课位内!" }); } }); dayPeriods = TimeOperation.TimeSlotInterSect(dayPeriods, classHourTimes); } } } } }); rule?.AmPmClassHours?.Where(a => a.Weight == 1 && a.ClassID == classID && a.CourseID == courseID)?.ToList()?.ForEach(x => { int pmNumber = 0; int amNumber = 0; var timePosition = cl.Positions.Where(p => p.DayPeriod.Day == it.DayPeriod.Day && p.DayPeriod.PeriodName == it.DayPeriod.PeriodName).FirstOrDefault(); var classHours = resultModel.ResultClasses?.Where(c => c.ClassID == classID) ?.SelectMany(c => c.ResultDetails)?.ToList(); classHours?.ForEach(c => { var tPosition = cl.Positions.Where(p => p.DayPeriod.Day == c.DayPeriod.Day && p.DayPeriod.PeriodName == c.DayPeriod.PeriodName).FirstOrDefault(); if (tPosition != null) { if (tPosition.Position == XYKernel.OS.Common.Enums.Position.AM) { amNumber = amNumber + 1; } if (tPosition.Position == XYKernel.OS.Common.Enums.Position.PM) { pmNumber = pmNumber + 1; } } }); //If current time slot is AM, And PMMax is full, Disable PM if (timePosition.Position == XYKernel.OS.Common.Enums.Position.AM) { if (x.PmMax > 0 && pmNumber >= x.PmMax) { //Disable PM var pmTimes = cl.Positions.Where(p => p.IsSelected && p.Position == XYKernel.OS.Common.Enums.Position.PM).Select(p => p.DayPeriod).ToList(); dayPeriods = TimeOperation.TimeSlotDiff(dayPeriods, pmTimes); pmTimes.ForEach(pt => { notReachable.Add(new PostionWithWarningInfo() { DayPeriod = pt, WaringMessage = "违反班级课程的下午最大课时规则!" }); }); } if (x.AmMax > 0 && amNumber > x.AmMax) { //Disable AM var amTimes = cl.Positions.Where(p => p.IsSelected && p.Position == XYKernel.OS.Common.Enums.Position.AM).Select(p => p.DayPeriod).ToList(); dayPeriods = TimeOperation.TimeSlotDiff(dayPeriods, amTimes); amTimes.ForEach(pt => { notReachable.Add(new PostionWithWarningInfo() { DayPeriod = pt, WaringMessage = "违反班级课程的上午最大课时规则!" }); }); } } //If current time slot is PM, And AMMax is full, Disable AM if (timePosition.Position == XYKernel.OS.Common.Enums.Position.PM) { if (x.AmMax > 0 && amNumber >= x.AmMax) { //Disable AM var amTimes = cl.Positions.Where(p => p.IsSelected && p.Position == XYKernel.OS.Common.Enums.Position.AM).Select(p => p.DayPeriod).ToList(); dayPeriods = TimeOperation.TimeSlotDiff(dayPeriods, amTimes); amTimes.ForEach(at => { notReachable.Add(new PostionWithWarningInfo() { DayPeriod = at, WaringMessage = "违反班级课程的上午最大课时规则!" }); }); } if (x.PmMax > 0 && pmNumber > x.PmMax) { //Disable PM var pmTimes = cl.Positions.Where(p => p.IsSelected && p.Position == XYKernel.OS.Common.Enums.Position.PM).Select(p => p.DayPeriod).ToList(); dayPeriods = TimeOperation.TimeSlotDiff(dayPeriods, pmTimes); pmTimes.ForEach(at => { notReachable.Add(new PostionWithWarningInfo() { DayPeriod = at, WaringMessage = "违反班级课程的下午最大课时规则!" }); }); } } }); }); return(Tuple.Create(dayPeriods, notReachable)); }