Skill Overview
This skill supports two modes, helping teachers complete the full question design and review process for junior high school mathematics midterm exams:
Mode A: Question Design Mode(Brand-new question design)
- Needs interview — confirm grade, scope, question types, score allocation
- Plan the two-way specification table — chapters × cognitive level proportions
- Generate questions — produce according to Bloom's four levels
- Geometric figure rendering — if there are geometry questions, automatically generate accompanying PNG figures (built-in, no need to call external skills)
- Format output — question paper, answer sheet, two-way specification table (three Word documents), geometric figures automatically inserted at corresponding positions
Mode B: Question Review Mode(Reviewing an existing exam paper)
- Receive exam paper — user pastes text or uploads images/Word
- Review each question — determine Bloom level, section attribution, answers, and question quality
- Output a graded report — display statistics and deviation alerts
- Format output — produce only the two-way specification table (one Word document)
Processing Flow
Step 1: Needs confirmation (mandatory)
Confirm the following information with the user (ask if not provided):
| Item | Description |
|---|---|
| Grade | Seventh grade / Eighth grade / Ninth grade |
| Semester & exam number | First semester third midterm exam, etc. |
| Exam scope | Chapter names + edition (Hanlin edition / Kang Hsuan edition / Nani edition) |
| Question type requirements | How many multiple-choice questions, how many non-multiple-choice questions, score allocation |
| Difficulty target | Refer to the proportions for each Bloom level, or teacher-defined |
| Mode | A. Question design(Newly produce question paper + answer sheet + specification table) / B. Question review(Review an existing exam paper, produce only the specification table) |
Step 2: Create the two-way specification table
Read references/shuangxiang-table.md to obtain the format specification, and plan according to the following structure:
- Vertical axis: textbook chapters (list each section name according to the exam scope)
- Horizontal axis: cognitive levels (Remember / Understand / Apply / Analyze)
- Cell: score (number of questions), e.g.,
6(2)
Recommended proportions for midterm exams(from the Bloom taxonomy expert settings):
| Level | Definition | Recommended proportion |
|---|---|---|
| Level 1: Remember | Recall formulas, definitions, terminology | 10% |
| Level 2: Understand | Explain, generalize, distinguish differences | 20% |
| Level 3: Apply | Substitute into concrete contexts to calculate, solve equations | 40% |
| Level 4: Analyze | Multi-step reasoning, identifying and analyzing structural relationships | 30% |
⚠️ If the deviation from this ratio exceeds ±10%, a reminder to adjust is required.
Step 3: Item Generation (Exclusive to Item-Writing Mode A)
Generate items according to each cell of the two-way specification table. Each item must be annotated with:
- Item number, item type (selected-response / constructed-response)
- Bloom level and key rationale for the determination
- Correct answer + solution process
- Geometric figure requirements(If the item requires a figure, fill in the
geometryfield, see the JSON specification below)
Item-writing principles for each level(Reference references/bloom-taxonomy.md):
- Level 1 (Remember): Recognize the correctness of formulas, recall definitions, e.g., "Which of the following is a linear equation in one variable?"
- Level 2 (Understand): Explain steps, distinguish differences, e.g., "At which of the following steps does the error first occur?"
- Level 3 (Apply): Given specific numerical values/contexts, apply formulas to calculate, e.g., "A store discount problem, find the original price"
- Level 4 (Analyze): Integrate multiple conditions, infer implicit relationships, e.g., "Given multiple systems of equations, find the relationship of a certain variable"
Selected-Response Item Format Specifications:
- Four options, choose one (A/B/C/D); each item must provide all four complete options
- Distractor options must be educationally meaningful (common errors)
- Each item must clearly have exactly one correct answer
Answer Distribution Rules (Must Be Strictly Followed):
- Answers must be evenly distributed across the four options A, B, C, and D; the number of occurrences of each option should be roughly equal (within ±1 item)
- For example: 16 selected-response items → A, B, C, and D each appear 4 times
- It is forbidden for two consecutive items to have the same answer(For example: if item 3 answers A, item 4 must not answer A again)
- After item writing is completed,a self-check is requiredon the answer sequence to confirm there are no consecutive repeats and to confirm that the occurrence counts of each option are balanced
Answer Distribution Self-Check Table(Fill in after completing item writing):
答案序列:題1=?, 題2=?, 題3=?, ...(列出全部)
A 出現 _ 次|B 出現 _ 次|C 出現 _ 次|D 出現 _ 次
是否有連續重複:□ 無 □ 有(需修正)
Constructed-Response Item Format Specifications:
- Must include a complete solution process requirement
- Divided into multiple sub-items (1)(2)(3), with the point allocation for each sub-item indicated
- It is recommended that the last item be a contextual application item (Levels 3-4)
Step 4: Cognitive Level Review (Exclusive to Item-Review Mode B)
Trigger condition: The user provides an already-written exam paper (pasted text, uploaded image, or .docx) and requests item review or the production of a two-way specification table.
4-1 Receive Exam Paper Information
Confirm the following information with the user (if already present in the exam paper, extract it automatically without asking again):
| Item | Description |
|---|---|
| Grade | Grade 7 / Grade 8 / Grade 9 |
| Semester & Exam Number | First Semester First Monthly Exam, etc. |
| Exam Scope | Chapter names (used for section attribution) |
| Point Allocation Rules | Points per selected-response item, point allocation for each major section |
4-2 Item-by-Item Review
Read references/bloom-taxonomy.md detailed leveling criteria, and determine for each item:
- section: Which section it belongs to (e.g., "1-1 Arithmetic Sequences"), filled in according to the chapter names in the exam scope
- bloom_level: Levels 1–4, fill in the complete format such as "Level 3 (Application)"
- Quality Check: Whether the questions are clear, whether the options are meaningful, and whether the non-multiple-choice questions are reasonable
Review output format (displayed in the conversation):
[題目審查報告]
題號 | 題目摘要(20字以內) | section | 判定層次 | 判定理由
-----|----------------------|-------------|-----------|------------------
01 | 辨認等差數列公差 | 1-1 等差數列 | 第1級(記憶)| 僅需辨認定義特徵
02 | 代入首項公差求第n項 | 1-1 等差數列 | 第3級(應用)| 給定數值帶公式計算
...
[統計摘要]
各節次題數:1-1 等差數列 X題 / 1-2 等差級數 X題 / ...
Bloom 分佈:1級 __%、2級 __%、3級 __%、4級 __%
建議比例:1級 10%、2級 20%、3級 40%、4級 30%
△ 差異提示:[若偏離 ±10% 則列出調整建議]
[品質問題]:[若有問題題目,列出題號與說明]
4-3 Organize into review JSON
After the review is complete, organize the exam paper information into review JSON,save as /home/claude/exam_data.json:
In review mode, there is no need to fill in
answer、solution(an empty string is allowed); the focus is onsectionandbloom_level. For non-multiple-choice questions,sub_questionsfor each sub-questionmust be filled in withbloom_levelandpoints, so that they can be correctly counted in the specification table. In review mode, you must additionally fill in thereview_reportfield(see the format below), so that the script will also generate the review report Word file.
review_report field format (added at the outermost level of the JSON):
"review_report": {
"mc_rows": [
{
"number": 1,
"summary": "辨認等差數列公差",
"section": "1-1 等差數列",
"bloom_level": "第1級(記憶)",
"answer": "C",
"reason": "僅需辨認定義特徵"
}
],
"open_rows": [
{
"big_number": 1,
"label": "(1)",
"summary": "代入首項公差求第n項",
"section": "1-1 等差數列",
"bloom_level": "第3級(應用)",
"points": 4,
"reason": "給定具體數值帶公式計算"
}
],
"section_stats": [
{ "section": "1-1 等差數列", "mc_pts": 20, "open_pts": 5, "total": 25 }
],
"bloom_stats": {
"第1級(記憶)": { "pts": 10, "pct": 10, "suggest": 10 },
"第2級(理解)": { "pts": 20, "pct": 20, "suggest": 20 },
"第3級(應用)": { "pts": 40, "pct": 40, "suggest": 40 },
"第4級(分析)": { "pts": 30, "pct": 30, "suggest": 30 }
},
"quality_issues": [
{
"type": "error",
"title": "配分說明有誤(需修正)",
"description": "說明欄寫「1-16題每題4分,15-21題每題3分」,應為「17-21題每題3分」。"
}
]
}
4-4 Execute the script (review mode, generate the two-way specification table + review report)
# 找腳本目錄
for d in /mnt/skills/user/jh-math-exam/scripts /tmp/jh-math-exam/scripts; do
[ -f "$d/generate_exam_docx.py" ] && SKILL_SCRIPTS="$d" && break
done
pip install python-docx lxml --break-system-packages -q
mkdir -p /home/claude/exam_output
cd "$SKILL_SCRIPTS"
# ★ 審題模式加 --blueprint-only,產出雙向細目表與審題報告(兩份)
python3 generate_exam_docx.py /home/claude/exam_data.json /home/claude/exam_output/ --blueprint-only
GRADE=$(python3 -c "import json; d=json.load(open('/home/claude/exam_data.json')); print(d['grade'])")
EN=$(python3 -c "import json; d=json.load(open('/home/claude/exam_data.json')); print(d['exam_number'])")
cp "/home/claude/exam_output/${GRADE}數學第${EN}次段考_雙向細目表.docx" "/mnt/user-data/outputs/"
[ -f "/home/claude/exam_output/${GRADE}數學第${EN}次段考_審題報告.docx" ] && \
cp "/home/claude/exam_output/${GRADE}數學第${EN}次段考_審題報告.docx" "/mnt/user-data/outputs/"
echo "✅ 完成"
Finally, use the present_files tool to provide downloads of two Word files at the same time (two-way specification table, review report).
Step 5: Organize into JSON data
Organize all questions into the following format, save as /home/claude/exam_data.json:
▶ geometry field description (for question-setting mode only)
If a question requires a geometric figure illustration, add the geometry field to that question; if no figure is needed, set it to null。
Geometric figure spec reference (common types for quick copying):
| Question type | geometry.spec.type | Common subtype |
|---|---|---|
| Right triangle | triangle |
right |
| Isosceles triangle | triangle |
isosceles |
| General triangle | triangle |
general |
| Parallelogram | quadrilateral |
parallelogram |
| Trapezoid | quadrilateral |
trapezoid |
| Circle (chord, arc, tangent) | circle |
— |
| Coordinate plane | coordinate_plane |
— |
| Prism/Pyramid | solid_3d |
rectangular_prism / cone , etc. |
| Parallel lines cut by a transversal | parallel_lines |
— |
For complete parameters, see the "Geometric Figure Parameter Quick Reference (Embedded)" section at the end of this SKILL.md
JSON format (including the geometry field):
{
"school_year": "114",
"semester": "1",
"exam_number": "3",
"grade": "七年級",
"scope": "翰林版第一冊第一章~第二章",
"total_pages": 2,
"mc_scoring": "1~7題每題4分、8~16題每題3分,共85分",
"mc_questions": [
{
"number": 1,
"section": "1-1 等差數列",
"bloom_level": "第3級(應用)",
"question": "如圖,△ABC 中,∠C = 90°,AC = 3,BC = 4,則 AB = ?",
"options": { "A": "5", "B": "6", "C": "7", "D": "8" },
"answer": "A",
"solution": "由畢氏定理 AB² = AC² + BC² = 9 + 16 = 25,AB = 5",
"geometry": {
"caption": "圖一",
"spec": {
"type": "triangle",
"config": {
"subtype": "right",
"vertex_labels": ["A", "B", "C"],
"right_angle_at": "C",
"side_labels": {"AC": "3", "BC": "4", "AB": "?"}
},
"canvas": {"width": 250, "height": 200}
}
}
},
{
"number": 2,
"section": "1-2 等差級數",
"bloom_level": "第2級(理解)",
"question": "不需要圖的題目範例",
"options": { "A": "", "B": "", "C": "", "D": "" },
"answer": "B",
"solution": "",
"geometry": null
}
],
"open_questions": [
{
"number": 1,
"section": "1-2 等差級數",
"total_points": 10,
"context": "如圖,梯形 ABCD 中,AD∥BC,AD = 6,BC = 10,高為 4。",
"geometry": {
"caption": "圖二",
"spec": {
"type": "quadrilateral",
"config": {
"subtype": "trapezoid",
"vertex_labels": ["A", "B", "C", "D"],
"side_labels": {"AD": "6", "BC": "10"},
"show_height": true,
"height_label": "4"
},
"canvas": {"width": 280, "height": 220}
}
},
"sub_questions": [
{
"label": "(1)",
"bloom_level": "第3級(應用)",
"points": 4,
"question": "求梯形 ABCD 的面積。",
"answer": "32",
"solution": "面積 = (AD + BC) × 高 ÷ 2 = (6 + 10) × 4 ÷ 2 = 32"
}
]
}
]
}
Note:
geometryThe field can be placed inmc_questionsfor each question, or inopen_questionsat the major-question context level (the whole question shares one figure), or at the sub-question level (each sub-question has its own figure).
Step 5.5: Geometric figure rendering (if there is a geometry field in the JSON)
Determine whether execution is needed: Scan exam_data.json, and if any question's geometry field is not null, then execute this step.
# ── 0. 確認幾何腳本位置 ──────────────────────────────────────
GEOM_DIR=""
for d in /mnt/skills/user/jh-math-geometry/scripts \
/tmp/jh-math-geometry/scripts; do
[ -f "$d/geometry_renderer.py" ] && GEOM_DIR="$d" && break
done
echo "幾何腳本目錄:$GEOM_DIR"
# ── 1. 安裝依賴 ────────────────────────────────────────────
pip install cairosvg python-docx --break-system-packages -q
# ── 2. 從 exam_data.json 提取所有 geometry spec,建立 geometry_spec.json ──
python3 - <<'PYEOF'
import json, pathlib
exam = json.load(open('/home/claude/exam_data.json', encoding='utf-8'))
figures = []
def collect(q, prefix):
geo = q.get('geometry')
if geo and geo.get('spec'):
spec = dict(geo['spec'])
spec['id'] = f"{prefix}_fig"
spec.setdefault('canvas', {'width': 260, 'height': 210})
figures.append({
'id': spec['id'],
'type': spec['type'],
'config': spec.get('config', {}),
'canvas': spec['canvas'],
'_caption': geo.get('caption', ''),
'_question_key': prefix
})
# 選擇題
for q in exam.get('mc_questions', []):
collect(q, f"mc_{q['number']}")
# 非選擇題(大題層級)
for q in exam.get('open_questions', []):
collect(q, f"open_{q['number']}")
# 子題層級
for sq in q.get('sub_questions', []):
label = sq['label'].strip('()')
collect(sq, f"open_{q['number']}_{label}")
if figures:
spec_data = {
'figures': [{'id': f['id'], 'type': f['type'], 'config': f['config'], 'canvas': f['canvas']} for f in figures],
'options': {'format': 'png', 'dpi': 150}
}
json.dump(spec_data, open('/home/claude/geometry_spec.json', 'w', encoding='utf-8'), ensure_ascii=False, indent=2)
# 儲存 caption mapping 供後續插入使用
mapping = {f['id']: {'caption': f['_caption'], 'question_key': f['_question_key']} for f in figures}
json.dump(mapping, open('/home/claude/geometry_mapping.json', 'w', encoding='utf-8'), ensure_ascii=False, indent=2)
print(f"✅ 需要渲染 {len(figures)} 張幾何圖形")
else:
print("ℹ️ 本份考卷無幾何圖形,跳過渲染")
PYEOF
# ── 3. 渲染(若有圖形)────────────────────────────────────
if [ -f /home/claude/geometry_spec.json ]; then
mkdir -p /home/claude/geometry_output
python3 "$GEOM_DIR/geometry_renderer.py" \
/home/claude/geometry_spec.json \
/home/claude/geometry_output/
echo "✅ 幾何圖形渲染完成:"
ls /home/claude/geometry_output/*.png 2>/dev/null || echo "(無 PNG 輸出)"
fi
Visual confirmation: Use the
viewtool to view/home/claude/geometry_output/*.svg, and confirm the figure is correct before continuing. If the figure is incorrect (label offset, poor proportions), modify the correspondingexam_data.jsoningeometry.spec.config, and rerun Step 5.5.
Step 6: Export Word document (required)
After the JSON is organized, execute the following script (generate both the question paper and the answer sheet):
# Step 6-1:找腳本目錄
for d in /mnt/skills/user/jh-math-exam/scripts \
/tmp/jh-math-exam/scripts; do
[ -f "$d/generate_exam_docx.py" ] && SKILL_SCRIPTS="$d" && break
done
echo "腳本目錄:$SKILL_SCRIPTS"
# Step 6-2:安裝相依套件
pip install python-docx lxml --break-system-packages -q
# Step 6-3:產生文件
mkdir -p /home/claude/exam_output
cd "$SKILL_SCRIPTS"
python3 generate_exam_docx.py /home/claude/exam_data.json /home/claude/exam_output/
GRADE=$(python3 -c "import json; d=json.load(open('/home/claude/exam_data.json')); print(d['grade'])")
EN=$(python3 -c "import json; d=json.load(open('/home/claude/exam_data.json')); print(d['exam_number'])")
echo "✅ Word 初稿產出完成"
Step 6.5: Insert geometric figures into the question paper (if there are geometric figures)
If Step 5.5 produced geometric figures, execute the following post-processing script to insert the PNG after the corresponding question:
# 確認是否有幾何圖形需要插入
if [ ! -f /home/claude/geometry_mapping.json ]; then
echo "ℹ️ 無幾何圖形,跳過插入步驟"
else
GEOM_DIR=""
for d in /mnt/skills/user/jh-math-geometry/scripts \
/tmp/jh-math-geometry/scripts; do
[ -f "$d/insert_to_docx.py" ] && GEOM_DIR="$d" && break
done
python3 - <<PYEOF
import json, sys, re
from pathlib import Path
from docx import Document
from docx.shared import Cm
from docx.enum.text import WD_ALIGN_PARAGRAPH
sys.path.insert(0, "$GEOM_DIR")
from insert_to_docx import insert_figure
exam = json.load(open('/home/claude/exam_data.json', encoding='utf-8'))
mapping = json.load(open('/home/claude/geometry_mapping.json', encoding='utf-8'))
grade = exam['grade']
en = exam['exam_number']
docx_path = f"/home/claude/exam_output/{grade}數學第{en}次段考_題目卷.docx"
doc = Document(docx_path)
# ── 建立「題號 → 段落索引」對照 ──────────────────────────────
# 策略:找段落文字以 "N." 開頭(選擇題)或 "(N)" / "大題N" 開頭(非選擇題)
para_index = {}
for i, para in enumerate(doc.paragraphs):
text = para.text.strip()
# 選擇題:匹配「1.」「2.」...「16.」
m = re.match(r'^(\d{1,2})[\..]', text)
if m:
key = f"mc_{m.group(1)}"
para_index.setdefault(key, i)
# 非選擇題大題:匹配「一、」「二、」「1、」「大題一」等或題號行
m2 = re.match(r'^[一二三四五六七八九十\d]+[、..]', text)
if m2 and '題' in text[:6]:
# 記錄為 open_N 對應關係(依出現順序)
pass
# 備援:找含「如圖」、「右圖」的段落
for i, para in enumerate(doc.paragraphs):
text = para.text.strip()
if '如圖' in text or '右圖' in text or '下圖' in text:
# 嘗試從前文找題號
for back in range(1, 4):
if i - back >= 0:
prev = doc.paragraphs[i - back].text.strip()
m = re.match(r'^(\d{1,2})[\..]', prev)
if m:
key = f"mc_{m.group(1)}"
para_index.setdefault(key, i)
break
# ── 依 mapping 插入圖形 ──────────────────────────────────────
# 先排序:讓插入從後往前,避免段落索引位移
insertions = []
for fig_id, info in mapping.items():
png_path = Path(f"/home/claude/geometry_output/{fig_id}.png")
if not png_path.exists():
print(f"⚠️ 找不到圖形:{png_path}")
continue
qkey = info['question_key']
caption = info.get('caption', '')
if qkey in para_index:
insertions.append((para_index[qkey], png_path, caption))
else:
# 找不到對應段落:插在文件末尾並提示
print(f"⚠️ 找不到題號段落 {qkey},圖形將插在文件末尾")
insertions.append((len(doc.paragraphs) - 1, png_path, f"[{qkey}] {caption}"))
# 從後往前插入,保持段落索引正確
insertions.sort(key=lambda x: -x[0])
for para_idx, png_path, caption in insertions:
# 在目標段落「之後」插入圖片段落
# python-docx 沒有原生「after」插入,用 XML 操作
from docx.oxml.ns import qn
from copy import deepcopy
import lxml.etree as etree
# 建立圖片段落
img_para = doc.add_paragraph()
img_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
run = img_para.add_run()
run.add_picture(str(png_path), width=Cm(5.5)) # 試卷圖寬 5.5cm
if caption:
cap_para = doc.add_paragraph(caption)
cap_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
for r in cap_para.runs:
from docx.shared import Pt
r.font.size = Pt(9)
r.font.italic = True
# 把剛 add 的段落(現在在文件末)移到目標位置後面
target_el = doc.paragraphs[para_idx]._element
img_el = img_para._element
# 如果有 caption,一起移動
if caption:
cap_el = cap_para._element
target_el.addnext(cap_el)
target_el.addnext(img_el)
else:
target_el.addnext(img_el)
print(f"✅ 已插入 {png_path.name} 於段落 {para_idx} 之後")
doc.save(docx_path)
print(f"✅ 幾何圖形插入完成:{docx_path}")
PYEOF
fi # end if geometry_mapping exists
Step 6.6: Copy the final output
GRADE=$(python3 -c "import json; d=json.load(open('/home/claude/exam_data.json')); print(d['grade'])")
EN=$(python3 -c "import json; d=json.load(open('/home/claude/exam_data.json')); print(d['exam_number'])")
cp "/home/claude/exam_output/${GRADE}數學第${EN}次段考_題目卷.docx" "/mnt/user-data/outputs/"
cp "/home/claude/exam_output/${GRADE}數學第${EN}次段考_答案卷(教師版).docx" "/mnt/user-data/outputs/"
cp "/home/claude/exam_output/${GRADE}數學第${EN}次段考_雙向細目表.docx" "/mnt/user-data/outputs/"
echo "✅ 輸出完成"
Finally, use present_files The tool also provides three Word file downloads (question paper, answer sheet, two-way specification table).
Mathematical Markup Syntax (Question Writing Rules)
In the question text, use curly braces {} to enclose mathematical expressions, and the system will automatically convert them to Word OMML format for correct display:
| Markup Syntax | Description | Example |
|---|---|---|
{x^2} |
x squared (superscript) | x² |
{x^{n+1}} |
Superscript containing an expression | x^(n+1) |
{x_1} |
x subscript 1 | x₁ |
{sqrt(2)} |
Square root of 2 | √2 |
{sqrt[3](8)} |
Cube root | ∛8 |
{frac(3,4)} |
Fraction 3/4 | ¾ |
{(a+b)/2} |
Fraction containing an expression | (a+b)/2 |
{|x-3|} |
Absolute value | |x-3| |
{<=} |
Less than or equal to symbol | ≤ |
{>=} |
Greater than or equal to symbol | ≥ |
{!=} |
Not equal to symbol | ≠ |
{a*b} |
Multiplication sign | a×b |
Reminder: Simple textual equations (such as
2x + 3 = 7) do not need{}; just keep them as plain text.
Quick Reference: Locations of Detailed Descriptions for Each Skill
| What you need | Which file to read |
|---|---|
| Detailed criteria for the four Bloom levels, keywords, question-setting principles | references/bloom-taxonomy.md |
| Two-way specification table format specifications | references/shuangxiang-table.md |
| Question paper / answer sheet layout format | references/exam-format.md |
| Complete chapters of three-year mathematics under the 108 Curriculum Guidelines, learning content codes (N/A/S/F/D), learning performance codes | references/jh-math-curriculum.md |
| Complete parameters for geometric figures + quick-copy examples | See the "Quick Reference for Geometric Figure Parameters (Embedded)" section below |
When to read the curriculum guideline file: When confirming the learning content codes for the exam scope, writing the "Corresponding Curriculum Guidelines" field of the two-way specification table, or when questions need to align with specific learning performances, please read this file first.
Notes
- Mathematical expressions must always use
{}markup, and must not use textual substitutes such as x^2 or √ - Contextual questions (levels 3-4) should be tied to daily life, and the contexts must be realistic and reasonable
- Multiple-choice options must not include "all of the above" or "none of the above"
- The point value of each sub-question in non-multiple-choice questions must be clearly indicated in the
pointsfield - For the solution process (
solution), please separate each step with a line break to facilitate layout - [Answer Distribution] The answers to multiple-choice questions must be evenly distributed among A/B/C/D, and two consecutive questions must not have the same answer. After filling in the
mc_questionsof the entire JSON, you must re-examine theanswerfield sequence; if there are consecutive repetitions or serious imbalance, immediately adjust the answer order of that question (and simultaneously adjust theoptionscontent to match the new answer). - [Geometric Figures] If the question text contains words such as "as shown in the figure", "figure on the right", "figure below", etc., the
geometryfield must be filled in and must not be left asnull. Figure canvas size: for test paper figures, it is recommended to use280×220; if two figures are placed side by side, use200×160。
Quick Reference for Geometric Figure Parameters (Embedded)
This section fully includes all supported figure types and parameters. When writing
geometry.spec, consult it directly; there is no need to read external files.
General Structure
{
"id": "fig1",
"type": "<圖形類型>",
"config": { ... },
"canvas": { "width": 280, "height": 220 }
}
Batch Specifications (provided to geometry_renderer.py):
{
"figures": [ {...}, {...} ],
"options": { "format": "png", "dpi": 150 }
}
1. triangle (triangle)
| Parameter | Description | Optional values |
|---|---|---|
subtype |
Type | general(default),right、isosceles、equilateral |
vertex_labels |
Vertex labels | String array, default ["A","B","C"] |
right_angle_at |
Right-angle symbol vertex | Vertex label string |
angle_arcs |
Number of angle arcs at each vertex | {"A":1, "B":2} |
side_labels |
Text label for each side | {"AB":"5", "BC":"3"} |
equal_marks |
Number of equal-length tick marks | {"AB":1, "CD":2} |
altitude_from |
Vertex for drawing altitude | Vertex label string |
median_from |
Vertex for drawing median | Vertex label string |
dashed_sides |
Sides drawn as dashed lines | ["AB"] |
show_dots |
Vertex dots | true(default) |
Common examples:
Right triangle (right angle at C, side lengths labeled):
{"type":"triangle","config":{"subtype":"right","vertex_labels":["A","B","C"],"right_angle_at":"C","side_labels":{"AB":"5","BC":"3","CA":"4"}}}
Isosceles triangle (equal sides + base angles labeled):
{"type":"triangle","config":{"subtype":"isosceles","equal_marks":{"AB":1,"AC":1},"angle_arcs":{"B":1,"C":1}}}
2. quadrilateral
| Parameter | Description |
|---|---|
subtype |
parallelogram / rectangle / rhombus / square / trapezoid / right_trapezoid / general |
vertex_labels |
Vertex label array, default ["A","B","C","D"] |
side_labels |
Text label for each side |
equal_marks |
Equal-length tick marks |
right_angles |
Array of vertices marked with right angles |
diagonals |
Whether to draw diagonals,true/false |
diagonal_labels |
Diagonal labels {"AC":"m","BD":"n"} |
Common examples:
Parallelogram (with diagonals + equal-length tick marks):
{"type":"quadrilateral","config":{"subtype":"parallelogram","vertex_labels":["A","B","C","D"],"diagonals":true,"equal_marks":{"AB":1,"CD":1,"BC":2,"AD":2}}}
Isosceles trapezoid:
{"type":"quadrilateral","config":{"subtype":"trapezoid","vertex_labels":["A","B","C","D"],"equal_marks":{"AB":1,"CD":1}}}
Right trapezoid:
{"type":"quadrilateral","config":{"subtype":"right_trapezoid","vertex_labels":["A","B","C","D"],"side_labels":{"AD":"6","BC":"10"}}}
3. circle
| Parameter | Description |
|---|---|
center_label |
Center label, default "O" |
show_center |
Whether to show the center point |
points |
Points on the circumference:{"A": 60, "B": 160}(angle, 0=right, 90=up, counterclockwise) |
radius_lines |
Array of points for drawing radius lines |
radius_label |
Radius labels |
chords |
Chord:[["A","B"],["C","D"]] |
diameter |
Diameter endpoints ["A","C"] |
tangent_at |
Tangent point |
central_angle |
Endpoints of the filled sector (central angle) |
inscribed_angle |
Inscribed angle:{"vertex":"C","arc":["A","B"]} |
Common examples:
Central angle and inscribed angle:
{"type":"circle","config":{"center_label":"O","points":{"A":30,"B":150,"C":270},"radius_lines":["A","B"],"central_angle":["A","B"],"inscribed_angle":{"vertex":"C","arc":["A","B"]}}}
4. coordinate_plane
| Parameter | Description |
|---|---|
x_range |
x-axis range, e.g. [-5, 5] |
y_range |
y-axis range |
show_grid |
Whether to show grid lines |
tick_interval |
Tick interval |
points |
Point array:[{"x":1,"y":2,"label":"A","color":"#cc0000"}] |
lines |
Line:[{"slope":2,"intercept":-1,"label":"y=2x-1"}] |
parabolas |
Parabola:[{"a":1,"b":0,"c":-2,"label":"y=x²-2"}] |
segments |
Line segment:[{"x1":0,"y1":0,"x2":3,"y2":4}] |
Common examples:
Linear function y=2x-1:
{"type":"coordinate_plane","config":{"x_range":[-3,5],"y_range":[-4,8],"lines":[{"slope":2,"intercept":-1,"label":"y=2x-1"}],"points":[{"x":0,"y":-1,"label":"(0,-1)"},{"x":0.5,"y":0,"label":"(½,0)"}]}}
Parabola y=x²-2x-3:
{"type":"coordinate_plane","config":{"x_range":[-2,5],"y_range":[-5,6],"parabolas":[{"a":1,"b":-2,"c":-3,"label":"y=x²-2x-3"}]}}
5. solid_3d
| subtype | Description | Vertex order |
|---|---|---|
rectangular_prism |
Rectangular prism (cuboid) | ABCD (top) EFGH (bottom) |
cylinder |
Cylinder | labels: radius, height |
cone |
Cone | labels: apex, base, radius, slant, height |
triangular_prism |
Triangular prism | ABC (back) DEF (front) |
square_pyramid |
Quadrilateral pyramid | ABCD (base) P (apex) |
triangular_pyramid |
Triangular pyramid | ABCD |
Shared parameters:show_hidden(whether to show dashed edges),vertex_labels、labels(label radius/height/slant height)
Common examples:
Rectangular prism (labeled vertices + dashed lines):
{"type":"solid_3d","config":{"subtype":"rectangular_prism","vertex_labels":["A","B","C","D","E","F","G","H"],"show_hidden":true}}
6. parallel_lines
| Parameter | Description |
|---|---|
n_parallel |
Number of parallel lines (usually 2) |
line_labels |
Parallel line labels ["l","m"] |
transversal_angle |
Transversal angle (degrees) |
transversal_labels |
Transversal labels ["t"] |
angle_marks |
Array of angle markers, each item contains line(which one)position(upper_left/upper_right/lower_left/lower_right)、label |
Common examples:
Two parallel lines cut by a transversal, labeling corresponding angles A/E and alternate interior angles C/E:
{"type":"parallel_lines","config":{"n_parallel":2,"line_labels":["l","m"],"transversal_angle":55,"angle_marks":[{"line":0,"position":"upper_left","label":"A"},{"line":0,"position":"lower_right","label":"C"},{"line":1,"position":"upper_left","label":"E"},{"line":1,"position":"lower_right","label":"G"}]}}
7. triangle_center (triangle centers)
center_type |
Description | Default label |
|---|---|---|
centroid |
Centroid (three medians) | G |
circumcenter |
Circumcenter (circumcircle) | O |
incenter |
Incenter (incircle) | I |
{"type":"triangle_center","config":{"center_type":"centroid","center_label":"G","triangle":{"subtype":"general","vertex_labels":["A","B","C"]}}}
8. similar_triangles (similar triangles)
Set up two triangles separately and display them side by side, marking equal angles with the same angle arcs:
{"type":"similar_triangles","config":{"triangle1":{"vertex_labels":["A","B","C"],"angle_arcs":{"A":1,"B":2},"side_labels":{"AB":"3","BC":"4","CA":"5"}},"triangle2":{"vertex_labels":["D","E","F"],"angle_arcs":{"D":1,"E":2},"side_labels":{"DE":"6","EF":"8","FD":"10"}}}}
Quick copy section (most commonly used)
| Problem type | Spec for direct copying |
|---|---|
| Pythagorean theorem | {"type":"triangle","config":{"subtype":"right","vertex_labels":["A","B","C"],"right_angle_at":"C","side_labels":{"AB":"c","BC":"a","CA":"b"}}} |
| Congruent triangles (SSS) | {"type":"triangle","config":{"subtype":"general","vertex_labels":["A","B","C"],"equal_marks":{"AB":1,"BC":2,"CA":3}}} |
| Central angle + inscribed angle | {"type":"circle","config":{"center_label":"O","points":{"A":30,"B":150,"C":270},"radius_lines":["A","B"],"central_angle":["A","B"],"inscribed_angle":{"vertex":"C","arc":["A","B"]}}} |
| Parallelogram diagonals | {"type":"quadrilateral","config":{"subtype":"parallelogram","vertex_labels":["A","B","C","D"],"diagonals":true,"equal_marks":{"AB":1,"CD":1,"BC":2,"AD":2}}} |
| Isosceles trapezoid | {"type":"quadrilateral","config":{"subtype":"trapezoid","vertex_labels":["A","B","C","D"],"equal_marks":{"AB":1,"CD":1}}} |
| Quadrilateral prism | {"type":"solid_3d","config":{"subtype":"rectangular_prism","vertex_labels":["A","B","C","D","E","F","G","H"],"show_hidden":true}} |
| Linear function | {"type":"coordinate_plane","config":{"x_range":[-3,5],"y_range":[-4,8],"lines":[{"slope":2,"intercept":-1,"label":"y=2x-1"}]}} |
| Parabola | {"type":"coordinate_plane","config":{"x_range":[-2,5],"y_range":[-5,6],"parabolas":[{"a":1,"b":-2,"c":-3,"label":"y=x²-2x-3"}]}} |