Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

- 五阶段课程路径与阶段切换;
- 40 节课件的学习目标、讲授内容、检验清单和练习建议;
- 每节课的先修关系:这一课要先会哪几课、具体要先会哪一件事、上一课是哪一课,都写在页首标题正下方,点得进去;
- 本地保存的逐项学习进度,不收集账号或个人信息;浏览器拒绝保存时会明确说明,并可在恢复后重试补写;
- 适合外部录课制作时使用的“视频组织建议”和移动端阅读布局。

Expand Down Expand Up @@ -282,3 +283,19 @@ CSP_E2E_LESSONS=s3-07 bun tests/e2e/flow-cdp.ts # 只跑一课
新加的课自动纳入检查。步骤与仍需人工确认的部分见
[`tests/e2e/keyboard-manual-checklist.md`](./tests/e2e/keyboard-manual-checklist.md)。

## 先修关系可见与可达复验

「进页面第一眼就知道这节课要先会什么,而且点得回去」同样有自动化复验:`bun run e2e:prereq` 在真实浏览器里
对全部 40 课逐课复验,242 项检查(40 课各 6 项:5 项笔记本视口 + 1 项手机竖屏,另含脚本自检 2 项)。

每课六项:先修块(`<h1>` 正下方那一块)不点任何按钮就已渲染并且整块落在首屏内、块里的文字与 `courseData`
里的先修课一致、每条链接都真的能打开(链接条数等于先修课数加一条上一课)、只用 `Tab` 也走得到且焦点环可见、
鼠标真的点得进那一课(同一项里先用 `elementFromPoint` 确认没有被其它元素盖住)、换成手机竖屏 390×844 时
整块仍在首屏内。第一课(S1-01)没有先修,第 3、5 项换成「一条链接都没有」。

脚本自带两项自检:先往 S3-04 的先修块里临时插一条指向不存在课程的死链,确认链接可达性检查真的报错了
(证明这项检查不是空转),再确认页面已还原成仓库里的样子。先修块最初排在图例之后,手机竖屏上会掉到 1060px
(首屏之外),这一项就是那时量出来的;现在它排在标题正下方,同时由 `bun test` 里的
[`tests/prerequisite-path.test.ts`](./tests/prerequisite-path.test.ts) 锁住位置与文字。步骤、量测数据与仍需
人工确认的部分见 [`tests/e2e/prereq-manual-checklist.md`](./tests/e2e/prereq-manual-checklist.md)。

4 changes: 4 additions & 0 deletions docs/course-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@

“必会”指 CSP-J 路线的核心;“拓展”只能作为能力边界说明,不能代替前置课的练习。

每节课的页面在标题下方直接写明它的先修关系:要先会哪几课、具体要先会的那一件事,以及上一课入口。
先修数据只写在 `index.html` 的 `courseData` 里,页面与课程目录详情都从那里取,改一处不会漏改另一处;
第一课明确写明不用先修。

## 第一阶段:建立程序感

