docs: 修改文档

This commit is contained in:
2026-05-20 23:49:30 +08:00
parent b31c045aa5
commit f88475499f
14 changed files with 2017 additions and 693 deletions
+208 -208
View File
@@ -1,43 +1,43 @@
## 整体架构概览
## Overall Architecture Overview
```mermaid
graph TB
subgraph "用户界面层 (TUI)"
subgraph "User Interface Layer (TUI)"
TUI[Textual App]
Screens[应用屏幕]
Widgets[谜题组件]
Screens[Application Screens]
Widgets[Puzzle Widgets]
end
subgraph "内核层 Kernel"
Reactor[调度反应器]
Algorithms[算法模块]
Particles[数据模型]
Puzzles[谜题引擎]
RepoLib[仓库系统]
Auxiliary[辅助工具]
subgraph "Kernel Layer"
Reactor[Scheduling Reactor]
Algorithms[Algorithm Modules]
Particles[Data Models]
Puzzles[Puzzle Engine]
RepoLib[Repository System]
Auxiliary[Auxiliary Tools]
end
subgraph "服务层"
Config[配置管理 ConfigDict]
Logger[日志系统]
Timer[时间服务]
Audio[音频服务]
TTS[TTS 服务]
Favorites[收藏管理]
Attic[持久化]
Hasher[哈希服务]
subgraph "Service Layer"
Config[Config Management ConfigDict]
Logger[Logging System]
Timer[Time Service]
Audio[Audio Service]
TTS[TTS Service]
Favorites[Favorites Management]
Attic[Persistence]
Hasher[Hash Service]
end
subgraph "提供者层"
AudioProv[音频提供者]
TTSProv[TTS 提供者]
LLMProv[LLM 提供者]
subgraph "Provider Layer"
AudioProv[Audio Provider]
TTSProv[TTS Provider]
LLMProv[LLM Provider]
end
subgraph "数据层"
RepoDir[TOML/JSON 仓库目录]
ConfigDir[TOML 配置目录]
Logs[日志文件]
subgraph "Data Layer"
RepoDir[TOML/JSON Repository Directory]
ConfigDir[TOML Config Directory]
Logs[Log Files]
end
TUI --> Screens
@@ -64,32 +64,32 @@ graph TB
Attic --> RepoDir
```
## 数据模型
## Data Model
项目以物理粒子隐喻为核心, 将记忆单元拆解为三个模型:
The project uses the physical particle metaphor as its core, decomposing memory units into three models:
### Nucleon (核子) - 内容层
### Nucleon - Content Layer
```
Nucleon(ident, payload, common)
```
- **只读**内容容器. 通过 `Evalizer` (基于 `eval()` 的模板系统)对 payload 和 common 进行编译展开.
- 包含 `puzzles` 字段, 定义该记忆单元支持哪些谜题类型.
- `repo.payload` `repo.typedef["common"]` 配对创建.
- 一旦创建, 内容不可修改 (`__setitem__` 抛出 `AttributeError`).
- **Read-only** content container. Compiles and expands `payload` and `common` via `Evalizer` (an `eval()`-based template system).
- Contains `puzzles` field, defining which puzzle types this memory unit supports.
- Created by pairing `repo.payload` and `repo.typedef["common"]`.
- Once created, content cannot be modified (`__setitem__` raises `AttributeError`).
### Electron (电子) - 状态层
### Electron - State Layer
```
Electron(ident, algodata, algo_name)
```
- 算法状态数据的包装器. 每个 Electron 绑定一个算法 (`algorithms[algo_name]`).
- `algodata` 是到仓库 `algodata.lict` 中对应字典的**引用**, 修改即持久化.
- 核心方法:`activate()` (标记激活)、`revisor()` (评分迭代)、`is_due()` (到期判断).
- Wrapper for algorithm state data. Each Electron is bound to one algorithm (`algorithms[algo_name]`).
- `algodata` is a **reference** to the corresponding dictionary in the repository's `algodata.lict` — modifications are persisted immediately.
- Core methods: `activate()` (mark as activated), `revisor()` (rating iteration), `is_due()` (due check).
### Orbital (轨道) - 策略层
### Orbital - Strategy Layer
```
orbital = {
@@ -101,33 +101,33 @@ orbital = {
}
```
- 定义复习阶段流程和各阶段内谜题选择策略的纯字典.
- 每个阶段对应一组 `(谜题类型, 概率系数)` 元组列表, 概率系数 >1 的部分表示强制重复次数.
- A plain dictionary defining the review phase flow and puzzle selection strategy within each phase.
- Each phase corresponds to a list of `(puzzle_type, probability_coefficient)` tuples; coefficients >1 indicate forced repetition count.
### Atom (原子) - 运行时组装
### Atom - Runtime Assembly
```
Atom(nucleon, electron, orbital)
```
- 三者的运行时组合, 附带 `runtime` 运行时标志 (`locked`, `min_rate`, `new_activation`).
- 是 UI 和调度层操作的基本单位.
- `revise()` 方法在 `locked` 为真时调用 `electron.revisor(min_rate)`, 执行最终评分迭代.
- Runtime composition of the three, with `runtime` flags (`locked`, `min_rate`, `new_activation`).
- The basic unit operated on by the UI and scheduling layers.
- `revise()` calls `electron.revisor(min_rate)` when `locked` is true, performing the final rating iteration.
**关系图**
**Relationship Diagram**:
```mermaid
graph LR
subgraph "持久化存储"
subgraph "Persistent Storage"
Payload[(payload.toml)]
Common[(typedef.toml)]
Algodata[(algodata.json)]
Schedule[(schedule.toml)]
end
subgraph "运行时组装"
Nucleon -->|内容| Atom
Electron -->|状态| Atom
Orbital -->|策略| Atom
subgraph "Runtime Assembly"
Nucleon -->|Content| Atom
Electron -->|State| Atom
Orbital -->|Strategy| Atom
end
Payload -->|Repo| Nucleon
@@ -136,65 +136,65 @@ graph LR
Schedule -->|Repo| Orbital
```
## 调度反应器 (Reactor)
## Scheduling Reactor
调度反应器是核心业务流程引擎, 采用三层嵌套的有限状态机设计 (基于 `transitions` ).
The Scheduling Reactor is the core business process engine, designed as a three-layer nested finite state machine (based on the `transitions` library).
### 状态枚举定义
### State Enumeration
| 状态机 | 状态 | 说明 |
|--------|------|------|
| **RouterState** | `unsure` | 初始状态, 自动推进 |
| | `quick_review` | 快速复习阶段 |
| | `recognition` | 新记忆识别阶段 |
| | `final_review` | 最终总复习阶段 |
| | `finished` | 完成, 执行评分 |
| **ProcessionState** | `active` | 进行中 |
| | `finished` | 已完成 |
| **ExpanderState** | `exammode` | 考试模式 (正面答题) |
| | `retronly` | 回溯模式 (仅识别) |
| State Machine | State | Description |
|---------------|-------|-------------|
| **RouterState** | `unsure` | Initial state, auto-advances |
| | `quick_review` | Quick review phase |
| | `recognition` | New memory recognition phase |
| | `final_review` | Final comprehensive review phase |
| | `finished` | Complete, execute rating |
| **ProcessionState** | `active` | In progress |
| | `finished` | Completed |
| **ExpanderState** | `exammode` | Exam mode (frontal answering) |
| | `retronly` | Retrospective mode (recognition only) |
### 状态机嵌套结构
### State Machine Nesting Structure
```mermaid
graph TB
subgraph "Router (全局路由器)"
R[Router<br/>状态: unsure→quick_review<br/>→recognition→final_review<br/>→finished]
P1[Procession 队列1: 快速复习]
P2[Procession 队列2: 新记忆]
P3[Procession 队列3: 总复习]
subgraph "Router (Global Router)"
R[Router<br/>State: unsure→quick_review<br/>→recognition→final_review<br/>→finished]
P1[Procession Queue 1: Quick Review]
P2[Procession Queue 2: New Memories]
P3[Procession Queue 3: Final Review]
R --> P1
R --> P2
R --> P3
end
subgraph "Procession (单阶段队列)"
P1 --> E1[Expander 原子A]
P1 --> E2[Expander 原子B]
P1 --> E3[Expander 原子C]
M{forward 推进} --> |完成| Finish((FINISHED))
subgraph "Procession (Single-Phase Queue)"
P1 --> E1[Expander Atom A]
P1 --> E2[Expander Atom B]
P1 --> E3[Expander Atom C]
M{forward} --> |Done| Finish((FINISHED))
end
subgraph "Expander (单原子展开器)"
E1 --> S[(轨道策略)]
S -->|概率展开| PZ1[谜题1: MCQ]
S -->|概率展开| PZ2[谜题2: Cloze]
PZ1 -->|评分| RPT[report]
PZ2 -->|评分| RPT
RPT -->|finish| RETRO[retronly 回溯模式]
subgraph "Expander (Single Atom Expander)"
E1 --> S[(Orbital Strategy)]
S -->|Probability Expansion| PZ1[Puzzle 1: MCQ]
S -->|Probability Expansion| PZ2[Puzzle 2: Cloze]
PZ1 -->|Rating| RPT[report]
PZ2 -->|Rating| RPT
RPT -->|finish| RETRO[retronly mode]
end
```
### 数据流详解
### Data Flow Detail
```
Router.__init__(atoms)
├─ 新旧原子分流
│ ├─ old_atoms → Procession(quick_review) "初始复习"
│ └─ new_atoms → Procession(recognition) "新记忆"
├─ Split atoms into new/old
│ ├─ old_atoms → Procession(quick_review) "Initial review"
│ └─ new_atoms → Procession(recognition) "New memories"
└─ 所有原子 → Procession(final_review) "总体复习"
└─ all atoms → Procession(final_review) "Final review"
└─ Procession.forward()
@@ -205,12 +205,12 @@ Router.__init__(atoms)
└─ Expander(atom, route)
├─ 读取 orbital.routes[route_value]
├─ 概率展开为谜题列表 self.puzzles_inf
├─ exammode → 依次展示谜题
├─ report(rating) → 记录最低评分
├─ forward() → 下一个谜题或 finish → retronly
└─ retronly → 展示 Recognition
├─ Read orbital.routes[route_value]
├─ Probability expansion → self.puzzles_inf
├─ exammode → display puzzles sequentially
├─ report(rating) → record minimum rating
├─ forward() → next puzzle or finish → retronly
└─ retronly → display Recognition
└─ Atom.revise()
@@ -219,60 +219,60 @@ Router.__init__(atoms)
└─ Algorithm.revisor(algodata, feedback)
```
评分累积机制: 原子在多谜题阶段的最终评分取所有谜题的最低评分 (`min_rate`), 确保严格评估.
Rating accumulation: The final rating for an atom across multiple puzzles takes the minimum rating (`min_rate`) across all puzzles, ensuring strict evaluation.
## 算法系统
## Algorithm System
所有算法继承自 `BaseAlgorithm`, 以类方法的风格实现, 通过 `algorithms` 字典注册.
All algorithms inherit from `BaseAlgorithm`, implemented in a class-method style, registered via the `algorithms` dictionary.
| 算法 | 文件 | 状态 | 说明 |
|------|------|------|------|
| **SM-2** | `sm2.py` | ✅ 完成 | 经典 SuperMemo 1987 算法 |
| **NSP-0** | `nsp0.py` | ✅ 完成 | 非间隔过滤调度器 |
| **SM-15M** | `sm15m.py` | ✅ 完成 | 从 CoffeeScript 移植的 SM-15 |
| **FSRS** | `fsrs.py` | ✅ 部分完成 | 优化器不可用 |
| **Base** | `base.py` | ✅ 基类 | 定义 `AlgodataDict` 结构和默认值 |
| Algorithm | File | Status | Description |
|-----------|------|--------|-------------|
| **SM-2** | `sm2.py` | ✅ Complete | Classic SuperMemo 1987 algorithm |
| **NSP-0** | `nsp0.py` | ✅ Complete | Non-spaced filtering scheduler |
| **SM-15M** | `sm15m.py` | ✅ Complete | SM-15 ported from CoffeeScript |
| **FSRS** | `fsrs.py` | ✅ Partial | Optimizer not available |
| **Base** | `base.py` | ✅ Base class | Defines `AlgodataDict` structure and defaults |
每个算法提供以下类方法:
Each algorithm provides the following class methods:
| 方法 | 功能 |
|------|------|
| `revisor(algodata, feedback, is_new_activation)` | 根据评分迭代记忆数据 |
| `is_due(algodata)` | 判断是否到期复习 |
| `get_rating(algodata)` | 获取评分信息 |
| `nextdate(algodata)` | 获取下一次复习时间戳 |
| `check_integrity(algodata)` | 校验 algodata 数据结构完整性 |
| Method | Function |
|--------|----------|
| `revisor(algodata, feedback, is_new_activation)` | Iterate memory data based on rating |
| `is_due(algodata)` | Check if due for review |
| `get_rating(algodata)` | Get rating information |
| `nextdate(algodata)` | Get next review timestamp |
| `check_integrity(algodata)` | Validate algodata data structure integrity |
### 算法数据结构 (AlgodataDict)
### Algorithm Data Structure (AlgodataDict)
```python
{
"real_rept": int, # 实际复习次数
"rept": int, # 当前重复计数
"interval": int, # 间隔天数
"last_date": int, # 上次复习日期
"next_date": int, # 下次到期日期
"is_activated": int, # 是否已激活 (0/1)
"last_modify": float, # 最后修改时间戳
"real_rept": int, # Actual review count
"rept": int, # Current repetition count
"interval": int, # Interval in days
"last_date": int, # Last review date
"next_date": int, # Next due date
"is_activated": int, # Whether activated (0/1)
"last_modify": float, # Last modification timestamp
}
```
## 仓库系统 (Repo)
## Repository System (Repo)
仓库为 TOML/JSON 文件目录, 无数据库依赖.
The repository is a directory of TOML/JSON files with no database dependency.
### 目录结构
### Directory Structure
```
data/repo/<package_name>/
├── manifest.toml # 元信息: title, author, package, desc
├── typedef.toml # 通用元数据、谜题定义、注解
├── payload.toml # 记忆条目 (key=ident)
├── algodata.json # 算法状态 (key=ident)
└── schedule.toml # 轨道/复习策略
├── manifest.toml # Meta info: title, author, package, desc
├── typedef.toml # Common metadata, puzzle definitions, annotations
├── payload.toml # Memory items (key=ident)
├── algodata.json # Algorithm state (key=ident)
└── schedule.toml # Orbital/review strategy
```
### Repo 类设计
### Repo Class Design
```mermaid
classDiagram
@@ -294,114 +294,114 @@ classDiagram
}
```
- `payload` `algodata` 使用 `Lict` (列表+字典混合容器), 支持双模式访问.
- `_generate_particles_data()` 在初始化时自动将 payload 数据转换为 `Nucleon` 所需的格式.
- 默认保存列表 `default_save_list = ["algodata"]`, 仅持久化算法状态.
- `payload` and `algodata` use `Lict` (list+dict hybrid container), supporting dual-mode access.
- `_generate_particles_data()` automatically converts payload data to `Nucleon`-required format during initialization.
- Default save list: `default_save_list = ["algodata"]`, only persists algorithm state.
## Lict 集合
## Lict Collection
`Lict` 继承 `MutableSequence`, 同时维护列表和字典访问:
`Lict` extends `MutableSequence`, maintaining both list and dictionary access:
```python
lict = Lict()
lict.append(("key1", value1)) # 列表追加
lict["key1"] # 字典访问
lict[0] # 索引访问
lict.keys() # 所有键
lict.dicted_data # 纯字典导出
lict.append(("key1", value1)) # List append
lict["key1"] # Dict access
lict[0] # Index access
lict.keys() # All keys
lict.dicted_data # Plain dict export
```
脏同步机制:修改列表时自动同步字典, 修改字典时自动同步列表. 用于 `payload` `algodata` 的双模式访问需求.
Dirty sync mechanism: modifying the list automatically syncs to the dictionary; modifying the dictionary automatically syncs to the list. Used for dual-mode access to `payload` and `algodata`.
## 配置系统 (ConfigDict)
## Configuration System (ConfigDict)
`ConfigDict` 继承 `UserDict`, 是**单例模式** TOML 懒加载配置管理器.
`ConfigDict` extends `UserDict`, a **singleton** TOML lazy-loading configuration manager.
### 配置目录约定
### Configuration Directory Convention
```
data/config/
├── _.toml # 顶层默认值 (递归合并)
├── _.toml # Top-level defaults (recursive merge)
├── interface/
│ ├── _.toml # interface 层默认值
│ ├── _.toml # Interface layer defaults
│ ├── global.toml
│ └── puzzles.toml
├── services/
│ ├── _.toml # services 层默认值
│ ├── _.toml # Services layer defaults
│ ├── audio.toml
│ └── tts.toml
└── repo/
└── _.toml
```
- `_.toml` 文件 = 该目录层级的默认值, 合并到父级
- 带后缀文件 = 按需懒加载
- 子目录 = 递归子配置
- `_.toml` files = defaults for that directory level, merged into parent
- Suffixed files = lazy-loaded on demand
- Subdirectories = recursive sub-configuration
### 上下文管理
### Context Management
```python
from heurams.context import config_var, ConfigContext
# 全局访问
# Global access
config = config_var.get()
algo = config["interface"]["global"]["algorithm"]
# 作用域覆盖
# Scope override
with ConfigContext(test_config):
... # 临时使用测试配置
... # Temporarily use test configuration
```
## 提供者系统 (Providers)
## Provider System (Providers)
可插拔的后端实现, 通过 `providers/__init__.py` 中的字典注册.
Pluggable backend implementations, registered via dictionaries in `providers/__init__.py`.
| 类别 | 提供者 | 说明 |
|------|--------|------|
| **TTS** | `edge_tts` | Microsoft Edge TTS (在线) |
| | `basetts` | 桩基类 (未实现) |
| **Audio** | `playsound` | 跨平台音频播放 |
| | `termux` | Android Termux 环境 |
| **LLM** | `openai` | OpenAI 兼容 API (未完整实现) |
| Category | Provider | Description |
|----------|----------|-------------|
| **TTS** | `edge_tts` | Microsoft Edge TTS (online) |
| | `basetts` | Stub base class (not implemented) |
| **Audio** | `playsound` | Cross-platform audio playback |
| | `termux` | Android Termux environment |
| **LLM** | `openai` | OpenAI compatible API (not fully implemented) |
选择方式:`services/*.toml` 中的 `provider` 字段.
Selection method: `provider` field in `services/*.toml`.
## 谜题系统 (Puzzles)
## Puzzle System (Puzzles)
谜题引擎用于在复习阶段生成评估视图:
The puzzle engine generates evaluation views during review phases:
| 谜题 | 文件 | 说明 |
|------|------|------|
| **MCQ** | `mcq.py` | 选择题 (Multiple Choice) |
| **Cloze** | `cloze.py` | 完形填空 (Cloze Deletion) |
| **Recognition** | `recognition.py` | 认读识别 |
| **Guess** | `guess.py` | 猜测词义 |
| **Base** | `base.py` | 抽象基类 |
| Puzzle | File | Description |
|--------|------|-------------|
| **MCQ** | `mcq.py` | Multiple Choice Questions |
| **Cloze** | `cloze.py` | Cloze Deletion |
| **Recognition** | `recognition.py` | Recognition identification |
| **Guess** | `guess.py` | Word meaning guessing |
| **Base** | `base.py` | Abstract base class |
谜题通过轨道策略 (Orbital)在 `Expander` 中按概率展开, 每个原子可产生多个谜题, 每个谜题独立评分.
Puzzles are expanded probabilistically by the Orbital strategy in the `Expander`. Each atom can generate multiple puzzles, and each puzzle is rated independently.
## 服务层
## Service Layer
| 服务 | 文件 | 说明 |
|------|------|------|
| **Config** | `config.py` | `ConfigDict(UserDict)` TOML 懒加载单例 |
| **Logger** | `logger.py` | `get_logger(name)`层级日志 (`heurams.*`) |
| **Timer** | `timer.py` | `get_daystamp()` / `get_timestamp()`, 支持可配置覆盖 |
| **Audio** | `audio_service.py` | 音频播放, 路由到配置的音频提供者 |
| **TTS** | `tts_service.py` | 文本转语音, 路由到配置的 TTS 提供者 |
| **Favorites** | `favorite_service.py` | JSON5 持久化的收藏管理器 (单例) |
| **Attic** | `attic.py` | 结构化 pickle 持久化, 支持 `<DAYSTAMP>`/`<TIMESTAMP>` 占位符 |
| **Hasher** | `hasher.py` | MD5 哈希 |
| **Epath** | `epath.py` | 点符号嵌套字典访问 (`epath(dct, "a.b.c")`) |
| Service | File | Description |
|---------|------|-------------|
| **Config** | `config.py` | `ConfigDict(UserDict)` TOML lazy-loading singleton |
| **Logger** | `logger.py` | `get_logger(name)`hierarchical logger (`heurams.*`) |
| **Timer** | `timer.py` | `get_daystamp()` / `get_timestamp()`, supports configurable override |
| **Audio** | `audio_service.py` | Audio playback, routes to configured audio provider |
| **TTS** | `tts_service.py` | Text-to-speech, routes to configured TTS provider |
| **Favorites** | `favorite_service.py` | JSON5-persisted favorites manager (singleton) |
| **Attic** | `attic.py` | Structured pickle persistence, supports `<DAYSTAMP>`/`<TIMESTAMP>` placeholders |
| **Hasher** | `hasher.py` | MD5 hashing |
| **Epath** | `epath.py` | Dot-notation nested dict access (`epath(dct, "a.b.c")`) |
| **TextProc** | `textproc.py` | `truncate()`, `domize()`, `undomize()` |
日志系统:每个模块通过 `get_logger(__name__)` 创建自己的日志器, 日志文件 10MB 轮转, 最多 5 个备份, 追加到 `heurams.log`.
Logging system: Each module creates its own logger via `get_logger(__name__)`. Log files rotate at 10MB, max 5 backups, appended to `heurams.log`.
## 复习全流程
## Complete Review Flow
```mermaid
sequenceDiagram
participant User as 用户
participant User as User
participant UI as TUI
participant Router as Router
participant Procession as Procession
@@ -410,29 +410,29 @@ sequenceDiagram
participant Electron as Electron
participant Algo as Algorithm
User->>UI: 开始复习
User->>UI: Start Review
UI->>Router: Router(atoms)
Router->>Procession: 创建复习队列
Router->>Procession: 创建新记忆队列
Router->>Procession: 创建总复习队列
Procession->>Expander: 展开当前原子
Expander->>Expander: 解析轨道策略
Expander-->>UI: 展示谜题
User->>UI: 评分 (1-5)
Router->>Procession: Create review queue
Router->>Procession: Create new memory queue
Router->>Procession: Create final review queue
Procession->>Expander: Expand current atom
Expander->>Expander: Parse orbital strategy
Expander-->>UI: Display puzzle
User->>UI: Rate (1-5)
UI->>Expander: report(rating)
Expander->>Expander: forward() 下一个谜题
Expander-->>UI: 下一个谜题或回溯
Expander->>Expander: forward() next puzzle
Expander-->>UI: Next puzzle or retrospective
Expander->>Expander: finish() → retronly
Expander-->>UI: Recognition 回溯
User->>UI: 最终评分
Expander-->>UI: Recognition retrospective
User->>UI: Final rating
UI->>Atom: revise()
Atom->>Electron: revisor(min_rate)
Electron->>Algo: revisor(algodata, feedback)
Algo-->>Electron: 更新 algodata
Algo-->>Atom: 更新 interval, next_date
Procession->>Procession: forward() 下一原子
Procession-->>Router: 队列完成
Router->>Router: 切换阶段
Router-->>UI: 完成 (finished)
UI->>User: 显示总结
Algo-->>Electron: Update algodata
Algo-->>Atom: Update interval, next_date
Procession->>Procession: forward() next atom
Procession-->>Router: Queue complete
Router->>Router: Switch phase
Router-->>UI: Complete (finished)
UI->>User: Show summary
```