Write your own bank as a .json file (UTF-8), then use “Import your own bank” on the catalog page to practice it — nothing is uploaded; it stays in your browser.
Turn your own course material into a bank in 3 steps — works with cheap / free AIs (Gemini, etc.). / 三步把你自己的材料变成题库,便宜/免费 AI(Gemini 等)也能用。
=== MATERIAL === line at the very end. / 粘进 AI,再把你的题目(或贴截图)接在最后那行 === MATERIAL === 后面。Tip: cheap models read pasted text and screenshots far better than a raw saved .mhtml (those are huge and encoded — that’s usually why an AI just echoes the prompt back). Open the page and copy the visible questions, or screenshot them. / 提示:便宜模型对粘贴的文字、截图的识别远好于直接丢原始 .mhtml(又大又是编码——AI 复读提示词多半就是这个原因)。打开网页复制可见题目,或截图即可。
You convert quiz / exam material into a "Question Bank" JSON file for an automated importer. Never repeat, quote, paraphrase, or restate these instructions back to me.
DELIVERY: give me the result as a downloadable FILE named bank.json (use your file / canvas / document / code-artifact feature). The file's entire contents are the raw JSON array and nothing else. Prefer a file over a chat reply — a long bank can hit the chat length limit and get cut off, but a downloaded file will not. Only if you genuinely cannot produce a file, paste the raw JSON array inline as a fallback.
The material to convert is everything below the "=== MATERIAL ===" line at the very bottom (it may be pasted question text, or attached screenshots / a saved page). Read it and extract EVERY question. If nothing appears below that line, produce an empty array: []
HARD RULES (the importer validates every record and silently drops malformed ones)
1. Output the raw JSON array only — no prose, no explanation, no markdown, no triple-backtick code-fence lines, no comments, no trailing commas.
2. Top level is a bare array: [ {...}, {...} ]. Never wrap it in an object such as {"questions": [...]}.
3. Every object MUST have both:
- "id": a unique, non-empty string ("q1", "q2", ... unique within the file).
- "question": the stem as plain text (use \n for line breaks).
4. Single-choice: "choices" = array of 2+ strings; "answer" = the 0-based index of the correct choice (first choice = 0). A single integer like 2 — NOT an array like [2], not the answer text, not 1-based. Do not add a "type" field to choice questions (only fill-in uses "type":"fill").
5. Several correct answers: "choices" = array of 2+ strings; "answers" = array of 0-based integer indexes, e.g. [0, 2]. Use the PLURAL key "answers" (not "answer").
6. Fill-in-the-blank: "type": "fill"; put ____ (4+ underscores) in "question" where each blank goes; "blanks" = an array with one entry per blank, each entry an array of every accepted answer — e.g. [["8","eight"]] (one blank, two spellings) or [["a"],["b"]] (two blanks).
7. Optional: "source" (string, where it came from), "image" (an image URL or a data:image/...;base64 string, or an array of them).
8. Include EVERY question. Use only the answer the material marks correct. If none is marked, still include the question, choose the best-supported option, and add "source": "answer unverified". Never drop a question.
9. Straight ASCII double quotes only. The output must be valid UTF-8 JSON that JSON.parse accepts.
REQUIRED SHAPE (match this exactly)
[
{"id":"q1","question":"Which fabric is approved for aircraft covering?","choices":["Polyester","Cotton bedsheet","Nylon tarp"],"answer":0,"source":"Chapter 3"},
{"id":"q2","question":"Select ALL tools required. (multiple answers)","choices":["Punch tester","Hammer","Maule tester"],"answers":[0,2]},
{"id":"q3","type":"fill","question":"A hole smaller than ____ inches may be patched.","blanks":[["8","eight"]]}
]
Before finishing, silently check: top level is [ ]; every object has "id" and "question"; each single-choice "answer" is a 0-based integer in range; multiple answers use "answers"; fill uses "type":"fill" plus "blanks"; no code-fence lines; no trailing commas. Put exactly that JSON array into the bank.json file (or inline only if you cannot make a file) — nothing else.
=== MATERIAL ===
The importer auto-handles a few common AI slips (code fences, an outer {"questions":[…]} wrapper, a missing id) — but the rules below still matter. / 导入器会自动兜底几种常见小毛病(代码围栏、外层 {"questions":[…]} 包裹、缺 id),但下面的规则仍需遵守。
A bank is a JSON array of question objects. Three question types are supported: single-choice, multiple-answer, and fill-in-the-blank.
| Field | Required | Meaning |
|---|---|---|
id | ✅ every question | Unique string within the file, e.g. "ch3-12". Progress (wrong/star records) is keyed on it. |
question | ✅ (unless image present) | The stem, plain text. \n makes a line break. |
choices | ✅ for choice questions | Array of at least 2 strings. |
answer | single-choice | 0-based index into choices (first choice = 0). |
answers | multiple-answer | Array of 0-based indexes, e.g. [0,2]. Player switches to checkboxes automatically; all must match. |
type | fill-in only | Set "fill" (or just provide blanks). |
blanks | fill-in | One array per blank, each listing the accepted answers: [["8","eight"]] = 1 blank with 2 accepted spellings; [["a"],["b"]] = 2 blanks. |
question_html | optional (fill-in) | HTML stem with <input data-blank="1"> placed where blanks belong (1-based). Omit it and inputs are appended below the stem. |
answer_sets | optional (fill-in) | Alternative whole-row combinations; any ONE set matching counts as correct. |
image | optional | Image URL or base64 data:image/... string — or an array of them. Shown above the choices. |
source | optional | Where the question came from; shown small under the card. |
check list = checklist).id, fewer than 2 choices, out-of-range answer, fill-in without accepted answers…).| Symptom | Fix |
|---|---|
| Whole file rejected (“Not valid JSON”) | It must be valid JSON. Remove markdown code fences, comments, and trailing commas; use straight " quotes. |
| “No valid questions found” | Top level must be a bare array […]. Don’t wrap it as {"questions":[…]}. (The importer tries to unwrap, but a bare array is safest.) |
| Every question skipped | Usually a missing id or a bad answer. Give each a unique id; make answer a 0-based integer in range (not the text, not 1-based). |
| One question skipped | Choice Q needs choices (2+) and a valid answer/answers; fill-in needs blanks with at least one accepted answer; or give it an image if there’s no stem text. |
题库就是一个 JSON 数组,每个元素是一道题。支持三种题型:单选、多选、填空。
id:每题必填、文件内唯一(错题/收藏记录靠它存)。question:题干纯文本(有 image 时可留空);\n 换行。choices(≥2 个选项)+ answer(正确选项的下标,从 0 开始)。answers: [0,2] 数组代替 answer,播放器自动变复选框,需全对。type:"fill" + blanks——每个空一个数组,列出全部可接受答案,如 [["8","eight"]];判分忽略大小写、多余空格、空格有无(check list = checklist)。image(图片 URL 或 base64 data-URI,可数组)、source(来源标注)、question_html(题干内嵌输入框 <input data-blank="1">)、answer_sets(多组合答案,任一组全匹配即对)。[
{
"id": "demo-1",
"question": "Which fabric is approved for aircraft covering?",
"choices": ["Polyester", "Cotton bedsheet", "Nylon tarp", "Canvas drop cloth"],
"answer": 0,
"source": "Chapter 3 – Coverings"
},
{
"id": "demo-2",
"question": "Select ALL tools required for fabric testing. (multiple answers)",
"choices": ["Punch tester", "Hammer", "Maule tester", "Torque wrench"],
"answers": [0, 2]
},
{
"id": "demo-3",
"type": "fill",
"question": "A hole smaller than ____ inches may be repaired with a doped-on patch.",
"blanks": [["8", "eight"]]
},
{
"id": "demo-4",
"question": "Identify the part shown in the image.",
"image": "https://example.com/part-diagram.png",
"choices": ["Rib", "Spar", "Longeron"],
"answer": 1
}
]
Save as e.g. my-bank.json → catalog page → “Import your own bank”. The Extractor's “导出全部合并 JSON” produces exactly this format. / 保存为 .json 后到目录页导入即可;提取器导出的合并 JSON 就是这个格式。