@intellectif/lk-core 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/README.md +2 -1
- package/dist/{activity-B2QxK15j.d.cts → activity-DfAmJ1sl.d.cts} +134 -7
- package/dist/{activity-B2QxK15j.d.ts → activity-DfAmJ1sl.d.ts} +134 -7
- package/dist/{chunk-VYE6BYON.cjs → chunk-DQKJUMUW.cjs} +38 -15
- package/dist/chunk-DQKJUMUW.cjs.map +1 -0
- package/dist/{chunk-RK2NVTHZ.js → chunk-FGN4LLSP.js} +50 -6
- package/dist/chunk-FGN4LLSP.js.map +1 -0
- package/dist/{chunk-O2IVKTHV.cjs → chunk-FT7SAC3X.cjs} +4 -4
- package/dist/{chunk-O2IVKTHV.cjs.map → chunk-FT7SAC3X.cjs.map} +1 -1
- package/dist/{chunk-UQPNJP2O.js → chunk-PYP3HCRQ.js} +2 -2
- package/dist/{chunk-4OHWLCI6.cjs → chunk-UHQVIC3P.cjs} +58 -14
- package/dist/chunk-UHQVIC3P.cjs.map +1 -0
- package/dist/{chunk-FVN37GIH.js → chunk-XKKKWKRH.js} +1944 -177
- package/dist/chunk-XKKKWKRH.js.map +1 -0
- package/dist/{chunk-J6POE4HL.cjs → chunk-XONKWL6D.cjs} +1785 -18
- package/dist/chunk-XONKWL6D.cjs.map +1 -0
- package/dist/{chunk-7JMMPE7O.js → chunk-Y36S3X3L.js} +26 -3
- package/dist/chunk-Y36S3X3L.js.map +1 -0
- package/dist/{index-B_scInLM.d.cts → index-Bz9wUigA.d.cts} +181 -4
- package/dist/{index-CRKtWP5G.d.ts → index-CJbbVE9o.d.ts} +181 -4
- package/dist/index.cjs +128 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -6
- package/dist/index.d.ts +14 -6
- package/dist/index.js +60 -5
- package/dist/index.js.map +1 -1
- package/dist/schemas.cjs +17 -3
- package/dist/schemas.cjs.map +1 -1
- package/dist/schemas.d.cts +2 -2
- package/dist/schemas.d.ts +2 -2
- package/dist/schemas.js +16 -2
- package/dist/scoring.cjs +19 -3
- package/dist/scoring.cjs.map +1 -1
- package/dist/scoring.d.cts +150 -5
- package/dist/scoring.d.ts +150 -5
- package/dist/scoring.js +18 -2
- package/dist/xapi.cjs +3 -3
- package/dist/xapi.d.cts +1 -1
- package/dist/xapi.d.ts +1 -1
- package/dist/xapi.js +2 -2
- package/package.json +1 -1
- package/vectors/README.md +9 -1
- package/vectors/scoring.json +12023 -1
- package/dist/chunk-4OHWLCI6.cjs.map +0 -1
- package/dist/chunk-7JMMPE7O.js.map +0 -1
- package/dist/chunk-FVN37GIH.js.map +0 -1
- package/dist/chunk-J6POE4HL.cjs.map +0 -1
- package/dist/chunk-RK2NVTHZ.js.map +0 -1
- package/dist/chunk-VYE6BYON.cjs.map +0 -1
- /package/dist/{chunk-UQPNJP2O.js.map → chunk-PYP3HCRQ.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @intellectif/lk-core
|
|
2
2
|
|
|
3
|
+
## 0.13.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- f26bab6: A built-in `dictation` activity type: the learner listens and types what they hear, and the grade is how close their text is to the transcript.
|
|
8
|
+
|
|
9
|
+
**lk-core**
|
|
10
|
+
|
|
11
|
+
- `DictationData` carries a `transcript` (the answer key), optional `acceptedTranscripts` scored best-of, an audio recording with the usual playback policy, an optional second slower recording (`slowMedia`, a separate file that follows the recording's policy and never has a play budget of its own), progressive word hints for practice (`hints`), and whole-word rewrite rules in `tolerance.equivalences` — the place a contraction table or a regional spelling lives, as content rather than as code inside the scorer.
|
|
12
|
+
- The score is `(length − edit distance) / length` over the whole sentence, in NFC code points, after case, punctuation, spacing and invisible characters (control, format and default-ignorable characters, variation selectors included) are ignored; typographic apostrophes and the hyphens of other scripts are folded, compatibility characters such as fullwidth and halfwidth forms, Latin digraphs, ligatures and Kangxi radicals are read as the characters they stand for (a halfwidth voiced sound mark as the mark on the kana before it), and a few sequences written two ways — the Thai SARA AM typed as its two parts, a Malayalam chillu in its older spelling — compare as one. What is spelling counts: an apostrophe, a hyphen, a Catalan middle dot or a Tibetan tsheg inside a word, a zero-width joiner or non-joiner where it changes what is written (beside a virama, as Unicode 16 lists them, or the Persian half-space between two letters that would otherwise join), the Mongolian vowel separator and free variation selectors, the tag characters of a subdivision flag, the base of a keycap and the format characters that are drawn, such as the Arabic number sign; a combining mark belongs to its word. One `ScoringDetail` per transcript word carries its own `score` — a new optional field on `ScoringDetail` — so a stored result records how each word was marked; the item's `score` is not the mean of them.
|
|
13
|
+
- `alignDictation(data, text)` returns the same comparison as data: the normalised strings, which transcript was scored against, and the word pairings with their similarities. `diffDictationChars(reference, attempt)` returns the character-level edit operations for a marked display, and `dictationReferenceWords(data)` the ids and words a stored result can be checked against. A review screen or an analytics job never re-implements the arithmetic.
|
|
14
|
+
- Learner text is compared up to 8000 code points and a transcript is at most 2000; the alignment says when text was cut. An item carries at most ten accepted transcripts and 100 equivalence rules, each `from` and `to` at most 200 code points; a rule rewrites whole words — in a script written without spaces, whose words show no edges, wherever its letters stand, though a number is a word in every script — and inserts its rewrite as words, set apart by a space where a letter of a script written with spaces, or a digit, would touch one, so `50%` with a rule for `%` reads as `50 percent`; no rule deletes a word. While rules run the text is cut at twice the attempt cap — a transcript that needs that cut is refused, an attempt that needs it is reported as truncated — so no combination of rules, authored or stale, can exhaust the process that grades an exam. The caps are exported as constants.
|
|
15
|
+
- The schema refuses captions on a dictation recording (they are the answer), and `validateItemGroup` refuses them on a group's stimulus recording that a dictation plays. It refuses a title or recording description that contains the whole transcript, or a whole accepted transcript, as whole words — as written and with the item's rules applied, and also where punctuation joins them to other words — or, for a transcript with four or more letters of a script written without spaces, wherever those letters stand, the transcript always read as it is written; and one too long to be searched in full. `validateActivity` reports these beside a refusal in any other field of the item. `assertRedacted` refuses a dictation projection that carries captions, a slow recording beside a play budget or a slow recording with no recording, and `assertRedactedItemGroup` a captioned stimulus a dictation plays, so a payload built by hand cannot pass as learner-safe.
|
|
16
|
+
- `score()` and `evaluate()` accept an optional `{ rounding }` so a pass line can be compared the way a score is displayed; without it nothing changes, and a malformed policy throws a `RangeError` instead of failing every comparison.
|
|
17
|
+
- `dictationType` and the previously unexported `gapSelectType` are on the barrel, and so are `MediaPlaybackPolicy`, the type of `ActivityMedia.playback`, and the `NativeControlHint` it lists, by name. Twenty-one draft issue codes (`dc_*`) with their severities and paths are in the authoring guide.
|
|
18
|
+
- `validateDraft` matches a schema's failures against the issues already reported in the depth of each path, where it made a pass over every reported issue for each failure: a draft with thousands of malformed entries took seconds, for every type. The issues it reports are unchanged. `validateDraft` and `validateItemGroupDraft` also normalise each dictation transcript, title and recording description once, however many of their checks read it.
|
|
19
|
+
- Every existing grade replays unchanged: vectors were added, none changed.
|
|
20
|
+
|
|
21
|
+
**lk-react**
|
|
22
|
+
|
|
23
|
+
- `<Dictation>`, also at `@intellectif/lk-react/components/Dictation`: the recording(s), the text box, and after submission an accessible word-by-word marked result with a character-level diff and a solution toggle. A recording's play limit binds through `mediaBudget` as for every other activity. Starting one of the two recordings pauses the other, and pausing spends no play.
|
|
24
|
+
- The marks are built for assistive technology and for every script: the per-word sentences a screen reader hears are in the interface language and stay hidden without the optional skin; the dictation's own words carry its `data.locale`, and its word list and diff take their direction from that tag when it names one — by a script subtag, or a language written right to left — or else from the transcript's first letter or directional mark, rather than from whatever was typed; the form is named by its title; authored feedback in the live announcement is isolated from the interface text around it. A wrong character inside a wrong word is marked by its own shape, in forced colours too — a combining mark or a stacked letter together with the character it is drawn into — and a missing character's bullet keeps its place inside a number or a word of the other direction. Keyboard focus stays on the hint controls, and a response reports only the hints actually shown.
|
|
25
|
+
- `LkStrings` gains the dictation strings. A dictionary declared as a complete `LkStrings` must add them; partial overrides are unaffected.
|
|
26
|
+
|
|
3
27
|
## 0.12.0
|
|
4
28
|
|
|
5
29
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -14,12 +14,13 @@ npm install @intellectif/lk-core
|
|
|
14
14
|
|
|
15
15
|
## What's in the box
|
|
16
16
|
|
|
17
|
-
- **Activity schemas** for `multiple-choice`, `fill-in-the-blanks
|
|
17
|
+
- **Activity schemas** for `multiple-choice`, `fill-in-the-blanks`, `written-response`, `gap-select` and `dictation`, with semantic refinements (e.g. *at least one correct option*, *single-select ⇒ exactly one correct*, *passage ↔ blank-id bijection*, *image/embed require `alt`*, *a dictation title never contains its whole transcript as words*). Loose at every level, so your sidecar fields survive validation.
|
|
18
18
|
- **`validateActivity(type, data)`** — the authoritative runtime validator. Returns a typed `{ success, data }` or a structured `{ success: false, errors[] }`, and **throws `UnknownActivityTypeError` if `type` is not registered** — so guard it when validating a content bank that may carry types this build does not know. `validateItemGroup(data)` is the equivalent for a `Stimulus` + `ItemGroup` container, which `validateActivity` cannot take.
|
|
19
19
|
- **`validateDraft(type, draft)`** — for editors. Reports `complete`, `incomplete` (something not written yet) or `invalid` (something wrong), each issue with a `severity` and a `code` — documented for every problem the checks recognise — and deliberately no `success` boolean to misread. Stricter than `validateActivity`, never looser. **`createDraft(type, { newId })`** returns an empty draft to start from; a multiple-choice draft marks no option correct.
|
|
20
20
|
- **An open type system** — `defineActivityType` / `registerActivityType` make an activity type a *value*, not a hard-coded union member: register one and `validateActivity`, `validateDraft`, `score`, `evaluate`, `redact` and `jsonSchemaFor` all work for it, with no SDK release. An `authoring` block on the descriptor gives it draft support.
|
|
21
21
|
- **JSON Schema (Draft-7) export** — `jsonSchemaFor(type)` for any registered type (plus the static per-type exports), suitable for form generators or AI prompting.
|
|
22
22
|
- **Scoring engine** — `score(activityType, data, response)` returning `{ score ∈ [0,1], maxScore: 1, passed, feedback, details }`. Pure, deterministic, 100 % test coverage enforced. It **throws** rather than inventing a number: `DeferredScoringError` for a deferred-graded type (`written-response`), and `RedactedScoringError` when handed a `redact()` projection, which has no answer key. Both are on the documented exam path — use `evaluate()` there, which returns `deferred` / `unscorable` instead of throwing.
|
|
23
|
+
- **Dictation marking as data** — a dictation is graded by the character-level similarity of the typed text to the transcript, with one `ScoringDetail` per word carrying its own `score`. `alignDictation(data, text)` returns the same comparison the grade was made of (normalised strings, word pairings, which accepted transcript won), `diffDictationChars(reference, attempt)` the character-level edits for a marked display, and `dictationReferenceWords(data)` the ids and words a stored result can be checked against — so a review screen or an analytics job never re-implements the arithmetic. `score()` and `evaluate()` take an optional `{ rounding }` to compare the pass line as displayed.
|
|
23
24
|
- **`evaluate(data, response)` → `ItemOutcome`** — the resilient result: `scored`, `deferred` (graded later by an AI or a human), `graded` (the grade came back), or `unscorable`. "Not graded yet" is expressible in the type system and is never conflated with a zero.
|
|
24
25
|
- **Deferred grading, both directions** — `GradeRecord`, `gradeFromRubric()` (the weighted total as a pure function of the grader's judgements — never the model's arithmetic; declare `maxScore` per criterion if your grader works out of 100 or out of 9), `outcomeFromGrade()`, `hasGrade()`.
|
|
25
26
|
- **Assessment composition** — `composeAssessmentScore()` for weighted, sectioned totals, with a `provisional` status so an unmarked essay never deflates a grade, and `RoundingPolicy` / `roundGrade` / `gte` / `classifyBand` keeping grade rounding and band classification as the two distinct operations they are.
|
|
@@ -360,6 +360,7 @@ interface ActivityDataMap {
|
|
|
360
360
|
'fill-in-the-blanks': FillInTheBlanksData;
|
|
361
361
|
'written-response': WrittenResponseData;
|
|
362
362
|
'gap-select': GapSelectData;
|
|
363
|
+
dictation: DictationData;
|
|
363
364
|
}
|
|
364
365
|
/**
|
|
365
366
|
* The set of activity types supported by learning-kit. Derived from
|
|
@@ -782,6 +783,108 @@ interface WrittenResponseData {
|
|
|
782
783
|
/** Subjective difficulty on a 1–5 scale. */
|
|
783
784
|
difficultyLevel?: 1 | 2 | 3 | 4 | 5;
|
|
784
785
|
}
|
|
786
|
+
/**
|
|
787
|
+
* A second, slower recording of a dictation — a separate file (a text-to-speech
|
|
788
|
+
* render at reduced speed, or a slower human reading), not a `playbackRate`
|
|
789
|
+
* change. It carries no `captionsUrl` (a caption track of a dictation is the
|
|
790
|
+
* transcript on screen) and no `playback` policy of its own: it follows the
|
|
791
|
+
* policy on `media`, except the play budget, which it never has.
|
|
792
|
+
*/
|
|
793
|
+
interface DictationSlowMedia {
|
|
794
|
+
type: 'audio';
|
|
795
|
+
/** Source URL, under the same policy as {@link ActivityMedia.url}. */
|
|
796
|
+
url: string;
|
|
797
|
+
/** Accessible label — a description ("Recording, slow"), never a transcription. */
|
|
798
|
+
alt?: string;
|
|
799
|
+
}
|
|
800
|
+
/**
|
|
801
|
+
* A whole-word rewrite applied to BOTH the transcript and the attempt before
|
|
802
|
+
* they are compared. `from` and `to` are literal text: a rule is applied to
|
|
803
|
+
* every whole-word occurrence, exactly once, in the order the rules are listed,
|
|
804
|
+
* after spacing is collapsed and before punctuation is ignored — so a rule may
|
|
805
|
+
* name a symbol (`{ from: '&', to: 'and' }`) and a multi-word `from` matches
|
|
806
|
+
* across any whitespace.
|
|
807
|
+
*/
|
|
808
|
+
interface DictationEquivalence {
|
|
809
|
+
/** What to rewrite: at least one code point that survives case, quote and whitespace folding. */
|
|
810
|
+
from: string;
|
|
811
|
+
/** What it becomes: 1..200 code points, something of which survives normalisation. A rule cannot delete a word. */
|
|
812
|
+
to: string;
|
|
813
|
+
}
|
|
814
|
+
/** Grading tolerances for a dictation. Part of the answer key. */
|
|
815
|
+
interface DictationTolerance {
|
|
816
|
+
/** Whole-word rewrites, applied in listed order, each exactly once. */
|
|
817
|
+
equivalences?: DictationEquivalence[];
|
|
818
|
+
}
|
|
819
|
+
/**
|
|
820
|
+
* Data contract for a Dictation activity: the learner listens to a recording
|
|
821
|
+
* and types what they hear; the grade is how close their text is to the
|
|
822
|
+
* transcript.
|
|
823
|
+
*
|
|
824
|
+
* Scoring is character-level similarity over the whole sentence —
|
|
825
|
+
* `(length − edit distance) / length` over NFC code points after case,
|
|
826
|
+
* punctuation and spacing are ignored — with one {@link ScoringDetail} per
|
|
827
|
+
* transcript word carrying that word's own {@link ScoringDetail.score}. It is
|
|
828
|
+
* deliberately not a mode of {@link FillInTheBlanksData}: a blank is right or
|
|
829
|
+
* wrong, a dictation is graded on a continuum, and the whole `TextMatchPolicy`
|
|
830
|
+
* surface (typo tolerance, diacritic folding) would be a second, competing
|
|
831
|
+
* notion of "close enough".
|
|
832
|
+
*/
|
|
833
|
+
interface DictationData {
|
|
834
|
+
schemaVersion: '1.0';
|
|
835
|
+
type: 'dictation';
|
|
836
|
+
/** Unique identifier for this activity. */
|
|
837
|
+
id: string;
|
|
838
|
+
/**
|
|
839
|
+
* Human-readable title used in xAPI statements and error boundaries. It is
|
|
840
|
+
* the stem the learner sees, so it must not contain the transcript.
|
|
841
|
+
*/
|
|
842
|
+
title: string;
|
|
843
|
+
/**
|
|
844
|
+
* What the learner is expected to type. ANSWER KEY. 1..2000 code points,
|
|
845
|
+
* before and after its equivalences are applied, and something must survive
|
|
846
|
+
* normalisation.
|
|
847
|
+
*/
|
|
848
|
+
transcript: string;
|
|
849
|
+
/**
|
|
850
|
+
* Alternative transcriptions accepted at full credit — a regional spelling, a
|
|
851
|
+
* numeral, a whole-sentence contraction variant. ANSWER KEY. At most 10, each
|
|
852
|
+
* 1..2000 code points, none normalising equal to the transcript or to each
|
|
853
|
+
* other. The attempt is scored against every candidate and the best
|
|
854
|
+
* similarity wins; a tie goes to `transcript`.
|
|
855
|
+
*/
|
|
856
|
+
acceptedTranscripts?: string[];
|
|
857
|
+
/**
|
|
858
|
+
* The recording. Audio only, never with captions. Optional in the schema — a
|
|
859
|
+
* dictation inside an item group may draw on the group's stimulus recording —
|
|
860
|
+
* but required whenever `slowMedia` is present. Budgeted per slot like any
|
|
861
|
+
* other activity media, with the usual playback policy.
|
|
862
|
+
*/
|
|
863
|
+
media?: ActivityMedia;
|
|
864
|
+
/** A second, slower recording. See {@link DictationSlowMedia}. */
|
|
865
|
+
slowMedia?: DictationSlowMedia;
|
|
866
|
+
/**
|
|
867
|
+
* Progressive word hints, in `practice` only (the transcript is absent in
|
|
868
|
+
* `exam` mode, so there is nothing to reveal). Public: it reveals nothing by
|
|
869
|
+
* itself. `progressive-words` reveals the transcript's words left to right,
|
|
870
|
+
* one per request; a revealed hint never changes the score.
|
|
871
|
+
*/
|
|
872
|
+
hints?: {
|
|
873
|
+
mode: 'progressive-words';
|
|
874
|
+
};
|
|
875
|
+
/** Grading tolerances. ANSWER KEY. */
|
|
876
|
+
tolerance?: DictationTolerance;
|
|
877
|
+
/** Optional authored overall feedback shown after submission. */
|
|
878
|
+
feedback?: ActivityFeedback;
|
|
879
|
+
/** Minimum scaled score [0–1] required to pass. Defaults to {@link DEFAULT_PASS_THRESHOLD} (0.7) when absent. */
|
|
880
|
+
passThreshold?: number;
|
|
881
|
+
/** BCP 47 language tag for the activity content. Presentation only: scoring never reads it. */
|
|
882
|
+
locale?: string;
|
|
883
|
+
/** IRI references to learning objectives addressed by this activity. */
|
|
884
|
+
learningObjectives?: string[];
|
|
885
|
+
/** Subjective difficulty on a 1–5 scale. */
|
|
886
|
+
difficultyLevel?: 1 | 2 | 3 | 4 | 5;
|
|
887
|
+
}
|
|
785
888
|
/**
|
|
786
889
|
* Maps each ActivityType string to its learner-response shape. Open for
|
|
787
890
|
* extension via module augmentation, mirroring {@link ActivityDataMap}.
|
|
@@ -791,6 +894,7 @@ interface LearnerResponseMap {
|
|
|
791
894
|
'fill-in-the-blanks': FillInTheBlanksLearnerResponse;
|
|
792
895
|
'written-response': WrittenResponseLearnerResponse;
|
|
793
896
|
'gap-select': GapSelectLearnerResponse;
|
|
897
|
+
dictation: DictationLearnerResponse;
|
|
794
898
|
}
|
|
795
899
|
/** Union of all learner response shapes. */
|
|
796
900
|
type LearnerResponse = LearnerResponseMap[keyof LearnerResponseMap];
|
|
@@ -828,18 +932,34 @@ interface WrittenResponseLearnerResponse {
|
|
|
828
932
|
/** Word count of `text`, computed with the canonical `countWords()` helper. */
|
|
829
933
|
wordCount: number;
|
|
830
934
|
}
|
|
935
|
+
/**
|
|
936
|
+
* Learner response for a Dictation activity.
|
|
937
|
+
*
|
|
938
|
+
* `text` is exactly what the learner typed; every normalisation happens in the
|
|
939
|
+
* scorer. `hintsRevealed` is client-reported telemetry — how many hint words
|
|
940
|
+
* were shown before submitting — that the scorer ignores and a consumer may
|
|
941
|
+
* log or penalise, knowing it cannot be verified.
|
|
942
|
+
*/
|
|
943
|
+
interface DictationLearnerResponse {
|
|
944
|
+
type: 'dictation';
|
|
945
|
+
/** The learner's text, as typed. */
|
|
946
|
+
text: string;
|
|
947
|
+
/** Hint words revealed before submitting (practice only). Absent or 0 means none. */
|
|
948
|
+
hintsRevealed?: number;
|
|
949
|
+
}
|
|
831
950
|
/**
|
|
832
951
|
* Fine-grained outcome of the learner's action on a single item, replacing the
|
|
833
952
|
* ambiguous {@link ScoringDetail.correct}:
|
|
834
953
|
* - `correct` — the learner selected/entered the right answer.
|
|
835
954
|
* - `incorrect` — the learner selected/entered a wrong answer.
|
|
836
955
|
* - `correct-omission` — the learner correctly left a non-answer unselected (multiple-choice only).
|
|
837
|
-
* - `incorrect-omission` —
|
|
956
|
+
* - `incorrect-omission` — a correct answer the learner did not give: an unselected
|
|
957
|
+
* correct option, an unanswered gap, a missing dictation word.
|
|
838
958
|
*/
|
|
839
959
|
type ScoringOutcome = 'correct' | 'incorrect' | 'correct-omission' | 'incorrect-omission';
|
|
840
960
|
/** Per-item scoring breakdown returned by the scoring engine. */
|
|
841
961
|
interface ScoringDetail {
|
|
842
|
-
/** ID of the option or
|
|
962
|
+
/** ID of the option, blank, gap or dictation word (`w1`…`wN`) this detail refers to. */
|
|
843
963
|
itemId: string;
|
|
844
964
|
/**
|
|
845
965
|
* @deprecated Ambiguous: for multiple-choice this means "the learner acted
|
|
@@ -852,8 +972,8 @@ interface ScoringDetail {
|
|
|
852
972
|
/**
|
|
853
973
|
* Unambiguous outcome of the learner's action on this item. Optional in the
|
|
854
974
|
* type so 0.2-era consumer-constructed literals keep compiling, but ALWAYS
|
|
855
|
-
* written by
|
|
856
|
-
* when the deprecated `correct` is removed.
|
|
975
|
+
* written by every built-in scorer (by the first two since 0.3.0); becomes
|
|
976
|
+
* required in v1.0 when the deprecated `correct` is removed.
|
|
857
977
|
*/
|
|
858
978
|
outcome?: ScoringOutcome;
|
|
859
979
|
/** The learner's actual response for this item. */
|
|
@@ -861,10 +981,17 @@ interface ScoringDetail {
|
|
|
861
981
|
/** The expected correct response(s) for this item. */
|
|
862
982
|
correctResponse: string | string[];
|
|
863
983
|
/**
|
|
864
|
-
* Weight applied to this item's contribution to the overall score.
|
|
865
|
-
* built-in
|
|
984
|
+
* Weight applied to this item's contribution to the overall score. Every
|
|
985
|
+
* built-in scorer currently weights every item equally and writes `1`.
|
|
866
986
|
*/
|
|
867
987
|
weight?: number;
|
|
988
|
+
/**
|
|
989
|
+
* The item's own scaled score in [0, 1], for a type that grades its items on
|
|
990
|
+
* a continuum rather than right or wrong. Written by the dictation scorer
|
|
991
|
+
* (the similarity of each transcript word to what was typed for it) and by
|
|
992
|
+
* nothing else today. Absent, an item is right or wrong: read `outcome`.
|
|
993
|
+
*/
|
|
994
|
+
score?: number;
|
|
868
995
|
}
|
|
869
996
|
/** Full scoring result returned by the scoring engine. */
|
|
870
997
|
interface ScoringResult {
|
|
@@ -1020,4 +1147,4 @@ interface InteractionEvent {
|
|
|
1020
1147
|
payload: Record<string, unknown>;
|
|
1021
1148
|
}
|
|
1022
1149
|
|
|
1023
|
-
export {
|
|
1150
|
+
export { type XAPIError as $, type ActivityData as A, type BlankConfig as B, type CriterionScore as C, type DeferredScoringPartial as D, type MultipleChoiceOption as E, type FillInTheBlanksData as F, type GapSelectBank as G, type MultipleChoiceOptionMedia as H, type InlineCorrection as I, type ScoringOutcome as J, type ScoringResult as K, type LearnerResponse as L, type MediaPlaybackPolicy as M, type NativeControlHint as N, type TextMatchResult as O, type ValidationResult as P, type WrittenResponseLearnerResponse as Q, type WrittenResponseRubric as R, type ScoringDetail as S, type TextMatchPolicy as T, type WrittenResponseRubricCriterion as U, type ValidationError as V, type WrittenResponseData as W, type XAPIActor as X, type XAPIConfig as Y, type XAPIContext as Z, type XAPIContextActivities as _, type ActivityDataMap as a, type XAPIObject as a0, type XAPIResult as a1, type XAPIScore as a2, type XAPIStatement as a3, type XAPIVerbObject as a4, levenshteinDistance as a5, matchText as a6, type ActivityFeedback as b, type ActivityMedia as c, type ActivityResult as d, type ActivityType as e, type DictationData as f, type DictationEquivalence as g, type DictationLearnerResponse as h, type DictationSlowMedia as i, type DictationTolerance as j, type FillInTheBlanksLearnerResponse as k, type GapSelectChoice as l, type GapSelectData as m, type GapSelectGap as n, type GapSelectLearnerResponse as o, type GradeRecord as p, type Grader as q, type GraderKind as r, type GraderUsage as s, type GradingState as t, type InteractionEvent as u, type InteractionKind as v, type ItemOutcome as w, type LearnerResponseMap as x, type MultipleChoiceData as y, type MultipleChoiceLearnerResponse as z };
|
|
@@ -360,6 +360,7 @@ interface ActivityDataMap {
|
|
|
360
360
|
'fill-in-the-blanks': FillInTheBlanksData;
|
|
361
361
|
'written-response': WrittenResponseData;
|
|
362
362
|
'gap-select': GapSelectData;
|
|
363
|
+
dictation: DictationData;
|
|
363
364
|
}
|
|
364
365
|
/**
|
|
365
366
|
* The set of activity types supported by learning-kit. Derived from
|
|
@@ -782,6 +783,108 @@ interface WrittenResponseData {
|
|
|
782
783
|
/** Subjective difficulty on a 1–5 scale. */
|
|
783
784
|
difficultyLevel?: 1 | 2 | 3 | 4 | 5;
|
|
784
785
|
}
|
|
786
|
+
/**
|
|
787
|
+
* A second, slower recording of a dictation — a separate file (a text-to-speech
|
|
788
|
+
* render at reduced speed, or a slower human reading), not a `playbackRate`
|
|
789
|
+
* change. It carries no `captionsUrl` (a caption track of a dictation is the
|
|
790
|
+
* transcript on screen) and no `playback` policy of its own: it follows the
|
|
791
|
+
* policy on `media`, except the play budget, which it never has.
|
|
792
|
+
*/
|
|
793
|
+
interface DictationSlowMedia {
|
|
794
|
+
type: 'audio';
|
|
795
|
+
/** Source URL, under the same policy as {@link ActivityMedia.url}. */
|
|
796
|
+
url: string;
|
|
797
|
+
/** Accessible label — a description ("Recording, slow"), never a transcription. */
|
|
798
|
+
alt?: string;
|
|
799
|
+
}
|
|
800
|
+
/**
|
|
801
|
+
* A whole-word rewrite applied to BOTH the transcript and the attempt before
|
|
802
|
+
* they are compared. `from` and `to` are literal text: a rule is applied to
|
|
803
|
+
* every whole-word occurrence, exactly once, in the order the rules are listed,
|
|
804
|
+
* after spacing is collapsed and before punctuation is ignored — so a rule may
|
|
805
|
+
* name a symbol (`{ from: '&', to: 'and' }`) and a multi-word `from` matches
|
|
806
|
+
* across any whitespace.
|
|
807
|
+
*/
|
|
808
|
+
interface DictationEquivalence {
|
|
809
|
+
/** What to rewrite: at least one code point that survives case, quote and whitespace folding. */
|
|
810
|
+
from: string;
|
|
811
|
+
/** What it becomes: 1..200 code points, something of which survives normalisation. A rule cannot delete a word. */
|
|
812
|
+
to: string;
|
|
813
|
+
}
|
|
814
|
+
/** Grading tolerances for a dictation. Part of the answer key. */
|
|
815
|
+
interface DictationTolerance {
|
|
816
|
+
/** Whole-word rewrites, applied in listed order, each exactly once. */
|
|
817
|
+
equivalences?: DictationEquivalence[];
|
|
818
|
+
}
|
|
819
|
+
/**
|
|
820
|
+
* Data contract for a Dictation activity: the learner listens to a recording
|
|
821
|
+
* and types what they hear; the grade is how close their text is to the
|
|
822
|
+
* transcript.
|
|
823
|
+
*
|
|
824
|
+
* Scoring is character-level similarity over the whole sentence —
|
|
825
|
+
* `(length − edit distance) / length` over NFC code points after case,
|
|
826
|
+
* punctuation and spacing are ignored — with one {@link ScoringDetail} per
|
|
827
|
+
* transcript word carrying that word's own {@link ScoringDetail.score}. It is
|
|
828
|
+
* deliberately not a mode of {@link FillInTheBlanksData}: a blank is right or
|
|
829
|
+
* wrong, a dictation is graded on a continuum, and the whole `TextMatchPolicy`
|
|
830
|
+
* surface (typo tolerance, diacritic folding) would be a second, competing
|
|
831
|
+
* notion of "close enough".
|
|
832
|
+
*/
|
|
833
|
+
interface DictationData {
|
|
834
|
+
schemaVersion: '1.0';
|
|
835
|
+
type: 'dictation';
|
|
836
|
+
/** Unique identifier for this activity. */
|
|
837
|
+
id: string;
|
|
838
|
+
/**
|
|
839
|
+
* Human-readable title used in xAPI statements and error boundaries. It is
|
|
840
|
+
* the stem the learner sees, so it must not contain the transcript.
|
|
841
|
+
*/
|
|
842
|
+
title: string;
|
|
843
|
+
/**
|
|
844
|
+
* What the learner is expected to type. ANSWER KEY. 1..2000 code points,
|
|
845
|
+
* before and after its equivalences are applied, and something must survive
|
|
846
|
+
* normalisation.
|
|
847
|
+
*/
|
|
848
|
+
transcript: string;
|
|
849
|
+
/**
|
|
850
|
+
* Alternative transcriptions accepted at full credit — a regional spelling, a
|
|
851
|
+
* numeral, a whole-sentence contraction variant. ANSWER KEY. At most 10, each
|
|
852
|
+
* 1..2000 code points, none normalising equal to the transcript or to each
|
|
853
|
+
* other. The attempt is scored against every candidate and the best
|
|
854
|
+
* similarity wins; a tie goes to `transcript`.
|
|
855
|
+
*/
|
|
856
|
+
acceptedTranscripts?: string[];
|
|
857
|
+
/**
|
|
858
|
+
* The recording. Audio only, never with captions. Optional in the schema — a
|
|
859
|
+
* dictation inside an item group may draw on the group's stimulus recording —
|
|
860
|
+
* but required whenever `slowMedia` is present. Budgeted per slot like any
|
|
861
|
+
* other activity media, with the usual playback policy.
|
|
862
|
+
*/
|
|
863
|
+
media?: ActivityMedia;
|
|
864
|
+
/** A second, slower recording. See {@link DictationSlowMedia}. */
|
|
865
|
+
slowMedia?: DictationSlowMedia;
|
|
866
|
+
/**
|
|
867
|
+
* Progressive word hints, in `practice` only (the transcript is absent in
|
|
868
|
+
* `exam` mode, so there is nothing to reveal). Public: it reveals nothing by
|
|
869
|
+
* itself. `progressive-words` reveals the transcript's words left to right,
|
|
870
|
+
* one per request; a revealed hint never changes the score.
|
|
871
|
+
*/
|
|
872
|
+
hints?: {
|
|
873
|
+
mode: 'progressive-words';
|
|
874
|
+
};
|
|
875
|
+
/** Grading tolerances. ANSWER KEY. */
|
|
876
|
+
tolerance?: DictationTolerance;
|
|
877
|
+
/** Optional authored overall feedback shown after submission. */
|
|
878
|
+
feedback?: ActivityFeedback;
|
|
879
|
+
/** Minimum scaled score [0–1] required to pass. Defaults to {@link DEFAULT_PASS_THRESHOLD} (0.7) when absent. */
|
|
880
|
+
passThreshold?: number;
|
|
881
|
+
/** BCP 47 language tag for the activity content. Presentation only: scoring never reads it. */
|
|
882
|
+
locale?: string;
|
|
883
|
+
/** IRI references to learning objectives addressed by this activity. */
|
|
884
|
+
learningObjectives?: string[];
|
|
885
|
+
/** Subjective difficulty on a 1–5 scale. */
|
|
886
|
+
difficultyLevel?: 1 | 2 | 3 | 4 | 5;
|
|
887
|
+
}
|
|
785
888
|
/**
|
|
786
889
|
* Maps each ActivityType string to its learner-response shape. Open for
|
|
787
890
|
* extension via module augmentation, mirroring {@link ActivityDataMap}.
|
|
@@ -791,6 +894,7 @@ interface LearnerResponseMap {
|
|
|
791
894
|
'fill-in-the-blanks': FillInTheBlanksLearnerResponse;
|
|
792
895
|
'written-response': WrittenResponseLearnerResponse;
|
|
793
896
|
'gap-select': GapSelectLearnerResponse;
|
|
897
|
+
dictation: DictationLearnerResponse;
|
|
794
898
|
}
|
|
795
899
|
/** Union of all learner response shapes. */
|
|
796
900
|
type LearnerResponse = LearnerResponseMap[keyof LearnerResponseMap];
|
|
@@ -828,18 +932,34 @@ interface WrittenResponseLearnerResponse {
|
|
|
828
932
|
/** Word count of `text`, computed with the canonical `countWords()` helper. */
|
|
829
933
|
wordCount: number;
|
|
830
934
|
}
|
|
935
|
+
/**
|
|
936
|
+
* Learner response for a Dictation activity.
|
|
937
|
+
*
|
|
938
|
+
* `text` is exactly what the learner typed; every normalisation happens in the
|
|
939
|
+
* scorer. `hintsRevealed` is client-reported telemetry — how many hint words
|
|
940
|
+
* were shown before submitting — that the scorer ignores and a consumer may
|
|
941
|
+
* log or penalise, knowing it cannot be verified.
|
|
942
|
+
*/
|
|
943
|
+
interface DictationLearnerResponse {
|
|
944
|
+
type: 'dictation';
|
|
945
|
+
/** The learner's text, as typed. */
|
|
946
|
+
text: string;
|
|
947
|
+
/** Hint words revealed before submitting (practice only). Absent or 0 means none. */
|
|
948
|
+
hintsRevealed?: number;
|
|
949
|
+
}
|
|
831
950
|
/**
|
|
832
951
|
* Fine-grained outcome of the learner's action on a single item, replacing the
|
|
833
952
|
* ambiguous {@link ScoringDetail.correct}:
|
|
834
953
|
* - `correct` — the learner selected/entered the right answer.
|
|
835
954
|
* - `incorrect` — the learner selected/entered a wrong answer.
|
|
836
955
|
* - `correct-omission` — the learner correctly left a non-answer unselected (multiple-choice only).
|
|
837
|
-
* - `incorrect-omission` —
|
|
956
|
+
* - `incorrect-omission` — a correct answer the learner did not give: an unselected
|
|
957
|
+
* correct option, an unanswered gap, a missing dictation word.
|
|
838
958
|
*/
|
|
839
959
|
type ScoringOutcome = 'correct' | 'incorrect' | 'correct-omission' | 'incorrect-omission';
|
|
840
960
|
/** Per-item scoring breakdown returned by the scoring engine. */
|
|
841
961
|
interface ScoringDetail {
|
|
842
|
-
/** ID of the option or
|
|
962
|
+
/** ID of the option, blank, gap or dictation word (`w1`…`wN`) this detail refers to. */
|
|
843
963
|
itemId: string;
|
|
844
964
|
/**
|
|
845
965
|
* @deprecated Ambiguous: for multiple-choice this means "the learner acted
|
|
@@ -852,8 +972,8 @@ interface ScoringDetail {
|
|
|
852
972
|
/**
|
|
853
973
|
* Unambiguous outcome of the learner's action on this item. Optional in the
|
|
854
974
|
* type so 0.2-era consumer-constructed literals keep compiling, but ALWAYS
|
|
855
|
-
* written by
|
|
856
|
-
* when the deprecated `correct` is removed.
|
|
975
|
+
* written by every built-in scorer (by the first two since 0.3.0); becomes
|
|
976
|
+
* required in v1.0 when the deprecated `correct` is removed.
|
|
857
977
|
*/
|
|
858
978
|
outcome?: ScoringOutcome;
|
|
859
979
|
/** The learner's actual response for this item. */
|
|
@@ -861,10 +981,17 @@ interface ScoringDetail {
|
|
|
861
981
|
/** The expected correct response(s) for this item. */
|
|
862
982
|
correctResponse: string | string[];
|
|
863
983
|
/**
|
|
864
|
-
* Weight applied to this item's contribution to the overall score.
|
|
865
|
-
* built-in
|
|
984
|
+
* Weight applied to this item's contribution to the overall score. Every
|
|
985
|
+
* built-in scorer currently weights every item equally and writes `1`.
|
|
866
986
|
*/
|
|
867
987
|
weight?: number;
|
|
988
|
+
/**
|
|
989
|
+
* The item's own scaled score in [0, 1], for a type that grades its items on
|
|
990
|
+
* a continuum rather than right or wrong. Written by the dictation scorer
|
|
991
|
+
* (the similarity of each transcript word to what was typed for it) and by
|
|
992
|
+
* nothing else today. Absent, an item is right or wrong: read `outcome`.
|
|
993
|
+
*/
|
|
994
|
+
score?: number;
|
|
868
995
|
}
|
|
869
996
|
/** Full scoring result returned by the scoring engine. */
|
|
870
997
|
interface ScoringResult {
|
|
@@ -1020,4 +1147,4 @@ interface InteractionEvent {
|
|
|
1020
1147
|
payload: Record<string, unknown>;
|
|
1021
1148
|
}
|
|
1022
1149
|
|
|
1023
|
-
export {
|
|
1150
|
+
export { type XAPIError as $, type ActivityData as A, type BlankConfig as B, type CriterionScore as C, type DeferredScoringPartial as D, type MultipleChoiceOption as E, type FillInTheBlanksData as F, type GapSelectBank as G, type MultipleChoiceOptionMedia as H, type InlineCorrection as I, type ScoringOutcome as J, type ScoringResult as K, type LearnerResponse as L, type MediaPlaybackPolicy as M, type NativeControlHint as N, type TextMatchResult as O, type ValidationResult as P, type WrittenResponseLearnerResponse as Q, type WrittenResponseRubric as R, type ScoringDetail as S, type TextMatchPolicy as T, type WrittenResponseRubricCriterion as U, type ValidationError as V, type WrittenResponseData as W, type XAPIActor as X, type XAPIConfig as Y, type XAPIContext as Z, type XAPIContextActivities as _, type ActivityDataMap as a, type XAPIObject as a0, type XAPIResult as a1, type XAPIScore as a2, type XAPIStatement as a3, type XAPIVerbObject as a4, levenshteinDistance as a5, matchText as a6, type ActivityFeedback as b, type ActivityMedia as c, type ActivityResult as d, type ActivityType as e, type DictationData as f, type DictationEquivalence as g, type DictationLearnerResponse as h, type DictationSlowMedia as i, type DictationTolerance as j, type FillInTheBlanksLearnerResponse as k, type GapSelectChoice as l, type GapSelectData as m, type GapSelectGap as n, type GapSelectLearnerResponse as o, type GradeRecord as p, type Grader as q, type GraderKind as r, type GraderUsage as s, type GradingState as t, type InteractionEvent as u, type InteractionKind as v, type ItemOutcome as w, type LearnerResponseMap as x, type MultipleChoiceData as y, type MultipleChoiceLearnerResponse as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
@@ -7,7 +7,10 @@
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
var _chunkXONKWL6Dcjs = require('./chunk-XONKWL6D.cjs');
|
|
11
14
|
|
|
12
15
|
// src/schemas/item-group.ts
|
|
13
16
|
var _v4 = require('zod/v4');
|
|
@@ -35,7 +38,7 @@ var StimulusSchema = _v4.z.looseObject({
|
|
|
35
38
|
title: _v4.z.string().optional(),
|
|
36
39
|
body: _v4.z.string().optional(),
|
|
37
40
|
bodyHtml: _v4.z.string().optional(),
|
|
38
|
-
media:
|
|
41
|
+
media: _chunkXONKWL6Dcjs.MediaSchema.optional(),
|
|
39
42
|
transcript: _v4.z.string().optional(),
|
|
40
43
|
locale: _v4.z.string().optional(),
|
|
41
44
|
attribution: _v4.z.string().optional()
|
|
@@ -85,7 +88,7 @@ var RedactedStimulusSchema = _v4.z.strictObject({
|
|
|
85
88
|
title: _v4.z.string().optional(),
|
|
86
89
|
body: _v4.z.string().optional(),
|
|
87
90
|
bodyHtml: _v4.z.string().optional(),
|
|
88
|
-
media:
|
|
91
|
+
media: _chunkXONKWL6Dcjs.RedactedMediaSchema.optional(),
|
|
89
92
|
locale: _v4.z.string().optional(),
|
|
90
93
|
attribution: _v4.z.string().optional()
|
|
91
94
|
});
|
|
@@ -99,6 +102,15 @@ var RedactedItemGroupSchema = _v4.z.strictObject({
|
|
|
99
102
|
stimulus: RedactedStimulusSchema,
|
|
100
103
|
items: _v4.z.array(_v4.z.unknown()).min(1),
|
|
101
104
|
shuffle: _v4.z.enum(["none", "within-group"]).optional()
|
|
105
|
+
}).check((ctx) => {
|
|
106
|
+
if (_chunkXONKWL6Dcjs.groupCaptionsRevealDictation.call(void 0, ctx.value)) {
|
|
107
|
+
ctx.issues.push({
|
|
108
|
+
code: "custom",
|
|
109
|
+
input: _optionalChain([ctx, 'access', _ => _.value, 'access', _2 => _2.stimulus, 'access', _3 => _3.media, 'optionalAccess', _4 => _4.captionsUrl]),
|
|
110
|
+
message: _chunkXONKWL6Dcjs.GROUP_CAPTIONS_REVEAL_DICTATION,
|
|
111
|
+
path: ["stimulus", "media", "captionsUrl"]
|
|
112
|
+
});
|
|
113
|
+
}
|
|
102
114
|
});
|
|
103
115
|
function toValidationErrors(issues, prefix) {
|
|
104
116
|
return issues.map((issue) => ({
|
|
@@ -115,7 +127,7 @@ function validateItemGroup(data) {
|
|
|
115
127
|
const errors = [];
|
|
116
128
|
const items = [];
|
|
117
129
|
container.data.items.forEach((item, index) => {
|
|
118
|
-
const descriptor =
|
|
130
|
+
const descriptor = _chunkXONKWL6Dcjs.getActivityTypeDescriptor.call(void 0, item.type);
|
|
119
131
|
if (descriptor === void 0) {
|
|
120
132
|
errors.push({
|
|
121
133
|
path: ["items", String(index), "type"],
|
|
@@ -131,6 +143,13 @@ function validateItemGroup(data) {
|
|
|
131
143
|
}
|
|
132
144
|
items.push(parsed.data);
|
|
133
145
|
});
|
|
146
|
+
if (_chunkXONKWL6Dcjs.groupCaptionsRevealDictation.call(void 0, container.data)) {
|
|
147
|
+
errors.push({
|
|
148
|
+
path: ["stimulus", "media", "captionsUrl"],
|
|
149
|
+
message: _chunkXONKWL6Dcjs.GROUP_CAPTIONS_REVEAL_DICTATION,
|
|
150
|
+
code: "custom"
|
|
151
|
+
});
|
|
152
|
+
}
|
|
134
153
|
if (errors.length > 0) {
|
|
135
154
|
return { success: false, errors };
|
|
136
155
|
}
|
|
@@ -141,31 +160,34 @@ function validateItemGroup(data) {
|
|
|
141
160
|
|
|
142
161
|
var stimulusJsonSchema = _v4.z.toJSONSchema(StimulusSchema, { target: "draft-7" });
|
|
143
162
|
var itemGroupJsonSchema = _v4.z.toJSONSchema(ItemGroupSchema, { target: "draft-7" });
|
|
144
|
-
var gapSelectJsonSchema = _v4.z.toJSONSchema(
|
|
163
|
+
var gapSelectJsonSchema = _v4.z.toJSONSchema(_chunkXONKWL6Dcjs.GapSelectDataSchema, {
|
|
164
|
+
target: "draft-7"
|
|
165
|
+
});
|
|
166
|
+
var dictationJsonSchema = _v4.z.toJSONSchema(_chunkXONKWL6Dcjs.DictationDataSchema, {
|
|
145
167
|
target: "draft-7"
|
|
146
168
|
});
|
|
147
|
-
var multipleChoiceJsonSchema = _v4.z.toJSONSchema(
|
|
169
|
+
var multipleChoiceJsonSchema = _v4.z.toJSONSchema(_chunkXONKWL6Dcjs.MultipleChoiceDataSchema, {
|
|
148
170
|
target: "draft-7"
|
|
149
171
|
});
|
|
150
|
-
var fillInTheBlanksJsonSchema = _v4.z.toJSONSchema(
|
|
172
|
+
var fillInTheBlanksJsonSchema = _v4.z.toJSONSchema(_chunkXONKWL6Dcjs.FillInTheBlanksDataSchema, {
|
|
151
173
|
target: "draft-7"
|
|
152
174
|
});
|
|
153
|
-
var writtenResponseJsonSchema = _v4.z.toJSONSchema(
|
|
175
|
+
var writtenResponseJsonSchema = _v4.z.toJSONSchema(_chunkXONKWL6Dcjs.WrittenResponseDataSchema, {
|
|
154
176
|
target: "draft-7"
|
|
155
177
|
});
|
|
156
178
|
function jsonSchemaFor(type) {
|
|
157
|
-
const descriptor =
|
|
179
|
+
const descriptor = _chunkXONKWL6Dcjs.getActivityTypeDescriptor.call(void 0, type);
|
|
158
180
|
if (descriptor === void 0) {
|
|
159
|
-
throw new (0,
|
|
181
|
+
throw new (0, _chunkXONKWL6Dcjs.UnknownActivityTypeError)(type);
|
|
160
182
|
}
|
|
161
183
|
return _v4.z.toJSONSchema(descriptor.schema, { target: "draft-7" });
|
|
162
184
|
}
|
|
163
185
|
|
|
164
186
|
// src/schemas/index.ts
|
|
165
187
|
function validateActivity(type, data) {
|
|
166
|
-
const descriptor =
|
|
188
|
+
const descriptor = _chunkXONKWL6Dcjs.getActivityTypeDescriptor.call(void 0, type);
|
|
167
189
|
if (descriptor === void 0) {
|
|
168
|
-
throw new (0,
|
|
190
|
+
throw new (0, _chunkXONKWL6Dcjs.UnknownActivityTypeError)(String(type));
|
|
169
191
|
}
|
|
170
192
|
const result = descriptor.schema.safeParse(data);
|
|
171
193
|
if (result.success) {
|
|
@@ -195,5 +217,6 @@ function validateActivity(type, data) {
|
|
|
195
217
|
|
|
196
218
|
|
|
197
219
|
|
|
198
|
-
|
|
199
|
-
|
|
220
|
+
|
|
221
|
+
exports.StimulusSchema = StimulusSchema; exports.ItemGroupSchema = ItemGroupSchema; exports.RedactedStimulusSchema = RedactedStimulusSchema; exports.RedactedItemGroupSchema = RedactedItemGroupSchema; exports.validateItemGroup = validateItemGroup; exports.stimulusJsonSchema = stimulusJsonSchema; exports.itemGroupJsonSchema = itemGroupJsonSchema; exports.gapSelectJsonSchema = gapSelectJsonSchema; exports.dictationJsonSchema = dictationJsonSchema; exports.multipleChoiceJsonSchema = multipleChoiceJsonSchema; exports.fillInTheBlanksJsonSchema = fillInTheBlanksJsonSchema; exports.writtenResponseJsonSchema = writtenResponseJsonSchema; exports.jsonSchemaFor = jsonSchemaFor; exports.validateActivity = validateActivity;
|
|
222
|
+
//# sourceMappingURL=chunk-DQKJUMUW.cjs.map
|