/// <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);
            }
        }
示例#4
0
        /// <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);
            }
        }
示例#6
0
        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));
        }