@conform-ed/qti-react 0.0.15 → 0.0.17
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/dist/index.d.ts +6 -4
- package/dist/index.js +2486 -405
- package/dist/normalized-item.d.ts +7 -5
- package/dist/pnp.d.ts +115 -0
- package/dist/response-validity.d.ts +28 -0
- package/dist/rp/evaluate.d.ts +6 -1
- package/dist/rp/index.d.ts +2 -2
- package/dist/rp/interpreter.d.ts +7 -1
- package/dist/rp/lookup-table.d.ts +17 -0
- package/dist/rp/template-processing.d.ts +5 -0
- package/dist/rp/types.d.ts +71 -7
- package/dist/runtime.d.ts +95 -0
- package/dist/store.d.ts +47 -0
- package/dist/test/controller.d.ts +22 -0
- package/dist/test/index.d.ts +2 -1
- package/dist/test/results.d.ts +102 -0
- package/dist/test/session-store.d.ts +32 -0
- package/dist/test/types.d.ts +173 -5
- package/dist/types.d.ts +5 -0
- package/package.json +7 -2
- package/src/content-model.ts +44 -4
- package/src/index.ts +43 -1
- package/src/normalized-item.ts +106 -4
- package/src/pnp.ts +333 -0
- package/src/reference-skin/choice.ts +3 -0
- package/src/response-validity.ts +163 -0
- package/src/rp/evaluate.ts +280 -32
- package/src/rp/index.ts +5 -0
- package/src/rp/interpreter.ts +81 -1
- package/src/rp/lookup-table.ts +46 -0
- package/src/rp/template-processing.ts +41 -0
- package/src/rp/types.ts +75 -7
- package/src/runtime.ts +397 -20
- package/src/store.ts +146 -8
- package/src/test/controller.ts +856 -82
- package/src/test/index.ts +23 -0
- package/src/test/results.ts +378 -0
- package/src/test/session-store.ts +109 -1
- package/src/test/types.ts +172 -5
- package/src/types.ts +1 -0
- package/src/xspattern.d.ts +11 -0
|
@@ -118,6 +118,19 @@ export function executeTemplateProcessing(
|
|
|
118
118
|
lookupVariable: (identifier) => templateValues.get(identifier) ?? null,
|
|
119
119
|
responseDeclaration: (identifier) => responseDeclarationsById.get(identifier),
|
|
120
120
|
responseValue: () => null, // no candidate responses exist at template-processing time
|
|
121
|
+
variableDefault: (identifier) => {
|
|
122
|
+
const declaration = declarationsById.get(identifier) ?? responseDeclarationsById.get(identifier);
|
|
123
|
+
|
|
124
|
+
if (!declaration?.defaultValue) {
|
|
125
|
+
return null; // "NULL if no default value was declared" (§2.11.1.3)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return rpValue(
|
|
129
|
+
declaration.cardinality,
|
|
130
|
+
declaration.defaultValue.values.map((entry) => coerceScalar(entry.value, declaration.baseType)),
|
|
131
|
+
declaration.baseType,
|
|
132
|
+
);
|
|
133
|
+
},
|
|
121
134
|
random: mulberry32(context.seed),
|
|
122
135
|
customOperators: context.customOperators,
|
|
123
136
|
};
|
|
@@ -229,6 +242,34 @@ export function executeTemplateProcessing(
|
|
|
229
242
|
};
|
|
230
243
|
}
|
|
231
244
|
|
|
245
|
+
/**
|
|
246
|
+
* The effective template declarations for a clone: test-level `templateDefault`
|
|
247
|
+
* values (§5.152) replace the declared defaults. A NULL value clears the default.
|
|
248
|
+
*/
|
|
249
|
+
export function applyTemplateDefaultOverrides(
|
|
250
|
+
declarations: readonly TemplateDeclarationView[],
|
|
251
|
+
overrides: Readonly<Record<string, OutcomeValue>>,
|
|
252
|
+
): readonly TemplateDeclarationView[] {
|
|
253
|
+
return declarations.map((declaration) => {
|
|
254
|
+
if (!(declaration.identifier in overrides)) {
|
|
255
|
+
return declaration;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const value = overrides[declaration.identifier];
|
|
259
|
+
|
|
260
|
+
if (value === null || value === undefined) {
|
|
261
|
+
const { defaultValue: _cleared, ...rest } = declaration;
|
|
262
|
+
|
|
263
|
+
return rest;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return {
|
|
267
|
+
...declaration,
|
|
268
|
+
defaultValue: { values: (Array.isArray(value) ? value : [value]).map((member) => ({ value: member })) },
|
|
269
|
+
};
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
|
|
232
273
|
/** The effective response declarations for a clone: setCorrectResponse overrides applied. */
|
|
233
274
|
export function applyCorrectResponseOverrides(
|
|
234
275
|
declarations: readonly ResponseDeclarationView[],
|
package/src/rp/types.ts
CHANGED
|
@@ -32,11 +32,53 @@ export interface RpValue {
|
|
|
32
32
|
|
|
33
33
|
export type MaybeRpValue = RpValue | null;
|
|
34
34
|
|
|
35
|
+
/** One matchTable row: exact integer source → target (§7.23). */
|
|
36
|
+
export interface MatchTableEntryView {
|
|
37
|
+
readonly sourceValue: number;
|
|
38
|
+
readonly targetValue: RpScalar;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* "A matchTable transforms a source integer by finding the first
|
|
43
|
+
* qti-match-table-entry with an exact match to the source." (§5.90)
|
|
44
|
+
*/
|
|
45
|
+
export interface MatchTableView {
|
|
46
|
+
/** "The default outcome value to be used when no matching table entry is found.
|
|
47
|
+
* If omitted, the NULL value is used." (§5.90.1) */
|
|
48
|
+
readonly defaultValue?: RpScalar;
|
|
49
|
+
readonly matchTableEntries: readonly MatchTableEntryView[];
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** One interpolationTable row; sourceValue is "the lower bound … to match this entry" (§7.18.1). */
|
|
53
|
+
export interface InterpolationTableEntryView {
|
|
54
|
+
readonly sourceValue: number;
|
|
55
|
+
readonly targetValue: RpScalar;
|
|
56
|
+
/** "If 'true', the default, then an exact match of the value is considered a match
|
|
57
|
+
* of this entry." (§7.18.2) */
|
|
58
|
+
readonly includeBoundary?: boolean;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* "An interpolationTable transforms a source float (or integer) by finding the first
|
|
63
|
+
* interpolationTableEntry with a sourceValue that is less than or equal to (subject
|
|
64
|
+
* to includeBoundary) the source value." (§5.78)
|
|
65
|
+
*/
|
|
66
|
+
export interface InterpolationTableView {
|
|
67
|
+
readonly defaultValue?: RpScalar;
|
|
68
|
+
readonly interpolationTableEntries: readonly InterpolationTableEntryView[];
|
|
69
|
+
}
|
|
70
|
+
|
|
35
71
|
export interface OutcomeDeclarationView {
|
|
36
72
|
readonly identifier: string;
|
|
37
73
|
readonly cardinality: Cardinality;
|
|
38
74
|
readonly baseType?: string;
|
|
39
75
|
readonly defaultValue?: { readonly values: ReadonlyArray<{ readonly value: RpScalar }> };
|
|
76
|
+
/** The declaration's lookupTable (at most one of the two), read by `lookupOutcomeValue` (§5.87). */
|
|
77
|
+
readonly matchTable?: MatchTableView;
|
|
78
|
+
readonly interpolationTable?: InterpolationTableView;
|
|
79
|
+
/** Declared score bounds, aggregated by `outcomeMaximum`/`outcomeMinimum` (§2.11.2.6-7). */
|
|
80
|
+
readonly normalMaximum?: number;
|
|
81
|
+
readonly normalMinimum?: number;
|
|
40
82
|
}
|
|
41
83
|
|
|
42
84
|
/**
|
|
@@ -49,11 +91,14 @@ export interface RpExpressionView {
|
|
|
49
91
|
readonly baseType?: string;
|
|
50
92
|
readonly value?: RpScalar;
|
|
51
93
|
readonly expressions?: readonly RpExpressionView[];
|
|
52
|
-
/**
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Bounds/step for the random operators and `anyN`; string values are variable
|
|
96
|
+
* references resolved at runtime (§2.11.3.6), bare or brace-enclosed (§7.13).
|
|
97
|
+
*/
|
|
98
|
+
readonly min?: number | string;
|
|
99
|
+
readonly max?: number | string;
|
|
100
|
+
readonly step?: number | string;
|
|
101
|
+
/** `equal` tolerance window; string entries are variable references. */
|
|
57
102
|
readonly toleranceMode?: "exact" | "absolute" | "relative";
|
|
58
103
|
readonly tolerance?: ReadonlyArray<number | string>;
|
|
59
104
|
readonly includeLowerBound?: boolean;
|
|
@@ -67,14 +112,18 @@ export interface RpExpressionView {
|
|
|
67
112
|
readonly figures?: number | string;
|
|
68
113
|
/** Pass count for `repeat`. */
|
|
69
114
|
readonly numberRepeats?: number | string;
|
|
115
|
+
/** XSD-dialect pattern for `patternMatch`; "{ref}" resolves from a variable (§7.13). */
|
|
116
|
+
readonly pattern?: string;
|
|
70
117
|
/** String comparison controls for `stringMatch` and `substring`. */
|
|
71
118
|
readonly caseSensitive?: boolean;
|
|
72
119
|
readonly substring?: boolean;
|
|
73
120
|
/** Area for `inside` (QTI shape + coords string). */
|
|
74
121
|
readonly shape?: string;
|
|
75
122
|
readonly coords?: string;
|
|
76
|
-
/** Test-level subset selection (`testVariables`
|
|
123
|
+
/** Test-level subset selection (`testVariables`, `outcomeMinimum`/`outcomeMaximum`, `number*`). */
|
|
77
124
|
readonly variableIdentifier?: string;
|
|
125
|
+
/** Outcome variable whose declared bounds `outcomeMinimum`/`outcomeMaximum` look up (§7.28.4). */
|
|
126
|
+
readonly outcomeIdentifier?: string;
|
|
78
127
|
readonly weightIdentifier?: string;
|
|
79
128
|
readonly sectionIdentifier?: string;
|
|
80
129
|
readonly includeCategory?: string | readonly string[];
|
|
@@ -103,11 +152,16 @@ export interface RpConditionBranch {
|
|
|
103
152
|
readonly rules: readonly RpRuleView[];
|
|
104
153
|
}
|
|
105
154
|
|
|
106
|
-
/**
|
|
155
|
+
/**
|
|
156
|
+
* One response rule: responseCondition, setOutcomeValue, lookupOutcomeValue,
|
|
157
|
+
* responseProcessingFragment, or exitResponse.
|
|
158
|
+
*/
|
|
107
159
|
export interface RpRuleView {
|
|
108
160
|
readonly kind: string;
|
|
109
161
|
readonly identifier?: string;
|
|
110
162
|
readonly expression?: RpExpressionView;
|
|
163
|
+
/** Nested rules of a `responseProcessingFragment` (§5.118). */
|
|
164
|
+
readonly rules?: readonly RpRuleView[];
|
|
111
165
|
readonly responseIf?: RpConditionBranch;
|
|
112
166
|
readonly responseElseIfs?: readonly RpConditionBranch[];
|
|
113
167
|
readonly responseElse?: { readonly rules: readonly RpRuleView[] };
|
|
@@ -156,6 +210,20 @@ export interface ResponseProcessingContext {
|
|
|
156
210
|
* submission sequence then replays the exact same outcomes (ADR-0004 determinism).
|
|
157
211
|
*/
|
|
158
212
|
readonly random?: (() => number) | undefined;
|
|
213
|
+
/**
|
|
214
|
+
* Built-in session variables (reserved identifiers; items must not declare them).
|
|
215
|
+
* `duration` is the item session's elapsed seconds; `numAttempts` "increases by 1
|
|
216
|
+
* at the start of each attempt", so it includes the attempt being scored.
|
|
217
|
+
*/
|
|
218
|
+
readonly duration?: number | undefined;
|
|
219
|
+
readonly numAttempts?: number | undefined;
|
|
220
|
+
/**
|
|
221
|
+
* The session's current `completionStatus` — the third built-in, "declared
|
|
222
|
+
* implicitly"; it enters the outcome map (defaulting to "not_attempted") so
|
|
223
|
+
* `setOutcomeValue` can change it (§2.2.2.3). An explicit declaration (legacy
|
|
224
|
+
* content) wins over this value.
|
|
225
|
+
*/
|
|
226
|
+
readonly completionStatus?: string | undefined;
|
|
159
227
|
/** Registered vendor `customOperator` implementations by class (opt-in). */
|
|
160
228
|
readonly customOperators?: Readonly<Record<string, CustomOperatorImplementation>> | undefined;
|
|
161
229
|
}
|