排班劳资权衡精算引擎
> 适用对象:HR / 薪酬经理 / 班表规划者 / 排班优化研究者。
> 输出形式:HTML 报告(含权衡平面 SVG)+ 可行集 CSV。
> 计算量:13 块窗口约 50.9 万序列,向量化数秒完成;运行无需联网。
何时使用 【必看】
- 用户需要为某段连续窗口(典型 13 块 = 91 天,约一个季度)做排班方案的劳资权衡分析。
- 需要在"员工收入最大化"与"公司单位人力成本最小化"之间做量化取舍,并给出可解释的最优/对比方案。
- 需要一份含逐月/全程对比表、劳资权衡平面(散点图)的交付级 HTML 报告。
🚀 一句话 TL;DR(30 秒能记住) 【必看】
> 给定一段连续窗口(默认 13 块 = 91 天),枚举所有合法的"7天块调度"序列,逐方案算员工均薪 vs 公司时均,给你看一份带权衡平面 SVG 的 HTML 报告。
> 最快上手:python run.py 一键完成(默认 2026/08/01 ~ 2026/10/31)。
> ⚠ 先看 ❌ 不能做什么 和 ⚖️ 我能做但有代价 两条再决定要不要用,避免踩坑。
📖 阅读路径图(按你想要的深度走,不用 500 行一次看完) 【必看】
| 你的角色 / 想法 | 看完这一档需要多久 | 跳到这些章节(按顺序) |
|---|---|---|
| 🟢 完全没听说过本引擎——想 30 秒内决定要不要试 | 30 秒 | 🚀 TL;DR → ❌ 不能做什么 → 🛤️ 新手入门 5 步走 |
| 🟡 想马上跑通一份报告看效果——按部就班 | 3 分钟 | 🛤️ 新手 5 步走(Step 1-3)→ 📐 执行流程 → 📊 输出长什么样 |
| 🔵 想改参数 / 换年份 / 跑特定窗口——动手党 | 10 分钟 | 🟡 上面的 + 🚀 场景速查表 + 适配其他年份 / 窗口 + CLI 参数 |
| 🟣 想理解"为什么这么算 / 怎么调参更划算 / 跨档怎么权衡"——研究者 | 30 分钟 | 🔵 上面的 + 方法论 + 💡 延伸思考 + 选方案逻辑 |
> 💡 每个章节标题前缀的标签: 【必看】= 必读、【选看】= 有空再看、【原理】= 想深入再看、【进阶】= 调参 / 深度用再看。
🛤️ 新手入门 5 步走(首次使用必看) 【必看】
> 一条统一路径。首次用就把这 5 步走完,中间任何一步卡住去 常见问题 FAQ 找答案;找不到再翻 错误码索引附录。
Step 1 · 确认本引擎能做(30 秒)
- 直接看 ❌ 不能做什么(避开你用不了的场景)。
- 你的场景不在"❌"清单里 → 继续;命中 → 看 ⚖️ 我能做但有代价 里是否有近似替代。
Step 2 · 一键跑通默认报告(2 分钟)
- 在本 skill 目录下执行:
python run.py - 看到
✅ 完成 + 报告路径即成功,不用看任何源码。 - 如果报错:直接复制错误末尾的
[错误码: E00X],去 错误码索引附录 对应行查建议。
Step 3 · 看懂报告(5 分钟)
- 打开
reports/班表精算报告.html。 - 先看顶部"📊 洞察摘要"区块——引擎已经替你把关键数字提炼出来(最大可行 H 档 / H 跨档罚款差 / 折中 vs 边界 距离)。
- 再翻到"三、H={H} 档 · 方案对比"看权衡平面散点图——散点越靠左上,员工均薪越高 + 公司时均越低,是理想的"双赢点"。
- 整篇报告为谁服务、怎么读,看 📊 输出长什么样。
Step 4 · 按你的场景改参数(5-10 分钟)
- 想跑别的年份 / 别的窗口 / 别的固定费?查 🚀 场景速查表 找最像你场景的那一行,照抄命令。
- 想知道每个参数的取值含义 / 默认是什么,看 CLI 参数 或 环境变量。
Step 5 · 排查问题 / 想深入(按需)
- 想搞懂"为什么这个方案最优 / 跨档罚款差怎么算 / 节假日三倍怎么定级" → 💡 延伸思考。
- 出错时优先看 错误码索引附录 + 运行
--doctor模式做自检:python schedule_engine.py --doctor。
❌ 不能做什么(先看这条再决定要不要用) 【必看】
本工具只适用以下场景;其它请绕道:
| ❌ 不能做 | 超范围时的近似替代方案(v1.4.0) |
|---|---|
| 非 7天块调度(如 5+2 / 4+3 / 10天1休 / 自定义作息) | 把"非 7天块"作息按周映射到 7天块:A→B→C 看 5天工/2天休;B→C 看 6/1;C→7/0。误差是双倍/三倍日的精细分布。注意这只是近似。v1.5.0 roadmap 会做真正的多周期扩展。 |
| 多团队/多班次并发排班 | 当前仅分析单人整月块序列。多员工请逐人跑(每次改 START_DATE 不行,需要改员工 ID 后缀输出文件),最后用 pandas 合并 feasible_H*.csv。v1.5.0 roadmap 加多员工并跑。 |
| 跨年窗口(同时含两个年份的节假日规则) | 拆成两窗口分别跑取并集/交集;详见下面「边界场景案例 1:跨年」。也可以调小 WINDOW_DAYS 让窗口不跨年。 |
| 社保 / 个税 / 加班费上限 等法定合规校验 | 本工具只校验"月≥208H 且 月≥6500元"两条建模阈值;不替代法律咨询(详见 Q9)。合规相关请走 HR 法务流程。 |
| 实时排班(按今天日期动态出方案) | 本工具是离线精算——窗口由 START_DATE 显式指定;不做实时调整。如需今日生效,先跑 --doctor 拿当前日期,再用当日日期作 START_DATE 跑。 |
| H=8 档下"只看正常档"分析 | H=8 在常见 92 天窗口下全部不可行。可调低 --comp-wage --comp-hours 看"理论边界"(如 --comp-wage 4000 --comp-hours 150),或调 --fixed-fee 0 看纯工资场景。详见 Q1。 |
| 调休补班日非国务院公布的年份 | MAKEUP_BY_YEAR 字典无该年则按"无补班"跑;结果仅供参考。请自查当年国务院放假安排后补行(如 {2027: [(9,27),(10,10)]})。 |
| 单文件输出 ≥ 1GB 的超长窗口 | 当前 WINDOW_DAYS 默认 ≤ 200 天;CSV 大小约 N × 7 × N_BLOCKS。如需更长,请按季度分四段(Q1/Q2/Q3/Q4)分别跑再合并。详见 Q19。 |
⚖️ 我能做但有代价(v1.4.0 新增) 【必看】
下表是"能做但有局限"的场景,事前知道能避免跑完才发现对不上:
| 场景 | 能做部分 | 代价 / 注意点 |
|---|---|---|
| 单月分析(30/31 天) | --window-days 30 即可 |
块边界可能落在月中,前 N%7 天是"非完整块",按"块内工作日轮转"处理,与完整 7 天块不完全等价;可能请用 28/35/42 天(7 的倍数) |
| 跨年窗口(同时含两年) | 引擎不会报错,但节假日/调休只用 START_DATE 那年的查表 | 拆成两窗口跑才是正确做法(见下"案例 1") |
| 任意周(7 天)而非整数月 | --window-days 7 即可 |
N_BLOCKS=1,序列数极少(3 条),不具统计学意义 |
| 单档 H(如只 H=10) | --hs 10 即可 |
报告里只显示一档;如需跨档对比请至少两档 |
--comp-wage 0 |
引擎会跑,但合规过滤后可行集变全集 | 不是真用价值,是看"理论无下限"边界 |
| 只跑 5 天(极小窗口) | --window-days 5 |
N_BLOCKS=0,序列数=0,无意义。引擎会跑但 CSV 空 |
| 超大窗口(如 180 天) | 引擎会跑 | N(25 块) 约 9.8×10¹³,不可枚举!请按季度分段。详见 Q19 |
| H 档非整数(如 H=9.5) | 当前 H 必须为整数 | 把 H=9.5 拆成 H=9 和 H=10 看线性插值;或取整到 10 |
📋 边界场景案例(v1.4.0 新增) 【选看】
案例 1:跨年窗口(如 2026-12-15 至 2027-01-15,32 天)
问题:2026 年和 2027 年节假日规则不同(2027 没调休),START_DATE=2026-12-15 的话引擎只用 2026 的查表。
正确做法:拆成两窗口分别跑。
python run.py -s 2026-12-15 -w 17 # 仅 2026 年
python run.py -s 2027-01-01 -w 15 # 仅 2027 年
最后用 pandas 合并 feasible_H10.csv(带 --hs 10,12 提速)。
案例 2:单月 10 月分析
场景:只想看 2026 年 10 月(31 天)。
问题:10/1-10/7 是 7 天整块,但 10/8-10/31 跨 4 个完整块 + 1 个不完整块(10/29-10/31,3 天尾部)。
正确做法:
python run.py -s 2026-10-01 -w 31 --hs 10,12
报告里"覆盖月份"会显示 2026年10月(1 个月),"三倍节假日(7天)"列出 10/1-10/7。
注意点:10/29-10/31 是 partial block(3 天),按"块内工作日轮转"处理,前 3 天视作"工作日"——与 10/29-31 是否真的是工作日可能不完全一致。介意的话请用 28 天(10/1-10/28)窗口。
案例 3:超 2040 年分析(如 2050 年)
问题:MID_AUTUMN 查表只到 2040。2050 年会 KeyError 或 silent miss。
正确做法:
1. 在 venv 里 pip install lunardate
2. 跑:
from lunardate import LunarDate
for y in range(2041, 2055):
sd = LunarDate(y, 8, 15).toSolarDate()
print(f"{y}:({sd.month},{sd.day}),", end=" ")
- 把输出追加到
schedule_engine.py的MID_AUTUMN字典 - 同时按 2050 年国务院放假安排补
MAKEUP_BY_YEAR[2050] = [(m,d),...] - 跑
python run.py -s 2050-08-01 -w 92
> 💡 提示:用之前先问自己"我的场景是否符合 7天块调度 + 单人 + 连续窗口"?三个都满足才继续。
📐 执行流程(一图看懂) 【必看】
┌─────────────────────────────────────────────┐
│ 你(用户) │
│ · 默认窗口:什么都不传 │
│ · 自定义:python run.py -s 2027-08-01 -w 92 │
└─────────────────────────────────────────────┘
│
▼
┌───────────────────────────────┐
│ run.py(一键入口,v1.3.0) │
│ =============== │
│ 把全部 CLI 参数透传给下面两步 │
└───────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────┐
│ ① schedule_engine.py │
│ ────────────────────── │
│ · preflight(numpy / 目录 / 磁盘 / 配置合法性) │
│ · [1/4] 枚举 N 个合法 7天块序列 → N=508,992 (13块) │
│ · [2/4] 展开 (N, WINDOW_DAYS) 出勤/双倍/档位矩阵 │
│ · [3/4] 按 H∈{8,10,12} 计算工资/时均,过合规下限 │
│ · [4/4] 选方案:①②③ 折中 + ④⑤⑥ 锁死工时 + 上下界 │
│ · 写出:reports/_summary.json │
│ reports/feasible_H{8,10,12}.csv │
└──────────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────┐
│ ② generate_report.py │
│ ────────────────────── │
│ · preflight(_summary.json 存在 / CSV 非空 / 输出可写) │
│ · [1/4] 读 _summary.json │
│ · [2/4] 构建表头/章节,月份分组 │
│ · [3/4] 渲染劳资权衡平面 SVG(每档 ≤1400 点抽样) │
│ · [4/4] 写出:reports/班表精算报告.html │
└──────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────┐
│ 浏览器打开报告(HTML) │
│ 双击 reports/班表精算报告.html │
└───────────────────────────────┘
在 AI 对话里如何触发本 Skill 【必看】
把下面任意一条自然语言描述发给 AI(含"请用班表精算师技能"或"跑一遍班表精算引擎"),AI 就会自动加载并按需执行。
示例 1 — 默认 2026/8-10 月分析(最常见)
> 请用班表精算师技能分析 2026 年 8 月 1 日到 10 月 31 日的排班劳资权衡,给出 HTML 报告与 CSV 数据。
示例 2 — 切到其他年份
> 用班表精算引擎跑 2027 年 8-10 月,注意 2027 年还没有任何调休,按规则跑就行。
示例 3 — 复现 2025 合并年示例
> 改 START_DATE=date(2025,8,1),跑 2025 年 8-10 月班表精算,对比和 2026 有什么差异。
示例 4 — 调小窗口做单月分析
> 用班表精算技能分析 2026 年 10 月 1 日到 10 月 31 日的 31 天窗口。
示例 5 — 让 AI 解释权衡平面怎么读
> 用班表精算技能跑 2026/8-10 月,然后给我讲讲权衡平面上 ①②③ 三个点的位置代表什么。
示例 6 — 只分析单月(如 10 月)
> 用班表精算引擎跑 2026 年 10 月 1 日到 10 月 31 日的 31 天窗口,注意块边界在月中。
示例 7 — 批量跑多年对比
> 用班表精算引擎批量跑 2025、2026、2027 三个年份的 8-10 月窗口,生成三份独立报告与汇总对比。
示例 8 — 调低合规阈值看 H=8
> 用班表精算引擎跑 2026/8-10 月,但把合规下限改成 4000 元 / 150 H,看 H=8 档是否能出现可行方案。
示例 9 — 改固定费重算
> 用班表精算引擎跑 2026/8-10 月,把月固定费从 1400 改成 2000,看 ①②③ 折中点怎么移动。
示例 10 — 跑前先做诊断
> 我准备部署班表精算引擎到一台新机器,请先跑 --doctor 模式看看依赖和磁盘是否都 OK,再正式跑默认 2026。
示例 11 — CI 回归测试
> 把班表精算引擎接入 CI:每次发布前跑 python schedule_engine.py --regression,确保 _summary.json 与 baseline 一致。
示例 12 — 让 AI 用环境变量传参
> 我要用流水线触发班表精算引擎,请把当前默认 2026 配置翻译成环境变量形式(START_DATE/WINDOW_DAYS/H_TIERS 等)。
> 触发关键词:班表精算、班表精算师、排班劳资权衡、7天块调度、schedule-tradeoff-engine、run.py、班表引擎、班表报告、班表分析、排班精算。
🚀 场景速查表(v1.4.0 新增) 【选看】
> 不确定怎么用?先看这张表选最贴近你场景的一行,复制命令即可。
| # | 场景 | 命令 / 说明 |
|---|---|---|
| 1 | 默认 2026/8-10 月 | python run.py |
| 2 | 切到其他年份(如 2027) | python run.py -s 2027-08-01 |
| 3 | 复现 2025 中秋国庆合并年 | python run.py -s 2025-08-01 |
| 4 | 只分析单月(如只 10 月) | python run.py -s 2026-10-01 -w 31(注意:块边界在月中) |
| 5 | 批量跑多年(2025-2030) | for y in 2025 2026 2027 2028 2029 2030; do python run.py -s $y-08-01 -w 92 && cp reports/_summary.json reports/_summary_$y.json; done |
| 6 | 对比两年(2026 vs 2027) | 跑两次后用 feasible_H10.csv / _summary_$y.json 对比(v1.5.0 做自动合并) |
| 7 | 只跑两档省时间 | python run.py --hs 10,12 |
| 8 | 调合规阈值(H=8 也想看) | python run.py --comp-wage 4000 --comp-hours 150 |
| 9 | 改固定费 | python run.py --fixed-fee 1500 |
| 10 | 只用引擎不要 HTML | python schedule_engine.py -s 2026-08-01(仅写 CSV + JSON) |
| 11 | 跑前先诊断(CI/容器) | python schedule_engine.py --doctor(只跑 preflight 不枚举) |
| 12 | CI 回归测试 | python schedule_engine.py --regression(首次生成 baseline,再次比对) |
| 13 | 环境变量形式(流水线) | START_DATE=2027-08-01 WINDOW_DAYS=92 H_TIERS=10,12 python schedule_engine.py |
| 14 | 跨年窗口(已含 2026+2027) | 拆成两窗口分别跑再合并:见下「边界场景案例 1」 |
| 15 | 超 2040 年分析 | 需在源码 MID_AUTUMN 加一行;见下「边界场景案例 3」 |
方法论(核心规则) 【原理】
- 块定义:7 天为一个调度块,三种模式
-A= 5 工 / 2 休
-B= 6 工 / 1 休
-C= 7 工 / 0 休
- 硬约束:任意两块 C 不能相邻(防止连续 14 天无休)。 - 双倍日:块内出勤≥6 天的块,其末位工作日触发双倍(即 B 的第 6 天、C 的第 7 天)。
- 三倍日:法定节假日且当天原排班为出勤 → 三倍(强制高于双倍;落在休息日不补薪)。
- 调休上班日:按正常档计,不叠加双倍/三倍。
- 日薪费率(建模参数,非法定标准):
- 正常档wN = 21×min(H,8) + 31.5×max(0,H−8)
- 双倍档wD = 42×H
- 三倍档wT = 63×H - 固定费:
1400 元/月,全程 n 个月合计1400×n。恒等式
公司时均 = 员工均薪 + (1400×n) ÷ 总工时 —— 故任一方案公司时均恒大于员工均薪,二者不可混比大小。 - 合规下限:每月 月工时 ≥ 208H 且 月工资 ≥ 6500 元;未通过者剔除出可行集。
文件结构 【选看】
schedule-tradeoff-engine/
├── SKILL.md # 本文档(技能描述 + 使用说明 + FAQ)
├── schedule_engine.py # ① 引擎(枚举 + 指标 + 选方案);输出 _summary.json + feasible_H*.csv
├── generate_report.py # ② 报告生成器;读 _summary.json → 写 班表精算报告.html
├── run.py # ★ v1.3.0 一键入口(透传参数调上面两步,免搞错顺序)
└── reports/ # 输出目录(自动创建)
├── _summary.json # 引擎产物的结构化摘要(含 meta + summary)
├── feasible_H{8,10,12}.csv # 各档可行集(按 (emp_avg, co_avg, ...) 列出每个方案)
└── 班表精算报告.html # ★ 最终交付物(含 2 张劳资权衡平面 SVG,直接浏览器打开)
使用步骤(推荐:run.py 一键) 【必看】
# === 一键(v1.3.0 推荐)===
python run.py # 用默认值(2026/92天/8,10,12档)
python run.py -s 2027-08-01 -w 92 # 切到 2027/8-10 月窗口
python run.py --hs 10,12 # 只算 H=10,H=12(速度更快)
python run.py -s 2025-08-01 -w 92 # 复现 2025 中秋国庆合并年
# === 等价写法(手动两步)===
python schedule_engine.py [...] # 先跑引擎
python generate_report.py # 再跑报告生成器
# === 只用 schedule_engine.py 不生成报告(数据党)===
python schedule_engine.py -s 2026-08-01 -w 92
# → 直接读 reports/_summary.json / feasible_H*.csv
> 依赖:Python 3.10+ 与 numpy(v1.3.0 引擎 import 即检测,缺则给完整安装命令)。
> 注:节假日自动定位用内置"中秋公历日期查表(2020-2040,已用 lunardate 库核验)",
> 运行时无需联网、无需 lunardate 库;该库仅用于发布前的查表校验。
> 年份特异性数据(调休补班日 MAKEUP_BY_YEAR、合并年 HOLIDAY_OVERRIDE)仍按年在本文件内维护——因为它们取决于当年国务院安排,无法从规则推算;其余参数均已可用 CLI/环境变量覆盖。
📊 输出长什么样(典型示例 + 报告章节导航) 【选看】
引擎终端输出(默认 2026/8-10 月)
╭──────────────────────────────────────────────────────────╮
│ 班表精算 · 一键流水线 v1.3.0 │
│ 等价于:python schedule_engine.py ... && python generate_report.py │
╰──────────────────────────────────────────────────────────╯
══════════════════════════════════════════════════════════════
步骤:① 枚举 + 展开 + 选方案
执行:python schedule_engine.py
══════════════════════════════════════════════════════════════
班表精算引擎 v1.4.0 —— 7天块调度 + 劳资权衡
──────────────────────────────────────────────────
遇到问题?可直接重新执行此脚本,所有错误都会给
【原因 / 建议 / 示例】三段式说明(不会丢给你 traceback)。
──────────────────────────────────────────────────
覆盖月份:2026年8月, 2026年9月, 2026年10月
三倍节假日(8天):2026-09-25, 2026-09-26, 2026-09-27, 2026-10-01, 2026-10-02,
2026-10-03, 2026-10-04, 2026-10-05, 2026-10-06, 2026-10-07
调休补班:2026-09-20, 2026-10-10
配置:H档=[8, 10, 12] 月固定费=1400 合规(工时≥208H, 工资≥6500元)
[1/4] 枚举 13 块合法序列中…
合法序列数 N = 508,992
[2/4] 展开 (N, 92) 出勤/双倍/档位矩阵…
[3/4] 计算 H=8/10/12 三档工资与时均…
[4/4] 选方案(①②③ 折中 + ④⑤⑥ 锁死工时 + 上下界)…
H=8 可行数: 0
H=10 可行数: 245,052
H=12 可行数: 508,992
✓ 已写入 reports\_summary.json
✓ 已写入 reports\feasible_H8.csv (0 行)
✓ 已写入 reports\feasible_H10.csv (245,052 行)
✓ 已写入 reports\feasible_H12.csv (508,992 行)
[完成] 主产物:reports\_summary.json
done
══════════════════════════════════════════════════════════════
步骤:② 渲染 HTML 报告 + 劳资权衡平面 SVG
执行:python generate_report.py
══════════════════════════════════════════════════════════════
[1/4] 读取 reports\_summary.json
[2/4] 构建表头/章节,3 个月份段:2026年8月, 2026年9月, 2026年10月
[3/4] 渲染 2 个可行档位的权衡平面 SVG(每档约数千点抽样)
[4/4] 拼装 HTML 并写入 reports\班表精算报告.html
✓ 报告已生成:reports\班表精算报告.html (约 90,000 字符)
══════════════════════════════════════════════════════════════
全部完成 ✓
打开报告: .../reports/班表精算报告.html
数据明细: .../reports
══════════════════════════════════════════════════════════════
HTML 报告章节导航表
打开 reports/班表精算报告.html 后,按顺序看到这 5 个卡片:
| 章节 | 卡片标题 | 内容 |
|---|---|---|
| 一 | 建模口径与关键假设 | 窗口范围 / 块定义 / 费率 / 固定费 / 节假日 / 合规下限 |
| 二 | 不可行档位结论 | H=8 等不可行档位的"为什么"+ "故以下仅对比 H=10,H=12" |
| 三 | H=10 档 · 方案对比 | ① ② ③ / 员工上限 / 公司下限 / ④ ⑤ ⑥ 共 6 行的对比表 + 1 张权衡平面 SVG |
| 三 | H=12 档 · 方案对比 | 同上 |
| 四 | 口径陷阱与解读提醒 | 5 条"别误读"提示(公司均薪不可比 / 锁死工时前提等) |
报告里的关键数值(2026 窗口下):
| 档 | 员工均薪 ① ② ③ | 公司时均 ① ② ③ | 员工上限 | 公司下限 |
|---|---|---|---|---|
| H=10 | 29.52 元/H | 34.46 元/H | 30.42 | 33.52 |
| H=12 | 30.59 元/H | 34.71 元/H | 31.46 | 33.79 |
H=8 全档不可行(合规过滤后 0 条);H=10 折中点距"理想点(员工高/公司低)"最近 3 个等价块序列共用同一组指标(详见报告"权衡平面")。
CSV 可行集(每档一份)
feasible_H10.csv:245,052 行 × 7 列(emp_avg / co_avg / total_work_days / double_days / triple_days / total_hours / total_wage)feasible_H12.csv:508,992 行 × 7 列feasible_H8.csv:0 行(合规过滤后为空)
适配其他年份 / 窗口 【选看】
最快方式(v1.2.0 参数模板化 + v1.3.0 run.py 一键 + v1.4.0 错误码 + --doctor/--regression):
python run.py --start-date 2027-08-01 --window-days 92
python run.py --start-date 2025-08-01 # 复现 2025 合并年
python run.py --hs 10,12 --fixed-fee 1500 # 只算两档、改固定费
若仍想改源码默认值,改 schedule_engine.py 顶部配置即可,无需手算任何 day index:
- START_DATE = date(年, 月, 日) —— 窗口起点(任意年)。
- WINDOW_DAYS = N —— 窗口总天数;引擎自动拆成 N//7 个整块 + N%7 天尾部块。
- H_TIERS = (8,10,12) —— 需计算的日工时档位;也可用 --hs 10,12 覆盖。
- FIXED_FEE / COMP_HOURS / COMP_WAGE —— 月固定费与合规阈值;也可用 --fixed-fee / --comp-hours / --comp-wage 覆盖。
- MAKEUP_BY_YEAR —— 形如 {2026: [(9,20),(10,10)]} 的按年调休补班日字典;未列出的年份默认无补班(请据当年国务院安排补充)。此字段只能改源码(取决于当年国务院安排,CLI 不覆盖)。
- MID_AUTUMN —— 中秋(农历八月十五)公历日期查表,已覆盖 2020-2040(lunardate 核验);超出范围请自行追加 (年,(月,日))。
- HOLIDAY_OVERRIDE —— 应对中秋国庆合并等特殊年(如 2025 合并为 10/1-10/8),显式列出该年全部三倍日;None 则用默认规则(国庆 10/1-7 + 中秋 festival 及其后 2 天)。2025 合并年示例已内置,改 START_DATE = date(2025, 8, 1)(或 run.py -s 2025-08-01)即可一键复现,无需再动本字典。
月份分组、三倍节假日、调休补班日全部由引擎按真实公历日期自动算出 day index 并填充矩阵。改完(或传完 CLI)重跑 run.py 即可。
选方案逻辑(报告里的标记) 【原理】
- ①②③ 折中最优:从可行集取离"理想点(员工均薪最高 ∧ 公司时均最低)"欧氏距离最近的 3 组(等价块序列去重)。若可行集在指标上收敛于唯一折中点,则①②③共用同一组指标。
- ④⑤⑥ 锁死工时:在无增工时前提下,锁死"可行出勤天数中位附近"的总工时,仅在该工时内对双倍日数量取舍——④双倍日最多(员工最高)、⑤双倍日最少(公司最低)、⑥取中点(可解释折中)。同锁死工时下
公司时均−员工均薪恒等于固定费总额 ÷ 总工时。 - 员工上限 / 公司下限:可行集在"员工均薪"与"公司时均"两个单目标上的边界参考点(权衡平面上界)。
常见问题(FAQ) 【必看】
> 索引:Q1-Q4 概念 / Q5-Q8 启动/失败 / Q9 数据性质 / Q10 参数模板化 / Q11-Q18 操作问题 / Q19 性能
Q1: 为什么 H=8 总是"无任一方案"(不可行)?
A: 正常档日薪仅 168 元(H=8),全月最高 168×26=4,368 元,远低于 6,500 元合规下限。要让 H=8 通过,必须窗口内含足够三倍日,但仍受"块内出勤≥6 才双倍"与"无相邻 C 块"双重约束,H=8 在常见 92 天窗口下均无可行方案。如确需分析 H=8,可用 CLI 调低合规下限(免改源码):python run.py --comp-wage 4000 --comp-hours 150;或改源码顶部 COMP_WAGE / COMP_HOURS 默认值。
Q2: 我想换到 2042 年分析,但 MID_AUTUMN 表里没有怎么办?
A: 本表已覆盖 2020-2040(lunardate 库核验)。超出 2040 请在 MID_AUTUMN 字典里追加一行 (年,(月,日))(按中秋农历八月十五公历日期,可用 lunardate 库 LunarDate(年,8,15).to_solar_date() 计算)。注意:换年的窗口除了中秋,还要补当年的调休补班日 MAKEUP_BY_YEAR(据国务院安排)。
Q3: 报告里 ①②③ 总是显示相同指标,是不是 bug?
A: 不是。表示该窗口下可行集在"员工均薪 / 公司时均"两个指标上收敛于唯一折中点——多组等价块序列(如仅 A 与 B 的不同排列)命中同一组 (emp, co) 数值。引擎在 pick_abc 内已做等价去重(seen.add(s)),但只要三个不同序列在指标上完全相同,呈现就一致。验证方法:打开 feasible_H10.csv 看分布点是否真的"挤"在几个像素里。
Q4: 恒等式 公司时均 = 员工均薪 + 固定费÷总工时 怎么用?
A: 直接验证:emp_avg + 1400×3 / total_hours == co_avg(全程 3 月)。这把"公司时均 = 员工均薪"之间的差锁定为常数 4200 / 工时,所以比较公司时均时只需看工时与固定费比,看不到 ①②③ 之间的细微差异是正常现象。结论:单看公司时均排序与单看员工均薪排序方向相反,要看完整权衡平面。
Q5: 启动报"【依赖缺失】未找到 numpy"
A: 在 venv 里 pip install numpy;或在沙箱/受限环境里用托管运行时:托管 Python 一般已自带 numpy。本引擎 v1.3.0 顶部预检会先验证 numpy 可导入,失败时给完整原因+安装命令。
Q6: 启动报"【目录不可写】"
A: 当前目录在只读位置(如 Program Files、网络只读盘)。把整个 skill 目录拷到可写位置(如 C:\Users\<你>\skills\schedule-tradeoff-engine)再跑;v1.3.0 起,引擎若写主目录失败会自动落回 cwd/_fallback_reports/,并打印告诉你备份路径在哪里。
Q7: 启动报"【磁盘空间不足】< 50MB"
A: 清掉一些大文件后重跑;或把 skill 目录挪到大点的盘。
Q8: 启动报"【缺少 _summary.json】"
A: 你跑了 generate_report.py 但没先跑 schedule_engine.py。先 python schedule_engine.py 看到 done,再 python generate_report.py。或者直接 python run.py 一键跑两步不遗漏。
Q9: 数据可信吗?能否拿去给公司真用?
A: 引擎数值与建模参数强相关(费率 21/31.5/42/63、固定费 1400、合规阈值 208H/6500元都是可配置参数,非法定标准)。本工具是量化建模与方案对比工具,不构成法律或薪酬建议。涉及劳动法、社保、加班费上限以当地法规与集体合同为准。
Q10: v1.2.0 / v1.3.0 的 CLI / 环境变量怎么用?不用改源码了吗?
A: 是的,常见参数已可免改源码。等价两种写法:
# CLI 参数(用 run.py 一键更省事)
python run.py --start-date 2027-08-01 --window-days 92 --hs 10,12 --fixed-fee 1500
# 环境变量(适合流水线 / 不改命令结构)
START_DATE=2027-08-01 WINDOW_DAYS=92 H_TIERS=10,12 FIXED_FEE=1500 python schedule_engine.py
可用参数:--start-date/-s、--window-days/-w、--hs、--fixed-fee、--comp-hours、--comp-wage(详情见"使用步骤")。唯二仍需改源码的是年份特异性数据 MAKEUP_BY_YEAR(调休补班日)与 HOLIDAY_OVERRIDE(合并年三倍日)——它们取决于当年国务院安排,无法从规则推算,CLI 不覆盖。
Q11: 报告 HTML 双击打开后看不到 SVG(权衡平面空白)?
A: 两种可能:① 用记事本等文本编辑器打开而不是浏览器(必须用 Chrome / Edge / Firefox 等浏览器)。② 浏览器禁用了内联 SVG——按 F12 看 Console,应无报错。报告是单文件,所有 SVG 内联在 HTML 里,不需要联网、不需要外部资源。
Q12: 我跑了 run.py,但 HTML 报告没出来,只看到 _summary.json?
A: 检查终端最后 10 行有没有"全部完成 ✓"——若有但 HTML 不在 reports/ 里,多半是 v1.3.0 兜底落到了 cwd/_fallback_reports/班表精算报告.html,按提示路径找即可。若没有"全部完成",看退出码 1 还是 2(1 = 预检类,错误已打印;2 = 未预期错误,附堆栈信息反馈给开发者)。
Q13: 同样参数这次跑出来的可行数与上次不同?
A: 引擎为纯确定性算法(numpy 向量化,无随机种子),数值应严格复现。若差异,检查:① 是否改了 WINDOW_DAYS / START_DATE / H_TIERS / FIXED_FEE / COMP_HOURS / COMP_WAGE 任一参数;② 是否升级了引擎版本;③ _summary.json 是否被覆盖——保留旧版与新版对照可定位。
Q14: 我用 IDEA / PyCharm 跑引擎报"Permission denied"或"沙箱禁写入"?
A: 把整个 skill 目录拷到 C:\Users\<你>\WorkBuddy\ 之类的本地用户目录下再跑;或运行容器/沙箱工具的白名单里加 skill 路径。v1.3.0 已加自动落回 cwd/_fallback_reports/ 的机制,写入会失败但会告诉你备份路径。
Q15: CSV 文件太大打不开(feasible_H12.csv 约 50MB)?
A: 这是设计内的——H=12 档下可行集覆盖率最高(508,992 条全可行)。处理建议:① 用 pandas 分块读 for chunk in pd.read_csv('feasible_H12.csv', chunksize=50000): ...;② 或先用 --hs 10,12 只跑两档,H=12 的 CSV 小一半;③ 或直接读 _summary.json 看聚合后的关键数值,不动原始可行集。
Q16: 输出能在 Excel 打开吗?中文乱码?
A: CSV 是 UTF-8 编码,默认用 Excel 打开会乱码(Excel 默认 GBK)。推荐两种方式:① 用 Excel "数据 → 自文本/CSV"导入并选 UTF-8;② 用 Notepad++ 转 GBK 后再用 Excel 打开;③ 改用 VSCode / WPS / Numbers 等默认支持 UTF-8 的工具打开。HTML 报告不受此影响,浏览器直接显示中文。
Q17: 能批量跑多个年份并合并报告吗?
A: 当前 v1.3.0 每个窗口生成一份 _summary.json + 一份 HTML。如需批量:
for y in 2025 2026 2027; do
python run.py -s $y-08-01 -w 92 --hs 10,12 \
&& cp reports/_summary.json reports/_summary_$y.json \
&& mv reports/班表精算报告.html reports/班表精算报告_$y.html
done
v1.4.0 roadmap 会做"多年对比"专项功能。
Q18: 想加 / 删字段或换中文列名,怎么改最少代码?
A: 列名硬编码在三处:① schedule_engine.py 里 w.writerow([...])(CSV 表头)+ plan_record() 内字段名;② generate_report.py 里 plan_row() 的列序;③ SKILL.md 的"📊 输出长什么样"。改一处会牵连另一处,v1.4.0 roadmap 会做"列名配置化"。
Q19: 性能如何?能不能跑 365 天?
A: 92 天窗口:枚举 N=508,992,约 5–15 秒(视机器);H=12 内存峰值约 200 MB。365 天窗口:N=13 块数递推 N(52) ≈ 2.5×10¹⁵——不可枚举,需先分段再合并。实用边界:WINDOW_DAYS ≤ 200;想跑全年请按季度分四段。
Q20: 报错末尾的 [错误码: E0XX] 是什么意思?
A: v1.4.0 引入的稳定错误码,便于定位和反馈。完整映射见下方「错误码索引附录」。
Q21: --doctor 模式是干嘛的?什么时候用?
A: 只跑 preflight + 打印环境配置概览(Python/numpy 版本、START_DATE/WINDOW_DAYS/H_TIERS/FIXED_FEE/COMP_、输出目录、磁盘剩余),不做枚举*。用法:python schedule_engine.py --doctor 或 python run.py --doctor(run.py 透传)。典型场景:① 部署到新机器/容器后先 sanity check;② 排查"为什么这次跑和上次不一样"——先看配置是否被环境变量覆盖。
Q22: --regression 模式是干嘛的?怎么用?
A: 自动跑默认 2026 + 与 reports/_checksum_baseline.txt 比对。首次跑会生成 baseline;之后跑比对,不一致则 sys.exit(3) 并打印差异头 16 位 hash。用法:python schedule_engine.py --regression。典型场景:CI 回归测试(每次发布前跑一遍,确保数值未漂移)。
错误码索引附录(v1.4.0 新增) 【必看】
| 码值 | 标题 | 触发场景 | 修复示例 |
|---|---|---|---|
| E001 | numpy 依赖缺失 | Python 解释器未装 numpy | pip install numpy 或建 venv 后 pip install numpy |
| E002 | --start-date 格式非法 | START_DATE 不是 YYYY-MM-DD | --start-date 2027-08-01 或 START_DATE=2027-08-01 |
| E003 | 输出目录不可写 | skill 目录在只读位置 | 拷到 C:/Users/<你>/skills/... 再跑 |
| E004 | 磁盘空间不足 | 输出盘剩余 < 50MB | 清大文件或换盘 |
| E005 | WINDOW_DAYS 配置错误 | WINDOW_DAYS < 1 或非整数 | --window-days 92 |
| E006 | START_DATE 类型错误 | START_DATE 不是 datetime.date(通常改源码时手写错) | 用 --start-date YYYY-MM-DD 或 START_DATE = date(年, 月, 日) |
| E007 | H_TIERS 为空 | --hs 后为空字符串 |
--hs 8,10,12 或 --hs 10,12 |
| E008 | H_TIERS 含非正值 | 日工时 ≤ 0 | --hs 8,10,12(正整数) |
| E009 | 文件写入失败 | 主目录与备份目录均不可写 | cd 到可写目录再跑 |
| E010 | WINDOW_DAYS 过大 | WINDOW_DAYS > 200 时仅警告(非阻断) | 按季度分段跑 |
| E011 | 报告生成器找不到 _summary.json | 先跑生成器再跑引擎(或反之) | 用 python run.py 一键,或先 python schedule_engine.py 再 python generate_report.py |
| E012 | 报告生成器找不到 feasible_H*.csv | 引擎侧所有档位均无可行方案(极端窗口) | 调宽窗口 / 调低合规下限 / --hs 10,12 排除 H=8 |
| E013 | 报告生成器 HTML 目录不可写 | 主目录与 cwd 备份目录均不可写 | cd 到可写目录(如 C:/Users/<你>/WorkBuddy/)再跑 |
> 💡 错误时引擎还会打印【调试小贴士】:当前 START_DATE / WINDOW_DAYS / H_TIERS / FIXED_FEE / COMP_HRS / COMP_WAGE + Python/numpy 版本。先看这两段再查本附录。
💡 延伸思考 / 启发性洞察(v1.5.0 新增) 【原理】
> 不止给数字,更给思路。下面 7 条是研究 / 调参 / 跨档分析时常用的启发,适合"看懂默认报告之后想深入"的读者。
1. 为什么默认 H 档选 {8, 10, 12} 三档?
- H=8(标准工时)覆盖绝大多数非加班场景;H=10(中等加班)覆盖制造业旺季;H=12(重加班)覆盖物流 / 建筑。
- 三档覆盖了"月工时 208 → 312 → 374"这条典型阶梯,每个 H 档都对应现实中能落地的工时密度。
- 若你的实际工时落在两档之间(如 H=9),可手动改
--hs 9,10或--hs 9,12,引擎会照样跑。
2. 合规下限"月≥208H 且 月≥6500元"是怎么定的?
- 月≥208H:源自 8H × 26 天(月均工作日),是法定月工时基线;低于则触发加班费上限讨论。
- 月≥6500元:是中国一二线城市最低工资的 1.5–2 倍覆盖线,给"全勤合理收入"一个下限。
- 两者是建模假设而非法律强制;调整
--comp-hours 176/--comp-wage 5000可模拟你公司的实际口径。
3. 跨档罚款倍数差怎么解读?
- 同一方案(如 ① 折中)在 H=10 和 H=12 的"公司时均"差距,主要来自固定费在更长工时下被稀释——H=12 时均降,但员工总工时也升。
- 如果两个 H 档的罚款倍数差 > 1.2,说明该方案在 H 档间可推广性差,建议锁定 H 档跑精算而不是跨档对齐。
- 如果差距 < 1.1,说明 H 档敏感性弱,可放心加大 H 档弹性。
4. 为什么折中方案(①②③)通常比锁死工时(④⑤⑥)更优?
- 折中方案在"员工均薪 - 公司时均"权衡平面上离原点(理论最优)距离最近;它不强求极值而是找平衡。
- 锁死工时方案适合工时已被外部因素限定的场景(如岗位编制),但代价是牺牲一个维度的优化。
- 决策建议:先看折中方案,再看锁死方案是否值得其代价。
5. 节假日调休怎么影响?
- 节假日三倍日:① 块末位双倍日落在节假日 → 自动升三倍(按劳动法节假加班);
② 调休上班日 正常计(与 8H 普通工作日同费率)。 - 这意味着块末位尽量不要出现在节假日——把双倍降级成三倍对员工是好事(更高工资),对公司时均不利。
- 想验证"块末位落在节假日的次数",可直接搜
_summary.json里每个方案的triple_days与double_days字段。
6. 想测出窗口最大可行 H 档,只跑一次不够
- 默认窗口已能区分 8/10/12 三档;但极端大窗口(如全年 365 天)需要
--hs 8,10,12,14跑一遍才知道 H=14 是否落进合规线。 - 这其实是默认场景中的"如果跑出来 H=14 没有可行方案"——此时可缩小窗口(季度分段)或降 COMP_HOURS,看是否能让 H 更大档位落进合规区间。
7. HTML 报告"📊 洞察摘要"是怎么生成的?
- 引擎在
meta.insights里写 3-5 条自动抽出的关键观察(如"最大可行 H 档=H12;H12 → H10 罚款倍数 1.18;折中①离原点 0.42")。 - 规则有 6 条(最大 H 档 / 跨档罚款倍数 / 折中 vs 边界距离 / 月工时富余度 / 节假日占比 / 块序列结构统计),源码见
schedule_engine.py末尾_gen_insights()。 - 想加自定义洞察?复制
_gen_insights()加一条规则即可,建议同时给meta.insights.append(...)写测试用例。
版本 Roadmap 【选看】
> 本 Skill 的演进路线;已完成项标注 ✅,进行中 🔧,规划中 📋。
- v1.0.0 ✅ 首发:13 块枚举引擎 + 2026 默认值 + HTML 报告。
- v1.1.0 ✅ 窗口可配置(START_DATE/WINDOW_DAYS),day index 自动算。
- v1.1.1 ✅ 内置 2025 中秋国庆合并年示例(HOLIDAY_OVERRIDE / MAKEUP_BY_YEAR)。
- v1.1.2 ✅ 测评优化:预检 + 友好错误 + 进度分步 + 典型输出示例 + FAQ。
- v1.2.0 ✅ 参数模板化:CLI/环境变量免改源码覆盖核心配置;H 档/固定费/合规阈值可配置;中秋查表延至 2040;报告动态适配任意 H 档。
- v1.3.0 ✅ **鲁棒性 + 可触达性再增强(v1.3.0 ✅):① 文件写入子 try/except 兜底自动落回 cwd;② 错误信息统一【原因/建议/示例】三段式 + 全中文;③
run.py一键入口;④ SKILL.md 加边界声明、流程图、章节导航、Q11-Q18 操作 FAQ。 - v1.4.0 ✅ 评测反馈第三轮再增强(针对 R 异常 / R 运行 / A 触发 / E 内容 4 个 4.5 分项):① 错误码索引 E001-E011 + 错误末尾打印码值 + SKILL.md 附录索引表;② 错误时打印【调试小贴士】(当前配置 + Python/numpy 版本 + 磁盘剩余);③ 新增
--doctor诊断模式(只跑 preflight 不枚举);④ 新增--regression模式(自动跑默认 2026 + 与 _checksum_baseline.txt 比对);⑤ 每次跑完生成reports/_checksum.txt(_summary.json 的 sha256);⑥ 进程锁reports/.engine.lock防并发;⑦ SKILL.md 加场景速查表(单月/对比两年/批量多份/--doctor/--regression 等 10 个场景);⑧ 触发 prompt 5→10 条 + 关键词 5→10 个;⑨ 加我能做但有代价清单 + 边界场景案例 3 个。 - v1.5.0 ✅ (当前) 评测反馈第四轮再增强(针对 C 文档质量 4.5 / C 渐进式披露 4.5 / E 创造力 4.6 三个分项):① SKILL.md 顶部加 🚀 TL;DR + 📖 阅读路径图(30秒/3分钟/完整/原理 四档)+ 🛤️ 新手入门 5 步走,让 500 行文档分层渐进披露,新手不再需要一次性读完;② 给每个章节打 【必看】/【选看】/【原理】/【进阶】 标签,扫一眼就知道哪些必须读;③ 加 💡 延伸思考 / 启发性洞察 章节,7 条研究 / 调参 / 跨档分析的常用启发(H档选择、口径陷阱、跨档倍数差、折中 vs 锁死对比、节假日调休、最大 H 档压测、
_gen_insights()源码定位);④ HTML 报告自动生成"📊 洞察摘要"区块,引擎在meta.insights写 3-5 条自动抽出的关键观察,打开报告先看洞察再看图表。
口径陷阱(务必在交付中保留) 【必看】
- "公司时均最低" ≠ "员工均薪最高":二者来自不同方案、分母也不同,必须逐方案列清再比。
- 锁死工时 = 无增工时前提:④⑤⑥ 不能在同一工时锁内既得员工最高又得公司最低;要进一步靠拢理想点须进入"增工时 ↔ 弹性排班"权衡。
- 节假日三倍高于双倍:块末位双倍日若落在节假日,自动升级为三倍。
- 参数为建模假设:费率与 1400 元/月固定费非法定标准;涉及劳动法、社保、加班费上限以当地法规与合同为准。
免责声明 【必看】
本引擎为量化建模与方案对比工具,所有费率、固定费、合规阈值均为可配置参数,不构成法律或薪酬建议。实际排班与薪酬须符合当地劳动法规与企业集体合同。