Skip to content

[QTI] Publish mixed Perseus + QTI exercises as one QTI package #6006

Description

@rtibbles

Overview

Let a single exercise node containing both raw Perseus questions and QTI questions publish together as one QTI package. Raw Perseus questions are wrapped in a custom QTI interaction that Kolibri's QTI Viewer renders via the Perseus renderer (Kolibri side: learningequality/kolibri#14892).

Complexity: High
Target branch: unstable

Context

  • Today a node publishes either Perseus or QTI, never both. publish.py:370-374 picks QTIExerciseGenerator when any question is free-response and PerseusExerciseGenerator otherwise, one generator per node.
  • Nodes mixing legacy Perseus with new QTI questions therefore have no publish path.
  • The mixed package needs the Perseus renderer too, so its qti File sets the exercise bit in the included_presets bitmask (Publish a renderer-preset bitmask (File.included_presets) into the content database #6004).

The Change

  • Relax the one-generator-per-node selection in publish.py (370-374) so a node whose questions include both raw Perseus and QTI items routes to QTIExerciseGenerator.
  • Have QTIExerciseGenerator emit each raw Perseus question as the custom interaction defined below.
  • Set the mixed qti File's included_presets to qti | exercise when it embeds ≥1 Perseus custom interaction.

Contract — Perseus-in-QTI custom interaction

Shared with the Kolibri renderer issue. Exact attribute validity is confirmed against the QTI 3.0 XSD under #6005.

  • Each raw Perseus question is a qti-custom-interaction (the spec's delivery-engine-specific element — no JS module required) with a data-type="perseus" marker.
  • The Perseus JSON is a resource file in the package, referenced by data-perseus-path.
  • Every file that JSON references (images, graphie .svg/-data.json) is packaged and declared as a dependency of that resource in the manifest.
  • The host's Perseus renderer, keyed off data-type="perseus", owns rendering and grading. It reports the resulting correct/incorrect back through the QTI response, with no QTI-native response-processing template.
<qti-custom-interaction
    response-identifier="RESPONSE"
    data-type="perseus"
    data-perseus-path="perseus/{assessment_id}.json"/>

Acceptance Criteria

  • A mixed node yields one QTI package whose manifest lists both native QTI items and Perseus custom interactions
  • Each Perseus custom interaction references its Perseus JSON and assets as package files (see Contract)
  • The package validates against the QTI 3.0 XSD ([QTI] QTI 3.0 schema XML validation utilities #6005)
  • The mixed qti File has included_presets = qti | exercise
  • Native QTI questions in the same node are unaffected
  • Tests cover a mixed node and assert both question kinds appear in the package

References

AI usage

Claude mapped the existing publish and validation code, proposed the breakdown, and drafted this issue; the maintainer steered every decision and reviewed throughout.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions