mcpField
M
microsim-generator

microsim-generator

github.com/dmccreary开发10937 次安装1 天前更新
代码仓库

关于 microsim-generator

microsim-generator 是用于生成交互式 MicroSim 的技能,会根据可视化需求路由到专用生成指南,并整合 17 种生成技能。它还提供批处理脚本,用于提取规格、搭建文件、更新导航和验证质量。

主要功能

  1. 01按可视化需求选择生成指南
  2. 02整合 17 种 MicroSim 生成技能
  3. 03批量提取章节模拟规格
  4. 04生成模拟目录和页面文件
  5. 05验证质量并更新导航

适用场景

  1. 01为章节批量生成多个 MicroSim
  2. 02创建交互式教育可视化
  3. 03按学习目标设计模拟交互
  4. 04将模拟嵌入课程页面

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dmccreary/ibook-skills --skill microsim-generator

安装后在 Claude Code 中输入/microsim-generator确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

assets/causal-loop/
cld-inline.js
assets/causal-loop/cld-viewer/
cld-viewer.js
main.html
assets/causal-loop/cld-viewer/examples/
ai-flywheel-cld.json
runaway-hypothesis-cld.json
winner-takes-all-cld.json
assets/concept-classifier/
concept-classifier-template.js
data-template.json
index-template.md
main-template.html
assets/docker-python-lab/
docker-lab.css
docker-lab.js
assets/infographic-overlay/
grid-main-template.html
main-template.html
assets/infographic-overlay/shared-libs/
diagram.js
grid-diagram.js
grid-overlay.css
style.css
assets/templates/chartjs/
data-template.json
index-template.md
main-template.html
market-share-example.html
metadata-template.json
script.js
style.css
assets/templates/comparison-table/
index-template.md
main-template.html
metadata-template.json
style.css
assets/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. 手动编写一个包含 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
  1. 仅为该模拟运行 scaffold:
python3 $UTILS/generate-sim-scaffold.py \
    --spec-file /tmp/ch-specs.json \
    --sim-id inscribed-angle-theorem \
    --project-dir $PROJECT \
    --verbose
  1. 跳至步骤 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 回答以下问题