目标:从“会跟着敲代码”进步到“能独立写出、运行并修正一个小程序”。
Expand Down
2 changes: 2 additions & 0 deletions docs/feature-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
| --- | --- | --- |
| 五阶段学习路径 | 已完成 | 可切换阶段并查看阶段目标与课程数量 |
| 40 节 CSP-J C++ 课件目录 | 已完成 | 每节含目标、内容、检验清单、视频组织建议和练习建议 |
| 每节课的先修关系可见 | 已完成 | 每课页首标题正下方列出先修课号、课名与要会的那一件事,并给上一课入口;课程目录详情面板同步显示同一份数据 |
| 单课件详情阅读 | 已完成 | 点击任意课件卡片即可切换详情;键盘上下方向键也可切换 |
| 交互动作反馈 | 已完成 | 切换阶段、选择课件、筛选和修改进度后显示即时状态提示 |
| 逐项学习检验 | 已完成 | 可勾选、撤销勾选或一键完成当前课 |
Expand Down Expand Up @@ -112,6 +113,7 @@
| 40 节随机在线测试 | 已完成 | 每课从 5 至 7 道已通过校验的题库随机组卷;选择题数量严格多于非选择题;完成后展示得分、解析和复习出口;空题库或题目无效时明确告知并保留进度;每题把检查目标绑到本课学习目标原文并另起一行说明本题检查,未通过时按学习目标汇总错题 |
| 题库与组卷质量控制 | 已完成 | 每道题关联课程 ID、学习目标、难度、题型、正确答案、解析与来源;同次不重复,试卷用种子标识复现;题目统一标记为已通过机器校验。难度档位统一为必会 `required` / 建议掌握 `recommended` / 拓展 `stretch`,由 `tests/lesson-contract.test.ts` 逐课校验;抽出来的那 3 道题另由 `tests/quiz-paper-contract.test.ts` 在 256 个种子下校验题数、同次不重复、只出选择题、同一试卷标识可复现、题库内每题都抽得到,以及抽题不会就地改写题库 |
| 学习尝试恢复 | 已完成 | 保存失败(含会话中途失败)当次会话立刻可见、可点“重试保存”;恢复后说明“本地保存已恢复”并把期间待写进度补写落盘;词条表载入失败同样当场说明、可点“重新载入词条表”,恢复后回到刚才点开的词条。两类失败都不伪造成功 |
| 先修关系可见与可达 | 已完成 | 全部 40 课都由 `bun run e2e:prereq` 在无头 Chrome 里复验(242 项检查:40 课各 6 项,5 项笔记本视口 + 1 项手机竖屏,另含脚本自检 2 项),覆盖先修块整块落在首屏、文字与 `courseData` 一致、链接全部可达、键盘走得到焦点环可见、真实鼠标点击真的进得去,以及手机竖屏下的同一块 |
| 键盘可达与焦点可见 | 已完成 | 全部 40 课都由 `bun run e2e:keyboard` 在无头 Chrome 里发真实按键事件复验(328 项检查:结构检查每课 8 项 + S1-02 与 S3-01 的键盘深路径每课 4 项),覆盖 Tab 绕圈全程可见焦点环、无正数 tabindex 打乱顺序、音效开关 Space 可切换、词条 Enter/Escape 与焦点归还、步进门闩挡得住、提交后焦点交给结果区;`tests/keyboard-access-contract.test.ts` 在 `bun test` 里逐课锁住两处焦点恢复动作(作答重画题面、提交成功),焦点环观感与读屏语气仍待人工确认 |
| 可复制的代码模板与错误对照 | 下一步 | 帮助初学者辨识常见 C++ 错误;不在浏览器端执行不受控代码 |
| 教师备课打印版 | 下一步 | 便于课堂使用;默认不包含学生账号或行为追踪 |
Expand Down
2 changes: 2 additions & 0 deletions docs/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

