家庭积分账本

孩子把表现换成积分,积分换成想要的东西。攒得越多,账本里那栋房子越大 —— 从破帐篷一路盖到云端宫殿,花掉了就缩回去。

这是可操作的演示:孩子、流水、余额全是合成数据,随便点。 真实系统在登录闸后运行,服务于一个真实家庭,账本内容不在这里。 你的改动只存在你自己的浏览器里,点「重置演示」即可还原。

1 · 这套系统解决什么问题

「表现好给你记 5 分」这句话,用纸和笔记不了三天 —— 家长记不全、孩子不信、攒到最后谁也说不清有多少。麻烦不在加减法上,在下面这些地方:

真实难点这套系统的取舍
数字不会让人心动 攒到 4500 分和攒到 8000 分,对孩子来说都只是「一个数」。所以给总市值划了 11 个家园档位,跨档时整页换装:破帐篷 → 茅草屋 → 砖瓦房 → 花园洋房 → 城堡 → 云端天堂。换场景不花积分,只看当前市值 —— 挣分房子长,花分房子缩,财富的诚实具象化,没有第二套逻辑。
孩子会给自己加分 权限故意不对称:孩子拿长效登录态,只能看账本、兑换、刷题;家长每次加分都要现场输口令,且不发 cookie。孩子拿到一台已登录的平板也加不了分 —— 能自己给自己加分的积分系统,第二天就变成刷分游戏。
唯一免口令的口子会被刷 「刷题自动得分」是唯一不需要家长在场的加分通道,所以额度由服务端按人按天封顶(每天 30 分)。改前端、直接调接口,都刷不出上限以外的分。
规则有 83 条、5 种形态 不写死在代码里。固定分 / 按个数 / 家长在区间内定 / 档位计算器 / 换电视时间,全在一份规则配置里。像「跳绳 3 组 190 个记 120 分」「语文 85 分以下少一分扣 5 分」这类公式本身也是配置,改规则不动代码。
预览和记账算出两个数 填数字时页面上要实时显示「这么算是多少分」。预览与真正记账走的是同一个计算函数,前端不复刻一份算法 —— 两边各算各的,迟早算出不同的数。
余额和流水对不上 账本 append-only,余额永远从流水累加出来,不单独存一个余额字段。存了就会漂移,而漂移的账本比没有账本更糟。
不只有一种货币 有些事只换电视时间不换钱(认识生字、背单词),有些事扣时间(拖延);「满足一个心愿」是第三本账。三本账走同一条时间线,各自累加各自的余额。
记错了怎么撤 撤销 = 把那条挪进留底区 + 重算其后每一条的余额快照,页面和走势图当它没发生过。早期做的是会计式红冲(记一笔反向流水),实测被否:走势图留一个凸起、流水里一排「撤销 xxx」,过程比错误本身还难看。
把纸表转成配置会编数 规则源头是家长手写的一张表。转成 83 条结构化规则时,有 6 处填了原表根本没有的值(「扣 10 以上」自己补了下限、「酌情」自己补了区间)—— 所有机器检查全绿、页面也正常。后来把原表逐格转成纯文本一起入库,用出处校验脚本逐条比对,才把这条路堵死。

下面这些规则、档位阈值和计算公式,都是真实系统里在跑的那一套;数据是编的。

2 · 上手点点看

加几笔分看市值涨、房子换装;再去商店花掉,看它缩回去。加分和撤销要家长口令(演示口令 2468),兑换和刷题不用 —— 这就是那条不对称的权限线。

小木屋
COTTAGE
🏚️
总市值
0 ≈ 0.00 元
📺 电视时间 0 分钟 🌠 心愿 0 ✏️ 今日刷题额度剩 30
家长口令 未验证 —— 加分、扣分、撤销都不放行
口令不换 cookie,每次操作都要它在场。
选一条规则

3 · 技术上怎么做的

部件做法与理由
后端Python 单文件、只用标准库,数据是几个 JSON 文件,systemd 起一个进程 + 一行 nginx 反代。一个家庭的量级,装依赖、拆服务、上数据库全是净成本。
账本append-only,只有一个写入口函数。余额 = 流水累加,按币种各算各的(积分 / 电视分钟 / 心愿次数)。扣分条款可以把积分扣成负的(欠着下次挣回来),但兑换那条路径不开透支的口子
规则引擎83 条规则 + 5 个档位计算器写在一份配置里,服务端和页面读同一份。5 种形态:固定分 / 按个数乘 / 家长在区间内填 / 档位计算器 / 换电视时间。档位从上往下第一个命中的生效,不重复累计
表达式求值配置里存的是字符串公式(15 + floor((n - 48) / 5))。绝不用 eval —— 那等于把任意代码执行权交给配置文件。走 AST 白名单:只放行数字、变量、四则、比较、and/or 和 7 个数学函数,看不懂的语法一律抛错,不猜、不放行。
皮肤分级11 档阈值 + 5 套时代皮肤是另一份配置(本页把它原样搬过来了)。服务端只回答「多少钱住什么房」,页面拿到时代标识给根元素挂一个属性,整套 CSS 变量和装饰跟着换。加一档、改一个阈值、换一套底图,都是改数据。
会话HMAC 签名的长效 token 走 cookie(孩子端);家长口令每次现验、不换 cookie。两种身份的生命周期不同,是设计不是遗漏。
出处门规则的一手来源(家长手写表)连同逐格纯文本转录一起入库,校验脚本逐条比对结构化后的 83 条规则。纯文本能 diff 能 grep —— 这是唯一能抓住「编了一个看着合理的数」的手段,因为那种错所有机器门都是绿的。
这个演示页单文件、零外部请求、零后端。上面那套计算逻辑(表达式求值器、档位计算器、五种规则形态、市值分档)用原生 JS 按同样的语义重写了一遍,数字是当场算的,不是写死的假数。
演示数据全部合成,仅存在于你的浏览器(localStorage)。本页不向任何服务器发送数据。