WRITING
我给孩子做了个「资产盘面」,他每天自己去看涨了多少

贴纸和小红花的问题不是不管用,是攒不住。
攒到第十七张,就没人记得第一张是为什么给的,更没人记得上周到底是涨了还是跌了。 孩子看不见自己在变好,只看得见今天有没有拿到那一张。
所以我把它做成了一个账本 —— 每一笔加分扣分都有事由、有时间、有当时的余额, 攒起来的那个总数摆在最上面,像看盘一样。
他现在每天回家自己点开看涨了多少。
一、打开是这样

最上面那个大数字是他的总积分。旁边跟着今天涨了多少、涨了百分之几、折合多少钱, 还有一个「历史新高」的标记 —— 破了自己的记录就会亮出来。
下面是三十天的走势。这条线是这套东西真正起作用的地方:单看今天加了 10 分没什么感觉, 看见这条线从月初一路爬到现在,感觉完全不一样。
再往下按学科拆开。哪一栏一直是矮的,不用我说他自己看得见。
二、一次加分是怎么走完的
分不是随手给的,是照着一张表给的。
家里本来就有一张《积分条例》,Excel 表,语文数学英语科学体育小号道法劳动一直到 「爸爸特别奖励」,奖分扣分并列写着。我把那张表整个搬进了系统 —— 83 条规则,一条不改,一条不漏。

打开「给他加分」,第一眼是锁着的。规则能看,分加不了 —— 要先输家长密码。

解锁之后整面墙铺开,每条规则一个按钮,点一下就记上。 按钮上那些小标签,是这条规则该怎么算:
| 标签 | 什么意思 | 例子 |
|---|---|---|
| (无) | 固定分,点一下就记 | 听写全对一次 +10 |
按个数 | 你填个数,按个算 | 听写错字 −1/个 |
自己填 | 表里给的是区间,你在区间里定 | 诗歌小古文背诵 10~50 |
算一下 | 有档位,填完自动算 | 跳绳 · 仰卧起坐 · 考试 |
换时间 | 换的不是分,是看电视的时间 | 认识生字 +1 分钟/2 个字 |
「算一下」这类最能说明问题。原表里跳绳写着七个档位,末尾一句「不重复累计」:

填「跳了 3 组、每分钟 190 个」,它自己算出 +120 分, 并且告诉你为什么是 120 —— 命中的是「3 组 190 个以上」那一档。
不用翻表,也不会把 180 那一档和 190 那一档记混。这种事人来记,迟早记混一次; 记混一次,孩子就知道这套规则是可以商量的。
三、防的是哪几件事
一个能自己给自己加分的积分系统,第二天就变成刷分游戏。所以这几条是硬的:
| 会发生的事 | 它怎么处理 |
|---|---|
| 孩子拿到已登录的平板,自己加分 | 加分要家长密码,而且每次现输。孩子这边登录多久都加不了一分 |
| 分不够还想换东西 | 换不了。卡片上写着「还差 N 分」 |
| 靠刷题无限挣分 | 做题挣的分每天封顶 30,而且是服务器那边封的,前端报多少都不算数 |
| 一道题不做直接交卷 | 不给分 |
| 记错了、点错了 | 每条流水后面有「撤销」。撤销是反向记一笔,原来那笔留在账上不删 |
| 扣分扣成负数 | 允许,欠着下次挣回来 —— 表里的扣分条款本来就是这么定的 |
最后一条特意说一下:这个账本不删记录。 撤销不是抹掉,是红冲。 半年后翻回去,什么时候记错过、什么时候改过,全都在。
一个能被悄悄改的账本,比没有账本更糟。
四、快到手的那一件,一直摆在眼前

商店里 12 件东西,从 150 分的「多看一集动画」到 20000 分的「一次短途旅行」。 买得起的亮着,买不起的灰着 —— 但灰的那些写着还差多少分。
图里这个状态是我特意摆出来的,因为它是整套东西里最有效的一屏:
「满足一个心愿」1500 分,还差 60 分。
60 分是什么概念?听写全对一次 +10,洗全家碗筷 +10,晨跑半小时 +20。 今天再做几件事就够了。
这比「继续加油」有用得多。「差一点」是能算出来的,而「加油」不能。
五、每一分是怎么来的,都查得到

