Skip to content

Latest commit

 

History

25 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

轮换课表(RotationClass)

ClassIsland 插件,自动处理课表里「轮流换着上」的课:每天算好今天该上什么并直接填好; 放假没上课就自动顺延,绝不跳内容。全部通过本地网页可视化配置,配置一次、天天省心。


它解决什么问题

很多学校的课表里,有几个固定时段的内容不是写死的,而是按顺序轮流换。比如:

  • 晚自习:晚自习,这周上语文、下周上英语、再下周上数学,三周一个循环
  • 周末加课:周六周日一整天的课在「轮 1 / 轮 2」两套排法之间一周一换

在 ClassIsland 里,需要你为每天这几节课创建好几张课表,再手动维护, 麻烦、容易错,放假顺延更是算不清楚。

轮换课表把这件事自动化:你只要配置一次轮换规则,插件每天自动找到今天用的课表、 算出今天每个轮换位置该上什么、直接填好——打开课表就是对的

核心特性

  • 每天自动填好:按你的轮换规则 + 当前进度,自动算出今天各轮换位置的内容并生效,不用手动改;
  • 放假自动顺延:只有真正上完课才轮到下一个内容。放假、停课那天没上课 → 不推进 → 内容顺延到下次, 不用关心节假日,也不会因为放假跳过内容;
  • 不动原始课表:内容通过「临时层」注入,基础课表原样保留。随时停用插件,课表恢复原状;
  • 可视化配置网页:浏览器里点选格子就能建轮换组、设轮换顺序,还能预览未来几周的排法;
  • 临时调课方便:哪天临时变了,网页里 一键改当天 / 从此节开始改 / 全局纠偏;
  • 手动优先:你自己手动设置的临时课表、临时层永远优先,插件绝不覆盖。

