@intellectif/lk-core 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/activity-D5tqgx8A.d.cts +330 -0
- package/dist/activity-D5tqgx8A.d.ts +330 -0
- package/dist/chunk-2T3IL7VL.js +147 -0
- package/dist/chunk-2T3IL7VL.js.map +1 -0
- package/dist/chunk-3JMLUUFS.cjs +124 -0
- package/dist/chunk-3JMLUUFS.cjs.map +1 -0
- package/dist/chunk-6VOCV4EX.js +25 -0
- package/dist/chunk-6VOCV4EX.js.map +1 -0
- package/dist/chunk-DCDOTQNH.cjs +147 -0
- package/dist/chunk-DCDOTQNH.cjs.map +1 -0
- package/dist/chunk-DV466SBJ.cjs +25 -0
- package/dist/chunk-DV466SBJ.cjs.map +1 -0
- package/dist/chunk-GZ73G2TS.js +124 -0
- package/dist/chunk-GZ73G2TS.js.map +1 -0
- package/dist/chunk-PJFDAP54.cjs +188 -0
- package/dist/chunk-PJFDAP54.cjs.map +1 -0
- package/dist/chunk-ZHOX6TO4.js +188 -0
- package/dist/chunk-ZHOX6TO4.js.map +1 -0
- package/dist/index.cjs +45 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +56 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas.cjs +23 -0
- package/dist/schemas.cjs.map +1 -0
- package/dist/schemas.d.cts +179 -0
- package/dist/schemas.d.ts +179 -0
- package/dist/schemas.js +23 -0
- package/dist/schemas.js.map +1 -0
- package/dist/scoring.cjs +10 -0
- package/dist/scoring.cjs.map +1 -0
- package/dist/scoring.d.cts +20 -0
- package/dist/scoring.d.ts +20 -0
- package/dist/scoring.js +10 -0
- package/dist/scoring.js.map +1 -0
- package/dist/xapi.cjs +14 -0
- package/dist/xapi.cjs.map +1 -0
- package/dist/xapi.d.cts +88 -0
- package/dist/xapi.d.ts +88 -0
- package/dist/xapi.js +14 -0
- package/dist/xapi.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
// src/schemas/fill-in-the-blanks.ts
|
|
2
|
+
import { z as z3 } from "zod/v4";
|
|
3
|
+
|
|
4
|
+
// src/schemas/feedback.ts
|
|
5
|
+
import { z } from "zod/v4";
|
|
6
|
+
var FeedbackSchema = z.object({
|
|
7
|
+
correct: z.string().min(1).optional(),
|
|
8
|
+
incorrect: z.string().min(1).optional()
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
// src/schemas/media.ts
|
|
12
|
+
import { z as z2 } from "zod/v4";
|
|
13
|
+
var MediaSchema = z2.object({
|
|
14
|
+
type: z2.enum(["image", "audio", "video", "embed"]),
|
|
15
|
+
url: z2.url(),
|
|
16
|
+
alt: z2.string().min(1).optional(),
|
|
17
|
+
captionsUrl: z2.url().optional()
|
|
18
|
+
}).refine(
|
|
19
|
+
(m) => m.type !== "image" && m.type !== "embed" || typeof m.alt === "string" && m.alt.length > 0,
|
|
20
|
+
{
|
|
21
|
+
error: "image and embed media require non-empty alt text (WCAG 1.1.1 / 4.1.2).",
|
|
22
|
+
path: ["alt"]
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
// src/schemas/fill-in-the-blanks.ts
|
|
27
|
+
var PLACEHOLDER_RE = /\{\{\s*([^{}]+?)\s*\}\}/g;
|
|
28
|
+
var BlankConfigSchema = z3.object({
|
|
29
|
+
id: z3.string().min(1),
|
|
30
|
+
acceptedAnswers: z3.array(z3.string().min(1)).min(1),
|
|
31
|
+
caseSensitive: z3.boolean().optional(),
|
|
32
|
+
trimWhitespace: z3.boolean().optional(),
|
|
33
|
+
hint: z3.string().optional(),
|
|
34
|
+
feedback: z3.string().optional()
|
|
35
|
+
});
|
|
36
|
+
var FillInTheBlanksDataSchema = z3.object({
|
|
37
|
+
schemaVersion: z3.literal("1.0"),
|
|
38
|
+
type: z3.literal("fill-in-the-blanks"),
|
|
39
|
+
id: z3.string().min(1),
|
|
40
|
+
title: z3.string().min(1),
|
|
41
|
+
passage: z3.string().min(1),
|
|
42
|
+
blanks: z3.array(BlankConfigSchema).min(1),
|
|
43
|
+
scoringStrategy: z3.enum(["all-or-nothing", "partial"]),
|
|
44
|
+
media: MediaSchema.optional(),
|
|
45
|
+
feedback: FeedbackSchema.optional(),
|
|
46
|
+
passThreshold: z3.number().min(0).max(1).optional(),
|
|
47
|
+
locale: z3.string().optional(),
|
|
48
|
+
learningObjectives: z3.array(z3.string()).optional(),
|
|
49
|
+
difficultyLevel: z3.literal([1, 2, 3, 4, 5]).optional()
|
|
50
|
+
}).refine(
|
|
51
|
+
(data) => {
|
|
52
|
+
const placeholderIds = new Set(
|
|
53
|
+
[...data.passage.matchAll(PLACEHOLDER_RE)].map((match) => match[1])
|
|
54
|
+
);
|
|
55
|
+
const blankIds = new Set(data.blanks.map((blank) => blank.id));
|
|
56
|
+
if (placeholderIds.size !== blankIds.size) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
for (const id of blankIds) {
|
|
60
|
+
if (!placeholderIds.has(id)) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return true;
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
error: "Each blank id must have exactly one matching {{id}} placeholder in the passage, and vice versa.",
|
|
68
|
+
path: ["passage"]
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
// src/schemas/multiple-choice.ts
|
|
73
|
+
import { z as z4 } from "zod/v4";
|
|
74
|
+
var MultipleChoiceOptionSchema = z4.object({
|
|
75
|
+
id: z4.string().min(1),
|
|
76
|
+
text: z4.string().min(1),
|
|
77
|
+
isCorrect: z4.boolean(),
|
|
78
|
+
feedback: z4.string().optional()
|
|
79
|
+
});
|
|
80
|
+
var MultipleChoiceDataSchema = z4.object({
|
|
81
|
+
schemaVersion: z4.literal("1.0"),
|
|
82
|
+
type: z4.literal("multiple-choice"),
|
|
83
|
+
id: z4.string().min(1),
|
|
84
|
+
title: z4.string().min(1),
|
|
85
|
+
question: z4.string().min(1),
|
|
86
|
+
mode: z4.enum(["single", "multi"]),
|
|
87
|
+
options: z4.array(MultipleChoiceOptionSchema).min(2).max(10),
|
|
88
|
+
scoringStrategy: z4.enum(["all-or-nothing", "partial"]),
|
|
89
|
+
media: MediaSchema.optional(),
|
|
90
|
+
feedback: FeedbackSchema.optional(),
|
|
91
|
+
passThreshold: z4.number().min(0).max(1).optional(),
|
|
92
|
+
shuffle: z4.boolean().optional(),
|
|
93
|
+
locale: z4.string().optional(),
|
|
94
|
+
learningObjectives: z4.array(z4.string()).optional(),
|
|
95
|
+
difficultyLevel: z4.literal([1, 2, 3, 4, 5]).optional()
|
|
96
|
+
}).refine((data) => data.options.some((option) => option.isCorrect), {
|
|
97
|
+
error: "At least one option must be marked correct.",
|
|
98
|
+
path: ["options"]
|
|
99
|
+
}).refine(
|
|
100
|
+
(data) => data.mode !== "single" || data.options.filter((option) => option.isCorrect).length === 1,
|
|
101
|
+
{
|
|
102
|
+
error: 'Single-select activities (mode: "single") must have exactly one correct option.',
|
|
103
|
+
path: ["options"]
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
// src/schemas/json-schema.ts
|
|
108
|
+
import { z as z5 } from "zod/v4";
|
|
109
|
+
var multipleChoiceJsonSchema = z5.toJSONSchema(MultipleChoiceDataSchema, {
|
|
110
|
+
target: "draft-7"
|
|
111
|
+
});
|
|
112
|
+
var fillInTheBlanksJsonSchema = z5.toJSONSchema(FillInTheBlanksDataSchema, {
|
|
113
|
+
target: "draft-7"
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// src/schemas/index.ts
|
|
117
|
+
var schemaMap = {
|
|
118
|
+
"multiple-choice": MultipleChoiceDataSchema,
|
|
119
|
+
"fill-in-the-blanks": FillInTheBlanksDataSchema
|
|
120
|
+
};
|
|
121
|
+
function validateActivity(type, data) {
|
|
122
|
+
const result = schemaMap[type].safeParse(data);
|
|
123
|
+
if (result.success) {
|
|
124
|
+
return { success: true, data: result.data };
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
success: false,
|
|
128
|
+
errors: result.error.issues.map((issue) => ({
|
|
129
|
+
path: issue.path.map(String),
|
|
130
|
+
message: issue.message,
|
|
131
|
+
code: issue.code
|
|
132
|
+
}))
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export {
|
|
137
|
+
FeedbackSchema,
|
|
138
|
+
MediaSchema,
|
|
139
|
+
BlankConfigSchema,
|
|
140
|
+
FillInTheBlanksDataSchema,
|
|
141
|
+
MultipleChoiceOptionSchema,
|
|
142
|
+
MultipleChoiceDataSchema,
|
|
143
|
+
multipleChoiceJsonSchema,
|
|
144
|
+
fillInTheBlanksJsonSchema,
|
|
145
|
+
validateActivity
|
|
146
|
+
};
|
|
147
|
+
//# sourceMappingURL=chunk-2T3IL7VL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/schemas/fill-in-the-blanks.ts","../src/schemas/feedback.ts","../src/schemas/media.ts","../src/schemas/multiple-choice.ts","../src/schemas/json-schema.ts","../src/schemas/index.ts"],"sourcesContent":["import { z } from 'zod/v4';\nimport { FeedbackSchema } from './feedback.js';\nimport { MediaSchema } from './media.js';\n\n/** Matches `{{ blank_id }}` placeholders in a passage, capturing the trimmed id. */\nconst PLACEHOLDER_RE = /\\{\\{\\s*([^{}]+?)\\s*\\}\\}/g;\n\n/** Zod schema for a single fill-in-the-blank slot configuration. */\nexport const BlankConfigSchema = z.object({\n id: z.string().min(1),\n acceptedAnswers: z.array(z.string().min(1)).min(1),\n caseSensitive: z.boolean().optional(),\n trimWhitespace: z.boolean().optional(),\n hint: z.string().optional(),\n feedback: z.string().optional(),\n});\n\n/**\n * Zod schema validating the full Fill-in-the-Blanks activity data contract.\n *\n * The refinement enforces a bijection between `{{id}}` placeholders in the\n * passage and `blanks[].id`; otherwise a blank could never be rendered, or a\n * placeholder could have no scoring config, yielding undefined behaviour.\n */\nexport const FillInTheBlanksDataSchema = z\n .object({\n schemaVersion: z.literal('1.0'),\n type: z.literal('fill-in-the-blanks'),\n id: z.string().min(1),\n title: z.string().min(1),\n passage: z.string().min(1),\n blanks: z.array(BlankConfigSchema).min(1),\n scoringStrategy: z.enum(['all-or-nothing', 'partial']),\n media: MediaSchema.optional(),\n feedback: FeedbackSchema.optional(),\n passThreshold: z.number().min(0).max(1).optional(),\n locale: z.string().optional(),\n learningObjectives: z.array(z.string()).optional(),\n difficultyLevel: z.literal([1, 2, 3, 4, 5]).optional(),\n })\n .refine(\n (data) => {\n const placeholderIds = new Set(\n [...data.passage.matchAll(PLACEHOLDER_RE)].map((match) => match[1]),\n );\n const blankIds = new Set(data.blanks.map((blank) => blank.id));\n if (placeholderIds.size !== blankIds.size) {\n return false;\n }\n for (const id of blankIds) {\n if (!placeholderIds.has(id)) {\n return false;\n }\n }\n return true;\n },\n {\n error:\n 'Each blank id must have exactly one matching {{id}} placeholder in the passage, and vice versa.',\n path: ['passage'],\n },\n );\n","import { z } from 'zod/v4';\n\n/**\n * Optional authored \"overall feedback\" shown after submission, selected by\n * whether the learner passed (h5p-style overall feedback). Both fields are\n * optional; non-empty when present.\n */\nexport const FeedbackSchema = z.object({\n correct: z.string().min(1).optional(),\n incorrect: z.string().min(1).optional(),\n});\n","import { z } from 'zod/v4';\n\n/**\n * Optional media attached to an activity, rendered above the question or\n * passage — e.g. a recording to listen to, or an embedded video to watch\n * before answering. URL-only by design: hosting/delivery (S3/CDN, or the\n * provider's own embed for `embed`) is the consuming app's responsibility\n * (see requirements \"Non-Goals and Shared Responsibility\").\n *\n * - `image`: rendered as `<img>` — `alt` is REQUIRED (WCAG 1.1.1 / Req 14.5).\n * - `audio` / `video`: rendered with native controls; `alt` is an optional\n * accessible label; `captionsUrl` points at a WebVTT `<track>`. `url` must\n * be a direct media file (NOT a YouTube/Vimeo page — use `embed` for those).\n * - `embed`: rendered as a sandboxed `<iframe>` for provider players\n * (YouTube/Vimeo/etc.). `url` MUST be the provider's *embeddable* URL\n * (e.g. `https://www.youtube.com/embed/<id>`). `alt` is REQUIRED and used\n * as the iframe's accessible `title` (WCAG 4.1.2 / 2.4.1).\n */\nexport const MediaSchema = z\n .object({\n type: z.enum(['image', 'audio', 'video', 'embed']),\n url: z.url(),\n alt: z.string().min(1).optional(),\n captionsUrl: z.url().optional(),\n })\n .refine(\n (m) =>\n (m.type !== 'image' && m.type !== 'embed') || (typeof m.alt === 'string' && m.alt.length > 0),\n {\n error: 'image and embed media require non-empty alt text (WCAG 1.1.1 / 4.1.2).',\n path: ['alt'],\n },\n );\n","import { z } from 'zod/v4';\nimport { FeedbackSchema } from './feedback.js';\nimport { MediaSchema } from './media.js';\n\n/** Zod schema for a single Multiple Choice option. */\nexport const MultipleChoiceOptionSchema = z.object({\n id: z.string().min(1),\n text: z.string().min(1),\n isCorrect: z.boolean(),\n feedback: z.string().optional(),\n});\n\n/**\n * Zod schema validating the full Multiple Choice activity data contract.\n *\n * Two semantic guards: (1) at least one option must be correct, otherwise the\n * activity can never be answered correctly; (2) `mode: 'single'` must have\n * exactly one correct option — multiple correct options under single-select\n * make `showCorrectAnswers` and the xAPI correct-response ambiguous and mask\n * authoring errors. Both are unrepresentable in JSON Schema and are dropped\n * from `toJSONSchema` output by design.\n */\nexport const MultipleChoiceDataSchema = z\n .object({\n schemaVersion: z.literal('1.0'),\n type: z.literal('multiple-choice'),\n id: z.string().min(1),\n title: z.string().min(1),\n question: z.string().min(1),\n mode: z.enum(['single', 'multi']),\n options: z.array(MultipleChoiceOptionSchema).min(2).max(10),\n scoringStrategy: z.enum(['all-or-nothing', 'partial']),\n media: MediaSchema.optional(),\n feedback: FeedbackSchema.optional(),\n passThreshold: z.number().min(0).max(1).optional(),\n shuffle: z.boolean().optional(),\n locale: z.string().optional(),\n learningObjectives: z.array(z.string()).optional(),\n difficultyLevel: z.literal([1, 2, 3, 4, 5]).optional(),\n })\n .refine((data) => data.options.some((option) => option.isCorrect), {\n error: 'At least one option must be marked correct.',\n path: ['options'],\n })\n .refine(\n (data) =>\n data.mode !== 'single' || data.options.filter((option) => option.isCorrect).length === 1,\n {\n error: 'Single-select activities (mode: \"single\") must have exactly one correct option.',\n path: ['options'],\n },\n );\n","import { z } from 'zod/v4';\nimport { FillInTheBlanksDataSchema } from './fill-in-the-blanks.js';\nimport { MultipleChoiceDataSchema } from './multiple-choice.js';\n\n/**\n * JSON Schema (Draft 7) representation of the Multiple Choice activity data\n * contract, generated natively by Zod 4. Draft 7 is mandated by Requirement\n * 2.2 for the widest AI-prompt / OpenAPI tooling compatibility. The semantic\n * `.refine()` guards are not representable in JSON Schema and are\n * intentionally omitted — the export captures the *structural* contract only.\n */\nexport const multipleChoiceJsonSchema = z.toJSONSchema(MultipleChoiceDataSchema, {\n target: 'draft-7',\n});\n\n/**\n * JSON Schema (Draft 7) representation of the Fill-in-the-Blanks activity data\n * contract, generated natively by Zod 4. Structural contract only (semantic\n * `.refine()` guards are Zod-only and not representable in JSON Schema).\n */\nexport const fillInTheBlanksJsonSchema = z.toJSONSchema(FillInTheBlanksDataSchema, {\n target: 'draft-7',\n});\n","import type { ActivityDataMap, ActivityType, ValidationResult } from '../types/activity.js';\nimport { FillInTheBlanksDataSchema } from './fill-in-the-blanks.js';\nimport { MultipleChoiceDataSchema } from './multiple-choice.js';\n\nexport { FeedbackSchema } from './feedback.js';\nexport { BlankConfigSchema, FillInTheBlanksDataSchema } from './fill-in-the-blanks.js';\nexport { fillInTheBlanksJsonSchema, multipleChoiceJsonSchema } from './json-schema.js';\nexport { MediaSchema } from './media.js';\nexport { MultipleChoiceDataSchema, MultipleChoiceOptionSchema } from './multiple-choice.js';\n\n/** Maps each activity type to the Zod schema that validates its data. */\nconst schemaMap = {\n 'multiple-choice': MultipleChoiceDataSchema,\n 'fill-in-the-blanks': FillInTheBlanksDataSchema,\n} as const;\n\n/**\n * Validates raw activity data against the schema for the given activity type.\n *\n * @returns `{ success: true, data }` with the typed, validated data, or\n * `{ success: false, errors }` with one entry per failed constraint.\n */\nexport function validateActivity<T extends ActivityType>(\n type: T,\n data: unknown,\n): ValidationResult<ActivityDataMap[T]> {\n const result = schemaMap[type].safeParse(data);\n\n if (result.success) {\n return { success: true, data: result.data as ActivityDataMap[T] };\n }\n\n return {\n success: false,\n errors: result.error.issues.map((issue) => ({\n path: issue.path.map(String),\n message: issue.message,\n code: issue.code,\n })),\n };\n}\n"],"mappings":"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","names":["z","z","z","z","z","z","z"]}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
|
+
|
|
3
|
+
var _chunkDV466SBJcjs = require('./chunk-DV466SBJ.cjs');
|
|
4
|
+
|
|
5
|
+
// src/scoring/strategies/all-or-nothing.ts
|
|
6
|
+
function allOrNothingStrategy(correctItems) {
|
|
7
|
+
return correctItems.every((isCorrect) => isCorrect) ? 1 : 0;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// src/scoring/strategies/partial.ts
|
|
11
|
+
function partialStrategy(correctSelected, incorrectSelected, totalCorrect, totalIncorrect) {
|
|
12
|
+
const reward = correctSelected / totalCorrect;
|
|
13
|
+
const penalty = totalIncorrect === 0 ? 0 : incorrectSelected / totalIncorrect;
|
|
14
|
+
return Math.max(0, reward - penalty);
|
|
15
|
+
}
|
|
16
|
+
function partialBlankStrategy(correctBlanks, totalBlanks) {
|
|
17
|
+
return correctBlanks / totalBlanks;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// src/scoring/activity-scorers/fill-in-the-blanks.ts
|
|
21
|
+
function normalize(value, blank) {
|
|
22
|
+
let result = value;
|
|
23
|
+
if (blank.trimWhitespace !== false) {
|
|
24
|
+
result = result.trim();
|
|
25
|
+
}
|
|
26
|
+
if (blank.caseSensitive !== true) {
|
|
27
|
+
result = result.toLowerCase();
|
|
28
|
+
}
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
function scoreFillInTheBlanks(data, response) {
|
|
32
|
+
const details = [];
|
|
33
|
+
const perBlankCorrect = [];
|
|
34
|
+
for (const blank of data.blanks) {
|
|
35
|
+
const rawInput = response.answers[blank.id];
|
|
36
|
+
const input = typeof rawInput === "string" ? rawInput : "";
|
|
37
|
+
const normalizedInput = normalize(input, blank);
|
|
38
|
+
const matched = blank.acceptedAnswers.some(
|
|
39
|
+
(accepted) => normalize(accepted, blank) === normalizedInput
|
|
40
|
+
);
|
|
41
|
+
perBlankCorrect.push(matched);
|
|
42
|
+
details.push({
|
|
43
|
+
itemId: blank.id,
|
|
44
|
+
correct: matched,
|
|
45
|
+
learnerResponse: [input],
|
|
46
|
+
correctResponse: [...blank.acceptedAnswers]
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
const correctBlanks = perBlankCorrect.filter(Boolean).length;
|
|
50
|
+
const scoreValue = data.scoringStrategy === "all-or-nothing" ? allOrNothingStrategy(perBlankCorrect) : partialBlankStrategy(correctBlanks, data.blanks.length);
|
|
51
|
+
return { score: scoreValue, maxScore: 1, feedback: null, details };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// src/scoring/activity-scorers/multiple-choice.ts
|
|
55
|
+
function scoreMultipleChoice(data, response) {
|
|
56
|
+
const optionById = new Map(data.options.map((option) => [option.id, option]));
|
|
57
|
+
const selected = new Set(response.selectedOptionIds);
|
|
58
|
+
const totalCorrect = data.options.filter((option) => option.isCorrect).length;
|
|
59
|
+
const totalIncorrect = data.options.length - totalCorrect;
|
|
60
|
+
let scoreValue;
|
|
61
|
+
if (data.scoringStrategy === "all-or-nothing") {
|
|
62
|
+
if (data.mode === "single") {
|
|
63
|
+
scoreValue = response.selectedOptionIds.length === 1 && _optionalChain([optionById, 'access', _ => _.get, 'call', _2 => _2(response.selectedOptionIds[0]), 'optionalAccess', _3 => _3.isCorrect]) === true ? 1 : 0;
|
|
64
|
+
} else {
|
|
65
|
+
const correctIds = data.options.filter((o) => o.isCorrect).map((o) => o.id);
|
|
66
|
+
const allCorrectSelected = correctIds.every((id) => selected.has(id));
|
|
67
|
+
scoreValue = selected.size === correctIds.length && allCorrectSelected ? 1 : 0;
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
let correctSelected = 0;
|
|
71
|
+
let incorrectSelected = 0;
|
|
72
|
+
for (const id of selected) {
|
|
73
|
+
const option = optionById.get(id);
|
|
74
|
+
if (_optionalChain([option, 'optionalAccess', _4 => _4.isCorrect])) {
|
|
75
|
+
correctSelected += 1;
|
|
76
|
+
} else {
|
|
77
|
+
incorrectSelected += 1;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
scoreValue = partialStrategy(correctSelected, incorrectSelected, totalCorrect, totalIncorrect);
|
|
81
|
+
}
|
|
82
|
+
const details = data.options.map((option) => {
|
|
83
|
+
const wasSelected = selected.has(option.id);
|
|
84
|
+
return {
|
|
85
|
+
itemId: option.id,
|
|
86
|
+
correct: wasSelected === option.isCorrect,
|
|
87
|
+
learnerResponse: [wasSelected ? "selected" : "not-selected"],
|
|
88
|
+
correctResponse: [option.isCorrect ? "selected" : "not-selected"]
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
return { score: scoreValue, maxScore: 1, feedback: null, details };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// src/scoring/index.ts
|
|
95
|
+
var DEFAULT_PASS_THRESHOLD = 0.7;
|
|
96
|
+
function computePassThreshold(activityData, score2) {
|
|
97
|
+
return score2 >= (_nullishCoalesce(activityData.passThreshold, () => ( DEFAULT_PASS_THRESHOLD)));
|
|
98
|
+
}
|
|
99
|
+
function score(activityType, activityData, learnerResponse) {
|
|
100
|
+
let result;
|
|
101
|
+
switch (activityType) {
|
|
102
|
+
case "multiple-choice":
|
|
103
|
+
result = scoreMultipleChoice(
|
|
104
|
+
activityData,
|
|
105
|
+
learnerResponse
|
|
106
|
+
);
|
|
107
|
+
break;
|
|
108
|
+
case "fill-in-the-blanks":
|
|
109
|
+
result = scoreFillInTheBlanks(
|
|
110
|
+
activityData,
|
|
111
|
+
learnerResponse
|
|
112
|
+
);
|
|
113
|
+
break;
|
|
114
|
+
default:
|
|
115
|
+
throw new (0, _chunkDV466SBJcjs.UnknownActivityTypeError)(String(activityType));
|
|
116
|
+
}
|
|
117
|
+
return { ...result, passed: computePassThreshold(activityData, result.score) };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
exports.computePassThreshold = computePassThreshold; exports.score = score;
|
|
124
|
+
//# sourceMappingURL=chunk-3JMLUUFS.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["c:\\Users\\onecu\\Documents\\Intellectif\\IT-for-Intellectif\\learning-kit\\packages\\lk-core\\dist\\chunk-3JMLUUFS.cjs"],"names":[],"mappings":"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","file":"C:\\Users\\onecu\\Documents\\Intellectif\\IT-for-Intellectif\\learning-kit\\packages\\lk-core\\dist\\chunk-3JMLUUFS.cjs","sourcesContent":[null]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
var ActivitySchemaError = class extends Error {
|
|
3
|
+
constructor(activityType, errors) {
|
|
4
|
+
super(`Invalid activity data for type "${activityType}"`);
|
|
5
|
+
this.activityType = activityType;
|
|
6
|
+
this.errors = errors;
|
|
7
|
+
this.name = "ActivitySchemaError";
|
|
8
|
+
}
|
|
9
|
+
activityType;
|
|
10
|
+
errors;
|
|
11
|
+
};
|
|
12
|
+
var UnknownActivityTypeError = class extends Error {
|
|
13
|
+
constructor(activityType) {
|
|
14
|
+
super(`Activity type "${activityType}" is not registered`);
|
|
15
|
+
this.activityType = activityType;
|
|
16
|
+
this.name = "UnknownActivityTypeError";
|
|
17
|
+
}
|
|
18
|
+
activityType;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export {
|
|
22
|
+
ActivitySchemaError,
|
|
23
|
+
UnknownActivityTypeError
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=chunk-6VOCV4EX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts"],"sourcesContent":["import type { ValidationError } from './types/activity.js';\n\n/** Thrown when activity data fails schema validation at a component boundary. */\nexport class ActivitySchemaError extends Error {\n constructor(\n public readonly activityType: string,\n public readonly errors: ValidationError[],\n ) {\n super(`Invalid activity data for type \"${activityType}\"`);\n this.name = 'ActivitySchemaError';\n }\n}\n\n/** Thrown when an unrecognised activity type is passed to the scoring engine. */\nexport class UnknownActivityTypeError extends Error {\n constructor(public readonly activityType: string) {\n super(`Activity type \"${activityType}\" is not registered`);\n this.name = 'UnknownActivityTypeError';\n }\n}\n"],"mappings":";AAGO,IAAM,sBAAN,cAAkC,MAAM;AAAA,EAC7C,YACkB,cACA,QAChB;AACA,UAAM,mCAAmC,YAAY,GAAG;AAHxC;AACA;AAGhB,SAAK,OAAO;AAAA,EACd;AAAA,EALkB;AAAA,EACA;AAKpB;AAGO,IAAM,2BAAN,cAAuC,MAAM;AAAA,EAClD,YAA4B,cAAsB;AAChD,UAAM,kBAAkB,YAAY,qBAAqB;AAD/B;AAE1B,SAAK,OAAO;AAAA,EACd;AAAA,EAH4B;AAI9B;","names":[]}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/schemas/fill-in-the-blanks.ts
|
|
2
|
+
var _v4 = require('zod/v4');
|
|
3
|
+
|
|
4
|
+
// src/schemas/feedback.ts
|
|
5
|
+
|
|
6
|
+
var FeedbackSchema = _v4.z.object({
|
|
7
|
+
correct: _v4.z.string().min(1).optional(),
|
|
8
|
+
incorrect: _v4.z.string().min(1).optional()
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
// src/schemas/media.ts
|
|
12
|
+
|
|
13
|
+
var MediaSchema = _v4.z.object({
|
|
14
|
+
type: _v4.z.enum(["image", "audio", "video", "embed"]),
|
|
15
|
+
url: _v4.z.url(),
|
|
16
|
+
alt: _v4.z.string().min(1).optional(),
|
|
17
|
+
captionsUrl: _v4.z.url().optional()
|
|
18
|
+
}).refine(
|
|
19
|
+
(m) => m.type !== "image" && m.type !== "embed" || typeof m.alt === "string" && m.alt.length > 0,
|
|
20
|
+
{
|
|
21
|
+
error: "image and embed media require non-empty alt text (WCAG 1.1.1 / 4.1.2).",
|
|
22
|
+
path: ["alt"]
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
// src/schemas/fill-in-the-blanks.ts
|
|
27
|
+
var PLACEHOLDER_RE = /\{\{\s*([^{}]+?)\s*\}\}/g;
|
|
28
|
+
var BlankConfigSchema = _v4.z.object({
|
|
29
|
+
id: _v4.z.string().min(1),
|
|
30
|
+
acceptedAnswers: _v4.z.array(_v4.z.string().min(1)).min(1),
|
|
31
|
+
caseSensitive: _v4.z.boolean().optional(),
|
|
32
|
+
trimWhitespace: _v4.z.boolean().optional(),
|
|
33
|
+
hint: _v4.z.string().optional(),
|
|
34
|
+
feedback: _v4.z.string().optional()
|
|
35
|
+
});
|
|
36
|
+
var FillInTheBlanksDataSchema = _v4.z.object({
|
|
37
|
+
schemaVersion: _v4.z.literal("1.0"),
|
|
38
|
+
type: _v4.z.literal("fill-in-the-blanks"),
|
|
39
|
+
id: _v4.z.string().min(1),
|
|
40
|
+
title: _v4.z.string().min(1),
|
|
41
|
+
passage: _v4.z.string().min(1),
|
|
42
|
+
blanks: _v4.z.array(BlankConfigSchema).min(1),
|
|
43
|
+
scoringStrategy: _v4.z.enum(["all-or-nothing", "partial"]),
|
|
44
|
+
media: MediaSchema.optional(),
|
|
45
|
+
feedback: FeedbackSchema.optional(),
|
|
46
|
+
passThreshold: _v4.z.number().min(0).max(1).optional(),
|
|
47
|
+
locale: _v4.z.string().optional(),
|
|
48
|
+
learningObjectives: _v4.z.array(_v4.z.string()).optional(),
|
|
49
|
+
difficultyLevel: _v4.z.literal([1, 2, 3, 4, 5]).optional()
|
|
50
|
+
}).refine(
|
|
51
|
+
(data) => {
|
|
52
|
+
const placeholderIds = new Set(
|
|
53
|
+
[...data.passage.matchAll(PLACEHOLDER_RE)].map((match) => match[1])
|
|
54
|
+
);
|
|
55
|
+
const blankIds = new Set(data.blanks.map((blank) => blank.id));
|
|
56
|
+
if (placeholderIds.size !== blankIds.size) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
for (const id of blankIds) {
|
|
60
|
+
if (!placeholderIds.has(id)) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return true;
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
error: "Each blank id must have exactly one matching {{id}} placeholder in the passage, and vice versa.",
|
|
68
|
+
path: ["passage"]
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
// src/schemas/multiple-choice.ts
|
|
73
|
+
|
|
74
|
+
var MultipleChoiceOptionSchema = _v4.z.object({
|
|
75
|
+
id: _v4.z.string().min(1),
|
|
76
|
+
text: _v4.z.string().min(1),
|
|
77
|
+
isCorrect: _v4.z.boolean(),
|
|
78
|
+
feedback: _v4.z.string().optional()
|
|
79
|
+
});
|
|
80
|
+
var MultipleChoiceDataSchema = _v4.z.object({
|
|
81
|
+
schemaVersion: _v4.z.literal("1.0"),
|
|
82
|
+
type: _v4.z.literal("multiple-choice"),
|
|
83
|
+
id: _v4.z.string().min(1),
|
|
84
|
+
title: _v4.z.string().min(1),
|
|
85
|
+
question: _v4.z.string().min(1),
|
|
86
|
+
mode: _v4.z.enum(["single", "multi"]),
|
|
87
|
+
options: _v4.z.array(MultipleChoiceOptionSchema).min(2).max(10),
|
|
88
|
+
scoringStrategy: _v4.z.enum(["all-or-nothing", "partial"]),
|
|
89
|
+
media: MediaSchema.optional(),
|
|
90
|
+
feedback: FeedbackSchema.optional(),
|
|
91
|
+
passThreshold: _v4.z.number().min(0).max(1).optional(),
|
|
92
|
+
shuffle: _v4.z.boolean().optional(),
|
|
93
|
+
locale: _v4.z.string().optional(),
|
|
94
|
+
learningObjectives: _v4.z.array(_v4.z.string()).optional(),
|
|
95
|
+
difficultyLevel: _v4.z.literal([1, 2, 3, 4, 5]).optional()
|
|
96
|
+
}).refine((data) => data.options.some((option) => option.isCorrect), {
|
|
97
|
+
error: "At least one option must be marked correct.",
|
|
98
|
+
path: ["options"]
|
|
99
|
+
}).refine(
|
|
100
|
+
(data) => data.mode !== "single" || data.options.filter((option) => option.isCorrect).length === 1,
|
|
101
|
+
{
|
|
102
|
+
error: 'Single-select activities (mode: "single") must have exactly one correct option.',
|
|
103
|
+
path: ["options"]
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
// src/schemas/json-schema.ts
|
|
108
|
+
|
|
109
|
+
var multipleChoiceJsonSchema = _v4.z.toJSONSchema(MultipleChoiceDataSchema, {
|
|
110
|
+
target: "draft-7"
|
|
111
|
+
});
|
|
112
|
+
var fillInTheBlanksJsonSchema = _v4.z.toJSONSchema(FillInTheBlanksDataSchema, {
|
|
113
|
+
target: "draft-7"
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// src/schemas/index.ts
|
|
117
|
+
var schemaMap = {
|
|
118
|
+
"multiple-choice": MultipleChoiceDataSchema,
|
|
119
|
+
"fill-in-the-blanks": FillInTheBlanksDataSchema
|
|
120
|
+
};
|
|
121
|
+
function validateActivity(type, data) {
|
|
122
|
+
const result = schemaMap[type].safeParse(data);
|
|
123
|
+
if (result.success) {
|
|
124
|
+
return { success: true, data: result.data };
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
success: false,
|
|
128
|
+
errors: result.error.issues.map((issue) => ({
|
|
129
|
+
path: issue.path.map(String),
|
|
130
|
+
message: issue.message,
|
|
131
|
+
code: issue.code
|
|
132
|
+
}))
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
exports.FeedbackSchema = FeedbackSchema; exports.MediaSchema = MediaSchema; exports.BlankConfigSchema = BlankConfigSchema; exports.FillInTheBlanksDataSchema = FillInTheBlanksDataSchema; exports.MultipleChoiceOptionSchema = MultipleChoiceOptionSchema; exports.MultipleChoiceDataSchema = MultipleChoiceDataSchema; exports.multipleChoiceJsonSchema = multipleChoiceJsonSchema; exports.fillInTheBlanksJsonSchema = fillInTheBlanksJsonSchema; exports.validateActivity = validateActivity;
|
|
147
|
+
//# sourceMappingURL=chunk-DCDOTQNH.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["c:\\Users\\onecu\\Documents\\Intellectif\\IT-for-Intellectif\\learning-kit\\packages\\lk-core\\dist\\chunk-DCDOTQNH.cjs"],"names":[],"mappings":"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","file":"C:\\Users\\onecu\\Documents\\Intellectif\\IT-for-Intellectif\\learning-kit\\packages\\lk-core\\dist\\chunk-DCDOTQNH.cjs","sourcesContent":[null]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/errors.ts
|
|
2
|
+
var ActivitySchemaError = class extends Error {
|
|
3
|
+
constructor(activityType, errors) {
|
|
4
|
+
super(`Invalid activity data for type "${activityType}"`);
|
|
5
|
+
this.activityType = activityType;
|
|
6
|
+
this.errors = errors;
|
|
7
|
+
this.name = "ActivitySchemaError";
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
};
|
|
12
|
+
var UnknownActivityTypeError = class extends Error {
|
|
13
|
+
constructor(activityType) {
|
|
14
|
+
super(`Activity type "${activityType}" is not registered`);
|
|
15
|
+
this.activityType = activityType;
|
|
16
|
+
this.name = "UnknownActivityTypeError";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
exports.ActivitySchemaError = ActivitySchemaError; exports.UnknownActivityTypeError = UnknownActivityTypeError;
|
|
25
|
+
//# sourceMappingURL=chunk-DV466SBJ.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["c:\\Users\\onecu\\Documents\\Intellectif\\IT-for-Intellectif\\learning-kit\\packages\\lk-core\\dist\\chunk-DV466SBJ.cjs"],"names":[],"mappings":"AAAA;AACA,IAAI,oBAAoB,EAAE,MAAM,QAAQ,MAAM;AAC9C,EAAE,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE;AACpC,IAAI,KAAK,CAAC,CAAC,gCAAgC,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;AAC7D,IAAI,IAAI,CAAC,aAAa,EAAE,YAAY;AACpC,IAAI,IAAI,CAAC,OAAO,EAAE,MAAM;AACxB,IAAI,IAAI,CAAC,KAAK,EAAE,qBAAqB;AACrC,EAAE;AACF,EAAE;AACF,EAAE;AACF,CAAC;AACD,IAAI,yBAAyB,EAAE,MAAM,QAAQ,MAAM;AACnD,EAAE,WAAW,CAAC,YAAY,EAAE;AAC5B,IAAI,KAAK,CAAC,CAAC,eAAe,EAAE,YAAY,CAAC,mBAAmB,CAAC,CAAC;AAC9D,IAAI,IAAI,CAAC,aAAa,EAAE,YAAY;AACpC,IAAI,IAAI,CAAC,KAAK,EAAE,0BAA0B;AAC1C,EAAE;AACF,EAAE;AACF,CAAC;AACD;AACA;AACE;AACA;AACF,+GAAC","file":"C:\\Users\\onecu\\Documents\\Intellectif\\IT-for-Intellectif\\learning-kit\\packages\\lk-core\\dist\\chunk-DV466SBJ.cjs","sourcesContent":[null]}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import {
|
|
2
|
+
UnknownActivityTypeError
|
|
3
|
+
} from "./chunk-6VOCV4EX.js";
|
|
4
|
+
|
|
5
|
+
// src/scoring/strategies/all-or-nothing.ts
|
|
6
|
+
function allOrNothingStrategy(correctItems) {
|
|
7
|
+
return correctItems.every((isCorrect) => isCorrect) ? 1 : 0;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// src/scoring/strategies/partial.ts
|
|
11
|
+
function partialStrategy(correctSelected, incorrectSelected, totalCorrect, totalIncorrect) {
|
|
12
|
+
const reward = correctSelected / totalCorrect;
|
|
13
|
+
const penalty = totalIncorrect === 0 ? 0 : incorrectSelected / totalIncorrect;
|
|
14
|
+
return Math.max(0, reward - penalty);
|
|
15
|
+
}
|
|
16
|
+
function partialBlankStrategy(correctBlanks, totalBlanks) {
|
|
17
|
+
return correctBlanks / totalBlanks;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// src/scoring/activity-scorers/fill-in-the-blanks.ts
|
|
21
|
+
function normalize(value, blank) {
|
|
22
|
+
let result = value;
|
|
23
|
+
if (blank.trimWhitespace !== false) {
|
|
24
|
+
result = result.trim();
|
|
25
|
+
}
|
|
26
|
+
if (blank.caseSensitive !== true) {
|
|
27
|
+
result = result.toLowerCase();
|
|
28
|
+
}
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
function scoreFillInTheBlanks(data, response) {
|
|
32
|
+
const details = [];
|
|
33
|
+
const perBlankCorrect = [];
|
|
34
|
+
for (const blank of data.blanks) {
|
|
35
|
+
const rawInput = response.answers[blank.id];
|
|
36
|
+
const input = typeof rawInput === "string" ? rawInput : "";
|
|
37
|
+
const normalizedInput = normalize(input, blank);
|
|
38
|
+
const matched = blank.acceptedAnswers.some(
|
|
39
|
+
(accepted) => normalize(accepted, blank) === normalizedInput
|
|
40
|
+
);
|
|
41
|
+
perBlankCorrect.push(matched);
|
|
42
|
+
details.push({
|
|
43
|
+
itemId: blank.id,
|
|
44
|
+
correct: matched,
|
|
45
|
+
learnerResponse: [input],
|
|
46
|
+
correctResponse: [...blank.acceptedAnswers]
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
const correctBlanks = perBlankCorrect.filter(Boolean).length;
|
|
50
|
+
const scoreValue = data.scoringStrategy === "all-or-nothing" ? allOrNothingStrategy(perBlankCorrect) : partialBlankStrategy(correctBlanks, data.blanks.length);
|
|
51
|
+
return { score: scoreValue, maxScore: 1, feedback: null, details };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// src/scoring/activity-scorers/multiple-choice.ts
|
|
55
|
+
function scoreMultipleChoice(data, response) {
|
|
56
|
+
const optionById = new Map(data.options.map((option) => [option.id, option]));
|
|
57
|
+
const selected = new Set(response.selectedOptionIds);
|
|
58
|
+
const totalCorrect = data.options.filter((option) => option.isCorrect).length;
|
|
59
|
+
const totalIncorrect = data.options.length - totalCorrect;
|
|
60
|
+
let scoreValue;
|
|
61
|
+
if (data.scoringStrategy === "all-or-nothing") {
|
|
62
|
+
if (data.mode === "single") {
|
|
63
|
+
scoreValue = response.selectedOptionIds.length === 1 && optionById.get(response.selectedOptionIds[0])?.isCorrect === true ? 1 : 0;
|
|
64
|
+
} else {
|
|
65
|
+
const correctIds = data.options.filter((o) => o.isCorrect).map((o) => o.id);
|
|
66
|
+
const allCorrectSelected = correctIds.every((id) => selected.has(id));
|
|
67
|
+
scoreValue = selected.size === correctIds.length && allCorrectSelected ? 1 : 0;
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
let correctSelected = 0;
|
|
71
|
+
let incorrectSelected = 0;
|
|
72
|
+
for (const id of selected) {
|
|
73
|
+
const option = optionById.get(id);
|
|
74
|
+
if (option?.isCorrect) {
|
|
75
|
+
correctSelected += 1;
|
|
76
|
+
} else {
|
|
77
|
+
incorrectSelected += 1;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
scoreValue = partialStrategy(correctSelected, incorrectSelected, totalCorrect, totalIncorrect);
|
|
81
|
+
}
|
|
82
|
+
const details = data.options.map((option) => {
|
|
83
|
+
const wasSelected = selected.has(option.id);
|
|
84
|
+
return {
|
|
85
|
+
itemId: option.id,
|
|
86
|
+
correct: wasSelected === option.isCorrect,
|
|
87
|
+
learnerResponse: [wasSelected ? "selected" : "not-selected"],
|
|
88
|
+
correctResponse: [option.isCorrect ? "selected" : "not-selected"]
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
return { score: scoreValue, maxScore: 1, feedback: null, details };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// src/scoring/index.ts
|
|
95
|
+
var DEFAULT_PASS_THRESHOLD = 0.7;
|
|
96
|
+
function computePassThreshold(activityData, score2) {
|
|
97
|
+
return score2 >= (activityData.passThreshold ?? DEFAULT_PASS_THRESHOLD);
|
|
98
|
+
}
|
|
99
|
+
function score(activityType, activityData, learnerResponse) {
|
|
100
|
+
let result;
|
|
101
|
+
switch (activityType) {
|
|
102
|
+
case "multiple-choice":
|
|
103
|
+
result = scoreMultipleChoice(
|
|
104
|
+
activityData,
|
|
105
|
+
learnerResponse
|
|
106
|
+
);
|
|
107
|
+
break;
|
|
108
|
+
case "fill-in-the-blanks":
|
|
109
|
+
result = scoreFillInTheBlanks(
|
|
110
|
+
activityData,
|
|
111
|
+
learnerResponse
|
|
112
|
+
);
|
|
113
|
+
break;
|
|
114
|
+
default:
|
|
115
|
+
throw new UnknownActivityTypeError(String(activityType));
|
|
116
|
+
}
|
|
117
|
+
return { ...result, passed: computePassThreshold(activityData, result.score) };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export {
|
|
121
|
+
computePassThreshold,
|
|
122
|
+
score
|
|
123
|
+
};
|
|
124
|
+
//# sourceMappingURL=chunk-GZ73G2TS.js.map
|