diff --git a/HFUTCourseSimulation/App.config b/HFUTCourseSimulation/App.config
index 8e15646..bcb2ae2 100644
--- a/HFUTCourseSimulation/App.config
+++ b/HFUTCourseSimulation/App.config
@@ -1,6 +1,14 @@
-
+
-
+
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
diff --git a/HFUTCourseSimulation/HFUTCourseSimulation.csproj b/HFUTCourseSimulation/HFUTCourseSimulation.csproj
index 2759d81..fffa8ea 100644
--- a/HFUTCourseSimulation/HFUTCourseSimulation.csproj
+++ b/HFUTCourseSimulation/HFUTCourseSimulation.csproj
@@ -8,10 +8,11 @@
WinExe
HFUTCourseSimulation
HFUTCourseSimulation
- v4.5
+ v4.8
512
{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
4
+
AnyCPU
@@ -37,8 +38,24 @@
..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll
+
+ ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+ ..\packages\System.Collections.Immutable.9.0.8\lib\net462\System.Collections.Immutable.dll
+
+
+ ..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll
+
+
+
+ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
@@ -60,6 +77,10 @@
+
+
+
+
Simulation.xaml
diff --git a/HFUTCourseSimulation/Kernel/Context.cs b/HFUTCourseSimulation/Kernel/Context.cs
new file mode 100644
index 0000000..06e24ea
--- /dev/null
+++ b/HFUTCourseSimulation/Kernel/Context.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HFUTCourseSimulation.Kernel {
+
+ public class Context {
+ private static Context s_Instance = new Context();
+ public static Context GetSingleton() { return s_Instance; }
+
+ private Context() {
+ currentSemester = null;
+ currentCourse = null;
+ currentSchedule = null;
+ }
+
+ private UserData.Semester currentSemester;
+ private UserData.Course currentCourse;
+ private UserData.Schedule currentSchedule;
+
+ }
+
+}
diff --git a/HFUTCourseSimulation/Kernel/MsgRecorder.cs b/HFUTCourseSimulation/Kernel/MsgRecorder.cs
new file mode 100644
index 0000000..1139393
--- /dev/null
+++ b/HFUTCourseSimulation/Kernel/MsgRecorder.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HFUTCourseSimulation.Kernel.MsgRecorder {
+
+ ///
+ /// 消息的类型
+ ///
+ public enum Kind {
+ Info,
+ Warning,
+ Error
+ }
+
+ ///
+ /// 被记录的消息条目
+ ///
+ public class Entry {
+ public Entry(Kind kind, string message) {
+ this.kind = kind;
+ this.message = message;
+ }
+
+ public readonly Kind kind;
+ public readonly string message;
+ }
+
+ ///
+ /// 用于记录模拟过程中的消息(例如错误,警告等)
+ ///
+ public class Recorder : IEnumerable {
+ public Recorder() {
+ entries = new List();
+ hasError = false;
+ }
+
+ 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();
+ }
+ ///
+ /// 检查过程中是否有错误类型的消息被记录
+ ///
+ /// 如果有则返回true,否则为false
+ public bool HasError() {
+ return hasError;
+ }
+
+ ///
+ /// 重置记录器状态
+ ///
+ public void Clear() {
+ entries.Clear();
+ hasError = false;
+ }
+
+ }
+
+}
diff --git a/HFUTCourseSimulation/Kernel/SimData.cs b/HFUTCourseSimulation/Kernel/SimData.cs
new file mode 100644
index 0000000..0bccdc6
--- /dev/null
+++ b/HFUTCourseSimulation/Kernel/SimData.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Drawing;
+
+namespace HFUTCourseSimulation.Kernel.SimData {
+
+ ///
+ /// 节次的类型
+ ///
+ public enum IndexKind {
+ ///
+ /// 破晓(太阳没升起前)
+ ///
+ Dawn,
+ ///
+ /// 上午(太阳升起后到正午)
+ ///
+ Morning,
+ ///
+ /// 下午(正午到太阳落山)
+ ///
+ Afternoon,
+ ///
+ /// 晚上(太阳落山后)
+ ///
+ Night
+ }
+
+ public class Semester {
+ ///
+ /// 学期开始日期。
+ /// 该类保证该日期一定是星期一,且没有时间数据。
+ ///
+ public readonly DateTime startDate;
+ ///
+ /// 教学周个数。
+ /// 该类保证该数值与weeks中存储的数据个数相同。
+ ///
+ public readonly int weekCount;
+ ///
+ /// 每天课程的节次数。
+ /// 该类保证该数值总是大于等于1。
+ ///
+ public readonly int indexCount;
+ ///
+ /// 早餐插入在第几节次后。
+ /// 该类保证该数值总是位于0至indexCount之间(含首尾)。
+ ///
+ public readonly int breakfastAt;
+ ///
+ /// 午餐插入在第几节次后。
+ /// 该类保证该数值总是位于0至indexCount之间(含首尾),
+ /// 且总是大于等于breakfastAt。
+ ///
+ public readonly int lunchAt;
+ ///
+ /// 晚餐插入在第几节次后。
+ /// 该类保证该数值总是位于0至indexCount之间(含首尾),
+ /// 且总是大于等于lunchAt。
+ ///
+ public readonly int dinnerAt;
+ ///
+ /// 每周课程数据。
+ ///
+ public readonly ImmutableList weeks;
+
+ public IndexKind GetIndexKind(int index) {
+ if (index <= 0) throw new ArgumentException("index out of range");
+ else if (index <= breakfastAt) return IndexKind.Dawn;
+ else if (index <= lunchAt) return IndexKind.Morning;
+ else if (index <= dinnerAt) return IndexKind.Afternoon;
+ else if (index <= indexCount) return IndexKind.Night;
+ else throw new ArgumentException("index out of range");
+ }
+ }
+
+ public class Week {
+ ///
+ /// 每周七天的数据。
+ /// 该类保证该字段总包含7项。
+ ///
+ public readonly ImmutableList days;
+ }
+
+ public class Day {
+ ///
+ /// 这一天的所有课程。
+ ///
+ public readonly ImmutableList lessons;
+ }
+
+ public class Lesson {
+ ///
+ /// 课程的名称。
+ ///
+ public readonly string name;
+ ///
+ /// 课程的说明,例如教室位置,教师姓名等。
+ /// 该值可以包含换行。
+ ///
+ public readonly string description;
+ ///
+ /// 课程的颜色
+ ///
+ public readonly Color color;
+ ///
+ /// 课程的起始节次。
+ /// 该类保证该值位于1到indexCount之间(含首尾)。
+ ///
+ public readonly int startIndex;
+ ///
+ /// 课程的结束节次。
+ /// 该类保证该值位于1到indexCount之间(含首尾),
+ /// 且大于等于startIndex。
+ ///
+ public readonly int endIndex;
+ }
+
+
+}
diff --git a/HFUTCourseSimulation/Kernel/UserData.cs b/HFUTCourseSimulation/Kernel/UserData.cs
new file mode 100644
index 0000000..d9a3116
--- /dev/null
+++ b/HFUTCourseSimulation/Kernel/UserData.cs
@@ -0,0 +1,155 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Drawing;
+using System.Globalization;
+using Newtonsoft.Json;
+
+namespace HFUTCourseSimulation.Kernel.UserData {
+
+ ///
+ /// 学期数据
+ ///
+ public class Semester {
+ public Semester() {
+ startDate = DateTime.Today;
+ weekCount = 20.ToString();
+ indexCount = 11.ToString();
+ breakfastAt = 0.ToString();
+ lunchAt = 4.ToString();
+ dinnerAt = 8.ToString();
+ courses = new List();
+ }
+
+ ///
+ /// 学期开始日期(星期一)
+ ///
+ [JsonProperty("start_date")]
+ [JsonConverter(typeof(CustomDateTimeConverter))]
+ public DateTime startDate;
+ ///
+ /// 教学周个数
+ ///
+ [JsonProperty("week_count")]
+ public string weekCount;
+ ///
+ /// 每天课程的节次数
+ ///
+ [JsonProperty("index_count")]
+ public string indexCount;
+ ///
+ /// 早餐插入在第几节次后
+ ///
+ [JsonProperty("breakfast_at")]
+ public string breakfastAt;
+ ///
+ /// 午餐插入在第几节次后
+ ///
+ [JsonProperty("lunch_at")]
+ public string lunchAt;
+ ///
+ /// 晚餐插入在第几节次后
+ ///
+ [JsonProperty("dinner_at")]
+ public string dinnerAt;
+ ///
+ /// 课程列表
+ ///
+ [JsonProperty("courses")]
+ public List courses;
+ }
+
+ public class Course {
+ public Course() {
+ name = "";
+ description = "";
+ color = Color.LightBlue;
+ schedules = new List();
+ }
+
+ ///
+ /// 课程的名称
+ ///
+ [JsonProperty("name")]
+ public string name;
+ ///
+ /// 课程的说明,例如教室位置,教师姓名等。
+ ///
+ [JsonProperty("description")]
+ public string description;
+ ///
+ /// 课程的颜色
+ ///
+ [JsonProperty("color")]
+ [JsonConverter(typeof(CustomColorConverter))]
+ public Color color;
+ ///
+ /// 课程的所有安排
+ ///
+ [JsonProperty("schedules")]
+ public List schedules;
+ }
+
+ public class Schedule {
+ public Schedule() {
+ week = "";
+ day = "";
+ index = "";
+ }
+
+ ///
+ /// 安排在哪些周
+ ///
+ [JsonProperty("week")]
+ public string week;
+ ///
+ /// 安排在周的星期几
+ ///
+ [JsonProperty("day")]
+ public string day;
+ ///
+ /// 安排在这些日子的哪些节次
+ ///
+ [JsonProperty("index")]
+ public string index;
+ }
+
+ internal class CustomDateTimeConverter : JsonConverter {
+ private static readonly string DATETIME_FORMAT = "yyyy-MM-dd";
+
+ public override DateTime ReadJson(JsonReader reader, Type objectType, DateTime existingValue, bool hasExistingValue, JsonSerializer serializer) {
+ if (reader.TokenType == JsonToken.String) {
+ var value = reader.Value as string;
+ if (DateTime.TryParseExact(value, DATETIME_FORMAT, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime rv)) {
+ return rv;
+ } else {
+ throw new JsonSerializationException($"given string can not be parsed as DateTime: {value}");
+ }
+ } else {
+ throw new JsonSerializationException($"expect a string but got {reader.TokenType}");
+ }
+ }
+
+ public override void WriteJson(JsonWriter writer, DateTime value, JsonSerializer serializer) {
+ writer.WriteValue(value.ToString(DATETIME_FORMAT, CultureInfo.InvariantCulture));
+ }
+ }
+
+ internal class CustomColorConverter : JsonConverter {
+ public override Color ReadJson(JsonReader reader, Type objectType, Color existingValue, bool hasExistingValue, JsonSerializer serializer) {
+ if (reader.TokenType == JsonToken.Integer) {
+ var argb = Convert.ToInt32(reader.Value);
+ return Color.FromArgb(argb);
+ } else {
+ throw new JsonSerializationException($"expect a integer but got {reader.TokenType}");
+ }
+ }
+
+ public override void WriteJson(JsonWriter writer, Color value, JsonSerializer serializer) {
+ writer.WriteValue(value.ToArgb());
+ }
+ }
+
+}
diff --git a/HFUTCourseSimulation/Properties/Resources.Designer.cs b/HFUTCourseSimulation/Properties/Resources.Designer.cs
index 9957e66..c48f6a9 100644
--- a/HFUTCourseSimulation/Properties/Resources.Designer.cs
+++ b/HFUTCourseSimulation/Properties/Resources.Designer.cs
@@ -1,53 +1,54 @@
//------------------------------------------------------------------------------
//
-// 此代码由工具生成。
-// 运行时版本: 4.0.30319.42000
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
//
-// 对此文件的更改可能导致不正确的行为,如果
-// 重新生成代码,则所做更改将丢失。
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
//
//------------------------------------------------------------------------------
namespace HFUTCourseSimulation.Properties {
-
-
+ using System;
+
+
///
- /// 强类型资源类,用于查找本地化字符串等。
+ /// A strongly-typed resource class, for looking up localized strings, etc.
///
- // 此类是由 StronglyTypedResourceBuilder
- // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
- // 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen
- // (以 /str 作为命令选项),或重新生成 VS 项目。
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
-
+
private static global::System.Resources.ResourceManager resourceMan;
-
+
private static global::System.Globalization.CultureInfo resourceCulture;
-
+
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
-
+
///
- /// 返回此类使用的缓存 ResourceManager 实例。
+ /// Returns the cached ResourceManager instance used by this class.
///
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
- if ((resourceMan == null)) {
+ if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("HFUTCourseSimulation.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
-
+
///
- /// 覆盖当前线程的 CurrentUICulture 属性
- /// 使用此强类型的资源类的资源查找。
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
///
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
diff --git a/HFUTCourseSimulation/Properties/Settings.Designer.cs b/HFUTCourseSimulation/Properties/Settings.Designer.cs
index ea7c749..9f57339 100644
--- a/HFUTCourseSimulation/Properties/Settings.Designer.cs
+++ b/HFUTCourseSimulation/Properties/Settings.Designer.cs
@@ -9,14 +9,14 @@
//------------------------------------------------------------------------------
namespace HFUTCourseSimulation.Properties {
-
-
+
+
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.14.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
-
+
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
-
+
public static Settings Default {
get {
return defaultInstance;
diff --git a/HFUTCourseSimulation/packages.config b/HFUTCourseSimulation/packages.config
index 7f83af3..dca5efc 100644
--- a/HFUTCourseSimulation/packages.config
+++ b/HFUTCourseSimulation/packages.config
@@ -1,4 +1,9 @@
+
+
+
+
+
\ No newline at end of file