diff --git a/HFUTCourseSimulation/Course.cs b/HFUTCourseSimulation/Course.cs deleted file mode 100644 index 4cedf03..0000000 --- a/HFUTCourseSimulation/Course.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows.Media; - -namespace HFUTCourseSimulation { - - public class Semester { - - public Semester() { - this.Courses = new List(); - StartDate = DateTime.Today.ToString(); - WeekCount = 1; - } - - public string StartDate { get; set; } - public int WeekCount { get; set; } - public List Courses { get; set; } - } - - public class CourseItem { - - public CourseItem() { - //BkColor = Colors.LightBlue.ColorToInt(); - this.Schedule = new List(); - } - - public string Name { get; set; } - public string Description { get; set; } - public int BkColor { get; set; } - - public List Schedule { get; set; } - - public CourseItem Clone() { - var newobj = new CourseItem(); - newobj.Name = this.Name; - newobj.Description = this.Description; - newobj.BkColor = this.BkColor; - newobj.Schedule = new List(); - newobj.Schedule.AddRange((from item in this.Schedule select item.Clone())); - return newobj; - } - } - - public class ScheduleItem { - public string Week { get; set; } - public string Day { get; set; } - public string Index { get; set; } - - public ScheduleItem Clone() { - return new ScheduleItem() { Week = this.Week, Index = this.Index, Day = this.Day }; - } - public override string ToString() { - return Week + " - " + Day + " - " + Index; - } - } - -} diff --git a/HFUTCourseSimulation/General.cs b/HFUTCourseSimulation/General.cs deleted file mode 100644 index b5cc3e9..0000000 --- a/HFUTCourseSimulation/General.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace HFUTCourseSimulation { - public static class General { - - public static Semester GeneralSheet; - - public static CourseItem CourseCache = new CourseItem(); - public static ScheduleItem ScheduleCache = new ScheduleItem(); - - public static string FilePath = ""; - - } -} diff --git a/HFUTCourseSimulation/HFUTCourseSimulation.csproj b/HFUTCourseSimulation/HFUTCourseSimulation.csproj index f868ca5..0cc3b3c 100644 --- a/HFUTCourseSimulation/HFUTCourseSimulation.csproj +++ b/HFUTCourseSimulation/HFUTCourseSimulation.csproj @@ -83,10 +83,12 @@ + + - + Simulation.xaml diff --git a/HFUTCourseSimulation/Kernel/Arranger.cs b/HFUTCourseSimulation/Kernel/Arranger.cs new file mode 100644 index 0000000..fafb2fd --- /dev/null +++ b/HFUTCourseSimulation/Kernel/Arranger.cs @@ -0,0 +1,234 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using HFUTCourseSimulation.Kernel.Data.Built; +using HFUTCourseSimulation.Util; + +namespace HFUTCourseSimulation.Kernel { + + /// + /// 一个标识符,用于指代学期中指定周的指定星期的指定节次 + /// + internal class ArrangerSpot : IEquatable { + public ArrangerSpot(int week, int day, int index) { + this.week = week; + this.day = day; + this.index = index; + } + + /// + /// 教学周 + /// + public int week; + /// + /// 星期几 + /// + public int day; + /// + /// 节次 + /// + public int index; + + public override bool Equals(object obj) { + return Equals(obj as ArrangerSpot); + } + + public bool Equals(ArrangerSpot other) { + return !(other is null) && + week == other.week && + day == other.day && + index == other.index; + } + + public override int GetHashCode() { + int hashCode = -206993699; + hashCode = hashCode * -1521134295 + week.GetHashCode(); + hashCode = hashCode * -1521134295 + day.GetHashCode(); + hashCode = hashCode * -1521134295 + index.GetHashCode(); + return hashCode; + } + + public static bool operator ==(ArrangerSpot left, ArrangerSpot right) { + return EqualityComparer.Default.Equals(left, right); + } + + public static bool operator !=(ArrangerSpot left, ArrangerSpot right) { + return !(left == right); + } + } + + /// + /// 课程安排器。 + /// 负责将课程安排到每周之中,并提示用户错误等各种信息。 + /// + public class Arranger { + public Arranger(Kernel.Data.Storage.Semester semester) { + this.semester = semester; + arrangeMap = new Dictionary(); + reporter = new Reporter(); + } + + private Kernel.Data.Storage.Semester semester; + private Dictionary arrangeMap; + private Reporter reporter; + + /// + /// 获取汇报器用于查看安排日志 + /// + /// + public Reporter GetReporter() { + return reporter; + } + + /// + /// 开始安排课程 + /// + /// 安排好的,用于呈现的课程。如果安排失败,则为null,查看汇报器来了解具体差错 + public Kernel.Data.Presentation.Semester Arrange() { + reporter.Clear(); + arrangeMap.Clear(); + return ConcludeCourses(); + } + + /// + /// 检查用户输入的学期数据是否正确 + /// + /// 如果检查无误,返回检查后的结果,否则返回null + private Semester CheckSemester() { + // 检查Semester + 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 courses = new List(); + foreach (var course in semester.Courses) { + // 检查课程(实际上只有安排需要检查) + var schedules = new List(); + + foreach (var schedule in course.Schedules) { + // 检查安排 + if + + + } + + // OK,插入课程 + courses.Add(new Course() { + name = course.Name, + description = course.Description, + color = ColorTrans.ToStandardColorPair(course.Color), + schedules = schedules + }); + } + + // OK无误,返回结果 + return new Semester() { + startDate = semester.StartDate, + weekCount = weekCount, + indexCount = indexCount, + breakfastAt = breakfastAt, + lunchAt = lunchAt, + dinnerAt = dinnerAt, + courses = courses + }; + } + + /// + /// 安排课程 + /// + /// 安排无误返回true,否则返回false + private bool ArrangeCourses() { + // Check it first + var rv = CheckSemester(); + if (rv is null) return false; + + // 遍历所有课程安排开始排课 + bool okey = true; + for (int course_index = 0; course_index < rv.courses.Count; ++course_index) { + var course = rv.courses[course_index]; + foreach (var schedule in course.schedules) { + foreach (var week in schedule.week) { + foreach (var day in schedule.day) { + foreach (var index in schedule.index) { + var spot = new ArrangerSpot(week, day, index); + if (arrangeMap.TryGetValue(spot, out int occupied_course_index)) { + var occupied_course = rv.courses[occupied_course_index]; + reporter.Error($"课程冲突:无法将{course.name}安排到周{week},星期{day},第{index}节。因为此处已被{occupied_course.name}占据"); + okey = false; + } else { + arrangeMap.Add(spot, course_index); + } + } + } + } + } + } + return okey; + } + + /// + /// 将安排好的课程总结为方便渲染的结果 + /// + /// + private Kernel.Data.Presentation.Semester ConcludeCourses() { + // Arrange it first + var rv = ArrangeCourses(); + if (!rv) return null; + + return null; + } + + } +} diff --git a/HFUTCourseSimulation/Kernel/Data/Built.cs b/HFUTCourseSimulation/Kernel/Data/Built.cs new file mode 100644 index 0000000..e363849 --- /dev/null +++ b/HFUTCourseSimulation/Kernel/Data/Built.cs @@ -0,0 +1,61 @@ +using Newtonsoft.Json.Linq; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HFUTCourseSimulation.Kernel.Data.Built { + + public class Semester { + public DateTime startDate; + public int weekCount, indexCount; + public int breakfastAt, lunchAt, dinnerAt; + public List courses; + } + + public class Course { + public string name, description; + public Util.ColorPair color; + public List schedules; + } + + public class Schedule { + public IEnumerable week; + public IEnumerable day; + public IEnumerable index; + } + + public class IndividualInt : IEnumerable { + public IndividualInt(IEnumerable it) { + _values = it.ToList(); + } + + private List _values; + + public IEnumerator GetEnumerator() { + return _values.GetEnumerator(); + } + IEnumerator IEnumerable.GetEnumerator() { + return GetEnumerator(); + } + } + + public class RangedInt : IEnumerable { + public RangedInt(int start, int end) { + this._start = start; + this._end = end; + } + + private int _start, _end; + + public IEnumerator GetEnumerator() { + return Enumerable.Range(_start, _end).GetEnumerator(); + } + IEnumerator IEnumerable.GetEnumerator() { + return GetEnumerator(); + } + } + +} diff --git a/HFUTCourseSimulation/Kernel/MsgRecorder.cs b/HFUTCourseSimulation/Kernel/Reporter.cs similarity index 68% rename from HFUTCourseSimulation/Kernel/MsgRecorder.cs rename to HFUTCourseSimulation/Kernel/Reporter.cs index 1139393..bff3347 100644 --- a/HFUTCourseSimulation/Kernel/MsgRecorder.cs +++ b/HFUTCourseSimulation/Kernel/Reporter.cs @@ -5,12 +5,12 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace HFUTCourseSimulation.Kernel.MsgRecorder { +namespace HFUTCourseSimulation.Kernel { /// /// 消息的类型 /// - public enum Kind { + public enum ReporterKind { Info, Warning, Error @@ -19,57 +19,28 @@ namespace HFUTCourseSimulation.Kernel.MsgRecorder { /// /// 被记录的消息条目 /// - public class Entry { - public Entry(Kind kind, string message) { - this.kind = kind; - this.message = message; + public class ReporterEntry { + public ReporterEntry(ReporterKind kind, string message) { + this.Kind = kind; + this.Message = message; } - public readonly Kind kind; - public readonly string message; + public ReporterKind Kind { get; private set; } + public string Message { get; private set; } } /// /// 用于记录模拟过程中的消息(例如错误,警告等) /// - public class Recorder : IEnumerable { - public Recorder() { - entries = new List(); + public class Reporter : IEnumerable { + public Reporter() { + entries = new List(); hasError = false; } - private List entries; + private List entries; private bool hasError; - /// - /// 记录一条提示消息 - /// - /// 消息内容 - public void Info(string message) { - entries.Add(new Entry(Kind.Info, message)); - } - /// - /// 记录一条警告消息 - /// - /// 消息内容 - public void Warning(string message) { - entries.Add(new Entry(Kind.Warning, message)); - } - /// - /// 记录一条错误消息 - /// - /// 消息内容 - public void Error(string message) { - this.hasError = true; - entries.Add(new Entry(Kind.Error, message)); - } - - public IEnumerator GetEnumerator() { - return entries.GetEnumerator(); - } - IEnumerator IEnumerable.GetEnumerator() { - return GetEnumerator(); - } /// /// 检查过程中是否有错误类型的消息被记录 /// @@ -78,6 +49,28 @@ namespace HFUTCourseSimulation.Kernel.MsgRecorder { return hasError; } + /// + /// 记录一条提示消息 + /// + /// 消息内容 + public void Info(string message) { + entries.Add(new ReporterEntry(ReporterKind.Info, message)); + } + /// + /// 记录一条警告消息 + /// + /// 消息内容 + public void Warning(string message) { + entries.Add(new ReporterEntry(ReporterKind.Warning, message)); + } + /// + /// 记录一条错误消息 + /// + /// 消息内容 + public void Error(string message) { + this.hasError = true; + entries.Add(new ReporterEntry(ReporterKind.Error, message)); + } /// /// 重置记录器状态 /// @@ -86,6 +79,12 @@ namespace HFUTCourseSimulation.Kernel.MsgRecorder { hasError = false; } + public IEnumerator GetEnumerator() { + return entries.GetEnumerator(); + } + IEnumerator IEnumerable.GetEnumerator() { + return GetEnumerator(); + } } }