@citolab/qti-components 7.27.3 → 7.27.4
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/cdn/index.global.js +1 -1
- package/cdn/index.js +164 -160
- package/custom-elements.json +4214 -1176
- package/dist/base.d.ts +3 -2
- package/dist/base.js +1 -1
- package/dist/{chunk-D6EHVZG2.js → chunk-3HJE3KRM.js} +6 -8
- package/dist/chunk-3HJE3KRM.js.map +1 -0
- package/dist/{chunk-WMPG7ULB.js → chunk-424AWLRU.js} +4 -4
- package/dist/{chunk-3XXXAWMZ.js → chunk-FFESMKSD.js} +263 -7
- package/dist/chunk-FFESMKSD.js.map +1 -0
- package/dist/{chunk-CVB5ISWF.js → chunk-LQZCSHN5.js} +2 -2
- package/dist/{chunk-DGIXWHK3.js → chunk-N7S3GNUP.js} +2 -2
- package/dist/{chunk-RXRKP6P7.js → chunk-SX63OCDZ.js} +2 -2
- package/dist/{chunk-K7HR6ZAY.js → chunk-UKPCQKPF.js} +2 -2
- package/dist/chunk-UKPCQKPF.js.map +1 -0
- package/dist/{chunk-CSYOTHK2.js → chunk-XYTJOQRZ.js} +23 -16
- package/dist/chunk-XYTJOQRZ.js.map +1 -0
- package/dist/{chunk-PHCCFYNE.js → chunk-YLIYPNMK.js} +994 -2
- package/dist/chunk-YLIYPNMK.js.map +1 -0
- package/dist/{chunk-A7HX4462.js → chunk-Z2SUBRH5.js} +14 -2
- package/dist/{chunk-A7HX4462.js.map → chunk-Z2SUBRH5.js.map} +1 -1
- package/dist/elements.d.ts +67 -2
- package/dist/elements.js +10 -6
- package/dist/index.d.ts +5 -4
- package/dist/index.js +55 -11
- package/dist/interactions.js +3 -3
- package/dist/item.js +4 -4
- package/dist/loader.d.ts +2 -1
- package/dist/loader.js +2 -2
- package/dist/processing.d.ts +374 -17
- package/dist/processing.js +42 -2
- package/dist/qti-components-jsx.d.ts +1446 -389
- package/dist/{qti-rule-base-DGhWN-as.d.ts → qti-condition-expression-B1BYmCcq.d.ts} +1 -14
- package/dist/{qti-feedback-BZjWNyxP.d.ts → qti-feedback-ChmXhZuf.d.ts} +1 -1
- package/dist/qti-rule-base-ajOnfGXY.d.ts +16 -0
- package/dist/test.d.ts +2 -1
- package/dist/test.js +6 -6
- package/dist/transformers.js +1 -1
- package/package.json +10 -10
- package/dist/chunk-3XXXAWMZ.js.map +0 -1
- package/dist/chunk-CSYOTHK2.js.map +0 -1
- package/dist/chunk-D6EHVZG2.js.map +0 -1
- package/dist/chunk-K7HR6ZAY.js.map +0 -1
- package/dist/chunk-PHCCFYNE.js.map +0 -1
- /package/dist/{chunk-WMPG7ULB.js.map → chunk-424AWLRU.js.map} +0 -0
- /package/dist/{chunk-CVB5ISWF.js.map → chunk-LQZCSHN5.js.map} +0 -0
- /package/dist/{chunk-DGIXWHK3.js.map → chunk-N7S3GNUP.js.map} +0 -0
- /package/dist/{chunk-RXRKP6P7.js.map → chunk-SX63OCDZ.js.map} +0 -0
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
r,
|
|
13
13
|
t,
|
|
14
14
|
testContext
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-Z2SUBRH5.js";
|
|
16
16
|
import {
|
|
17
17
|
__decorateClass,
|
|
18
18
|
__privateAdd,
|
|
@@ -234,6 +234,51 @@ function qtiAndMixin(Base) {
|
|
|
234
234
|
};
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
+
// ../qti-processing/src/components/qti-any-n/qti-any-n.ts
|
|
238
|
+
var QtiAnyN = class extends QtiExpression {
|
|
239
|
+
constructor() {
|
|
240
|
+
super(...arguments);
|
|
241
|
+
this.min = 0;
|
|
242
|
+
this.max = Infinity;
|
|
243
|
+
}
|
|
244
|
+
getResult() {
|
|
245
|
+
const variables = this.getVariables();
|
|
246
|
+
if (!variables || variables.length === 0) {
|
|
247
|
+
console.error("qti-any-n requires at least one child expression");
|
|
248
|
+
return null;
|
|
249
|
+
}
|
|
250
|
+
if (this.min < 0 || this.max < this.min) {
|
|
251
|
+
console.error("qti-any-n requires 0 <= min <= max");
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
let trueCount = 0;
|
|
255
|
+
for (const variable of variables) {
|
|
256
|
+
if (variable.cardinality !== "single" || Array.isArray(variable.value)) {
|
|
257
|
+
console.error("qti-any-n requires single cardinality boolean expressions");
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
if (variable.baseType !== "boolean") {
|
|
261
|
+
console.error("qti-any-n requires boolean base-type");
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
if (variable.value === null || variable.value === void 0) {
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
if (variable.value === "true") {
|
|
268
|
+
trueCount++;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return trueCount >= this.min && trueCount <= this.max;
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
__decorateClass([
|
|
275
|
+
n({ type: Number })
|
|
276
|
+
], QtiAnyN.prototype, "min", 2);
|
|
277
|
+
__decorateClass([
|
|
278
|
+
n({ type: Number })
|
|
279
|
+
], QtiAnyN.prototype, "max", 2);
|
|
280
|
+
customElements.define("qti-any-n", QtiAnyN);
|
|
281
|
+
|
|
237
282
|
// ../qti-processing/src/components/qti-basevalue/qti-basevalue.ts
|
|
238
283
|
var QtiBaseValue = class extends QtiExpression {
|
|
239
284
|
constructor() {
|
|
@@ -604,6 +649,9 @@ var QtiEqual = class extends QtiExpression {
|
|
|
604
649
|
const values = this.getVariables();
|
|
605
650
|
const value1 = values[0];
|
|
606
651
|
const value2 = values[1];
|
|
652
|
+
if (!value1 || !value2) {
|
|
653
|
+
return null;
|
|
654
|
+
}
|
|
607
655
|
if (this.toleranceMode !== "exact") {
|
|
608
656
|
console.error("toleranceMode is not supported yet");
|
|
609
657
|
return false;
|
|
@@ -612,6 +660,9 @@ var QtiEqual = class extends QtiExpression {
|
|
|
612
660
|
console.error("unexpected cardinality in qti equal");
|
|
613
661
|
return false;
|
|
614
662
|
}
|
|
663
|
+
if (value1.value === null || value2.value === null || value1.value === void 0 || value2.value === void 0) {
|
|
664
|
+
return null;
|
|
665
|
+
}
|
|
615
666
|
return ScoringHelper.compareSingleValues(value1.value, value2.value, value1.baseType);
|
|
616
667
|
}
|
|
617
668
|
console.error("unexpected number of children in qti-equal");
|
|
@@ -623,6 +674,136 @@ __decorateClass([
|
|
|
623
674
|
], QtiEqual.prototype, "toleranceMode", 2);
|
|
624
675
|
customElements.define("qti-equal", QtiEqual);
|
|
625
676
|
|
|
677
|
+
// ../qti-processing/src/components/qti-divide/qti-divide.ts
|
|
678
|
+
var QtiDivide = class extends QtiExpression {
|
|
679
|
+
getResult() {
|
|
680
|
+
const values = this.#collectNumericValues(this.getVariables());
|
|
681
|
+
if (values.length !== 2) {
|
|
682
|
+
console.warn("qti-divide: expected exactly 2 numeric values");
|
|
683
|
+
return null;
|
|
684
|
+
}
|
|
685
|
+
if (values[1] === 0) {
|
|
686
|
+
console.warn("qti-divide: division by zero");
|
|
687
|
+
return null;
|
|
688
|
+
}
|
|
689
|
+
return values[0] / values[1];
|
|
690
|
+
}
|
|
691
|
+
#collectNumericValues(variables) {
|
|
692
|
+
const values = [];
|
|
693
|
+
for (const variable of variables) {
|
|
694
|
+
if (!variable) {
|
|
695
|
+
continue;
|
|
696
|
+
}
|
|
697
|
+
const pushValue = (raw) => {
|
|
698
|
+
if (raw === null || raw === void 0) {
|
|
699
|
+
return;
|
|
700
|
+
}
|
|
701
|
+
const numValue = parseFloat(raw.toString());
|
|
702
|
+
if (Number.isNaN(numValue)) {
|
|
703
|
+
console.warn("qti-divide: non-numeric value encountered");
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
values.push(numValue);
|
|
707
|
+
};
|
|
708
|
+
if (Array.isArray(variable.value)) {
|
|
709
|
+
variable.value.forEach((item) => pushValue(item));
|
|
710
|
+
continue;
|
|
711
|
+
}
|
|
712
|
+
pushValue(variable.value);
|
|
713
|
+
}
|
|
714
|
+
return values;
|
|
715
|
+
}
|
|
716
|
+
};
|
|
717
|
+
customElements.define("qti-divide", QtiDivide);
|
|
718
|
+
|
|
719
|
+
// ../qti-processing/src/components/qti-duration-gte/qti-duration-gte.ts
|
|
720
|
+
var QtiDurationGte = class extends QtiExpression {
|
|
721
|
+
getResult() {
|
|
722
|
+
const values = this.#getDurationValues();
|
|
723
|
+
if (!values) {
|
|
724
|
+
return null;
|
|
725
|
+
}
|
|
726
|
+
return values[0] >= values[1];
|
|
727
|
+
}
|
|
728
|
+
#getDurationValues() {
|
|
729
|
+
const variables = this.getVariables();
|
|
730
|
+
if (variables.length !== 2) {
|
|
731
|
+
console.error("qti-duration-gte requires exactly 2 duration expressions");
|
|
732
|
+
return null;
|
|
733
|
+
}
|
|
734
|
+
const values = variables.map((variable) => this.#parseDuration(variable));
|
|
735
|
+
if (values.some((value) => value === null)) {
|
|
736
|
+
return null;
|
|
737
|
+
}
|
|
738
|
+
return values;
|
|
739
|
+
}
|
|
740
|
+
#parseDuration(variable) {
|
|
741
|
+
if (variable.cardinality !== "single" || Array.isArray(variable.value)) {
|
|
742
|
+
console.error("qti-duration-gte requires single cardinality");
|
|
743
|
+
return null;
|
|
744
|
+
}
|
|
745
|
+
if (variable.baseType !== "duration") {
|
|
746
|
+
console.error("qti-duration-gte requires duration base-type");
|
|
747
|
+
return null;
|
|
748
|
+
}
|
|
749
|
+
if (variable.value === null || variable.value === void 0) {
|
|
750
|
+
return null;
|
|
751
|
+
}
|
|
752
|
+
const value = Number.parseFloat(variable.value.toString());
|
|
753
|
+
if (Number.isNaN(value)) {
|
|
754
|
+
console.error(
|
|
755
|
+
`qti-duration-gte requires duration values expressed in seconds, got "${variable.value.toString()}"`
|
|
756
|
+
);
|
|
757
|
+
return null;
|
|
758
|
+
}
|
|
759
|
+
return value;
|
|
760
|
+
}
|
|
761
|
+
};
|
|
762
|
+
customElements.define("qti-duration-gte", QtiDurationGte);
|
|
763
|
+
|
|
764
|
+
// ../qti-processing/src/components/qti-duration-lt/qti-duration-lt.ts
|
|
765
|
+
var QtiDurationLt = class extends QtiExpression {
|
|
766
|
+
getResult() {
|
|
767
|
+
const values = this.#getDurationValues();
|
|
768
|
+
if (!values) {
|
|
769
|
+
return null;
|
|
770
|
+
}
|
|
771
|
+
return values[0] < values[1];
|
|
772
|
+
}
|
|
773
|
+
#getDurationValues() {
|
|
774
|
+
const variables = this.getVariables();
|
|
775
|
+
if (variables.length !== 2) {
|
|
776
|
+
console.error("qti-duration-lt requires exactly 2 duration expressions");
|
|
777
|
+
return null;
|
|
778
|
+
}
|
|
779
|
+
const values = variables.map((variable) => this.#parseDuration(variable));
|
|
780
|
+
if (values.some((value) => value === null)) {
|
|
781
|
+
return null;
|
|
782
|
+
}
|
|
783
|
+
return values;
|
|
784
|
+
}
|
|
785
|
+
#parseDuration(variable) {
|
|
786
|
+
if (variable.cardinality !== "single" || Array.isArray(variable.value)) {
|
|
787
|
+
console.error("qti-duration-lt requires single cardinality");
|
|
788
|
+
return null;
|
|
789
|
+
}
|
|
790
|
+
if (variable.baseType !== "duration") {
|
|
791
|
+
console.error("qti-duration-lt requires duration base-type");
|
|
792
|
+
return null;
|
|
793
|
+
}
|
|
794
|
+
if (variable.value === null || variable.value === void 0) {
|
|
795
|
+
return null;
|
|
796
|
+
}
|
|
797
|
+
const value = Number.parseFloat(variable.value.toString());
|
|
798
|
+
if (Number.isNaN(value)) {
|
|
799
|
+
console.error(`qti-duration-lt requires duration values expressed in seconds, got "${variable.value.toString()}"`);
|
|
800
|
+
return null;
|
|
801
|
+
}
|
|
802
|
+
return value;
|
|
803
|
+
}
|
|
804
|
+
};
|
|
805
|
+
customElements.define("qti-duration-lt", QtiDurationLt);
|
|
806
|
+
|
|
626
807
|
// ../qti-processing/src/components/qti-gcd/qti.gcd.ts
|
|
627
808
|
var QtiGcd = class extends QtiExpression {
|
|
628
809
|
getResult() {
|
|
@@ -761,6 +942,313 @@ var QtiGte = class extends QtiConditionExpression {
|
|
|
761
942
|
};
|
|
762
943
|
customElements.define("qti-gte", QtiGte);
|
|
763
944
|
|
|
945
|
+
// ../qti-processing/src/components/qti-inside/qti-inside.ts
|
|
946
|
+
var QtiInside = class extends QtiExpression {
|
|
947
|
+
constructor() {
|
|
948
|
+
super(...arguments);
|
|
949
|
+
this.shape = "";
|
|
950
|
+
this.coords = "";
|
|
951
|
+
}
|
|
952
|
+
getResult() {
|
|
953
|
+
const variables = this.getVariables();
|
|
954
|
+
if (variables.length !== 1) {
|
|
955
|
+
console.error("qti-inside requires exactly one point expression");
|
|
956
|
+
return null;
|
|
957
|
+
}
|
|
958
|
+
const variable = variables[0];
|
|
959
|
+
if (variable.cardinality !== "single" || Array.isArray(variable.value)) {
|
|
960
|
+
console.error("qti-inside requires single cardinality");
|
|
961
|
+
return null;
|
|
962
|
+
}
|
|
963
|
+
if (variable.value === null || variable.value === void 0) {
|
|
964
|
+
return null;
|
|
965
|
+
}
|
|
966
|
+
if (!this.shape || !this.coords) {
|
|
967
|
+
console.error("qti-inside requires shape and coords attributes");
|
|
968
|
+
return null;
|
|
969
|
+
}
|
|
970
|
+
const point = this.#parsePoint(variable.value.toString());
|
|
971
|
+
const coords = this.#parseCoords(this.coords);
|
|
972
|
+
if (!point || coords.length === 0) {
|
|
973
|
+
return null;
|
|
974
|
+
}
|
|
975
|
+
switch (this.shape.toLowerCase()) {
|
|
976
|
+
case "circle":
|
|
977
|
+
return this.#isInsideCircle(point, coords);
|
|
978
|
+
case "rect":
|
|
979
|
+
return this.#isInsideRect(point, coords);
|
|
980
|
+
case "ellipse":
|
|
981
|
+
return this.#isInsideEllipse(point, coords);
|
|
982
|
+
case "poly":
|
|
983
|
+
case "polygon":
|
|
984
|
+
return this.#isInsidePolygon(point, coords);
|
|
985
|
+
default:
|
|
986
|
+
console.error(`qti-inside does not support shape "${this.shape}"`);
|
|
987
|
+
return null;
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
#parsePoint(value) {
|
|
991
|
+
const tokens = value.split(/[,\s]+/).map((token) => token.trim()).filter(Boolean);
|
|
992
|
+
if (tokens.length !== 2) {
|
|
993
|
+
console.error('qti-inside requires a point value formatted as "x y" or "x,y"');
|
|
994
|
+
return null;
|
|
995
|
+
}
|
|
996
|
+
const x = Number.parseFloat(tokens[0]);
|
|
997
|
+
const y = Number.parseFloat(tokens[1]);
|
|
998
|
+
if (Number.isNaN(x) || Number.isNaN(y)) {
|
|
999
|
+
console.error("qti-inside requires numeric point coordinates");
|
|
1000
|
+
return null;
|
|
1001
|
+
}
|
|
1002
|
+
return { x, y };
|
|
1003
|
+
}
|
|
1004
|
+
#parseCoords(value) {
|
|
1005
|
+
const coords = value.split(",").map((token) => token.trim()).filter(Boolean).map((token) => Number.parseFloat(token));
|
|
1006
|
+
if (coords.some((coord) => Number.isNaN(coord))) {
|
|
1007
|
+
console.error("qti-inside requires numeric coords");
|
|
1008
|
+
return [];
|
|
1009
|
+
}
|
|
1010
|
+
return coords;
|
|
1011
|
+
}
|
|
1012
|
+
#isInsideCircle(point, coords) {
|
|
1013
|
+
if (coords.length !== 3) {
|
|
1014
|
+
console.error("qti-inside circle requires x,y,r");
|
|
1015
|
+
return null;
|
|
1016
|
+
}
|
|
1017
|
+
const [centerX, centerY, radius] = coords;
|
|
1018
|
+
return (point.x - centerX) ** 2 + (point.y - centerY) ** 2 <= radius ** 2;
|
|
1019
|
+
}
|
|
1020
|
+
#isInsideRect(point, coords) {
|
|
1021
|
+
if (coords.length !== 4) {
|
|
1022
|
+
console.error("qti-inside rect requires left,top,right,bottom");
|
|
1023
|
+
return null;
|
|
1024
|
+
}
|
|
1025
|
+
const [x1, y1, x2, y2] = coords;
|
|
1026
|
+
const left = Math.min(x1, x2);
|
|
1027
|
+
const right = Math.max(x1, x2);
|
|
1028
|
+
const top = Math.min(y1, y2);
|
|
1029
|
+
const bottom = Math.max(y1, y2);
|
|
1030
|
+
return point.x >= left && point.x <= right && point.y >= top && point.y <= bottom;
|
|
1031
|
+
}
|
|
1032
|
+
#isInsideEllipse(point, coords) {
|
|
1033
|
+
if (coords.length !== 4) {
|
|
1034
|
+
console.error("qti-inside ellipse requires centerX,centerY,radiusX,radiusY");
|
|
1035
|
+
return null;
|
|
1036
|
+
}
|
|
1037
|
+
const [centerX, centerY, radiusX, radiusY] = coords;
|
|
1038
|
+
if (radiusX === 0 || radiusY === 0) {
|
|
1039
|
+
return false;
|
|
1040
|
+
}
|
|
1041
|
+
return (point.x - centerX) ** 2 / radiusX ** 2 + (point.y - centerY) ** 2 / radiusY ** 2 <= 1;
|
|
1042
|
+
}
|
|
1043
|
+
#isInsidePolygon(point, coords) {
|
|
1044
|
+
if (coords.length < 6 || coords.length % 2 !== 0) {
|
|
1045
|
+
console.error("qti-inside polygon requires at least 3 coordinate pairs");
|
|
1046
|
+
return null;
|
|
1047
|
+
}
|
|
1048
|
+
let inside = false;
|
|
1049
|
+
for (let current = 0, previous = coords.length - 2; current < coords.length; current += 2) {
|
|
1050
|
+
const xi = coords[current];
|
|
1051
|
+
const yi = coords[current + 1];
|
|
1052
|
+
const xj = coords[previous];
|
|
1053
|
+
const yj = coords[previous + 1];
|
|
1054
|
+
const intersects = yi > point.y !== yj > point.y && point.x < (xj - xi) * (point.y - yi) / (yj - yi || Number.EPSILON) + xi;
|
|
1055
|
+
if (intersects) {
|
|
1056
|
+
inside = !inside;
|
|
1057
|
+
}
|
|
1058
|
+
previous = current;
|
|
1059
|
+
}
|
|
1060
|
+
return inside;
|
|
1061
|
+
}
|
|
1062
|
+
};
|
|
1063
|
+
__decorateClass([
|
|
1064
|
+
n({ type: String })
|
|
1065
|
+
], QtiInside.prototype, "shape", 2);
|
|
1066
|
+
__decorateClass([
|
|
1067
|
+
n({ type: String })
|
|
1068
|
+
], QtiInside.prototype, "coords", 2);
|
|
1069
|
+
customElements.define("qti-inside", QtiInside);
|
|
1070
|
+
|
|
1071
|
+
// ../qti-processing/src/components/qti-integer-divide/qti-integer-divide.ts
|
|
1072
|
+
var QtiIntegerDivide = class extends QtiExpression {
|
|
1073
|
+
getResult() {
|
|
1074
|
+
const values = this.#collectIntegerValues(this.getVariables());
|
|
1075
|
+
if (values.length !== 2) {
|
|
1076
|
+
console.error("qti-integer-divide requires exactly 2 integer values");
|
|
1077
|
+
return null;
|
|
1078
|
+
}
|
|
1079
|
+
if (values[1] === 0) {
|
|
1080
|
+
console.error("qti-integer-divide: division by zero");
|
|
1081
|
+
return null;
|
|
1082
|
+
}
|
|
1083
|
+
return Math.floor(values[0] / values[1]);
|
|
1084
|
+
}
|
|
1085
|
+
#collectIntegerValues(variables) {
|
|
1086
|
+
const values = [];
|
|
1087
|
+
for (const variable of variables) {
|
|
1088
|
+
if (variable.baseType !== "integer") {
|
|
1089
|
+
console.error("qti-integer-divide requires integer base-type");
|
|
1090
|
+
return [];
|
|
1091
|
+
}
|
|
1092
|
+
if (variable.cardinality !== "single" || Array.isArray(variable.value)) {
|
|
1093
|
+
console.error("qti-integer-divide requires single cardinality");
|
|
1094
|
+
return [];
|
|
1095
|
+
}
|
|
1096
|
+
if (variable.value === null || variable.value === void 0) {
|
|
1097
|
+
return [];
|
|
1098
|
+
}
|
|
1099
|
+
const value = Number.parseInt(variable.value, 10);
|
|
1100
|
+
if (Number.isNaN(value)) {
|
|
1101
|
+
console.error("qti-integer-divide requires integer values");
|
|
1102
|
+
return [];
|
|
1103
|
+
}
|
|
1104
|
+
values.push(value);
|
|
1105
|
+
}
|
|
1106
|
+
return values;
|
|
1107
|
+
}
|
|
1108
|
+
};
|
|
1109
|
+
customElements.define("qti-integer-divide", QtiIntegerDivide);
|
|
1110
|
+
|
|
1111
|
+
// ../qti-processing/src/components/qti-integer-modulus/qti-integer-modulus.ts
|
|
1112
|
+
var QtiIntegerModulus = class extends QtiExpression {
|
|
1113
|
+
getResult() {
|
|
1114
|
+
const values = this.#collectIntegerValues(this.getVariables());
|
|
1115
|
+
if (values.length !== 2) {
|
|
1116
|
+
console.error("qti-integer-modulus requires exactly 2 integer values");
|
|
1117
|
+
return null;
|
|
1118
|
+
}
|
|
1119
|
+
if (values[1] === 0) {
|
|
1120
|
+
console.error("qti-integer-modulus: division by zero");
|
|
1121
|
+
return null;
|
|
1122
|
+
}
|
|
1123
|
+
return values[0] % values[1];
|
|
1124
|
+
}
|
|
1125
|
+
#collectIntegerValues(variables) {
|
|
1126
|
+
const values = [];
|
|
1127
|
+
for (const variable of variables) {
|
|
1128
|
+
if (variable.baseType !== "integer") {
|
|
1129
|
+
console.error("qti-integer-modulus requires integer base-type");
|
|
1130
|
+
return [];
|
|
1131
|
+
}
|
|
1132
|
+
if (variable.cardinality !== "single" || Array.isArray(variable.value)) {
|
|
1133
|
+
console.error("qti-integer-modulus requires single cardinality");
|
|
1134
|
+
return [];
|
|
1135
|
+
}
|
|
1136
|
+
if (variable.value === null || variable.value === void 0) {
|
|
1137
|
+
return [];
|
|
1138
|
+
}
|
|
1139
|
+
const value = Number.parseInt(variable.value, 10);
|
|
1140
|
+
if (Number.isNaN(value)) {
|
|
1141
|
+
console.error("qti-integer-modulus requires integer values");
|
|
1142
|
+
return [];
|
|
1143
|
+
}
|
|
1144
|
+
values.push(value);
|
|
1145
|
+
}
|
|
1146
|
+
return values;
|
|
1147
|
+
}
|
|
1148
|
+
};
|
|
1149
|
+
customElements.define("qti-integer-modulus", QtiIntegerModulus);
|
|
1150
|
+
|
|
1151
|
+
// ../qti-processing/src/components/qti-integer-to-float/qti-integer-to-float.ts
|
|
1152
|
+
var QtiIntegerToFloat = class extends QtiExpression {
|
|
1153
|
+
getResult() {
|
|
1154
|
+
const variables = this.getVariables();
|
|
1155
|
+
if (variables.length !== 1) {
|
|
1156
|
+
console.error("qti-integer-to-float requires exactly one child expression");
|
|
1157
|
+
return null;
|
|
1158
|
+
}
|
|
1159
|
+
const variable = variables[0];
|
|
1160
|
+
if (variable.baseType !== "integer") {
|
|
1161
|
+
console.error("qti-integer-to-float requires integer base-type");
|
|
1162
|
+
return null;
|
|
1163
|
+
}
|
|
1164
|
+
if (variable.cardinality !== "single" || Array.isArray(variable.value)) {
|
|
1165
|
+
console.error("qti-integer-to-float requires single cardinality");
|
|
1166
|
+
return null;
|
|
1167
|
+
}
|
|
1168
|
+
if (variable.value === null || variable.value === void 0) {
|
|
1169
|
+
return null;
|
|
1170
|
+
}
|
|
1171
|
+
const value = Number.parseInt(variable.value, 10);
|
|
1172
|
+
if (Number.isNaN(value)) {
|
|
1173
|
+
console.error("qti-integer-to-float requires an integer value");
|
|
1174
|
+
return null;
|
|
1175
|
+
}
|
|
1176
|
+
return value;
|
|
1177
|
+
}
|
|
1178
|
+
};
|
|
1179
|
+
customElements.define("qti-integer-to-float", QtiIntegerToFloat);
|
|
1180
|
+
|
|
1181
|
+
// ../qti-processing/src/components/qti-lcm/qti-lcm.ts
|
|
1182
|
+
var QtiLcm = class extends QtiExpression {
|
|
1183
|
+
getResult() {
|
|
1184
|
+
const values = this.#collectIntegerValues(this.getVariables());
|
|
1185
|
+
if (values.length === 0) {
|
|
1186
|
+
console.error("qti-lcm requires at least one integer value");
|
|
1187
|
+
return null;
|
|
1188
|
+
}
|
|
1189
|
+
return values.reduce((accumulator, value) => this.#lcm(accumulator, value));
|
|
1190
|
+
}
|
|
1191
|
+
#collectIntegerValues(variables) {
|
|
1192
|
+
const values = [];
|
|
1193
|
+
for (const variable of variables) {
|
|
1194
|
+
if (variable.baseType !== "integer") {
|
|
1195
|
+
console.error("qti-lcm requires integer base-type");
|
|
1196
|
+
return [];
|
|
1197
|
+
}
|
|
1198
|
+
if (variable.value === null || variable.value === void 0) {
|
|
1199
|
+
return [];
|
|
1200
|
+
}
|
|
1201
|
+
if (variable.cardinality === "single") {
|
|
1202
|
+
if (Array.isArray(variable.value)) {
|
|
1203
|
+
console.error("qti-lcm unexpected array value for single cardinality");
|
|
1204
|
+
return [];
|
|
1205
|
+
}
|
|
1206
|
+
const value = Number.parseInt(variable.value, 10);
|
|
1207
|
+
if (Number.isNaN(value)) {
|
|
1208
|
+
console.error("qti-lcm requires integer values");
|
|
1209
|
+
return [];
|
|
1210
|
+
}
|
|
1211
|
+
values.push(value);
|
|
1212
|
+
continue;
|
|
1213
|
+
}
|
|
1214
|
+
if (variable.cardinality !== "multiple" && variable.cardinality !== "ordered") {
|
|
1215
|
+
console.error("qti-lcm unsupported cardinality");
|
|
1216
|
+
return [];
|
|
1217
|
+
}
|
|
1218
|
+
if (!Array.isArray(variable.value)) {
|
|
1219
|
+
console.error("qti-lcm expected array value for container cardinality");
|
|
1220
|
+
return [];
|
|
1221
|
+
}
|
|
1222
|
+
for (const entry of variable.value) {
|
|
1223
|
+
const value = Number.parseInt(entry, 10);
|
|
1224
|
+
if (Number.isNaN(value)) {
|
|
1225
|
+
console.error("qti-lcm requires integer values");
|
|
1226
|
+
return [];
|
|
1227
|
+
}
|
|
1228
|
+
values.push(value);
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
return values;
|
|
1232
|
+
}
|
|
1233
|
+
#gcd(a, b) {
|
|
1234
|
+
let left = Math.abs(a);
|
|
1235
|
+
let right = Math.abs(b);
|
|
1236
|
+
while (right !== 0) {
|
|
1237
|
+
const remainder = left % right;
|
|
1238
|
+
left = right;
|
|
1239
|
+
right = remainder;
|
|
1240
|
+
}
|
|
1241
|
+
return left;
|
|
1242
|
+
}
|
|
1243
|
+
#lcm(a, b) {
|
|
1244
|
+
if (a === 0 || b === 0) {
|
|
1245
|
+
return 0;
|
|
1246
|
+
}
|
|
1247
|
+
return Math.abs(a * b / this.#gcd(a, b));
|
|
1248
|
+
}
|
|
1249
|
+
};
|
|
1250
|
+
customElements.define("qti-lcm", QtiLcm);
|
|
1251
|
+
|
|
764
1252
|
// ../qti-processing/src/components/qti-null/qti-null.ts
|
|
765
1253
|
var QtiNull = class extends QtiExpression {
|
|
766
1254
|
getResult() {
|
|
@@ -1198,6 +1686,44 @@ var QtiMatch = class _QtiMatch extends QtiExpression {
|
|
|
1198
1686
|
};
|
|
1199
1687
|
customElements.define("qti-match", QtiMatch);
|
|
1200
1688
|
|
|
1689
|
+
// ../qti-processing/src/components/qti-max/qti-max.ts
|
|
1690
|
+
var QtiMax = class extends QtiExpression {
|
|
1691
|
+
getResult() {
|
|
1692
|
+
const values = this.#collectNumericValues(this.getVariables());
|
|
1693
|
+
if (values.length === 0) {
|
|
1694
|
+
console.warn("qti-max: no numeric values provided");
|
|
1695
|
+
return null;
|
|
1696
|
+
}
|
|
1697
|
+
return Math.max(...values);
|
|
1698
|
+
}
|
|
1699
|
+
#collectNumericValues(variables) {
|
|
1700
|
+
const values = [];
|
|
1701
|
+
for (const variable of variables) {
|
|
1702
|
+
if (!variable) {
|
|
1703
|
+
continue;
|
|
1704
|
+
}
|
|
1705
|
+
const pushValue = (raw) => {
|
|
1706
|
+
if (raw === null || raw === void 0) {
|
|
1707
|
+
return;
|
|
1708
|
+
}
|
|
1709
|
+
const numValue = parseFloat(raw.toString());
|
|
1710
|
+
if (Number.isNaN(numValue)) {
|
|
1711
|
+
console.warn("qti-max: non-numeric value encountered");
|
|
1712
|
+
return;
|
|
1713
|
+
}
|
|
1714
|
+
values.push(numValue);
|
|
1715
|
+
};
|
|
1716
|
+
if (Array.isArray(variable.value)) {
|
|
1717
|
+
variable.value.forEach((item) => pushValue(item));
|
|
1718
|
+
continue;
|
|
1719
|
+
}
|
|
1720
|
+
pushValue(variable.value);
|
|
1721
|
+
}
|
|
1722
|
+
return values;
|
|
1723
|
+
}
|
|
1724
|
+
};
|
|
1725
|
+
customElements.define("qti-max", QtiMax);
|
|
1726
|
+
|
|
1201
1727
|
// ../qti-processing/src/components/qti-member/qti-member.ts
|
|
1202
1728
|
var QtiMember = class extends QtiExpression {
|
|
1203
1729
|
getResult() {
|
|
@@ -1228,6 +1754,44 @@ var QtiMember = class extends QtiExpression {
|
|
|
1228
1754
|
};
|
|
1229
1755
|
customElements.define("qti-member", QtiMember);
|
|
1230
1756
|
|
|
1757
|
+
// ../qti-processing/src/components/qti-min/qti-min.ts
|
|
1758
|
+
var QtiMin = class extends QtiExpression {
|
|
1759
|
+
getResult() {
|
|
1760
|
+
const values = this.#collectNumericValues(this.getVariables());
|
|
1761
|
+
if (values.length === 0) {
|
|
1762
|
+
console.warn("qti-min: no numeric values provided");
|
|
1763
|
+
return null;
|
|
1764
|
+
}
|
|
1765
|
+
return Math.min(...values);
|
|
1766
|
+
}
|
|
1767
|
+
#collectNumericValues(variables) {
|
|
1768
|
+
const values = [];
|
|
1769
|
+
for (const variable of variables) {
|
|
1770
|
+
if (!variable) {
|
|
1771
|
+
continue;
|
|
1772
|
+
}
|
|
1773
|
+
const pushValue = (raw) => {
|
|
1774
|
+
if (raw === null || raw === void 0) {
|
|
1775
|
+
return;
|
|
1776
|
+
}
|
|
1777
|
+
const numValue = parseFloat(raw.toString());
|
|
1778
|
+
if (Number.isNaN(numValue)) {
|
|
1779
|
+
console.warn("qti-min: non-numeric value encountered");
|
|
1780
|
+
return;
|
|
1781
|
+
}
|
|
1782
|
+
values.push(numValue);
|
|
1783
|
+
};
|
|
1784
|
+
if (Array.isArray(variable.value)) {
|
|
1785
|
+
variable.value.forEach((item) => pushValue(item));
|
|
1786
|
+
continue;
|
|
1787
|
+
}
|
|
1788
|
+
pushValue(variable.value);
|
|
1789
|
+
}
|
|
1790
|
+
return values;
|
|
1791
|
+
}
|
|
1792
|
+
};
|
|
1793
|
+
customElements.define("qti-min", QtiMin);
|
|
1794
|
+
|
|
1231
1795
|
// ../qti-processing/src/components/qti-multiple/qti-multiple.ts
|
|
1232
1796
|
var QtiMultiple = class extends QtiExpression {
|
|
1233
1797
|
getResult() {
|
|
@@ -1386,6 +1950,43 @@ var QtiPower = class extends QtiExpression {
|
|
|
1386
1950
|
};
|
|
1387
1951
|
customElements.define("qti-power", QtiPower);
|
|
1388
1952
|
|
|
1953
|
+
// ../qti-processing/src/components/qti-pattern-match/qti-pattern-match.ts
|
|
1954
|
+
var QtiPatternMatch = class extends QtiExpression {
|
|
1955
|
+
constructor() {
|
|
1956
|
+
super(...arguments);
|
|
1957
|
+
this.pattern = "";
|
|
1958
|
+
}
|
|
1959
|
+
getResult() {
|
|
1960
|
+
const variables = this.getVariables();
|
|
1961
|
+
if (variables.length !== 1) {
|
|
1962
|
+
console.error("qti-pattern-match requires exactly one child expression");
|
|
1963
|
+
return null;
|
|
1964
|
+
}
|
|
1965
|
+
if (!this.pattern) {
|
|
1966
|
+
console.error("qti-pattern-match requires a pattern attribute");
|
|
1967
|
+
return null;
|
|
1968
|
+
}
|
|
1969
|
+
const variable = variables[0];
|
|
1970
|
+
if (variable.cardinality !== "single" || Array.isArray(variable.value)) {
|
|
1971
|
+
console.error("qti-pattern-match requires single cardinality");
|
|
1972
|
+
return null;
|
|
1973
|
+
}
|
|
1974
|
+
if (variable.value === null || variable.value === void 0) {
|
|
1975
|
+
return null;
|
|
1976
|
+
}
|
|
1977
|
+
try {
|
|
1978
|
+
return new RegExp(this.pattern).test(variable.value.toString());
|
|
1979
|
+
} catch (error) {
|
|
1980
|
+
console.error("qti-pattern-match requires a valid regular expression", error);
|
|
1981
|
+
return null;
|
|
1982
|
+
}
|
|
1983
|
+
}
|
|
1984
|
+
};
|
|
1985
|
+
__decorateClass([
|
|
1986
|
+
n({ type: String })
|
|
1987
|
+
], QtiPatternMatch.prototype, "pattern", 2);
|
|
1988
|
+
customElements.define("qti-pattern-match", QtiPatternMatch);
|
|
1989
|
+
|
|
1389
1990
|
// ../qti-processing/src/components/qti-printed-variable/qti-printed-variable.ts
|
|
1390
1991
|
var QtiPrintedVariable = class extends i {
|
|
1391
1992
|
render() {
|
|
@@ -1427,6 +2028,314 @@ var QtiProduct = class extends QtiExpression {
|
|
|
1427
2028
|
};
|
|
1428
2029
|
customElements.define("qti-product", QtiProduct);
|
|
1429
2030
|
|
|
2031
|
+
// ../qti-processing/src/components/qti-repeat/qti-repeat.ts
|
|
2032
|
+
var QtiRepeat = class extends QtiExpression {
|
|
2033
|
+
constructor() {
|
|
2034
|
+
super(...arguments);
|
|
2035
|
+
this.numberRepeats = "";
|
|
2036
|
+
}
|
|
2037
|
+
getResult() {
|
|
2038
|
+
const count = this.#resolveRepeatCount();
|
|
2039
|
+
if (count <= 0) {
|
|
2040
|
+
return [];
|
|
2041
|
+
}
|
|
2042
|
+
const expression = this.firstElementChild;
|
|
2043
|
+
if (!expression) {
|
|
2044
|
+
console.warn("qti-repeat: missing child expression");
|
|
2045
|
+
return [];
|
|
2046
|
+
}
|
|
2047
|
+
const results = [];
|
|
2048
|
+
for (let i2 = 0; i2 < count; i2++) {
|
|
2049
|
+
const value = expression.calculate();
|
|
2050
|
+
const variable = this.#toResponseVariable(value);
|
|
2051
|
+
if (variable) {
|
|
2052
|
+
results.push(variable);
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
2055
|
+
return results;
|
|
2056
|
+
}
|
|
2057
|
+
#resolveRepeatCount() {
|
|
2058
|
+
if (!this.numberRepeats) {
|
|
2059
|
+
console.warn("qti-repeat: missing number-repeats attribute");
|
|
2060
|
+
return 0;
|
|
2061
|
+
}
|
|
2062
|
+
const numericCount = parseInt(this.numberRepeats, 10);
|
|
2063
|
+
if (!Number.isNaN(numericCount)) {
|
|
2064
|
+
return numericCount;
|
|
2065
|
+
}
|
|
2066
|
+
const identifier = this.numberRepeats;
|
|
2067
|
+
const variable = this.context?.variables?.find((v) => v.identifier === identifier);
|
|
2068
|
+
if (!variable) {
|
|
2069
|
+
console.warn(`qti-repeat: unknown identifier "${identifier}"`);
|
|
2070
|
+
return 0;
|
|
2071
|
+
}
|
|
2072
|
+
const rawValue = Array.isArray(variable.value) ? variable.value[0] : variable.value;
|
|
2073
|
+
const resolvedCount = parseInt(rawValue?.toString() ?? "", 10);
|
|
2074
|
+
if (Number.isNaN(resolvedCount)) {
|
|
2075
|
+
console.warn(`qti-repeat: invalid repeat count from "${identifier}"`);
|
|
2076
|
+
return 0;
|
|
2077
|
+
}
|
|
2078
|
+
return resolvedCount;
|
|
2079
|
+
}
|
|
2080
|
+
#toResponseVariable(value) {
|
|
2081
|
+
if (value === null || value === void 0) {
|
|
2082
|
+
return null;
|
|
2083
|
+
}
|
|
2084
|
+
if (typeof value === "number") {
|
|
2085
|
+
return {
|
|
2086
|
+
identifier: "",
|
|
2087
|
+
cardinality: "single",
|
|
2088
|
+
baseType: Number.isInteger(value) ? "integer" : "float",
|
|
2089
|
+
value: value.toString(),
|
|
2090
|
+
type: "response"
|
|
2091
|
+
};
|
|
2092
|
+
}
|
|
2093
|
+
if (typeof value === "string") {
|
|
2094
|
+
const numericValue = parseFloat(value);
|
|
2095
|
+
if (!Number.isNaN(numericValue)) {
|
|
2096
|
+
return {
|
|
2097
|
+
identifier: "",
|
|
2098
|
+
cardinality: "single",
|
|
2099
|
+
baseType: Number.isInteger(numericValue) ? "integer" : "float",
|
|
2100
|
+
value: value.toString(),
|
|
2101
|
+
type: "response"
|
|
2102
|
+
};
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
if (value && typeof value === "object" && "value" in value) {
|
|
2106
|
+
const responseValue = value.value;
|
|
2107
|
+
return {
|
|
2108
|
+
identifier: "",
|
|
2109
|
+
cardinality: "single",
|
|
2110
|
+
baseType: value.baseType ?? "string",
|
|
2111
|
+
value: responseValue !== null && responseValue !== void 0 ? responseValue.toString() : null,
|
|
2112
|
+
type: "response"
|
|
2113
|
+
};
|
|
2114
|
+
}
|
|
2115
|
+
return {
|
|
2116
|
+
identifier: "",
|
|
2117
|
+
cardinality: "single",
|
|
2118
|
+
baseType: "string",
|
|
2119
|
+
value: value.toString(),
|
|
2120
|
+
type: "response"
|
|
2121
|
+
};
|
|
2122
|
+
}
|
|
2123
|
+
};
|
|
2124
|
+
__decorateClass([
|
|
2125
|
+
n({ type: String, attribute: "number-repeats" })
|
|
2126
|
+
], QtiRepeat.prototype, "numberRepeats", 2);
|
|
2127
|
+
customElements.define("qti-repeat", QtiRepeat);
|
|
2128
|
+
|
|
2129
|
+
// ../qti-processing/src/components/qti-set-correct-response/qti-set-correct-response.ts
|
|
2130
|
+
var QtiSetCorrectResponse = class extends QtiRule {
|
|
2131
|
+
/**
|
|
2132
|
+
* Processes the QTI rule and dispatches a custom event with the computed correct response value.
|
|
2133
|
+
*/
|
|
2134
|
+
process() {
|
|
2135
|
+
const responseIdentifier = this.getAttribute("identifier");
|
|
2136
|
+
if (!responseIdentifier) {
|
|
2137
|
+
console.warn('QtiSetCorrectResponse: Missing "identifier" attribute.');
|
|
2138
|
+
return;
|
|
2139
|
+
}
|
|
2140
|
+
const expression = this.firstElementChild;
|
|
2141
|
+
if (!expression) {
|
|
2142
|
+
console.warn("QtiSetCorrectResponse: No expression found.");
|
|
2143
|
+
return;
|
|
2144
|
+
}
|
|
2145
|
+
const rule = new QtiSetCorrectResponseRule(expression);
|
|
2146
|
+
const value = rule.process();
|
|
2147
|
+
this.dispatchEvent(
|
|
2148
|
+
new CustomEvent("qti-set-correct-response", {
|
|
2149
|
+
bubbles: true,
|
|
2150
|
+
composed: true,
|
|
2151
|
+
detail: {
|
|
2152
|
+
responseIdentifier,
|
|
2153
|
+
value: this.#formatValue(value)
|
|
2154
|
+
}
|
|
2155
|
+
})
|
|
2156
|
+
);
|
|
2157
|
+
}
|
|
2158
|
+
#formatValue(value) {
|
|
2159
|
+
if (value === null || value === void 0) {
|
|
2160
|
+
return null;
|
|
2161
|
+
}
|
|
2162
|
+
if (Array.isArray(value)) {
|
|
2163
|
+
return value.map((item) => convertNumberToUniversalFormat(this.#unwrapValue(item)));
|
|
2164
|
+
}
|
|
2165
|
+
return convertNumberToUniversalFormat(this.#unwrapValue(value));
|
|
2166
|
+
}
|
|
2167
|
+
#unwrapValue(value) {
|
|
2168
|
+
if (value && typeof value === "object" && "value" in value) {
|
|
2169
|
+
const responseValue = value.value;
|
|
2170
|
+
return responseValue !== null && responseValue !== void 0 ? responseValue.toString() : "";
|
|
2171
|
+
}
|
|
2172
|
+
return value?.toString() ?? "";
|
|
2173
|
+
}
|
|
2174
|
+
};
|
|
2175
|
+
var QtiSetCorrectResponseRule = class {
|
|
2176
|
+
constructor(expression) {
|
|
2177
|
+
this.expression = expression;
|
|
2178
|
+
}
|
|
2179
|
+
/**
|
|
2180
|
+
* Evaluates the expression and returns its value.
|
|
2181
|
+
*/
|
|
2182
|
+
process() {
|
|
2183
|
+
const value = this.expression.calculate() ?? null;
|
|
2184
|
+
if (value === null) {
|
|
2185
|
+
console.warn("QtiSetCorrectResponseRule: Evaluated value is null.");
|
|
2186
|
+
}
|
|
2187
|
+
if (Array.isArray(value)) {
|
|
2188
|
+
return value.map((item) => this.#unwrapResult(item));
|
|
2189
|
+
}
|
|
2190
|
+
return this.#unwrapResult(value);
|
|
2191
|
+
}
|
|
2192
|
+
#unwrapResult(value) {
|
|
2193
|
+
if (value && typeof value === "object" && "value" in value) {
|
|
2194
|
+
return value.value;
|
|
2195
|
+
}
|
|
2196
|
+
return value;
|
|
2197
|
+
}
|
|
2198
|
+
};
|
|
2199
|
+
customElements.define("qti-set-correct-response", QtiSetCorrectResponse);
|
|
2200
|
+
|
|
2201
|
+
// ../qti-processing/src/components/qti-set-template-value/qti-set-template-value.ts
|
|
2202
|
+
var QtiSetTemplateValue = class extends QtiRule {
|
|
2203
|
+
/**
|
|
2204
|
+
* Processes the QTI rule and dispatches a custom event with the computed template value.
|
|
2205
|
+
*/
|
|
2206
|
+
process() {
|
|
2207
|
+
const templateIdentifier = this.getAttribute("identifier");
|
|
2208
|
+
if (!templateIdentifier) {
|
|
2209
|
+
console.warn('QtiSetTemplateValue: Missing "identifier" attribute.');
|
|
2210
|
+
return;
|
|
2211
|
+
}
|
|
2212
|
+
const expression = this.firstElementChild;
|
|
2213
|
+
if (!expression) {
|
|
2214
|
+
console.warn("QtiSetTemplateValue: No expression found.");
|
|
2215
|
+
return;
|
|
2216
|
+
}
|
|
2217
|
+
const rule = new QtiSetTemplateValueRule(expression);
|
|
2218
|
+
const value = rule.process();
|
|
2219
|
+
this.dispatchEvent(
|
|
2220
|
+
new CustomEvent("qti-set-template-value", {
|
|
2221
|
+
bubbles: true,
|
|
2222
|
+
composed: true,
|
|
2223
|
+
detail: {
|
|
2224
|
+
templateIdentifier,
|
|
2225
|
+
value: this.#formatValue(value)
|
|
2226
|
+
}
|
|
2227
|
+
})
|
|
2228
|
+
);
|
|
2229
|
+
}
|
|
2230
|
+
/**
|
|
2231
|
+
* Formats the computed value before dispatching.
|
|
2232
|
+
* Ensures numbers are converted to a universal format.
|
|
2233
|
+
*/
|
|
2234
|
+
#formatValue(value) {
|
|
2235
|
+
if (value === null || value === void 0) {
|
|
2236
|
+
return null;
|
|
2237
|
+
}
|
|
2238
|
+
if (Array.isArray(value)) {
|
|
2239
|
+
return value.map((item) => convertNumberToUniversalFormat(this.#unwrapValue(item)));
|
|
2240
|
+
}
|
|
2241
|
+
return convertNumberToUniversalFormat(this.#unwrapValue(value));
|
|
2242
|
+
}
|
|
2243
|
+
#unwrapValue(value) {
|
|
2244
|
+
if (value && typeof value === "object" && "value" in value) {
|
|
2245
|
+
const responseValue = value.value;
|
|
2246
|
+
return responseValue !== null && responseValue !== void 0 ? responseValue.toString() : "";
|
|
2247
|
+
}
|
|
2248
|
+
return value?.toString() ?? "";
|
|
2249
|
+
}
|
|
2250
|
+
};
|
|
2251
|
+
var QtiSetTemplateValueRule = class {
|
|
2252
|
+
constructor(expression) {
|
|
2253
|
+
this.expression = expression;
|
|
2254
|
+
}
|
|
2255
|
+
/**
|
|
2256
|
+
* Evaluates the expression and returns its value.
|
|
2257
|
+
*/
|
|
2258
|
+
process() {
|
|
2259
|
+
const value = this.expression.calculate() ?? null;
|
|
2260
|
+
if (value === null) {
|
|
2261
|
+
console.warn("QtiSetTemplateValueRule: Evaluated value is null.");
|
|
2262
|
+
}
|
|
2263
|
+
if (Array.isArray(value)) {
|
|
2264
|
+
return value.map((item) => this.#unwrapResult(item));
|
|
2265
|
+
}
|
|
2266
|
+
return this.#unwrapResult(value);
|
|
2267
|
+
}
|
|
2268
|
+
#unwrapResult(value) {
|
|
2269
|
+
if (value && typeof value === "object" && "value" in value) {
|
|
2270
|
+
return value.value;
|
|
2271
|
+
}
|
|
2272
|
+
return value;
|
|
2273
|
+
}
|
|
2274
|
+
};
|
|
2275
|
+
customElements.define("qti-set-template-value", QtiSetTemplateValue);
|
|
2276
|
+
|
|
2277
|
+
// ../qti-processing/src/components/qti-stats-operator/qti-stats-operator.ts
|
|
2278
|
+
var QtiStatsOperator = class extends QtiExpression {
|
|
2279
|
+
constructor() {
|
|
2280
|
+
super(...arguments);
|
|
2281
|
+
this.name = "";
|
|
2282
|
+
}
|
|
2283
|
+
getResult() {
|
|
2284
|
+
if (!this.name) {
|
|
2285
|
+
console.warn("qti-stats-operator: missing name attribute");
|
|
2286
|
+
return null;
|
|
2287
|
+
}
|
|
2288
|
+
const values = this.#collectNumericValues(this.getVariables());
|
|
2289
|
+
if (values.length === 0) {
|
|
2290
|
+
console.warn("qti-stats-operator: no numeric values provided");
|
|
2291
|
+
return null;
|
|
2292
|
+
}
|
|
2293
|
+
switch (this.name.toLowerCase()) {
|
|
2294
|
+
case "mean":
|
|
2295
|
+
return values.reduce((sum, value) => sum + value, 0) / values.length;
|
|
2296
|
+
case "popsd":
|
|
2297
|
+
return this.#populationStandardDeviation(values);
|
|
2298
|
+
default:
|
|
2299
|
+
console.warn(`qti-stats-operator: unsupported operator "${this.name}"`);
|
|
2300
|
+
return null;
|
|
2301
|
+
}
|
|
2302
|
+
}
|
|
2303
|
+
#populationStandardDeviation(values) {
|
|
2304
|
+
const mean = values.reduce((sum, value) => sum + value, 0) / values.length;
|
|
2305
|
+
const variance = values.reduce((sum, value) => sum + Math.pow(value - mean, 2), 0) / values.length;
|
|
2306
|
+
return Math.sqrt(variance);
|
|
2307
|
+
}
|
|
2308
|
+
#collectNumericValues(variables) {
|
|
2309
|
+
const values = [];
|
|
2310
|
+
for (const variable of variables) {
|
|
2311
|
+
if (!variable) {
|
|
2312
|
+
continue;
|
|
2313
|
+
}
|
|
2314
|
+
const pushValue = (raw) => {
|
|
2315
|
+
if (raw === null || raw === void 0) {
|
|
2316
|
+
return;
|
|
2317
|
+
}
|
|
2318
|
+
const numValue = parseFloat(raw.toString());
|
|
2319
|
+
if (Number.isNaN(numValue)) {
|
|
2320
|
+
console.warn("qti-stats-operator: non-numeric value encountered");
|
|
2321
|
+
return;
|
|
2322
|
+
}
|
|
2323
|
+
values.push(numValue);
|
|
2324
|
+
};
|
|
2325
|
+
if (Array.isArray(variable.value)) {
|
|
2326
|
+
variable.value.forEach((item) => pushValue(item));
|
|
2327
|
+
continue;
|
|
2328
|
+
}
|
|
2329
|
+
pushValue(variable.value);
|
|
2330
|
+
}
|
|
2331
|
+
return values;
|
|
2332
|
+
}
|
|
2333
|
+
};
|
|
2334
|
+
__decorateClass([
|
|
2335
|
+
n({ type: String })
|
|
2336
|
+
], QtiStatsOperator.prototype, "name", 2);
|
|
2337
|
+
customElements.define("qti-stats-operator", QtiStatsOperator);
|
|
2338
|
+
|
|
1430
2339
|
// ../qti-processing/src/components/qti-subtract/qti-subtract.ts
|
|
1431
2340
|
var QtiSubtract = class extends qtiSubtractMixin(QtiExpression) {
|
|
1432
2341
|
getResult() {
|
|
@@ -1458,6 +2367,39 @@ function qtiSubtractMixin(Base) {
|
|
|
1458
2367
|
};
|
|
1459
2368
|
}
|
|
1460
2369
|
|
|
2370
|
+
// ../qti-processing/src/components/qti-substring/qti-substring.ts
|
|
2371
|
+
var QtiSubstring = class extends QtiExpression {
|
|
2372
|
+
constructor() {
|
|
2373
|
+
super(...arguments);
|
|
2374
|
+
this.caseSensitive = "true";
|
|
2375
|
+
}
|
|
2376
|
+
getResult() {
|
|
2377
|
+
const variables = this.getVariables();
|
|
2378
|
+
if (variables.length !== 2) {
|
|
2379
|
+
console.error("qti-substring requires exactly 2 child expressions");
|
|
2380
|
+
return null;
|
|
2381
|
+
}
|
|
2382
|
+
const [needle, haystack] = variables;
|
|
2383
|
+
if (needle.cardinality !== "single" || haystack.cardinality !== "single" || Array.isArray(needle.value) || Array.isArray(haystack.value)) {
|
|
2384
|
+
console.error("qti-substring requires single cardinality");
|
|
2385
|
+
return null;
|
|
2386
|
+
}
|
|
2387
|
+
if (needle.value === null || haystack.value === null || needle.value === void 0 || haystack.value === void 0) {
|
|
2388
|
+
return null;
|
|
2389
|
+
}
|
|
2390
|
+
const left = needle.value.toString();
|
|
2391
|
+
const right = haystack.value.toString();
|
|
2392
|
+
if (this.caseSensitive !== "true") {
|
|
2393
|
+
return right.toLowerCase().includes(left.toLowerCase());
|
|
2394
|
+
}
|
|
2395
|
+
return right.includes(left);
|
|
2396
|
+
}
|
|
2397
|
+
};
|
|
2398
|
+
__decorateClass([
|
|
2399
|
+
n({ type: String, attribute: "case-sensitive" })
|
|
2400
|
+
], QtiSubstring.prototype, "caseSensitive", 2);
|
|
2401
|
+
customElements.define("qti-substring", QtiSubstring);
|
|
2402
|
+
|
|
1461
2403
|
// ../qti-processing/src/components/qti-string-match/qti-string-match.ts
|
|
1462
2404
|
var QtiStringMatch = class extends QtiExpression {
|
|
1463
2405
|
constructor() {
|
|
@@ -1516,6 +2458,36 @@ var QtiSumExpression = class {
|
|
|
1516
2458
|
};
|
|
1517
2459
|
customElements.define("qti-sum", QtiSum);
|
|
1518
2460
|
|
|
2461
|
+
// ../qti-processing/src/components/qti-truncate/qti-truncate.ts
|
|
2462
|
+
var QtiTruncate = class extends QtiExpression {
|
|
2463
|
+
getResult() {
|
|
2464
|
+
const variables = this.getVariables();
|
|
2465
|
+
if (variables.length !== 1) {
|
|
2466
|
+
console.error("qti-truncate requires exactly one child expression");
|
|
2467
|
+
return null;
|
|
2468
|
+
}
|
|
2469
|
+
const variable = variables[0];
|
|
2470
|
+
if (variable.cardinality !== "single" || Array.isArray(variable.value)) {
|
|
2471
|
+
console.error("qti-truncate requires single cardinality");
|
|
2472
|
+
return null;
|
|
2473
|
+
}
|
|
2474
|
+
if (variable.baseType !== "integer" && variable.baseType !== "float") {
|
|
2475
|
+
console.error("qti-truncate requires numerical base-type");
|
|
2476
|
+
return null;
|
|
2477
|
+
}
|
|
2478
|
+
if (variable.value === null || variable.value === void 0) {
|
|
2479
|
+
return null;
|
|
2480
|
+
}
|
|
2481
|
+
const value = Number.parseFloat(variable.value);
|
|
2482
|
+
if (Number.isNaN(value)) {
|
|
2483
|
+
console.error("qti-truncate requires a numerical value");
|
|
2484
|
+
return null;
|
|
2485
|
+
}
|
|
2486
|
+
return Math.trunc(value);
|
|
2487
|
+
}
|
|
2488
|
+
};
|
|
2489
|
+
customElements.define("qti-truncate", QtiTruncate);
|
|
2490
|
+
|
|
1519
2491
|
// ../qti-processing/src/components/qti-variable/qti-variable.ts
|
|
1520
2492
|
var QtiVariable = class extends QtiExpression {
|
|
1521
2493
|
getResult() {
|
|
@@ -1715,6 +2687,7 @@ export {
|
|
|
1715
2687
|
QtiResponseElseIf,
|
|
1716
2688
|
QtiAnd,
|
|
1717
2689
|
qtiAndMixin,
|
|
2690
|
+
QtiAnyN,
|
|
1718
2691
|
QtiBaseValue,
|
|
1719
2692
|
QtiContainerSize,
|
|
1720
2693
|
QtiContains,
|
|
@@ -1724,9 +2697,17 @@ export {
|
|
|
1724
2697
|
QtiRound,
|
|
1725
2698
|
QtiRoundTo,
|
|
1726
2699
|
QtiEqual,
|
|
2700
|
+
QtiDivide,
|
|
2701
|
+
QtiDurationGte,
|
|
2702
|
+
QtiDurationLt,
|
|
1727
2703
|
QtiGcd,
|
|
1728
2704
|
QtiGt,
|
|
1729
2705
|
QtiGte,
|
|
2706
|
+
QtiInside,
|
|
2707
|
+
QtiIntegerDivide,
|
|
2708
|
+
QtiIntegerModulus,
|
|
2709
|
+
QtiIntegerToFloat,
|
|
2710
|
+
QtiLcm,
|
|
1730
2711
|
QtiNull,
|
|
1731
2712
|
QtiIsNull,
|
|
1732
2713
|
QtiFieldValue,
|
|
@@ -1736,23 +2717,34 @@ export {
|
|
|
1736
2717
|
QtiMapResponsePoint,
|
|
1737
2718
|
QtiMathOperator,
|
|
1738
2719
|
QtiMatch,
|
|
2720
|
+
QtiMax,
|
|
1739
2721
|
QtiMember,
|
|
2722
|
+
QtiMin,
|
|
1740
2723
|
QtiMultiple,
|
|
1741
2724
|
QtiNot,
|
|
1742
2725
|
QtiOr,
|
|
1743
2726
|
QtiOrdered,
|
|
1744
2727
|
QtiPower,
|
|
2728
|
+
QtiPatternMatch,
|
|
1745
2729
|
QtiPrintedVariable,
|
|
1746
2730
|
QtiProduct,
|
|
2731
|
+
QtiRepeat,
|
|
2732
|
+
QtiSetCorrectResponse,
|
|
2733
|
+
QtiSetCorrectResponseRule,
|
|
2734
|
+
QtiSetTemplateValue,
|
|
2735
|
+
QtiSetTemplateValueRule,
|
|
2736
|
+
QtiStatsOperator,
|
|
1747
2737
|
QtiSubtract,
|
|
1748
2738
|
qtiSubtractMixin,
|
|
2739
|
+
QtiSubstring,
|
|
1749
2740
|
QtiStringMatch,
|
|
1750
2741
|
QtiSum,
|
|
1751
2742
|
QtiSumExpression,
|
|
2743
|
+
QtiTruncate,
|
|
1752
2744
|
QtiVariable,
|
|
1753
2745
|
QtiRandomInteger,
|
|
1754
2746
|
QtiRandom,
|
|
1755
2747
|
QtiDelete,
|
|
1756
2748
|
QtiIndex
|
|
1757
2749
|
};
|
|
1758
|
-
//# sourceMappingURL=chunk-
|
|
2750
|
+
//# sourceMappingURL=chunk-YLIYPNMK.js.map
|