Files
feifei/开发文档-第1关.md
T
2026-10-13 20:40:09 +08:00

364 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 第 1 关开发文档:1-1 左手基准键 ASDF
对应规划:`分关难度规划.md` → 第 1 章 · 基准键入门 → **1-1**。
本文只覆盖第 1 关的实现范围,作为后续关卡的模板。第 1 关同时要搭好练习页的通用骨架,后关复用,不重做。
---
## 1. 目标
让完全新手在不看键盘的情况下,用正确指法打出左手四个基准键:
| 键 | 手指 |
|----|------|
| `A` | 左手小指 |
| `S` | 左手无名指 |
| `D` | 左手中指 |
| `F` | 左手食指 |
本关**不考速度**,只考正确率和指法习惯。
通关条件:**正确率 ≥ 90%**(无速度门槛)。
---
## 2. 范围
### 2.1 本关要做
- 关卡选择页中,1-1 默认解锁,可进入
- 练习页:待打文本、实时对错着色、键盘指法图、实时数据条
- 约 40 个目标键,字符集仅 `a s d f`(小写)
- 击键判定、正确率、键/分、进度
- 结束结算:通过 / 未通过,可重打
- 通过后解锁 **1-2**
- 记录本关历史最好正确率(本地存储)
### 2.2 本关不做
- 右手键 `j k l ;`、空格、大写、数字、符号
- 速度门槛、限时模式
- 中文拼音、单词、文章
- 热力图统计(可先预留数据结构,本关不展示)
- 账号 / 云同步
---
## 3. 页面与信息架构
建议单页 HTML,用视图切换,不必多文件路由。
```
启动
└─ 关卡选择(第 1 章四关列表)
└─ 练习中(1-1)
└─ 结算弹层
├─ 再打一次 → 回到练习中(重新抽题)
└─ 返回选关 → 关卡选择
```
### 3.1 关卡选择页(本关相关)
| 元素 | 说明 |
|------|------|
| 章标题 | 第 1 章 · 基准键入门 |
| 关卡卡片 1-1 | 标题「左手基准键 ASDF」;状态:已解锁 / 已通关 |
| 关卡卡片 1-2~1-4 | 未通关 1-1 前置灰,不可点 |
| 最佳成绩 | 若打过 1-1,显示历史最高正确率 |
### 3.2 练习页布局(自上而下)
1. **顶栏**:关卡名「1-1 左手基准键」、返回选关
2. **数据条**:进度 `已打/总数`、正确率、速度(键/分)、用时
3. **文本区**:一行待打字符,当前目标键放大/下划线,已打正确为绿、错误为红
4. **键盘区**:QWERTY 示意图,强制显示;当前目标键高亮;四指提示
5. **提示文案**:「食指放在 F,小指放在 A,不要看键盘」
结算用遮罩弹层盖在练习页上,不跳新页。
---
## 4. 关卡配置
实现时用一份配置驱动,后关只改配置、少改逻辑。
```js
{
id: "1-1",
chapter: 1,
title: "左手基准键 ASDF",
charset: ["a", "s", "d", "f"],
length: 40,
allowSpace: false,
caseSensitive: false, // 本关只产生小写;Shift+A 视为错误
passAccuracy: 0.90,
passKpm: null, // 本关不卡速度
unlockNext: "1-2",
showKeyboard: true, // 强制显示,不可关
generate: "random-from-charset"
}
```
### 4.1 题目生成规则
- 从 `charset` 均匀随机抽取 `length` 个字符,连成一串,例如:`asdfafsdasfd...`
- **不要**出现空格、换行
- 建议约束:同一字符连续不超过 3 次(避免 `aaaa` 失去指法切换训练)
- 每次进入或「再打一次」都重新生成,不固定题库
### 4.2 允许输入
| 按键 | 行为 |
|------|------|
| `a` `s` `d` `f` | 有效击键,进入对错判定 |
| 其他字母 / 数字 / 符号 | 记为一次错误击键,不前进光标(卡住当前目标,直到打对) |
| `Shift` / `CapsLock` 产生的 `A` 等 | 视为错误(本关只认小写) |
| `Backspace` | **忽略**,本关不允许改错(对标金山打字通初级指法:打错就记错,必须打对当前键才继续) |
| `Enter` `Tab` `Esc` | 忽略,不计入对错 |
| `Alt` `Meta` `Ctrl` 组合 | 忽略 |
采用「必须打对才前进」:错了标红提示,光标停在当前目标,直到按下正确键。
正确率分母按「总击键次数(含错键)」计算,而不是按「已完成字符数」。见第 6 节。
---
## 5. 指法与键盘 UI
### 5.1 手指映射(本关只用左手)
| 键 | 手指 | 建议高亮色 |
|----|------|------------|
| A | 小指 | 橙 |
| S | 无名指 | 黄 |
| D | 中指 | 绿 |
| F | 食指 | 蓝 |
其余键绘制出来但呈禁用态(降低透明度),避免误导用户去打。
### 5.2 键盘交互
- 当前目标键:描边 + 放大/脉冲
- 按下正确键:该键闪绿后熄灭,切到下一目标
- 按下错误键:目标键闪红,可加轻微震动(CSS)
- 键盘图下方固定文案:
「左手:小指 A · 无名指 S · 中指 D · 食指 F」
### 5.3 文本区表现
假设目标串为 `asdf`,用户先打对 `a` `s`,第三个该打 `d` 却打了 `f`:
```
[a] [s] [d] [f]
绿 绿 当前(红闪) 灰
```
- 已正确:绿色
- 当前目标:深色底 + 下划线;若刚打错则红框
- 未打到:灰色
- 不把错误字符插入文本(文本始终是标准答案,只改颜色/状态)
---
## 6. 判定与统计
从**第一次有效击键**开始计时(`a/s/d/f` 或其他会记错的可见字符)。纯功能键不开始计时。
### 6.1 字段
| 字段 | 定义 |
|------|------|
| `targetLength` | 40 |
| `cursor` | 当前待打下标,0~40;到 40 结束 |
| `correctHits` | 打对次数(每前进一格 +1,最大 40) |
| `wrongHits` | 打错次数(每次错误按键 +1,可大于 40) |
| `totalHits` | `correctHits + wrongHits` |
| `elapsedMs` | 从首次有效击键到结束(或当前)的毫秒 |
### 6.2 公式
```
正确率 accuracy = correctHits / totalHits
进度 percent = cursor / targetLength
速度 kpm = correctHits / (elapsedMs / 60000)
用时 time = elapsedMs
```
展示:
- 正确率:百分数,保留 1 位小数,如 `92.5%`
- 速度:整数「键/分」,未开始时显示 `--`
- 进度:`12 / 40` + 进度条
- 用时:`mm:ss`
### 6.3 通关判定(结束时一次性算)
```
passed = accuracy >= 0.90
```
本关 `passKpm` 为空,不判断速度。
`totalHits` 为 0 时(理论上不会结束)正确率按 0。
### 6.4 结束时机
`cursor === targetLength` 立即结束,弹出结算。不再接收击键。
---
## 7. 结算
### 7.1 展示
| 项 | 说明 |
|----|------|
| 结果标题 | 「通关」或「未通关」 |
| 正确率 | 实际值,并标明门槛「≥ 90%」 |
| 速度 | 键/分(仅展示,不影响通关) |
| 用时 | mm:ss |
| 击键 | 正确 / 错误 / 总计 |
| 操作 | 「再打一次」「返回选关」 |
通关时额外一行:「已解锁 1-2 右手基准键」。
### 7.2 进度写入
使用 `localStorage`,键名建议:`typing-progress-v1`。
```js
{
unlocked: ["1-1", "1-2"], // 通关 1-1 后写入 1-2
records: {
"1-1": {
bestAccuracy: 0.95,
bestKpm: 62,
passed: true,
lastPlayedAt: "2026-08-13T15:30:00+08:00"
}
}
}
```
规则:
- 初始 `unlocked` 含 `1-1`
- 通关才把 `unlockNext` 加入 `unlocked`
- `bestAccuracy` / `bestKpm` 只升不降
- 未通关也写入 `lastPlayedAt` 和当前成绩,但不把 `passed` 从 true 改回 false
- 重打失败不锁回 1-2
---
## 8. 状态机
```
idle 进入练习页,题目已生成,等待第一击
playing 已开始计时,接收击键
finished 40 键打完,弹出结算,忽略击键
```
转移:
- `idle` → `playing`:第一次有效/错误可见击键
- `playing` → `finished`:`cursor` 达到 40
- `finished` → `idle`:点「再打一次」(新题、清零统计)
- 任意 → 选关:点返回(练习中途返回不保存通关,可选择是否写入 lastPlayedAt;本关规定:**中途退出不记成绩**)
---
## 9. 技术约定
| 项 | 约定 |
|----|------|
| 形态 | 单文件或「HTML + CSS + JS」,先保证双击即可打开 |
| 输入 | `window` 上 `keydown`;用 `event.key` 判定字符 |
| 防干扰 | 练习中 `preventDefault` 掉会滚动/选中的键;不要用隐藏 `<input>` 抢焦点(避免 IME) |
| 本关 IME | 不需要中文输入;若系统处于中文输入法,提示「请切换到英文」 |
| 样式 | 深色背景、大字号文本区,适合全屏练习 |
| 兼容 | 现代桌面 Chrome / Edge / Safari;本关按物理键盘设计,不做触屏键盘 |
### 9.1 建议模块划分(同一文件内亦可)
1. `config`:关卡配置
2. `progress`:读写 localStorage
3. `generator`:按 charset 生成题目
4. `engine`:状态机、击键、统计
5. `keyboardView`:键盘高亮
6. `textView`:文本着色
7. `hud`:数据条
8. `resultModal`:结算
9. `stageSelect`:选关
第 1 关实现时就把 1~8 做成可复用,选关先只列第 1 章四关。
---
## 10. 文案
| 位置 | 文案 |
|------|------|
| 选关卡片标题 | 1-1 左手基准键 |
| 选关卡片副标 | 只打 A S D F,正确率 90% 即可通关 |
| 练习顶栏 | 第 1 关 · 左手基准键 ASDF |
| 指法提示 | 食指放 F,小指放 A。请看着屏幕,不要看键盘。 |
| 通关 | 通关!基准键已经记住了。 |
| 未通关 | 再练一次。先求正确,再求速度。 |
| 输入法提示 | 请切换到英文输入法后再开始。 |
---
## 11. 验收标准
- [ ] 打开页面即可进入 1-1,无需登录
- [ ] 题目长度为 40,仅含 `a s d f`,无空格
- [ ] 同一字符连续不超过 3 次
- [ ] 打对前进一格,打错不前进并记一次错误
- [ ] Backspace 不影响进度与统计
- [ ] 正确率按 `正确 / (正确+错误)` 计算,≥ 90% 判定通关
- [ ] 无速度门槛;结算仍显示键/分
- [ ] 键盘图始终显示,当前键高亮,非 ASDF 键呈禁用态
- [ ] 通关后 1-2 可点;未通关 1-2 仍锁
- [ ] 刷新页面后解锁状态仍在
- [ ] 中途返回选关不记本局成绩
- [ ] 「再打一次」重新抽题并清零
---
## 12. 测试用例
| 编号 | 操作 | 期望 |
|------|------|------|
| T1 | 40 次全对 | 正确率 100%,通关,解锁 1-2 |
| T2 | 打对 36、打错 4(错键后补对) | 总击键 44,正确率 ≈ 81.8%,未通关 |
| T3 | 打对 36、打错 4 之外再算:正确 36 / 总击键 40 | 注意:因打错不前进,40 个正确键必须打满;未通关局 `correctHits` 仍为 40,`wrongHits` > 0。例如错 5 次则正确率 = 40/45 ≈ 88.9%,未通关 |
| T4 | 正确率刚好 90%(40 对 + 约 4.44 错不可整除) | 用 40 对 + 5 错 = 88.9% 未过;40 对 + 4 错 = 90.9% 通过。门槛按 `>= 0.90` |
| T5 | 练习中按 Backspace、方向键 | 无效果 |
| T6 | 打 `g` 或其他非 charset 键 | 错误 +1,光标不动 |
| T7 | 通关后刷新 | 1-2 仍解锁 |
| T8 | 通关后再打失败 | 1-2 保持解锁 |
| T9 | 第一键前等待 | 速度显示 `--`,用时 00:00 |
| T10 | 中途点返回 | 无结算、不改 best、不解锁 |
**正确率要点(务必实现一致):**
本关结束时 `correctHits` 恒为 40。通关只取决于错了多少次:
```
accuracy = 40 / (40 + wrongHits)
90% 通关 ⇒ 40 / (40 + wrongHits) >= 0.90 ⇒ wrongHits <= 4
```
即:全程最多允许打错 4 次。
---
## 13. 后续关卡复用说明
第 1 关落地后,1-2 只需改配置:
| 项 | 1-1 | 1-2(预告,不在本文实现) |
|----|-----|---------------------------|
| charset | a s d f | j k l ; |
| 手指 | 左手四指 | 右手四指 |
| 通关 | 正确率 ≥ 90% | 同 1-1 |
| 键盘禁用态 | 非 ASDF | 非 JKL; |
不要为 1-2 另写一套引擎。