@longsightgroup/qti3-core 0.9.0 → 0.9.2

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.
Files changed (51) hide show
  1. package/README.md +39 -0
  2. package/dist/adaptive-turn-materializer.d.ts +14 -0
  3. package/dist/adaptive-turn-materializer.d.ts.map +1 -0
  4. package/dist/adaptive-turn-materializer.js +56 -0
  5. package/dist/adaptive-turn-materializer.js.map +1 -0
  6. package/dist/adaptive-turn.d.ts +23 -0
  7. package/dist/adaptive-turn.d.ts.map +1 -0
  8. package/dist/adaptive-turn.js +60 -0
  9. package/dist/adaptive-turn.js.map +1 -0
  10. package/dist/asset-url.d.ts.map +1 -1
  11. package/dist/asset-url.js +1 -0
  12. package/dist/asset-url.js.map +1 -1
  13. package/dist/delivery-redaction.d.ts +50 -0
  14. package/dist/delivery-redaction.d.ts.map +1 -0
  15. package/dist/delivery-redaction.js +176 -0
  16. package/dist/delivery-redaction.js.map +1 -0
  17. package/dist/delivery-security.d.ts +3 -18
  18. package/dist/delivery-security.d.ts.map +1 -1
  19. package/dist/delivery-security.js +35 -189
  20. package/dist/delivery-security.js.map +1 -1
  21. package/dist/index.d.ts +2 -1
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +1 -0
  24. package/dist/index.js.map +1 -1
  25. package/dist/server-scoring.d.ts +4 -14
  26. package/dist/server-scoring.d.ts.map +1 -1
  27. package/dist/server-scoring.js +19 -157
  28. package/dist/server-scoring.js.map +1 -1
  29. package/dist/shared-vocabulary-support.d.ts.map +1 -1
  30. package/dist/shared-vocabulary-support.js +1 -0
  31. package/dist/shared-vocabulary-support.js.map +1 -1
  32. package/dist/support.d.ts.map +1 -1
  33. package/dist/support.js +8 -4
  34. package/dist/support.js.map +1 -1
  35. package/dist/trusted-item-session.d.ts +49 -0
  36. package/dist/trusted-item-session.d.ts.map +1 -0
  37. package/dist/trusted-item-session.js +260 -0
  38. package/dist/trusted-item-session.js.map +1 -0
  39. package/package.json +4 -2
  40. package/src/adaptive-turn-materializer.ts +85 -0
  41. package/src/adaptive-turn.ts +109 -0
  42. package/src/asset-url.ts +1 -0
  43. package/src/delivery-redaction.ts +268 -0
  44. package/src/delivery-security.ts +59 -245
  45. package/src/index.ts +7 -0
  46. package/src/server-scoring.ts +30 -226
  47. package/src/shared-vocabulary-support.ts +1 -0
  48. package/src/support.ts +9 -4
  49. package/src/trusted-item-session.ts +427 -0
  50. package/src/interaction-test-fixtures.ts +0 -44
  51. package/src/serializer-processing.fixtures.ts +0 -469
@@ -1,469 +0,0 @@
1
- import type { QtiProcessingExpression } from "./types.js";
2
-
3
- const baseOne = {
4
- type: "baseValue",
5
- baseType: "integer",
6
- value: 1,
7
- } satisfies QtiProcessingExpression;
8
- const baseTwo = {
9
- type: "baseValue",
10
- baseType: "integer",
11
- value: 2,
12
- } satisfies QtiProcessingExpression;
13
- const variableScore = { type: "variable", identifier: "SCORE" } satisfies QtiProcessingExpression;
14
- const variableResponse = {
15
- type: "variable",
16
- identifier: "RESPONSE",
17
- } satisfies QtiProcessingExpression;
18
-
19
- export type ExpressionCoverage = {
20
- [K in QtiProcessingExpression["type"]]: {
21
- expression: Extract<QtiProcessingExpression, { type: K }>;
22
- xml: string;
23
- };
24
- };
25
-
26
- export const expressionCoverage = {
27
- baseValue: {
28
- expression: baseOne,
29
- xml: ' <qti-base-value base-type="integer">1</qti-base-value>',
30
- },
31
- null: { expression: { type: "null" }, xml: " <qti-null/>" },
32
- isNull: {
33
- expression: { type: "isNull", identifier: "RESPONSE" },
34
- xml: [
35
- " <qti-is-null>",
36
- ' <qti-variable identifier="RESPONSE"/>',
37
- " </qti-is-null>",
38
- ].join("\n"),
39
- },
40
- matchCorrect: {
41
- expression: {
42
- type: "matchCorrect",
43
- identifier: "RESPONSE",
44
- correctIdentifier: "RESPONSE",
45
- },
46
- xml: [
47
- " <qti-match>",
48
- ' <qti-variable identifier="RESPONSE"/>',
49
- ' <qti-correct identifier="RESPONSE"/>',
50
- " </qti-match>",
51
- ].join("\n"),
52
- },
53
- match: {
54
- expression: { type: "match", left: variableResponse, right: baseOne },
55
- xml: [
56
- " <qti-match>",
57
- ' <qti-variable identifier="RESPONSE"/>',
58
- ' <qti-base-value base-type="integer">1</qti-base-value>',
59
- " </qti-match>",
60
- ].join("\n"),
61
- },
62
- correct: {
63
- expression: { type: "correct", identifier: "RESPONSE" },
64
- xml: ' <qti-correct identifier="RESPONSE"/>',
65
- },
66
- default: {
67
- expression: { type: "default", identifier: "SCORE" },
68
- xml: ' <qti-default identifier="SCORE"/>',
69
- },
70
- mapResponse: {
71
- expression: { type: "mapResponse", identifier: "RESPONSE" },
72
- xml: ' <qti-map-response identifier="RESPONSE"/>',
73
- },
74
- mapResponsePoint: {
75
- expression: { type: "mapResponsePoint", identifier: "RESPONSE" },
76
- xml: ' <qti-map-response-point identifier="RESPONSE"/>',
77
- },
78
- variable: {
79
- expression: variableResponse,
80
- xml: ' <qti-variable identifier="RESPONSE"/>',
81
- },
82
- randomInteger: {
83
- expression: { type: "randomInteger", min: 1, max: 10, step: 1, attributes: {} },
84
- xml: ' <qti-random-integer min="1" max="10" step="1"/>',
85
- },
86
- randomFloat: {
87
- expression: { type: "randomFloat", min: 0, max: 1, attributes: {} },
88
- xml: ' <qti-random-float min="0" max="1"/>',
89
- },
90
- random: {
91
- expression: { type: "random", values: [baseOne, baseTwo] },
92
- xml: [
93
- " <qti-random>",
94
- ' <qti-base-value base-type="integer">1</qti-base-value>',
95
- ' <qti-base-value base-type="integer">2</qti-base-value>',
96
- " </qti-random>",
97
- ].join("\n"),
98
- },
99
- multiple: {
100
- expression: { type: "multiple", expressions: [baseOne, baseTwo] },
101
- xml: [
102
- " <qti-multiple>",
103
- ' <qti-base-value base-type="integer">1</qti-base-value>',
104
- ' <qti-base-value base-type="integer">2</qti-base-value>',
105
- " </qti-multiple>",
106
- ].join("\n"),
107
- },
108
- ordered: {
109
- expression: { type: "ordered", expressions: [baseOne, baseTwo] },
110
- xml: [
111
- " <qti-ordered>",
112
- ' <qti-base-value base-type="integer">1</qti-base-value>',
113
- ' <qti-base-value base-type="integer">2</qti-base-value>',
114
- " </qti-ordered>",
115
- ].join("\n"),
116
- },
117
- index: {
118
- expression: { type: "index", expression: variableResponse, n: "1" },
119
- xml: [
120
- ' <qti-index n="1">',
121
- ' <qti-variable identifier="RESPONSE"/>',
122
- " </qti-index>",
123
- ].join("\n"),
124
- },
125
- containerSize: {
126
- expression: { type: "containerSize", expression: variableResponse },
127
- xml: [
128
- " <qti-container-size>",
129
- ' <qti-variable identifier="RESPONSE"/>',
130
- " </qti-container-size>",
131
- ].join("\n"),
132
- },
133
- sum: {
134
- expression: { type: "sum", expressions: [baseOne, baseTwo] },
135
- xml: [
136
- " <qti-sum>",
137
- ' <qti-base-value base-type="integer">1</qti-base-value>',
138
- ' <qti-base-value base-type="integer">2</qti-base-value>',
139
- " </qti-sum>",
140
- ].join("\n"),
141
- },
142
- product: {
143
- expression: { type: "product", expressions: [baseOne, baseTwo] },
144
- xml: [
145
- " <qti-product>",
146
- ' <qti-base-value base-type="integer">1</qti-base-value>',
147
- ' <qti-base-value base-type="integer">2</qti-base-value>',
148
- " </qti-product>",
149
- ].join("\n"),
150
- },
151
- min: {
152
- expression: { type: "min", expressions: [baseOne, baseTwo] },
153
- xml: [
154
- " <qti-min>",
155
- ' <qti-base-value base-type="integer">1</qti-base-value>',
156
- ' <qti-base-value base-type="integer">2</qti-base-value>',
157
- " </qti-min>",
158
- ].join("\n"),
159
- },
160
- max: {
161
- expression: { type: "max", expressions: [baseOne, baseTwo] },
162
- xml: [
163
- " <qti-max>",
164
- ' <qti-base-value base-type="integer">1</qti-base-value>',
165
- ' <qti-base-value base-type="integer">2</qti-base-value>',
166
- " </qti-max>",
167
- ].join("\n"),
168
- },
169
- subtract: {
170
- expression: { type: "subtract", left: baseTwo, right: baseOne },
171
- xml: [
172
- " <qti-subtract>",
173
- ' <qti-base-value base-type="integer">2</qti-base-value>',
174
- ' <qti-base-value base-type="integer">1</qti-base-value>',
175
- " </qti-subtract>",
176
- ].join("\n"),
177
- },
178
- divide: {
179
- expression: { type: "divide", left: baseTwo, right: baseOne },
180
- xml: [
181
- " <qti-divide>",
182
- ' <qti-base-value base-type="integer">2</qti-base-value>',
183
- ' <qti-base-value base-type="integer">1</qti-base-value>',
184
- " </qti-divide>",
185
- ].join("\n"),
186
- },
187
- power: {
188
- expression: { type: "power", left: baseTwo, right: baseOne },
189
- xml: [
190
- " <qti-power>",
191
- ' <qti-base-value base-type="integer">2</qti-base-value>',
192
- ' <qti-base-value base-type="integer">1</qti-base-value>',
193
- " </qti-power>",
194
- ].join("\n"),
195
- },
196
- integerDivide: {
197
- expression: { type: "integerDivide", left: baseTwo, right: baseOne },
198
- xml: [
199
- " <qti-integer-divide>",
200
- ' <qti-base-value base-type="integer">2</qti-base-value>',
201
- ' <qti-base-value base-type="integer">1</qti-base-value>',
202
- " </qti-integer-divide>",
203
- ].join("\n"),
204
- },
205
- integerModulus: {
206
- expression: { type: "integerModulus", left: baseTwo, right: baseOne },
207
- xml: [
208
- " <qti-integer-modulus>",
209
- ' <qti-base-value base-type="integer">2</qti-base-value>',
210
- ' <qti-base-value base-type="integer">1</qti-base-value>',
211
- " </qti-integer-modulus>",
212
- ].join("\n"),
213
- },
214
- round: {
215
- expression: { type: "round", expression: baseOne },
216
- xml: [
217
- " <qti-round>",
218
- ' <qti-base-value base-type="integer">1</qti-base-value>',
219
- " </qti-round>",
220
- ].join("\n"),
221
- },
222
- roundTo: {
223
- expression: {
224
- type: "roundTo",
225
- expression: baseOne,
226
- roundingMode: "decimalPlaces",
227
- figures: 1,
228
- },
229
- xml: [
230
- ' <qti-round-to rounding-mode="decimalPlaces" figures="1">',
231
- ' <qti-base-value base-type="integer">1</qti-base-value>',
232
- " </qti-round-to>",
233
- ].join("\n"),
234
- },
235
- truncate: {
236
- expression: { type: "truncate", expression: baseOne },
237
- xml: [
238
- " <qti-truncate>",
239
- ' <qti-base-value base-type="integer">1</qti-base-value>',
240
- " </qti-truncate>",
241
- ].join("\n"),
242
- },
243
- integerToFloat: {
244
- expression: { type: "integerToFloat", expression: baseOne },
245
- xml: [
246
- " <qti-integer-to-float>",
247
- ' <qti-base-value base-type="integer">1</qti-base-value>',
248
- " </qti-integer-to-float>",
249
- ].join("\n"),
250
- },
251
- and: {
252
- expression: { type: "and", expressions: [variableScore] },
253
- xml: [" <qti-and>", ' <qti-variable identifier="SCORE"/>', " </qti-and>"].join("\n"),
254
- },
255
- anyN: {
256
- expression: { type: "anyN", min: "1", max: "2", expressions: [variableScore] },
257
- xml: [
258
- ' <qti-any-n min="1" max="2">',
259
- ' <qti-variable identifier="SCORE"/>',
260
- " </qti-any-n>",
261
- ].join("\n"),
262
- },
263
- or: {
264
- expression: { type: "or", expressions: [variableScore] },
265
- xml: [" <qti-or>", ' <qti-variable identifier="SCORE"/>', " </qti-or>"].join("\n"),
266
- },
267
- not: {
268
- expression: { type: "not", expression: variableScore },
269
- xml: [" <qti-not>", ' <qti-variable identifier="SCORE"/>', " </qti-not>"].join("\n"),
270
- },
271
- equal: {
272
- expression: { type: "equal", left: baseOne, right: baseOne },
273
- xml: [
274
- " <qti-equal>",
275
- ' <qti-base-value base-type="integer">1</qti-base-value>',
276
- ' <qti-base-value base-type="integer">1</qti-base-value>',
277
- " </qti-equal>",
278
- ].join("\n"),
279
- },
280
- equalRounded: {
281
- expression: {
282
- type: "equalRounded",
283
- left: baseOne,
284
- right: baseOne,
285
- roundingMode: "decimalPlaces",
286
- figures: 1,
287
- },
288
- xml: [
289
- ' <qti-equal-rounded rounding-mode="decimalPlaces" figures="1">',
290
- ' <qti-base-value base-type="integer">1</qti-base-value>',
291
- ' <qti-base-value base-type="integer">1</qti-base-value>',
292
- " </qti-equal-rounded>",
293
- ].join("\n"),
294
- },
295
- numericCompare: {
296
- expression: { type: "numericCompare", operator: "gte", left: variableScore, right: baseOne },
297
- xml: [
298
- " <qti-gte>",
299
- ' <qti-variable identifier="SCORE"/>',
300
- ' <qti-base-value base-type="integer">1</qti-base-value>',
301
- " </qti-gte>",
302
- ].join("\n"),
303
- },
304
- durationCompare: {
305
- expression: { type: "durationCompare", operator: "lt", left: variableScore, right: baseOne },
306
- xml: [
307
- " <qti-duration-lt>",
308
- ' <qti-variable identifier="SCORE"/>',
309
- ' <qti-base-value base-type="integer">1</qti-base-value>',
310
- " </qti-duration-lt>",
311
- ].join("\n"),
312
- },
313
- stringMatch: {
314
- expression: {
315
- type: "stringMatch",
316
- left: variableResponse,
317
- right: { type: "baseValue", baseType: "string", value: "A" },
318
- caseSensitive: false,
319
- substring: true,
320
- },
321
- xml: [
322
- ' <qti-string-match case-sensitive="false" substring="true">',
323
- ' <qti-variable identifier="RESPONSE"/>',
324
- ' <qti-base-value base-type="string">A</qti-base-value>',
325
- " </qti-string-match>",
326
- ].join("\n"),
327
- },
328
- substring: {
329
- expression: {
330
- type: "substring",
331
- left: variableResponse,
332
- right: { type: "baseValue", baseType: "string", value: "A" },
333
- caseSensitive: true,
334
- },
335
- xml: [
336
- ' <qti-substring case-sensitive="true">',
337
- ' <qti-variable identifier="RESPONSE"/>',
338
- ' <qti-base-value base-type="string">A</qti-base-value>',
339
- " </qti-substring>",
340
- ].join("\n"),
341
- },
342
- patternMatch: {
343
- expression: { type: "patternMatch", expression: variableResponse, pattern: "[A-Z]+" },
344
- xml: [
345
- ' <qti-pattern-match pattern="[A-Z]+">',
346
- ' <qti-variable identifier="RESPONSE"/>',
347
- " </qti-pattern-match>",
348
- ].join("\n"),
349
- },
350
- fieldValue: {
351
- expression: { type: "fieldValue", fieldIdentifier: "candidate", expression: variableResponse },
352
- xml: [
353
- ' <qti-field-value field-identifier="candidate">',
354
- ' <qti-variable identifier="RESPONSE"/>',
355
- " </qti-field-value>",
356
- ].join("\n"),
357
- },
358
- member: {
359
- expression: { type: "member", value: baseOne, collection: variableResponse },
360
- xml: [
361
- " <qti-member>",
362
- ' <qti-base-value base-type="integer">1</qti-base-value>',
363
- ' <qti-variable identifier="RESPONSE"/>',
364
- " </qti-member>",
365
- ].join("\n"),
366
- },
367
- delete: {
368
- expression: { type: "delete", value: baseOne, collection: variableResponse },
369
- xml: [
370
- " <qti-delete>",
371
- ' <qti-base-value base-type="integer">1</qti-base-value>',
372
- ' <qti-variable identifier="RESPONSE"/>',
373
- " </qti-delete>",
374
- ].join("\n"),
375
- },
376
- contains: {
377
- expression: { type: "contains", collection: variableResponse, values: baseOne },
378
- xml: [
379
- " <qti-contains>",
380
- ' <qti-variable identifier="RESPONSE"/>',
381
- ' <qti-base-value base-type="integer">1</qti-base-value>',
382
- " </qti-contains>",
383
- ].join("\n"),
384
- },
385
- gcd: {
386
- expression: { type: "gcd", expressions: [baseOne, baseTwo] },
387
- xml: [
388
- " <qti-gcd>",
389
- ' <qti-base-value base-type="integer">1</qti-base-value>',
390
- ' <qti-base-value base-type="integer">2</qti-base-value>',
391
- " </qti-gcd>",
392
- ].join("\n"),
393
- },
394
- inside: {
395
- expression: {
396
- type: "inside",
397
- shape: "circle",
398
- coords: [10, 20, 5],
399
- attributes: { coords: "0,0,0", shape: "rect", tolerance: "2" },
400
- expression: variableResponse,
401
- },
402
- xml: [
403
- ' <qti-inside shape="rect" coords="0,0,0" tolerance="2">',
404
- ' <qti-variable identifier="RESPONSE"/>',
405
- " </qti-inside>",
406
- ].join("\n"),
407
- },
408
- lcm: {
409
- expression: { type: "lcm", expressions: [baseOne, baseTwo] },
410
- xml: [
411
- " <qti-lcm>",
412
- ' <qti-base-value base-type="integer">1</qti-base-value>',
413
- ' <qti-base-value base-type="integer">2</qti-base-value>',
414
- " </qti-lcm>",
415
- ].join("\n"),
416
- },
417
- mathConstant: {
418
- expression: { type: "mathConstant", name: "pi" },
419
- xml: ' <qti-math-constant name="pi"/>',
420
- },
421
- mathOperator: {
422
- expression: { type: "mathOperator", name: "sin", expressions: [baseOne] },
423
- xml: [
424
- ' <qti-math-operator name="sin">',
425
- ' <qti-base-value base-type="integer">1</qti-base-value>',
426
- " </qti-math-operator>",
427
- ].join("\n"),
428
- },
429
- repeat: {
430
- expression: { type: "repeat", numberRepeats: "2", expressions: [baseOne] },
431
- xml: [
432
- ' <qti-repeat number-repeats="2">',
433
- ' <qti-base-value base-type="integer">1</qti-base-value>',
434
- " </qti-repeat>",
435
- ].join("\n"),
436
- },
437
- statsOperator: {
438
- expression: { type: "statsOperator", name: "mean", expression: variableResponse },
439
- xml: [
440
- ' <qti-stats-operator name="mean">',
441
- ' <qti-variable identifier="RESPONSE"/>',
442
- " </qti-stats-operator>",
443
- ].join("\n"),
444
- },
445
- customOperator: {
446
- expression: {
447
- type: "customOperator",
448
- definition: "https://example.invalid/operator?a=1&b=2",
449
- className: "demo",
450
- attributes: { "data-extra": `"quoted"` },
451
- expressions: [{ type: "null" }],
452
- },
453
- xml: [
454
- ' <qti-custom-operator class="demo" data-extra="&quot;quoted&quot;" definition="https://example.invalid/operator?a=1&amp;b=2">',
455
- " <qti-null/>",
456
- " </qti-custom-operator>",
457
- ].join("\n"),
458
- },
459
- } satisfies ExpressionCoverage;
460
-
461
- export function expressionCoverageXml(expressionType: QtiProcessingExpression["type"]): string {
462
- return [
463
- "<qti-response-processing>",
464
- ' <qti-set-outcome-value identifier="SCORE">',
465
- expressionCoverage[expressionType].xml,
466
- " </qti-set-outcome-value>",
467
- "</qti-response-processing>",
468
- ].join("\n");
469
- }