这是我自己最看重的一屏。
每一笔都有时间、有事由、有当时的余额。不是「你有 1440 分」, 是「8 月 8 号爸爸特别奖励 +300,余额从 1080 变成 1380」。
余额那一列不是单独存着的一个数字,是从流水一笔一笔加出来的。 所以账本和余额永远不可能对不上。
上面还能筛「只看加分」「只看花掉的」。这个月钱都花哪儿去了,一点就出来。
六、现在有什么
先说口径:下面数的是规则表和商店的条目数,不含系统自带的机制 (做题积分、每日上限、撤销这些不算规则),也不含练习平台那边的题库。
| 项 | 数量 | 说明 |
|---|---|---|
| 规则 | 83 条 | 全部来自家里那张表,逐条搬进来的 |
| 覆盖学科 | 9 门 | 语文 28 · 数学 13 · 劳动 10 · 英语 9 · 体育 8 · 道法品德 7 · 小号 4 · 日常 3 · 爸爸特别奖励 1 |
| 其中扣分条款 | 23 条 | 奖分扣分并列,不是只报喜 |
| 规则形态 | 5 种 | 固定分 49 · 家长填区间 17 · 按个数 9 · 档位计算器 5 · 换电视时间 3 |
| 档位计算器 | 5 个 | 跳绳 · 仰卧起坐 · 语文考试 · 比上次进步 · 作文字数 |
| 兑换商品 | 12 件 | 150 分到 20000 分 |
| 货币 | 3 种 | 积分 · 电视时间 · 心愿,走同一条时间线 |
| 汇率 | 100 分 = 1 元 | 表里原写 10 分兑 1 元;按表里的分值估下来一个月约 1700 分,十比一就是 170 元/月,一个三年级小孩的零花钱,我判定偏高,压了十倍 |
还空着的:规则表里「科学」那一栏一条规则都没有 —— 家里那张表就没写。 首页那张卡会一直显示 0,等补。空着的地方我不替它编,编出来的规则执行不下去。
七、想要一套的话
这套东西是给我自己家做的,跑在我自己的服务器上,没有开放注册,这篇也不放地址 —— 里面是一个具体的小孩的账本、他的错题和他的试卷。
想要的话跟我说,我可以帮你搭一份你自己的:一张你家自己的规则表、一个你自己的账本, 数据在你自己手里。规则表长什么样都行,我这份就是从家里现成的 Excel 一条条搬进去的。
八、给同行的一段
零第三方依赖。服务端是 Python 标准库写的一个 HTTP 服务,静态文件和接口都归它发,
数据是一个 JSON 账本文件。整套东西一条 pip install 都没有。
几条我自己觉得值得说的约束:
- 登录门在应用层,不在 nginx。 用
auth_request的话,登录门在本地根本测不到, 等于没有门。现在本地起一份就能跑同一条路径,测的是真的那道门。 - 家长密码不发 cookie。 这是有意的 —— 发了,孩子拿到已登录的平板就能自己加分。
- 分值一律服务端算,页面预览和真正记账走的是同一个函数。 两边各算各的, 迟早算出不同的数,而家长看到的是预览、孩子拿到的是记账。
- 档位表达式用
ast白名单求值,绝不用eval。 表达式来自配置文件,eval等于把任意代码执行权交出去。 - 账本 append-only,余额永远从流水累计。 单独存一个 balance 字段就会和流水漂移。
- 每个分值都得能在原表里指出出处。 原表没给的(比如「其他酌情加分」没给数), 必须在那条规则上标明「这个值是我们定的」—— 有一道机器门盯着,标不出来就红。 这条是上一篇的教训换来的。
关于这几张图
全部是真页面跑真操作截下来的,不是画的示意图:起一个真的服务端、真的登录、 真的点解锁、真的点规则按钮,一条命令能全部重跑。截图前还要过三道门 —— 该出现的东西在不在、页面是不是白屏(白屏照样能截出一张图,得看像素)、 以及公开前把第三方真名遮掉。
图里的账本是造出来的演示数据,真实账本一个字节都没进来:服务端跑在临时目录里, 跑完就没;规则编号和商品全从产品自己的配置现取,取不到就报错退出,不编。
第一版我在演示脚本里编了 8 个不存在的规则编号,被这道校验当场抓住 —— 刚写完上一篇讲编数字的教训,转头又犯一次。 这大概就是为什么那道校验得写死在代码里,而不是写在文档里。
相关文章
订阅
新文章都先发在这里。用 RSS 订阅: /feed.xml