# CES-Alpha 問題JSONファイル形式 — バージョン 1.0

この文書は、CES-Alpha の自動採点問題を1問以上収めた JSON ファイルの仕様を定めます。手作業、スクリプト、AI エージェントのいずれでファイルを作成する場合も、この仕様に従ってください。

- この文書のWebページ: <https://document.ces-alpha.jp/manual/auto_grade_question_format.html>
- この文書の Markdown 版: <https://document.ces-alpha.jp/manual/auto_grade_question_format.ja.md>
- サンプルファイル: 第9節

## 1. ファイルを使う場所

教員の問題編集ページで使います。

- **ダウンロード**: ページ下部の「問題JSONファイル」欄の「JSONファイルをダウンロード」で、問題をこの形式のファイルとしてダウンロードできます。
- **1つのファイルを読み込む**: 「問題をロード」→「ローカルのJSONファイルから」で、1問分の内容がフォームに入力されます。保存ボタンを押すまでは保存されません。
- **複数の問題を読み込む**: 複数のファイル、`.zip` ファイル、または問題のリストを収めたファイルを選ぶと、すべての問題が、ページで選択中のグループに新しい問題として追加されます。

サイトは2つあり、ファイルはそのどちらか一方のためのものです。

| サイト | `site` | 問題 |
|---|---|---|
| プログラミングサイト（`code.ces-alpha.org` とそのサブサイト） | `"code"` | プログラミング問題、および短いテキスト解答の問題 |
| 数学サイト（`math.ces-alpha.org`） | `"math"` | 記号計算で採点する数学の問題 |

## 2. ファイルの基本

