@qti-components/processing 1.1.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/LICENSE.md +674 -0
- package/dist/components/index.d.ts +38 -0
- package/dist/components/index.js +44 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/qti-and/qti-and.d.ts +20 -0
- package/dist/components/qti-and/qti-and.js +56 -0
- package/dist/components/qti-and/qti-and.js.map +1 -0
- package/dist/components/qti-basevalue/qti-basevalue.d.ts +6 -0
- package/dist/components/qti-basevalue/qti-basevalue.js +23 -0
- package/dist/components/qti-basevalue/qti-basevalue.js.map +1 -0
- package/dist/components/qti-container-size/qti-container-size.d.ts +12 -0
- package/dist/components/qti-container-size/qti-container-size.js +40 -0
- package/dist/components/qti-container-size/qti-container-size.js.map +1 -0
- package/dist/components/qti-contains/qti-contains.d.ts +4 -0
- package/dist/components/qti-contains/qti-contains.js +38 -0
- package/dist/components/qti-contains/qti-contains.js.map +1 -0
- package/dist/components/qti-correct/qti-correct.d.ts +5 -0
- package/dist/components/qti-correct/qti-correct.js +18 -0
- package/dist/components/qti-correct/qti-correct.js.map +1 -0
- package/dist/components/qti-default/qti-default.d.ts +17 -0
- package/dist/components/qti-default/qti-default.js +87 -0
- package/dist/components/qti-default/qti-default.js.map +1 -0
- package/dist/components/qti-delete/qti-delete.d.ts +4 -0
- package/dist/components/qti-delete/qti-delete.js +23 -0
- package/dist/components/qti-delete/qti-delete.js.map +1 -0
- package/dist/components/qti-equal/qti-equal.d.ts +5 -0
- package/dist/components/qti-equal/qti-equal.js +41 -0
- package/dist/components/qti-equal/qti-equal.js.map +1 -0
- package/dist/components/qti-equal-rounded/qti-equal-rounded.d.ts +6 -0
- package/dist/components/qti-equal-rounded/qti-equal-rounded.js +84 -0
- package/dist/components/qti-equal-rounded/qti-equal-rounded.js.map +1 -0
- package/dist/components/qti-field-value/qti-field-value.d.ts +4 -0
- package/dist/components/qti-field-value/qti-field-value.js +27 -0
- package/dist/components/qti-field-value/qti-field-value.js.map +1 -0
- package/dist/components/qti-gcd/qti.gcd.d.ts +13 -0
- package/dist/components/qti-gcd/qti.gcd.js +119 -0
- package/dist/components/qti-gcd/qti.gcd.js.map +1 -0
- package/dist/components/qti-gt/qti-gt.d.ts +4 -0
- package/dist/components/qti-gt/qti-gt.js +21 -0
- package/dist/components/qti-gt/qti-gt.js.map +1 -0
- package/dist/components/qti-gte/qti-gte.d.ts +4 -0
- package/dist/components/qti-gte/qti-gte.js +24 -0
- package/dist/components/qti-gte/qti-gte.js.map +1 -0
- package/dist/components/qti-index/qti-index.d.ts +6 -0
- package/dist/components/qti-index/qti-index.js +82 -0
- package/dist/components/qti-index/qti-index.js.map +1 -0
- package/dist/components/qti-is-null/qti-is-null.d.ts +4 -0
- package/dist/components/qti-is-null/qti-is-null.js +19 -0
- package/dist/components/qti-is-null/qti-is-null.js.map +1 -0
- package/dist/components/qti-lookup-outcome-value/qti-lookup-outcome-value.d.ts +19 -0
- package/dist/components/qti-lookup-outcome-value/qti-lookup-outcome-value.js +51 -0
- package/dist/components/qti-lookup-outcome-value/qti-lookup-outcome-value.js.map +1 -0
- package/dist/components/qti-lt/qti-lt.d.ts +4 -0
- package/dist/components/qti-lt/qti-lt.js +21 -0
- package/dist/components/qti-lt/qti-lt.js.map +1 -0
- package/dist/components/qti-lte/qti-lte.d.ts +4 -0
- package/dist/components/qti-lte/qti-lte.js +24 -0
- package/dist/components/qti-lte/qti-lte.js.map +1 -0
- package/dist/components/qti-map-response/qti-map-response.d.ts +5 -0
- package/dist/components/qti-map-response/qti-map-response.js +52 -0
- package/dist/components/qti-map-response/qti-map-response.js.map +1 -0
- package/dist/components/qti-map-response-point/qti-map-response-point.d.ts +5 -0
- package/dist/components/qti-map-response-point/qti-map-response-point.js +60 -0
- package/dist/components/qti-map-response-point/qti-map-response-point.js.map +1 -0
- package/dist/components/qti-match/qti-match.d.ts +6 -0
- package/dist/components/qti-match/qti-match.js +84 -0
- package/dist/components/qti-match/qti-match.js.map +1 -0
- package/dist/components/qti-math-operator/qti-math-operator.d.ts +14 -0
- package/dist/components/qti-math-operator/qti-math-operator.js +213 -0
- package/dist/components/qti-math-operator/qti-math-operator.js.map +1 -0
- package/dist/components/qti-member/qti-member.d.ts +4 -0
- package/dist/components/qti-member/qti-member.js +34 -0
- package/dist/components/qti-member/qti-member.js.map +1 -0
- package/dist/components/qti-multiple/qti-multiple.d.ts +5 -0
- package/dist/components/qti-multiple/qti-multiple.js +26 -0
- package/dist/components/qti-multiple/qti-multiple.js.map +1 -0
- package/dist/components/qti-not/qti-not.d.ts +5 -0
- package/dist/components/qti-not/qti-not.js +14 -0
- package/dist/components/qti-not/qti-not.js.map +1 -0
- package/dist/components/qti-null/qti-null.d.ts +11 -0
- package/dist/components/qti-null/qti-null.js +15 -0
- package/dist/components/qti-null/qti-null.js.map +1 -0
- package/dist/components/qti-or/qti-or.d.ts +4 -0
- package/dist/components/qti-or/qti-or.js +39 -0
- package/dist/components/qti-or/qti-or.js.map +1 -0
- package/dist/components/qti-ordered/qti-ordered.d.ts +5 -0
- package/dist/components/qti-ordered/qti-ordered.js +19 -0
- package/dist/components/qti-ordered/qti-ordered.js.map +1 -0
- package/dist/components/qti-power/qti-power.d.ts +12 -0
- package/dist/components/qti-power/qti-power.js +99 -0
- package/dist/components/qti-power/qti-power.js.map +1 -0
- package/dist/components/qti-printed-variable/qti-printed-variable.d.ts +9 -0
- package/dist/components/qti-printed-variable/qti-printed-variable.js +29 -0
- package/dist/components/qti-printed-variable/qti-printed-variable.js.map +1 -0
- package/dist/components/qti-product/qti-product.d.ts +4 -0
- package/dist/components/qti-product/qti-product.js +23 -0
- package/dist/components/qti-product/qti-product.js.map +1 -0
- package/dist/components/qti-random/qti-random.d.ts +4 -0
- package/dist/components/qti-random/qti-random.js +19 -0
- package/dist/components/qti-random/qti-random.js.map +1 -0
- package/dist/components/qti-random-integer/qti-random-integer.d.ts +18 -0
- package/dist/components/qti-random-integer/qti-random-integer.js +90 -0
- package/dist/components/qti-random-integer/qti-random-integer.js.map +1 -0
- package/dist/components/qti-response-condition/qti-response-condition.d.ts +5 -0
- package/dist/components/qti-response-condition/qti-response-condition.js +19 -0
- package/dist/components/qti-response-condition/qti-response-condition.js.map +1 -0
- package/dist/components/qti-response-else/qti-response-else.d.ts +8 -0
- package/dist/components/qti-response-else/qti-response-else.js +21 -0
- package/dist/components/qti-response-else/qti-response-else.js.map +1 -0
- package/dist/components/qti-response-else-if/qti-response-else-if.d.ts +4 -0
- package/dist/components/qti-response-else-if/qti-response-else-if.js +9 -0
- package/dist/components/qti-response-else-if/qti-response-else-if.js.map +1 -0
- package/dist/components/qti-response-if/qti-response-if.d.ts +6 -0
- package/dist/components/qti-response-if/qti-response-if.js +17 -0
- package/dist/components/qti-response-if/qti-response-if.js.map +1 -0
- package/dist/components/qti-round/qti-round.d.ts +13 -0
- package/dist/components/qti-round/qti-round.js +66 -0
- package/dist/components/qti-round/qti-round.js.map +1 -0
- package/dist/components/qti-round-to/qti-round-to.d.ts +15 -0
- package/dist/components/qti-round-to/qti-round-to.js +117 -0
- package/dist/components/qti-round-to/qti-round-to.js.map +1 -0
- package/dist/components/qti-rule/qti-rule.d.ts +11 -0
- package/dist/components/qti-rule/qti-rule.js +21 -0
- package/dist/components/qti-rule/qti-rule.js.map +1 -0
- package/dist/components/qti-set-outcome-value/qti-set-outcome-value.d.ts +24 -0
- package/dist/components/qti-set-outcome-value/qti-set-outcome-value.js +63 -0
- package/dist/components/qti-set-outcome-value/qti-set-outcome-value.js.map +1 -0
- package/dist/components/qti-string-match/qti-string-match.d.ts +5 -0
- package/dist/components/qti-string-match/qti-string-match.js +39 -0
- package/dist/components/qti-string-match/qti-string-match.js.map +1 -0
- package/dist/components/qti-subtract/index.d.ts +7 -0
- package/dist/components/qti-subtract/index.js +4 -0
- package/dist/components/qti-subtract/index.js.map +1 -0
- package/dist/components/qti-subtract/qti-subtract.d.ts +20 -0
- package/dist/components/qti-subtract/qti-subtract.js +34 -0
- package/dist/components/qti-subtract/qti-subtract.js.map +1 -0
- package/dist/components/qti-sum/qti-sum.d.ts +12 -0
- package/dist/components/qti-sum/qti-sum.js +36 -0
- package/dist/components/qti-sum/qti-sum.js.map +1 -0
- package/dist/components/qti-variable/qti-variable.d.ts +4 -0
- package/dist/components/qti-variable/qti-variable.js +10 -0
- package/dist/components/qti-variable/qti-variable.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { QtiResponseElse } from '../qti-response-else/qti-response-else';
|
|
2
|
+
export class QtiResponseIf extends QtiResponseElse {
|
|
3
|
+
calculate() {
|
|
4
|
+
const expression = this.firstElementChild;
|
|
5
|
+
const result = expression.calculate();
|
|
6
|
+
return result;
|
|
7
|
+
}
|
|
8
|
+
getSubRules() {
|
|
9
|
+
const result = [];
|
|
10
|
+
for (let i = 1; i < this.children.length; i++) {
|
|
11
|
+
result.push(this.children[i]);
|
|
12
|
+
}
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
customElements.define('qti-response-if', QtiResponseIf);
|
|
17
|
+
//# sourceMappingURL=qti-response-if.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qti-response-if.js","sourceRoot":"","sources":["../../../src/components/qti-response-if/qti-response-if.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAC;AAKzE,MAAM,OAAO,aAAc,SAAQ,eAAe;IAChC,SAAS;QACvB,MAAM,UAAU,GAAG,IAAI,CAAC,iBAA2C,CAAC;QACpE,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,EAAa,CAAC;QACjD,OAAO,MAAM,CAAC;IAChB,CAAC;IAEe,WAAW;QACzB,MAAM,MAAM,GAAG,EAAE,CAAC;QAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC9C,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAY,CAAC,CAAC;QAC3C,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAED,cAAc,CAAC,MAAM,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC","sourcesContent":["import { QtiResponseElse } from '../qti-response-else/qti-response-else';\n\nimport type { QtiExpression } from '@qti-components/base';\nimport type { QtiRule } from '../qti-rule/qti-rule';\n\nexport class QtiResponseIf extends QtiResponseElse {\n public override calculate() {\n const expression = this.firstElementChild as QtiExpression<boolean>;\n const result = expression.calculate() as boolean;\n return result;\n }\n\n public override getSubRules(): QtiRule[] {\n const result = [];\n for (let i = 1; i < this.children.length; i++) {\n result.push(this.children[i] as QtiRule);\n }\n return result;\n }\n}\n\ncustomElements.define('qti-response-if', QtiResponseIf);\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { QtiExpression } from '@qti-components/base';
|
|
2
|
+
/**
|
|
3
|
+
* @summary The qti-round operator rounds a numerical value to the nearest integer.
|
|
4
|
+
* @documentation https://www.imsglobal.org/spec/qti/v3p0/impl#h.round
|
|
5
|
+
*
|
|
6
|
+
* Takes a single sub-expression with single cardinality and numerical base-type.
|
|
7
|
+
* Returns an integer formed by rounding the value using the rule: n for all input
|
|
8
|
+
* values in the range [n-0.5, n+0.5). For example, 6.8 and 6.5 both round to 7,
|
|
9
|
+
* 6.49 rounds to 6, and -6.5 rounds to -6.
|
|
10
|
+
*/
|
|
11
|
+
export declare class QtiRound extends QtiExpression<number | null> {
|
|
12
|
+
getResult(): number | null;
|
|
13
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { QtiExpression } from '@qti-components/base';
|
|
2
|
+
/**
|
|
3
|
+
* @summary The qti-round operator rounds a numerical value to the nearest integer.
|
|
4
|
+
* @documentation https://www.imsglobal.org/spec/qti/v3p0/impl#h.round
|
|
5
|
+
*
|
|
6
|
+
* Takes a single sub-expression with single cardinality and numerical base-type.
|
|
7
|
+
* Returns an integer formed by rounding the value using the rule: n for all input
|
|
8
|
+
* values in the range [n-0.5, n+0.5). For example, 6.8 and 6.5 both round to 7,
|
|
9
|
+
* 6.49 rounds to 6, and -6.5 rounds to -6.
|
|
10
|
+
*/
|
|
11
|
+
export class QtiRound extends QtiExpression {
|
|
12
|
+
getResult() {
|
|
13
|
+
if (this.children.length !== 1) {
|
|
14
|
+
console.error('qti-round must have exactly one child expression');
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
const variables = this.getVariables();
|
|
18
|
+
if (!variables || variables.length === 0) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const variable = variables[0];
|
|
22
|
+
// Check cardinality
|
|
23
|
+
if (variable.cardinality !== 'single') {
|
|
24
|
+
console.error('qti-round requires single cardinality');
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
// Check if value is array (shouldn't be for single cardinality)
|
|
28
|
+
if (Array.isArray(variable.value)) {
|
|
29
|
+
console.error('qti-round unexpected array value for single cardinality');
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
// Handle null values
|
|
33
|
+
if (variable.value === null || variable.value === undefined) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
// Check base type
|
|
37
|
+
if (variable.baseType !== 'integer' && variable.baseType !== 'float') {
|
|
38
|
+
console.error('qti-round requires numerical base-type (integer or float)');
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
// Convert to number
|
|
42
|
+
const numericValue = parseFloat(variable.value);
|
|
43
|
+
// Handle special cases
|
|
44
|
+
if (isNaN(numericValue)) {
|
|
45
|
+
console.warn('qti-round: NaN input results in NULL');
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
if (!isFinite(numericValue)) {
|
|
49
|
+
// Handle infinity cases
|
|
50
|
+
if (numericValue === Infinity) {
|
|
51
|
+
return Infinity;
|
|
52
|
+
}
|
|
53
|
+
if (numericValue === -Infinity) {
|
|
54
|
+
return -Infinity;
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
// Apply QTI rounding rule: result is integer n for all input values in [n-0.5, n+0.5)
|
|
59
|
+
// This means we need to find n such that: n-0.5 <= value < n+0.5
|
|
60
|
+
// Rearranging: n <= value + 0.5 < n + 1
|
|
61
|
+
// So n = floor(value + 0.5)
|
|
62
|
+
return Math.floor(numericValue + 0.5);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
customElements.define('qti-round', QtiRound);
|
|
66
|
+
//# sourceMappingURL=qti-round.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qti-round.js","sourceRoot":"","sources":["../../../src/components/qti-round/qti-round.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAIrD;;;;;;;;GAQG;AACH,MAAM,OAAO,QAAS,SAAQ,aAA4B;IACxC,SAAS;QACvB,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,OAAO,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;YAClE,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,EAAwB,CAAC;QAC5D,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,QAAQ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAE9B,oBAAoB;QACpB,IAAI,QAAQ,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;YACtC,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;YACvD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,gEAAgE;QAChE,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAClC,OAAO,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC;YACzE,OAAO,IAAI,CAAC;QACd,CAAC;QAED,qBAAqB;QACrB,IAAI,QAAQ,CAAC,KAAK,KAAK,IAAI,IAAI,QAAQ,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC5D,OAAO,IAAI,CAAC;QACd,CAAC;QAED,kBAAkB;QAClB,IAAI,QAAQ,CAAC,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;YACrE,OAAO,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;YAC3E,OAAO,IAAI,CAAC;QACd,CAAC;QAED,oBAAoB;QACpB,MAAM,YAAY,GAAG,UAAU,CAAC,QAAQ,CAAC,KAAe,CAAC,CAAC;QAE1D,uBAAuB;QACvB,IAAI,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;YACrD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;YAC5B,wBAAwB;YACxB,IAAI,YAAY,KAAK,QAAQ,EAAE,CAAC;gBAC9B,OAAO,QAAQ,CAAC;YAClB,CAAC;YACD,IAAI,YAAY,KAAK,CAAC,QAAQ,EAAE,CAAC;gBAC/B,OAAO,CAAC,QAAQ,CAAC;YACnB,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,sFAAsF;QACtF,iEAAiE;QACjE,wCAAwC;QACxC,4BAA4B;QAC5B,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,GAAG,CAAC,CAAC;IACxC,CAAC;CACF;AAED,cAAc,CAAC,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC","sourcesContent":["import { QtiExpression } from '@qti-components/base';\n\nimport type { ResponseVariable } from '@qti-components/base';\n\n/**\n * @summary The qti-round operator rounds a numerical value to the nearest integer.\n * @documentation https://www.imsglobal.org/spec/qti/v3p0/impl#h.round\n *\n * Takes a single sub-expression with single cardinality and numerical base-type.\n * Returns an integer formed by rounding the value using the rule: n for all input\n * values in the range [n-0.5, n+0.5). For example, 6.8 and 6.5 both round to 7,\n * 6.49 rounds to 6, and -6.5 rounds to -6.\n */\nexport class QtiRound extends QtiExpression<number | null> {\n public override getResult(): number | null {\n if (this.children.length !== 1) {\n console.error('qti-round must have exactly one child expression');\n return null;\n }\n\n const variables = this.getVariables() as ResponseVariable[];\n if (!variables || variables.length === 0) {\n return null;\n }\n\n const variable = variables[0];\n\n // Check cardinality\n if (variable.cardinality !== 'single') {\n console.error('qti-round requires single cardinality');\n return null;\n }\n\n // Check if value is array (shouldn't be for single cardinality)\n if (Array.isArray(variable.value)) {\n console.error('qti-round unexpected array value for single cardinality');\n return null;\n }\n\n // Handle null values\n if (variable.value === null || variable.value === undefined) {\n return null;\n }\n\n // Check base type\n if (variable.baseType !== 'integer' && variable.baseType !== 'float') {\n console.error('qti-round requires numerical base-type (integer or float)');\n return null;\n }\n\n // Convert to number\n const numericValue = parseFloat(variable.value as string);\n\n // Handle special cases\n if (isNaN(numericValue)) {\n console.warn('qti-round: NaN input results in NULL');\n return null;\n }\n\n if (!isFinite(numericValue)) {\n // Handle infinity cases\n if (numericValue === Infinity) {\n return Infinity;\n }\n if (numericValue === -Infinity) {\n return -Infinity;\n }\n return null;\n }\n\n // Apply QTI rounding rule: result is integer n for all input values in [n-0.5, n+0.5)\n // This means we need to find n such that: n-0.5 <= value < n+0.5\n // Rearranging: n <= value + 0.5 < n + 1\n // So n = floor(value + 0.5)\n return Math.floor(numericValue + 0.5);\n }\n}\n\ncustomElements.define('qti-round', QtiRound);\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { QtiExpression } from '@qti-components/base';
|
|
2
|
+
/**
|
|
3
|
+
* @summary The qti-round-to operator rounds a numerical value to specified precision.
|
|
4
|
+
* @documentation https://www.imsglobal.org/spec/qti/v3p0/impl#h.round-to
|
|
5
|
+
*
|
|
6
|
+
* Takes one sub-expression with single cardinality and numerical base-type.
|
|
7
|
+
* Returns a single float rounded by the specified method to the specified precision.
|
|
8
|
+
* Supports rounding to decimal places or significant figures.
|
|
9
|
+
*/
|
|
10
|
+
export declare class QtiRoundTo extends QtiExpression<number | null> {
|
|
11
|
+
#private;
|
|
12
|
+
roundingMode: 'decimalPlaces' | 'significantFigures';
|
|
13
|
+
figures: number;
|
|
14
|
+
getResult(): number | null;
|
|
15
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { property } from 'lit/decorators.js';
|
|
8
|
+
import { QtiExpression } from '@qti-components/base';
|
|
9
|
+
/**
|
|
10
|
+
* @summary The qti-round-to operator rounds a numerical value to specified precision.
|
|
11
|
+
* @documentation https://www.imsglobal.org/spec/qti/v3p0/impl#h.round-to
|
|
12
|
+
*
|
|
13
|
+
* Takes one sub-expression with single cardinality and numerical base-type.
|
|
14
|
+
* Returns a single float rounded by the specified method to the specified precision.
|
|
15
|
+
* Supports rounding to decimal places or significant figures.
|
|
16
|
+
*/
|
|
17
|
+
export class QtiRoundTo extends QtiExpression {
|
|
18
|
+
constructor() {
|
|
19
|
+
super(...arguments);
|
|
20
|
+
this.roundingMode = 'significantFigures';
|
|
21
|
+
this.figures = 3;
|
|
22
|
+
}
|
|
23
|
+
getResult() {
|
|
24
|
+
if (this.children.length !== 1) {
|
|
25
|
+
console.error('qti-round-to must have exactly one child expression');
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
const variables = this.getVariables();
|
|
29
|
+
if (!variables || variables.length === 0) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
const variable = variables[0];
|
|
33
|
+
// Check cardinality
|
|
34
|
+
if (variable.cardinality !== 'single') {
|
|
35
|
+
console.error('qti-round-to requires single cardinality');
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
// Check if value is array (shouldn't be for single cardinality)
|
|
39
|
+
if (Array.isArray(variable.value)) {
|
|
40
|
+
console.error('qti-round-to unexpected array value for single cardinality');
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
// Handle null values
|
|
44
|
+
if (variable.value === null || variable.value === undefined) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
// Check base type
|
|
48
|
+
if (variable.baseType !== 'integer' && variable.baseType !== 'float') {
|
|
49
|
+
console.error('qti-round-to requires numerical base-type');
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
// Convert to number
|
|
53
|
+
const numericValue = parseFloat(variable.value);
|
|
54
|
+
// Handle special cases
|
|
55
|
+
if (isNaN(numericValue)) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
if (!isFinite(numericValue)) {
|
|
59
|
+
// Handle infinity cases
|
|
60
|
+
if (numericValue === Infinity) {
|
|
61
|
+
return Infinity;
|
|
62
|
+
}
|
|
63
|
+
if (numericValue === -Infinity) {
|
|
64
|
+
return -Infinity;
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
// Validate figures
|
|
69
|
+
if (this.figures < 0) {
|
|
70
|
+
console.error('qti-round-to: figures must be non-negative');
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
if (this.roundingMode === 'significantFigures' && this.figures < 1) {
|
|
74
|
+
console.error('qti-round-to: figures must be at least 1 for significantFigures mode');
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
// Perform rounding
|
|
78
|
+
if (this.roundingMode === 'decimalPlaces') {
|
|
79
|
+
return this.#roundToDecimalPlaces(numericValue, this.figures);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
return this.#roundToSignificantFigures(numericValue, this.figures);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Round to specified number of decimal places
|
|
87
|
+
*/
|
|
88
|
+
#roundToDecimalPlaces(value, decimalPlaces) {
|
|
89
|
+
if (value === 0) {
|
|
90
|
+
return 0;
|
|
91
|
+
}
|
|
92
|
+
const multiplier = Math.pow(10, decimalPlaces);
|
|
93
|
+
return Math.round(value * multiplier) / multiplier;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Round to specified number of significant figures
|
|
97
|
+
*/
|
|
98
|
+
#roundToSignificantFigures(value, significantFigures) {
|
|
99
|
+
if (value === 0) {
|
|
100
|
+
return 0;
|
|
101
|
+
}
|
|
102
|
+
// Find the order of magnitude of the first non-zero digit
|
|
103
|
+
const magnitude = Math.floor(Math.log10(Math.abs(value)));
|
|
104
|
+
// Calculate the multiplier to shift the decimal point
|
|
105
|
+
const multiplier = Math.pow(10, significantFigures - magnitude - 1);
|
|
106
|
+
// Round and shift back
|
|
107
|
+
return Math.round(value * multiplier) / multiplier;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
__decorate([
|
|
111
|
+
property({ type: String, attribute: 'rounding-mode' })
|
|
112
|
+
], QtiRoundTo.prototype, "roundingMode", void 0);
|
|
113
|
+
__decorate([
|
|
114
|
+
property({ type: Number })
|
|
115
|
+
], QtiRoundTo.prototype, "figures", void 0);
|
|
116
|
+
customElements.define('qti-round-to', QtiRoundTo);
|
|
117
|
+
//# sourceMappingURL=qti-round-to.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qti-round-to.js","sourceRoot":"","sources":["../../../src/components/qti-round-to/qti-round-to.ts"],"names":[],"mappings":"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","sourcesContent":["import { property } from 'lit/decorators.js';\n\nimport { QtiExpression } from '@qti-components/base';\n\nimport type { ResponseVariable } from '@qti-components/base';\n\n/**\n * @summary The qti-round-to operator rounds a numerical value to specified precision.\n * @documentation https://www.imsglobal.org/spec/qti/v3p0/impl#h.round-to\n *\n * Takes one sub-expression with single cardinality and numerical base-type.\n * Returns a single float rounded by the specified method to the specified precision.\n * Supports rounding to decimal places or significant figures.\n */\nexport class QtiRoundTo extends QtiExpression<number | null> {\n @property({ type: String, attribute: 'rounding-mode' })\n roundingMode: 'decimalPlaces' | 'significantFigures' = 'significantFigures';\n\n @property({ type: Number })\n figures: number = 3;\n\n public override getResult(): number | null {\n if (this.children.length !== 1) {\n console.error('qti-round-to must have exactly one child expression');\n return null;\n }\n\n const variables = this.getVariables() as ResponseVariable[];\n if (!variables || variables.length === 0) {\n return null;\n }\n\n const variable = variables[0];\n\n // Check cardinality\n if (variable.cardinality !== 'single') {\n console.error('qti-round-to requires single cardinality');\n return null;\n }\n\n // Check if value is array (shouldn't be for single cardinality)\n if (Array.isArray(variable.value)) {\n console.error('qti-round-to unexpected array value for single cardinality');\n return null;\n }\n\n // Handle null values\n if (variable.value === null || variable.value === undefined) {\n return null;\n }\n\n // Check base type\n if (variable.baseType !== 'integer' && variable.baseType !== 'float') {\n console.error('qti-round-to requires numerical base-type');\n return null;\n }\n\n // Convert to number\n const numericValue = parseFloat(variable.value as string);\n\n // Handle special cases\n if (isNaN(numericValue)) {\n return null;\n }\n\n if (!isFinite(numericValue)) {\n // Handle infinity cases\n if (numericValue === Infinity) {\n return Infinity;\n }\n if (numericValue === -Infinity) {\n return -Infinity;\n }\n return null;\n }\n\n // Validate figures\n if (this.figures < 0) {\n console.error('qti-round-to: figures must be non-negative');\n return null;\n }\n\n if (this.roundingMode === 'significantFigures' && this.figures < 1) {\n console.error('qti-round-to: figures must be at least 1 for significantFigures mode');\n return null;\n }\n\n // Perform rounding\n if (this.roundingMode === 'decimalPlaces') {\n return this.#roundToDecimalPlaces(numericValue, this.figures);\n } else {\n return this.#roundToSignificantFigures(numericValue, this.figures);\n }\n }\n\n /**\n * Round to specified number of decimal places\n */\n #roundToDecimalPlaces(value: number, decimalPlaces: number): number {\n if (value === 0) {\n return 0;\n }\n\n const multiplier = Math.pow(10, decimalPlaces);\n return Math.round(value * multiplier) / multiplier;\n }\n\n /**\n * Round to specified number of significant figures\n */\n #roundToSignificantFigures(value: number, significantFigures: number): number {\n if (value === 0) {\n return 0;\n }\n\n // Find the order of magnitude of the first non-zero digit\n const magnitude = Math.floor(Math.log10(Math.abs(value)));\n\n // Calculate the multiplier to shift the decimal point\n const multiplier = Math.pow(10, significantFigures - magnitude - 1);\n\n // Round and shift back\n return Math.round(value * multiplier) / multiplier;\n }\n}\n\ncustomElements.define('qti-round-to', QtiRoundTo);\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
import type { QtiRuleBase } from '@qti-components/base';
|
|
3
|
+
export declare class QtiRule extends LitElement implements QtiRuleBase {
|
|
4
|
+
render(): import("lit").TemplateResult<1>;
|
|
5
|
+
process(): void;
|
|
6
|
+
}
|
|
7
|
+
declare global {
|
|
8
|
+
interface HTMLElementTagNameMap {
|
|
9
|
+
'qti-rule': QtiRule;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { customElement } from 'lit/decorators.js';
|
|
8
|
+
import { html, LitElement } from 'lit';
|
|
9
|
+
let QtiRule = class QtiRule extends LitElement {
|
|
10
|
+
render() {
|
|
11
|
+
return html `<slot></slot>`;
|
|
12
|
+
}
|
|
13
|
+
process() {
|
|
14
|
+
throw new Error('Not implemented');
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
QtiRule = __decorate([
|
|
18
|
+
customElement('qti-rule')
|
|
19
|
+
], QtiRule);
|
|
20
|
+
export { QtiRule };
|
|
21
|
+
//# sourceMappingURL=qti-rule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qti-rule.js","sourceRoot":"","sources":["../../../src/components/qti-rule/qti-rule.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AAKhC,IAAM,OAAO,GAAb,MAAM,OAAQ,SAAQ,UAAU;IAC5B,MAAM;QACb,OAAO,IAAI,CAAA,eAAe,CAAC;IAC7B,CAAC;IAEM,OAAO;QACZ,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACrC,CAAC;CACF,CAAA;AARY,OAAO;IADnB,aAAa,CAAC,UAAU,CAAC;GACb,OAAO,CAQnB","sourcesContent":["import { customElement } from 'lit/decorators.js';\nimport { html, LitElement } from 'lit';\n\nimport type { QtiRuleBase } from '@qti-components/base';\n\n@customElement('qti-rule')\nexport class QtiRule extends LitElement implements QtiRuleBase {\n override render() {\n return html`<slot></slot>`;\n }\n\n public process() {\n throw new Error('Not implemented');\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'qti-rule': QtiRule;\n }\n}\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { QtiRule } from '../qti-rule/qti-rule';
|
|
2
|
+
import type { QtiExpressionBase } from '@qti-components/base';
|
|
3
|
+
import type { QtiRuleBase } from '@qti-components/base';
|
|
4
|
+
/**
|
|
5
|
+
* Web component that processes `setOutcomeValue` in QTI.
|
|
6
|
+
*/
|
|
7
|
+
export declare class QtiSetOutcomeValue extends QtiRule {
|
|
8
|
+
#private;
|
|
9
|
+
/**
|
|
10
|
+
* Processes the QTI rule and dispatches a custom event with the computed outcome value.
|
|
11
|
+
*/
|
|
12
|
+
process(): void;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Encapsulates the logic for processing QTI setOutcomeValue expressions.
|
|
16
|
+
*/
|
|
17
|
+
export declare class QtiSetOutcomeValueRule<T> implements QtiRuleBase {
|
|
18
|
+
private expression;
|
|
19
|
+
constructor(expression: QtiExpressionBase<T>);
|
|
20
|
+
/**
|
|
21
|
+
* Evaluates the expression and returns its value.
|
|
22
|
+
*/
|
|
23
|
+
process(): string | string[] | null;
|
|
24
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { convertNumberToUniversalFormat } from '@qti-components/base';
|
|
2
|
+
import { QtiRule } from '../qti-rule/qti-rule';
|
|
3
|
+
/**
|
|
4
|
+
* Web component that processes `setOutcomeValue` in QTI.
|
|
5
|
+
*/
|
|
6
|
+
export class QtiSetOutcomeValue extends QtiRule {
|
|
7
|
+
/**
|
|
8
|
+
* Processes the QTI rule and dispatches a custom event with the computed outcome value.
|
|
9
|
+
*/
|
|
10
|
+
process() {
|
|
11
|
+
const outcomeIdentifier = this.getAttribute('identifier');
|
|
12
|
+
if (!outcomeIdentifier) {
|
|
13
|
+
console.warn('QtiSetOutcomeValue: Missing "identifier" attribute.');
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const expression = this.firstElementChild;
|
|
17
|
+
if (!expression) {
|
|
18
|
+
console.warn('QtiSetOutcomeValue: No expression found.');
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const rule = new QtiSetOutcomeValueRule(expression);
|
|
22
|
+
const value = rule.process();
|
|
23
|
+
this.dispatchEvent(new CustomEvent('qti-set-outcome-value', {
|
|
24
|
+
bubbles: true,
|
|
25
|
+
composed: true,
|
|
26
|
+
detail: {
|
|
27
|
+
outcomeIdentifier,
|
|
28
|
+
value: this.#formatValue(value)
|
|
29
|
+
}
|
|
30
|
+
}));
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Formats the computed value before dispatching.
|
|
34
|
+
* Ensures numbers are converted to a universal format.
|
|
35
|
+
*/
|
|
36
|
+
#formatValue(value) {
|
|
37
|
+
if (Array.isArray(value)) {
|
|
38
|
+
return value.map(convertNumberToUniversalFormat);
|
|
39
|
+
}
|
|
40
|
+
return value !== null ? convertNumberToUniversalFormat(value) : null;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Encapsulates the logic for processing QTI setOutcomeValue expressions.
|
|
45
|
+
*/
|
|
46
|
+
export class QtiSetOutcomeValueRule {
|
|
47
|
+
constructor(expression) {
|
|
48
|
+
this.expression = expression;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Evaluates the expression and returns its value.
|
|
52
|
+
*/
|
|
53
|
+
process() {
|
|
54
|
+
const value = (this.expression.calculate() ?? null);
|
|
55
|
+
if (value === null) {
|
|
56
|
+
console.warn('QtiSetOutcomeValueRule: Evaluated value is null.');
|
|
57
|
+
}
|
|
58
|
+
return Array.isArray(value) ? value.map((v) => (v.value ? v.value : v)) : value;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Define the custom element
|
|
62
|
+
customElements.define('qti-set-outcome-value', QtiSetOutcomeValue);
|
|
63
|
+
//# sourceMappingURL=qti-set-outcome-value.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qti-set-outcome-value.js","sourceRoot":"","sources":["../../../src/components/qti-set-outcome-value/qti-set-outcome-value.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,8BAA8B,EAAE,MAAM,sBAAsB,CAAC;AAEtE,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAM/C;;GAEG;AACH,MAAM,OAAO,kBAAmB,SAAQ,OAAO;IAC7C;;OAEG;IACa,OAAO;QACrB,MAAM,iBAAiB,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;QAE1D,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,OAAO,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAC;YACpE,OAAO;QACT,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAsE,CAAC;QAE/F,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;YACzD,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,sBAAsB,CAAqC,UAAU,CAAC,CAAC;QACxF,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAE7B,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAiE,uBAAuB,EAAE;YACvG,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;YACd,MAAM,EAAE;gBACN,iBAAiB;gBACjB,KAAK,EAAE,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC;aAChC;SACF,CAAC,CACH,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,YAAY,CAAC,KAA+B;QAC1C,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,KAAK,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;QACnD,CAAC;QACD,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,8BAA8B,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACvE,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,sBAAsB;IACjC,YAAoB,UAAgC;QAAhC,eAAU,GAAV,UAAU,CAAsB;IAAG,CAAC;IAExD;;OAEG;IACH,OAAO;QACL,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,IAAI,IAAI,CAAwC,CAAC;QAE3F,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,OAAO,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;QACnE,CAAC;QAED,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAE,KAAa,CAAC,GAAG,CAAC,CAAC,CAAiB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC3G,CAAC;CACF;AAED,4BAA4B;AAC5B,cAAc,CAAC,MAAM,CAAC,uBAAuB,EAAE,kBAAkB,CAAC,CAAC","sourcesContent":["import { convertNumberToUniversalFormat } from '@qti-components/base';\n\nimport { QtiRule } from '../qti-rule/qti-rule';\n\nimport type { ResponseVariable } from '@qti-components/base';\nimport type { QtiExpression, QtiExpressionBase } from '@qti-components/base';\nimport type { QtiRuleBase } from '@qti-components/base';\n\n/**\n * Web component that processes `setOutcomeValue` in QTI.\n */\nexport class QtiSetOutcomeValue extends QtiRule {\n /**\n * Processes the QTI rule and dispatches a custom event with the computed outcome value.\n */\n public override process(): void {\n const outcomeIdentifier = this.getAttribute('identifier');\n\n if (!outcomeIdentifier) {\n console.warn('QtiSetOutcomeValue: Missing \"identifier\" attribute.');\n return;\n }\n\n const expression = this.firstElementChild as QtiExpression<string | ResponseVariable[]> | null;\n\n if (!expression) {\n console.warn('QtiSetOutcomeValue: No expression found.');\n return;\n }\n\n const rule = new QtiSetOutcomeValueRule<string | ResponseVariable[] | null>(expression);\n const value = rule.process();\n\n this.dispatchEvent(\n new CustomEvent<{ outcomeIdentifier: string; value: string | string[] | null }>('qti-set-outcome-value', {\n bubbles: true,\n composed: true,\n detail: {\n outcomeIdentifier,\n value: this.#formatValue(value)\n }\n })\n );\n }\n\n /**\n * Formats the computed value before dispatching.\n * Ensures numbers are converted to a universal format.\n */\n #formatValue(value: string | string[] | null): string | string[] | null {\n if (Array.isArray(value)) {\n return value.map(convertNumberToUniversalFormat);\n }\n return value !== null ? convertNumberToUniversalFormat(value) : null;\n }\n}\n\n/**\n * Encapsulates the logic for processing QTI setOutcomeValue expressions.\n */\nexport class QtiSetOutcomeValueRule<T> implements QtiRuleBase {\n constructor(private expression: QtiExpressionBase<T>) {}\n\n /**\n * Evaluates the expression and returns its value.\n */\n process(): string | string[] | null {\n const value = (this.expression.calculate() ?? null) as unknown as string | string[] | null;\n\n if (value === null) {\n console.warn('QtiSetOutcomeValueRule: Evaluated value is null.');\n }\n\n return Array.isArray(value) ? (value as any).map((v: { value: any }) => (v.value ? v.value : v)) : value;\n }\n}\n\n// Define the custom element\ncustomElements.define('qti-set-outcome-value', QtiSetOutcomeValue);\n"]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { property } from 'lit/decorators.js';
|
|
8
|
+
import { ScoringHelper } from '@qti-components/base';
|
|
9
|
+
import { QtiExpression } from '@qti-components/base';
|
|
10
|
+
export class QtiStringMatch extends QtiExpression {
|
|
11
|
+
constructor() {
|
|
12
|
+
super(...arguments);
|
|
13
|
+
this.caseSensitive = 'true';
|
|
14
|
+
}
|
|
15
|
+
getResult() {
|
|
16
|
+
if (this.children.length === 2) {
|
|
17
|
+
const values = this.getVariables();
|
|
18
|
+
const value1 = values[0];
|
|
19
|
+
const value2 = values[1];
|
|
20
|
+
if (value1.cardinality !== 'single' ||
|
|
21
|
+
value2.cardinality !== 'single' ||
|
|
22
|
+
Array.isArray(value1.value) ||
|
|
23
|
+
Array.isArray(value2.value)) {
|
|
24
|
+
console.error('unexpected cardinality in qti string-match');
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
const v1 = this.caseSensitive === 'true' ? value1.value : value1.value.toLowerCase();
|
|
28
|
+
const v2 = this.caseSensitive === 'true' ? value2.value : value2.value.toLowerCase();
|
|
29
|
+
return ScoringHelper.compareSingleValues(v1, v2, value1.baseType);
|
|
30
|
+
}
|
|
31
|
+
console.error('unexpected number of children in qti-string-match');
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
__decorate([
|
|
36
|
+
property({ type: String, attribute: 'case-sensitive' })
|
|
37
|
+
], QtiStringMatch.prototype, "caseSensitive", void 0);
|
|
38
|
+
customElements.define('qti-string-match', QtiStringMatch);
|
|
39
|
+
//# sourceMappingURL=qti-string-match.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qti-string-match.js","sourceRoot":"","sources":["../../../src/components/qti-string-match/qti-string-match.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAE7C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAIrD,MAAM,OAAO,cAAe,SAAQ,aAAsB;IAA1D;;QAC2D,kBAAa,GAAG,MAAM,CAAC;IAuBlF,CAAC;IArBiB,SAAS;QACvB,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,EAAwB,CAAC;YACzD,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YACzB,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YACzB,IACE,MAAM,CAAC,WAAW,KAAK,QAAQ;gBAC/B,MAAM,CAAC,WAAW,KAAK,QAAQ;gBAC/B,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;gBAC3B,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAC3B,CAAC;gBACD,OAAO,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;gBAC5D,OAAO,KAAK,CAAC;YACf,CAAC;YACD,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAE,MAAM,CAAC,KAAgB,CAAC,WAAW,EAAE,CAAC;YACjG,MAAM,EAAE,GAAG,IAAI,CAAC,aAAa,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAE,MAAM,CAAC,KAAgB,CAAC,WAAW,EAAE,CAAC;YACjG,OAAO,aAAa,CAAC,mBAAmB,CAAC,EAAY,EAAE,EAAY,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QACxF,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACnE,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAvB0D;IAAxD,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,gBAAgB,EAAE,CAAC;qDAAwB;AAyBlF,cAAc,CAAC,MAAM,CAAC,kBAAkB,EAAE,cAAc,CAAC,CAAC","sourcesContent":["import { property } from 'lit/decorators.js';\n\nimport { ScoringHelper } from '@qti-components/base';\nimport { QtiExpression } from '@qti-components/base';\n\nimport type { ResponseVariable } from '@qti-components/base';\n\nexport class QtiStringMatch extends QtiExpression<boolean> {\n @property({ type: String, attribute: 'case-sensitive' }) caseSensitive = 'true';\n\n public override getResult() {\n if (this.children.length === 2) {\n const values = this.getVariables() as ResponseVariable[];\n const value1 = values[0];\n const value2 = values[1];\n if (\n value1.cardinality !== 'single' ||\n value2.cardinality !== 'single' ||\n Array.isArray(value1.value) ||\n Array.isArray(value2.value)\n ) {\n console.error('unexpected cardinality in qti string-match');\n return false;\n }\n const v1 = this.caseSensitive === 'true' ? value1.value : (value1.value as string).toLowerCase();\n const v2 = this.caseSensitive === 'true' ? value2.value : (value2.value as string).toLowerCase();\n return ScoringHelper.compareSingleValues(v1 as string, v2 as string, value1.baseType);\n }\n console.error('unexpected number of children in qti-string-match');\n return null;\n }\n}\n\ncustomElements.define('qti-string-match', QtiStringMatch);\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/qti-subtract/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,cAAc,CAAC,MAAM,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;AAEnD,cAAc,gBAAgB,CAAC","sourcesContent":["import { QtiSubtract } from './qti-subtract';\ncustomElements.define('qti-subtract', QtiSubtract);\n\nexport * from './qti-subtract';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'qti-subtract': QtiSubtract;\n }\n}\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { QtiExpression } from '@qti-components/base';
|
|
2
|
+
type Constructor<T> = new (...args: any[]) => T;
|
|
3
|
+
declare const QtiSubtract_base: {
|
|
4
|
+
new (...args: any[]): {
|
|
5
|
+
calculateChildren(children: Array<MockQtiExpression<any>>): number;
|
|
6
|
+
};
|
|
7
|
+
} & Constructor<QtiExpression<number>>;
|
|
8
|
+
export declare class QtiSubtract extends QtiSubtract_base {
|
|
9
|
+
getResult(): number;
|
|
10
|
+
}
|
|
11
|
+
type MockQtiExpression<T> = {
|
|
12
|
+
calculate: () => T;
|
|
13
|
+
};
|
|
14
|
+
type MockConstructor = new (...args: any[]) => {};
|
|
15
|
+
export declare function qtiSubtractMixin<TBase extends MockConstructor>(Base: TBase): {
|
|
16
|
+
new (...args: any[]): {
|
|
17
|
+
calculateChildren(children: Array<MockQtiExpression<any>>): number;
|
|
18
|
+
};
|
|
19
|
+
} & TBase;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { QtiExpression } from '@qti-components/base';
|
|
2
|
+
export class QtiSubtract extends qtiSubtractMixin((QtiExpression)) {
|
|
3
|
+
getResult() {
|
|
4
|
+
// children can be a mix of qti-expression and qti-condition-expression
|
|
5
|
+
const value = this.calculateChildren(Array.from(this.children));
|
|
6
|
+
return value;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export function qtiSubtractMixin(Base) {
|
|
10
|
+
return class MockQtiSubtract extends Base {
|
|
11
|
+
calculateChildren(children) {
|
|
12
|
+
// children can be a mix of qti-expression and qti-condition-expression
|
|
13
|
+
const values = children.map(expression => {
|
|
14
|
+
if (!expression.calculate) {
|
|
15
|
+
console.error("Element doesn't implement QtiConditionExpression");
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
const value = expression.calculate();
|
|
19
|
+
if (Number.isNaN(value)) {
|
|
20
|
+
console.error('Unexpected value in qti-subtract, expected number');
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
return Number(value);
|
|
24
|
+
});
|
|
25
|
+
if (values.some(value => value === null)) {
|
|
26
|
+
console.error('One or more child expressions returned invalid values');
|
|
27
|
+
return 0;
|
|
28
|
+
}
|
|
29
|
+
// Subtract the two values
|
|
30
|
+
return values[0] - values[1];
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=qti-subtract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qti-subtract.js","sourceRoot":"","sources":["../../../src/components/qti-subtract/qti-subtract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrD,MAAM,OAAO,WAAY,SAAQ,gBAAgB,CAAC,CAAA,aAAmE,CAAA,CAAC;IACpG,SAAS;QACvB,uEAAuE;QACvE,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAA2C,CAAC,CAAC,CAAC;QACnG,OAAO,KAAK,CAAC;IACf,CAAC;CACF;AAKD,MAAM,UAAU,gBAAgB,CAAgC,IAAW;IACzE,OAAO,MAAM,eAAgB,SAAQ,IAAI;QAChC,iBAAiB,CAAC,QAAuC;YAC9D,uEAAuE;YACvE,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE;gBACvC,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC;oBAC1B,OAAO,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;oBAClE,OAAO,IAAI,CAAC;gBACd,CAAC;gBACD,MAAM,KAAK,GAAG,UAAU,CAAC,SAAS,EAAE,CAAC;gBACrC,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;oBACxB,OAAO,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;oBACnE,OAAO,IAAI,CAAC;gBACd,CAAC;gBACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;YACvB,CAAC,CAAC,CAAC;YACH,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,EAAE,CAAC;gBACzC,OAAO,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;gBACvE,OAAO,CAAC,CAAC;YACX,CAAC;YACD,0BAA0B;YAC1B,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QAC/B,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { QtiExpression } from '@qti-components/base';\n\ntype Constructor<T> = new (...args: any[]) => T;\nexport class QtiSubtract extends qtiSubtractMixin(QtiExpression<any> as unknown as Constructor<QtiExpression<number>>) {\n public override getResult() {\n // children can be a mix of qti-expression and qti-condition-expression\n const value = this.calculateChildren(Array.from(this.children as unknown as QtiExpression<any>[]));\n return value;\n }\n}\n\ntype MockQtiExpression<T> = { calculate: () => T };\ntype MockConstructor = new (...args: any[]) => {};\n\nexport function qtiSubtractMixin<TBase extends MockConstructor>(Base: TBase) {\n return class MockQtiSubtract extends Base {\n public calculateChildren(children: Array<MockQtiExpression<any>>) {\n // children can be a mix of qti-expression and qti-condition-expression\n const values = children.map(expression => {\n if (!expression.calculate) {\n console.error(\"Element doesn't implement QtiConditionExpression\");\n return null;\n }\n const value = expression.calculate();\n if (Number.isNaN(value)) {\n console.error('Unexpected value in qti-subtract, expected number');\n return null;\n }\n return Number(value);\n });\n if (values.some(value => value === null)) {\n console.error('One or more child expressions returned invalid values');\n return 0;\n }\n // Subtract the two values\n return values[0] - values[1];\n }\n };\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { QtiExpression } from '@qti-components/base';
|
|
2
|
+
import type { QtiExpressionBase } from '@qti-components/base';
|
|
3
|
+
export declare class QtiSum extends QtiExpression<number> {
|
|
4
|
+
#private;
|
|
5
|
+
constructor();
|
|
6
|
+
getResult(): number;
|
|
7
|
+
}
|
|
8
|
+
export declare class QtiSumExpression implements QtiExpressionBase<number> {
|
|
9
|
+
private expressions;
|
|
10
|
+
constructor(expressions: QtiExpressionBase<number>[]);
|
|
11
|
+
calculate(): number;
|
|
12
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { QtiExpression } from '@qti-components/base';
|
|
2
|
+
export class QtiSum extends QtiExpression {
|
|
3
|
+
#expression;
|
|
4
|
+
constructor() {
|
|
5
|
+
super();
|
|
6
|
+
this.#expression = new QtiSumExpression(Array.from(this.children));
|
|
7
|
+
}
|
|
8
|
+
getResult() {
|
|
9
|
+
// children can be a mix of qti-expression and qti-condition-expression
|
|
10
|
+
const value = this.#expression.calculate();
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export class QtiSumExpression {
|
|
15
|
+
constructor(expressions) {
|
|
16
|
+
this.expressions = expressions;
|
|
17
|
+
}
|
|
18
|
+
calculate() {
|
|
19
|
+
const expressions = this.expressions.filter(c => c.calculate !== undefined);
|
|
20
|
+
// check if one expresssion returns null
|
|
21
|
+
if (expressions.some(c => c.calculate() === null)) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const values = this.expressions.map(c => {
|
|
25
|
+
const value = c.calculate();
|
|
26
|
+
if (Number.isNaN(value)) {
|
|
27
|
+
console.error('unexpected value in qti-sum, expected number');
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
return Number(value);
|
|
31
|
+
});
|
|
32
|
+
return values.reduce((a, b) => a + b, 0);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
customElements.define('qti-sum', QtiSum);
|
|
36
|
+
//# sourceMappingURL=qti-sum.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qti-sum.js","sourceRoot":"","sources":["../../../src/components/qti-sum/qti-sum.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAIrD,MAAM,OAAO,MAAO,SAAQ,aAAqB;IAC/C,WAAW,CAAmB;IAC9B;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,WAAW,GAAG,IAAI,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAkD,CAAC,CAAC,CAAC;IAC/G,CAAC;IAEe,SAAS;QACvB,uEAAuE;QACvE,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC;QAC3C,OAAO,KAAK,CAAC;IACf,CAAC;CACF;AAED,MAAM,OAAO,gBAAgB;IAC3B,YAAoB,WAAwC;QAAxC,gBAAW,GAAX,WAAW,CAA6B;IAAG,CAAC;IAEzD,SAAS;QACd,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC;QAC5E,wCAAwC;QACxC,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;YAClD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;YACtC,MAAM,KAAK,GAAG,CAAC,CAAC,SAAS,EAAE,CAAC;YAC5B,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxB,OAAO,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;gBAC9D,OAAO,IAAI,CAAC;YACd,CAAC;YAED,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3C,CAAC;CACF;AAED,cAAc,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC","sourcesContent":["import { QtiExpression } from '@qti-components/base';\n\nimport type { QtiExpressionBase } from '@qti-components/base';\n\nexport class QtiSum extends QtiExpression<number> {\n #expression: QtiSumExpression;\n constructor() {\n super();\n this.#expression = new QtiSumExpression(Array.from(this.children as unknown as QtiExpressionBase<number>[]));\n }\n\n public override getResult() {\n // children can be a mix of qti-expression and qti-condition-expression\n const value = this.#expression.calculate();\n return value;\n }\n}\n\nexport class QtiSumExpression implements QtiExpressionBase<number> {\n constructor(private expressions: QtiExpressionBase<number>[]) {}\n\n public calculate() {\n const expressions = this.expressions.filter(c => c.calculate !== undefined);\n // check if one expresssion returns null\n if (expressions.some(c => c.calculate() === null)) {\n return null;\n }\n\n const values = this.expressions.map(c => {\n const value = c.calculate();\n if (Number.isNaN(value)) {\n console.error('unexpected value in qti-sum, expected number');\n return null;\n }\n\n return Number(value);\n });\n return values.reduce((a, b) => a + b, 0);\n }\n}\n\ncustomElements.define('qti-sum', QtiSum);\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { QtiExpression } from '@qti-components/base';
|
|
2
|
+
export class QtiVariable extends QtiExpression {
|
|
3
|
+
getResult() {
|
|
4
|
+
const identifier = this.getAttribute('identifier');
|
|
5
|
+
const result = this.context.variables.find(v => v.identifier === identifier).value;
|
|
6
|
+
return result;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
customElements.define('qti-variable', QtiVariable);
|
|
10
|
+
//# sourceMappingURL=qti-variable.js.map
|