Skip to content

git25math/25maths-examhub

Repository files navigation

开发规范(适用于任何开发者 / AI 工具)

本文档是 25Maths ExamHub 项目的唯一权威规范。 无论你是人类开发者、Claude、Cursor、Copilot 还是其他 AI——都必须遵守此文档。 本文档存在于 git 仓库内,所有协作者均可读取。


一、项目概览

  • 项目: 25Maths ExamHub — 双语数学词汇 + 真题学习平台
  • 仓库: git25math/25maths-examhub
  • 磁盘路径: /Users/zhuxingzhe/Project/ExamBoard/25Maths-Keywords/(注意:不是 25Maths-ExamHub)
  • 部署: push main → GitHub Pages → https://examhub.25maths.com
  • 技术栈: Vanilla JS(无框架)+ CSS + esbuild minify + Supabase + KaTeX
  • 当前版本: v5.45.0 (2026-03-19)

二、产品定位

面向 CIE 0580 / Edexcel 4MA1 / Harrow Y7-Y11 的数学学习平台,核心功能:

维度 内容 规模
词汇 双语数学术语学习(6 种模式) ~931 词
真题 历年考试真题 + MCQ 练习 5,822 真题 + 3,073 MCQ
知识点 201 个 KP 六阶段学习 201 KP
学习引擎 FLM 掌握模型 + 衰退复查 + 错误记忆 8 层架构

用户角色

角色 权限
Guest (id='local') 所有模式,有限 level,无云同步
Student 全部访问,云同步,作业,排行榜
Teacher 班级/学生 CRUD,作业,成绩分析
Super Admin 词汇 CRUD,反馈管理

三、FLM 掌握模型(核心引擎)

FLM (Filter-Learn-Master) 是整个学习系统的核心状态机:

new → learning → uncertain → mastered
 ↑       ↑          ↑           |
 └───────┴──────────┴───────────┘  (衰退复查失败 → 回退)

三个维度的 FLM

维度 转换触发 cs 含义 存储
词汇 逐题 recordAnswer/recordScan 逐题连续正确数 localStorage (wmatch_v3)
KP session-based saveKPResult 连续成功 session (≥85%) localStorage (wmatch_v3)
PP practice: cs-based; exam: 高置信度直接 mastered 连续正确数 localStorage (pp_mastery)

衰退复查

  • REFRESH_INTERVALS = [7, 14, 30]
  • rc (refresh count) 递增,上限 MAX_RC = 2
  • 词汇/KP/PP 共用相同衰退机制
  • getSectionHealth() 四维加权:vocabScore + practiceScore + knowledgeScore + ppScore

关键规则

  • 不要直接修改 FLM 状态转换逻辑——它经过多轮验证,牵一发动全身
  • 新增学习维度必须遵循现有 FLM 接口:recordAnswer(type, id, verdict)
  • getStaleUnits(board) 是聚合器,词汇/KP/PP 各有独立 stale 检测函数

四、架构概览

8 层学习引擎

Layer 1  课纲层 — Exam Boards / Year Groups / Sections
Layer 2  内容层 — Vocabulary / KPs / Questions / Past Papers
Layer 3  关系层 — Learning Graph (vocab ↔ KP ↔ questions via section codes)
Layer 4  状态层 — FLM / Mastery / Stale / Mistakes / Reflow
Layer 5  规划层 — Today's Plan / Section Health / Weak Groups
Layer 6  执行层 — Recovery Session / Practice / Refresh Scan
Layer 7  修复层 — Recovery Pack / Print Repair Sheet
Layer 8  反馈层 — Return by ID / Re-attempt / Status Update

Panel 系统

showPanel(id) 在 18 个面板间切换: panel-home, panel-deck, panel-study, panel-battle, panel-review-dash, panel-review, panel-quiz, panel-spell, panel-match, panel-preview, panel-daily, panel-practice, panel-import, panel-board, panel-stats, panel-admin, panel-homework

布局断点

断点 布局
≥1080px 固定侧边栏 (260px) + 主内容
640-1079px 顶部 header + 底部导航 + 内容
<640px 紧凑模式,窄 padding

五、JS 模块架构

构建系统

  • 无 bundler 开发: 26 个 JS 文件通过 <script> 标签按顺序加载
  • 生产构建: npm run build → esbuild 合并+压缩
  • 构建脚本: scripts/minify.sh

Bundle 分组

