diff --git a/HFUTCourseSimulation/HFUTCourseSimulation.csproj b/HFUTCourseSimulation/HFUTCourseSimulation.csproj index 0cc3b3c..2997690 100644 --- a/HFUTCourseSimulation/HFUTCourseSimulation.csproj +++ b/HFUTCourseSimulation/HFUTCourseSimulation.csproj @@ -74,14 +74,12 @@ MSBuild:Compile - EditCourse.xaml EditSchedule.xaml - diff --git a/HFUTCourseSimulation/Kernel/Arranger.cs b/HFUTCourseSimulation/Kernel/Arranger.cs index fafb2fd..c27361c 100644 --- a/HFUTCourseSimulation/Kernel/Arranger.cs +++ b/HFUTCourseSimulation/Kernel/Arranger.cs @@ -98,70 +98,48 @@ namespace HFUTCourseSimulation.Kernel { /// 如果检查无误,返回检查后的结果,否则返回null private Semester CheckSemester() { // 检查Semester + reporter.Info($"正在检查学期"); if (semester.StartDate.DayOfWeek != DayOfWeek.Monday) { reporter.Error($"起始日期{semester.StartDate:yyyy-MM-dd}不是星期一"); return null; } - int weekCount; - if (int.TryParse(semester.WeekCount, out weekCount)) { - if (weekCount <= 0) { - reporter.Error($"周数{semester.WeekCount}超出范围(必须大于0)"); - return null; - } - } else { - reporter.Error($"周数{semester.WeekCount}不是有效数字"); - return null; - } - int indexCount; - if (int.TryParse(semester.IndexCount, out indexCount)) { - if (indexCount <= 0) { - reporter.Error($"节次数{semester.IndexCount}超出范围(必须大于0)"); - return null; - } - } else { - reporter.Error($"节次数{semester.IndexCount}不是有效数字"); - return null; - } - int breakfastAt, lunchAt, dinnerAt; - if (int.TryParse(semester.BreakfastAt, out breakfastAt)) { - if (breakfastAt < 0 || breakfastAt > indexCount) { - reporter.Error($"早餐时间点{semester.BreakfastAt}超出范围(必须大于等于0且小于等于节次数)"); - return null; - } - } else { - reporter.Error($"早餐时间点{semester.BreakfastAt}不是有效数字"); - return null; - } - if (int.TryParse(semester.LunchAt, out lunchAt)) { - if (lunchAt < breakfastAt || lunchAt > indexCount) { - reporter.Error($"午餐时间点{semester.LunchAt}超出范围(必须大于等于早餐时间点且小于等于节次数)"); - return null; - } - } else { - reporter.Error($"午餐时间点{semester.LunchAt}不是有效数字"); - return null; - } - if (int.TryParse(semester.DinnerAt, out dinnerAt)) { - if (dinnerAt < lunchAt || dinnerAt > indexCount) { - reporter.Error($"晚餐时间点{semester.DinnerAt}超出范围(必须大于等于午餐时间点且小于等于节次数)"); - return null; - } - } else { - reporter.Error($"晚餐时间点{semester.DinnerAt}不是有效数字"); - return null; - } - + var rv = CheckInteger(semester.WeekCount, 1, 100, "周数", "0 < N"); + if (rv is null) return null; + int weekCount = rv.Value; + rv = CheckInteger(semester.IndexCount, 1, 100, "节次数", "0 < N"); + if (rv is null) return null; + int indexCount = rv.Value; + rv = CheckInteger(semester.BreakfastAt, 0, indexCount, "早餐时间点", "0 <= N <= 节次数"); + if (rv is null) return null; + int breakfastAt = rv.Value; + rv = CheckInteger(semester.LunchAt, breakfastAt, indexCount, "午餐时间点", "早餐时间点 <= N <= 节次数"); + if (rv is null) return null; + int lunchAt = rv.Value; + rv = CheckInteger(semester.DinnerAt, lunchAt, indexCount, "晚餐时间点", "午餐时间点 <= N <= 节次数"); + if (rv is null) return null; + int dinnerAt = rv.Value; var courses = new List(); foreach (var course in semester.Courses) { // 检查课程(实际上只有安排需要检查) + reporter.Info($"正在检查课程:{course.Name}"); + var schedules = new List(); foreach (var schedule in course.Schedules) { // 检查安排 - if - + var week = CheckIntegerCollection(schedule.Week, 1, weekCount, "周", "1 <= N <= 周数"); + var day = CheckIntegerCollection(schedule.Day, 1, 7, "星期", "1 <= N <= 7"); + var index = CheckIntegerCollection(schedule.Index, 1, indexCount, "节次", "1 <= N <= 节次数"); + // 如果格式均正确,就添加这个安排 + if (!(week is null || day is null || index is null)) { + schedules.Add(new Schedule() { + week = week, + day = day, + index = index + }); + } } // OK,插入课程 @@ -184,6 +162,96 @@ namespace HFUTCourseSimulation.Kernel { courses = courses }; } + /// + /// 检查整数的辅助函数。 + /// 检查范围时含提供的最小值min和最大值max。 + /// field_name是字段的名称,field_require是字段的要求,均用于用户提示。 + /// 返回null表示检查失败,否则返回检查好的值。 + /// + private int? CheckInteger(string s, int min, int max, string field_name, string field_require) { + if (int.TryParse(semester.WeekCount, out int rv)) { + if (rv < min || rv > max) { + reporter.Error($"{field_name}的值“{s}”超出范围。要求:{field_require}"); + return null; + } else { + return rv; + } + } else { + reporter.Error($"{field_name}的值“{s}”不是有效数字"); + return null; + } + } + /// + /// 整数集合的两种类型 + /// + private enum IntegerCollectionKind { + Individual, + Range + } + /// + /// 检查整数集合的辅助函数,即检查Schedule中的三个字段Week,Day和Index的格式。 + /// 各类参数含义与上面函数相同,只不过是作用到每一项上。 + /// + private IEnumerable CheckIntegerCollection(string s, int min, int max, string field_name, string field_require) { + // 两种整数集合所特有的字符常量,用于分割和分析 + const char COMMA = ','; + const char DASH = '-'; + + // 分析文本组成,决定其整数集合类型 + IntegerCollectionKind kind; + if (s.Contains(COMMA)) { + kind = IntegerCollectionKind.Individual; + } else if (s.Contains(DASH)) { + kind = IntegerCollectionKind.Range; + } else { + reporter.Error($"{field_name}的值“{s}”无法被解析"); + return null; + } + + // 根据整数集合类型,决定分割用字符 + char split_char; + switch (kind) { + case IntegerCollectionKind.Individual: + split_char = COMMA; + break; + case IntegerCollectionKind.Range: + split_char = DASH; + break; + default: + return null; + } + + // 开始分割文本并将每一项转换为整数,同时检查其范围 + var ints = new List(); + foreach (var part in s.Split(split_char).Select((i) => i.Trim())) { + if (int.TryParse(part, out int rv)) { + if (rv < min || rv > max) { + reporter.Error($"{field_name}的值“{s}”包含的整数超出范围。要求:{field_require}"); + return null; + } else { + ints.Add(rv); + } + } else { + reporter.Error($"{field_name}的值“{s}”包含无效的整数"); + return null; + } + } + + // 按整数集合类型进行收尾检查并返回 + switch (kind) { + case IntegerCollectionKind.Individual: + return new IndividualInt(ints); + case IntegerCollectionKind.Range: + if (ints.Count != 2) { + reporter.Error($"{field_name}的值“{s}”不是有效的整数范围表达式"); + return null; + } else { + return new RangedInt(ints[0], ints[1]); + } + default: + return null; + } + } /// /// 安排课程