继续之前,请回答以下问题:

  1. 学习者必须看到哪些具体数据?

    • 不是“动画粒子”,而是“分词后的数组 ['physics', 'ball']”
  2. 学习者是否需要在观察之前进行预测?

    • 如果是 → 使用带有“下一步/上一步”按钮的逐步演示
    • 如果是 → 不要使用连续动画
  3. 动画比静态箭头多了什么?

    • 如果无法清楚回答 → 不要使用动画
  4. 连续动画是否适合此布鲁姆层级?

    • 对于动词为“解释”的理解(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.mdvis-timeline
地图、地理、坐标、纬度、经度、地点、标记references/map-guide.mdLeaflet.js
函数、f(x)、方程、绘图、微积分、正弦、余弦、多项式references/plotly-guide.mdPlotly.js
网络、节点、边、图、依赖关系、概念图、知识图谱references/vis-network-guide.mdvis-network
流程图、工作流、流程、状态机、UML、时序图references/mermaid-guide.mdMermaid.js
维恩图、集合、重叠、交集、并集、类别references/venn-guide.mdCustom
图表、柱状图、折线图、饼图、圆环图、雷达图、统计数据、数据references/chartjs-guide.mdChart.js
气泡图、优先级、矩阵、象限、影响与投入、风险与价值references/bubble-guide.mdChart.js
因果、反馈、循环、系统思维、增强、平衡、CLD、系统原型references/causal-loop-guide.mdvis-network
比较、表格、评分、星级、并排、功能references/comparison-table-guide.mdCustom
矩阵、框架比较、可点击单元格、详情面板、可展开references/html-table.mdCustom
动画、庆祝、粒子、彩纸、效果references/celebration-guide.mdp5.js
分类、分类器、归类、场景排序、识别类型、识别模式references/concept-classifier-guide.mdp5.js
图示叠加层、标注标签、解剖图、带标签的插图、信息图叠加层、探索/测验模式references/infographic-overlay-guide.mdCustom (diagram.js) — 交互式模拟;标签位于 data.json 中,图像不含文字
Python 实验室、代码运行器、可运行代码块、交互式 Python 练习、Dockerreferences/docker-python-lab-guide.mdCustom (docker-lab.js)
已核实的信息图、统计海报、事实核查海报、带引用的数据、来源明确的主张、基于证据的比较references/verified-infographic-guide.mdCustom (text-verify → image) — 静态 PNG;数字直接烘焙进像素,绝不能单独作为最终交付物
自定义、模拟、物理、交互、弹跳、运动、p5.jsreferences/p5-guide.mdp5.js
区分两种 infographic 路由

两种路由的名称中都有 “infographic”,而且经常被混淆。请通过询问 文字位于何处来选择:

infographic-overlay-guide.mdverified-infographic-guide.md
产出docs/sims/{sim-id}/ 中的 MicroSimdocs/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。

每份指南都包含:

  1. 特定于库的要求
  2. 代码模板和模式
  3. 针对此类可视化的最佳实践
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。本步骤的其他所有内容(如何计算数值、+2 iframe 规则)都相同。

格式:// CANVAS_HEIGHT: <integer>

该值是 iframe 显示完整 MicroSim 而不发生裁切所需的总像素高度,包括画布、控件、图例、信息面板、标题和所有内边距。

如何按库类型计算 CANVAS_HEIGHT
库公式示例
p5.jsdrawHeight + 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() {
规则
  1. 注释必须出现在 .js 文件的前 10 行内,以便解析工具快速找到。
  2. 该值必须是整数(不得带 px 后缀,也不得使用表达式)。
  3. iframe 高度 = CANVAS_HEIGHT + 2(额外的 2px 用于计算 iframe 边框)。sync-iframe-heights.py 工具会自动添加这部分高度。
  4. 对于 p5.js 模拟,CANVAS_HEIGHT 的值必须等于 drawHeight + controlHeight(如果存在 graphHeight,还需加上它)。保留现有的命名变量——该注释是为工具提供的冗余但权威的声明。
  5. 更新现有模拟时,如果更改了任何与高度相关的值,务必同步更新 CANVAS_HEIGHT 注释。
  6. 如果不确定高度,请在浏览器中渲染模拟,测量内容总高度,并使用该值。宁可稍微偏高一些(多余的空白也好过控件被裁切)。
4.5 处理含糊的请求

如果该请求可能匹配多个生成器:

  1. 阅读 references/routing-criteria.md,了解详细的评分方法
  2. 使用 0-100 分制为得分最高的 3 个候选项评分
  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?
    
  4. 根据用户的选择继续操作
常见歧义
歧义术语需要澄清的内容
“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.html10文件存在(5)、schema meta 标签(3)、<main> 标签(2)
metadata.json30文件存在(10)、必需字段(10)、教育性(5)、教学性(5)
index.md35标题(2)、YAML(3)、图片(5)、Iframe(10)、全屏(5)、示例(5)、描述(5)
截图5PNG 文件存在
教案10index.md 中包含相应章节
参考资料5index.md 中包含相应章节
p5.js 规范5updateCanvasSize、无 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

如果某个模拟未通过:

  1. 将 .js 文件中的 // CANVAS_HEIGHT: 注释更新为建议高度减去 10
  2. 对该模拟重新运行 sync-iframe-heights.py
  3. 重新运行 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)
上下文窗口填满后的续接

当批量运行在章节中途填满上下文窗口时:

  1. 新会话读取 sim-status.json,查看已完成的内容
  2. 状态为 implemented 或更后续状态的模拟会跳过
  3. 状态为 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-guidep5.js自定义模拟、物理、动画
chartjs-guideChart.js柱状图、折线图、饼图、圆环图、雷达图
timeline-guidevis-timeline按时间顺序排列的事件、历史、日程
map-guideLeaflet.js地理数据、地点、路线
vis-network-guidevis-network网络图、依赖关系、概念图
mermaid-guideMermaid.js流程图、工作流、UML 图
plotly-guidePlotly.js数学函数图
venn-guideCustom集合关系(2-4 个集合)
bubble-guideChart.js优先级矩阵、多维数据
causal-loop-guidevis-network系统思维、反馈循环、多循环 CLD 文章
comparison-table-guideCustom带评分的并排比较
html-tableCustom带可点击单元格和详情面板的矩阵比较
celebration-guidep5.js粒子效果、视觉反馈
concept-classifier-guidep5.js分类测验——将场景分类到各类别
infographic-overlay-guideCustom (diagram.js)插图上的交互式标注/区域叠加层——图像本身不含文字;也是每张经验证信息图的强制包装层
docker-python-lab-guideCustom (docker-lab.js)在 Docker 容器中运行的 Python 实验
verified-infographic-guideCustom (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 路径必须始终使用相对路径,绝不能使用绝对路径:
    • 从模拟自身的 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
implementedJS 文件存在且超过 50 行
validatedquality_score >= 70
deployed已通过验证,且章节中包含 iframe

评论

支持 Markdown