TianTianSpeak 文档

文档/开放格式

tasks 格式说明

任务是一个 JSON 文件,描述「要做哪些练习、做到什么程度」。进度不另存,每次由你的练习记录算出来,删了记录进度跟着回退。App 里「任务 → 导入任务」选文件即可。

最小的任务#

累计完成三次、都要 90 分以上的朗读:

three-reads.json
{
  "id": "three-reads-90",
  "name": "三次 90 分",
  "description": "朗读三篇,每篇 90 分以上。",
  "steps": [
    {"type": "readAloud", "times": 3, "minScore": 90}
  ]
}

id、name 和 steps(或 stages)是必填的。同 id 再次导入是替换,开始状态保留。Schema:task.schema.json。

步骤 step#

一个步骤就是一条要满足的条件,用来匹配你产生的练习记录。

字段说明
type必填:readAloud 朗诵 / retell 复述 / speak 口述(旧名 diary 也认)
mode模式,不写 = 该模块任意模式;可写数组,任一即可。取值见下表
style仅口述的自我介绍 / 汇报:introNormal introInterview reportWork reportReview;与 mode 矛盾会报错
times需要达标几次,默认 1。在 daily 阶段里是每天几次
minScore总分下限,0–100
minChars转写字数下限(复述、口述):写数字,或按年龄段写对象,没写的年龄段不限
minDurationSeconds时长下限(秒)
minAccuracy / maxSeconds仅打字、默写:正确率下限 0–100 / 用时上限
sameArticletrue:times 次必须是同一篇。「每天同一篇读 3 次」就是 A 读 3 次才算,A、B、A 只算 2 次。需要 minAppVersion ≥ 0.5.18
target限定内容:bank + title 指定某一篇;只写 bank 是该题库任意一篇;bankSet 引用题库集合(见下)

mode 的取值#

模块mode
readAloudread 朗读 · recite 背诵 · typing 打字 · dictation 默写。不写 mode 时只含 read 和 recite,要打字、默写必须明确写
retellnormal 正常 · brief 极简总结 · structured 总分总 · guided 指导
speakdiary 日记 · topic 命题说话 · intro 自我介绍 · report 工作汇报 · review 读后感
写错模式会被拒绝

不认识的模式不会被悄悄当成「不限」,导入时报「可能需要升级 App」。

阶段与「每天」#

一个扁平的步骤列表表达不了「三周 × 每天」。用 stages 代替 steps:

  • 每个阶段有自己的 steps,按 order 顺序(或任意顺序)完成。只有 steps 的任务等价于一个阶段。
  • daily: true + days: N:阶段里全部步骤每天都要达标,累计 N 个达标日阶段才完成,不要求连续,漏一天不用重来。一天按本地时间的自然日算。
  • daily 默认 false,此时步骤在整个阶段内累计。days 只能和 daily 一起用。
  • 同一个阶段(daily 按天)里,一条练习记录只算给一个步骤:先分给指定了具体 mode 的,剩下的再分给更宽的。所以「复述 3 篇,其中 1 篇极简总结、1 篇总分总」写成三个步骤:brief ×1、structured ×1、不限模式 ×1。
memory-14-day.json(官方任务,说明略有精简)
{
  "id": "memory-14-day",
  "name": "练记忆 14 天",
  "description": "累计 14 个达标日,每天朗诵 6 次、背诵 2 次,题库不限。",
  "order": "sequence",
  "badge": {"id": "memory-14", "name": "记忆达人", "icon": "brain.head.profile", "description": "14 天坚持朗诵与背诵"},
  "stages": [
    {"id": "daily", "name": "每日朗诵与背诵", "days": 14, "daily": true,
     "steps": [
       {"type": "readAloud", "mode": "recite", "times": 2},
       {"type": "readAloud", "mode": "read", "times": 6}
     ]}
  ]
}

按年龄段指定题库 bankSets#

顶层 bankSets 定义题库集合,步骤的 target 用 {"bankSet": "名字"} 引用,表示「集合里任意题库的任意一篇」。键是年龄段:kindergarten primary middle high adult。集合也可以是普通数组(所有人相同)。

"bankSets": {
  "byAge": {
    "kindergarten": ["hsk-1", "hsk-2"],
    "primary": ["zh-grade-1", "zh-grade-2", "zh-grade-3"],
    "adult": ["putonghua-50"]
  }
},
"steps": [
  {"type": "readAloud", "times": 3, "target": {"bankSet": "byAge"}},
  {"type": "speak", "mode": "review", "target": {"bankSet": "byAge"},
   "minChars": {"kindergarten": 50, "primary": 100, "adult": 300}}
]
  • 当前用户的年龄段在集合里没有对应项时,任务不能开始,并提示原因。
  • 这里的题库 id 是题库文件里写的 id(见 稳定标识),本机没有该题库时,任务卡片会提示缺哪些,并可跳到题库商店。

顶层字段#

字段说明
id name必填。id 只用字母、数字和 ._-;别以 custom- 开头,那是 App 里新建的自定义任务专用
description任务卡片上的说明,用 \n 换行
ordersequence(默认)按顺序解锁;any 任意顺序。顺序任务里,上一阶段完成之后的记录才算数下一阶段
ageGroups只对这些年龄段显示;不写 = 所有人
badge完成整个任务得一枚徽章:id name icon(SF Symbol 名,不存在时用默认图标)description。授予后不撤销
minAppVersion最低 App 版本,如 "0.5.18"。版本更低的 App 会标「需要升级 App」,不能开始。用到较新的能力(如 sameArticle)要写

计算规则要点#

  • 只统计任务开始之后产生的记录,历史记录不会直接把任务刷完。
  • 打字、默写不加每日积分、不进日历分数,但任务里可以明确用 typing / dictation 来要求。
  • 任务本身不加积分;任务里的练习照常计入每日积分。

校验#

导入时 App 会校验,不通过会说明原因:缺 id / 名称、steps 和 stages 同时写、没有步骤、daily 阶段缺 days、minScore 越界、找不到题库集合、写了 title 没写 bank 等。也可以先用 task.schema.json 在本地检查:

shell
pip install jsonschema
python3 - <<'EOF'
import json
from jsonschema import Draft202012Validator as V
schema = json.load(open("task.schema.json"))
print(list(V(schema).iter_errors(json.load(open("three-reads.json")))))
EOF
在线任务的样子

现有的官方任务见题库商店 · 任务。想让 AI 帮你写,见 用 AI 制作 tasks。