给小学生出题、判题、讲解、记错题的一套东西。题不是从教辅上抄的 —— 是从孩子自己做错的卷子里长出来的。
做练习 App 的人很多,难的从来不是「出一道题」,而是下面这几件反直觉的事。每一条右边都是踩过坑之后定下来的取舍:
| 刷题刷的是别人的错 | 通用题库出的题,孩子早就会的占一大半。这里反过来:先把孩子自己的卷子逐题录入档案(题干、标准答案、他当时怎么答的、错在哪一步),归纳出真实失分点,再按失分点写题型生成器。 |
| 原题重放 = 背答案 | 错题本如果存的是那一道原题,第二次做就变成了默写。所以错题本只记「哪一类题错了」,不存答案和选项;复习时用同一个题型现出一道新题,换数字、换选项、换文本。 |
| 无限流让人没有底 | 一次显示一题、做完就消失,孩子不知道自己做了什么,家长也看不到边界。改成一次组一套(真实系统 12 题,本演示 8 题):有题号条、能翻回去、能跳过、能交卷看总览。「无限」和「无结构」是两件事。 |
| 答错立刻给答案等于没练 | 两次机会:第一次错只给提示方向,第二次错才给正确答案 + 完整分步讲解,并把这一类题记进错题本。 |
| 重试能把正确率刷成 100% | 统计口径写死为一次做对才算对。答错改对了仍计入「做过」,但不计入「对」——否则掌握度是假的,而假的掌握度会让系统一直不给他出该练的题。 |
| 一次蒙对就算学会 | 错题划掉的条件是连着两次一次做对;中间只要错一次,订正进度归零。 |
| 孩子不点第二次,一切白搭 | 任务条永远写着「还差 N 题」,等级条永远写着「还差多少经验」,勋章墙把没解锁的也灰着摆出来并写明条件。让「差一点就完成」始终在眼前。 |
| 题目会被生成器写错 | 每个题型自带 verify(),用与出题不同的算法反算一遍(例如出题用除法,验算用连减)。真实系统在建库时逐道跑;本页打开时当场跑一遍,结果就印在下面。 |
| 站的形态 | 练习页是纯静态单文件:题型代码、样式、勋章清单全部内联进 HTML,断网也能做题,做题记录写 localStorage。没有做题接口,也就没有做题接口会挂这回事。 |
| 题库 | SQLite 单文件是 SSOT,一道题一行,可查可改可溯源回到来源卷子的第几题。页面内联的题数必须等于库里的数,渲染门盯着这条,页面和库不许分家。 |
| 两种出题形态 | 显式写死不靠猜:generate(数学,现场 make())与 enumerate(语文,建库时反复生成 + 逐道验算 + 按内容指纹去重,连续几千次出不了新题才算枚举完)。没收敛的生成器拒绝固化 —— 假装枚举完了比不枚举更糟。 |
| 选题权重 | 6 − 星级×1.5,没见过 +4,进过错题本 +6,与上一题同型 ×0.35,下限 0.4。抽完即定住,一套之内不再变 —— 边做边变权重会让「这一套是什么」说不清。 |
| 掌握度 | 按题型算星:一次做对 ≥3 道给 1 星;≥8 道且正确率 ≥70% 给 2 星;≥15 道且 ≥85% 给 3 星。整课掌握度 = 星数总和 ÷(题型数×3)。 |
| 激励 | 一次做对 +12 经验(连对 3/6/10 题分别 ×1.5 / ×2 / ×3),订正对 +4,答错也 +2(敢试就有分)。升级所需经验 80 + (等级−1)×50,前几级升得快。 |
| 存档分两份 | 单课存档管「这一课练得怎么样」,全局成长档案管「这孩子整体走到哪」(经验、等级、连续天数、勋章)—— 所以跨学科是同一条成长线,不是每课各算各的。 |
| 渲染是派生的 | 课的源是一份 Markdown(讲解正文 + 题型代码块),渲染器产出 HTML;学习路径首页由一份 YAML 派生。所有门都是 fail-closed:没写日期不给渲、题型自检不过不给渲、首页有死链不给渲、枚举为空一律非零退出(拒绝在空集上报绿)。 |
| 隐私 | 档案目录永不上线;部署是白名单组装(只有首页和练习页进包),另有敏感词闸扫姓名、本地路径、档案引用,命中即中止部署。站本身在登录闸后并 noindex。 |