- 文字コード: **UTF-8**。形式: JSON（[RFC 8259](https://www.rfc-editor.org/rfc/rfc8259)）。拡張子: `.json`。
- 1つの問題は1つの JSON **オブジェクト**です。複数の問題を扱う場合は、次のいずれかを使います。
    - 1つのファイルに問題オブジェクトの JSON **配列**を書く
    - 複数の `.json` ファイルを同時に選ぶ
    - `.json` ファイルをまとめた `.zip` ファイル（中のフォルダは使用可。`.` で始まるファイルと `__MACOSX` フォルダは読み飛ばされます）
- テキストの値はすべて JSON 文字列です。改行は `\n` と書きます。バックスラッシュは `\\` と書くため、LaTeX の `\frac{1}{2}` はファイル内では `"\\frac{1}{2}"` となります。
- この文書に記載のないキーは無視されます。
- 空文字列 `""` は、キーがない場合と同じ意味です。

## 3. ヘッダー（必須）

形式 1.0 の問題オブジェクトは、必ず次の2つのキーで始めます。

| キー | 型 | 値 |
|---|---|---|
| `ces_question_format` | 文字列 | `"1.0"`: 形式のバージョン（`"メジャー.マイナー"`）。 |
| `site` | 文字列 | `"code"` または `"math"`: 問題の対象サイト。 |

ファイル読み込み時の規則:

- **メジャーバージョンが同じ（マイナーバージョンは問わない）**（`"1.0"`、`"1.2"`、…）: ファイルは読み込まれます。後のマイナーバージョンで追加されたキーは無視されます。
- **メジャーバージョンが異なる**（`"2.0"`、…）: ファイルは拒否されます。
- **`site` がページのサイトと一致しない**: ファイルは拒否されます。数学の問題をプログラミングサイトで読み込むことはできず、その逆もできません。
- **`ces_question_format` キーがない**: 1.0 より前のファイル（第8節）とみなし、従来どおりに読み込みます。

## 4. 両サイト共通のフィールド

| キー | 型 | 必須 | 既定値 | 意味 |
|---|---|---|---|---|
| `question_type` | 文字列 | はい | — | 問題の種類。値は第5節（数学）と第6節（プログラミング）を参照。 |
| `question_title` | 文字列 | はい\* | `""` | 問題一覧に表示されるタイトル。 |
| `question_content` | 文字列 | はい\* | `""` | 学生に表示される問題文（第7節）。 |
| `score` | 整数 | いいえ | `1` | 問題の配点（「点数の設定」）。 |
| `evaluation_method` | 整数 | いいえ | 数学 `0`、プログラミング `1` | 解答の採点方法。値は第5節と第6節を参照。 |
| `question_hint` | 文字列 | いいえ | `""` | 学生が開いて見られるヒント（「ヒント」）。 |
| `q_solution_explanation` | 文字列 | いいえ | `""` | 解答の解説。正解とともに学生に表示されます（「問題の解説」）。 |
| `note` | 文字列 | いいえ | `""` | 教員向けのメモ（「備考」）。学生には表示されません。 |

\* `question_title` と `question_content` の少なくとも一方は設定が必要です。両方を設定してください。

## 5. 数学サイト（`"site": "math"`）

### 5.1 問題の種類

| `question_type` | 学生は… | 使用するフィールド |
|---|---|---|
| `"text"`（「テキスト入力 (穴埋めを含む)」） | 1つ以上の式を入力する | `question_answer`, `question_variable`, `answer_const` |
| `"select"`（「多肢選択」） | リストから1つを選ぶ | `answer_candidate`, `question_answer` |
| `"matrix"`（「ベクトル/行列入力」） | ベクトルまたは行列を入力する | `question_answer`, `question_variable` |

### 5.2 フィールド

| キー | 型 | 必須 | 意味 |
|---|---|---|---|
| `question_variable` | 文字列 | いいえ | パラメータ（「パラメータ」）: 学生ごとに問題を変えるためのランダムな値（5.3）。 |
| `question_answer` | 文字列 | はい | 正解。書き方は `question_type` によって異なります（5.4）。 |
| `answer_candidate` | 文字列の配列 | `select` のみ | 選択肢。表示される順に並べます。 |
| `answer_const` | 真偽値 | いいえ（`text` のみ） | `true`: `question_answer` と定数だけ異なる解答も正解とします（不定積分など。「定数分の違いを許容する（不定積分など）」）。既定値は `false`。 |

### 5.3 パラメータ（`question_variable`）

1行に1つのパラメータを `名前=値` の形で書きます（行の区切りは `\n`）。

```text
a=1,2,5
b_1=-3,...,-1,1,...,5
alpha=1,...,5
beta=a+b_1
```

- カンマ区切りの数値のリスト: 学生ごとに1つの値がランダムに選ばれます。`m,...,n` は `m` から `n` までのすべての整数を表します。
- 式（`beta=a+b_1` のように文字を含むもの）: 他のパラメータから計算されます。
- 名前: 1文字（`a`, `b`, `x`, …）またはギリシャ文字の名前（`alpha`, `beta`, …。ただし `lambda`, `pi`, `e` は不可）。1桁の添字を付けることもできます（`b_1`, `beta_9`）。
- `E`（または `e`）、`pi`、`I`（虚数単位）は数学定数です。
- `question_content` では、`$...$` 内のパラメータがその値に置き換えられます。ギリシャ文字は、問題文ではバックスラッシュを付けて（`$\\alpha$`）、`question_variable` では付けずに（`alpha`）書きます。

### 5.4 正解（`question_answer`）

**`text`**: 解答欄ごとに1行、`名前=式` の形で書きます。

```text
A=2*a*x+b
B=2*a+b
```

- 名前（`A`, `B`）は解答欄のラベルです。問題文中に `\ans{A}` と書いて、解答欄の位置を示します（第7節）。
- 式は電卓と同じように SymPy の記法で書きます。掛け算は `*`、累乗は `^` または `**`、ほかに `sqrt(x)`, `sin(x)`, `exp(x)`, `log(x)`, `pi`, `E`, `I`, `oo`（無限大）が使えます。パラメータも使えます。
- 1つの解答欄に複数の正解がある場合: `;` で区切ります（`x=2;-2`）。
- 1行だけ採点方法を変える場合: 行末に `# mode:1`、`# mode:2`、`# mode:3` のいずれかを付けます（`A=x+1 # mode:3`）。番号は 5.5 のものです。

**`matrix`**: 1行に行列の1行を書き、要素はカンマで区切ります。列ベクトルは1行に1要素です。

```text
a+2, 2
1, 1
```

**`select`**: 正解の選択肢のテキストを、`answer_candidate` に書いたとおりに書きます。

### 5.5 採点方法（`evaluation_method`）

| 値 | フォーム上の名前 | 正解となる条件 |
|---|---|---|
| `0` | [mode:1] 数式の同値性チェック | 数学的に同じ意味である: `(x-1)^2` = `x^2-2x+1`。 |
| `1` | [mode:2] 形式を含めたチェック | 順序の違いを除いて同じ形である: `(x-3)(x-1)` = `(x-1)(x-3)`。ただし `3x` ≠ `x+2x`。 |
| `2` | [mode:3] 完全一致のチェック | 文字列として同じである: `2x` ≠ `2*x`。 |

`select` では使いません。`select` は常に選ばれたテキストを比較します。

## 6. プログラミングサイト（`"site": "code"`）

### 6.1 問題の種類

| `question_type` | 学生は… | 採点方法 |
|---|---|---|
| `"code"`（「コード作成」） | プログラムを書く | `sample_code` と学生のコードを同じ入力で実行し、結果を比較する |
| `"text"`（「テキスト入力 (穴埋めを含む)」） | 短い解答を入力する | `question_answer` と比較する |

### 6.2 `code` 問題のフィールド

| キー | 型 | 必須 | 意味 |
|---|---|---|---|
| `code_language` | 文字列 | はい | `"Python"`（Python 3）、`"R"`、`"MATLAB"`（Octave で実行）のいずれか。既定値は `"Python"`。 |
| `answer_template` | 文字列 | いいえ | 学生のエディタに最初に表示されるコード。 |
| `sample_code` | 文字列 | はい | 模範解答。採点サーバーで実行され、学生には表示されません。 |
| `object_for_grade` | 文字列 | はい | 比較の対象（6.3）。 |
| `input_argument` | 文字列 | いいえ | 関数呼び出しの入力。1行に1つのテストケースを書きます（6.3）。 |
| `evaluation_method` | 整数 | いいえ | `1`: コードを実行して結果を比較します（既定値。「コードの実行結果を確認」）。 |

### 6.3 比較の対象（`object_for_grade`, `input_argument`）

方法は2つあります。

**関数。** `object_for_grade` は `add(a, b)` のような関数呼び出しです。`input_argument` の各行が1つのテストケースで、カンマ区切りの値が順に引数の位置に入ります。各テストケースについて `sample_code` と学生のコードの両方で関数が呼び出され、戻り値が一致する必要があります。

```json
"object_for_grade": "add(a, b)",
"input_argument": "1, 2\n-3, 5\n0.5, 0.25"
```

- リストや入れ子の呼び出しも値として使えます。`[1,2], 5` と `c(1,2,3), 1000` はどちらも2つの値です。
- プレースホルダー `var1`, `var2`, …（値が1つなら `var`）も使えます。式の中でも使えます: `solve(var1, np.array([var2, var3]))`。
- `input_argument` がない場合、関数は引数なしで1回だけ呼び出されます（`f()`）。

**変数。** `object_for_grade` は `m, mx` のような、カンマ区切りの変数名のリストです。両方のプログラムを実行し、終了時のこれらの変数の値が一致する必要があります。`input_argument` は使いません。

### 6.4 プログラミングサイトの `text` 問題

`question_answer` には、5.4 と同じく解答欄ごとに1行、`名前=値` の形で書きます。複数の正解は `;` で区切ります（`PrimeNumber=3;13;23`）。解答そのものにセミコロンが含まれる場合は `\;` と書きます（JSON ファイル内では `"\\;"`）。

## 7. 問題文・ヒント・解説のテキスト

- `question_content`、`question_hint`、`q_solution_explanation` は **Markdown** です。空行で新しい段落になります。コードはバッククォートで囲んで書けます。
- 数学サイトでは LaTeX の数式が使えます。インラインは `$...$`、ブロックは `$$...$$` です。
- `\ans{名前}` は、テキスト中のその位置に、解答 `名前` の入力欄を表示します。

## 8. 1.0 より前のファイル

`ces_question_format` のないファイルは従来どおりに読み込まれます。そのようなファイルに限り、互換性のために次の別名も受け付けます。新しいファイルでは使わないでください。

| 1.0 のキー | 受け付ける別名 |
|---|---|
| `question_type` | `exercise_type`, `q_type` |
| `question_title` | `title` |
| `question_content` | `q_content` |
| `question_variable` | `q_variable` |
| `question_answer` | `answer` |
| `answer_candidate` | `answer_choices` |
| `question_hint` | `hint` |
| `q_solution_explanation` | `solution_explanation` |
| `answer_template` | `code_template` |
| `object_for_grade` | `code_output` |

1.0 より前のファイルで、問題の種類がない場合やサイトにない種類の場合は、種類を推定します。プログラミングサイトでは、`answer_template` または `object_for_grade` がある問題は `code`、それ以外は `text` とみなします。

## 9. サンプル

| ファイル | サイト | 種類 |
|---|---|---|
| [code_python_function.json](https://document.ces-alpha.jp/manual/question_format_examples/code_python_function.json) | code | `code`、テストケース付きの関数 |
| [code_python_variables.json](https://document.ces-alpha.jp/manual/question_format_examples/code_python_variables.json) | code | `code`、変数 |
| [code_text.json](https://document.ces-alpha.jp/manual/question_format_examples/code_text.json) | code | `text` |
| [math_text.json](https://document.ces-alpha.jp/manual/question_format_examples/math_text.json) | math | `text`、パラメータあり、解答2つ |
| [math_text_integral.json](https://document.ces-alpha.jp/manual/question_format_examples/math_text_integral.json) | math | `text`、`answer_const` あり |
| [math_select.json](https://document.ces-alpha.jp/manual/question_format_examples/math_select.json) | math | `select` |
| [math_matrix.json](https://document.ces-alpha.jp/manual/question_format_examples/math_matrix.json) | math | `matrix` |
| [math_several_questions.json](https://document.ces-alpha.jp/manual/question_format_examples/math_several_questions.json) | math | 2問の配列 |

プログラミング問題の例:

```json
{
  "ces_question_format": "1.0",
  "site": "code",
  "question_type": "code",
  "question_title": "Sum of two numbers",
  "question_content": "Write a function `add(a, b)` that returns the sum of `a` and `b`.",
  "score": 1,
  "evaluation_method": 1,
  "code_language": "Python",
  "answer_template": "def add(a, b):\n    # Write your code here.\n    return None\n",
  "sample_code": "def add(a, b):\n    return a + b\n",
  "object_for_grade": "add(a, b)",
  "input_argument": "1, 2\n-3, 5\n0.5, 0.25",
  "question_hint": "Use the + operator.",
  "q_solution_explanation": "Return `a + b`.",
  "note": "Week 1"
}
```

数学の問題の例:

```json
{
  "ces_question_format": "1.0",
  "site": "math",
  "question_type": "text",
  "question_title": "Derivative of a polynomial",
  "question_content": "Let $f(x) = a x^2 + b x$. Find $f'(x)$ and $f'(1)$.\n\n$f'(x) = $ \\ans{A}, $f'(1) = $ \\ans{B}",
  "question_variable": "a=1,...,5\nb=-3,-2,-1,1,2,3",
  "question_answer": "A=2*a*x+b\nB=2*a+b",
  "evaluation_method": 0,
  "score": 2,
  "question_hint": "$(x^n)' = n x^{n-1}$",
  "q_solution_explanation": "$f'(x) = 2ax + b$, so $f'(1) = 2a + b$."
}
```

## 10. AI エージェント向けの指示

問題ファイルを作成する AI エージェントには、この節、または文書全体を渡してください。

```text
あなたは CES-Alpha の問題ファイルを「CES-Alpha 問題JSONファイル形式 1.0」で作成します。
- 出力は有効な JSON のみとし、UTF-8 で、コメントや前後の文章を含めないでください。
- 各問題はオブジェクトとし、"ces_question_format": "1.0" と "site": "code" または "math" で始めてください。
- 複数の問題は、そのようなオブジェクトの JSON 配列として出力してください。
- この形式のキーだけを使ってください。第8節の旧名は決して使わないでください。
- question_type, question_title, question_content, question_answer は必ず設定してください
  （プログラミングの "code" 問題では、question_answer の代わりに code_language, sample_code, object_for_grade を設定します）。
- 数学サイト: question_type は "text", "select", "matrix" のいずれかです。式は SymPy の記法で書きます（2*x, x^2, sqrt(x), pi, E）。
  "text" の正解は、解答欄ごとに1行 "name=expression" と書き、問題文中の各解答欄の位置を \ans{name} で示します。
  "select" の正解は、answer_candidate のいずれか1つと完全に同じ文字列にします。
- プログラミングサイト: question_type は "code" または "text" です。code_language は "Python", "R", "MATLAB" のいずれかです。
  sample_code はエラーなく実行でき、object_for_grade が指すものを定義していなければなりません。
  関数の場合は、input_argument に複数のテストケースを1行に1つずつ書いてください。
- JSON 文字列内のエスケープ: 改行は \n、バックスラッシュは \\（LaTeX の \frac は \\frac と書く）、ダブルクォートは \" とします。
- 正解を書く前に、その正解が正しいことを確認してください。
```

## 11. 変更履歴

| バージョン | 日付 | 変更内容 |
|---|---|---|
| 1.0 | 2026-10 | 最初のバージョン: ヘッダー `ces_question_format` と `site`、`answer_const` を追加。第8節の旧名は互換性のためだけに残す。 |
