@intellectif/lk-core 0.15.0 → 0.17.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/CHANGELOG.md +74 -0
- package/dist/{activity-C7cR8U9n.d.cts → activity-BmjBjXVJ.d.cts} +218 -3
- package/dist/{activity-C7cR8U9n.d.ts → activity-BmjBjXVJ.d.ts} +218 -3
- package/dist/{chunk-W7AQP6AV.cjs → chunk-2CV6NU32.cjs} +24 -22
- package/dist/chunk-2CV6NU32.cjs.map +1 -0
- package/dist/{chunk-DPHX4E7X.js → chunk-D3GP5MET.js} +718 -662
- package/dist/chunk-D3GP5MET.js.map +1 -0
- package/dist/{chunk-QFWEF5ST.cjs → chunk-D4TOPSHV.cjs} +539 -483
- package/dist/chunk-D4TOPSHV.cjs.map +1 -0
- package/dist/{chunk-7ETU6EXQ.cjs → chunk-EOFWSGLU.cjs} +4 -4
- package/dist/{chunk-7ETU6EXQ.cjs.map → chunk-EOFWSGLU.cjs.map} +1 -1
- package/dist/{chunk-L6YBQXSB.js → chunk-WXS5EB65.js} +2 -2
- package/dist/{chunk-54XYQ3CS.js → chunk-X5DAXBJI.js} +2 -2
- package/dist/{chunk-5KWF34LJ.cjs → chunk-XNMKDFPW.cjs} +31 -31
- package/dist/{chunk-5KWF34LJ.cjs.map → chunk-XNMKDFPW.cjs.map} +1 -1
- package/dist/{chunk-EEMVWBPP.js → chunk-Z7QQZ53L.js} +10 -8
- package/dist/chunk-Z7QQZ53L.js.map +1 -0
- package/dist/{index-BWyMDlUS.d.cts → index-CvfeD_cU.d.cts} +144 -86
- package/dist/{index-D10NaztZ.d.ts → index-G_KusUcK.d.ts} +144 -86
- package/dist/index.cjs +544 -128
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +135 -5
- package/dist/index.d.ts +135 -5
- package/dist/index.js +426 -10
- package/dist/index.js.map +1 -1
- package/dist/schemas.cjs +5 -3
- package/dist/schemas.cjs.map +1 -1
- package/dist/schemas.d.cts +2 -2
- package/dist/schemas.d.ts +2 -2
- package/dist/schemas.js +4 -2
- package/dist/scoring.cjs +3 -3
- package/dist/scoring.d.cts +2 -2
- package/dist/scoring.d.ts +2 -2
- package/dist/scoring.js +2 -2
- package/dist/xapi.cjs +3 -3
- package/dist/xapi.d.cts +1 -1
- package/dist/xapi.d.ts +1 -1
- package/dist/xapi.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-DPHX4E7X.js.map +0 -1
- package/dist/chunk-EEMVWBPP.js.map +0 -1
- package/dist/chunk-QFWEF5ST.cjs.map +0 -1
- package/dist/chunk-W7AQP6AV.cjs.map +0 -1
- /package/dist/{chunk-L6YBQXSB.js.map → chunk-WXS5EB65.js.map} +0 -0
- /package/dist/{chunk-54XYQ3CS.js.map → chunk-X5DAXBJI.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -16,14 +16,14 @@
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
var
|
|
19
|
+
var _chunkXNMKDFPWcjs = require('./chunk-XNMKDFPW.cjs');
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
var
|
|
26
|
+
var _chunkEOFWSGLUcjs = require('./chunk-EOFWSGLU.cjs');
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
|
|
@@ -49,7 +49,7 @@ var _chunk7ETU6EXQcjs = require('./chunk-7ETU6EXQ.cjs');
|
|
|
49
49
|
|
|
50
50
|
|
|
51
51
|
|
|
52
|
-
var
|
|
52
|
+
var _chunk2CV6NU32cjs = require('./chunk-2CV6NU32.cjs');
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
|
|
@@ -134,7 +134,408 @@ var _chunkW7AQP6AVcjs = require('./chunk-W7AQP6AV.cjs');
|
|
|
134
134
|
|
|
135
135
|
|
|
136
136
|
|
|
137
|
-
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
var _chunkD4TOPSHVcjs = require('./chunk-D4TOPSHV.cjs');
|
|
140
|
+
|
|
141
|
+
// src/ai.ts
|
|
142
|
+
var AI_EXPLANATION_TYPES = [
|
|
143
|
+
"multiple-choice",
|
|
144
|
+
"fill-in-the-blanks",
|
|
145
|
+
"gap-select",
|
|
146
|
+
"dictation"
|
|
147
|
+
];
|
|
148
|
+
var AI_HINT_TYPES = [
|
|
149
|
+
"multiple-choice",
|
|
150
|
+
"fill-in-the-blanks",
|
|
151
|
+
"gap-select"
|
|
152
|
+
];
|
|
153
|
+
var AI_TEXT_MAX_LENGTH = 2e3;
|
|
154
|
+
function aiSupports(activityType, feature) {
|
|
155
|
+
const types = feature === "hint" ? AI_HINT_TYPES : AI_EXPLANATION_TYPES;
|
|
156
|
+
return types.includes(activityType);
|
|
157
|
+
}
|
|
158
|
+
function aiAllowedByContent(data, feature) {
|
|
159
|
+
const permissions = data.ai;
|
|
160
|
+
if (typeof permissions !== "object" || permissions === null) {
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
const key = feature === "hint" ? "hints" : "explanations";
|
|
164
|
+
return permissions[key] !== false;
|
|
165
|
+
}
|
|
166
|
+
function aiGradeOf(result) {
|
|
167
|
+
const ratio = result.maxScore > 0 ? result.score / result.maxScore : 0;
|
|
168
|
+
let category = "partly-correct";
|
|
169
|
+
if (ratio >= 1 - 1e-9) {
|
|
170
|
+
category = "correct";
|
|
171
|
+
} else if (ratio <= 1e-9) {
|
|
172
|
+
category = "incorrect";
|
|
173
|
+
}
|
|
174
|
+
return { score: result.score, maxScore: result.maxScore, passed: result.passed, category };
|
|
175
|
+
}
|
|
176
|
+
function placeholderOrder(passage) {
|
|
177
|
+
return [...passage.matchAll(_chunkD4TOPSHVcjs.PLACEHOLDER_RE)].map((match) => match[1]);
|
|
178
|
+
}
|
|
179
|
+
function numberedPassage(passage) {
|
|
180
|
+
let position = 0;
|
|
181
|
+
return passage.replace(_chunkD4TOPSHVcjs.PLACEHOLDER_RE, () => {
|
|
182
|
+
position += 1;
|
|
183
|
+
return `[${position}]`;
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
function isAnswerOption(detail, chosen) {
|
|
187
|
+
switch (detail.outcome) {
|
|
188
|
+
case "correct":
|
|
189
|
+
case "incorrect-omission":
|
|
190
|
+
return true;
|
|
191
|
+
case "incorrect":
|
|
192
|
+
case "correct-omission":
|
|
193
|
+
return false;
|
|
194
|
+
default:
|
|
195
|
+
return chosen ? detail.correct : !detail.correct;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
var firstString = (value) => Array.isArray(value) ? value[0] : value;
|
|
199
|
+
var listOf = (value) => value === void 0 ? null : Array.isArray(value) ? [...value] : [value];
|
|
200
|
+
function emptyResponse(type) {
|
|
201
|
+
switch (type) {
|
|
202
|
+
case "multiple-choice":
|
|
203
|
+
return { type: "multiple-choice", selectedOptionIds: [] };
|
|
204
|
+
case "fill-in-the-blanks":
|
|
205
|
+
return { type: "fill-in-the-blanks", answers: {} };
|
|
206
|
+
case "gap-select":
|
|
207
|
+
return { type: "gap-select", selections: {} };
|
|
208
|
+
case "dictation":
|
|
209
|
+
return { type: "dictation", text: "" };
|
|
210
|
+
default:
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
var base = (data) => ({
|
|
215
|
+
activityId: data.id,
|
|
216
|
+
title: data.title,
|
|
217
|
+
...typeof data.locale === "string" ? { locale: data.locale } : {}
|
|
218
|
+
});
|
|
219
|
+
function buildAiFacts(data, response, details) {
|
|
220
|
+
const byId = new Map((_nullishCoalesce(details, () => ( []))).map((detail) => [detail.itemId, detail]));
|
|
221
|
+
const full = data.redacted !== true;
|
|
222
|
+
switch (data.type) {
|
|
223
|
+
case "multiple-choice": {
|
|
224
|
+
const item = data;
|
|
225
|
+
const chosen = new Set(
|
|
226
|
+
_optionalChain([response, 'optionalAccess', _ => _.type]) === "multiple-choice" ? response.selectedOptionIds : []
|
|
227
|
+
);
|
|
228
|
+
return {
|
|
229
|
+
...base(data),
|
|
230
|
+
activityType: "multiple-choice",
|
|
231
|
+
question: item.question,
|
|
232
|
+
mode: item.mode,
|
|
233
|
+
options: item.options.map((option) => {
|
|
234
|
+
const detail = byId.get(option.id);
|
|
235
|
+
const wasChosen = chosen.has(option.id);
|
|
236
|
+
let correct = null;
|
|
237
|
+
if (full && typeof option.isCorrect === "boolean") {
|
|
238
|
+
correct = option.isCorrect;
|
|
239
|
+
} else if (detail !== void 0) {
|
|
240
|
+
correct = isAnswerOption(detail, wasChosen);
|
|
241
|
+
}
|
|
242
|
+
return {
|
|
243
|
+
id: option.id,
|
|
244
|
+
text: option.text,
|
|
245
|
+
chosen: wasChosen,
|
|
246
|
+
correct,
|
|
247
|
+
...typeof option.feedback === "string" ? { feedback: option.feedback } : {}
|
|
248
|
+
};
|
|
249
|
+
})
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
case "fill-in-the-blanks": {
|
|
253
|
+
const item = data;
|
|
254
|
+
const answers = _optionalChain([response, 'optionalAccess', _2 => _2.type]) === "fill-in-the-blanks" ? response.answers : {};
|
|
255
|
+
const blanks = new Map(item.blanks.map((blank) => [blank.id, blank]));
|
|
256
|
+
return {
|
|
257
|
+
...base(data),
|
|
258
|
+
activityType: "fill-in-the-blanks",
|
|
259
|
+
passage: numberedPassage(item.passage),
|
|
260
|
+
blanks: placeholderOrder(item.passage).map((id, index) => {
|
|
261
|
+
const blank = blanks.get(id);
|
|
262
|
+
const detail = byId.get(id);
|
|
263
|
+
const accepted = full && Array.isArray(_optionalChain([blank, 'optionalAccess', _3 => _3.acceptedAnswers])) ? [...blank.acceptedAnswers] : listOf(_optionalChain([detail, 'optionalAccess', _4 => _4.correctResponse]));
|
|
264
|
+
return {
|
|
265
|
+
id,
|
|
266
|
+
position: index + 1,
|
|
267
|
+
typed: typeof answers[id] === "string" ? answers[id] : "",
|
|
268
|
+
accepted,
|
|
269
|
+
correct: detail === void 0 ? null : detail.correct,
|
|
270
|
+
...typeof _optionalChain([blank, 'optionalAccess', _5 => _5.hint]) === "string" ? { hint: blank.hint } : {},
|
|
271
|
+
...typeof _optionalChain([blank, 'optionalAccess', _6 => _6.feedback]) === "string" ? { feedback: blank.feedback } : {}
|
|
272
|
+
};
|
|
273
|
+
})
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
case "gap-select": {
|
|
277
|
+
const item = data;
|
|
278
|
+
const selections = _optionalChain([response, 'optionalAccess', _7 => _7.type]) === "gap-select" ? response.selections : {};
|
|
279
|
+
const gaps = new Map(item.gaps.map((gap) => [gap.id, gap]));
|
|
280
|
+
const banks = new Map((_nullishCoalesce(item.banks, () => ( []))).map((bank) => [bank.id, bank]));
|
|
281
|
+
return {
|
|
282
|
+
...base(data),
|
|
283
|
+
activityType: "gap-select",
|
|
284
|
+
passage: numberedPassage(item.passage),
|
|
285
|
+
gaps: placeholderOrder(item.passage).map((id, index) => {
|
|
286
|
+
const gap = gaps.get(id);
|
|
287
|
+
const choices = _nullishCoalesce(_optionalChain([gap, 'optionalAccess', _8 => _8.choices]), () => ( (_optionalChain([gap, 'optionalAccess', _9 => _9.bankId]) === void 0 ? [] : _nullishCoalesce(_optionalChain([banks, 'access', _10 => _10.get, 'call', _11 => _11(gap.bankId), 'optionalAccess', _12 => _12.choices]), () => ( [])))));
|
|
288
|
+
const textOf = (choiceId) => choiceId === void 0 ? null : _nullishCoalesce(_optionalChain([choices, 'access', _13 => _13.find, 'call', _14 => _14((choice) => choice.id === choiceId), 'optionalAccess', _15 => _15.text]), () => ( null));
|
|
289
|
+
const detail = byId.get(id);
|
|
290
|
+
const answerId = full && typeof _optionalChain([gap, 'optionalAccess', _16 => _16.correctChoiceId]) === "string" ? gap.correctChoiceId : firstString(_optionalChain([detail, 'optionalAccess', _17 => _17.correctResponse]));
|
|
291
|
+
return {
|
|
292
|
+
id,
|
|
293
|
+
position: index + 1,
|
|
294
|
+
choices: choices.map((choice) => choice.text),
|
|
295
|
+
chosen: textOf(selections[id]),
|
|
296
|
+
answer: textOf(answerId),
|
|
297
|
+
correct: detail === void 0 ? null : detail.correct,
|
|
298
|
+
...typeof _optionalChain([gap, 'optionalAccess', _18 => _18.feedback]) === "string" ? { feedback: gap.feedback } : {}
|
|
299
|
+
};
|
|
300
|
+
})
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
case "dictation": {
|
|
304
|
+
const item = data;
|
|
305
|
+
const typed = _optionalChain([response, 'optionalAccess', _19 => _19.type]) === "dictation" ? response.text : "";
|
|
306
|
+
const hasKey = full && typeof item.transcript === "string";
|
|
307
|
+
let words = null;
|
|
308
|
+
if (hasKey) {
|
|
309
|
+
words = _chunkD4TOPSHVcjs.alignDictation.call(void 0, item, typed).words.map((word) => ({
|
|
310
|
+
expected: word.reference,
|
|
311
|
+
typed: word.attempt,
|
|
312
|
+
status: word.status
|
|
313
|
+
}));
|
|
314
|
+
} else if (details !== null && details.length > 0) {
|
|
315
|
+
words = details.map((detail) => {
|
|
316
|
+
const expected = _nullishCoalesce(firstString(detail.correctResponse), () => ( ""));
|
|
317
|
+
const attempt = _nullishCoalesce(firstString(detail.learnerResponse), () => ( ""));
|
|
318
|
+
let status = "incorrect";
|
|
319
|
+
if (detail.correct) {
|
|
320
|
+
status = "correct";
|
|
321
|
+
} else if (attempt === "") {
|
|
322
|
+
status = "missing";
|
|
323
|
+
} else if (expected === "") {
|
|
324
|
+
status = "extra";
|
|
325
|
+
}
|
|
326
|
+
return { expected, typed: attempt, status };
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
return {
|
|
330
|
+
...base(data),
|
|
331
|
+
activityType: "dictation",
|
|
332
|
+
transcript: hasKey ? item.transcript : null,
|
|
333
|
+
typed,
|
|
334
|
+
words
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
default:
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
function gradeLocally(data, response) {
|
|
342
|
+
if (data.redacted === true) {
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
try {
|
|
346
|
+
const result = _chunkXNMKDFPWcjs.score.call(void 0, data.type, data, response);
|
|
347
|
+
return { details: result.details, grade: aiGradeOf(result) };
|
|
348
|
+
} catch (e) {
|
|
349
|
+
return null;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
function aiExplanationRequest(input) {
|
|
353
|
+
const { data, response, outcome, learnerLocale } = input;
|
|
354
|
+
if (!aiSupports(data.type, "explanation") || !aiAllowedByContent(data, "explanation")) {
|
|
355
|
+
return null;
|
|
356
|
+
}
|
|
357
|
+
let details = null;
|
|
358
|
+
let grade = null;
|
|
359
|
+
if (_optionalChain([outcome, 'optionalAccess', _20 => _20.status]) === "scored") {
|
|
360
|
+
details = outcome.details;
|
|
361
|
+
grade = aiGradeOf(outcome);
|
|
362
|
+
} else if (response !== null) {
|
|
363
|
+
const local = gradeLocally(data, response);
|
|
364
|
+
if (local !== null) {
|
|
365
|
+
details = local.details;
|
|
366
|
+
grade = local.grade;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
if (grade === null) {
|
|
370
|
+
return null;
|
|
371
|
+
}
|
|
372
|
+
const facts = buildAiFacts(data, response, details);
|
|
373
|
+
if (facts === null) {
|
|
374
|
+
return null;
|
|
375
|
+
}
|
|
376
|
+
return {
|
|
377
|
+
feature: "explanation",
|
|
378
|
+
facts,
|
|
379
|
+
grade,
|
|
380
|
+
...learnerLocale !== void 0 ? { learnerLocale } : {}
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
function aiHintRequest(input) {
|
|
384
|
+
const { data, previousHints, learnerLocale } = input;
|
|
385
|
+
if (!aiSupports(data.type, "hint") || !aiAllowedByContent(data, "hint") || data.redacted === true) {
|
|
386
|
+
return null;
|
|
387
|
+
}
|
|
388
|
+
const response = _nullishCoalesce(input.response, () => ( emptyResponse(data.type)));
|
|
389
|
+
const local = response === null ? null : gradeLocally(data, response);
|
|
390
|
+
const facts = buildAiFacts(data, response, _nullishCoalesce(_optionalChain([local, 'optionalAccess', _21 => _21.details]), () => ( null)));
|
|
391
|
+
if (facts === null) {
|
|
392
|
+
return null;
|
|
393
|
+
}
|
|
394
|
+
return {
|
|
395
|
+
feature: "hint",
|
|
396
|
+
facts,
|
|
397
|
+
hintNumber: previousHints.length + 1,
|
|
398
|
+
previousHints: [...previousHints],
|
|
399
|
+
...learnerLocale !== void 0 ? { learnerLocale } : {}
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
var VERDICTS = ["correct", "partly-correct", "incorrect"];
|
|
403
|
+
function provenanceOf(raw) {
|
|
404
|
+
if (typeof raw !== "object" || raw === null) {
|
|
405
|
+
return void 0;
|
|
406
|
+
}
|
|
407
|
+
const kept = {};
|
|
408
|
+
for (const key of ["model", "promptHash", "generatedAt"]) {
|
|
409
|
+
const value = raw[key];
|
|
410
|
+
if (typeof value === "string" && value.length > 0 && value.length <= 200) {
|
|
411
|
+
kept[key] = value;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
return Object.keys(kept).length > 0 ? kept : void 0;
|
|
415
|
+
}
|
|
416
|
+
function cleanText(text) {
|
|
417
|
+
return text.replace(/\r\n?/g, "\n").replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F\u2028\u2029]/g, "").replace(/\n{3,}/g, "\n\n").trim();
|
|
418
|
+
}
|
|
419
|
+
function readAiTextResult(raw) {
|
|
420
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
421
|
+
return { ok: false, refusal: "malformed" };
|
|
422
|
+
}
|
|
423
|
+
const record = raw;
|
|
424
|
+
if (typeof record.text !== "string") {
|
|
425
|
+
return { ok: false, refusal: "malformed" };
|
|
426
|
+
}
|
|
427
|
+
if (record.verdict !== void 0 && !VERDICTS.includes(record.verdict)) {
|
|
428
|
+
return { ok: false, refusal: "malformed" };
|
|
429
|
+
}
|
|
430
|
+
const text = cleanText(record.text);
|
|
431
|
+
if (text === "") {
|
|
432
|
+
return { ok: false, refusal: "empty" };
|
|
433
|
+
}
|
|
434
|
+
if ([...text].length > AI_TEXT_MAX_LENGTH) {
|
|
435
|
+
return { ok: false, refusal: "too-long" };
|
|
436
|
+
}
|
|
437
|
+
const provenance = provenanceOf(record.provenance);
|
|
438
|
+
return {
|
|
439
|
+
ok: true,
|
|
440
|
+
result: {
|
|
441
|
+
text,
|
|
442
|
+
...record.verdict !== void 0 ? { verdict: record.verdict } : {},
|
|
443
|
+
...provenance !== void 0 ? { provenance } : {}
|
|
444
|
+
}
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
function checkAiExplanation(raw, request) {
|
|
448
|
+
const read = readAiTextResult(raw);
|
|
449
|
+
if (!read.ok) {
|
|
450
|
+
return read;
|
|
451
|
+
}
|
|
452
|
+
if (read.result.verdict !== void 0 && read.result.verdict !== request.grade.category) {
|
|
453
|
+
return { ok: false, refusal: "contradicts-grade" };
|
|
454
|
+
}
|
|
455
|
+
return read;
|
|
456
|
+
}
|
|
457
|
+
function checkAiHint(raw, request) {
|
|
458
|
+
const read = readAiTextResult(raw);
|
|
459
|
+
if (!read.ok) {
|
|
460
|
+
return read;
|
|
461
|
+
}
|
|
462
|
+
if (hintRevealsAnswer(request.facts, read.result.text)) {
|
|
463
|
+
return { ok: false, refusal: "reveals-answer" };
|
|
464
|
+
}
|
|
465
|
+
return read;
|
|
466
|
+
}
|
|
467
|
+
function fold(text) {
|
|
468
|
+
const folded = text.normalize("NFKD").replace(/\p{M}/gu, "").toLowerCase().replace(/[^\p{L}\p{N}]+/gu, " ").trim();
|
|
469
|
+
return folded === "" ? [] : folded.split(" ");
|
|
470
|
+
}
|
|
471
|
+
function containsWords(haystack, needle) {
|
|
472
|
+
if (needle.length === 0 || needle.length > haystack.length) {
|
|
473
|
+
return false;
|
|
474
|
+
}
|
|
475
|
+
for (let start = 0; start + needle.length <= haystack.length; start += 1) {
|
|
476
|
+
let match = true;
|
|
477
|
+
for (let offset = 0; offset < needle.length; offset += 1) {
|
|
478
|
+
if (haystack[start + offset] !== needle[offset]) {
|
|
479
|
+
match = false;
|
|
480
|
+
break;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
if (match) {
|
|
484
|
+
return true;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
return false;
|
|
488
|
+
}
|
|
489
|
+
var isShort = (words) => words.length === 1 && [...words[0]].length < 4;
|
|
490
|
+
function neighbours(passage, position) {
|
|
491
|
+
const marker = `[${position}]`;
|
|
492
|
+
const at = passage.indexOf(marker);
|
|
493
|
+
if (at === -1) {
|
|
494
|
+
return {};
|
|
495
|
+
}
|
|
496
|
+
const strip = (text) => text.replace(/\[\d+\]/g, " ");
|
|
497
|
+
const left = fold(strip(passage.slice(0, at)));
|
|
498
|
+
const right = fold(strip(passage.slice(at + marker.length)));
|
|
499
|
+
const before = left[left.length - 1];
|
|
500
|
+
const after = right[0];
|
|
501
|
+
return {
|
|
502
|
+
...before !== void 0 ? { before } : {},
|
|
503
|
+
...after !== void 0 ? { after } : {}
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
function hintRevealsAnswer(facts, hint) {
|
|
507
|
+
const words = fold(hint);
|
|
508
|
+
const reveals = (answer, passage, position) => {
|
|
509
|
+
const needle = fold(answer);
|
|
510
|
+
if (needle.length === 0) {
|
|
511
|
+
return false;
|
|
512
|
+
}
|
|
513
|
+
if (!isShort(needle) || passage === void 0 || position === void 0) {
|
|
514
|
+
return containsWords(words, needle);
|
|
515
|
+
}
|
|
516
|
+
const { before, after } = neighbours(passage, position);
|
|
517
|
+
if (before === void 0 && after === void 0) {
|
|
518
|
+
return containsWords(words, needle);
|
|
519
|
+
}
|
|
520
|
+
return before !== void 0 && containsWords(words, [before, ...needle]) || after !== void 0 && containsWords(words, [...needle, after]);
|
|
521
|
+
};
|
|
522
|
+
switch (facts.activityType) {
|
|
523
|
+
case "multiple-choice":
|
|
524
|
+
return facts.options.some((option) => option.correct === true && reveals(option.text));
|
|
525
|
+
case "fill-in-the-blanks":
|
|
526
|
+
return facts.blanks.some(
|
|
527
|
+
(blank) => (_nullishCoalesce(blank.accepted, () => ( []))).some((answer) => reveals(answer, facts.passage, blank.position))
|
|
528
|
+
);
|
|
529
|
+
case "gap-select":
|
|
530
|
+
return facts.gaps.some(
|
|
531
|
+
(gap) => gap.answer !== null && reveals(gap.answer, facts.passage, gap.position)
|
|
532
|
+
);
|
|
533
|
+
case "dictation":
|
|
534
|
+
return false;
|
|
535
|
+
default:
|
|
536
|
+
return false;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
138
539
|
|
|
139
540
|
// src/content-hash.ts
|
|
140
541
|
function canonicalJson(value, seen = /* @__PURE__ */ new Set()) {
|
|
@@ -283,7 +684,7 @@ function flattenSequence(entries, options = {}) {
|
|
|
283
684
|
const presented = timeline !== void 0 ? inQuizOrder(items, timeline) : entry.shuffle === "within-group" ? seededShuffle(items, `${seed}:group:${entry.id}`) : items;
|
|
284
685
|
const size = presented.length;
|
|
285
686
|
presented.forEach(({ item, itemIndex }, position) => {
|
|
286
|
-
const cue = _optionalChain([timeline, 'optionalAccess',
|
|
687
|
+
const cue = _optionalChain([timeline, 'optionalAccess', _22 => _22.cues, 'access', _23 => _23.find, 'call', _24 => _24((candidate) => candidate.itemIds.includes(item.id))]);
|
|
287
688
|
slots.push({
|
|
288
689
|
// Slot ids stay AUTHORED — the item's index or its key — whatever the
|
|
289
690
|
// presented order: moving a quiz must never re-map a stored answer.
|
|
@@ -337,16 +738,16 @@ function stimulusMediaKey(slotId) {
|
|
|
337
738
|
}
|
|
338
739
|
function resolvePlaybackPolicy(media) {
|
|
339
740
|
const p = media.playback;
|
|
340
|
-
const budgeted = typeof _optionalChain([p, 'optionalAccess',
|
|
341
|
-
const seek = _nullishCoalesce(_optionalChain([p, 'optionalAccess',
|
|
342
|
-
const rate = _nullishCoalesce(_optionalChain([p, 'optionalAccess',
|
|
343
|
-
const controls = _nullishCoalesce(_optionalChain([p, 'optionalAccess',
|
|
741
|
+
const budgeted = typeof _optionalChain([p, 'optionalAccess', _25 => _25.maxPlays]) === "number";
|
|
742
|
+
const seek = _nullishCoalesce(_optionalChain([p, 'optionalAccess', _26 => _26.seek]), () => ( (budgeted ? "none" : "allow")));
|
|
743
|
+
const rate = _nullishCoalesce(_optionalChain([p, 'optionalAccess', _27 => _27.rate]), () => ( "allow"));
|
|
744
|
+
const controls = _nullishCoalesce(_optionalChain([p, 'optionalAccess', _28 => _28.controls]), () => ( (budgeted || seek === "none" || rate === "fixed" ? "minimal" : "native")));
|
|
344
745
|
return {
|
|
345
746
|
controls,
|
|
346
|
-
maxPlays: budgeted ? _optionalChain([p, 'optionalAccess',
|
|
747
|
+
maxPlays: budgeted ? _optionalChain([p, 'optionalAccess', _29 => _29.maxPlays]) : null,
|
|
347
748
|
seek,
|
|
348
749
|
rate,
|
|
349
|
-
nativeControlHints: _nullishCoalesce(_optionalChain([p, 'optionalAccess',
|
|
750
|
+
nativeControlHints: _nullishCoalesce(_optionalChain([p, 'optionalAccess', _30 => _30.nativeControlHints]), () => ( []))
|
|
350
751
|
};
|
|
351
752
|
}
|
|
352
753
|
function planMediaBudgets(plan) {
|
|
@@ -361,7 +762,7 @@ function planMediaBudgets(plan) {
|
|
|
361
762
|
function assertEntry(key, entry) {
|
|
362
763
|
if (entry === null || typeof entry !== "object" || !Number.isInteger(entry.plays) || entry.plays < 0) {
|
|
363
764
|
throw new Error(
|
|
364
|
-
`serializeMediaPlayLedger: play count for ${JSON.stringify(key)} is ${JSON.stringify(_optionalChain([entry, 'optionalAccess',
|
|
765
|
+
`serializeMediaPlayLedger: play count for ${JSON.stringify(key)} is ${JSON.stringify(_optionalChain([entry, 'optionalAccess', _31 => _31.plays]))}. A count must be a non-negative integer; Number(a NULL column) is the usual cause.`
|
|
365
766
|
);
|
|
366
767
|
}
|
|
367
768
|
if (entry.at !== void 0 && (!Number.isFinite(entry.at) || entry.at < 0)) {
|
|
@@ -434,7 +835,7 @@ function mediaBudgetsOf(slot) {
|
|
|
434
835
|
budgets.push({ key: slotMediaKey(slot.slotId), maxPlays });
|
|
435
836
|
}
|
|
436
837
|
}
|
|
437
|
-
const stimulusMedia = _optionalChain([slot, 'access',
|
|
838
|
+
const stimulusMedia = _optionalChain([slot, 'access', _32 => _32.group, 'optionalAccess', _33 => _33.stimulus, 'access', _34 => _34.media]);
|
|
438
839
|
if (stimulusMedia !== void 0) {
|
|
439
840
|
const maxPlays = resolvePlaybackPolicy(stimulusMedia).maxPlays;
|
|
440
841
|
if (maxPlays !== null) {
|
|
@@ -500,7 +901,7 @@ function planAttempt(entries, options = {}) {
|
|
|
500
901
|
...seed !== void 0 ? { seed } : {}
|
|
501
902
|
});
|
|
502
903
|
assertNoSplitBudgets(slots);
|
|
503
|
-
const planned = slots.map((slot) => planSlot(slot, _nullishCoalesce(_optionalChain([points, 'optionalCall',
|
|
904
|
+
const planned = slots.map((slot) => planSlot(slot, _nullishCoalesce(_optionalChain([points, 'optionalCall', _35 => _35(slot)]), () => ( 1))));
|
|
504
905
|
const totalPoints = planned.reduce((sum, slot) => sum + slot.points, 0);
|
|
505
906
|
return {
|
|
506
907
|
planVersion: "1.0",
|
|
@@ -532,10 +933,10 @@ function verifyAttemptPlan(plan, current) {
|
|
|
532
933
|
if (now.contentHash !== slot.contentHash) {
|
|
533
934
|
changedSlotIds.push(slot.slotId);
|
|
534
935
|
}
|
|
535
|
-
if (_optionalChain([now, 'access',
|
|
936
|
+
if (_optionalChain([now, 'access', _36 => _36.group, 'optionalAccess', _37 => _37.stimulusHash]) !== _optionalChain([slot, 'access', _38 => _38.group, 'optionalAccess', _39 => _39.stimulusHash])) {
|
|
536
937
|
changedStimulusSlotIds.push(slot.slotId);
|
|
537
938
|
}
|
|
538
|
-
if (contentHash(_nullishCoalesce(_optionalChain([now, 'access',
|
|
939
|
+
if (contentHash(_nullishCoalesce(_optionalChain([now, 'access', _40 => _40.group, 'optionalAccess', _41 => _41.cue]), () => ( null))) !== contentHash(_nullishCoalesce(_optionalChain([slot, 'access', _42 => _42.group, 'optionalAccess', _43 => _43.cue]), () => ( null)))) {
|
|
539
940
|
changedCueSlotIds.push(slot.slotId);
|
|
540
941
|
}
|
|
541
942
|
if (now.points !== slot.points) {
|
|
@@ -708,22 +1109,22 @@ function createInteractiveVideoDraft(context) {
|
|
|
708
1109
|
};
|
|
709
1110
|
}
|
|
710
1111
|
function validateItemGroupDraft(draft) {
|
|
711
|
-
return
|
|
1112
|
+
return _chunkD4TOPSHVcjs.withValidationScope.call(void 0, () => validateItemGroupDraftInScope(draft));
|
|
712
1113
|
}
|
|
713
1114
|
function validateItemGroupDraftInScope(draft) {
|
|
714
1115
|
const issues = [];
|
|
715
|
-
if (!
|
|
1116
|
+
if (!_chunkD4TOPSHVcjs.isRecord.call(void 0, draft)) {
|
|
716
1117
|
issues.push(
|
|
717
|
-
|
|
1118
|
+
_chunkD4TOPSHVcjs.issue.call(void 0, "ig_not_an_object", [], "A group must be an object with a stimulus and its items.")
|
|
718
1119
|
);
|
|
719
1120
|
return { status: "invalid", issues };
|
|
720
1121
|
}
|
|
721
1122
|
issues.push(...checkGroupIdentity(draft));
|
|
722
|
-
if (
|
|
1123
|
+
if (_chunkD4TOPSHVcjs.isRecord.call(void 0, draft.stimulus)) {
|
|
723
1124
|
issues.push(...checkStimulus(draft.stimulus));
|
|
724
|
-
} else if (
|
|
1125
|
+
} else if (_chunkD4TOPSHVcjs.isUnset.call(void 0, draft.stimulus)) {
|
|
725
1126
|
issues.push(
|
|
726
|
-
|
|
1127
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
727
1128
|
"ig_stimulus_required",
|
|
728
1129
|
["stimulus"],
|
|
729
1130
|
"Add the passage, recording or image the questions are about."
|
|
@@ -734,25 +1135,26 @@ function validateItemGroupDraftInScope(draft) {
|
|
|
734
1135
|
if (draft.timeline !== void 0 && draft.timeline !== null) {
|
|
735
1136
|
issues.push(...checkTimeline(draft));
|
|
736
1137
|
}
|
|
737
|
-
|
|
1138
|
+
const captions = _chunkD4TOPSHVcjs.groupCaptionsField.call(void 0, draft, (captionsUrl) => !_chunkD4TOPSHVcjs.isUnwritten.call(void 0, captionsUrl));
|
|
1139
|
+
if (captions !== void 0) {
|
|
738
1140
|
issues.push(
|
|
739
|
-
|
|
1141
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
740
1142
|
"dc_captions_not_allowed",
|
|
741
|
-
["stimulus", "media",
|
|
742
|
-
|
|
1143
|
+
["stimulus", "media", captions],
|
|
1144
|
+
_chunkD4TOPSHVcjs.GROUP_CAPTIONS_REVEAL_DICTATION
|
|
743
1145
|
)
|
|
744
1146
|
);
|
|
745
1147
|
}
|
|
746
|
-
const parsed =
|
|
1148
|
+
const parsed = _chunk2CV6NU32cjs.ItemGroupSchema.safeParse(draft, { reportInput: true });
|
|
747
1149
|
if (!parsed.success) {
|
|
748
1150
|
for (const schemaIssue of parsed.error.issues) {
|
|
749
1151
|
const path = schemaIssue.path.map(String);
|
|
750
|
-
if (issues.some((known) =>
|
|
1152
|
+
if (issues.some((known) => _chunkD4TOPSHVcjs.covers.call(void 0, known.path, path))) {
|
|
751
1153
|
continue;
|
|
752
1154
|
}
|
|
753
|
-
if (path.length > 0 &&
|
|
1155
|
+
if (path.length > 0 && _chunkD4TOPSHVcjs.refusesEmpty.call(void 0, draft, schemaIssue)) {
|
|
754
1156
|
issues.push(
|
|
755
|
-
|
|
1157
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
756
1158
|
"null_not_allowed",
|
|
757
1159
|
path,
|
|
758
1160
|
"This field cannot be null. Leave it out if it is optional, or give it a value."
|
|
@@ -768,7 +1170,7 @@ function validateItemGroupDraftInScope(draft) {
|
|
|
768
1170
|
});
|
|
769
1171
|
}
|
|
770
1172
|
}
|
|
771
|
-
const stored =
|
|
1173
|
+
const stored = _chunk2CV6NU32cjs.validateItemGroup.call(void 0, draft);
|
|
772
1174
|
if (issues.length === 0 && stored.success) {
|
|
773
1175
|
return { status: "complete", data: stored.data, issues };
|
|
774
1176
|
}
|
|
@@ -783,21 +1185,21 @@ function validateItemGroupDraftInScope(draft) {
|
|
|
783
1185
|
function checkTimeline(draft) {
|
|
784
1186
|
const issues = [];
|
|
785
1187
|
const timeline = draft.timeline;
|
|
786
|
-
if (!
|
|
1188
|
+
if (!_chunkD4TOPSHVcjs.isRecord.call(void 0, timeline)) {
|
|
787
1189
|
return issues;
|
|
788
1190
|
}
|
|
789
|
-
const stimulus =
|
|
790
|
-
if (stimulus !== void 0 && !
|
|
1191
|
+
const stimulus = _chunkD4TOPSHVcjs.isRecord.call(void 0, draft.stimulus) ? draft.stimulus : void 0;
|
|
1192
|
+
if (stimulus !== void 0 && !_chunkD4TOPSHVcjs.isUnwritten.call(void 0, stimulus.kind) && stimulus.kind !== "video") {
|
|
791
1193
|
issues.push(
|
|
792
|
-
|
|
1194
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
793
1195
|
"ig_timeline_stimulus_kind",
|
|
794
1196
|
["stimulus", "kind"],
|
|
795
1197
|
"An interactive video needs a video: quizzes open at moments of it."
|
|
796
1198
|
)
|
|
797
1199
|
);
|
|
798
|
-
} else if (stimulus !== void 0 &&
|
|
1200
|
+
} else if (stimulus !== void 0 && _chunkD4TOPSHVcjs.isRecord.call(void 0, stimulus.media) && !_chunkD4TOPSHVcjs.isUnwritten.call(void 0, stimulus.media.type) && stimulus.media.type !== "video") {
|
|
799
1201
|
issues.push(
|
|
800
|
-
|
|
1202
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
801
1203
|
"ig_timeline_stimulus_kind",
|
|
802
1204
|
["stimulus", "media", "type"],
|
|
803
1205
|
"Upload a video file. An embedded player from another site cannot be paused when a quiz opens."
|
|
@@ -806,7 +1208,7 @@ function checkTimeline(draft) {
|
|
|
806
1208
|
}
|
|
807
1209
|
if (draft.shuffle === "within-group") {
|
|
808
1210
|
issues.push(
|
|
809
|
-
|
|
1211
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
810
1212
|
"ig_timeline_shuffle",
|
|
811
1213
|
["shuffle"],
|
|
812
1214
|
"The questions of an interactive video appear in the order their quizzes open, so they cannot be shuffled."
|
|
@@ -816,25 +1218,25 @@ function checkTimeline(draft) {
|
|
|
816
1218
|
const items = Array.isArray(draft.items) ? draft.items : [];
|
|
817
1219
|
const itemIndexById = /* @__PURE__ */ new Map();
|
|
818
1220
|
items.forEach((item, index) => {
|
|
819
|
-
if (!
|
|
1221
|
+
if (!_chunkD4TOPSHVcjs.isRecord.call(void 0, item)) {
|
|
820
1222
|
return;
|
|
821
1223
|
}
|
|
822
1224
|
if (typeof item.id === "string" && item.id !== "") {
|
|
823
1225
|
itemIndexById.set(item.id, index);
|
|
824
1226
|
}
|
|
825
1227
|
const type = item.type;
|
|
826
|
-
if (typeof type === "string" && type !== "" && type !== "item-group" && !
|
|
1228
|
+
if (typeof type === "string" && type !== "" && type !== "item-group" && !_chunk2CV6NU32cjs.isInteractiveVideoItemType.call(void 0, type) && _chunkD4TOPSHVcjs.getActivityTypeDescriptor.call(void 0, type) !== void 0) {
|
|
827
1229
|
issues.push(
|
|
828
|
-
|
|
1230
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
829
1231
|
"ig_timeline_item_type",
|
|
830
1232
|
["items", index, "type"],
|
|
831
|
-
`An interactive video can hold ${
|
|
1233
|
+
`An interactive video can hold ${_chunk2CV6NU32cjs.INTERACTIVE_VIDEO_ITEM_TYPES.join(", ")} questions only.`
|
|
832
1234
|
)
|
|
833
1235
|
);
|
|
834
1236
|
}
|
|
835
|
-
if (type === "dictation" &&
|
|
1237
|
+
if (type === "dictation" && _chunkD4TOPSHVcjs.isUnset.call(void 0, item.media)) {
|
|
836
1238
|
issues.push(
|
|
837
|
-
|
|
1239
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
838
1240
|
"ig_timeline_dictation_media",
|
|
839
1241
|
["items", index, "media"],
|
|
840
1242
|
"Add the recording this dictation plays: inside a video it cannot play the video."
|
|
@@ -846,7 +1248,7 @@ function checkTimeline(draft) {
|
|
|
846
1248
|
const quizIds = /* @__PURE__ */ new Set();
|
|
847
1249
|
const placed = /* @__PURE__ */ new Set();
|
|
848
1250
|
cues.forEach((cue, cueIndex) => {
|
|
849
|
-
if (!
|
|
1251
|
+
if (!_chunkD4TOPSHVcjs.isRecord.call(void 0, cue)) {
|
|
850
1252
|
return;
|
|
851
1253
|
}
|
|
852
1254
|
const at = (field, ...rest) => [
|
|
@@ -856,19 +1258,19 @@ function checkTimeline(draft) {
|
|
|
856
1258
|
field,
|
|
857
1259
|
...rest
|
|
858
1260
|
];
|
|
859
|
-
if (
|
|
860
|
-
issues.push(
|
|
1261
|
+
if (_chunkD4TOPSHVcjs.isMissingId.call(void 0, cue.id)) {
|
|
1262
|
+
issues.push(_chunkD4TOPSHVcjs.issue.call(void 0, "ig_timeline_quiz_id_required", at("id"), "This quiz has no id."));
|
|
861
1263
|
} else if (typeof cue.id === "string") {
|
|
862
1264
|
if (quizIds.has(cue.id)) {
|
|
863
1265
|
issues.push(
|
|
864
|
-
|
|
1266
|
+
_chunkD4TOPSHVcjs.issue.call(void 0, "ig_timeline_quiz_id_duplicate", at("id"), `Two quizzes share the id "${cue.id}".`)
|
|
865
1267
|
);
|
|
866
1268
|
}
|
|
867
1269
|
quizIds.add(cue.id);
|
|
868
1270
|
}
|
|
869
|
-
if (
|
|
1271
|
+
if (_chunkD4TOPSHVcjs.isUnset.call(void 0, cue.at)) {
|
|
870
1272
|
issues.push(
|
|
871
|
-
|
|
1273
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
872
1274
|
"ig_timeline_quiz_time_required",
|
|
873
1275
|
at("at"),
|
|
874
1276
|
"Choose when in the video this quiz opens."
|
|
@@ -876,16 +1278,16 @@ function checkTimeline(draft) {
|
|
|
876
1278
|
);
|
|
877
1279
|
} else if (typeof cue.at !== "number" || !Number.isFinite(cue.at) || cue.at < 0) {
|
|
878
1280
|
issues.push(
|
|
879
|
-
|
|
1281
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
880
1282
|
"ig_timeline_quiz_time_invalid",
|
|
881
1283
|
at("at"),
|
|
882
1284
|
"A quiz opens at a number of seconds, 0 or more."
|
|
883
1285
|
)
|
|
884
1286
|
);
|
|
885
1287
|
}
|
|
886
|
-
if (
|
|
1288
|
+
if (_chunkD4TOPSHVcjs.isUnset.call(void 0, cue.itemIds) || Array.isArray(cue.itemIds) && cue.itemIds.length === 0) {
|
|
887
1289
|
issues.push(
|
|
888
|
-
|
|
1290
|
+
_chunkD4TOPSHVcjs.issue.call(void 0, "ig_timeline_quiz_empty", at("itemIds"), "Add at least one question to this quiz.")
|
|
889
1291
|
);
|
|
890
1292
|
return;
|
|
891
1293
|
}
|
|
@@ -898,7 +1300,7 @@ function checkTimeline(draft) {
|
|
|
898
1300
|
}
|
|
899
1301
|
if (!itemIndexById.has(itemId)) {
|
|
900
1302
|
issues.push(
|
|
901
|
-
|
|
1303
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
902
1304
|
"ig_timeline_quiz_unknown_item",
|
|
903
1305
|
at("itemIds", position),
|
|
904
1306
|
`This quiz names a question that is not in the video ("${itemId}").`
|
|
@@ -906,7 +1308,7 @@ function checkTimeline(draft) {
|
|
|
906
1308
|
);
|
|
907
1309
|
} else if (placed.has(itemId)) {
|
|
908
1310
|
issues.push(
|
|
909
|
-
|
|
1311
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
910
1312
|
"ig_timeline_item_duplicate",
|
|
911
1313
|
at("itemIds", position),
|
|
912
1314
|
"This question is already in a quiz: each question belongs to one quiz."
|
|
@@ -919,7 +1321,7 @@ function checkTimeline(draft) {
|
|
|
919
1321
|
for (const [itemId, index] of itemIndexById) {
|
|
920
1322
|
if (!placed.has(itemId)) {
|
|
921
1323
|
issues.push(
|
|
922
|
-
|
|
1324
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
923
1325
|
"ig_timeline_item_unplaced",
|
|
924
1326
|
["items", index],
|
|
925
1327
|
"Add this question to a quiz, or the video never shows it."
|
|
@@ -930,12 +1332,12 @@ function checkTimeline(draft) {
|
|
|
930
1332
|
const chapters = Array.isArray(timeline.chapters) ? timeline.chapters : [];
|
|
931
1333
|
let previousAt;
|
|
932
1334
|
chapters.forEach((chapter, index) => {
|
|
933
|
-
if (!
|
|
1335
|
+
if (!_chunkD4TOPSHVcjs.isRecord.call(void 0, chapter)) {
|
|
934
1336
|
return;
|
|
935
1337
|
}
|
|
936
|
-
if (
|
|
1338
|
+
if (_chunkD4TOPSHVcjs.isUnwritten.call(void 0, chapter.title)) {
|
|
937
1339
|
issues.push(
|
|
938
|
-
|
|
1340
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
939
1341
|
"ig_timeline_chapter_title",
|
|
940
1342
|
["timeline", "chapters", index, "title"],
|
|
941
1343
|
"Give this chapter a title."
|
|
@@ -945,7 +1347,7 @@ function checkTimeline(draft) {
|
|
|
945
1347
|
if (typeof chapter.at === "number" && Number.isFinite(chapter.at)) {
|
|
946
1348
|
if (previousAt !== void 0 && chapter.at <= previousAt) {
|
|
947
1349
|
issues.push(
|
|
948
|
-
|
|
1350
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
949
1351
|
"ig_timeline_chapter_order",
|
|
950
1352
|
["timeline", "chapters", index, "at"],
|
|
951
1353
|
"Chapters must start in order, each after the one before it."
|
|
@@ -961,7 +1363,7 @@ function checkGroupIdentity(draft) {
|
|
|
961
1363
|
const issues = [];
|
|
962
1364
|
if (draft.schemaVersion !== "1.0") {
|
|
963
1365
|
issues.push(
|
|
964
|
-
|
|
1366
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
965
1367
|
"schema_version_invalid",
|
|
966
1368
|
["schemaVersion"],
|
|
967
1369
|
'The draft must have schemaVersion "1.0". A draft from createItemGroupDraft has it.'
|
|
@@ -969,14 +1371,14 @@ function checkGroupIdentity(draft) {
|
|
|
969
1371
|
);
|
|
970
1372
|
}
|
|
971
1373
|
if (draft.type !== "item-group") {
|
|
972
|
-
issues.push(
|
|
1374
|
+
issues.push(_chunkD4TOPSHVcjs.issue.call(void 0, "type_mismatch", ["type"], `The draft's type must be "item-group".`));
|
|
973
1375
|
}
|
|
974
|
-
if (
|
|
975
|
-
issues.push(
|
|
1376
|
+
if (_chunkD4TOPSHVcjs.isMissingId.call(void 0, draft.id)) {
|
|
1377
|
+
issues.push(_chunkD4TOPSHVcjs.issue.call(void 0, "id_required", ["id"], "The group has no id."));
|
|
976
1378
|
}
|
|
977
|
-
if (!
|
|
1379
|
+
if (!_chunkD4TOPSHVcjs.isUnset.call(void 0, draft.shuffle) && draft.shuffle !== "none" && draft.shuffle !== "within-group") {
|
|
978
1380
|
issues.push(
|
|
979
|
-
|
|
1381
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
980
1382
|
"ig_shuffle_invalid",
|
|
981
1383
|
["shuffle"],
|
|
982
1384
|
'Shuffling is either "none" or "within-group". Leave it out to keep the authored order.'
|
|
@@ -995,13 +1397,13 @@ var MEDIA_FOR_KIND = {
|
|
|
995
1397
|
function checkStimulus(stimulus) {
|
|
996
1398
|
const issues = [];
|
|
997
1399
|
const at = (...rest) => ["stimulus", ...rest];
|
|
998
|
-
if (
|
|
999
|
-
issues.push(
|
|
1400
|
+
if (_chunkD4TOPSHVcjs.isMissingId.call(void 0, stimulus.id)) {
|
|
1401
|
+
issues.push(_chunkD4TOPSHVcjs.issue.call(void 0, "ig_stimulus_id_required", at("id"), "The stimulus has no id."));
|
|
1000
1402
|
}
|
|
1001
1403
|
const kind = stimulus.kind;
|
|
1002
|
-
if (
|
|
1404
|
+
if (_chunkD4TOPSHVcjs.isUnwritten.call(void 0, kind)) {
|
|
1003
1405
|
issues.push(
|
|
1004
|
-
|
|
1406
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1005
1407
|
"ig_stimulus_kind_required",
|
|
1006
1408
|
at("kind"),
|
|
1007
1409
|
"Choose what the questions are about: a text, a recording, a video, an image, or a mix."
|
|
@@ -1010,71 +1412,71 @@ function checkStimulus(stimulus) {
|
|
|
1010
1412
|
} else if (typeof kind !== "string" || !KINDS.has(kind)) {
|
|
1011
1413
|
if (typeof kind === "string") {
|
|
1012
1414
|
issues.push(
|
|
1013
|
-
|
|
1415
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1014
1416
|
"ig_stimulus_kind_invalid",
|
|
1015
1417
|
at("kind"),
|
|
1016
1418
|
`"${kind}" is not a stimulus kind. Use text, audio, video, image or mixed.`
|
|
1017
1419
|
)
|
|
1018
1420
|
);
|
|
1019
1421
|
}
|
|
1020
|
-
if (
|
|
1021
|
-
issues.push(...
|
|
1422
|
+
if (_chunkD4TOPSHVcjs.isRecord.call(void 0, stimulus.media)) {
|
|
1423
|
+
issues.push(..._chunkD4TOPSHVcjs.checkMedia.call(void 0, stimulus.media, at("media")));
|
|
1022
1424
|
}
|
|
1023
1425
|
return issues;
|
|
1024
1426
|
}
|
|
1025
1427
|
const hasBody = typeof stimulus.body === "string" && stimulus.body.trim() !== "";
|
|
1026
|
-
const htmlPresent = !
|
|
1428
|
+
const htmlPresent = !_chunkD4TOPSHVcjs.isUnset.call(void 0, stimulus.bodyHtml);
|
|
1027
1429
|
if (!hasBody && (kind === "text" || kind === "mixed" || htmlPresent)) {
|
|
1028
1430
|
issues.push(
|
|
1029
|
-
|
|
1431
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1030
1432
|
"ig_stimulus_body_required",
|
|
1031
1433
|
at("body"),
|
|
1032
|
-
|
|
1434
|
+
_chunkD4TOPSHVcjs.isUnwritten.call(void 0, stimulus.bodyHtml) ? "Write the passage." : "Write the passage as plain text too. The rich-text version is shown only where a sanitiser is supplied."
|
|
1033
1435
|
)
|
|
1034
1436
|
);
|
|
1035
1437
|
}
|
|
1036
|
-
if (kind !== "text" &&
|
|
1438
|
+
if (kind !== "text" && _chunkD4TOPSHVcjs.isUnset.call(void 0, stimulus.media)) {
|
|
1037
1439
|
issues.push(
|
|
1038
|
-
|
|
1440
|
+
_chunkD4TOPSHVcjs.issue.call(void 0, "ig_stimulus_media_required", at("media"), "Add the recording, video or image.")
|
|
1039
1441
|
);
|
|
1040
|
-
} else if (
|
|
1442
|
+
} else if (_chunkD4TOPSHVcjs.isRecord.call(void 0, stimulus.media)) {
|
|
1041
1443
|
const allowed = MEDIA_FOR_KIND[kind];
|
|
1042
1444
|
const mediaType = stimulus.media.type;
|
|
1043
1445
|
if (allowed !== void 0 && typeof mediaType === "string" && !allowed.includes(mediaType)) {
|
|
1044
1446
|
issues.push(
|
|
1045
|
-
|
|
1447
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1046
1448
|
"ig_stimulus_media_kind",
|
|
1047
1449
|
at("media", "type"),
|
|
1048
1450
|
`A "${kind}" stimulus cannot carry ${mediaType} media. Use ${allowed.join(" or ")}.`
|
|
1049
1451
|
)
|
|
1050
1452
|
);
|
|
1051
1453
|
}
|
|
1052
|
-
issues.push(...
|
|
1454
|
+
issues.push(..._chunkD4TOPSHVcjs.checkMedia.call(void 0, stimulus.media, at("media")));
|
|
1053
1455
|
}
|
|
1054
1456
|
return issues;
|
|
1055
1457
|
}
|
|
1056
1458
|
function checkItems(draft) {
|
|
1057
1459
|
const issues = [];
|
|
1058
|
-
const items =
|
|
1460
|
+
const items = _chunkD4TOPSHVcjs.isUnset.call(void 0, draft.items) ? [] : draft.items;
|
|
1059
1461
|
if (!Array.isArray(items)) {
|
|
1060
1462
|
return issues;
|
|
1061
1463
|
}
|
|
1062
1464
|
if (items.length === 0) {
|
|
1063
1465
|
issues.push(
|
|
1064
|
-
|
|
1466
|
+
_chunkD4TOPSHVcjs.issue.call(void 0, "ig_items_required", ["items"], "Add at least one question about this material.")
|
|
1065
1467
|
);
|
|
1066
1468
|
return issues;
|
|
1067
1469
|
}
|
|
1068
1470
|
const seen = /* @__PURE__ */ new Set();
|
|
1069
1471
|
const repeated = /* @__PURE__ */ new Set();
|
|
1070
1472
|
for (const [index, item] of items.entries()) {
|
|
1071
|
-
if (!
|
|
1473
|
+
if (!_chunkD4TOPSHVcjs.isRecord.call(void 0, item)) {
|
|
1072
1474
|
continue;
|
|
1073
1475
|
}
|
|
1074
1476
|
const ordinal = index + 1;
|
|
1075
|
-
if (
|
|
1477
|
+
if (_chunkD4TOPSHVcjs.isMissingId.call(void 0, item.id)) {
|
|
1076
1478
|
issues.push(
|
|
1077
|
-
|
|
1479
|
+
_chunkD4TOPSHVcjs.issue.call(void 0, "ig_item_id_required", ["items", index, "id"], `Question ${ordinal} has no id.`)
|
|
1078
1480
|
);
|
|
1079
1481
|
} else if (typeof item.id === "string") {
|
|
1080
1482
|
if (seen.has(item.id)) {
|
|
@@ -1084,7 +1486,7 @@ function checkItems(draft) {
|
|
|
1084
1486
|
}
|
|
1085
1487
|
if (item.type === "item-group") {
|
|
1086
1488
|
issues.push(
|
|
1087
|
-
|
|
1489
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1088
1490
|
"ig_item_nested_group",
|
|
1089
1491
|
["items", index, "type"],
|
|
1090
1492
|
"Groups do not nest: every item must be an activity."
|
|
@@ -1092,9 +1494,9 @@ function checkItems(draft) {
|
|
|
1092
1494
|
);
|
|
1093
1495
|
continue;
|
|
1094
1496
|
}
|
|
1095
|
-
if (
|
|
1497
|
+
if (_chunkD4TOPSHVcjs.isUnwritten.call(void 0, item.type)) {
|
|
1096
1498
|
issues.push(
|
|
1097
|
-
|
|
1499
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1098
1500
|
"ig_item_type_required",
|
|
1099
1501
|
["items", index, "type"],
|
|
1100
1502
|
`Choose what kind of question ${ordinal} is.`
|
|
@@ -1109,11 +1511,11 @@ function checkItems(draft) {
|
|
|
1109
1511
|
try {
|
|
1110
1512
|
result = validateDraft(item.type, item);
|
|
1111
1513
|
} catch (error) {
|
|
1112
|
-
if (!(error instanceof
|
|
1514
|
+
if (!(error instanceof _chunkD4TOPSHVcjs.UnknownActivityTypeError) || error.activityType !== item.type) {
|
|
1113
1515
|
throw error;
|
|
1114
1516
|
}
|
|
1115
1517
|
issues.push(
|
|
1116
|
-
|
|
1518
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1117
1519
|
"ig_item_type_unknown",
|
|
1118
1520
|
["items", index, "type"],
|
|
1119
1521
|
`"${item.type}" is not a registered activity type.`
|
|
@@ -1127,7 +1529,7 @@ function checkItems(draft) {
|
|
|
1127
1529
|
}
|
|
1128
1530
|
for (const id of repeated) {
|
|
1129
1531
|
issues.push(
|
|
1130
|
-
|
|
1532
|
+
_chunkD4TOPSHVcjs.issue.call(void 0, "ig_item_id_duplicate", ["items"], `More than one question has the id "${id}".`)
|
|
1131
1533
|
);
|
|
1132
1534
|
}
|
|
1133
1535
|
return issues;
|
|
@@ -1135,30 +1537,30 @@ function checkItems(draft) {
|
|
|
1135
1537
|
|
|
1136
1538
|
// src/authoring/index.ts
|
|
1137
1539
|
function validateDraft(type, draft) {
|
|
1138
|
-
return
|
|
1540
|
+
return _chunkD4TOPSHVcjs.withValidationScope.call(void 0, () => validateDraftInScope(type, draft));
|
|
1139
1541
|
}
|
|
1140
1542
|
function validateDraftInScope(type, draft) {
|
|
1141
|
-
const descriptor =
|
|
1543
|
+
const descriptor = _chunkD4TOPSHVcjs.getActivityTypeDescriptor.call(void 0, type);
|
|
1142
1544
|
if (descriptor === void 0) {
|
|
1143
|
-
throw new (0,
|
|
1545
|
+
throw new (0, _chunkD4TOPSHVcjs.UnknownActivityTypeError)(String(type));
|
|
1144
1546
|
}
|
|
1145
|
-
const reported =
|
|
1547
|
+
const reported = _chunkD4TOPSHVcjs.isRecord.call(void 0, draft) && _optionalChain([descriptor, 'access', _44 => _44.authoring, 'optionalAccess', _45 => _45.checkDraft]) !== void 0 ? descriptor.authoring.checkDraft(draft).map(normalise) : [];
|
|
1146
1548
|
const issues = [...reported];
|
|
1147
1549
|
const parsed = descriptor.schema.safeParse(draft, { reportInput: true });
|
|
1148
1550
|
if (!parsed.success) {
|
|
1149
|
-
const covered =
|
|
1551
|
+
const covered = _chunkD4TOPSHVcjs.coveredPathsOf.call(void 0, reported);
|
|
1150
1552
|
const reportedEmpty = /* @__PURE__ */ new Set();
|
|
1151
1553
|
for (const schemaIssue of parsed.error.issues) {
|
|
1152
1554
|
const path = schemaIssue.path.map(String);
|
|
1153
|
-
if (covered.has(
|
|
1555
|
+
if (covered.has(_chunkD4TOPSHVcjs.pathKey.call(void 0, path))) {
|
|
1154
1556
|
continue;
|
|
1155
1557
|
}
|
|
1156
|
-
if (path.length > 0 &&
|
|
1558
|
+
if (path.length > 0 && _chunkD4TOPSHVcjs.refusesEmpty.call(void 0, draft, schemaIssue)) {
|
|
1157
1559
|
const key = JSON.stringify(path);
|
|
1158
1560
|
if (!reportedEmpty.has(key)) {
|
|
1159
1561
|
reportedEmpty.add(key);
|
|
1160
1562
|
issues.push(
|
|
1161
|
-
|
|
1563
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1162
1564
|
"null_not_allowed",
|
|
1163
1565
|
path,
|
|
1164
1566
|
typeof schemaIssue.path.at(-1) === "number" ? "This entry has no value. Remove it, or fill it in." : "This field cannot be null. Leave it out if it is optional, or give it a value."
|
|
@@ -1182,11 +1584,11 @@ function validateDraftInScope(type, draft) {
|
|
|
1182
1584
|
return { status: invalid ? "invalid" : "incomplete", issues };
|
|
1183
1585
|
}
|
|
1184
1586
|
function createDraft(type, context) {
|
|
1185
|
-
const descriptor =
|
|
1587
|
+
const descriptor = _chunkD4TOPSHVcjs.getActivityTypeDescriptor.call(void 0, type);
|
|
1186
1588
|
if (descriptor === void 0) {
|
|
1187
|
-
throw new (0,
|
|
1589
|
+
throw new (0, _chunkD4TOPSHVcjs.UnknownActivityTypeError)(String(type));
|
|
1188
1590
|
}
|
|
1189
|
-
const create = _optionalChain([descriptor, 'access',
|
|
1591
|
+
const create = _optionalChain([descriptor, 'access', _46 => _46.authoring, 'optionalAccess', _47 => _47.createDraft]);
|
|
1190
1592
|
if (create === void 0) {
|
|
1191
1593
|
throw new Error(
|
|
1192
1594
|
`Activity type "${String(type)}" declares no authoring.createDraft, so there is no empty draft to create. Build the draft yourself; validateDraft works for every registered type.`
|
|
@@ -1209,7 +1611,7 @@ function createDraft(type, context) {
|
|
|
1209
1611
|
return create({ newId });
|
|
1210
1612
|
}
|
|
1211
1613
|
function normalise(found) {
|
|
1212
|
-
const documented = Object.hasOwn(
|
|
1614
|
+
const documented = Object.hasOwn(_chunkD4TOPSHVcjs.DRAFT_ISSUE_SEVERITY, found.code) ? _chunkD4TOPSHVcjs.DRAFT_ISSUE_SEVERITY[found.code] : void 0;
|
|
1213
1615
|
return {
|
|
1214
1616
|
...found,
|
|
1215
1617
|
path: found.path.map(String),
|
|
@@ -1218,11 +1620,11 @@ function normalise(found) {
|
|
|
1218
1620
|
}
|
|
1219
1621
|
|
|
1220
1622
|
// src/redact.ts
|
|
1221
|
-
function mergePolicy(
|
|
1623
|
+
function mergePolicy(base2, overrides) {
|
|
1222
1624
|
if (overrides === void 0) {
|
|
1223
|
-
return
|
|
1625
|
+
return base2;
|
|
1224
1626
|
}
|
|
1225
|
-
const merged = { ...
|
|
1627
|
+
const merged = { ...base2 };
|
|
1226
1628
|
for (const [key, override] of Object.entries(overrides)) {
|
|
1227
1629
|
const current = merged[key];
|
|
1228
1630
|
merged[key] = typeof override === "object" && typeof current === "object" ? { ...current, ...override } : override;
|
|
@@ -1273,9 +1675,9 @@ function redactValue(value, policy, reveal) {
|
|
|
1273
1675
|
}
|
|
1274
1676
|
function redact(data, options = {}) {
|
|
1275
1677
|
const reveal = _nullishCoalesce(options.reveal, () => ( "none"));
|
|
1276
|
-
const descriptor =
|
|
1678
|
+
const descriptor = _chunkD4TOPSHVcjs.getActivityTypeDescriptor.call(void 0, data.type);
|
|
1277
1679
|
if (descriptor === void 0) {
|
|
1278
|
-
throw new (0,
|
|
1680
|
+
throw new (0, _chunkD4TOPSHVcjs.UnknownActivityTypeError)(String(data.type));
|
|
1279
1681
|
}
|
|
1280
1682
|
if (descriptor.fieldPolicy === void 0) {
|
|
1281
1683
|
throw new Error(
|
|
@@ -1288,7 +1690,7 @@ function redact(data, options = {}) {
|
|
|
1288
1690
|
if (reveal === "none" && descriptor.redactedSchema !== void 0) {
|
|
1289
1691
|
const parsed = descriptor.redactedSchema.safeParse(result);
|
|
1290
1692
|
if (!parsed.success) {
|
|
1291
|
-
throw new (0,
|
|
1693
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)(
|
|
1292
1694
|
descriptor.type,
|
|
1293
1695
|
parsed.error.issues.map((issue2) => ({
|
|
1294
1696
|
path: issue2.path.map(String),
|
|
@@ -1302,13 +1704,13 @@ function redact(data, options = {}) {
|
|
|
1302
1704
|
}
|
|
1303
1705
|
function assertRedacted(data) {
|
|
1304
1706
|
if (typeof data !== "object" || data === null) {
|
|
1305
|
-
throw new (0,
|
|
1707
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)("unknown", [
|
|
1306
1708
|
{ path: [], message: "Redacted activity data must be an object.", code: "invalid_type" }
|
|
1307
1709
|
]);
|
|
1308
1710
|
}
|
|
1309
1711
|
const candidate = data;
|
|
1310
1712
|
if (candidate.redacted !== true) {
|
|
1311
|
-
throw new (0,
|
|
1713
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)(String(_nullishCoalesce(candidate.type, () => ( "unknown"))), [
|
|
1312
1714
|
{
|
|
1313
1715
|
path: ["redacted"],
|
|
1314
1716
|
message: "Missing redacted marker \u2014 this payload is not a redact() projection.",
|
|
@@ -1317,12 +1719,12 @@ function assertRedacted(data) {
|
|
|
1317
1719
|
]);
|
|
1318
1720
|
}
|
|
1319
1721
|
const type = typeof candidate.type === "string" ? candidate.type : "";
|
|
1320
|
-
const descriptor =
|
|
1722
|
+
const descriptor = _chunkD4TOPSHVcjs.getActivityTypeDescriptor.call(void 0, type);
|
|
1321
1723
|
if (descriptor === void 0) {
|
|
1322
|
-
throw new (0,
|
|
1724
|
+
throw new (0, _chunkD4TOPSHVcjs.UnknownActivityTypeError)(type);
|
|
1323
1725
|
}
|
|
1324
1726
|
if (descriptor.redactedSchema === void 0) {
|
|
1325
|
-
throw new (0,
|
|
1727
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)(descriptor.type, [
|
|
1326
1728
|
{
|
|
1327
1729
|
path: [],
|
|
1328
1730
|
message: `Activity type "${descriptor.type}" registers no redactedSchema; assertRedacted cannot prove this payload is learner-safe.`,
|
|
@@ -1332,7 +1734,7 @@ function assertRedacted(data) {
|
|
|
1332
1734
|
}
|
|
1333
1735
|
const parsed = descriptor.redactedSchema.safeParse(candidate);
|
|
1334
1736
|
if (!parsed.success) {
|
|
1335
|
-
throw new (0,
|
|
1737
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)(
|
|
1336
1738
|
descriptor.type,
|
|
1337
1739
|
parsed.error.issues.map((issue2) => ({
|
|
1338
1740
|
path: issue2.path.map(String),
|
|
@@ -1348,7 +1750,7 @@ var STIMULUS_FIELD_POLICY = {
|
|
|
1348
1750
|
title: "public",
|
|
1349
1751
|
body: "public",
|
|
1350
1752
|
bodyHtml: "public",
|
|
1351
|
-
media:
|
|
1753
|
+
media: _chunkD4TOPSHVcjs.MEDIA_FIELD_POLICY,
|
|
1352
1754
|
locale: "public",
|
|
1353
1755
|
attribution: "public",
|
|
1354
1756
|
transcript: "author-only"
|
|
@@ -1392,9 +1794,9 @@ function redactItemGroup(group, options = {}) {
|
|
|
1392
1794
|
redacted: true
|
|
1393
1795
|
};
|
|
1394
1796
|
if (reveal === "none") {
|
|
1395
|
-
const parsed =
|
|
1797
|
+
const parsed = _chunk2CV6NU32cjs.RedactedItemGroupSchema.safeParse(result);
|
|
1396
1798
|
if (!parsed.success) {
|
|
1397
|
-
throw new (0,
|
|
1799
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)(
|
|
1398
1800
|
"item-group",
|
|
1399
1801
|
parsed.error.issues.map((issue2) => ({
|
|
1400
1802
|
path: issue2.path.map(String),
|
|
@@ -1408,13 +1810,13 @@ function redactItemGroup(group, options = {}) {
|
|
|
1408
1810
|
}
|
|
1409
1811
|
function assertRedactedItemGroup(data) {
|
|
1410
1812
|
if (typeof data !== "object" || data === null) {
|
|
1411
|
-
throw new (0,
|
|
1813
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)("item-group", [
|
|
1412
1814
|
{ path: [], message: "Redacted item group must be an object.", code: "invalid_type" }
|
|
1413
1815
|
]);
|
|
1414
1816
|
}
|
|
1415
1817
|
const candidate = data;
|
|
1416
1818
|
if (candidate.redacted !== true) {
|
|
1417
|
-
throw new (0,
|
|
1819
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)("item-group", [
|
|
1418
1820
|
{
|
|
1419
1821
|
path: ["redacted"],
|
|
1420
1822
|
message: "Missing redacted marker \u2014 this payload is not a redactItemGroup() projection.",
|
|
@@ -1422,9 +1824,9 @@ function assertRedactedItemGroup(data) {
|
|
|
1422
1824
|
}
|
|
1423
1825
|
]);
|
|
1424
1826
|
}
|
|
1425
|
-
const parsed =
|
|
1827
|
+
const parsed = _chunk2CV6NU32cjs.RedactedItemGroupSchema.safeParse(candidate);
|
|
1426
1828
|
if (!parsed.success) {
|
|
1427
|
-
throw new (0,
|
|
1829
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)(
|
|
1428
1830
|
"item-group",
|
|
1429
1831
|
parsed.error.issues.map((issue2) => ({
|
|
1430
1832
|
path: issue2.path.map(String),
|
|
@@ -1437,8 +1839,8 @@ function assertRedactedItemGroup(data) {
|
|
|
1437
1839
|
try {
|
|
1438
1840
|
assertRedacted(item);
|
|
1439
1841
|
} catch (error) {
|
|
1440
|
-
if (error instanceof
|
|
1441
|
-
throw new (0,
|
|
1842
|
+
if (error instanceof _chunkD4TOPSHVcjs.ActivitySchemaError) {
|
|
1843
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)(
|
|
1442
1844
|
"item-group",
|
|
1443
1845
|
error.errors.map((issue2) => ({
|
|
1444
1846
|
...issue2,
|
|
@@ -1461,7 +1863,7 @@ function readMediaProgress(value, duration) {
|
|
|
1461
1863
|
return null;
|
|
1462
1864
|
}
|
|
1463
1865
|
({ progressVersion: version, at, furthest } = value);
|
|
1464
|
-
} catch (
|
|
1866
|
+
} catch (e2) {
|
|
1465
1867
|
return null;
|
|
1466
1868
|
}
|
|
1467
1869
|
if (version !== "1.0" || typeof at !== "number" || !Number.isFinite(at)) {
|
|
@@ -1483,7 +1885,7 @@ function composeTimelineScore(entryKey, items, policy) {
|
|
|
1483
1885
|
`composeTimelineScore: no scored item belongs to entry "${entryKey}". Pass the video's slotKey (or its position in the sequence), and the items of the attempt that holds it.`
|
|
1484
1886
|
);
|
|
1485
1887
|
}
|
|
1486
|
-
return
|
|
1888
|
+
return _chunkXNMKDFPWcjs.composeAssessmentScore.call(void 0, [{ id: entryKey, weight: 1, items: own }], policy);
|
|
1487
1889
|
}
|
|
1488
1890
|
|
|
1489
1891
|
|
|
@@ -1631,5 +2033,19 @@ function composeTimelineScore(entryKey, items, policy) {
|
|
|
1631
2033
|
|
|
1632
2034
|
|
|
1633
2035
|
|
|
1634
|
-
|
|
2036
|
+
|
|
2037
|
+
|
|
2038
|
+
|
|
2039
|
+
|
|
2040
|
+
|
|
2041
|
+
|
|
2042
|
+
|
|
2043
|
+
|
|
2044
|
+
|
|
2045
|
+
|
|
2046
|
+
|
|
2047
|
+
|
|
2048
|
+
|
|
2049
|
+
|
|
2050
|
+
exports.AI_EXPLANATION_TYPES = AI_EXPLANATION_TYPES; exports.AI_HINT_TYPES = AI_HINT_TYPES; exports.AI_TEXT_MAX_LENGTH = AI_TEXT_MAX_LENGTH; exports.ActivitySchemaError = _chunkD4TOPSHVcjs.ActivitySchemaError; exports.AiPermissionsSchema = _chunkD4TOPSHVcjs.AiPermissionsSchema; exports.BlankConfigSchema = _chunkD4TOPSHVcjs.BlankConfigSchema; exports.DEFAULT_PASS_THRESHOLD = _chunkXNMKDFPWcjs.DEFAULT_PASS_THRESHOLD; exports.DICTATION_MAX_ACCEPTED_TRANSCRIPTS = _chunkD4TOPSHVcjs.DICTATION_MAX_ACCEPTED_TRANSCRIPTS; exports.DICTATION_MAX_EQUIVALENCES = _chunkD4TOPSHVcjs.DICTATION_MAX_EQUIVALENCES; exports.DICTATION_MAX_EQUIVALENCE_LENGTH = _chunkD4TOPSHVcjs.DICTATION_MAX_EQUIVALENCE_LENGTH; exports.DICTATION_MAX_TEXT_LENGTH = _chunkD4TOPSHVcjs.DICTATION_MAX_TEXT_LENGTH; exports.DICTATION_MAX_TRANSCRIPT_LENGTH = _chunkD4TOPSHVcjs.DICTATION_MAX_TRANSCRIPT_LENGTH; exports.DeferredScoringError = _chunkD4TOPSHVcjs.DeferredScoringError; exports.DictationDataSchema = _chunkD4TOPSHVcjs.DictationDataSchema; exports.DictationEquivalenceSchema = _chunkD4TOPSHVcjs.DictationEquivalenceSchema; exports.DictationSlowMediaSchema = _chunkD4TOPSHVcjs.DictationSlowMediaSchema; exports.DictationToleranceSchema = _chunkD4TOPSHVcjs.DictationToleranceSchema; exports.FeedbackSchema = _chunkD4TOPSHVcjs.FeedbackSchema; exports.FillInTheBlanksDataSchema = _chunkD4TOPSHVcjs.FillInTheBlanksDataSchema; exports.GapSelectBankSchema = _chunkD4TOPSHVcjs.GapSelectBankSchema; exports.GapSelectChoiceSchema = _chunkD4TOPSHVcjs.GapSelectChoiceSchema; exports.GapSelectDataSchema = _chunkD4TOPSHVcjs.GapSelectDataSchema; exports.GapSelectGapSchema = _chunkD4TOPSHVcjs.GapSelectGapSchema; exports.INTERACTIVE_VIDEO_ITEM_TYPES = _chunk2CV6NU32cjs.INTERACTIVE_VIDEO_ITEM_TYPES; exports.ItemGroupSchema = _chunk2CV6NU32cjs.ItemGroupSchema; exports.MediaPlaybackSchema = _chunkD4TOPSHVcjs.MediaPlaybackSchema; exports.MediaSchema = _chunkD4TOPSHVcjs.MediaSchema; exports.MediaTimelineSchema = _chunk2CV6NU32cjs.MediaTimelineSchema; exports.MediaTrackSchema = _chunkD4TOPSHVcjs.MediaTrackSchema; exports.MediaUrlSchema = _chunkD4TOPSHVcjs.MediaUrlSchema; exports.MultipleChoiceDataSchema = _chunkD4TOPSHVcjs.MultipleChoiceDataSchema; exports.MultipleChoiceOptionMediaSchema = _chunkD4TOPSHVcjs.MultipleChoiceOptionMediaSchema; exports.MultipleChoiceOptionSchema = _chunkD4TOPSHVcjs.MultipleChoiceOptionSchema; exports.NativeControlHintSchema = _chunkD4TOPSHVcjs.NativeControlHintSchema; exports.READ_ALOUD_MAX_DIMENSION_WEIGHT = _chunkD4TOPSHVcjs.READ_ALOUD_MAX_DIMENSION_WEIGHT; exports.READ_ALOUD_MAX_REFERENCE_LENGTH = _chunkD4TOPSHVcjs.READ_ALOUD_MAX_REFERENCE_LENGTH; exports.READ_ALOUD_MAX_SECONDS = _chunkD4TOPSHVcjs.READ_ALOUD_MAX_SECONDS; exports.READ_ALOUD_MAX_TAKES = _chunkD4TOPSHVcjs.READ_ALOUD_MAX_TAKES; exports.ReadAloudDataSchema = _chunkD4TOPSHVcjs.ReadAloudDataSchema; exports.ReadAloudSlowMediaSchema = _chunkD4TOPSHVcjs.ReadAloudSlowMediaSchema; exports.RedactedBlankConfigSchema = _chunkD4TOPSHVcjs.RedactedBlankConfigSchema; exports.RedactedDictationDataSchema = _chunkD4TOPSHVcjs.RedactedDictationDataSchema; exports.RedactedDictationSlowMediaSchema = _chunkD4TOPSHVcjs.RedactedDictationSlowMediaSchema; exports.RedactedFillInTheBlanksDataSchema = _chunkD4TOPSHVcjs.RedactedFillInTheBlanksDataSchema; exports.RedactedGapSelectBankSchema = _chunkD4TOPSHVcjs.RedactedGapSelectBankSchema; exports.RedactedGapSelectChoiceSchema = _chunkD4TOPSHVcjs.RedactedGapSelectChoiceSchema; exports.RedactedGapSelectDataSchema = _chunkD4TOPSHVcjs.RedactedGapSelectDataSchema; exports.RedactedGapSelectGapSchema = _chunkD4TOPSHVcjs.RedactedGapSelectGapSchema; exports.RedactedItemGroupSchema = _chunk2CV6NU32cjs.RedactedItemGroupSchema; exports.RedactedMediaSchema = _chunkD4TOPSHVcjs.RedactedMediaSchema; exports.RedactedMultipleChoiceDataSchema = _chunkD4TOPSHVcjs.RedactedMultipleChoiceDataSchema; exports.RedactedMultipleChoiceOptionMediaSchema = _chunkD4TOPSHVcjs.RedactedMultipleChoiceOptionMediaSchema; exports.RedactedMultipleChoiceOptionSchema = _chunkD4TOPSHVcjs.RedactedMultipleChoiceOptionSchema; exports.RedactedReadAloudDataSchema = _chunkD4TOPSHVcjs.RedactedReadAloudDataSchema; exports.RedactedScoringError = _chunkD4TOPSHVcjs.RedactedScoringError; exports.RedactedStimulusSchema = _chunk2CV6NU32cjs.RedactedStimulusSchema; exports.RedactedWrittenResponseDataSchema = _chunkD4TOPSHVcjs.RedactedWrittenResponseDataSchema; exports.SPEECH_ASSESSMENT_MAX_WORDS = _chunkD4TOPSHVcjs.SPEECH_ASSESSMENT_MAX_WORDS; exports.StimulusSchema = _chunk2CV6NU32cjs.StimulusSchema; exports.TIMELINE_MAX_CHAPTERS = _chunk2CV6NU32cjs.TIMELINE_MAX_CHAPTERS; exports.TIMELINE_MAX_ITEMS = _chunk2CV6NU32cjs.TIMELINE_MAX_ITEMS; exports.TIMELINE_MAX_QUIZZES = _chunk2CV6NU32cjs.TIMELINE_MAX_QUIZZES; exports.TIMELINE_MAX_TITLE_LENGTH = _chunk2CV6NU32cjs.TIMELINE_MAX_TITLE_LENGTH; exports.TextMatchPolicySchema = _chunkD4TOPSHVcjs.TextMatchPolicySchema; exports.TimelineChapterSchema = _chunk2CV6NU32cjs.TimelineChapterSchema; exports.TimelineCueSchema = _chunk2CV6NU32cjs.TimelineCueSchema; exports.UnknownActivityTypeError = _chunkD4TOPSHVcjs.UnknownActivityTypeError; exports.WrittenResponseDataSchema = _chunkD4TOPSHVcjs.WrittenResponseDataSchema; exports.WrittenResponseRubricCriterionSchema = _chunkD4TOPSHVcjs.WrittenResponseRubricCriterionSchema; exports.WrittenResponseRubricSchema = _chunkD4TOPSHVcjs.WrittenResponseRubricSchema; exports.XAPIVerb = _chunkEOFWSGLUcjs.XAPIVerb; exports.XAPI_VERB_DISPLAY = _chunkEOFWSGLUcjs.XAPI_VERB_DISPLAY; exports.aiAllowedByContent = aiAllowedByContent; exports.aiExplanationRequest = aiExplanationRequest; exports.aiGradeOf = aiGradeOf; exports.aiHintRequest = aiHintRequest; exports.aiSupports = aiSupports; exports.alignDictation = _chunkD4TOPSHVcjs.alignDictation; exports.alignReadAloud = _chunkXNMKDFPWcjs.alignReadAloud; exports.assertRedacted = assertRedacted; exports.assertRedactedItemGroup = assertRedactedItemGroup; exports.buildAiFacts = buildAiFacts; exports.canonicalJson = canonicalJson; exports.checkAiExplanation = checkAiExplanation; exports.checkAiHint = checkAiHint; exports.classifyBand = _chunkXNMKDFPWcjs.classifyBand; exports.composeAssessmentScore = _chunkXNMKDFPWcjs.composeAssessmentScore; exports.composeTimelineScore = composeTimelineScore; exports.computePassThreshold = _chunkXNMKDFPWcjs.computePassThreshold; exports.contentHash = contentHash; exports.countWords = _chunkD4TOPSHVcjs.countWords; exports.createDraft = createDraft; exports.createInteractiveVideoDraft = createInteractiveVideoDraft; exports.createItemGroupDraft = createItemGroupDraft; exports.defineActivityType = _chunkD4TOPSHVcjs.defineActivityType; exports.dictationJsonSchema = _chunk2CV6NU32cjs.dictationJsonSchema; exports.dictationReferenceWords = _chunkD4TOPSHVcjs.dictationReferenceWords; exports.dictationType = _chunkD4TOPSHVcjs.dictationType; exports.diffDictationChars = _chunkXNMKDFPWcjs.diffDictationChars; exports.diffResponses = diffResponses; exports.entryKeyOf = entryKeyOf; exports.evaluate = _chunkXNMKDFPWcjs.evaluate; exports.fillInTheBlanksJsonSchema = _chunk2CV6NU32cjs.fillInTheBlanksJsonSchema; exports.fillInTheBlanksType = _chunkD4TOPSHVcjs.fillInTheBlanksType; exports.fingerprint = fingerprint; exports.flattenSequence = flattenSequence; exports.gapSelectJsonSchema = _chunk2CV6NU32cjs.gapSelectJsonSchema; exports.gapSelectType = _chunkD4TOPSHVcjs.gapSelectType; exports.getActivityTypeDescriptor = _chunkD4TOPSHVcjs.getActivityTypeDescriptor; exports.gradeFromRubric = _chunkXNMKDFPWcjs.gradeFromRubric; exports.gradeReadAloud = _chunkXNMKDFPWcjs.gradeReadAloud; exports.gte = _chunkXNMKDFPWcjs.gte; exports.hasGrade = _chunkXNMKDFPWcjs.hasGrade; exports.hashSeed = hashSeed; exports.hintRevealsAnswer = hintRevealsAnswer; exports.inspectWav = _chunkXNMKDFPWcjs.inspectWav; exports.isInteractiveVideoItemType = _chunk2CV6NU32cjs.isInteractiveVideoItemType; exports.isItemGroup = isItemGroup; exports.itemGroupJsonSchema = _chunk2CV6NU32cjs.itemGroupJsonSchema; exports.jsonSchemaFor = _chunk2CV6NU32cjs.jsonSchemaFor; exports.levenshteinDistance = _chunkD4TOPSHVcjs.levenshteinDistance; exports.matchText = _chunkD4TOPSHVcjs.matchText; exports.multipleChoiceJsonSchema = _chunk2CV6NU32cjs.multipleChoiceJsonSchema; exports.multipleChoiceType = _chunkD4TOPSHVcjs.multipleChoiceType; exports.outcomeFromGrade = _chunkXNMKDFPWcjs.outcomeFromGrade; exports.outcomeFromUnscorable = _chunkXNMKDFPWcjs.outcomeFromUnscorable; exports.planAttempt = planAttempt; exports.planMediaBudgets = planMediaBudgets; exports.readAiTextResult = readAiTextResult; exports.readAloudJsonSchema = _chunk2CV6NU32cjs.readAloudJsonSchema; exports.readAloudType = _chunkD4TOPSHVcjs.readAloudType; exports.readMediaProgress = readMediaProgress; exports.redact = redact; exports.redactItemGroup = redactItemGroup; exports.registerActivityType = _chunkD4TOPSHVcjs.registerActivityType; exports.registeredActivityTypes = _chunkD4TOPSHVcjs.registeredActivityTypes; exports.resolvePlaybackPolicy = resolvePlaybackPolicy; exports.restoreAttemptState = restoreAttemptState; exports.restoreMediaPlayLedger = restoreMediaPlayLedger; exports.roundGrade = _chunkXNMKDFPWcjs.roundGrade; exports.score = _chunkXNMKDFPWcjs.score; exports.scoredItemsFromPlan = scoredItemsFromPlan; exports.seededShuffle = seededShuffle; exports.serializeAttemptState = serializeAttemptState; exports.serializeMediaPlayLedger = serializeMediaPlayLedger; exports.slotMediaKey = slotMediaKey; exports.stimulusJsonSchema = _chunk2CV6NU32cjs.stimulusJsonSchema; exports.stimulusMediaKey = stimulusMediaKey; exports.validateActivity = _chunk2CV6NU32cjs.validateActivity; exports.validateDraft = validateDraft; exports.validateItemGroup = _chunk2CV6NU32cjs.validateItemGroup; exports.validateItemGroupDraft = validateItemGroupDraft; exports.validateSpeechAssessment = _chunkXNMKDFPWcjs.validateSpeechAssessment; exports.validateXAPIStatement = _chunkEOFWSGLUcjs.validateXAPIStatement; exports.verifyAttemptPlan = verifyAttemptPlan; exports.writtenResponseJsonSchema = _chunk2CV6NU32cjs.writtenResponseJsonSchema; exports.writtenResponseType = _chunkD4TOPSHVcjs.writtenResponseType; exports.xAPIBuilder = _chunkEOFWSGLUcjs.xAPIBuilder; exports.xapiDefinitionFor = _chunkEOFWSGLUcjs.xapiDefinitionFor;
|
|
1635
2051
|
//# sourceMappingURL=index.cjs.map
|