@examplary/qti 0.0.1 → 1.0.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/README.md +6 -1
- package/dist/ims/ims-package.d.ts +1 -1
- package/dist/ims/ims-package.js +2 -2
- package/dist/ims/ims-package.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/qti/interactions/associate-interaction.d.ts +36 -0
- package/dist/qti/interactions/associate-interaction.js +46 -0
- package/dist/qti/interactions/associate-interaction.js.map +1 -0
- package/dist/qti/interactions/choice-interaction.d.ts +36 -0
- package/dist/qti/interactions/choice-interaction.js +43 -0
- package/dist/qti/interactions/choice-interaction.js.map +1 -0
- package/dist/qti/interactions/drawing-interaction.d.ts +25 -0
- package/dist/qti/interactions/drawing-interaction.js +30 -0
- package/dist/qti/interactions/drawing-interaction.js.map +1 -0
- package/dist/qti/interactions/end-attempt-interaction.d.ts +21 -0
- package/dist/qti/interactions/end-attempt-interaction.js +27 -0
- package/dist/qti/interactions/end-attempt-interaction.js.map +1 -0
- package/dist/qti/interactions/extended-text-interaction.d.ts +28 -0
- package/dist/qti/interactions/extended-text-interaction.js +34 -0
- package/dist/qti/interactions/extended-text-interaction.js.map +1 -0
- package/dist/qti/interactions/gap-match-interaction.d.ts +34 -0
- package/dist/qti/interactions/gap-match-interaction.js +46 -0
- package/dist/qti/interactions/gap-match-interaction.js.map +1 -0
- package/dist/qti/interactions/graphic-associate-interaction.d.ts +37 -0
- package/dist/qti/interactions/graphic-associate-interaction.js +47 -0
- package/dist/qti/interactions/graphic-associate-interaction.js.map +1 -0
- package/dist/qti/interactions/graphic-gap-match-interaction.d.ts +42 -0
- package/dist/qti/interactions/graphic-gap-match-interaction.js +64 -0
- package/dist/qti/interactions/graphic-gap-match-interaction.js.map +1 -0
- package/dist/qti/interactions/graphic-order-interaction.d.ts +28 -0
- package/dist/qti/interactions/graphic-order-interaction.js +46 -0
- package/dist/qti/interactions/graphic-order-interaction.js.map +1 -0
- package/dist/qti/interactions/hotspot-interaction.d.ts +41 -0
- package/dist/qti/interactions/hotspot-interaction.js +46 -0
- package/dist/qti/interactions/hotspot-interaction.js.map +1 -0
- package/dist/qti/interactions/hottext-interaction.d.ts +22 -0
- package/dist/qti/interactions/hottext-interaction.js +31 -0
- package/dist/qti/interactions/hottext-interaction.js.map +1 -0
- package/dist/qti/interactions/index.d.ts +63 -0
- package/dist/qti/interactions/index.js +64 -0
- package/dist/qti/interactions/index.js.map +1 -0
- package/dist/qti/interactions/inline-choice-interaction.d.ts +30 -0
- package/dist/qti/interactions/inline-choice-interaction.js +40 -0
- package/dist/qti/interactions/inline-choice-interaction.js.map +1 -0
- package/dist/qti/interactions/interaction.d.ts +20 -0
- package/dist/qti/interactions/interaction.js +24 -0
- package/dist/qti/interactions/interaction.js.map +1 -0
- package/dist/qti/interactions/match-interaction.d.ts +31 -0
- package/dist/qti/interactions/match-interaction.js +63 -0
- package/dist/qti/interactions/match-interaction.js.map +1 -0
- package/dist/qti/interactions/media-interaction.d.ts +31 -0
- package/dist/qti/interactions/media-interaction.js +36 -0
- package/dist/qti/interactions/media-interaction.js.map +1 -0
- package/dist/qti/interactions/order-interaction.d.ts +28 -0
- package/dist/qti/interactions/order-interaction.js +43 -0
- package/dist/qti/interactions/order-interaction.js.map +1 -0
- package/dist/qti/interactions/position-object-interaction.d.ts +36 -0
- package/dist/qti/interactions/position-object-interaction.js +43 -0
- package/dist/qti/interactions/position-object-interaction.js.map +1 -0
- package/dist/qti/interactions/select-point-interaction.d.ts +28 -0
- package/dist/qti/interactions/select-point-interaction.js +33 -0
- package/dist/qti/interactions/select-point-interaction.js.map +1 -0
- package/dist/qti/interactions/slider-interaction.d.ts +26 -0
- package/dist/qti/interactions/slider-interaction.js +32 -0
- package/dist/qti/interactions/slider-interaction.js.map +1 -0
- package/dist/qti/interactions/text-entry-interaction.d.ts +25 -0
- package/dist/qti/interactions/text-entry-interaction.js +31 -0
- package/dist/qti/interactions/text-entry-interaction.js.map +1 -0
- package/dist/qti/interactions/upload-interaction.d.ts +19 -0
- package/dist/qti/interactions/upload-interaction.js +25 -0
- package/dist/qti/interactions/upload-interaction.js.map +1 -0
- package/dist/qti/qti-element.d.ts +11 -0
- package/dist/qti/qti-element.js +29 -0
- package/dist/qti/qti-element.js.map +1 -0
- package/dist/qti/qti-item.d.ts +7 -3
- package/dist/qti/qti-item.js +18 -21
- package/dist/qti/qti-item.js.map +1 -1
- package/dist/qti/qti-test.d.ts +5 -3
- package/dist/qti/qti-test.js +8 -6
- package/dist/qti/qti-test.js.map +1 -1
- package/dist/utils/html.d.ts +2 -0
- package/dist/utils/html.js +15 -0
- package/dist/utils/html.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,9 +20,14 @@ const item = new QtiItem({
|
|
|
20
20
|
title: "Sample Question",
|
|
21
21
|
});
|
|
22
22
|
|
|
23
|
-
item.addItemBodyFromHtml("<p>What is 2 + 2?</p>");
|
|
24
23
|
item.addResponseDeclaration({ identifier: "RESPONSE" });
|
|
25
24
|
item.addCorrectResponse("RESPONSE", ["4"]);
|
|
25
|
+
|
|
26
|
+
item.addItemBodyFromHtml("<p>What is 2 + 2?</p>");
|
|
27
|
+
item.addInteraction(
|
|
28
|
+
new TextEntryInteraction({ responseIdentifier: "RESPONSE" }),
|
|
29
|
+
);
|
|
30
|
+
|
|
26
31
|
item.addResponseProcessing(ResponseProcessingTemplate.MatchCorrect);
|
|
27
32
|
|
|
28
33
|
item.addToTest(test);
|
|
@@ -21,7 +21,7 @@ export declare class ImsPackage {
|
|
|
21
21
|
/**
|
|
22
22
|
* Add a resource to the IMS Package, along with its associated files.
|
|
23
23
|
*/
|
|
24
|
-
addResource(resource: ImsManifestResourceWithoutFiles, files: ImsPackageFile[]): void
|
|
24
|
+
addResource(resource: ImsManifestResourceWithoutFiles, files: ImsPackageFile[]): Promise<void>;
|
|
25
25
|
/**
|
|
26
26
|
* Add a file directly to the final ZIP, without adding it to the manifest.
|
|
27
27
|
* Can fetch from URL or add from data.
|
package/dist/ims/ims-package.js
CHANGED
|
@@ -11,9 +11,9 @@ export class ImsPackage {
|
|
|
11
11
|
/**
|
|
12
12
|
* Add a resource to the IMS Package, along with its associated files.
|
|
13
13
|
*/
|
|
14
|
-
addResource(resource, files) {
|
|
14
|
+
async addResource(resource, files) {
|
|
15
15
|
for (const file of files) {
|
|
16
|
-
this.addFileDirectly(file);
|
|
16
|
+
await this.addFileDirectly(file);
|
|
17
17
|
}
|
|
18
18
|
this.manifest.addResource({
|
|
19
19
|
...resource,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ims-package.js","sourceRoot":"","sources":["../../src/ims/ims-package.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,OAAO,CAAC;AAExB,OAAO,EACL,WAAW,GAGZ,MAAM,gBAAgB,CAAC;AA0BxB,MAAM,OAAO,UAAU;IAIrB;;OAEG;IACH,YAAY,eAAoC;QAC9C,IAAI,CAAC,QAAQ,GAAG,IAAI,WAAW,CAAC,eAAe,CAAC,CAAC;QACjD,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,WAAW,
|
|
1
|
+
{"version":3,"file":"ims-package.js","sourceRoot":"","sources":["../../src/ims/ims-package.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,OAAO,CAAC;AAExB,OAAO,EACL,WAAW,GAGZ,MAAM,gBAAgB,CAAC;AA0BxB,MAAM,OAAO,UAAU;IAIrB;;OAEG;IACH,YAAY,eAAoC;QAC9C,IAAI,CAAC,QAAQ,GAAG,IAAI,WAAW,CAAC,eAAe,CAAC,CAAC;QACjD,IAAI,CAAC,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CACf,QAAyC,EACzC,KAAuB;QAEvB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QACnC,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC;YACxB,GAAG,QAAQ;YACX,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;SACtD,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,eAAe,CAAC,IAAoB;QACxC,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;YAClB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACvC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CACb,iCAAiC,IAAI,CAAC,GAAG,KAAK,QAAQ,CAAC,UAAU,EAAE,CACpE,CAAC;YACJ,CAAC;YACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC;YAE1C,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACrC,CAAC;QAED,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IAED;;OAEG;IACH,WAAW;QACT,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;QAE3D,OAAO,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAC;IACzD,CAAC;CACF"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export * from "./ims/ims-manifest";
|
|
2
2
|
export * from "./ims/ims-package";
|
|
3
|
+
export * from "./qti/qti-element";
|
|
3
4
|
export * from "./qti/qti-test";
|
|
4
5
|
export * from "./qti/qti-item";
|
|
6
|
+
export * from "./qti/interactions";
|
|
5
7
|
export * from "./qti/types";
|
|
6
8
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,aAAa,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { QtiPromptInteraction, QtiPromptInteractionOptions } from "./interaction";
|
|
2
|
+
export type SimpleAssociableChoiceOptions = {
|
|
3
|
+
identifier: string;
|
|
4
|
+
matchMax?: number;
|
|
5
|
+
matchMin?: number;
|
|
6
|
+
matchGroup?: string;
|
|
7
|
+
fixed?: boolean;
|
|
8
|
+
templateIdentifier?: string;
|
|
9
|
+
content?: string;
|
|
10
|
+
};
|
|
11
|
+
export type AssociateInteractionOptions = QtiPromptInteractionOptions & {
|
|
12
|
+
shuffle?: boolean;
|
|
13
|
+
minAssociations?: number;
|
|
14
|
+
maxAssociations?: number;
|
|
15
|
+
choices?: SimpleAssociableChoiceOptions[];
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Presents a set of choices for candidates to pair or associate with each other.
|
|
19
|
+
* Unlike MatchInteraction, choices come from a single set and can be paired freely.
|
|
20
|
+
*
|
|
21
|
+
* @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.7cs7637r54vv
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* const interaction = new AssociateInteraction({
|
|
25
|
+
* responseIdentifier: "RESPONSE",
|
|
26
|
+
* choices: [
|
|
27
|
+
* { identifier: "A", content: "Cat", matchMax: 1 },
|
|
28
|
+
* { identifier: "B", content: "Dog", matchMax: 1 },
|
|
29
|
+
* { identifier: "C", content: "Meow", matchMax: 1 },
|
|
30
|
+
* { identifier: "D", content: "Bark", matchMax: 1 },
|
|
31
|
+
* ],
|
|
32
|
+
* });
|
|
33
|
+
*/
|
|
34
|
+
export declare class AssociateInteraction extends QtiPromptInteraction {
|
|
35
|
+
constructor(options: AssociateInteractionOptions);
|
|
36
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { fragment } from "xmlbuilder2";
|
|
2
|
+
import { QtiPromptInteraction, } from "./interaction";
|
|
3
|
+
import { appendHtmlFragment } from "../../utils/html";
|
|
4
|
+
/**
|
|
5
|
+
* Presents a set of choices for candidates to pair or associate with each other.
|
|
6
|
+
* Unlike MatchInteraction, choices come from a single set and can be paired freely.
|
|
7
|
+
*
|
|
8
|
+
* @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.7cs7637r54vv
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* const interaction = new AssociateInteraction({
|
|
12
|
+
* responseIdentifier: "RESPONSE",
|
|
13
|
+
* choices: [
|
|
14
|
+
* { identifier: "A", content: "Cat", matchMax: 1 },
|
|
15
|
+
* { identifier: "B", content: "Dog", matchMax: 1 },
|
|
16
|
+
* { identifier: "C", content: "Meow", matchMax: 1 },
|
|
17
|
+
* { identifier: "D", content: "Bark", matchMax: 1 },
|
|
18
|
+
* ],
|
|
19
|
+
* });
|
|
20
|
+
*/
|
|
21
|
+
export class AssociateInteraction extends QtiPromptInteraction {
|
|
22
|
+
constructor(options) {
|
|
23
|
+
super(options);
|
|
24
|
+
this.item = fragment().ele("qti-associate-interaction", {
|
|
25
|
+
"response-identifier": options.responseIdentifier,
|
|
26
|
+
label: options.label,
|
|
27
|
+
shuffle: options.shuffle ? "true" : "false",
|
|
28
|
+
"min-associations": options.minAssociations?.toString(),
|
|
29
|
+
"max-associations": options.maxAssociations?.toString(),
|
|
30
|
+
});
|
|
31
|
+
for (const choice of options.choices || []) {
|
|
32
|
+
const choiceEl = this.item.ele("qti-simple-associable-choice", {
|
|
33
|
+
identifier: choice.identifier,
|
|
34
|
+
"match-max": choice.matchMax?.toString(),
|
|
35
|
+
"match-min": choice.matchMin?.toString(),
|
|
36
|
+
"match-group": choice.matchGroup,
|
|
37
|
+
fixed: choice.fixed ? "true" : undefined,
|
|
38
|
+
"template-identifier": choice.templateIdentifier,
|
|
39
|
+
});
|
|
40
|
+
if (choice.content) {
|
|
41
|
+
appendHtmlFragment(choice.content, choiceEl);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=associate-interaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"associate-interaction.js","sourceRoot":"","sources":["../../../src/qti/interactions/associate-interaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,OAAO,EACL,oBAAoB,GAErB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAmBtD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,oBAAqB,SAAQ,oBAAoB;IAC5D,YAAY,OAAoC;QAC9C,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,IAAI,CAAC,IAAI,GAAG,QAAQ,EAAE,CAAC,GAAG,CAAC,2BAA2B,EAAE;YACtD,qBAAqB,EAAE,OAAO,CAAC,kBAAkB;YACjD,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;YAC3C,kBAAkB,EAAE,OAAO,CAAC,eAAe,EAAE,QAAQ,EAAE;YACvD,kBAAkB,EAAE,OAAO,CAAC,eAAe,EAAE,QAAQ,EAAE;SACxD,CAAC,CAAC;QAEH,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;YAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,8BAA8B,EAAE;gBAC7D,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,WAAW,EAAE,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE;gBACxC,WAAW,EAAE,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE;gBACxC,aAAa,EAAE,MAAM,CAAC,UAAU;gBAChC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;gBACxC,qBAAqB,EAAE,MAAM,CAAC,kBAAkB;aACjD,CAAC,CAAC;YAEH,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,kBAAkB,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YAC/C,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { QtiPromptInteraction, QtiPromptInteractionOptions } from "./interaction";
|
|
2
|
+
export type SimpleChoiceOptions = {
|
|
3
|
+
identifier: string;
|
|
4
|
+
fixed?: boolean;
|
|
5
|
+
templateIdentifier?: string;
|
|
6
|
+
label?: string;
|
|
7
|
+
content?: string;
|
|
8
|
+
};
|
|
9
|
+
export type ChoiceInteractionOptions = QtiPromptInteractionOptions & {
|
|
10
|
+
shuffle?: boolean;
|
|
11
|
+
maxChoices?: number;
|
|
12
|
+
minChoices?: number;
|
|
13
|
+
orientation?: "horizontal" | "vertical";
|
|
14
|
+
minSelectionsMessage?: string;
|
|
15
|
+
maxSelectionsMessage?: string;
|
|
16
|
+
choices?: SimpleChoiceOptions[];
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Presents a set of choices for candidates to select one or more options.
|
|
20
|
+
* Supports single-select (radio) or multi-select (checkbox) modes via maxChoices.
|
|
21
|
+
*
|
|
22
|
+
* @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.j9nu1oa1tu3b
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* const interaction = new ChoiceInteraction({
|
|
26
|
+
* responseIdentifier: "RESPONSE",
|
|
27
|
+
* maxChoices: 1,
|
|
28
|
+
* choices: [
|
|
29
|
+
* { identifier: "A", content: "Option A" },
|
|
30
|
+
* { identifier: "B", content: "Option B" },
|
|
31
|
+
* ],
|
|
32
|
+
* });
|
|
33
|
+
*/
|
|
34
|
+
export declare class ChoiceInteraction extends QtiPromptInteraction {
|
|
35
|
+
constructor(options: ChoiceInteractionOptions);
|
|
36
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { fragment } from "xmlbuilder2";
|
|
2
|
+
import { QtiPromptInteraction, } from "./interaction";
|
|
3
|
+
import { appendHtmlFragment } from "../../utils/html";
|
|
4
|
+
/**
|
|
5
|
+
* Presents a set of choices for candidates to select one or more options.
|
|
6
|
+
* Supports single-select (radio) or multi-select (checkbox) modes via maxChoices.
|
|
7
|
+
*
|
|
8
|
+
* @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.j9nu1oa1tu3b
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* const interaction = new ChoiceInteraction({
|
|
12
|
+
* responseIdentifier: "RESPONSE",
|
|
13
|
+
* maxChoices: 1,
|
|
14
|
+
* choices: [
|
|
15
|
+
* { identifier: "A", content: "Option A" },
|
|
16
|
+
* { identifier: "B", content: "Option B" },
|
|
17
|
+
* ],
|
|
18
|
+
* });
|
|
19
|
+
*/
|
|
20
|
+
export class ChoiceInteraction extends QtiPromptInteraction {
|
|
21
|
+
constructor(options) {
|
|
22
|
+
super(options);
|
|
23
|
+
this.item = fragment().ele("qti-choice-interaction", {
|
|
24
|
+
"response-identifier": options.responseIdentifier,
|
|
25
|
+
label: options.label,
|
|
26
|
+
shuffle: options.shuffle ? "true" : "false",
|
|
27
|
+
"max-choices": options.maxChoices?.toString(),
|
|
28
|
+
"min-choices": options.minChoices?.toString(),
|
|
29
|
+
orientation: options.orientation,
|
|
30
|
+
"data-min-selections-message": options.minSelectionsMessage,
|
|
31
|
+
"data-max-selections-message": options.maxSelectionsMessage,
|
|
32
|
+
});
|
|
33
|
+
for (const choice of options.choices || []) {
|
|
34
|
+
appendHtmlFragment(choice.content || "", this.item.ele("qti-simple-choice", {
|
|
35
|
+
identifier: choice.identifier,
|
|
36
|
+
fixed: choice.fixed ? "true" : "false",
|
|
37
|
+
"template-identifier": choice.templateIdentifier,
|
|
38
|
+
label: choice.label,
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=choice-interaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"choice-interaction.js","sourceRoot":"","sources":["../../../src/qti/interactions/choice-interaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,OAAO,EACL,oBAAoB,GAErB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAoBtD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,iBAAkB,SAAQ,oBAAoB;IACzD,YAAY,OAAiC;QAC3C,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,IAAI,CAAC,IAAI,GAAG,QAAQ,EAAE,CAAC,GAAG,CAAC,wBAAwB,EAAE;YACnD,qBAAqB,EAAE,OAAO,CAAC,kBAAkB;YACjD,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;YAC3C,aAAa,EAAE,OAAO,CAAC,UAAU,EAAE,QAAQ,EAAE;YAC7C,aAAa,EAAE,OAAO,CAAC,UAAU,EAAE,QAAQ,EAAE;YAC7C,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,6BAA6B,EAAE,OAAO,CAAC,oBAAoB;YAC3D,6BAA6B,EAAE,OAAO,CAAC,oBAAoB;SAC5D,CAAC,CAAC;QAEH,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;YAC3C,kBAAkB,CAChB,MAAM,CAAC,OAAO,IAAI,EAAE,EACpB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,mBAAmB,EAAE;gBACjC,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;gBACtC,qBAAqB,EAAE,MAAM,CAAC,kBAAkB;gBAChD,KAAK,EAAE,MAAM,CAAC,KAAK;aACpB,CAAC,CACH,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { QtiPromptInteraction, QtiPromptInteractionOptions } from "./interaction";
|
|
2
|
+
export type DrawingObjectOptions = {
|
|
3
|
+
data: string;
|
|
4
|
+
type: string;
|
|
5
|
+
width?: number;
|
|
6
|
+
height?: number;
|
|
7
|
+
};
|
|
8
|
+
export type DrawingInteractionOptions = QtiPromptInteractionOptions & {
|
|
9
|
+
object: DrawingObjectOptions;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Presents a canvas where candidates can draw or annotate over a background image.
|
|
13
|
+
* Used for freeform drawing, labeling, or annotation tasks.
|
|
14
|
+
*
|
|
15
|
+
* @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.8yrkpwgsrs4b
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* const interaction = new DrawingInteraction({
|
|
19
|
+
* responseIdentifier: "RESPONSE",
|
|
20
|
+
* object: { data: "canvas.png", type: "image/png", width: 400, height: 300 },
|
|
21
|
+
* });
|
|
22
|
+
*/
|
|
23
|
+
export declare class DrawingInteraction extends QtiPromptInteraction {
|
|
24
|
+
constructor(options: DrawingInteractionOptions);
|
|
25
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { fragment } from "xmlbuilder2";
|
|
2
|
+
import { QtiPromptInteraction, } from "./interaction";
|
|
3
|
+
/**
|
|
4
|
+
* Presents a canvas where candidates can draw or annotate over a background image.
|
|
5
|
+
* Used for freeform drawing, labeling, or annotation tasks.
|
|
6
|
+
*
|
|
7
|
+
* @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.8yrkpwgsrs4b
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const interaction = new DrawingInteraction({
|
|
11
|
+
* responseIdentifier: "RESPONSE",
|
|
12
|
+
* object: { data: "canvas.png", type: "image/png", width: 400, height: 300 },
|
|
13
|
+
* });
|
|
14
|
+
*/
|
|
15
|
+
export class DrawingInteraction extends QtiPromptInteraction {
|
|
16
|
+
constructor(options) {
|
|
17
|
+
super(options);
|
|
18
|
+
this.item = fragment().ele("qti-drawing-interaction", {
|
|
19
|
+
"response-identifier": options.responseIdentifier,
|
|
20
|
+
label: options.label,
|
|
21
|
+
});
|
|
22
|
+
this.item.ele("object", {
|
|
23
|
+
data: options.object.data,
|
|
24
|
+
type: options.object.type,
|
|
25
|
+
width: options.object.width?.toString(),
|
|
26
|
+
height: options.object.height?.toString(),
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=drawing-interaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"drawing-interaction.js","sourceRoot":"","sources":["../../../src/qti/interactions/drawing-interaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,OAAO,EACL,oBAAoB,GAErB,MAAM,eAAe,CAAC;AAavB;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,kBAAmB,SAAQ,oBAAoB;IAC1D,YAAY,OAAkC;QAC5C,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,IAAI,CAAC,IAAI,GAAG,QAAQ,EAAE,CAAC,GAAG,CAAC,yBAAyB,EAAE;YACpD,qBAAqB,EAAE,OAAO,CAAC,kBAAkB;YACjD,KAAK,EAAE,OAAO,CAAC,KAAK;SACrB,CAAC,CAAC;QAEH,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE;YACtB,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI;YACzB,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI;YACzB,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE;YACvC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE;SAC1C,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { QtiInteraction, QtiInteractionOptions } from "./interaction";
|
|
2
|
+
export type EndAttemptInteractionOptions = QtiInteractionOptions & {
|
|
3
|
+
title: string;
|
|
4
|
+
countAttempt?: boolean;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Presents a button that allows candidates to voluntarily end their assessment attempt.
|
|
8
|
+
* Used for "give up" or "submit early" functionality in adaptive testing scenarios.
|
|
9
|
+
*
|
|
10
|
+
* @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.b3g8rgbtuwqp
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* const interaction = new EndAttemptInteraction({
|
|
14
|
+
* responseIdentifier: "RESPONSE",
|
|
15
|
+
* title: "Give Up",
|
|
16
|
+
* countAttempt: true,
|
|
17
|
+
* });
|
|
18
|
+
*/
|
|
19
|
+
export declare class EndAttemptInteraction extends QtiInteraction {
|
|
20
|
+
constructor(options: EndAttemptInteractionOptions);
|
|
21
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { fragment } from "xmlbuilder2";
|
|
2
|
+
import { QtiInteraction } from "./interaction";
|
|
3
|
+
/**
|
|
4
|
+
* Presents a button that allows candidates to voluntarily end their assessment attempt.
|
|
5
|
+
* Used for "give up" or "submit early" functionality in adaptive testing scenarios.
|
|
6
|
+
*
|
|
7
|
+
* @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.b3g8rgbtuwqp
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const interaction = new EndAttemptInteraction({
|
|
11
|
+
* responseIdentifier: "RESPONSE",
|
|
12
|
+
* title: "Give Up",
|
|
13
|
+
* countAttempt: true,
|
|
14
|
+
* });
|
|
15
|
+
*/
|
|
16
|
+
export class EndAttemptInteraction extends QtiInteraction {
|
|
17
|
+
constructor(options) {
|
|
18
|
+
super(options);
|
|
19
|
+
this.item = fragment().ele("qti-end-attempt-interaction", {
|
|
20
|
+
"response-identifier": options.responseIdentifier,
|
|
21
|
+
label: options.label,
|
|
22
|
+
title: options.title,
|
|
23
|
+
"count-attempt": options.countAttempt ? "true" : undefined,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=end-attempt-interaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"end-attempt-interaction.js","sourceRoot":"","sources":["../../../src/qti/interactions/end-attempt-interaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,OAAO,EAAE,cAAc,EAAyB,MAAM,eAAe,CAAC;AAOtE;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,qBAAsB,SAAQ,cAAc;IACvD,YAAY,OAAqC;QAC/C,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,IAAI,CAAC,IAAI,GAAG,QAAQ,EAAE,CAAC,GAAG,CAAC,6BAA6B,EAAE;YACxD,qBAAqB,EAAE,OAAO,CAAC,kBAAkB;YACjD,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,eAAe,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;SAC3D,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { QtiPromptInteraction, QtiPromptInteractionOptions } from "./interaction";
|
|
2
|
+
export type ExtendedTextInteractionOptions = QtiPromptInteractionOptions & {
|
|
3
|
+
base?: number;
|
|
4
|
+
stringIdentifier?: string;
|
|
5
|
+
expectedLength?: number;
|
|
6
|
+
patternMask?: string;
|
|
7
|
+
placeholderText?: string;
|
|
8
|
+
maxStrings?: number;
|
|
9
|
+
minStrings?: number;
|
|
10
|
+
expectedLines?: number;
|
|
11
|
+
format?: "plain" | "pre-formatted" | "xhtml";
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Allows candidates to enter extended text responses, such as essays or paragraphs.
|
|
15
|
+
* Supports configurable length constraints, formatting options, and input validation.
|
|
16
|
+
*
|
|
17
|
+
* @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.omuxci3o5dmg
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* const interaction = new ExtendedTextInteraction({
|
|
21
|
+
* responseIdentifier: "RESPONSE",
|
|
22
|
+
* expectedLines: 10,
|
|
23
|
+
* format: "plain",
|
|
24
|
+
* });
|
|
25
|
+
*/
|
|
26
|
+
export declare class ExtendedTextInteraction extends QtiPromptInteraction {
|
|
27
|
+
constructor(options: ExtendedTextInteractionOptions);
|
|
28
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { fragment } from "xmlbuilder2";
|
|
2
|
+
import { QtiPromptInteraction, } from "./interaction";
|
|
3
|
+
/**
|
|
4
|
+
* Allows candidates to enter extended text responses, such as essays or paragraphs.
|
|
5
|
+
* Supports configurable length constraints, formatting options, and input validation.
|
|
6
|
+
*
|
|
7
|
+
* @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.omuxci3o5dmg
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const interaction = new ExtendedTextInteraction({
|
|
11
|
+
* responseIdentifier: "RESPONSE",
|
|
12
|
+
* expectedLines: 10,
|
|
13
|
+
* format: "plain",
|
|
14
|
+
* });
|
|
15
|
+
*/
|
|
16
|
+
export class ExtendedTextInteraction extends QtiPromptInteraction {
|
|
17
|
+
constructor(options) {
|
|
18
|
+
super(options);
|
|
19
|
+
this.item = fragment().ele("qti-extended-text-interaction", {
|
|
20
|
+
"response-identifier": options.responseIdentifier,
|
|
21
|
+
label: options.label,
|
|
22
|
+
base: options.base?.toString(),
|
|
23
|
+
"string-identifier": options.stringIdentifier,
|
|
24
|
+
"expected-length": options.expectedLength?.toString(),
|
|
25
|
+
"pattern-mask": options.patternMask,
|
|
26
|
+
"placeholder-text": options.placeholderText,
|
|
27
|
+
"max-strings": options.maxStrings?.toString(),
|
|
28
|
+
"min-strings": options.minStrings?.toString(),
|
|
29
|
+
"expected-lines": options.expectedLines?.toString(),
|
|
30
|
+
format: options.format,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=extended-text-interaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extended-text-interaction.js","sourceRoot":"","sources":["../../../src/qti/interactions/extended-text-interaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,OAAO,EACL,oBAAoB,GAErB,MAAM,eAAe,CAAC;AAcvB;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,uBAAwB,SAAQ,oBAAoB;IAC/D,YAAY,OAAuC;QACjD,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,IAAI,CAAC,IAAI,GAAG,QAAQ,EAAE,CAAC,GAAG,CAAC,+BAA+B,EAAE;YAC1D,qBAAqB,EAAE,OAAO,CAAC,kBAAkB;YACjD,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE;YAC9B,mBAAmB,EAAE,OAAO,CAAC,gBAAgB;YAC7C,iBAAiB,EAAE,OAAO,CAAC,cAAc,EAAE,QAAQ,EAAE;YACrD,cAAc,EAAE,OAAO,CAAC,WAAW;YACnC,kBAAkB,EAAE,OAAO,CAAC,eAAe;YAC3C,aAAa,EAAE,OAAO,CAAC,UAAU,EAAE,QAAQ,EAAE;YAC7C,aAAa,EAAE,OAAO,CAAC,UAAU,EAAE,QAAQ,EAAE;YAC7C,gBAAgB,EAAE,OAAO,CAAC,aAAa,EAAE,QAAQ,EAAE;YACnD,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { QtiPromptInteraction, QtiPromptInteractionOptions } from "./interaction";
|
|
2
|
+
export type GapTextOptions = {
|
|
3
|
+
identifier: string;
|
|
4
|
+
matchMax?: number;
|
|
5
|
+
matchMin?: number;
|
|
6
|
+
matchGroup?: string;
|
|
7
|
+
content?: string;
|
|
8
|
+
};
|
|
9
|
+
export type GapMatchInteractionOptions = QtiPromptInteractionOptions & {
|
|
10
|
+
shuffle?: boolean;
|
|
11
|
+
minAssociations?: number;
|
|
12
|
+
maxAssociations?: number;
|
|
13
|
+
gapTexts?: GapTextOptions[];
|
|
14
|
+
content?: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Presents candidates with a set of gaps within content and a set of choices to fill them.
|
|
18
|
+
* Candidates drag or select choices to match them with the appropriate gaps.
|
|
19
|
+
*
|
|
20
|
+
* @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.7sroqk3xl8e1
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* const interaction = new GapMatchInteraction({
|
|
24
|
+
* responseIdentifier: "RESPONSE",
|
|
25
|
+
* gapTexts: [
|
|
26
|
+
* { identifier: "gap-1", content: "Paris" },
|
|
27
|
+
* { identifier: "gap-2", content: "London" },
|
|
28
|
+
* ],
|
|
29
|
+
* content: "<p>The capital of France is <qti-gap identifier='G1'/>.</p>",
|
|
30
|
+
* });
|
|
31
|
+
*/
|
|
32
|
+
export declare class GapMatchInteraction extends QtiPromptInteraction {
|
|
33
|
+
constructor(options: GapMatchInteractionOptions);
|
|
34
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { fragment } from "xmlbuilder2";
|
|
2
|
+
import { QtiPromptInteraction, } from "./interaction";
|
|
3
|
+
import { appendHtmlFragment } from "../../utils/html";
|
|
4
|
+
/**
|
|
5
|
+
* Presents candidates with a set of gaps within content and a set of choices to fill them.
|
|
6
|
+
* Candidates drag or select choices to match them with the appropriate gaps.
|
|
7
|
+
*
|
|
8
|
+
* @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.7sroqk3xl8e1
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* const interaction = new GapMatchInteraction({
|
|
12
|
+
* responseIdentifier: "RESPONSE",
|
|
13
|
+
* gapTexts: [
|
|
14
|
+
* { identifier: "gap-1", content: "Paris" },
|
|
15
|
+
* { identifier: "gap-2", content: "London" },
|
|
16
|
+
* ],
|
|
17
|
+
* content: "<p>The capital of France is <qti-gap identifier='G1'/>.</p>",
|
|
18
|
+
* });
|
|
19
|
+
*/
|
|
20
|
+
export class GapMatchInteraction extends QtiPromptInteraction {
|
|
21
|
+
constructor(options) {
|
|
22
|
+
super(options);
|
|
23
|
+
this.item = fragment().ele("qti-gap-match-interaction", {
|
|
24
|
+
"response-identifier": options.responseIdentifier,
|
|
25
|
+
label: options.label,
|
|
26
|
+
shuffle: options.shuffle ? "true" : "false",
|
|
27
|
+
"min-associations": options.minAssociations?.toString(),
|
|
28
|
+
"max-associations": options.maxAssociations?.toString(),
|
|
29
|
+
});
|
|
30
|
+
for (const gapText of options.gapTexts || []) {
|
|
31
|
+
const gapTextEl = this.item.ele("qti-gap-text", {
|
|
32
|
+
identifier: gapText.identifier,
|
|
33
|
+
"match-max": gapText.matchMax?.toString(),
|
|
34
|
+
"match-min": gapText.matchMin?.toString(),
|
|
35
|
+
"match-group": gapText.matchGroup,
|
|
36
|
+
});
|
|
37
|
+
if (gapText.content) {
|
|
38
|
+
appendHtmlFragment(gapText.content, gapTextEl);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (options.content) {
|
|
42
|
+
appendHtmlFragment(options.content, this.item);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=gap-match-interaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gap-match-interaction.js","sourceRoot":"","sources":["../../../src/qti/interactions/gap-match-interaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,OAAO,EACL,oBAAoB,GAErB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAkBtD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,mBAAoB,SAAQ,oBAAoB;IAC3D,YAAY,OAAmC;QAC7C,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,IAAI,CAAC,IAAI,GAAG,QAAQ,EAAE,CAAC,GAAG,CAAC,2BAA2B,EAAE;YACtD,qBAAqB,EAAE,OAAO,CAAC,kBAAkB;YACjD,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;YAC3C,kBAAkB,EAAE,OAAO,CAAC,eAAe,EAAE,QAAQ,EAAE;YACvD,kBAAkB,EAAE,OAAO,CAAC,eAAe,EAAE,QAAQ,EAAE;SACxD,CAAC,CAAC;QAEH,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;YAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE;gBAC9C,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,WAAW,EAAE,OAAO,CAAC,QAAQ,EAAE,QAAQ,EAAE;gBACzC,WAAW,EAAE,OAAO,CAAC,QAAQ,EAAE,QAAQ,EAAE;gBACzC,aAAa,EAAE,OAAO,CAAC,UAAU;aAClC,CAAC,CAAC;YAEH,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBACpB,kBAAkB,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,kBAAkB,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { HotspotShape, ObjectOptions } from "./hotspot-interaction";
|
|
2
|
+
import { QtiPromptInteraction, QtiPromptInteractionOptions } from "./interaction";
|
|
3
|
+
export { HotspotShape, ObjectOptions };
|
|
4
|
+
export type AssociableHotspotOptions = {
|
|
5
|
+
identifier: string;
|
|
6
|
+
shape: HotspotShape;
|
|
7
|
+
coords: string;
|
|
8
|
+
matchMax?: number;
|
|
9
|
+
matchMin?: number;
|
|
10
|
+
matchGroup?: string;
|
|
11
|
+
hotspotLabel?: string;
|
|
12
|
+
};
|
|
13
|
+
export type GraphicAssociateInteractionOptions = QtiPromptInteractionOptions & {
|
|
14
|
+
minAssociations?: number;
|
|
15
|
+
maxAssociations?: number;
|
|
16
|
+
object: ObjectOptions;
|
|
17
|
+
associableHotspots?: AssociableHotspotOptions[];
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Presents an image with hotspots for candidates to associate or connect with each other.
|
|
21
|
+
* Used for drawing connections between points on a diagram or map.
|
|
22
|
+
*
|
|
23
|
+
* @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.acwq9g2z1cwt
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* const interaction = new GraphicAssociateInteraction({
|
|
27
|
+
* responseIdentifier: "RESPONSE",
|
|
28
|
+
* object: { data: "circuit.png", type: "image/png", width: 400, height: 300 },
|
|
29
|
+
* associableHotspots: [
|
|
30
|
+
* { identifier: "A", shape: "circle", coords: "100,100,15", matchMax: 1 },
|
|
31
|
+
* { identifier: "B", shape: "circle", coords: "200,100,15", matchMax: 1 },
|
|
32
|
+
* ],
|
|
33
|
+
* });
|
|
34
|
+
*/
|
|
35
|
+
export declare class GraphicAssociateInteraction extends QtiPromptInteraction {
|
|
36
|
+
constructor(options: GraphicAssociateInteractionOptions);
|
|
37
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { fragment } from "xmlbuilder2";
|
|
2
|
+
import { QtiPromptInteraction, } from "./interaction";
|
|
3
|
+
/**
|
|
4
|
+
* Presents an image with hotspots for candidates to associate or connect with each other.
|
|
5
|
+
* Used for drawing connections between points on a diagram or map.
|
|
6
|
+
*
|
|
7
|
+
* @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.acwq9g2z1cwt
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* const interaction = new GraphicAssociateInteraction({
|
|
11
|
+
* responseIdentifier: "RESPONSE",
|
|
12
|
+
* object: { data: "circuit.png", type: "image/png", width: 400, height: 300 },
|
|
13
|
+
* associableHotspots: [
|
|
14
|
+
* { identifier: "A", shape: "circle", coords: "100,100,15", matchMax: 1 },
|
|
15
|
+
* { identifier: "B", shape: "circle", coords: "200,100,15", matchMax: 1 },
|
|
16
|
+
* ],
|
|
17
|
+
* });
|
|
18
|
+
*/
|
|
19
|
+
export class GraphicAssociateInteraction extends QtiPromptInteraction {
|
|
20
|
+
constructor(options) {
|
|
21
|
+
super(options);
|
|
22
|
+
this.item = fragment().ele("qti-graphic-associate-interaction", {
|
|
23
|
+
"response-identifier": options.responseIdentifier,
|
|
24
|
+
label: options.label,
|
|
25
|
+
"min-associations": options.minAssociations?.toString(),
|
|
26
|
+
"max-associations": options.maxAssociations?.toString(),
|
|
27
|
+
});
|
|
28
|
+
this.item.ele("object", {
|
|
29
|
+
data: options.object.data,
|
|
30
|
+
type: options.object.type,
|
|
31
|
+
width: options.object.width?.toString(),
|
|
32
|
+
height: options.object.height?.toString(),
|
|
33
|
+
});
|
|
34
|
+
for (const hotspot of options.associableHotspots || []) {
|
|
35
|
+
this.item.ele("qti-associable-hotspot", {
|
|
36
|
+
identifier: hotspot.identifier,
|
|
37
|
+
shape: hotspot.shape,
|
|
38
|
+
coords: hotspot.coords,
|
|
39
|
+
"match-max": hotspot.matchMax?.toString(),
|
|
40
|
+
"match-min": hotspot.matchMin?.toString(),
|
|
41
|
+
"match-group": hotspot.matchGroup,
|
|
42
|
+
"hotspot-label": hotspot.hotspotLabel,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=graphic-associate-interaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphic-associate-interaction.js","sourceRoot":"","sources":["../../../src/qti/interactions/graphic-associate-interaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvC,OAAO,EACL,oBAAoB,GAErB,MAAM,eAAe,CAAC;AAqBvB;;;;;;;;;;;;;;;GAeG;AACH,MAAM,OAAO,2BAA4B,SAAQ,oBAAoB;IACnE,YAAY,OAA2C;QACrD,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,IAAI,CAAC,IAAI,GAAG,QAAQ,EAAE,CAAC,GAAG,CAAC,mCAAmC,EAAE;YAC9D,qBAAqB,EAAE,OAAO,CAAC,kBAAkB;YACjD,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,kBAAkB,EAAE,OAAO,CAAC,eAAe,EAAE,QAAQ,EAAE;YACvD,kBAAkB,EAAE,OAAO,CAAC,eAAe,EAAE,QAAQ,EAAE;SACxD,CAAC,CAAC;QAEH,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE;YACtB,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI;YACzB,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI;YACzB,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE;YACvC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE;SAC1C,CAAC,CAAC;QAEH,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,kBAAkB,IAAI,EAAE,EAAE,CAAC;YACvD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,wBAAwB,EAAE;gBACtC,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,WAAW,EAAE,OAAO,CAAC,QAAQ,EAAE,QAAQ,EAAE;gBACzC,WAAW,EAAE,OAAO,CAAC,QAAQ,EAAE,QAAQ,EAAE;gBACzC,aAAa,EAAE,OAAO,CAAC,UAAU;gBACjC,eAAe,EAAE,OAAO,CAAC,YAAY;aACtC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF"}
|