Bundle 包含文件 加载方式
app.bundle.min.js config + levels-loader + storage + auth + ui + mastery + syllabus + app 立即
study-quiz-battle.min.js study + quiz + battle 延迟
practice.min.js practice + knowledge-node + learning-graph + topic-practice 延迟
recovery.min.js 8 个 recovery/AI 模块 延迟
tools.min.js stats + export 延迟
modes.min.js spell + match 延迟
单独 lazy homework, admin, super-admin, particles 等 按需

JS Load Order (核心 8 文件)

1. config.js      — 常量、主题、全局状态、断点检测
2. levels-loader.js — 词汇数据懒加载
3. storage.js     — localStorage + 云同步 + FLM + 模式完成追踪
4. auth.js        — 登录/注册/Guest + 设置 + Board 选择
5. ui.js          — Panel 导航、Toast、Modal、语言切换、排序
6. mastery.js     — 首页仪表盘、deck 详情、模式选择
7. syllabus.js    — 课纲浏览、KP 面板、Smart Path
8. app.js         — 初始化、排行榜、URL 深度链接、iOS 分享恢复

六、编码规范

6.1 变量声明

  • 所有 JS 文件使用 var 声明(浏览器兼容性)
  • CSS 使用自定义属性(紫色主题:--c-primary: #5248C9

6.2 函数调用审计(最重要的规则)

调用项目已有函数前,必须先 Grep 读其实现,确认:

  • 参数签名(个数、类型、顺序)
  • 返回值类型(对象 vs 原始类型 vs 数组)
  • 副作用(是否写入 localStorage / 触发 UI)

6.3 易错 API 速查表

函数 签名 陷阱
showModal(html) 1 个 HTML 字符串 没有 title/callback 参数
getVisibleBoards() 返回 [{id, name}] 不是字符串数组!取 board 需 .id
createCustomList(title) 返回 list 对象 不是 id 字符串
wordKey(li, wid) uid 含小写 → W_uid,否则 → L_slug_Wid 双路径逻辑
makeUid(word) 小写+去特殊+空格转连字符 与 vocabulary UID 命名体系一致
showToast(msg) 单参数消息字符串
t(en, zh) 不存在于 ui.js 需用 appLang !== 'en' ? zh : en 模式

6.4 事件绑定

  • 禁止 onclick="fn()" 在 innerHTML 中(XSS 风险)
  • 必须 使用 data-action + 事件委托模式
  • 委托绑定在面板容器上,用 _ppDelegated 类标志防重复

6.5 缓存闭环

添加任何缓存时,必须同时完成

  1. 定义 invalidate 函数
  2. Grep 所有数据写入路径,逐一插入 invalidate 调用
  3. 验证:写入 → 重读 → 确认数据刷新

标准写入后失效序列:

writeS(s) / localStorage.setItem(...)
  → invalidateRecoveryPlanCache()
  → invalidateCache()
  → toast/badge 更新
  → debouncedSync()

6.6 Hook 插入模式

if (typeof _hookFunction === 'function') _hookFunction(args);
  • 始终用 typeof 守卫(hook 可能在 lazy-loaded 文件中)
  • 位置:数据写入之后,UI 反馈之前

6.7 跨文件迁移

把函数从一个 JS 文件迁到另一个时:

  1. 列出所有被调用的外部函数
  2. 检查每个在新加载位置是否可用
  3. 不可用 → 内建本地版或 typeof 守卫

6.8 新建 JS 文件

  1. scripts/minify.sh 的对应 bundle cat 列表中添加(注意加载顺序)
  2. index.html 不需改(使用 bundle)
  3. 更新 CLAUDE.md 的 JS Load Order
  4. 更新本文档第五节

6.9 CSS 规范

  • 使用 CSS 变量(--c-primary 等),自动适配暗色模式
  • 新样式涉及硬编码颜色 → 必须加 [data-theme="dark"] 覆盖规则
  • 用户可见文本必须用 t(en, zh) 或等效双语包裹
  • 字体栈:Bricolage Grotesque (display) + DM Sans (body) + JetBrains Mono (code) + Noto Sans SC (中文)

6.10 HTML 安全

  • 动态内容用 escapeHtml() 转义
  • 拼接 innerHTML 时不要信任用户输入

七、数据架构

词汇数据

  • 源文件:.tex 文件 → scripts/extract-vocab.pydata/ JSON
  • 映射配置:data/sources.json
  • 状态字段:st (status), iv (interval), nr (next review), lr (last review), ok (correct), fail (error), lv (SRS 0-7), stars (0-4)
  • 模式完成:modeDone 对象,键为 "slug:mode" (study/quiz/review/spell/match/battle)

真题数据 (Block 结构)

Question {
  stem: Block[]              // 题干
  parts: [{
    content: Block[]         // 小题内容
    marks: number
    answer: Answer           // number/vector/table_input/coordinate/multiline/expression
    subparts?: [...]         // 层级化小题
  }]
  _rawBody?: string          // 原始 tex 保留
}
  • Block 类型:text / table / figure / list
  • Answer 类型:number / vector / table_input / coordinate / multiline / expression
  • 543 题含子问题结构(有 subparts 则无 marks/answer)

Supabase 表

vocab_progress, leaderboard, schools, teachers, kw_classes, kw_class_students, kw_assignments, assignment_results, vocab_levels, notifications, feedback

  • 迁移文件:supabase/migrations/(17 个 SQL 文件)
  • 共享实例:与 25maths-website 共用 (ref: jjjigohjvmyewasmmmyf)

八、6 种学习模式

模式 说明 实现文件
Scan (Study) 三按钮 FLM 循环:Know / Fuzzy / Don't know study.js
Quiz 四选一 MCQ + Daily Challenge + 分享卡 quiz.js
Spell 听写模式(Web Speech API) spell.js
Match 拖拽配对匹配 match.js
Battle 限时匹配挑战 + 计分 battle.js
Daily Challenge 每日词汇测验 + 连续打卡 quiz.js (内置)

真题练习

模式 说明 实现文件
Practice MCQ 按章节分类 MCQ 练习 practice.js
Knowledge Node KP 六阶段学习(概念→词汇→MCQ→真题→综合→挑战) knowledge-node.js
Topic Practice 专题练习包 topic-practice.js

九、外部工具集成

9.1 Gemini CLI

  • 路径:/opt/homebrew/bin/gemini
  • -o json 输出是包装结构:{ session_id, response: "<json string>", stats }
  • response 是字符串,需要二次 JSON.parse(),可能含 markdown code fence
  • 频繁 429 限流 + ETIMEDOUT → 脚本必须幂等可断点续跑
  • 调用超时设 180s(默认 120s 不够大 batch)
  • 大批量任务按 section 分文件输出,重跑时跳过已存在文件
  • Key 池:~/.gemini_keys.json(多 key 轮换,最大化免费配额)

9.2 批量数据处理脚本设计原则

  1. 幂等性 — 支持断点续跑,自动跳过已完成单元
  2. 分批 — 大数据集按 section/batch 切分,每批独立输出
  3. 降级 — 前端对缺失映射数据做 graceful fallback
  4. 验证 — merge 脚本统计报告(数量、平均值、异常)

十、审查标准

每次提交前(或审查时)必须检查:

功能正确性

  • npm run build 零错误
  • 每个新调用的已有函数,确认参数和返回值
  • 数据流 trace — 关键路径从点击到数据到 UI 完整走一遍
  • 跨模块 typeof 守卫保护跨文件调用

代码质量

  • 事件绑定用 data-action 委托,不用 onclick
  • 新 CSS 用变量或有 dark 规则
  • 用户可见文本用双语包裹
  • 缓存失效 — 新增写入路径触发了相关缓存清除
  • 加载顺序 — minify.sh 中位置在依赖之后
  • 动态内容用 escapeHtml() 转义

数据完整性

  • JSON 文件格式正确(可被 JSON.parse() 解析)
  • LaTeX 语法正确($ 配对、花括号配对)
  • Block 结构符合 schema(stem/parts/answer)
  • 版本号一致(config.js APP_VERSION = CHANGELOG = ROADMAP)

十一、关联项目

CIE 分析(知识点定义) → ExamHub(词汇+真题) ↔ Play(闯关) → 主站(入口)
                                 ↑
                            共享 Supabase
                            共享用户账号
项目 路径 关系
Play 游戏 25maths-games-legends 共享 Supabase + 用户账号
主站 25maths-website 入口链接,共享 Supabase
CIE 分析 CIE/IGCSE_v2/analysis/ 真题标签 + KP 数据源
视频引擎 多目录 未来集成(视频 ID 与 kpId 对齐)

数据流

CIE 真题 PDF → 分析流水线(提取+标签) → levels.js(ExamHub) + kp-registry.ts(Play)
                                        ↓                      ↓
                                   ExamHub 真题练习          Play 关卡生成
                                        ↓                      ↓
                              Supabase vocab_progress (共享用户数据)

十二、Git 规范

12.1 Commit 规范

  • 提交消息中文概要,格式:v{版本} {功能名} — {简述}
  • 多功能合并提交时,在 body 中分行列出每个功能

12.2 构建验证

  • commit 前必须 npm run build 零错误
  • push main 自动部署到 GitHub Pages
  • 验证部署:gh api repos/git25math/25maths-examhub/pages/builds

12.3 安全规则

  • 不要 force push
  • 已 push 的 commit 不要 amend → 创建新 commit 或 push --force-with-lease
  • commit 前重新检查文件状态(外部可能修改了 config.js 版本号等)
  • 不用 git add -A,只 stage 自己修改的文件
  • 新文件必须 git add(检查 git status?? 未跟踪文件)

十三、版本号管理

ExamHub 有两处版本号,必须保持一致

位置 格式 说明
js/config.js APP_VERSION = 'v5.45.0' 运行时版本(SW 缓存版本自动同步)
CHANGELOG.md 顶部 ## [5.45.0] - 日期 变更记录
ROADMAP.md 顶部 ## v5.45.0 — 标题 规划状态

package.json 的 version 字段需同步更新,以 config.js APP_VERSION 为权威来源。

发版流程

  1. 修改 js/config.jsAPP_VERSION
  2. npm run build(自动同步 SW 缓存版本 + index.html cache-bust)
  3. 在 CHANGELOG.md 顶部新增版本条目
  4. 在 ROADMAP.md 中标记已完成项 [x],新增下一版本条目
  5. git commitgit push origin main
  6. 验证 GitHub Pages 部署

十四、Anti-Patterns 黑名单

不要 应该
onclick="fn()" 在 innerHTML data-action + 事件委托
except: except Exception:
定义 invalidate 不接入写入路径 同时 grep 所有 writer 并插入
依赖 lazy-loaded 文件中的函数 typeof 守卫或本地实现
凭记忆猜函数签名 先 Grep/Read 确认实现
build 成功就 ship 人工 trace 关键路径
假设磁盘路径等于仓库名 25Maths-Keywords 路径
已 push 的 commit 做 amend 新建 commit 或 force-with-lease
Gemini output 直接 JSON.parse 先解包 wrapper.response
大批量脚本一次性跑完 分 section 输出 + 幂等断点续跑
git add -A 提交所有 只 stage 自己改的文件
硬编码颜色不加 dark 规则 用 CSS 变量或加 dark override

十五、工作流

开发时

Step 1: Git 基线检查 (status + diff + log)
Step 2: 确认 APP_VERSION (grep config.js)
Step 3: Plan → Execute → Ship(见 CLAUDE.md)
Step 4: npm run build 零错误
Step 5: git commit + push
Step 6: 验证 GitHub Pages 部署

Ship 收尾步骤(自动触发)

  1. npm run build 重新生成 minified 文件
  2. CHANGELOG.md — 新增版本条目
  3. ROADMAP.md — 标记 [x] + 新增下一阶段
  4. git commit + git push origin main
  5. 验证部署状态
  6. 向用户输出:版本号、变更摘要

交接时(对话/session 结束)

  1. 更新 config.js 版本号 + CHANGELOG + ROADMAP
  2. 回顾对话,记录新的共识/偏好/纠正
  3. commit + push + 确认部署
  4. 输出接手指令(一句话可复制到新 session)

十六、核心文件索引

文件 用途
docs/CONTRIBUTING.md 本文档 — 开发规范(AI/人类通用)
docs/DEVELOPMENT-PLAN.md 版本历程概览 + 下一步规划
docs/SYSTEM_GLOSSARY.md 系统术语表(FLM/KP/PP 等标准定义)
docs/learning-engine-architecture.md 8 层学习引擎架构详解
docs/sync-research.md Supabase 同步方案 + 冲突解决
docs/v2-database-schema.sql 数据库完整 schema
CLAUDE.md Claude Code 启动协议
CHANGELOG.md 完整版本变更记录 (v5.14.1→v5.45.0)
ROADMAP.md 开发路线图
js/config.js 应用常量 + APP_VERSION
js/storage.js FLM 状态机 + localStorage + 云同步
js/practice.js 真题练习模式
js/knowledge-node.js KP 六阶段学习
js/learning-graph.js 运行时关系查询层
scripts/minify.sh 构建脚本(bundle 分组 + esbuild)
scripts/extract-vocab.py 词汇数据提取
data/sources.json .tex 文件路径映射
supabase/migrations/ 17 个 SQL 迁移文件

About

IGCSE Exam Support Hub

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors