@examplary/qti 0.0.1 → 1.0.1
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-manifest.js +15 -7
- package/dist/ims/ims-package.d.ts +1 -1
- package/dist/ims/ims-package.js +16 -8
- package/dist/index.d.ts +2 -0
- package/dist/index.js +23 -6
- package/dist/qti/interactions/associate-interaction.d.ts +36 -0
- package/dist/qti/interactions/associate-interaction.js +49 -0
- package/dist/qti/interactions/choice-interaction.d.ts +36 -0
- package/dist/qti/interactions/choice-interaction.js +46 -0
- package/dist/qti/interactions/drawing-interaction.d.ts +25 -0
- package/dist/qti/interactions/drawing-interaction.js +33 -0
- package/dist/qti/interactions/end-attempt-interaction.d.ts +21 -0
- package/dist/qti/interactions/end-attempt-interaction.js +30 -0
- package/dist/qti/interactions/extended-text-interaction.d.ts +28 -0
- package/dist/qti/interactions/extended-text-interaction.js +37 -0
- package/dist/qti/interactions/gap-match-interaction.d.ts +34 -0
- package/dist/qti/interactions/gap-match-interaction.js +49 -0
- package/dist/qti/interactions/graphic-associate-interaction.d.ts +37 -0
- package/dist/qti/interactions/graphic-associate-interaction.js +50 -0
- package/dist/qti/interactions/graphic-gap-match-interaction.d.ts +42 -0
- package/dist/qti/interactions/graphic-gap-match-interaction.js +67 -0
- package/dist/qti/interactions/graphic-order-interaction.d.ts +28 -0
- package/dist/qti/interactions/graphic-order-interaction.js +49 -0
- package/dist/qti/interactions/hotspot-interaction.d.ts +41 -0
- package/dist/qti/interactions/hotspot-interaction.js +49 -0
- package/dist/qti/interactions/hottext-interaction.d.ts +22 -0
- package/dist/qti/interactions/hottext-interaction.js +34 -0
- package/dist/qti/interactions/index.d.ts +63 -0
- package/dist/qti/interactions/index.js +80 -0
- package/dist/qti/interactions/inline-choice-interaction.d.ts +30 -0
- package/dist/qti/interactions/inline-choice-interaction.js +43 -0
- package/dist/qti/interactions/interaction.d.ts +20 -0
- package/dist/qti/interactions/interaction.js +31 -0
- package/dist/qti/interactions/match-interaction.d.ts +31 -0
- package/dist/qti/interactions/match-interaction.js +66 -0
- package/dist/qti/interactions/media-interaction.d.ts +31 -0
- package/dist/qti/interactions/media-interaction.js +39 -0
- package/dist/qti/interactions/order-interaction.d.ts +28 -0
- package/dist/qti/interactions/order-interaction.js +46 -0
- package/dist/qti/interactions/position-object-interaction.d.ts +36 -0
- package/dist/qti/interactions/position-object-interaction.js +46 -0
- package/dist/qti/interactions/select-point-interaction.d.ts +28 -0
- package/dist/qti/interactions/select-point-interaction.js +36 -0
- package/dist/qti/interactions/slider-interaction.d.ts +26 -0
- package/dist/qti/interactions/slider-interaction.js +35 -0
- package/dist/qti/interactions/text-entry-interaction.d.ts +25 -0
- package/dist/qti/interactions/text-entry-interaction.js +34 -0
- package/dist/qti/interactions/upload-interaction.d.ts +19 -0
- package/dist/qti/interactions/upload-interaction.js +28 -0
- package/dist/qti/qti-element.d.ts +11 -0
- package/dist/qti/qti-element.js +32 -0
- package/dist/qti/qti-item.d.ts +7 -3
- package/dist/qti/qti-item.js +38 -28
- package/dist/qti/qti-test.d.ts +5 -3
- package/dist/qti/qti-test.js +25 -11
- package/dist/qti/types.js +2 -2
- package/dist/utils/html.d.ts +2 -0
- package/dist/utils/html.js +18 -0
- package/package.json +3 -3
- package/dist/ims/ims-manifest.js.map +0 -1
- package/dist/ims/ims-package.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/qti/qti-item.js.map +0 -1
- package/dist/qti/qti-test.js.map +0 -1
- package/dist/qti/types.js.map +0 -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);
|
package/dist/ims/ims-manifest.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ImsManifest = exports.ImsManifestResourceType = void 0;
|
|
4
|
+
const xmlbuilder2_1 = require("xmlbuilder2");
|
|
5
|
+
var ImsManifestResourceType;
|
|
3
6
|
(function (ImsManifestResourceType) {
|
|
4
7
|
// QTI 3 AssessmentTest
|
|
5
8
|
ImsManifestResourceType["imsqti_test_xmlv3p0"] = "imsqti_test_xmlv3p0";
|
|
@@ -45,10 +48,15 @@ export var ImsManifestResourceType;
|
|
|
45
48
|
ImsManifestResourceType["resourceextmetadata/xml"] = "resourceextmetadata/xml";
|
|
46
49
|
// QTI 3 Usage Data (may need to pass to a CAT engine)
|
|
47
50
|
ImsManifestResourceType["qtiusagedata/xml"] = "qtiusagedata/xml";
|
|
48
|
-
})(ImsManifestResourceType || (ImsManifestResourceType = {}));
|
|
49
|
-
|
|
51
|
+
})(ImsManifestResourceType || (exports.ImsManifestResourceType = ImsManifestResourceType = {}));
|
|
52
|
+
class ImsManifest {
|
|
53
|
+
resources = new Map();
|
|
54
|
+
identifier;
|
|
55
|
+
title;
|
|
56
|
+
language;
|
|
57
|
+
toolName;
|
|
58
|
+
toolVersion;
|
|
50
59
|
constructor(options) {
|
|
51
|
-
this.resources = new Map();
|
|
52
60
|
this.identifier = options?.identifier || "manifest-" + Date.now();
|
|
53
61
|
this.title = options?.title || "QTI 3 Package";
|
|
54
62
|
this.language = options?.language || "en";
|
|
@@ -66,7 +74,7 @@ export class ImsManifest {
|
|
|
66
74
|
return Array.from(this.resources.values());
|
|
67
75
|
}
|
|
68
76
|
buildXml() {
|
|
69
|
-
const manifest = create({ version: "1.0", encoding: "UTF-8" }).ele("manifest", {
|
|
77
|
+
const manifest = (0, xmlbuilder2_1.create)({ version: "1.0", encoding: "UTF-8" }).ele("manifest", {
|
|
70
78
|
xmlns: "http://www.imsglobal.org/xsd/qti/qtiv3p0/imscp_v1p1",
|
|
71
79
|
"xmlns:lom": "http://ltsc.ieee.org/xsd/LOM",
|
|
72
80
|
"xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance",
|
|
@@ -123,4 +131,4 @@ export class ImsManifest {
|
|
|
123
131
|
return manifest.end({ prettyPrint: true });
|
|
124
132
|
}
|
|
125
133
|
}
|
|
126
|
-
|
|
134
|
+
exports.ImsManifest = ImsManifest;
|
|
@@ -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
|
@@ -1,19 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ImsPackage = void 0;
|
|
7
|
+
const jszip_1 = __importDefault(require("jszip"));
|
|
8
|
+
const ims_manifest_1 = require("./ims-manifest");
|
|
9
|
+
class ImsPackage {
|
|
10
|
+
manifest;
|
|
11
|
+
zip;
|
|
4
12
|
/**
|
|
5
13
|
* Create a new IMS Package.
|
|
6
14
|
*/
|
|
7
15
|
constructor(manifestOptions) {
|
|
8
|
-
this.manifest = new ImsManifest(manifestOptions);
|
|
9
|
-
this.zip = new
|
|
16
|
+
this.manifest = new ims_manifest_1.ImsManifest(manifestOptions);
|
|
17
|
+
this.zip = new jszip_1.default();
|
|
10
18
|
}
|
|
11
19
|
/**
|
|
12
20
|
* Add a resource to the IMS Package, along with its associated files.
|
|
13
21
|
*/
|
|
14
|
-
addResource(resource, files) {
|
|
22
|
+
async addResource(resource, files) {
|
|
15
23
|
for (const file of files) {
|
|
16
|
-
this.addFileDirectly(file);
|
|
24
|
+
await this.addFileDirectly(file);
|
|
17
25
|
}
|
|
18
26
|
this.manifest.addResource({
|
|
19
27
|
...resource,
|
|
@@ -45,4 +53,4 @@ export class ImsPackage {
|
|
|
45
53
|
return this.zip.generateAsync({ type: "arraybuffer" });
|
|
46
54
|
}
|
|
47
55
|
}
|
|
48
|
-
|
|
56
|
+
exports.ImsPackage = ImsPackage;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./ims/ims-manifest"), exports);
|
|
18
|
+
__exportStar(require("./ims/ims-package"), exports);
|
|
19
|
+
__exportStar(require("./qti/qti-element"), exports);
|
|
20
|
+
__exportStar(require("./qti/qti-test"), exports);
|
|
21
|
+
__exportStar(require("./qti/qti-item"), exports);
|
|
22
|
+
__exportStar(require("./qti/interactions"), exports);
|
|
23
|
+
__exportStar(require("./qti/types"), exports);
|
|
@@ -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,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AssociateInteraction = void 0;
|
|
4
|
+
const xmlbuilder2_1 = require("xmlbuilder2");
|
|
5
|
+
const interaction_1 = require("./interaction");
|
|
6
|
+
const html_1 = require("../../utils/html");
|
|
7
|
+
/**
|
|
8
|
+
* Presents a set of choices for candidates to pair or associate with each other.
|
|
9
|
+
* Unlike MatchInteraction, choices come from a single set and can be paired freely.
|
|
10
|
+
*
|
|
11
|
+
* @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.7cs7637r54vv
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const interaction = new AssociateInteraction({
|
|
15
|
+
* responseIdentifier: "RESPONSE",
|
|
16
|
+
* choices: [
|
|
17
|
+
* { identifier: "A", content: "Cat", matchMax: 1 },
|
|
18
|
+
* { identifier: "B", content: "Dog", matchMax: 1 },
|
|
19
|
+
* { identifier: "C", content: "Meow", matchMax: 1 },
|
|
20
|
+
* { identifier: "D", content: "Bark", matchMax: 1 },
|
|
21
|
+
* ],
|
|
22
|
+
* });
|
|
23
|
+
*/
|
|
24
|
+
class AssociateInteraction extends interaction_1.QtiPromptInteraction {
|
|
25
|
+
constructor(options) {
|
|
26
|
+
super(options);
|
|
27
|
+
this.item = (0, xmlbuilder2_1.fragment)().ele("qti-associate-interaction", {
|
|
28
|
+
"response-identifier": options.responseIdentifier,
|
|
29
|
+
label: options.label,
|
|
30
|
+
shuffle: options.shuffle ? "true" : "false",
|
|
31
|
+
"min-associations": options.minAssociations?.toString(),
|
|
32
|
+
"max-associations": options.maxAssociations?.toString(),
|
|
33
|
+
});
|
|
34
|
+
for (const choice of options.choices || []) {
|
|
35
|
+
const choiceEl = this.item.ele("qti-simple-associable-choice", {
|
|
36
|
+
identifier: choice.identifier,
|
|
37
|
+
"match-max": choice.matchMax?.toString(),
|
|
38
|
+
"match-min": choice.matchMin?.toString(),
|
|
39
|
+
"match-group": choice.matchGroup,
|
|
40
|
+
fixed: choice.fixed ? "true" : undefined,
|
|
41
|
+
"template-identifier": choice.templateIdentifier,
|
|
42
|
+
});
|
|
43
|
+
if (choice.content) {
|
|
44
|
+
(0, html_1.appendHtmlFragment)(choice.content, choiceEl);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.AssociateInteraction = AssociateInteraction;
|
|
@@ -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,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ChoiceInteraction = void 0;
|
|
4
|
+
const xmlbuilder2_1 = require("xmlbuilder2");
|
|
5
|
+
const interaction_1 = require("./interaction");
|
|
6
|
+
const html_1 = require("../../utils/html");
|
|
7
|
+
/**
|
|
8
|
+
* Presents a set of choices for candidates to select one or more options.
|
|
9
|
+
* Supports single-select (radio) or multi-select (checkbox) modes via maxChoices.
|
|
10
|
+
*
|
|
11
|
+
* @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.j9nu1oa1tu3b
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const interaction = new ChoiceInteraction({
|
|
15
|
+
* responseIdentifier: "RESPONSE",
|
|
16
|
+
* maxChoices: 1,
|
|
17
|
+
* choices: [
|
|
18
|
+
* { identifier: "A", content: "Option A" },
|
|
19
|
+
* { identifier: "B", content: "Option B" },
|
|
20
|
+
* ],
|
|
21
|
+
* });
|
|
22
|
+
*/
|
|
23
|
+
class ChoiceInteraction extends interaction_1.QtiPromptInteraction {
|
|
24
|
+
constructor(options) {
|
|
25
|
+
super(options);
|
|
26
|
+
this.item = (0, xmlbuilder2_1.fragment)().ele("qti-choice-interaction", {
|
|
27
|
+
"response-identifier": options.responseIdentifier,
|
|
28
|
+
label: options.label,
|
|
29
|
+
shuffle: options.shuffle ? "true" : "false",
|
|
30
|
+
"max-choices": options.maxChoices?.toString(),
|
|
31
|
+
"min-choices": options.minChoices?.toString(),
|
|
32
|
+
orientation: options.orientation,
|
|
33
|
+
"data-min-selections-message": options.minSelectionsMessage,
|
|
34
|
+
"data-max-selections-message": options.maxSelectionsMessage,
|
|
35
|
+
});
|
|
36
|
+
for (const choice of options.choices || []) {
|
|
37
|
+
(0, html_1.appendHtmlFragment)(choice.content || "", this.item.ele("qti-simple-choice", {
|
|
38
|
+
identifier: choice.identifier,
|
|
39
|
+
fixed: choice.fixed ? "true" : "false",
|
|
40
|
+
"template-identifier": choice.templateIdentifier,
|
|
41
|
+
label: choice.label,
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.ChoiceInteraction = ChoiceInteraction;
|
|
@@ -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,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DrawingInteraction = void 0;
|
|
4
|
+
const xmlbuilder2_1 = require("xmlbuilder2");
|
|
5
|
+
const interaction_1 = require("./interaction");
|
|
6
|
+
/**
|
|
7
|
+
* Presents a canvas where candidates can draw or annotate over a background image.
|
|
8
|
+
* Used for freeform drawing, labeling, or annotation tasks.
|
|
9
|
+
*
|
|
10
|
+
* @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.8yrkpwgsrs4b
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* const interaction = new DrawingInteraction({
|
|
14
|
+
* responseIdentifier: "RESPONSE",
|
|
15
|
+
* object: { data: "canvas.png", type: "image/png", width: 400, height: 300 },
|
|
16
|
+
* });
|
|
17
|
+
*/
|
|
18
|
+
class DrawingInteraction extends interaction_1.QtiPromptInteraction {
|
|
19
|
+
constructor(options) {
|
|
20
|
+
super(options);
|
|
21
|
+
this.item = (0, xmlbuilder2_1.fragment)().ele("qti-drawing-interaction", {
|
|
22
|
+
"response-identifier": options.responseIdentifier,
|
|
23
|
+
label: options.label,
|
|
24
|
+
});
|
|
25
|
+
this.item.ele("object", {
|
|
26
|
+
data: options.object.data,
|
|
27
|
+
type: options.object.type,
|
|
28
|
+
width: options.object.width?.toString(),
|
|
29
|
+
height: options.object.height?.toString(),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
exports.DrawingInteraction = DrawingInteraction;
|
|
@@ -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,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EndAttemptInteraction = void 0;
|
|
4
|
+
const xmlbuilder2_1 = require("xmlbuilder2");
|
|
5
|
+
const interaction_1 = require("./interaction");
|
|
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
|
+
class EndAttemptInteraction extends interaction_1.QtiInteraction {
|
|
20
|
+
constructor(options) {
|
|
21
|
+
super(options);
|
|
22
|
+
this.item = (0, xmlbuilder2_1.fragment)().ele("qti-end-attempt-interaction", {
|
|
23
|
+
"response-identifier": options.responseIdentifier,
|
|
24
|
+
label: options.label,
|
|
25
|
+
title: options.title,
|
|
26
|
+
"count-attempt": options.countAttempt ? "true" : undefined,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.EndAttemptInteraction = EndAttemptInteraction;
|
|
@@ -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,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ExtendedTextInteraction = void 0;
|
|
4
|
+
const xmlbuilder2_1 = require("xmlbuilder2");
|
|
5
|
+
const interaction_1 = require("./interaction");
|
|
6
|
+
/**
|
|
7
|
+
* Allows candidates to enter extended text responses, such as essays or paragraphs.
|
|
8
|
+
* Supports configurable length constraints, formatting options, and input validation.
|
|
9
|
+
*
|
|
10
|
+
* @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.omuxci3o5dmg
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* const interaction = new ExtendedTextInteraction({
|
|
14
|
+
* responseIdentifier: "RESPONSE",
|
|
15
|
+
* expectedLines: 10,
|
|
16
|
+
* format: "plain",
|
|
17
|
+
* });
|
|
18
|
+
*/
|
|
19
|
+
class ExtendedTextInteraction extends interaction_1.QtiPromptInteraction {
|
|
20
|
+
constructor(options) {
|
|
21
|
+
super(options);
|
|
22
|
+
this.item = (0, xmlbuilder2_1.fragment)().ele("qti-extended-text-interaction", {
|
|
23
|
+
"response-identifier": options.responseIdentifier,
|
|
24
|
+
label: options.label,
|
|
25
|
+
base: options.base?.toString(),
|
|
26
|
+
"string-identifier": options.stringIdentifier,
|
|
27
|
+
"expected-length": options.expectedLength?.toString(),
|
|
28
|
+
"pattern-mask": options.patternMask,
|
|
29
|
+
"placeholder-text": options.placeholderText,
|
|
30
|
+
"max-strings": options.maxStrings?.toString(),
|
|
31
|
+
"min-strings": options.minStrings?.toString(),
|
|
32
|
+
"expected-lines": options.expectedLines?.toString(),
|
|
33
|
+
format: options.format,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.ExtendedTextInteraction = ExtendedTextInteraction;
|
|
@@ -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,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GapMatchInteraction = void 0;
|
|
4
|
+
const xmlbuilder2_1 = require("xmlbuilder2");
|
|
5
|
+
const interaction_1 = require("./interaction");
|
|
6
|
+
const html_1 = require("../../utils/html");
|
|
7
|
+
/**
|
|
8
|
+
* Presents candidates with a set of gaps within content and a set of choices to fill them.
|
|
9
|
+
* Candidates drag or select choices to match them with the appropriate gaps.
|
|
10
|
+
*
|
|
11
|
+
* @see https://www.imsglobal.org/spec/qti/v3p0/impl#h.7sroqk3xl8e1
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const interaction = new GapMatchInteraction({
|
|
15
|
+
* responseIdentifier: "RESPONSE",
|
|
16
|
+
* gapTexts: [
|
|
17
|
+
* { identifier: "gap-1", content: "Paris" },
|
|
18
|
+
* { identifier: "gap-2", content: "London" },
|
|
19
|
+
* ],
|
|
20
|
+
* content: "<p>The capital of France is <qti-gap identifier='G1'/>.</p>",
|
|
21
|
+
* });
|
|
22
|
+
*/
|
|
23
|
+
class GapMatchInteraction extends interaction_1.QtiPromptInteraction {
|
|
24
|
+
constructor(options) {
|
|
25
|
+
super(options);
|
|
26
|
+
this.item = (0, xmlbuilder2_1.fragment)().ele("qti-gap-match-interaction", {
|
|
27
|
+
"response-identifier": options.responseIdentifier,
|
|
28
|
+
label: options.label,
|
|
29
|
+
shuffle: options.shuffle ? "true" : "false",
|
|
30
|
+
"min-associations": options.minAssociations?.toString(),
|
|
31
|
+
"max-associations": options.maxAssociations?.toString(),
|
|
32
|
+
});
|
|
33
|
+
for (const gapText of options.gapTexts || []) {
|
|
34
|
+
const gapTextEl = this.item.ele("qti-gap-text", {
|
|
35
|
+
identifier: gapText.identifier,
|
|
36
|
+
"match-max": gapText.matchMax?.toString(),
|
|
37
|
+
"match-min": gapText.matchMin?.toString(),
|
|
38
|
+
"match-group": gapText.matchGroup,
|
|
39
|
+
});
|
|
40
|
+
if (gapText.content) {
|
|
41
|
+
(0, html_1.appendHtmlFragment)(gapText.content, gapTextEl);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (options.content) {
|
|
45
|
+
(0, html_1.appendHtmlFragment)(options.content, this.item);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
exports.GapMatchInteraction = GapMatchInteraction;
|
|
@@ -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
|
+
}
|