- **五阶段课程导航**:`index.html` 已提供第一阶段至第五阶段的切换、筛选和 40 节课浏览。
- **单课件学习面板**:`index.html` 的课件详情会显示每节课的学习目标、具体内容、检验清单、视频组织建议和练习建议。
- **每节课的先修关系**:每课 `lessons/<课程-id>/index.html` 的标题正下方列出要先会的课号、课名与该课要会的那一件事,并给上一课入口;第一课说明「不用先修」且不列任何链接,课程目录的详情面板显示同一份数据,页面上写的与 `courseData` 不一致会被校验当场挡下。
- **本地学习进度**:课件逐项检验结果保存在浏览器 `localStorage`;不可用时显示明确提示并继续允许当前会话学习。保存失败发生在会话中途(例如配额用尽)时会立刻可见、可重试,恢复后说明数据状态并补写待保存的进度。
- **即时交互反馈**:阶段、课件、筛选和进度操作均会显示明确状态提示,避免用户把页面更新误认为无响应。
- **Bun 开发工具链**:`bun run dev` 提供本地静态课程路由,`bun run scaffold:lessons` 创建课程目录,`bun test` 执行无依赖校验。
Expand Down Expand Up @@ -196,6 +197,7 @@
| 学习尝试恢复(保存失败可见、可重试、恢复后补写) | 中 | ✅ 首页与全部 40 课的保存成功路径逐课验证 | ✅ 会话中途写入被浏览器拒绝时当次立刻说明“没有保存成功、刷新后不会恢复进度”,不伪装成已保存,互动不中断 | 不适用:无账号 | ✅ 提示里提供“重试保存”;恢复后提示消失、说明“本地保存已恢复”并把期间待写进度补写落盘 | [`tests/storage-recovery.test.ts`](../tests/storage-recovery.test.ts)、[`E2E-06`](../tests/e2e/manual-checklist.md#e2e-06-会话中途保存失败与恢复)、[`E2E-S1-01-06`](../tests/e2e/s1-01-manual-checklist.md#e2e-s1-01-06-会话中途保存失败与恢复) |
| 微编程浏览器自动化复验(S1-02 至 S1-08、S2-01 至 S2-08、S3-01 至 S3-08、S4-01 至 S4-08、S5-01 至 S5-08 样板) | 中 | ✅ 659 项检查覆盖 39 课手写填空(每课 16 至 17 项),`bun run e2e:s1-typed` / `bun run e2e:s2-typed` / `bun run e2e:s3-typed` / `bun run e2e:s4-typed` / `bun run e2e:s5-typed` / `bun run e2e:typed` 自动启停浏览器与服务 | ✅ 每课验证空提交、全角符号、语义写错(S1:把更新写成 `==` 而不是 `=` / 漏括号写成 `a + b / 2` / 连续读入写成 `cin >> a, b;` / `>=` 丢掉等于 / 循环上界写成 `i < n` / 内层循环变量写成 `r` / 多写字符写成 `;n`;S2 起:越界下标 / 漏括号 / 参数或大小写不符 / 写引用或指针 / 取错成员 / 换同一格或跳格 / 该取个位写成 `x / 10` / 递归括号里还是 `n` 到不了边界 / 中点漏括号写成 `left + right / 2` / 前缀和漏减 1 写成 `sum[i]` / 窗口两步写成 `sum += a[right]; right++` / 贪心排序按开始时间排 `by_start` / 弹栈写成只看不弹的 `st.top()` / DP 转移把两类走法相乘 / 剪枝写成 `if (sum >= target) return;` / 计数写成 `cnt[score] = 1;` 覆盖已数次数 / 转移漏写金额 `max(dp[i - 1], dp[i - 2])` / 干净输出写成 `cin >> n + 1;` / 累加写成 `sum = a[i];` 覆盖掉前面的和 / 边界把允许的 0 写成 `> 0` / 防止重复访问写成条件写反的 `if (!visited[u]) return;` / 保底条件写成子任务 2 上限 `if (n <= 100000)` / 分段输出把方向写成读入 `cin >> i >> prefix;` / 累加变量仍写 `int sum = 0;` 装不下 / 区间和漏减 1 写成 `sum[r] - sum[l]` / 空数组判断写成 `if (n == 1)` / 循环范围漏掉等号写成 `i < n` / 按审题圈出的范围开数组正好差一格写成 `int a[100000];` / 交叉检查漏写 `1LL` 让 `n * (n + 1)` 溢出 / 计数数组清零写成标量 `int cnt[105] = 0;`)三类失败路径均给出具体指正且不算完成 | 不适用:无账号 | ✅ 刷新后恢复草稿与完成状态;重置可清空;输入内容原样保留且不会被当成 HTML 或正确答案 | [`tests/e2e/s2-typed-cdp.ts`](../tests/e2e/s2-typed-cdp.ts)、[`S2 复验记录`](../tests/e2e/s2-01-manual-checklist.md#自动化复验记录)、[`S3 复验记录`](../tests/e2e/s3-01-manual-checklist.md#自动化复验记录)、[`S4 复验记录`](../tests/e2e/s4-01-manual-checklist.md#自动化复验记录)、[`S5 复验记录`](../tests/e2e/s5-02-manual-checklist.md#自动化复验记录)、[`S1 复验记录`](../tests/e2e/s1-02-manual-checklist.md#自动化复验记录) |
| 单课浏览器自动化复验(S1-01 样板) | 中 | ✅ 88 项检查覆盖八个场景,`bun run e2e:s1-01` 自动启停浏览器与服务 | ✅ 存储不可用、会话中途保存失败、词条表载入失败、词条面板脚本未载入与题库异常(空题库、答案越界)五条失败路径在真实浏览器中验证 | 不适用:无账号 | ✅ 脚本临时改写题库后会强制还原并断言“临时改动已还原”;保存失败后重试会补写落盘;词条表恢复后回到刚才点开的词条;面板脚本 404 时当场说明且不中断其他互动 | [`tests/e2e/s1-01-cdp.ts`](../tests/e2e/s1-01-cdp.ts)、[`复验记录`](../tests/e2e/s1-01-manual-checklist.md#自动化复验记录) |
| 先修关系可见与可达(全部 40 课样板) | 中 | ✅ 全部 40 节课逐课在真实浏览器里复验「进页面第一眼就知道要先会什么、而且点得回去」:`bun run e2e:prereq` 242 项检查(40 课各 6 项:5 项笔记本视口检查 + 1 项手机竖屏检查;另含脚本自检 2 项。2026-09-21 Chrome 153 无头) | ✅ 指向不存在课程的死链、链接被其它元素盖住、先修块被挤出首屏、键盘走不到、页面文字与 `courseData` 不一致都会失败;脚本自检会先插一条死链并确认它被抓到,检查器空转同样失败 | 不适用:无账号 | 不适用:只读导航,不修改状态 | [`tests/prerequisite-path.test.ts`](../tests/prerequisite-path.test.ts)、[`tests/e2e/prereq-cdp.ts`](../tests/e2e/prereq-cdp.ts)、[`tests/e2e/prereq-manual-checklist.md`](../tests/e2e/prereq-manual-checklist.md) |
| 键盘可达与焦点可见(全部 40 课样板) | 中 | ✅ 全部 40 课逐课复验「不用鼠标也能走完,而且始终看得见焦点在哪」:`bun run e2e:keyboard` 在真实浏览器里发真实按键事件,328 项检查(结构检查每课 8 项 + S1-02 与 S3-01 的键盘深路径每课 4 项),覆盖 `Tab` 绕圈每个停靠点都有可见焦点环、没有正数 `tabindex` 打乱自然顺序、原生控件没被 `tabindex="-1"` 移出 `Tab` 顺序、没有「看着能点、键盘够不到」的元素、音效开关 `Space` 能切换且 `aria-pressed` 与文案同步、词条 `Enter` 打开 / `Esc` 关闭并把焦点交还刚才那个词条、步进轨道每一步(含锁着的)都在 `Tab` 顺序里 | ✅ 焦点丢失这条高风险失败路径逐课看住:作答重画题面后必须把焦点交还刚答的那一项、提交成功后必须交给结果区 `#quizResult`(此前两处都会掉回文档主体);`bun test` 里的 `tests/keyboard-access-contract.test.ts` 反向锁住这两个恢复动作被删掉或挪错位置,按 `courseData` 派生所以新课自动纳入 | 不适用:无账号 | ✅ 步进门闩 `Tab` 够得到但 `Enter` 与 `Space` 都推不动进度,面板照旧藏着且状态区说明原因;词条面板关闭后焦点回到刚才那个词条而不是文档开头;清掉本地存储后键盘路径仍可重走 | [`tests/keyboard-access-contract.test.ts`](../tests/keyboard-access-contract.test.ts)、[`tests/e2e/keyboard-cdp.ts`](../tests/e2e/keyboard-cdp.ts)、[`键盘清单`](../tests/e2e/keyboard-manual-checklist.md#自动化复验记录) |
| S1-01 引导式在线学习界面 | 中 | ✅ 已复验:88 项浏览器检查(`bun run e2e:s1-01`,2026-09-21 Chrome 153 无头) | ✅ 错误选择、未解锁任务、存储不可用、会话中途保存失败、词条表载入失败与词条面板脚本未载入均给出明确反馈 | 不适用:无账号 | ✅ 刷新后恢复任务与答题状态;存储失败时说明限制并可重试保存;词条表失败时可重新载入;面板脚本载入失败时给出重新载入本课入口 | [`S1-01 E2E`](../tests/e2e/s1-01-manual-checklist.md#自动化复验记录)、[`tests/e2e/s1-01-cdp.ts`](../tests/e2e/s1-01-cdp.ts) |
| S1-02 引导式在线学习界面 | 中 | ✅ 微编程 17 项浏览器检查已复验(2026-09-21,`bun run e2e:s1-typed`);整课推进与随机小测已复验(`bun run e2e:flow`,每课 19 项浏览器检查,2026-09-21 Chrome 153 无头) | ✅ 错误类型、跳过声明/赋值和存储不可用均给出明确反馈 | 不适用:无账号 | ✅ 刷新后恢复任务与答题状态;存储失败时说明限制 | [`S1-02 E2E`](../tests/e2e/s1-02-manual-checklist.md#自动化复验记录)、[`E2E-s1-typed`](../tests/e2e/s2-typed-cdp.ts)、[`E2E-flow`](../tests/e2e/flow-cdp.ts) |
Expand Down
Loading
Loading