Document the H5P findings

docs/API.md gains the endpoint and what it returns, why `play` is the bigger
and lesser of the two, the element-by-id route found while probing, and the
per-library shapes with the traps in them — the string "true", the inline cloze
markers, the correct-option-first convention, and the UI subtrees that drown an
exercise in button labels.

CLAUDE.md's "no quiz of its own" note said a contentId was the only handle onto
the content. That was the reason nobody looked further, so it now says where to
look instead.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-09-17 21:39:19 +02:00
parent a0cef532c6
commit ad8ba28313
5 changed files with 81 additions and 11 deletions

View File

@@ -225,6 +225,53 @@ hops and without Etherpad's API key; `core/etherpad.ts` does this. The url is
built from the server's `ETHERPAD__PAD_URI`, so it must be checked against the
instance host before the session cookie is sent to it.
### H5P elements are the quizzes, and one request holds a whole one
An `h5p` element carries nothing but `content: { contentId }`. The content
itself comes from the H5P service, whose API lives under `/api/v3/h5p-editor/`
— not in `docs-json`, and with no document of its own
(`/api/v3/h5p-editor/docs-json` is a 404). The deployment's ingress table routes
`/h5p/player` and `/h5p/editor`, which are the front-end apps, not this API.
- **`GET /api/v3/h5p-editor/params/{contentId}`** returns the JSON the player is
fed: `{ h5p: <metadata>, library, params: { metadata, params } }`. The inner
`params` is the exercise — **every question, every option and which are
correct** — so the player showing one question at a time is a display detail,
not a limit on what can be read. Bearer auth, same as everything else.
- `GET /api/v3/h5p-editor/play/{contentId}` is the same content wrapped in the
player's integration object: 74 KB against 51 KB for the live quiz below,
because it carries script and style lists. `params` is both smaller and
complete, so nothing needs `play`.
- `GET /api/v3/elements/{elementId}` returns a single board element with its
content, which is how an element's `contentId` can be re-read without its
board. (`/api/v3/board/element/{id}` does not exist.)
The **shape inside `params` belongs to the H5P library** the teacher used, which
is where the work is. Verified against the live quiz "Quiz zur formalen
Gestaltung einer Projektdoku" (`H5P.QuestionSet`, 20 questions):
- A `QuestionSet` holds `questions: [{ library, params, subContentId }]`, each
sub-content naming its own library — `H5P.MultiChoice 1.16` here. Any other
main library *is* a single question, with the same `params` shape.
- `H5P.MultiChoice`: `question` and `answers[].text` are HTML,
`answers[].correct` is the solution, `answers[].tipsAndFeedback.tip` a hint,
and `behaviour.singleAnswer` is what makes the player draw radio buttons —
the only honest source for "tick exactly one".
- `H5P.TrueFalse` stores `correct` as the **string** `"true"`/`"false"`, with
the button labels in `l10n`.
- Cloze libraries (`H5P.Blanks`, `H5P.DragText`, `H5P.MarkTheWords`) mark the
solutions inside the text as `*answer:tip*`, alternatives separated by `/`.
- `H5P.SingleChoiceSet` and `H5P.Summary` put the **correct option first** and
let the player shuffle; nothing else marks it.
- Every payload also carries `UI`, `l10n`, `behaviour` and `overallFeedback`
subtrees of button labels and display settings. Anything that harvests text
generically has to skip them, or the exercise reads as "Überprüfen,
Wiederholen, Absenden".
`core/h5p.ts` models the libraries above and harvests the text of anything else
under a label saying so — a teacher's exercise reported as "0 questions" would
be worse than a clumsy rendering of it.
## The file manager ("Dateien") is a third store
Persönliche Dateien, Kurs-Dateien, Team-Dateien and Geteilte Dateien are the