关于 microsim-generator
microsim-generator 是用于生成交互式 MicroSim 的技能,会根据可视化需求路由到专用生成指南,并整合 17 种生成技能。它还提供批处理脚本,用于提取规格、搭建文件、更新导航和验证质量。
主要功能
- 01按可视化需求选择生成指南
- 02整合 17 种 MicroSim 生成技能
- 03批量提取章节模拟规格
- 04生成模拟目录和页面文件
- 05验证质量并更新导航
适用场景
- 01为章节批量生成多个 MicroSim
- 02创建交互式教育可视化
- 03按学习目标设计模拟交互
- 04将模拟嵌入课程页面
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ dmccreary/ ibook-skills --skill microsim-generator安装后在 Claude Code 中输入/microsim-generator确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
assets/causal-loop/cld-inline.jsassets/causal-loop/cld-viewer/cld-viewer.jsmain.htmlassets/causal-loop/cld-viewer/examples/ai-flywheel-cld.jsonrunaway-hypothesis-cld.jsonwinner-takes-all-cld.jsonassets/concept-classifier/concept-classifier-template.jsdata-template.jsonindex-template.mdmain-template.htmlassets/docker-python-lab/docker-lab.cssdocker-lab.jsassets/infographic-overlay/grid-main-template.htmlmain-template.htmlassets/infographic-overlay/shared-libs/diagram.jsgrid-diagram.jsgrid-overlay.cssstyle.cssassets/templates/chartjs/data-template.jsonindex-template.mdmain-template.htmlmarket-share-example.htmlmetadata-template.jsonscript.jsstyle.cssassets/templates/comparison-table/index-template.mdmain-template.htmlmetadata-template.jsonstyle.cssassets/templates/map/choropleth-example.html详细介绍
MicroSim 生成器
版本: 1.0
概述
这个元技能会根据可视化需求,将 MicroSim 创建请求路由到相应的专用生成器。它将 17 个独立的 MicroSim 生成器技能整合到一个入口中,并按需加载特定的实现指南。
src/microsim-utils/ 中的 6 个 Python 批处理实用程序可自动完成 MicroSim 生成中的重复性工作(解析规范、搭建文件框架、插入 iframe、修正 iframe 高度、验证质量、更新导航),每次批处理可节省约 430K 个令牌。Agent 的创意工作集中在编写 .js 文件上。
默认顺序执行
在对某章的所有 #### 图表元素使用 microsim generator 技能时,除非用户明确使用“execute in parallel”这一短语,否则始终按顺序运行 microsim generator 任务。
何时使用此技能
用户提出以下请求时,请使用此技能:
- 交互式教育可视化
- 数据可视化(图表、曲线图、绘图)
- 时间线或按时间顺序排列的展示
- 地理/地图可视化
- 网络图或概念图
- 流程图或工作流图
- 数学函数图
- 集合图(维恩图)
- 优先级矩阵或气泡图
- 自定义模拟或动画
- 带评级的比较表
- 可展开单元格详情的矩阵比较
- 事实经过核实的信息图海报,其中每项统计数据都可追溯到引用来源
- 为某一章批量生成 MicroSim
步骤 0:环境设置
开始任何生成工作之前,先设置路径并确定范围。
0.1 设置路径
# Python utilities live in the ibook-skills repo
UTILS="$HOME/Documents/ws/ibook-skills/src/microsim-utils"
# Detect project root (directory containing mkdocs.yml)
PROJECT=$(python3 -c "
import os, sys
d = os.path.abspath('.')
while d != os.path.dirname(d):
if os.path.isfile(os.path.join(d, 'mkdocs.yml')): print(d); sys.exit()
d = os.path.dirname(d)
print('ERROR: mkdocs.yml not found', file=sys.stderr); sys.exit(1)
")
如果在 $UTILS 中找不到脚本,请检查项目自身的 src/microsim-utils/ 目录。
0.2 确定范围
| 用户请求 | 路由 |
|---|---|
| “为第 11 章生成 MicroSim” | 章节批处理 → 步骤 1 |
| “为内接角创建一个 MicroSim” | 单个模拟 → 步骤 1B |
| “构建一条 Unix 历史时间线” | 单个模拟 → 步骤 1B |
步骤 1:从章节中提取规范(批处理路由)
章节级生成的必做步骤。 不要手动解析章节 Markdown。
python3 $UTILS/extract-sim-specs.py \
--project-dir $PROJECT \
--chapter <chapter-dir-name> \
--output /tmp/ch-specs.json \
--status-file /tmp/sim-status.json \
--verbose
此操作会:
- 从章节的
index.md中解析所有#### Diagram:和#### Drawing:标题 - 提取
<details>块内容、iframe 路径、模拟 ID、Bloom 层级和库提示 - 生成一个 JSON 规范对象数组(每个模拟对应一个对象)
- 生成包含生命周期状态的
sim-status.json:specified → scaffolded → implemented → validated → deployed
查看输出:
cat /tmp/ch-specs.json | python3 -m json.tool | head -60
检查状态文件,了解哪些模拟需要处理:
python3 -c "
import json
with open('/tmp/sim-status.json') as f:
for e in json.load(f):
if e['status'] != 'deployed':
print(f\" {e['status']:12s} {e['sim_id']}\")
"
提取完成后,继续执行步骤 2。
步骤 1B:单个模拟快捷流程
对于单个 MicroSim 请求(而非整个章节的批处理):
- 手动编写一个包含 1 个条目的规范 JSON:
cat > /tmp/ch-specs.json << 'EOF'
[{
"sim_id": "inscribed-angle-theorem",
"title": "Central vs Inscribed Angles Interactive",
"summary": "Demonstrates the inscribed angle theorem",
"heading_type": "Diagram",
"chapter": "",
"element_type": "microsim",
"bloom_level": "Analyze",
"library": "p5.js",
"iframe_src": "",
"iframe_height": "",
"spec_text": "",
"status": ""
}]
EOF
- 仅为该模拟运行 scaffold:
python3 $UTILS/generate-sim-scaffold.py \
--spec-file /tmp/ch-specs.json \
--sim-id inscribed-angle-theorem \
--project-dir $PROJECT \
--verbose
- 跳至步骤 3(教学设计检查点),然后执行步骤 4(实现 .js)。
步骤 2:搭建模拟目录
批处理生成的必做步骤。 不要手动创建 main.html、index.md 或 metadata.json。
python3 $UTILS/generate-sim-scaffold.py \
--spec-file /tmp/ch-specs.json \
--project-dir $PROJECT \
--verbose
此操作会:
- 为每个规范创建
docs/sims/<sim-id>/目录 - 生成
main.html,其中包含正确的 CDN 链接、<main>标签和 schema 元标签 - 生成
index.md,其中包含 frontmatter、iframe 嵌入、全屏链接和课程计划框架 - 生成包含 Dublin Core 字段和教育元数据的
metadata.json - 跳过已存在的目录(除非使用
--force)
对部分构建的模拟使用 --force:
如果模拟目录已存在(包含 main.html 和 .js),但缺少 index.md 或 metadata.json,scaffold 脚本默认会跳过整个目录。使用 --force 可重新生成所有框架文件。这是安全的,因为创意内容保存在 .js 文件中,而 scaffold 不会覆盖该文件。
python3 $UTILS/generate-sim-scaffold.py \
--spec-file /tmp/ch-specs.json \
--project-dir $PROJECT \
--force \
--verbose
搭建完成后,Agent 接下来只需编写 .js 文件。
第 3 步:教学设计检查点(必须完成)
编写任何 .js 文件之前,必须完成此检查点。
3.1 确定学习目标详情
从规格说明中提取:
- 布鲁姆层级:记忆、理解、应用、分析、评价或创造
- 布鲁姆动词:动作动词(解释、演示、计算等)
- 学习目标:完整说明学习者将能够完成什么
3.2 根据布鲁姆层级匹配交互模式
| 布鲁姆层级 | 合适的模式 | 不合适的模式 |
|---|---|---|
| 记忆(L1) | 闪卡、配对、标注 | 复杂模拟 |
| 理解(L2) | 逐步讲解示例、具体数据可见性 | 连续动画、粒子效果 |
| 应用(L3) | 参数滑块、计算器、练习题 | 仅被动观看 |
| 分析(L4) | 网络探索器、比较工具、模式查找器 | 预先计算的结果 |
| 评价(L5) | 排序/排名活动、评分标准工具 | 无反馈机制 |
| 创造(L6) | 构建器、编辑器、画布工具 | 固定模板 |
3.3 回答以下问题
继续之前,请回答以下问题:
-
学习者必须看到哪些具体数据?
- 不是“动画粒子”,而是“分词后的数组 ['physics', 'ball']”
-
学习者是否需要在观察之前进行预测?
- 如果是 → 使用带有“下一步/上一步”按钮的逐步演示
- 如果是 → 不要使用连续动画
-
动画比静态箭头多了什么?
- 如果无法清楚回答 → 不要使用动画
-
连续动画是否适合此布鲁姆层级?
- 对于动词为“解释”的理解(L2)目标 → 几乎总是不适合
- 对于带有实时反馈的应用(L3)目标 → 通常适合
3.4 必要时修改规格说明
如果规格说明要求为理解层级的目标添加动画/效果:
- 将此标记为潜在的教学设计问题
- 建议改用逐步演示模式
- 询问用户:“规格说明要求添加动画,但对于‘解释’类目标,采用逐步演示并展示具体数据通常更有助于学习。是否改用逐步演示?”
3.5 记录你的决定
在回复中添加:
Instructional Design Check:
- Bloom Level: [level]
- Bloom Verb: [verb]
- Recommended Pattern: [pattern]
- Specification Alignment: [aligned/modified]
- Rationale: [why this pattern supports the learning objective]
第 4 步:实现 .js 文件
Agent 的创意工作从这里开始。对于每个需要实现的模拟:
4.1 分析请求并匹配生成器
扫描规格说明中的触发关键词,并匹配相应的生成器指南。
快速参考路由表
| 触发关键词 | 指南文件 | 库 |
|---|---|---|
| 时间线、日期、按时间顺序、事件、历史、日程安排、里程碑 | references/timeline-guide.md | vis-timeline |
| 地图、地理、坐标、纬度、经度、地点、标记 | references/map-guide.md | Leaflet.js |
| 函数、f(x)、方程、绘图、微积分、正弦、余弦、多项式 | references/plotly-guide.md | Plotly.js |
| 网络、节点、边、图、依赖关系、概念图、知识图谱 | references/vis-network-guide.md | vis-network |
| 流程图、工作流、流程、状态机、UML、时序图 | references/mermaid-guide.md | Mermaid.js |
| 维恩图、集合、重叠、交集、并集、类别 | references/venn-guide.md | Custom |
| 图表、柱状图、折线图、饼图、圆环图、雷达图、统计数据、数据 | references/chartjs-guide.md | Chart.js |
| 气泡图、优先级、矩阵、象限、影响与投入、风险与价值 | references/bubble-guide.md | Chart.js |
| 因果、反馈、循环、系统思维、增强、平衡、CLD、系统原型 | references/causal-loop-guide.md | vis-network |
| 比较、表格、评分、星级、并排、功能 | references/comparison-table-guide.md | Custom |
| 矩阵、框架比较、可点击单元格、详情面板、可展开 | references/html-table.md | Custom |
| 动画、庆祝、粒子、彩纸、效果 | references/celebration-guide.md | p5.js |
| 分类、分类器、归类、场景排序、识别类型、识别模式 | references/concept-classifier-guide.md | p5.js |
| 图示叠加层、标注标签、解剖图、带标签的插图、信息图叠加层、探索/测验模式 | references/infographic-overlay-guide.md | Custom (diagram.js) — 交互式模拟;标签位于 data.json 中,图像不含文字 |
| Python 实验室、代码运行器、可运行代码块、交互式 Python 练习、Docker | references/docker-python-lab-guide.md | Custom (docker-lab.js) |
| 已核实的信息图、统计海报、事实核查海报、带引用的数据、来源明确的主张、基于证据的比较 | references/verified-infographic-guide.md | Custom (text-verify → image) — 静态 PNG;数字直接烘焙进像素,绝不能单独作为最终交付物 |
| 自定义、模拟、物理、交互、弹跳、运动、p5.js | references/p5-guide.md | p5.js |
区分两种 infographic 路由
两种路由的名称中都有 “infographic”,而且经常被混淆。请通过询问 文字位于何处来选择:
infographic-overlay-guide.md | verified-infographic-guide.md | |
|---|---|---|
| 产出 | docs/sims/{sim-id}/ 中的 MicroSim | docs/posters/<slug>/ 中的静态 PNG + 审计记录 |
| 解决的问题 | 让图像可探索、可测量 | 避免烘焙进图像的数字被捏造 |
| 图像中的文字 | 没有——连标题也没有 | 文字和数字就是内容 |
| 标签所在位置 | data.json,由 diagram.js 在运行时渲染 | 位于像素之中,在渲染前锁定 |
| 网络搜索 / 引用 | 不使用 | 必须(每条主张至少搜索 2 次,每个元素都要有 source_id) |
| 是否发出交互事件 | 是(悬停、测验尝试) | 否——平面图像不会发出任何内容 |
经验法则:**可能出错的数字主张 → 已核实指南;需要命名的结构 → 叠加层指南。**两者并非替代关系——请参阅以下两项策略,它们将二者串联成工作流,而不是分支。
政策:默认提供交互体验,而非静态图像
除非用户明确要求,否则绝不要将静态图像作为交付物。
扁平 PNG 属于 1 级产物:它不会发出任何交互事件,因此无法告诉我们读者是否理解了内容。本库面向 2 级及以上(参见根目录中的 CLAUDE.md),这意味着对于“制作一张信息图”的请求,默认应提供交互式方案。如果两种方案都可满足请求,请选择叠加层指南,而非海报方案。
政策:每张经过验证的海报都要添加叠加层
**生成包含可验证事实的静态海报时——因为用户要求制作海报——之后必须始终为其添加交互式叠加层。**这不是可选项,也不是可以作为后续建议提出的内容,而是海报方案的第二部分。
原因在于测量。海报的价值在于其经过验证的主张,但单独的 PNG 无法告诉我们是否有人与这些主张进行了互动。使用 grid-diagram.js 叠加层将其包裹后,海报的每个区域都会变成经过埋点的区域:悬停、打开区域和测验尝试都会成为交互事件,让我们能够汇总预测读者是否掌握了信息图所教授的概念。根据根目录 CLAUDE.md 中的“2.99”目标,汇总所有读者的这些事件以估算概念理解程度——绝不要保留与可识别读者相关联的单个学生表现历史。
具体操作:完成第 8 阶段后,按照 references/infographic-overlay-guide.md 中的网格叠加层工作流,将 data.json.image 指向渲染后的 poster.png,并将 showLabels: false 保持不变(海报上已经印有列标题)。将每项主张的 source_id 传递到区域的 facts[] 中,以便显示引用来源。
决策树
Numeric claims that must be verified against sources?
→ YES: run Phases 1–4 of verified-infographic-guide.md to lock a cited claim set, then:
· user explicitly asked for a static poster/image/PNG?
→ render it (Phases 5–8), THEN always add a grid overlay on top (see Exit Route)
· otherwise → carry the verified claims into the matched sim guide below.
Never ship a static image the user did not ask for.
Has dates/timeline/chronological events?
→ YES: timeline-guide.md
Has geographic coordinates/locations?
→ YES: map-guide.md
Mathematical function f(x) or equation?
→ YES: plotly-guide.md
Nodes and edges/network relationships?
→ YES: vis-network-guide.md (or causal-loop-guide.md if systems thinking)
Flowchart/workflow/process diagram?
→ YES: mermaid-guide.md
Sets with overlaps (2-4 categories)?
→ YES: venn-guide.md
Priority matrix/2x2 quadrant/multi-dimensional?
→ YES: bubble-guide.md
Standard chart (bar/line/pie/radar)?
→ YES: chartjs-guide.md
Comparison table with ratings/stars?
→ YES: comparison-table-guide.md
Matrix comparison with clickable cells/detail panels?
→ YES: html-table.md
Celebration/particles/visual feedback?
→ YES: celebration-guide.md
Students classify scenarios into categories (sorting quiz)?
→ YES: concept-classifier-guide.md
Labeled illustration with interactive callout markers or hover zones?
→ YES: infographic-overlay-guide.md
Runnable Python code block executed in Docker?
→ YES: docker-python-lab-guide.md
Custom simulation/animation/physics?
→ YES: p5-guide.md
退出路线:事实核验海报(不是 MicroSim)
先判断是否符合此路线。 只有当用户明确要求静态海报、图片或 PNG 时,才采用此路线。如果用户要求“信息图”但没有指定静态格式,则不要制作海报——运行阶段 1–4,整理经核验的声明集,并将其交给交互式指南(见上文“策略:默认采用交互方式”)。
references/verified-infographic-guide.md 是此技能中唯一一种本身不会生成模拟目录的路线。它会在 docs/posters/<slug>/ 中生成静态海报 PNG,同时附上核验报告和来源附属文件——之后总是会为其添加叠加层(见下文)。当请求符合此路线时:
- 完全跳过本文档的步骤 0–9。 不创建脚手架,不创建
.js,不设置CANVAS_HEIGHT,不插入 iframe,不运行质量验证器,也不添加docs/sims/条目。 - 阅读指南并改为遵循其中的8 阶段工作流。阶段 1–6 是 Agent 的纯文本工作;阶段 7 是唯一一次图像模型调用;阶段 8 审核渲染结果。
- 这条路线之所以值得采用,关键在于这条硬性规则:未经核验来源的声明不得进入图像。 未核验的声明会阻断流程、降级为定性表述,或被删除——绝不会凭猜测渲染出来。
强制阶段 9:为海报添加交互式叠加层。 渲染出的海报绝不是最终交付物。阶段 8 通过后,立即按照 references/infographic-overlay-guide.md 中的网格叠加工作流,在海报上构建网格叠加 MicroSim:
- 将
data.json.image指向渲染出的poster.png - 保留
showLabels: false——海报已经印有列标题 - 为海报的每个区域定义一个区域,并将每条声明的
source_id传入该区域的facts[] - 添加测验问题,让叠加层衡量理解情况,而不只是接触情况
此要求的原因:海报中的数字已经过核验,但静态 PNG 不会发出交互事件,因此我们无法得知读者是否真正关注了这些声明。叠加层会将每个区域变为一个可埋点的区域,其悬停、打开和答题记录可让我们根据“2.99”目标(见根目录中的 CLAUDE.md),汇总所有读者的数据,预测信息图中的概念是否已被掌握。绝不保留与可识别读者关联的个人学生历史记录。
将核验阶段用于真正的 MicroSim。 阶段 1–4(声明计划 → 来源发现 → 逐条声明核验 → 核验报告)与输出格式无关。当某个模拟必须包含有来源依据的事实——例如真实产品的比较表、已发布测量数据的图表、标注日期的事件时间线——先运行阶段 1–4,再将锁定的声明集交给匹配的模拟指南,并将每个 source_id 传入模拟的数据文件,使学生能够看到引文。跳过阶段 5–8;这些是海报渲染步骤。
4.2 加载匹配的指南
从 references/ 目录中阅读相应的指南文件,并遵循其中编写 .js 文件的工作流。
4.3 仅编写 .js 文件
脚手架(步骤 2)已经创建了 main.html、index.md 和 metadata.json。你只需编写 docs/sims/<sim-id>/<sim-id>.js。
每份指南都包含:
- 特定于库的要求
- 代码模板和模式
- 针对此类可视化的最佳实践
4.4 必须:在 .js 文件中添加 CANVAS_HEIGHT 注释
每个 .js 文件都必须在文件顶部附近(前 10 行内)单独占一行添加 // CANVAS_HEIGHT: 注释。 这是所有库类型中 iframe 高度的主要可信来源。sync-iframe-heights.py 工具和手动调整高度都依赖此注释。
**没有
.js文件的模拟:**如果某个模拟完全由main.html渲染,且不包含<id>.js(有些项目会通过这种方式编写 Mermaid、vis-network 或自定义 HTML 模拟),就没有.js文件来存放注释。请改为在模拟的metadata.json中以"canvasHeight": <integer>的形式存储高度,这是下游工具在.js注释之后读取的统一结构化备用来源。有关完整的解析顺序,请参阅 microsim-utils 技能中的references/canvas-height-strategy.md。本步骤的其他所有内容(如何计算数值、+2iframe 规则)都相同。
格式:// CANVAS_HEIGHT: <integer>
该值是 iframe 显示完整 MicroSim 而不发生裁切所需的总像素高度,包括画布、控件、图例、信息面板、标题和所有内边距。
如何按库类型计算 CANVAS_HEIGHT
| 库 | 公式 | 示例 |
|---|---|---|
| p5.js | drawHeight + controlHeight + graphHeight(canvasHeight 变量) | // CANVAS_HEIGHT: 695 |
| vis-network | 容器高度 + 标题(约 35px)+ 信息面板(约 60px)+ 图例(约 30px)+ 控件(约 40px) | // CANVAS_HEIGHT: 685 |
| Chart.js | 图表容器高度 + 标题(约 35px)+ 控件(约 40px)+ 图例(约 30px) | // CANVAS_HEIGHT: 505 |
| Plotly.js | 绘图 div 高度 + 标题(约 35px)+ 控件(约 40px) | // CANVAS_HEIGHT: 475 |
| vis-timeline | 时间线容器高度 + 标题(约 35px)+ 控件(约 40px) | // CANVAS_HEIGHT: 475 |
| Leaflet.js | 地图容器高度 + 标题(约 35px)+ 控件(约 40px)+ 图例(约 40px) | // CANVAS_HEIGHT: 515 |
| Mermaid.js | 图表容器高度 + 标题(约 35px)+ 控件(约 40px) | // CANVAS_HEIGHT: 475 |
| 自定义 HTML(比较表、html-table、venn) | 所有 DOM 元素渲染后的总高度 | // CANVAS_HEIGHT: 600 |
| 交互式信息图叠加层 | 图片容器高度 + 工具栏(约 40px)+ 信息面板(约 60px) | // CANVAS_HEIGHT: 620 |
各库类型的示例
p5.js:
// Predator-Prey Population Dynamics Simulator
// CANVAS_HEIGHT: 695
let drawHeight = 400;
let graphHeight = 180;
let controlHeight = 115;
let canvasHeight = drawHeight + graphHeight + controlHeight;
vis-network:
// Climate Feedback Loops - vis-network
// CANVAS_HEIGHT: 685
document.addEventListener('DOMContentLoaded', function() {
Chart.js:
// Air Quality Trends Dashboard - Chart.js
// CANVAS_HEIGHT: 505
document.addEventListener('DOMContentLoaded', function () {
Leaflet.js:
// Watershed Map - Leaflet
// CANVAS_HEIGHT: 515
document.addEventListener('DOMContentLoaded', function() {
交互式信息图叠加层:
// Ecosystem Components Overlay
// CANVAS_HEIGHT: 620
document.addEventListener('DOMContentLoaded', function() {
规则
- 注释必须出现在 .js 文件的前 10 行内,以便解析工具快速找到。
- 该值必须是整数(不得带
px后缀,也不得使用表达式)。 - iframe 高度 = CANVAS_HEIGHT + 2(额外的 2px 用于计算 iframe 边框)。
sync-iframe-heights.py工具会自动添加这部分高度。 - 对于 p5.js 模拟,CANVAS_HEIGHT 的值必须等于
drawHeight + controlHeight(如果存在graphHeight,还需加上它)。保留现有的命名变量——该注释是为工具提供的冗余但权威的声明。 - 更新现有模拟时,如果更改了任何与高度相关的值,务必同步更新 CANVAS_HEIGHT 注释。
- 如果不确定高度,请在浏览器中渲染模拟,测量内容总高度,并使用该值。宁可稍微偏高一些(多余的空白也好过控件被裁切)。
4.5 处理含糊的请求
如果该请求可能匹配多个生成器:
- 阅读
references/routing-criteria.md,了解详细的评分方法 - 使用 0-100 分制为得分最高的 3 个候选项评分
- 向用户提供选项并说明理由:
Based on your request, I recommend: 1. [Generator A] (Score: 85) - Best for [reason] 2. [Generator B] (Score: 70) - Alternative if you need [feature] 3. [Generator C] (Score: 55) - Possible if [condition] Which would you prefer? - 根据用户的选择继续操作
常见歧义
| 歧义术语 | 需要澄清的内容 |
|---|---|
| “graph” | 图表(ChartJS)还是网络图(vis-network)? |
| “diagram” | 结构图(Mermaid)、网络图(vis-network)还是自定义图(p5)? |
| “map” | 地理地图(Leaflet)还是概念图(vis-network)? |
| “table” | 星级评分(comparison-table)还是带详情面板的可点击单元格(html-table)? |
| “visualization” | 数据类型是什么?需要什么交互? |
第 5 步:修复章节中的 Iframe
批量生成时必须执行。 不要在章节 Markdown 中手动插入或编辑 Iframe。
python3 $UTILS/add-iframes-to-chapter.py \
--chapter <chapter-dir-name> \
--project-dir $PROJECT \
--fix-heights \
--fix-paths \
--verbose
此操作会:
- 查找缺少 Iframe 嵌入的
#### Diagram:/#### Drawing:标题 - 在
<details>块之前插入带有正确相对路径的<iframe>标签 --fix-heights:解析.js文件以检测createCanvas()的高度,并将 Iframe 高度设为画布高度 + 2px--fix-paths:将绝对路径(/sims/...)转换为相对路径(../../sims/...)- 修复高度拼写错误(
500xp→500px)
一次处理所有章节:
python3 $UTILS/add-iframes-to-chapter.py \
--all \
--project-dir $PROJECT \
--fix-heights \
--fix-paths \
--verbose
先试运行以预览更改:
python3 $UTILS/add-iframes-to-chapter.py \
--chapter <chapter-dir-name> \
--project-dir $PROJECT \
--fix-heights --fix-paths \
--dry-run --verbose
第 6 步:验证质量
实现 .js 文件后必须执行。 不要依赖手动检查清单。
python3 $UTILS/validate-sims.py \
--project-dir $PROJECT \
--format table \
--verbose
此操作会:
按照 100 分制评分标准对每个 MicroSim 进行评分:
| 类别 | 分值 | 检查项 |
|---|---|---|
| main.html | 10 | 文件存在(5)、schema meta 标签(3)、<main> 标签(2) |
| metadata.json | 30 | 文件存在(10)、必需字段(10)、教育性(5)、教学性(5) |
| index.md | 35 | 标题(2)、YAML(3)、图片(5)、Iframe(10)、全屏(5)、示例(5)、描述(5) |
| 截图 | 5 | PNG 文件存在 |
| 教案 | 10 | index.md 中包含相应章节 |
| 参考资料 | 5 | index.md 中包含相应章节 |
| p5.js 规范 | 5 | updateCanvasSize、无 DOM 按钮、使用 querySelector 设置父元素、无 textFont('Segoe UI') |
等级标准: A(85+)、B(70-84)、C(50-69)、D(<50)
验证单个模拟:
python3 $UTILS/validate-sims.py \
--project-dir $PROJECT \
--sim <sim-id> \
--verbose
修复发现的问题,然后重新验证以确认改进:
# After fixing issues...
python3 $UTILS/validate-sims.py \
--project-dir $PROJECT \
--min-score 0 \
--format table \
--verbose
第 6B 步:同步 Iframe 高度
实现 .js 文件后必须执行。 不要手动计算 Iframe 高度。
python3 $UTILS/sync-iframe-heights.py \
--project-dir $PROJECT \
--verbose
此操作会:
- 解析每个模拟的
.js文件,查找// CANVAS_HEIGHT: <value>注释(主要来源,参见第 4.4 步) - 按以下顺序回退:
metadata.json中的"canvasHeight"(适用于没有.js的模拟)、main.html中的 `` 注释,然后是根据.js计算出的drawHeight + controlHeight - 将 Iframe 高度设为
CANVAS_HEIGHT + 2(边框占 2px) - 更新每个模拟的
index.md以及docs/下所有嵌入该模拟的页面中的<iframe>高度属性,包括章节、教师指南和海报页面 - 跳过已经正确的模拟
请使用 sync-iframe-heights.py,不要使用 fix-iframe-heights.py。 后者是仅更新自身页面的旧工具:它会更新模拟自身的 index.md,但会默默保留第 5 步插入的、仍使用过期高度的章节嵌入,因此模拟在自己的页面上看起来正常,在章节页面中却会被裁切。
重要: .js 文件中的 // CANVAS_HEIGHT: 注释是所有库类型(p5.js、vis-network、Chart.js、Leaflet、Mermaid 等)的唯一真实来源。如果缺少该注释,请在运行此工具前将其添加到 .js 文件中——格式和计算规则参见第 4.4 步。
修复单个模拟:
python3 $UTILS/sync-iframe-heights.py \
--project-dir $PROJECT \
--sim <sim-id> \
--verbose
先试运行以预览更改:
python3 $UTILS/sync-iframe-heights.py \
--project-dir $PROJECT \
--dry-run --verbose
步骤 6C:验证 iframe 中的控件是否可见(Playwright)
修正 iframe 高度后必须执行。 这项检查可以发现超出 iframe 边界的控件——静态高度计算可能会漏掉这类问题,尤其是采用响应式布局或视口较窄的模拟。
TESTER="$BK_HOME/skills/microsim-utils/scripts"
# Single sim (after generating one MicroSim)
python3 $TESTER/test-iframe-heights.py --sims-dir $PROJECT/docs/sims --sim <sim-id>
# All sims in a batch run
python3 $TESTER/test-iframe-heights.py --sims-dir $PROJECT/docs/sims
此步骤的作用:
- 通过 Playwright 启动无头 Chromium
- 在受限视口中加载每个 MicroSim 的
main.html,视口高度取自index.md中的 iframe 高度 - 等待库(p5.js、vis-network、Chart.js)完成渲染
- 检查所有交互控件(按钮、滑块、选择框、复选框)是否完全可见
- 对任何未通过的项报告 PASS/FAIL,并给出建议高度
先决条件(一次性设置):
pip install playwright
playwright install chromium
如果某个模拟未通过:
- 将
.js文件中的// CANVAS_HEIGHT:注释更新为建议高度减去 10 - 对该模拟重新运行
sync-iframe-heights.py - 重新运行 Playwright 测试以确认通过
步骤 7:更新导航
创建新模拟后必须执行。 不要手动编辑 mkdocs.yml 中的 MicroSims 部分。
python3 $UTILS/update-mkdocs-nav.py \
--project-dir $PROJECT \
--verbose
此步骤的作用:
- 扫描
docs/sims/中包含index.md的目录 - 从 frontmatter 或
# Heading中提取显示标题 - 将
mkdocs.yml中整个- MicroSims:部分替换为按字母顺序排序的列表 - 具有幂等性,可安全地多次运行
先试运行:
python3 $UTILS/update-mkdocs-nav.py \
--project-dir $PROJECT \
--dry-run --verbose
步骤 8:生成 MicroSim 的屏幕截图
/doc/sims/index.md 文件需要 MicroSim 的屏幕截图,以便列出教科书中的所有 MicroSim。
使用 Unix shell 脚本获取 MicroSim 的屏幕截图。该脚本会以无头模式运行 Google Chrome,并创建一张宽度为 800px 的图像;屏幕截图的高度由 iframe 高度决定。
屏幕截图 shell 脚本安装在 ~/.local/bin/bk-capture-screenshot,它是指向 $BK_HOME/scripts/bk-capture-screenshot 程序的符号链接。
bk-capture-screenshot 有 3 个命令行参数:
$1 MicroSim 目录路径(默认值:当前目录) $2 JS 渲染延迟秒数(默认值:3) $3 目标图像高度(像素)(默认值:600)
提示:使用 MicroSim 的 index.md 文件中的 iframe 高度,以获得正确的高度。
示例用法:
bk-capture-screenshot /path/to/microsim 3 700 # 3 second delay, 700px height
输出:
在 MicroSim 目录中创建 <microsim-name>.png,文件通常约为 50K 字节。
步骤 9:视觉布局审查(必须执行)
截取屏幕截图后必须执行。 这是 iframe-tester 工具的视觉 QA 对应环节(iframe-tester 使用 Playwright 边界框检查)。布局审查可以发现几何检查会遗漏的问题:行标签被裁切、控件重叠、文本残留笔画、面板内容溢出、标签对比度过低、绘制顺序错误,以及特定库的渲染问题。
使用步骤 8 中的屏幕截图作为输入——不要重新截图。
对每个新生成的模拟使用 microsim-utils 中的 layout-reviewer 工具:
For each sim that was generated in this batch:
1. Read references/visual-checklist.md from microsim-utils
2. Read the sim's screenshot PNG (Read tool — Claude Vision sees it)
3. Walk every checklist item; mark PASS / FAIL / N/A with quoted
evidence for any FAIL
4. For each FAIL, consult references/common-fixes.md and apply the
smallest patch that resolves it (typically a small edit to the
.js for p5.js / Chart.js / vis-network / Leaflet sims, or to
main.html for Mermaid sims)
5. Re-capture, re-read, re-walk the checklist
6. Stop after 3 review-patch cycles even if issues remain — surface
residue rather than over-tweak
该工具在 $BK_HOME/skills/microsim-utils/references/layout-reviewer.md 中详细说明了完整工作流程。从此生成器的角度来看,其要求是:“步骤 8 之后,每个模拟都必须通过布局审查,或者明确报告仍存在的问题。”
布局审查不会做什么:
- 不会修复 iframe 高度导致的裁切(内容超出 iframe 边缘)——这应由步骤 6B / 6C 中的
sync-iframe-heights.py和 iframe-tester 工具(microsim-utils)处理。 - 不会修改已批准的模拟(frontmatter
status: approved)。这与此生成器的工作流程无关——新生成的模拟尚未获批——但此规则仍然适用。
为什么这在生成流程中是必须的: 在用户看到模拟之前、生成时就发现布局问题,价值远高于之后再发现。将视觉审查安排在步骤 8 末尾,意味着“嵌入后显示正常”是每个新 MicroSim 完成标准的一部分,而不是单独的人工 QA 环节。
工作流概述
批量(按章节)生成
Step 0: Set UTILS and PROJECT paths
↓
Step 1: extract-sim-specs.py → /tmp/ch-specs.json
↓
Step 2: generate-sim-scaffold.py → creates main.html, index.md, metadata.json
↓
Step 3: Instructional Design Checkpoint (per sim)
↓
Step 4: Write .js files (creative work — route to guide, implement)
↓
Step 5: add-iframes-to-chapter.py → inserts/fixes iframes
↓
Step 6: validate-sims.py → scores quality, fix issues
↓
Step 6B: sync-iframe-heights.py → syncs iframe heights (own page + chapter embeds)
↓
Step 6C: test-iframe-heights.py → Playwright verifies controls visible in iframe
↓
Step 7: update-mkdocs-nav.py → regenerates nav
↓
Step 8: bk-capture-screenshot /path/to/microsim 3 {height} → creates screen image
↓
Step 9: microsim-utils layout-reviewer → Claude Vision walks the checklist,
diagnoses + patches FAILs, re-captures to verify (max 3 cycles)
单个模拟生成
Step 0: Set UTILS and PROJECT paths
↓
Step 1B: Write 1-entry spec JSON + scaffold
↓
Step 3: Instructional Design Checkpoint
↓
Step 4: Write .js file
↓
Step 6: validate-sims.py --sim <name>
↓
Step 6B: sync-iframe-heights.py --sim <name>
↓
Step 6C: test-iframe-heights.py --sim <name> → Playwright verifies controls visible
↓
Step 7: update-mkdocs-nav.py
↓
Step 8: bk-capture-screenshot /path/to/microsim 3 {height} → creates screen image
↓
Step 9: microsim-utils layout-reviewer → Claude Vision walks the checklist,
diagnoses + patches FAILs, re-captures to verify (max 3 cycles)
上下文窗口填满后的续接
当批量运行在章节中途填满上下文窗口时:
- 新会话读取
sim-status.json,查看已完成的内容 - 状态为
implemented或更后续状态的模拟会跳过 - 状态为
specified或scaffolded的模拟仍需要.js文件
# Check where we left off
python3 $UTILS/extract-sim-specs.py \
--project-dir $PROJECT \
--chapter <chapter-dir-name> \
--status-file /tmp/sim-status.json \
--verbose
可用生成器
主要生成器
| 生成器 | 库 | 最适用场景 |
|---|---|---|
| p5-guide | p5.js | 自定义模拟、物理、动画 |
| chartjs-guide | Chart.js | 柱状图、折线图、饼图、圆环图、雷达图 |
| timeline-guide | vis-timeline | 按时间顺序排列的事件、历史、日程 |
| map-guide | Leaflet.js | 地理数据、地点、路线 |
| vis-network-guide | vis-network | 网络图、依赖关系、概念图 |
| mermaid-guide | Mermaid.js | 流程图、工作流、UML 图 |
| plotly-guide | Plotly.js | 数学函数图 |
| venn-guide | Custom | 集合关系(2-4 个集合) |
| bubble-guide | Chart.js | 优先级矩阵、多维数据 |
| causal-loop-guide | vis-network | 系统思维、反馈循环、多循环 CLD 文章 |
| comparison-table-guide | Custom | 带评分的并排比较 |
| html-table | Custom | 带可点击单元格和详情面板的矩阵比较 |
| celebration-guide | p5.js | 粒子效果、视觉反馈 |
| concept-classifier-guide | p5.js | 分类测验——将场景分类到各类别 |
| infographic-overlay-guide | Custom (diagram.js) | 插图上的交互式标注/区域叠加层——图像本身不含文字;也是每张经验证信息图的强制包装层 |
| docker-python-lab-guide | Custom (docker-lab.js) | 在 Docker 容器中运行的 Python 实验 |
| verified-infographic-guide | Custom (text-verify → image) | 经事实核验的统计海报——声明计划、来源核验、锁定的图像提示词(仅在明确要求时使用静态 PNG,且之后始终使用叠加层包装) |
共享标准
所有 MicroSim 均遵循以下标准,不受生成器影响:
目录结构:
docs/sims/<microsim-name>/
├── main.html # Main visualization file
├── index.md # Documentation page
├── *.js or *.css # Supporting files
└── metadata.json # Dublin Core metadata (optional)
便于发现的 URI 方案:
所有 MicroSim HTML 文件都必须包含此 schema meta 标签,以便全球发现:
<meta name="schema" content="https://dmccreary.github.io/intelligent-textbooks/ns/microsim/v1">
这样便可通过代码搜索统计和发现 GitHub 上的 MicroSim。详情请参阅 URI 方案文档。
集成:
- 通过 iframe 嵌入 MkDocs 页面
- 宽度响应式设计
- iframe 容器不滚动
- 标准高度:
CANVAS_HEIGHT + 2px(其中 CANVAS_HEIGHT 在.js文件顶部的// CANVAS_HEIGHT: <value>注释中声明——参见步骤 4.4) - 防止滚动劫持:
- 章节 iframe 保持不滚动:
scrolling="no" - 默认情况下,模拟中不得占用页面的滚轮滚动(例如,除非明确要求,否则设置 Leaflet 的
scrollWheelZoom: false)
- 章节 iframe 保持不滚动:
- iframe 路径必须始终使用相对路径,绝不能使用绝对路径:
- 从模拟自身的
index.md:<iframe src="main.html" ...> - 从章节文件(
docs/chapters/*/index.md):<iframe src="../../sims/[sim-name]/main.html" ...> - 绝不要使用
/sims/...这样的绝对路径——当 GitHub Pages 将网站托管在子目录下(例如/geometry-course/)时,这类路径会失效
- 从模拟自身的
质量检查清单:
- 可在现代浏览器中无错误运行
- 可根据容器宽度进行响应式调整
- 控件能立即响应
- 嵌入 iframe 时不会劫持页面滚动
- 教育目的明确
- 代码注释完善
- 除非设计明确要求特定字体,否则不得调用
textFont();绝不要使用textFont('Segoe UI'),因为这是仅限 Windows 的字体,在 macOS/Linux 上不可用
示例
示例 1:时间线请求
用户:“创建一条时间线,展示计算机发展史上的重要事件”
**路由:**关键词“时间线”“事件”“历史”→ references/timeline-guide.md
**操作:**阅读 timeline-guide.md 并遵循其工作流
示例 2:图表请求
用户:“制作一张条形图,对比编程语言的受欢迎程度”
**路由:**关键词“条形图”“对比”→ references/chartjs-guide.md
**操作:**阅读 chartjs-guide.md 并遵循其工作流
示例 3:自定义模拟
用户:“构建一个交互式弹跳球模拟”
**路由:**关键词“交互式”“弹跳”“模拟”→ references/p5-guide.md
**操作:**阅读 p5-guide.md 并遵循其工作流
示例 4:含糊的请求
用户:“创建一张展示我们项目依赖关系的图”
路由:“图”+“依赖关系”暗示网络 → references/vis-network-guide.md
**操作:**阅读 vis-network-guide.md(但如果用户指的是图表,则需先澄清)
示例 5:章节批量处理
用户:“为第 11 章生成 MicroSims” **操作:**步骤 0 → 步骤 1 → 步骤 2 → 步骤 3-4(每个模拟依次循环)→ 步骤 5 → 步骤 6 → 步骤 6B → 步骤 6C → 步骤 7
示例 6:分类测验
用户:“创建一个测验,让学生判断每种情境体现了哪种认知偏差”
**路由:**关键词“判断”“对情境进行分类”→ references/concept-classifier-guide.md
**操作:**阅读 concept-classifier-guide.md 并遵循其工作流
示例 7:因果回路文章
用户:“展示供应链中的牛鞭效应反馈回路”
**路由:**关键词“反馈回路”→ references/causal-loop-guide.md
**操作:**阅读 causal-loop-guide.md;如请求完整文章,则生成完整文章;否则生成单个内嵌 CLD
示例 8:带标签的图示叠加层
用户:“制作一张交互式苔藓孢子体解剖图,并标注各结构”
**路由:**关键词“解剖”“标注”→ references/infographic-overlay-guide.md
**操作:**阅读 infographic-overlay-guide.md 并遵循其标注工作流
示例 9:Python 实验
用户:“在此页面添加一个可运行的 Python 列表操作实验”
**路由:**关键词“可运行”“Python 实验”→ references/docker-python-lab-guide.md
**操作:**阅读 docker-python-lab-guide.md 并遵循其工作流
示例 10:经过事实核验的海报
用户:“制作一张海报,用真实数据对比 LED 与白炽灯的能耗”
**路由:**明确要求“海报”+ 需要来源的数值声明 → 退出常规路由
操作:跳过步骤 0-9;执行指南中的 8 个阶段;在调用图像工具前核验每个数字。然后始终执行阶段 9:使用 infographic-overlay-guide.md 中的网格叠加层包裹 poster.png,以便海报发出交互事件。
示例 11:未指定格式的信息图
用户:“制作一张信息图,展示各类粮食作物的生长需水量”
**路由:**包含数值声明,但未要求静态格式 → 先执行核验阶段 1-4,再使用交互式指南
**操作:**不要渲染静态海报。先执行 verified-infographic-guide.md 的阶段 1-4,锁定带引文的声明集合,然后使用匹配的模拟指南(此处为 chartjs-guide.md)构建可视化,并将每个 source_id 保留在模拟的数据文件中。
示例 11:带来源的对比模拟
用户:“使用经过核验的规格参数,为这五种面包板电源制作一张对比表”
路由:“对比表”→ references/comparison-table-guide.md,但规格参数必须注明来源
**操作:**执行 verified-infographic-guide.md 的阶段 1-4,锁定声明并添加引文,然后使用 comparison-table-guide.md 构建模拟,并将每个 source_id 保留在表格中,以便引文始终可见
参考文件
如需详细信息,请查阅:
references/routing-criteria.md- 所有生成器的完整评分方法references/<generator>-guide.md- 各生成器的具体实现指南assets/templates/- 共享模板和模式references/infographic-claim-plan-template.yaml、references/infographic-verification-report-template.md、references/infographic-layout-spec-template.yaml、references/poster-image-prompt.md、references/infographic-biophilic-case-study.md- verified-infographic 路线scripts/posters/generate-poster-thumbnails.py- 海报图库缩略图(参见 verified-infographic-guide.md 中的“Gallery Thumbnails”)
sim-status.json 生命周期
extract-sim-specs.py --status-file 标志会生成一个生命周期跟踪文件。状态按如下顺序推进:
| 状态 | 含义 |
|---|---|
| specified | 章节中有规范,但尚无 sim 目录 |
| scaffolded | 目录中有 main.html/index.md,但没有实质性的 JS |
| implemented | JS 文件存在且超过 50 行 |
| validated | quality_score >= 70 |
| deployed | 已通过验证,且章节中包含 iframe |