快速上手

  1. 安装插件:下载发布包 .cipx,应用内「设置 → 插件 → 导入插件包」导入,重启 ClassIsland;
  2. 打开配置网页:设置 → 插件 → 找到「轮换课表」→ 打开配置网页 (或直接访问 http://127.0.0.1:18757/);
  3. 配置轮换规则:网页里选中要轮换的格子 → 新建组 → 设置轮换序列(哪些科目 / 哪几张课表轮流)→ 保存;
  4. 完成:插件每天自动注入今天的内容;网页里能看到未来排课预览和每个组「下次上课」的时间。

配置一次,之后只在临时变动时偶尔打开网页纠偏一下即可。

配置网页能做什么

  • 点选课表格子建组 / 加组,可视化编辑轮换序列与当前进度(游标);
  • 预览:从今天、当前进度往后排,看未来几周每个轮换位置会是什么课;
  • 「本节为:」临时调课
    • 仅改当天:只改选中那一天的这一节;
    • 从此节开始:改这一节,并让后续排课从该内容继续;
    • 全局纠偏:直接调整整体轮换进度;
  • 每个组显示**「下次上课:M/D(周X) 时间 科目」**;
  • 所有修改立即生效并重新注入今天,无需手动保存。

工作原理

  1. 找到今天使用的课表ILessonsService.GetClassPlanByDate(today)(与窗口显示一致);
  2. 创建临时层:官方接口 CreateTempClassPlan(基础课表, 日期=today) —— 深度复制基础课表为独立临时层, 预定到今天(OrderedSchedules[today])。只改临时层副本,带「?」的基础课表原样保留, 规避了实测「内存改写被应用持久化」的污染问题;过期临时层由应用自动清理;
  3. 算出今天课表并注入:引擎 ResolveSlot(rules, state, 槽) 按规则 + 各组游标算出每个轮换位置该上什么, 写进临时层对应 Classes[i].SubjectId
  4. 顺延推进:订阅 OnClass(记录当前课)→ OnBreakingTime/OnAfterSchool(下课)时, 若该槽是推进点(unit 最后一槽;group 还要是最后一个 unit)→ 游标 +1 并落盘 state.json。 放假没上课 → 没事件 → 游标不动 → 自动顺延;
  5. 手动优先:用户手动设置的临时层 / 手动临时课表(TempClassPlanId)一律不覆盖; 同一天重新注入会先清掉插件自己上次创建的临时层再重建。

目录结构

RotationClass.csproj             ← 工程文件在仓库根(对齐官方 cipx-template 布局)
manifest.yml                    (id: com.classisland.rotationclass,name: 轮换课表)
src/                            ← 插件 C# 源代码
  Plugin.cs                     入口:接线服务 / 启动本地服务器 / 设置页
  PluginSettingsPage.cs         设置页(纯代码 Avalonia):打开网页 / 立即注入 / 状态
  Engine/                       C# 移植的引擎纯函数(与 web/core/*.js 一一对应)
    RotationEngine.cs           查找 / 显示 / 推进(resolveSlot / shouldAdvance / handleLessonEnd)
    RotationModels.cs           rules.json / state.json 数据模型(JSON 格式与网页一致)
    RotationRulesBuilder.cs     规则构建辅助(normalize / suggestUnits / 合并拆分)
    RotationValidator.cs        配置不变量校验(§8)
  Services/                     与 ClassIsland 应用服务对接的抽象层
    ServiceAbstractions.cs      注入器/推进钩子依赖的最小服务面(插件自定义接口)
    ServiceAdapters.cs          用 IProfileService / ILessonsService 实现的适配器
    StateStore.cs               插件配置目录 JSON 读写(rules.json / state.json / meta.json / log)
  DailyInjector.cs              每日流程:找课表→清旧临时层→CreateTempClassPlan→注入
  AdvanceHook.cs                下课事件推进游标(顺延机制)
  LocalWebServer.cs             HttpListener:提供 H5 页面 + /api/*(rules/state/profile/inject/log)

web/                             ← H5 配置页(统一存放;构建时打进插件 wwwroot/)
  index.html / app.js / style.css
  sample-rules.json              针对真实 Old.json 的示例规则(手动上传用)
  core/                           ESM 纯函数核心(node / 浏览器共用)
    engine.js / state.js / build.js / preview.js / validate.js / index.js
  serve.mjs                       极简静态服务器(ESM 需要 http 协议;npm run serve)

tests/                           ← 与主插件相关的测试
  RotationTest/                  C# 离线测试(不需要运行 ClassIsland,与插件共享 src/ 同一份源码)
  engine/                        JS 引擎 node 测试(§11 案例 + 真实档案冒烟)

docs/rotation-engine-design.md    引擎设计文档(§11 是测试案例)
build.sh                          一键构建 / 测试 / 打包(见下方用法)

注:仓库根同时保留 package.json(仅服务于 web 前端开发:npm test / npm run serve), 与 C# 插件构建(./build.sh)无关。

构建 / 测试 / 打包(Linux)

./build.sh                          # 构建插件 + 离线测试项目
./build.sh test                     # 构建并运行离线测试(RotationTest)
./build.sh package                  # 构建插件 + 打包官方插件包(.cipx + checksums.md)
./build.sh package --skip-build     # 跳过构建,直接用现有产物打包
CLASSISLAND_APP_DIR=... ./build.sh  # 指定应用目录(影响构建)

产物:bin/Release/(RotationClass.dll + manifest.yml + wwwroot/); ./build.sh package 额外生成 bin/Release/RotationClass-<版本>.cipx(官方插件包,zip 容器 + MD5)。

本地安装与调试(开发用,无需 MD5)

cp -r bin/Release/* /path/to/your/ClassIsland/data/Plugins/RotationClass/
# 重启 ClassIsland

启动后:

  • 日志:<应用>/data/Config/Plugins/com.classisland.rotationclass/rotation.log
  • 配置网页:http://127.0.0.1:18757/(应用设置 → 插件 → 本插件 → 打开配置网页)
  • 卸载:删掉 data/Plugins/RotationClass/data/Config/Plugins/com.classisland.rotationclass/

本地 API(插件模式网页用)

端点 说明
GET /api/status 插件状态(版本、最近注入、规则组数、档案路径)
GET /api/settings 应用设置快照:semesterStart(学期起始)、selectedProfiletoday
GET /api/profile 当前档案原始 JSON(从应用数据目录读取)
GET /api/week?start=YYYY-MM-DD&days=N 按天返回实际显示的课表(课表名、是否临时层、每节科目名+时间)
GET /api/rules / POST /api/rules 读 / 保存规则配置(保存后立即重注入今天)
GET /api/state / POST /api/state 读 / 保存游标状态(含 overrides 临时调课记录)
POST /api/override 「本节为:」临时调课/纠错 {date, groupId, planId, index, seqIndex, mode}(mode 1/2/3,立即落盘并重注入今天)
POST /api/override-delete 删除某天某格的覆盖记录 {date, planId, index}
POST /api/inject(也接受 GET) 立即重算今天的临时层(POST 需带 body,如 {}
GET /api/log 插件日志尾部

测试

C# 离线测试(不需要运行 ClassIsland)

./build.sh test   # 构建插件 + 测试项目,并运行离线测试

用真实档案 sample-rules.json 构造内存 Profile,跑插件同款源码:

  • 引擎 §11 案例 1~5(三周一循环 / 两节不跳课 / 重启幂等 / 整组推进 / 顺延);
  • 一周 7 天逐日注入:临时层创建、注入内容与引擎解析一致、基础课表「?」不被污染
  • 下课事件推进游标、手动临时层不覆盖、同一天重新注入清旧重建;
  • 本地配置服务器冒烟:/api/status、静态页面、/api/rules、/api/profile、POST /api/inject。

JS 引擎测试(web/ 前端共用核心)

npm test        # node --test tests/engine/*.test.js(§11 案例 + Old.json 真实数据)

Web 前端开发

网页代码统一放在仓库根 web/(含 web/core/ ESM 引擎),与插件 C# 代码分离; 构建时由 RotationClass.csproj 把整个 web/ 链接复制进插件 wwwroot/

npm run serve   # http://127.0.0.1:8080
  • 必须走 http(file:// 打开会被浏览器拦截模块加载);
  • 进入页面后由用户自己上传 Profile 档案与规则配置(两个文件选择框); web/sample-rules.json 是示例规则,可直接上传;
  • 主课表 = 官方课表页样式:工具栏左右箭头翻周(第 x 周 + 日期范围), 表头两行(星期+日期 / 课表名),每格显示该周该节「将上什么课」—— 组内 = 引擎解析结果 + 同组同色;未分组 = 原科目/「?」;格子内小字为准确上课时间;
  • 点任一格 → 右侧新建组 / 加入组 / 编辑序列与游标 / 模拟下课推进

About

轮换课表:解决「固定时段内容轮流换」的排课方式。课表里某些位置(如晚自习、周末加课)不固定,按顺序在几套内容间轮流上(如晚自习语数英循环、周末整表轮换);本插件每天自动算出今天各轮换位置该上什么并注入临时层,下课自动推进游标,放假没上课自动顺延。

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages