@longsightgroup/qti3-core 0.9.1 → 0.9.3

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 (244) hide show
  1. package/README.md +59 -3
  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/assert-never.d.ts +3 -0
  11. package/dist/assert-never.d.ts.map +1 -0
  12. package/dist/assert-never.js +5 -0
  13. package/dist/assert-never.js.map +1 -0
  14. package/dist/attempt-state-constants.d.ts +6 -0
  15. package/dist/attempt-state-constants.d.ts.map +1 -0
  16. package/dist/attempt-state-constants.js +6 -0
  17. package/dist/attempt-state-constants.js.map +1 -0
  18. package/dist/attempt-state.d.ts +5 -0
  19. package/dist/attempt-state.d.ts.map +1 -0
  20. package/dist/attempt-state.js +190 -0
  21. package/dist/attempt-state.js.map +1 -0
  22. package/dist/catalog.js +1 -1
  23. package/dist/catalog.js.map +1 -1
  24. package/dist/content-text.d.ts.map +1 -1
  25. package/dist/content-text.js +3 -0
  26. package/dist/content-text.js.map +1 -1
  27. package/dist/custom-operators.d.ts +13 -0
  28. package/dist/custom-operators.d.ts.map +1 -0
  29. package/dist/custom-operators.js +2 -0
  30. package/dist/custom-operators.js.map +1 -0
  31. package/dist/delivery-redaction.d.ts +50 -0
  32. package/dist/delivery-redaction.d.ts.map +1 -0
  33. package/dist/delivery-redaction.js +176 -0
  34. package/dist/delivery-redaction.js.map +1 -0
  35. package/dist/delivery-security.d.ts +3 -18
  36. package/dist/delivery-security.d.ts.map +1 -1
  37. package/dist/delivery-security.js +35 -189
  38. package/dist/delivery-security.js.map +1 -1
  39. package/dist/index.d.ts +4 -1
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +3 -0
  42. package/dist/index.js.map +1 -1
  43. package/dist/parser-custom-interactions.js +1 -1
  44. package/dist/parser-custom-interactions.js.map +1 -1
  45. package/dist/parser-declarations.d.ts.map +1 -1
  46. package/dist/parser-declarations.js +4 -4
  47. package/dist/parser-declarations.js.map +1 -1
  48. package/dist/parser-item-metadata.d.ts.map +1 -1
  49. package/dist/parser-item-metadata.js +8 -7
  50. package/dist/parser-item-metadata.js.map +1 -1
  51. package/dist/parser-processing.js +2 -2
  52. package/dist/parser-processing.js.map +1 -1
  53. package/dist/parser-values.d.ts +5 -1
  54. package/dist/parser-values.d.ts.map +1 -1
  55. package/dist/parser-values.js +33 -0
  56. package/dist/parser-values.js.map +1 -1
  57. package/dist/processing-evaluator-boolean.d.ts +8 -0
  58. package/dist/processing-evaluator-boolean.d.ts.map +1 -0
  59. package/dist/processing-evaluator-boolean.js +47 -0
  60. package/dist/processing-evaluator-boolean.js.map +1 -0
  61. package/dist/processing-evaluator-collection.d.ts +12 -0
  62. package/dist/processing-evaluator-collection.d.ts.map +1 -0
  63. package/dist/processing-evaluator-collection.js +35 -0
  64. package/dist/processing-evaluator-collection.js.map +1 -0
  65. package/dist/processing-evaluator-comparison.d.ts +8 -0
  66. package/dist/processing-evaluator-comparison.d.ts.map +1 -0
  67. package/dist/processing-evaluator-comparison.js +88 -0
  68. package/dist/processing-evaluator-comparison.js.map +1 -0
  69. package/dist/processing-evaluator-custom.d.ts +8 -0
  70. package/dist/processing-evaluator-custom.d.ts.map +1 -0
  71. package/dist/processing-evaluator-custom.js +14 -0
  72. package/dist/processing-evaluator-custom.js.map +1 -0
  73. package/dist/processing-evaluator-geometry.d.ts +8 -0
  74. package/dist/processing-evaluator-geometry.d.ts.map +1 -0
  75. package/dist/processing-evaluator-geometry.js +21 -0
  76. package/dist/processing-evaluator-geometry.js.map +1 -0
  77. package/dist/processing-evaluator-numeric.d.ts +8 -0
  78. package/dist/processing-evaluator-numeric.d.ts.map +1 -0
  79. package/dist/processing-evaluator-numeric.js +112 -0
  80. package/dist/processing-evaluator-numeric.js.map +1 -0
  81. package/dist/processing-evaluator-string.d.ts +8 -0
  82. package/dist/processing-evaluator-string.d.ts.map +1 -0
  83. package/dist/processing-evaluator-string.js +33 -0
  84. package/dist/processing-evaluator-string.js.map +1 -0
  85. package/dist/processing-evaluator-variable.d.ts +8 -0
  86. package/dist/processing-evaluator-variable.d.ts.map +1 -0
  87. package/dist/processing-evaluator-variable.js +39 -0
  88. package/dist/processing-evaluator-variable.js.map +1 -0
  89. package/dist/processing-evaluator.d.ts +22 -0
  90. package/dist/processing-evaluator.d.ts.map +1 -0
  91. package/dist/processing-evaluator.js +137 -0
  92. package/dist/processing-evaluator.js.map +1 -0
  93. package/dist/processing-expression-children.d.ts +3 -0
  94. package/dist/processing-expression-children.d.ts.map +1 -0
  95. package/dist/processing-expression-children.js +68 -0
  96. package/dist/processing-expression-children.js.map +1 -0
  97. package/dist/processing-mapping.d.ts +13 -0
  98. package/dist/processing-mapping.d.ts.map +1 -0
  99. package/dist/processing-mapping.js +120 -0
  100. package/dist/processing-mapping.js.map +1 -0
  101. package/dist/processing-operators.d.ts +11 -0
  102. package/dist/processing-operators.d.ts.map +1 -0
  103. package/dist/processing-operators.js +178 -0
  104. package/dist/processing-operators.js.map +1 -0
  105. package/dist/processing-random.d.ts +2 -0
  106. package/dist/processing-random.d.ts.map +1 -0
  107. package/dist/processing-random.js +16 -0
  108. package/dist/processing-random.js.map +1 -0
  109. package/dist/processing-state.d.ts +8 -0
  110. package/dist/processing-state.d.ts.map +1 -0
  111. package/dist/processing-state.js +44 -0
  112. package/dist/processing-state.js.map +1 -0
  113. package/dist/processing-templates.d.ts +3 -0
  114. package/dist/processing-templates.d.ts.map +1 -0
  115. package/dist/processing-templates.js +12 -0
  116. package/dist/processing-templates.js.map +1 -0
  117. package/dist/processing-values.d.ts +15 -0
  118. package/dist/processing-values.d.ts.map +1 -0
  119. package/dist/processing-values.js +150 -0
  120. package/dist/processing-values.js.map +1 -0
  121. package/dist/processing-variables.d.ts +7 -0
  122. package/dist/processing-variables.d.ts.map +1 -0
  123. package/dist/processing-variables.js +40 -0
  124. package/dist/processing-variables.js.map +1 -0
  125. package/dist/serializer-processing-expressions.d.ts.map +1 -1
  126. package/dist/serializer-processing-expressions.js +2 -8
  127. package/dist/serializer-processing-expressions.js.map +1 -1
  128. package/dist/serializer-processing-xml.js +2 -2
  129. package/dist/serializer-processing-xml.js.map +1 -1
  130. package/dist/serializer-processing.d.ts.map +1 -1
  131. package/dist/serializer-processing.js +3 -0
  132. package/dist/serializer-processing.js.map +1 -1
  133. package/dist/server-scoring.d.ts +4 -14
  134. package/dist/server-scoring.d.ts.map +1 -1
  135. package/dist/server-scoring.js +19 -157
  136. package/dist/server-scoring.js.map +1 -1
  137. package/dist/session.d.ts +5 -14
  138. package/dist/session.d.ts.map +1 -1
  139. package/dist/session.js +76 -1158
  140. package/dist/session.js.map +1 -1
  141. package/dist/shared-vocabulary-coverage-policy.js +1 -1
  142. package/dist/shared-vocabulary-coverage-policy.js.map +1 -1
  143. package/dist/shared-vocabulary-generated-families.js +1 -1
  144. package/dist/shared-vocabulary-generated-families.js.map +1 -1
  145. package/dist/shared-vocabulary-support.js +3 -3
  146. package/dist/shared-vocabulary-support.js.map +1 -1
  147. package/dist/shared-vocabulary.d.ts.map +1 -1
  148. package/dist/shared-vocabulary.js +4 -3
  149. package/dist/shared-vocabulary.js.map +1 -1
  150. package/dist/support-evidence.d.ts +22 -0
  151. package/dist/support-evidence.d.ts.map +1 -0
  152. package/dist/support-evidence.js +93 -0
  153. package/dist/support-evidence.js.map +1 -0
  154. package/dist/support.d.ts.map +1 -1
  155. package/dist/support.js +38 -47
  156. package/dist/support.js.map +1 -1
  157. package/dist/trusted-item-session.d.ts +49 -0
  158. package/dist/trusted-item-session.d.ts.map +1 -0
  159. package/dist/trusted-item-session.js +261 -0
  160. package/dist/trusted-item-session.js.map +1 -0
  161. package/dist/tts.d.ts.map +1 -1
  162. package/dist/tts.js +16 -2
  163. package/dist/tts.js.map +1 -1
  164. package/dist/validation-geometry.d.ts +8 -0
  165. package/dist/validation-geometry.d.ts.map +1 -0
  166. package/dist/validation-geometry.js +187 -0
  167. package/dist/validation-geometry.js.map +1 -0
  168. package/dist/validation-interactions.d.ts +3 -0
  169. package/dist/validation-interactions.d.ts.map +1 -0
  170. package/dist/validation-interactions.js +644 -0
  171. package/dist/validation-interactions.js.map +1 -0
  172. package/dist/validation-primitives.d.ts +11 -0
  173. package/dist/validation-primitives.d.ts.map +1 -0
  174. package/dist/validation-primitives.js +48 -0
  175. package/dist/validation-primitives.js.map +1 -0
  176. package/dist/validation-processing.d.ts +4 -0
  177. package/dist/validation-processing.d.ts.map +1 -0
  178. package/dist/validation-processing.js +569 -0
  179. package/dist/validation-processing.js.map +1 -0
  180. package/dist/validation-shared-vocabulary-layout.d.ts +10 -0
  181. package/dist/validation-shared-vocabulary-layout.d.ts.map +1 -0
  182. package/dist/validation-shared-vocabulary-layout.js +102 -0
  183. package/dist/validation-shared-vocabulary-layout.js.map +1 -0
  184. package/dist/validation.d.ts.map +1 -1
  185. package/dist/validation.js +27 -1641
  186. package/dist/validation.js.map +1 -1
  187. package/dist/xml.js +1 -1
  188. package/dist/xml.js.map +1 -1
  189. package/package.json +4 -2
  190. package/src/adaptive-turn-materializer.ts +85 -0
  191. package/src/adaptive-turn.ts +109 -0
  192. package/src/assert-never.ts +4 -0
  193. package/src/attempt-state-constants.ts +5 -0
  194. package/src/attempt-state.ts +245 -0
  195. package/src/catalog.ts +1 -1
  196. package/src/content-text.ts +3 -0
  197. package/src/custom-operators.ts +12 -0
  198. package/src/delivery-redaction.ts +268 -0
  199. package/src/delivery-security.ts +59 -245
  200. package/src/index.ts +9 -0
  201. package/src/parser-custom-interactions.ts +1 -1
  202. package/src/parser-declarations.ts +4 -3
  203. package/src/parser-item-metadata.ts +8 -7
  204. package/src/parser-processing.ts +2 -2
  205. package/src/parser-values.ts +36 -0
  206. package/src/processing-evaluator-boolean.ts +48 -0
  207. package/src/processing-evaluator-collection.ts +50 -0
  208. package/src/processing-evaluator-comparison.ts +106 -0
  209. package/src/processing-evaluator-custom.ts +20 -0
  210. package/src/processing-evaluator-geometry.ts +26 -0
  211. package/src/processing-evaluator-numeric.ts +155 -0
  212. package/src/processing-evaluator-string.ts +60 -0
  213. package/src/processing-evaluator-variable.ts +81 -0
  214. package/src/processing-evaluator.ts +173 -0
  215. package/src/processing-expression-children.ts +69 -0
  216. package/src/processing-mapping.ts +153 -0
  217. package/src/processing-operators.ts +184 -0
  218. package/src/processing-random.ts +16 -0
  219. package/src/processing-state.ts +69 -0
  220. package/src/processing-templates.ts +12 -0
  221. package/src/processing-values.ts +162 -0
  222. package/src/processing-variables.ts +83 -0
  223. package/src/serializer-processing-expressions.ts +2 -12
  224. package/src/serializer-processing-xml.ts +2 -2
  225. package/src/serializer-processing.ts +3 -0
  226. package/src/server-scoring.ts +30 -226
  227. package/src/session.ts +128 -2006
  228. package/src/shared-vocabulary-coverage-policy.ts +1 -1
  229. package/src/shared-vocabulary-generated-families.ts +1 -1
  230. package/src/shared-vocabulary-support.ts +3 -3
  231. package/src/shared-vocabulary.ts +3 -2
  232. package/src/support-evidence.ts +107 -0
  233. package/src/support.ts +68 -54
  234. package/src/trusted-item-session.ts +429 -0
  235. package/src/tts.ts +29 -15
  236. package/src/validation-geometry.ts +204 -0
  237. package/src/validation-interactions.ts +831 -0
  238. package/src/validation-primitives.ts +63 -0
  239. package/src/validation-processing.ts +785 -0
  240. package/src/validation-shared-vocabulary-layout.ts +117 -0
  241. package/src/validation.ts +44 -2077
  242. package/src/xml.ts +1 -1
  243. package/src/interaction-test-fixtures.ts +0 -44
  244. package/src/serializer-processing.fixtures.ts +0 -469
@@ -0,0 +1,120 @@
1
+ import { qtiScalarToString, qtiValueToStringList } from "./value-format.js";
2
+ import { isRecordValue, numericValue, valuesEqual } from "./processing-values.js";
3
+ export function lookupOutcomeValue(document, identifier, value) {
4
+ const declaration = document.item.outcomeDeclarations.find((outcome) => outcome.identifier === identifier);
5
+ const lookupTable = declaration?.lookupTable;
6
+ if (!lookupTable)
7
+ return null;
8
+ if (value === null)
9
+ return lookupTable.defaultValue;
10
+ const numeric = numericValue(value);
11
+ if (lookupTable.type === "match") {
12
+ return (lookupTable.entries.find((entry) => entry.sourceValue === numeric)?.targetValue ??
13
+ lookupTable.defaultValue);
14
+ }
15
+ const entry = [...lookupTable.entries]
16
+ .toSorted((left, right) => left.sourceValue - right.sourceValue)
17
+ .find((candidate) => numeric < candidate.sourceValue ||
18
+ (candidate.includeBoundary !== false && numeric === candidate.sourceValue));
19
+ return entry?.targetValue ?? lookupTable.defaultValue;
20
+ }
21
+ export function mapOrMatchResponse(declaration, response, correctResponse) {
22
+ if (declaration.areaMapping)
23
+ return scoreAreaMapping(response, declaration.areaMapping);
24
+ if (declaration.mapping)
25
+ return scoreMapping(response, declaration.mapping);
26
+ return valuesEqual(response, correctResponse, declaration.cardinality === "ordered") ? 1 : 0;
27
+ }
28
+ export function scoreAreaMapping(response, areaMapping) {
29
+ const points = Array.isArray(response)
30
+ ? response.map(qtiScalarToString)
31
+ : response === null
32
+ ? []
33
+ : qtiValueToStringList(response);
34
+ let score = 0;
35
+ for (const point of points) {
36
+ const parsed = parsePoint(point);
37
+ if (!parsed) {
38
+ score += areaMapping.defaultValue;
39
+ continue;
40
+ }
41
+ const entry = areaMapping.entries.find((candidate) => pointInsideArea(parsed, candidate));
42
+ score += entry?.mappedValue ?? areaMapping.defaultValue;
43
+ }
44
+ return clampMappedScore(score, areaMapping.attributes);
45
+ }
46
+ export function parsePoint(value) {
47
+ const [x, y] = value
48
+ .trim()
49
+ .split(/[,\s]+/)
50
+ .map((part) => Number(part));
51
+ if (x === undefined || y === undefined || !Number.isFinite(x) || !Number.isFinite(y)) {
52
+ return undefined;
53
+ }
54
+ return { x, y };
55
+ }
56
+ export function pointInsideArea(point, entry) {
57
+ if (entry.shape === "circle") {
58
+ const [cx, cy, radius] = entry.coords;
59
+ if (cx === undefined || cy === undefined || radius === undefined)
60
+ return false;
61
+ return Math.hypot(point.x - cx, point.y - cy) <= radius;
62
+ }
63
+ if (entry.shape === "rect") {
64
+ const [left, top, right, bottom] = entry.coords;
65
+ if (left === undefined || top === undefined || right === undefined || bottom === undefined) {
66
+ return false;
67
+ }
68
+ return point.x >= left && point.x <= right && point.y >= top && point.y <= bottom;
69
+ }
70
+ if (entry.shape === "poly") {
71
+ return pointInsidePolygon(point, entry.coords);
72
+ }
73
+ return false;
74
+ }
75
+ function pointInsidePolygon(point, coords) {
76
+ if (coords.length < 6 || coords.length % 2 !== 0)
77
+ return false;
78
+ let inside = false;
79
+ for (let index = 0, previous = coords.length - 2; index < coords.length; index += 2) {
80
+ const xi = coords[index];
81
+ const yi = coords[index + 1];
82
+ const xj = coords[previous];
83
+ const yj = coords[previous + 1];
84
+ const intersects = yi > point.y !== yj > point.y && point.x < ((xj - xi) * (point.y - yi)) / (yj - yi) + xi;
85
+ if (intersects)
86
+ inside = !inside;
87
+ previous = index;
88
+ }
89
+ return inside;
90
+ }
91
+ function scoreMapping(response, mapping) {
92
+ const values = Object.fromEntries(mapping.entries
93
+ .filter((entry) => entry.mapKey !== undefined)
94
+ .map((entry) => [entry.mapKey, entry.mappedValue]));
95
+ if (Array.isArray(response)) {
96
+ const score = response.reduce((sum, value) => sum + (values[String(value)] ?? mapping.defaultValue), 0);
97
+ return clampMappedScore(score, mapping.attributes);
98
+ }
99
+ const score = response === null || isRecordValue(response)
100
+ ? 0
101
+ : (values[String(response)] ?? mapping.defaultValue);
102
+ return clampMappedScore(score, mapping.attributes);
103
+ }
104
+ function clampMappedScore(score, attributes) {
105
+ const lower = numericBound(attributes["lower-bound"]);
106
+ const upper = numericBound(attributes["upper-bound"]);
107
+ let clamped = score;
108
+ if (lower !== undefined)
109
+ clamped = Math.max(clamped, lower);
110
+ if (upper !== undefined)
111
+ clamped = Math.min(clamped, upper);
112
+ return clamped;
113
+ }
114
+ function numericBound(value) {
115
+ if (value === undefined)
116
+ return undefined;
117
+ const numberValue = Number(value);
118
+ return Number.isFinite(numberValue) ? numberValue : undefined;
119
+ }
120
+ //# sourceMappingURL=processing-mapping.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processing-mapping.js","sourceRoot":"","sources":["../src/processing-mapping.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAElF,MAAM,UAAU,kBAAkB,CAChC,QAAqB,EACrB,UAAkB,EAClB,KAAe;IAEf,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CACxD,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,KAAK,UAAU,CAC/C,CAAC;IACF,MAAM,WAAW,GAAG,WAAW,EAAE,WAAW,CAAC;IAC7C,IAAI,CAAC,WAAW;QAAE,OAAO,IAAI,CAAC;IAC9B,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,WAAW,CAAC,YAAY,CAAC;IACpD,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACpC,IAAI,WAAW,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QACjC,OAAO,CACL,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,KAAK,OAAO,CAAC,EAAE,WAAW;YAC/E,WAAW,CAAC,YAAY,CACzB,CAAC;IACJ,CAAC;IACD,MAAM,KAAK,GAAG,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC;SACnC,QAAQ,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC;SAC/D,IAAI,CACH,CAAC,SAAS,EAAE,EAAE,CACZ,OAAO,GAAG,SAAS,CAAC,WAAW;QAC/B,CAAC,SAAS,CAAC,eAAe,KAAK,KAAK,IAAI,OAAO,KAAK,SAAS,CAAC,WAAW,CAAC,CAC7E,CAAC;IACJ,OAAO,KAAK,EAAE,WAAW,IAAI,WAAW,CAAC,YAAY,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,kBAAkB,CAChC,WAAmC,EACnC,QAAkB,EAClB,eAAyB;IAEzB,IAAI,WAAW,CAAC,WAAW;QAAE,OAAO,gBAAgB,CAAC,QAAQ,EAAE,WAAW,CAAC,WAAW,CAAC,CAAC;IACxF,IAAI,WAAW,CAAC,OAAO;QAAE,OAAO,YAAY,CAAC,QAAQ,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IAC5E,OAAO,WAAW,CAAC,QAAQ,EAAE,eAAe,EAAE,WAAW,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/F,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,QAAkB,EAClB,WAA+D;IAE/D,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;QACpC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,iBAAiB,CAAC;QACjC,CAAC,CAAC,QAAQ,KAAK,IAAI;YACjB,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC;IACrC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,KAAK,IAAI,WAAW,CAAC,YAAY,CAAC;YAClC,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;QAC1F,KAAK,IAAI,KAAK,EAAE,WAAW,IAAI,WAAW,CAAC,YAAY,CAAC;IAC1D,CAAC;IACD,OAAO,gBAAgB,CAAC,KAAK,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,KAAK;SACjB,IAAI,EAAE;SACN,KAAK,CAAC,QAAQ,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/B,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QACrF,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,KAA+B,EAC/B,KAA4E;IAE5E,IAAI,KAAK,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;QACtC,IAAI,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QAC/E,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,MAAM,CAAC;IAC1D,CAAC;IAED,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;QAC3B,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;QAChD,IAAI,IAAI,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YAC3F,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,KAAK,CAAC,CAAC,IAAI,IAAI,IAAI,KAAK,CAAC,CAAC,IAAI,KAAK,IAAI,KAAK,CAAC,CAAC,IAAI,GAAG,IAAI,KAAK,CAAC,CAAC,IAAI,MAAM,CAAC;IACpF,CAAC;IAED,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;QAC3B,OAAO,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACjD,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,kBAAkB,CAAC,KAA+B,EAAE,MAAgB;IAC3E,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/D,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpF,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,CAAE,CAAC;QAC1B,MAAM,EAAE,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC,CAAE,CAAC;QAC9B,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAE,CAAC;QAC7B,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAE,CAAC;QACjC,MAAM,UAAU,GACd,EAAE,GAAG,KAAK,CAAC,CAAC,KAAK,EAAE,GAAG,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC;QAC3F,IAAI,UAAU;YAAE,MAAM,GAAG,CAAC,MAAM,CAAC;QACjC,QAAQ,GAAG,KAAK,CAAC;IACnB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,YAAY,CACnB,QAAkB,EAClB,OAAuD;IAEvD,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAC/B,OAAO,CAAC,OAAO;SACZ,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC;SAC7C,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,MAAO,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC,CACtD,CAAC;IACF,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAC3B,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,OAAO,CAAC,YAAY,CAAC,EACrE,CAAC,CACF,CAAC;QACF,OAAO,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IACrD,CAAC;IACD,MAAM,KAAK,GACT,QAAQ,KAAK,IAAI,IAAI,aAAa,CAAC,QAAQ,CAAC;QAC1C,CAAC,CAAC,CAAC;QACH,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,OAAO,CAAC,YAAY,CAAC,CAAC;IACzD,OAAO,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;AACrD,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAa,EAAE,UAAkC;IACzE,MAAM,KAAK,GAAG,YAAY,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC;IACtD,MAAM,KAAK,GAAG,YAAY,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC;IACtD,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC5D,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC5D,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,YAAY,CAAC,KAAyB;IAC7C,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAClC,OAAO,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;AAChE,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { QtiValue } from "./types.js";
2
+ export declare const MATH_OPERATOR_NAMES: readonly ["abs", "acos", "acot", "acsc", "asec", "asin", "atan", "atan2", "ceil", "cos", "cosh", "cot", "coth", "csc", "csch", "exp", "floor", "ln", "log", "sec", "sech", "signum", "sin", "sinh", "tan", "tanh", "toDegrees", "toRadians"];
3
+ export declare const STATS_OPERATOR_NAMES: readonly ["mean", "sampleVariance", "sampleSD", "popVariance", "popSD"];
4
+ export declare function roundToDecimalPlaces(value: number, figures: number): number;
5
+ export declare function roundToSignificantFigures(value: number, figures: number): number;
6
+ export declare function roundWithMode(value: number, roundingMode: string, figures: number): number | null;
7
+ export declare function generalizedGcd(values: number[]): number;
8
+ export declare function generalizedLcm(values: number[]): number;
9
+ export declare function mathOperatorValue(name: string, values: number[]): QtiValue;
10
+ export declare function statsOperatorValue(name: string, values: number[]): QtiValue;
11
+ //# sourceMappingURL=processing-operators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processing-operators.d.ts","sourceRoot":"","sources":["../src/processing-operators.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,eAAO,MAAM,mBAAmB,8OA6BtB,CAAC;AAEX,eAAO,MAAM,oBAAoB,yEAMvB,CAAC;AAEX,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAG3E;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAIhF;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKjG;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAMvD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAGvD;AAiBD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,CA+D1E;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,CAkB3E"}
@@ -0,0 +1,178 @@
1
+ export const MATH_OPERATOR_NAMES = [
2
+ "abs",
3
+ "acos",
4
+ "acot",
5
+ "acsc",
6
+ "asec",
7
+ "asin",
8
+ "atan",
9
+ "atan2",
10
+ "ceil",
11
+ "cos",
12
+ "cosh",
13
+ "cot",
14
+ "coth",
15
+ "csc",
16
+ "csch",
17
+ "exp",
18
+ "floor",
19
+ "ln",
20
+ "log",
21
+ "sec",
22
+ "sech",
23
+ "signum",
24
+ "sin",
25
+ "sinh",
26
+ "tan",
27
+ "tanh",
28
+ "toDegrees",
29
+ "toRadians",
30
+ ];
31
+ export const STATS_OPERATOR_NAMES = [
32
+ "mean",
33
+ "sampleVariance",
34
+ "sampleSD",
35
+ "popVariance",
36
+ "popSD",
37
+ ];
38
+ export function roundToDecimalPlaces(value, figures) {
39
+ const factor = 10 ** figures;
40
+ return Math.round(value * factor) / factor;
41
+ }
42
+ export function roundToSignificantFigures(value, figures) {
43
+ if (value === 0 || figures <= 0)
44
+ return 0;
45
+ const factor = 10 ** (figures - 1 - Math.floor(Math.log10(Math.abs(value))));
46
+ return Math.round(value * factor) / factor;
47
+ }
48
+ export function roundWithMode(value, roundingMode, figures) {
49
+ if (!Number.isFinite(value))
50
+ return null;
51
+ if (roundingMode === "decimalPlaces")
52
+ return roundToDecimalPlaces(value, figures);
53
+ if (roundingMode === "significantFigures")
54
+ return roundToSignificantFigures(value, figures);
55
+ return null;
56
+ }
57
+ export function generalizedGcd(values) {
58
+ let result = 0;
59
+ for (const value of values) {
60
+ result = gcd(result, Math.abs(value));
61
+ }
62
+ return result;
63
+ }
64
+ export function generalizedLcm(values) {
65
+ if (values.some((value) => value === 0))
66
+ return 0;
67
+ return values.reduce((result, value) => lcm(result, Math.abs(value)), 1);
68
+ }
69
+ function gcd(left, right) {
70
+ let a = Math.abs(left);
71
+ let b = Math.abs(right);
72
+ while (b !== 0) {
73
+ const next = a % b;
74
+ a = b;
75
+ b = next;
76
+ }
77
+ return a;
78
+ }
79
+ function lcm(left, right) {
80
+ return Math.abs(left * right) / gcd(left, right);
81
+ }
82
+ export function mathOperatorValue(name, values) {
83
+ const [first, second] = values;
84
+ if (first === undefined)
85
+ return null;
86
+ switch (name) {
87
+ case "abs":
88
+ return finiteOrNull(Math.abs(first));
89
+ case "acos":
90
+ return Math.abs(first) > 1 ? null : finiteOrNull(Math.acos(first));
91
+ case "acot":
92
+ return finiteOrNull(Math.PI / 2 - Math.atan(1 / first));
93
+ case "acsc":
94
+ return Math.abs(first) < 1 ? null : finiteOrNull(Math.PI / 2 - Math.asin(1 / first));
95
+ case "asec":
96
+ return Math.abs(first) < 1 ? null : finiteOrNull(Math.PI / 2 - Math.acos(1 / first));
97
+ case "asin":
98
+ return Math.abs(first) > 1 ? null : finiteOrNull(Math.asin(first));
99
+ case "atan":
100
+ return finiteOrNull(Math.atan(first));
101
+ case "atan2":
102
+ return second === undefined ? null : finiteOrNull(Math.atan2(first, second));
103
+ case "ceil":
104
+ return finiteOrNull(Math.ceil(first));
105
+ case "cos":
106
+ return finiteOrNull(Math.cos(first));
107
+ case "cosh":
108
+ return finiteOrNull(Math.cosh(first));
109
+ case "cot":
110
+ return finiteOrNull(1 / Math.tan(first));
111
+ case "coth":
112
+ return finiteOrNull(1 / Math.tanh(first));
113
+ case "csc":
114
+ return finiteOrNull(1 / Math.sin(first));
115
+ case "csch":
116
+ return finiteOrNull(1 / Math.sinh(first));
117
+ case "exp":
118
+ return finiteOrNull(Math.exp(first));
119
+ case "floor":
120
+ return finiteOrNull(Math.floor(first));
121
+ case "ln":
122
+ return first < 0 ? null : finiteOrNull(Math.log(first));
123
+ case "log":
124
+ return first < 0 ? null : finiteOrNull(Math.log10(first));
125
+ case "sec":
126
+ return finiteOrNull(1 / Math.cos(first));
127
+ case "sech":
128
+ return finiteOrNull(1 / Math.cosh(first));
129
+ case "signum":
130
+ return finiteOrNull(Math.sign(first));
131
+ case "sin":
132
+ return finiteOrNull(Math.sin(first));
133
+ case "sinh":
134
+ return finiteOrNull(Math.sinh(first));
135
+ case "tan":
136
+ return finiteOrNull(Math.tan(first));
137
+ case "tanh":
138
+ return finiteOrNull(Math.tanh(first));
139
+ case "toDegrees":
140
+ return finiteOrNull((first * 180) / Math.PI);
141
+ case "toRadians":
142
+ return finiteOrNull((first * Math.PI) / 180);
143
+ default:
144
+ return null;
145
+ }
146
+ }
147
+ export function statsOperatorValue(name, values) {
148
+ if (values.length === 0)
149
+ return 0;
150
+ const meanValue = mean(values);
151
+ const squareDiffs = values.map((value) => (value - meanValue) ** 2);
152
+ switch (name) {
153
+ case "mean":
154
+ return meanValue;
155
+ case "sampleVariance":
156
+ return meanWithDivisor(squareDiffs, values.length > 1 ? values.length - 1 : 1);
157
+ case "sampleSD":
158
+ return Math.sqrt(meanWithDivisor(squareDiffs, values.length > 1 ? values.length - 1 : 1));
159
+ case "popVariance":
160
+ return mean(squareDiffs);
161
+ case "popSD":
162
+ return Math.sqrt(mean(squareDiffs));
163
+ default:
164
+ return null;
165
+ }
166
+ }
167
+ function mean(values) {
168
+ return meanWithDivisor(values, values.length);
169
+ }
170
+ function meanWithDivisor(values, divisor) {
171
+ if (values.length === 0)
172
+ return 0;
173
+ return values.reduce((sum, value) => sum + value, 0) / divisor;
174
+ }
175
+ function finiteOrNull(value) {
176
+ return Number.isFinite(value) ? value : null;
177
+ }
178
+ //# sourceMappingURL=processing-operators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processing-operators.js","sourceRoot":"","sources":["../src/processing-operators.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function seededRandom(seed: string | number): () => number;
2
+ //# sourceMappingURL=processing-random.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processing-random.d.ts","sourceRoot":"","sources":["../src/processing-random.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,MAAM,CAMhE"}
@@ -0,0 +1,16 @@
1
+ export function seededRandom(seed) {
2
+ let state = typeof seed === "number" ? seed >>> 0 : hashSeed(seed);
3
+ return () => {
4
+ state = (1664525 * state + 1013904223) >>> 0;
5
+ return state / 0x100000000;
6
+ };
7
+ }
8
+ function hashSeed(seed) {
9
+ let hash = 2166136261;
10
+ for (let index = 0; index < seed.length; index += 1) {
11
+ hash ^= seed.charCodeAt(index);
12
+ hash = Math.imul(hash, 16777619);
13
+ }
14
+ return hash >>> 0;
15
+ }
16
+ //# sourceMappingURL=processing-random.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processing-random.js","sourceRoot":"","sources":["../src/processing-random.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAAC,IAAqB;IAChD,IAAI,KAAK,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACnE,OAAO,GAAG,EAAE;QACV,KAAK,GAAG,CAAC,OAAO,GAAG,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QAC7C,OAAO,KAAK,GAAG,WAAW,CAAC;IAC7B,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY;IAC5B,IAAI,IAAI,GAAG,UAAU,CAAC;IACtB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,IAAI,KAAK,CAAC,CAAC;AACpB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { QtiAttemptStateV1, QtiAttemptStatus, QtiDiagnostic, QtiPortableCustomStateValue, QtiValue } from "./types.js";
2
+ export declare function serialize(itemIdentifier: string, status: QtiAttemptStatus, responses: Record<string, QtiValue>, outcomes: Record<string, QtiValue>, templateValues: Record<string, QtiValue>, interactionStates: Record<string, QtiPortableCustomStateValue>, validationMessages: QtiDiagnostic[]): QtiAttemptStateV1;
3
+ export declare function cloneValueRecord(record: Record<string, QtiValue>): Record<string, QtiValue>;
4
+ export declare function clonePortableCustomStateRecord(record: Record<string, QtiPortableCustomStateValue>): Record<string, QtiPortableCustomStateValue>;
5
+ export declare function cloneValue(value: QtiValue): QtiValue;
6
+ export declare function clonePortableCustomState(value: QtiPortableCustomStateValue): QtiPortableCustomStateValue;
7
+ export declare function cloneDiagnostics(diagnostics: QtiDiagnostic[]): QtiDiagnostic[];
8
+ //# sourceMappingURL=processing-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processing-state.d.ts","sourceRoot":"","sources":["../src/processing-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,2BAA2B,EAC3B,QAAQ,EACT,MAAM,YAAY,CAAC;AAIpB,wBAAgB,SAAS,CACvB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,gBAAgB,EACxB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,EACnC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,EAClC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,EACxC,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,2BAA2B,CAAC,EAC9D,kBAAkB,EAAE,aAAa,EAAE,GAClC,iBAAiB,CAWnB;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAE3F;AAED,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,2BAA2B,CAAC,GAClD,MAAM,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAI7C;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,QAAQ,GAAG,QAAQ,CAIpD;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,2BAA2B,GACjC,2BAA2B,CAI7B;AAQD,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,aAAa,EAAE,GAAG,aAAa,EAAE,CAK9E"}
@@ -0,0 +1,44 @@
1
+ import { ATTEMPT_STATE_SCHEMA } from "./attempt-state-constants.js";
2
+ import { isRecordValue } from "./processing-values.js";
3
+ export function serialize(itemIdentifier, status, responses, outcomes, templateValues, interactionStates, validationMessages) {
4
+ return {
5
+ schema: ATTEMPT_STATE_SCHEMA,
6
+ itemIdentifier,
7
+ status,
8
+ responses: cloneValueRecord(responses),
9
+ outcomes: cloneValueRecord(outcomes),
10
+ templateValues: cloneValueRecord(templateValues),
11
+ interactionStates: clonePortableCustomStateRecord(interactionStates),
12
+ validationMessages: cloneDiagnostics(validationMessages),
13
+ };
14
+ }
15
+ export function cloneValueRecord(record) {
16
+ return Object.fromEntries(Object.entries(record).map(([key, value]) => [key, cloneValue(value)]));
17
+ }
18
+ export function clonePortableCustomStateRecord(record) {
19
+ return Object.fromEntries(Object.entries(record).map(([key, value]) => [key, clonePortableCustomState(value)]));
20
+ }
21
+ export function cloneValue(value) {
22
+ if (Array.isArray(value))
23
+ return [...value];
24
+ if (isRecordValue(value))
25
+ return cloneValueRecord(value);
26
+ return value;
27
+ }
28
+ export function clonePortableCustomState(value) {
29
+ if (Array.isArray(value))
30
+ return value.map(clonePortableCustomState);
31
+ if (isPortableCustomStateObject(value))
32
+ return clonePortableCustomStateRecord(value);
33
+ return value;
34
+ }
35
+ function isPortableCustomStateObject(value) {
36
+ return typeof value === "object" && value !== null && !Array.isArray(value);
37
+ }
38
+ export function cloneDiagnostics(diagnostics) {
39
+ return diagnostics.map((diagnostic) => ({
40
+ ...diagnostic,
41
+ source: diagnostic.source ? { ...diagnostic.source } : undefined,
42
+ }));
43
+ }
44
+ //# sourceMappingURL=processing-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processing-state.js","sourceRoot":"","sources":["../src/processing-state.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAEvD,MAAM,UAAU,SAAS,CACvB,cAAsB,EACtB,MAAwB,EACxB,SAAmC,EACnC,QAAkC,EAClC,cAAwC,EACxC,iBAA8D,EAC9D,kBAAmC;IAEnC,OAAO;QACL,MAAM,EAAE,oBAAoB;QAC5B,cAAc;QACd,MAAM;QACN,SAAS,EAAE,gBAAgB,CAAC,SAAS,CAAC;QACtC,QAAQ,EAAE,gBAAgB,CAAC,QAAQ,CAAC;QACpC,cAAc,EAAE,gBAAgB,CAAC,cAAc,CAAC;QAChD,iBAAiB,EAAE,8BAA8B,CAAC,iBAAiB,CAAC;QACpE,kBAAkB,EAAE,gBAAgB,CAAC,kBAAkB,CAAC;KACzD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAgC;IAC/D,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACpG,CAAC;AAED,MAAM,UAAU,8BAA8B,CAC5C,MAAmD;IAEnD,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,wBAAwB,CAAC,KAAK,CAAC,CAAC,CAAC,CACrF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAe;IACxC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;IAC5C,IAAI,aAAa,CAAC,KAAK,CAAC;QAAE,OAAO,gBAAgB,CAAC,KAAK,CAAC,CAAC;IACzD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,wBAAwB,CACtC,KAAkC;IAElC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IACrE,IAAI,2BAA2B,CAAC,KAAK,CAAC;QAAE,OAAO,8BAA8B,CAAC,KAAK,CAAC,CAAC;IACrF,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,2BAA2B,CAClC,KAAkC;IAElC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,WAA4B;IAC3D,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QACtC,GAAG,UAAU;QACb,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS;KACjE,CAAC,CAAC,CAAC;AACN,CAAC"}
@@ -0,0 +1,3 @@
1
+ export type ResponseProcessingTemplateKind = "matchCorrect" | "mapResponse" | "mapResponsePoint";
2
+ export declare function responseProcessingTemplateKind(template: string): ResponseProcessingTemplateKind | undefined;
3
+ //# sourceMappingURL=processing-templates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processing-templates.d.ts","sourceRoot":"","sources":["../src/processing-templates.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,8BAA8B,GAAG,cAAc,GAAG,aAAa,GAAG,kBAAkB,CAAC;AAEjG,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,MAAM,GACf,8BAA8B,GAAG,SAAS,CAO5C"}
@@ -0,0 +1,12 @@
1
+ export function responseProcessingTemplateKind(template) {
2
+ const path = template.split(/[?#]/, 1)[0] ?? "";
3
+ const name = path.slice(path.lastIndexOf("/") + 1).replace(/\.xml$/i, "");
4
+ if (name === "match_correct")
5
+ return "matchCorrect";
6
+ if (name === "map_response")
7
+ return "mapResponse";
8
+ if (name === "map_response_point")
9
+ return "mapResponsePoint";
10
+ return undefined;
11
+ }
12
+ //# sourceMappingURL=processing-templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processing-templates.js","sourceRoot":"","sources":["../src/processing-templates.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,8BAA8B,CAC5C,QAAgB;IAEhB,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAChD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IAC1E,IAAI,IAAI,KAAK,eAAe;QAAE,OAAO,cAAc,CAAC;IACpD,IAAI,IAAI,KAAK,cAAc;QAAE,OAAO,aAAa,CAAC;IAClD,IAAI,IAAI,KAAK,oBAAoB;QAAE,OAAO,kBAAkB,CAAC;IAC7D,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { QtiRecordValue, QtiResponseDeclaration, QtiScalarValue, QtiValue } from "./types.js";
2
+ export declare function isNullResponse(response: QtiValue): boolean;
3
+ export declare function valuesEqual(actual: QtiValue, expected: QtiValue, ordered?: boolean): boolean;
4
+ export declare function qtiMatchValues(actual: QtiValue, expected: QtiValue, ordered?: boolean): boolean | null;
5
+ export declare function normalizeValueForCardinality(value: QtiValue, cardinality: QtiResponseDeclaration["cardinality"]): QtiValue;
6
+ export declare function valueContainer(value: QtiValue): QtiScalarValue[];
7
+ export declare function isRecordValue(value: QtiValue): value is QtiRecordValue;
8
+ export declare function containsValues(collection: QtiScalarValue[], values: QtiScalarValue[]): boolean;
9
+ export declare function numericValue(value: QtiValue): number;
10
+ export declare function numericValueOrNull(value: QtiValue): number | null;
11
+ export declare function durationSeconds(value: QtiValue): number | null;
12
+ export declare function booleanValue(value: QtiValue): boolean;
13
+ export declare function booleanValueOrNull(value: QtiValue): boolean | null;
14
+ export declare function stringMatch(left: QtiValue, right: QtiValue, caseSensitive: boolean, substring: boolean): boolean | null;
15
+ //# sourceMappingURL=processing-values.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processing-values.d.ts","sourceRoot":"","sources":["../src/processing-values.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,sBAAsB,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGnG,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAE1D;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,UAAQ,GAAG,OAAO,CAsB1F;AAED,wBAAgB,cAAc,CAC5B,MAAM,EAAE,QAAQ,EAChB,QAAQ,EAAE,QAAQ,EAClB,OAAO,UAAQ,GACd,OAAO,GAAG,IAAI,CAGhB;AAkBD,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,QAAQ,EACf,WAAW,EAAE,sBAAsB,CAAC,aAAa,CAAC,GACjD,QAAQ,CAUV;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,QAAQ,GAAG,cAAc,EAAE,CAIhE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,QAAQ,GAAG,KAAK,IAAI,cAAc,CAEtE;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,cAAc,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,OAAO,CAQ9F;AAMD,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAKpD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAQjE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,CAoB9D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAMrD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,GAAG,IAAI,CAGlE;AAED,wBAAgB,WAAW,CACzB,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,QAAQ,EACf,aAAa,EAAE,OAAO,EACtB,SAAS,EAAE,OAAO,GACjB,OAAO,GAAG,IAAI,CAShB"}
@@ -0,0 +1,150 @@
1
+ import { qtiValueToString } from "./value-format.js";
2
+ export function isNullResponse(response) {
3
+ return response === null || response === "" || (Array.isArray(response) && response.length === 0);
4
+ }
5
+ export function valuesEqual(actual, expected, ordered = false) {
6
+ if (isRecordValue(actual) || isRecordValue(expected)) {
7
+ if (!isRecordValue(actual) || !isRecordValue(expected))
8
+ return false;
9
+ const actualKeys = Object.keys(actual).toSorted();
10
+ const expectedKeys = Object.keys(expected).toSorted();
11
+ return (valuesEqual(actualKeys, expectedKeys, true) &&
12
+ actualKeys.every((key) => valuesEqual(actual[key] ?? null, expected[key] ?? null, ordered)));
13
+ }
14
+ if (Array.isArray(actual) || Array.isArray(expected)) {
15
+ const actualValues = valueContainer(actual);
16
+ const expectedValues = Array.isArray(expected) ? expected : expected === null ? [] : [expected];
17
+ if (actualValues.length !== expectedValues.length)
18
+ return false;
19
+ if (ordered)
20
+ return actualValues.every((value, index) => scalarValuesEqual(value, expectedValues[index]));
21
+ const sortedExpected = [...expectedValues].toSorted(compareScalarValues);
22
+ return [...actualValues]
23
+ .toSorted(compareScalarValues)
24
+ .every((value, index) => scalarValuesEqual(value, sortedExpected[index]));
25
+ }
26
+ return scalarValuesEqual(actual, expected);
27
+ }
28
+ export function qtiMatchValues(actual, expected, ordered = false) {
29
+ if (actual === null || expected === null)
30
+ return null;
31
+ return valuesEqual(actual, expected, ordered);
32
+ }
33
+ function scalarValuesEqual(actual, expected) {
34
+ if (typeof actual === "boolean" && typeof expected === "string") {
35
+ return String(actual) === expected;
36
+ }
37
+ if (typeof actual === "string" && typeof expected === "boolean") {
38
+ return actual === String(expected);
39
+ }
40
+ if (typeof actual === "number" && typeof expected === "string") {
41
+ return String(actual) === expected;
42
+ }
43
+ if (typeof actual === "string" && typeof expected === "number") {
44
+ return actual === String(expected);
45
+ }
46
+ return actual === expected;
47
+ }
48
+ export function normalizeValueForCardinality(value, cardinality) {
49
+ if ((cardinality === "multiple" || cardinality === "ordered") &&
50
+ value !== null &&
51
+ !Array.isArray(value) &&
52
+ !isRecordValue(value)) {
53
+ return [value];
54
+ }
55
+ return value;
56
+ }
57
+ export function valueContainer(value) {
58
+ if (value === null)
59
+ return [];
60
+ if (isRecordValue(value))
61
+ return [];
62
+ return Array.isArray(value) ? value : [value];
63
+ }
64
+ export function isRecordValue(value) {
65
+ return typeof value === "object" && value !== null && !Array.isArray(value);
66
+ }
67
+ export function containsValues(collection, values) {
68
+ const remaining = [...collection];
69
+ for (const value of values) {
70
+ const index = remaining.findIndex((candidate) => valuesEqual(candidate, value));
71
+ if (index === -1)
72
+ return false;
73
+ remaining.splice(index, 1);
74
+ }
75
+ return true;
76
+ }
77
+ function compareScalarValues(left, right) {
78
+ return String(left).localeCompare(String(right));
79
+ }
80
+ export function numericValue(value) {
81
+ if (typeof value === "number")
82
+ return value;
83
+ if (typeof value === "boolean")
84
+ return value ? 1 : 0;
85
+ if (typeof value === "string")
86
+ return Number(value);
87
+ return 0;
88
+ }
89
+ export function numericValueOrNull(value) {
90
+ if (typeof value === "number")
91
+ return Number.isFinite(value) ? value : null;
92
+ if (typeof value === "boolean")
93
+ return value ? 1 : 0;
94
+ if (typeof value === "string") {
95
+ const parsed = Number(value);
96
+ return Number.isFinite(parsed) ? parsed : null;
97
+ }
98
+ return null;
99
+ }
100
+ export function durationSeconds(value) {
101
+ if (value === null || Array.isArray(value) || isRecordValue(value))
102
+ return null;
103
+ if (typeof value === "number")
104
+ return Number.isFinite(value) ? value : null;
105
+ const raw = String(value).trim();
106
+ if (raw.length === 0)
107
+ return null;
108
+ const numeric = Number(raw);
109
+ if (Number.isFinite(numeric))
110
+ return numeric;
111
+ const match = /^P(?:(\d+(?:\.\d+)?)D)?(?:T(?:(\d+(?:\.\d+)?)H)?(?:(\d+(?:\.\d+)?)M)?(?:(\d+(?:\.\d+)?)S)?)?$/i.exec(raw);
112
+ if (!match)
113
+ return null;
114
+ const [, days, hours, minutes, seconds] = match;
115
+ if (!days && !hours && !minutes && !seconds)
116
+ return null;
117
+ const total = Number(days ?? 0) * 86_400 +
118
+ Number(hours ?? 0) * 3_600 +
119
+ Number(minutes ?? 0) * 60 +
120
+ Number(seconds ?? 0);
121
+ return Number.isFinite(total) ? total : null;
122
+ }
123
+ export function booleanValue(value) {
124
+ if (typeof value === "boolean")
125
+ return value;
126
+ if (typeof value === "number")
127
+ return value !== 0;
128
+ if (typeof value === "string")
129
+ return value.length > 0 && value !== "false";
130
+ if (Array.isArray(value))
131
+ return value.length > 0;
132
+ return false;
133
+ }
134
+ export function booleanValueOrNull(value) {
135
+ if (value === null)
136
+ return null;
137
+ return booleanValue(value);
138
+ }
139
+ export function stringMatch(left, right, caseSensitive, substring) {
140
+ if (left === null || right === null)
141
+ return null;
142
+ let actual = qtiValueToString(left);
143
+ let expected = qtiValueToString(right);
144
+ if (!caseSensitive) {
145
+ actual = actual.toLocaleLowerCase();
146
+ expected = expected.toLocaleLowerCase();
147
+ }
148
+ return substring ? actual.includes(expected) : actual === expected;
149
+ }
150
+ //# sourceMappingURL=processing-values.js.map