> ## Documentation Index
> Fetch the complete documentation index at: https://docs.asakiri.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Exercises

> Presentation and evaluation as separate concerns, across seven exercise types.

Every exercise separates two things:

* **Presentation:** the fragments a learner sees and the pieces they manipulate (prompt,
  options, tokens, pairs, blanks). These are compositions of
  [bindings](/data-structure/bindings), the same as any lesson content.
* **Evaluation:** how a response is graded. Correctness always refers to stable IDs or to
  accepted-value bindings, never to duplicated display values.

The stable core is a small set of evaluation strategies. An exercise `type` is an
authoring and interaction template layered on top, and several types can share one
strategy.

## Shared shape

```ts theme={null}
type ExerciseType =
  | "multiple-choice" | "select-image" | "match-pairs"
  | "fill-blank" | "word-order" | "listening" | "speaking";

interface ChoiceOption {
  readonly id: string;
  readonly body: readonly RenderFragment[]; // may render text, audio, an image, or several
}

interface ExerciseBase {
  readonly id: string;
  readonly type: ExerciseType;
  readonly instruction?: string;
  readonly prompt: readonly RenderFragment[];
  readonly evaluation: Evaluation;
  readonly feedback?: ExerciseFeedback;   // correct / incorrect / per-option
  readonly settings?: ExerciseSettings;   // per-type toggles
  readonly presentation?: { readonly layout?: "list" | "image-grid" };
}
```

`ChoiceOption` is reused wherever an exercise offers addressable pieces: options, pair
items, and tokens.

## Evaluation strategies

```ts theme={null}
type Evaluation =
  | { kind: "selected-options"; select?: "one" | "many"; correctOptionIds: readonly string[] }
  | { kind: "ordered-tokens"; correctOrder: readonly string[] }
  | { kind: "matched-pairs"; pairs: readonly { leftId: string; rightId: string }[] }
  | { kind: "filled-blanks"; blanks: readonly BlankAnswer[] }
  | { kind: "typed-answer"; accepted: readonly AcceptedValue[]; normalize?: NormalizationRules }
  | { kind: "spoken-response"; strictness: "lenient" | "standard" | "strict" };
```

Accepted-value bindings usually point at a field such as `field_alternate_answers`, so
"a cat" and "cats" both pass without duplicating text in the exercise. Typed grading uses
`NormalizationRules` for case, whitespace, punctuation, or script (for example accepting
kana for kanji).

## Types at a glance

| Type | Learner does | Evaluation | Auto-graded in Studio |
| - | - | - | - |
| `multiple-choice` | Picks one or more options | `selected-options` | Yes |
| `select-image` | Hears audio, taps the matching image | `selected-options` | Yes |
| `match-pairs` | Links each item to its partner | `matched-pairs` | Yes |
| `fill-blank` | Fills blanks from a bank or by typing | `filled-blanks` | Yes |
| `word-order` | Orders tokens into a sentence | `ordered-tokens` | Yes |
| `listening` | Hears audio, then taps or types | `selected-options` or `typed-answer` | Yes |
| `speaking` | Says the phrase aloud | `spoken-response` | No, learner app only |

<Note>
  `select-image` is mechanically `multiple-choice` with image-valued option bodies and an
  audio prompt. It is a distinct template that shares the `selected-options` strategy, with
  `presentation.layout` set to `image-grid`.
</Note>

## Type-specific bodies

```ts theme={null}
interface MultipleChoiceExercise extends ExerciseBase {
  readonly type: "multiple-choice" | "select-image";
  readonly options: readonly ChoiceOption[];
}

interface MatchPairsExercise extends ExerciseBase {
  readonly type: "match-pairs";
  readonly left: readonly ChoiceOption[];
  readonly right: readonly ChoiceOption[]; // extra right items are distractors
}

interface FillBlankExercise extends ExerciseBase {
  readonly type: "fill-blank";
  readonly stem: readonly BlankSegment[]; // sentence with one or more blanks
  readonly bank?: readonly ChoiceOption[]; // present in tap-to-fill mode
  readonly translation?: RenderFragment;
}

interface WordOrderExercise extends ExerciseBase {
  readonly type: "word-order";
  readonly tokens: readonly ChoiceOption[];
  readonly distractors?: readonly ChoiceOption[]; // extra tokens that stay unused
}

interface ListeningExercise extends ExerciseBase {
  readonly type: "listening";
  readonly stimulus: RenderFragment;      // the audio is the whole question
  readonly answerMode: "select" | "type";
  readonly options?: readonly ChoiceOption[];
}

interface SpeakingExercise extends ExerciseBase {
  readonly type: "speaking";
  readonly target: RenderFragment;        // the phrase to say
}
```

## Distractors

Distractors stay explicit for every type: options, unpaired right items, and unused
tokens are all stored. Distractor queries are editor tooling only: the author selects a
pool, Studio proposes candidates, and the chosen distractors are saved explicitly.

## Where grading runs

Auto-gradable types resolve entirely from authored IDs, ordering, pairs, or normalized
text, so Studio can preview and grade them.

<Warning>
  `speaking` is different. It needs a microphone and on-device speech recognition, so
  recording and scoring run only in the learner application. Studio authors the target
  phrase and strictness; it does not record or score, and nothing is uploaded.
</Warning>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.