@intellectif/lk-core 0.16.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 +45 -0
- package/dist/{activity-DcxtpX7Z.d.cts → activity-BmjBjXVJ.d.cts} +213 -2
- package/dist/{activity-DcxtpX7Z.d.ts → activity-BmjBjXVJ.d.ts} +213 -2
- package/dist/{chunk-FJJ2GVBA.cjs → chunk-2CV6NU32.cjs} +19 -19
- package/dist/{chunk-FJJ2GVBA.cjs.map → chunk-2CV6NU32.cjs.map} +1 -1
- package/dist/{chunk-IRUD73IQ.js → chunk-D3GP5MET.js} +683 -638
- package/dist/chunk-D3GP5MET.js.map +1 -0
- package/dist/{chunk-F7UOLKWV.cjs → chunk-D4TOPSHV.cjs} +518 -473
- package/dist/chunk-D4TOPSHV.cjs.map +1 -0
- package/dist/{chunk-VFTVZJO5.cjs → chunk-EOFWSGLU.cjs} +4 -4
- package/dist/{chunk-VFTVZJO5.cjs.map → chunk-EOFWSGLU.cjs.map} +1 -1
- package/dist/{chunk-S63IOKFP.js → chunk-WXS5EB65.js} +2 -2
- package/dist/{chunk-OXF7VT7S.js → chunk-X5DAXBJI.js} +2 -2
- package/dist/{chunk-6P6XK2LI.cjs → chunk-XNMKDFPW.cjs} +31 -31
- package/dist/{chunk-6P6XK2LI.cjs.map → chunk-XNMKDFPW.cjs.map} +1 -1
- package/dist/{chunk-GOZGBVJP.js → chunk-Z7QQZ53L.js} +2 -2
- package/dist/{chunk-GOZGBVJP.js.map → chunk-Z7QQZ53L.js.map} +1 -1
- package/dist/{index-BWpwZRQw.d.cts → index-CvfeD_cU.d.cts} +144 -86
- package/dist/{index-DRJqwO2y.d.ts → index-G_KusUcK.d.ts} +144 -86
- package/dist/index.cjs +542 -127
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +122 -5
- package/dist/index.d.ts +122 -5
- package/dist/index.js +422 -7
- 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-F7UOLKWV.cjs.map +0 -1
- package/dist/chunk-IRUD73IQ.js.map +0 -1
- /package/dist/{chunk-S63IOKFP.js.map → chunk-WXS5EB65.js.map} +0 -0
- /package/dist/{chunk-OXF7VT7S.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 _chunkVFTVZJO5cjs = require('./chunk-VFTVZJO5.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 _chunkFJJ2GVBAcjs = require('./chunk-FJJ2GVBA.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,26 +1135,26 @@ function validateItemGroupDraftInScope(draft) {
|
|
|
734
1135
|
if (draft.timeline !== void 0 && draft.timeline !== null) {
|
|
735
1136
|
issues.push(...checkTimeline(draft));
|
|
736
1137
|
}
|
|
737
|
-
const captions =
|
|
1138
|
+
const captions = _chunkD4TOPSHVcjs.groupCaptionsField.call(void 0, draft, (captionsUrl) => !_chunkD4TOPSHVcjs.isUnwritten.call(void 0, captionsUrl));
|
|
738
1139
|
if (captions !== void 0) {
|
|
739
1140
|
issues.push(
|
|
740
|
-
|
|
1141
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
741
1142
|
"dc_captions_not_allowed",
|
|
742
1143
|
["stimulus", "media", captions],
|
|
743
|
-
|
|
1144
|
+
_chunkD4TOPSHVcjs.GROUP_CAPTIONS_REVEAL_DICTATION
|
|
744
1145
|
)
|
|
745
1146
|
);
|
|
746
1147
|
}
|
|
747
|
-
const parsed =
|
|
1148
|
+
const parsed = _chunk2CV6NU32cjs.ItemGroupSchema.safeParse(draft, { reportInput: true });
|
|
748
1149
|
if (!parsed.success) {
|
|
749
1150
|
for (const schemaIssue of parsed.error.issues) {
|
|
750
1151
|
const path = schemaIssue.path.map(String);
|
|
751
|
-
if (issues.some((known) =>
|
|
1152
|
+
if (issues.some((known) => _chunkD4TOPSHVcjs.covers.call(void 0, known.path, path))) {
|
|
752
1153
|
continue;
|
|
753
1154
|
}
|
|
754
|
-
if (path.length > 0 &&
|
|
1155
|
+
if (path.length > 0 && _chunkD4TOPSHVcjs.refusesEmpty.call(void 0, draft, schemaIssue)) {
|
|
755
1156
|
issues.push(
|
|
756
|
-
|
|
1157
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
757
1158
|
"null_not_allowed",
|
|
758
1159
|
path,
|
|
759
1160
|
"This field cannot be null. Leave it out if it is optional, or give it a value."
|
|
@@ -769,7 +1170,7 @@ function validateItemGroupDraftInScope(draft) {
|
|
|
769
1170
|
});
|
|
770
1171
|
}
|
|
771
1172
|
}
|
|
772
|
-
const stored =
|
|
1173
|
+
const stored = _chunk2CV6NU32cjs.validateItemGroup.call(void 0, draft);
|
|
773
1174
|
if (issues.length === 0 && stored.success) {
|
|
774
1175
|
return { status: "complete", data: stored.data, issues };
|
|
775
1176
|
}
|
|
@@ -784,21 +1185,21 @@ function validateItemGroupDraftInScope(draft) {
|
|
|
784
1185
|
function checkTimeline(draft) {
|
|
785
1186
|
const issues = [];
|
|
786
1187
|
const timeline = draft.timeline;
|
|
787
|
-
if (!
|
|
1188
|
+
if (!_chunkD4TOPSHVcjs.isRecord.call(void 0, timeline)) {
|
|
788
1189
|
return issues;
|
|
789
1190
|
}
|
|
790
|
-
const stimulus =
|
|
791
|
-
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") {
|
|
792
1193
|
issues.push(
|
|
793
|
-
|
|
1194
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
794
1195
|
"ig_timeline_stimulus_kind",
|
|
795
1196
|
["stimulus", "kind"],
|
|
796
1197
|
"An interactive video needs a video: quizzes open at moments of it."
|
|
797
1198
|
)
|
|
798
1199
|
);
|
|
799
|
-
} 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") {
|
|
800
1201
|
issues.push(
|
|
801
|
-
|
|
1202
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
802
1203
|
"ig_timeline_stimulus_kind",
|
|
803
1204
|
["stimulus", "media", "type"],
|
|
804
1205
|
"Upload a video file. An embedded player from another site cannot be paused when a quiz opens."
|
|
@@ -807,7 +1208,7 @@ function checkTimeline(draft) {
|
|
|
807
1208
|
}
|
|
808
1209
|
if (draft.shuffle === "within-group") {
|
|
809
1210
|
issues.push(
|
|
810
|
-
|
|
1211
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
811
1212
|
"ig_timeline_shuffle",
|
|
812
1213
|
["shuffle"],
|
|
813
1214
|
"The questions of an interactive video appear in the order their quizzes open, so they cannot be shuffled."
|
|
@@ -817,25 +1218,25 @@ function checkTimeline(draft) {
|
|
|
817
1218
|
const items = Array.isArray(draft.items) ? draft.items : [];
|
|
818
1219
|
const itemIndexById = /* @__PURE__ */ new Map();
|
|
819
1220
|
items.forEach((item, index) => {
|
|
820
|
-
if (!
|
|
1221
|
+
if (!_chunkD4TOPSHVcjs.isRecord.call(void 0, item)) {
|
|
821
1222
|
return;
|
|
822
1223
|
}
|
|
823
1224
|
if (typeof item.id === "string" && item.id !== "") {
|
|
824
1225
|
itemIndexById.set(item.id, index);
|
|
825
1226
|
}
|
|
826
1227
|
const type = item.type;
|
|
827
|
-
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) {
|
|
828
1229
|
issues.push(
|
|
829
|
-
|
|
1230
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
830
1231
|
"ig_timeline_item_type",
|
|
831
1232
|
["items", index, "type"],
|
|
832
|
-
`An interactive video can hold ${
|
|
1233
|
+
`An interactive video can hold ${_chunk2CV6NU32cjs.INTERACTIVE_VIDEO_ITEM_TYPES.join(", ")} questions only.`
|
|
833
1234
|
)
|
|
834
1235
|
);
|
|
835
1236
|
}
|
|
836
|
-
if (type === "dictation" &&
|
|
1237
|
+
if (type === "dictation" && _chunkD4TOPSHVcjs.isUnset.call(void 0, item.media)) {
|
|
837
1238
|
issues.push(
|
|
838
|
-
|
|
1239
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
839
1240
|
"ig_timeline_dictation_media",
|
|
840
1241
|
["items", index, "media"],
|
|
841
1242
|
"Add the recording this dictation plays: inside a video it cannot play the video."
|
|
@@ -847,7 +1248,7 @@ function checkTimeline(draft) {
|
|
|
847
1248
|
const quizIds = /* @__PURE__ */ new Set();
|
|
848
1249
|
const placed = /* @__PURE__ */ new Set();
|
|
849
1250
|
cues.forEach((cue, cueIndex) => {
|
|
850
|
-
if (!
|
|
1251
|
+
if (!_chunkD4TOPSHVcjs.isRecord.call(void 0, cue)) {
|
|
851
1252
|
return;
|
|
852
1253
|
}
|
|
853
1254
|
const at = (field, ...rest) => [
|
|
@@ -857,19 +1258,19 @@ function checkTimeline(draft) {
|
|
|
857
1258
|
field,
|
|
858
1259
|
...rest
|
|
859
1260
|
];
|
|
860
|
-
if (
|
|
861
|
-
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."));
|
|
862
1263
|
} else if (typeof cue.id === "string") {
|
|
863
1264
|
if (quizIds.has(cue.id)) {
|
|
864
1265
|
issues.push(
|
|
865
|
-
|
|
1266
|
+
_chunkD4TOPSHVcjs.issue.call(void 0, "ig_timeline_quiz_id_duplicate", at("id"), `Two quizzes share the id "${cue.id}".`)
|
|
866
1267
|
);
|
|
867
1268
|
}
|
|
868
1269
|
quizIds.add(cue.id);
|
|
869
1270
|
}
|
|
870
|
-
if (
|
|
1271
|
+
if (_chunkD4TOPSHVcjs.isUnset.call(void 0, cue.at)) {
|
|
871
1272
|
issues.push(
|
|
872
|
-
|
|
1273
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
873
1274
|
"ig_timeline_quiz_time_required",
|
|
874
1275
|
at("at"),
|
|
875
1276
|
"Choose when in the video this quiz opens."
|
|
@@ -877,16 +1278,16 @@ function checkTimeline(draft) {
|
|
|
877
1278
|
);
|
|
878
1279
|
} else if (typeof cue.at !== "number" || !Number.isFinite(cue.at) || cue.at < 0) {
|
|
879
1280
|
issues.push(
|
|
880
|
-
|
|
1281
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
881
1282
|
"ig_timeline_quiz_time_invalid",
|
|
882
1283
|
at("at"),
|
|
883
1284
|
"A quiz opens at a number of seconds, 0 or more."
|
|
884
1285
|
)
|
|
885
1286
|
);
|
|
886
1287
|
}
|
|
887
|
-
if (
|
|
1288
|
+
if (_chunkD4TOPSHVcjs.isUnset.call(void 0, cue.itemIds) || Array.isArray(cue.itemIds) && cue.itemIds.length === 0) {
|
|
888
1289
|
issues.push(
|
|
889
|
-
|
|
1290
|
+
_chunkD4TOPSHVcjs.issue.call(void 0, "ig_timeline_quiz_empty", at("itemIds"), "Add at least one question to this quiz.")
|
|
890
1291
|
);
|
|
891
1292
|
return;
|
|
892
1293
|
}
|
|
@@ -899,7 +1300,7 @@ function checkTimeline(draft) {
|
|
|
899
1300
|
}
|
|
900
1301
|
if (!itemIndexById.has(itemId)) {
|
|
901
1302
|
issues.push(
|
|
902
|
-
|
|
1303
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
903
1304
|
"ig_timeline_quiz_unknown_item",
|
|
904
1305
|
at("itemIds", position),
|
|
905
1306
|
`This quiz names a question that is not in the video ("${itemId}").`
|
|
@@ -907,7 +1308,7 @@ function checkTimeline(draft) {
|
|
|
907
1308
|
);
|
|
908
1309
|
} else if (placed.has(itemId)) {
|
|
909
1310
|
issues.push(
|
|
910
|
-
|
|
1311
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
911
1312
|
"ig_timeline_item_duplicate",
|
|
912
1313
|
at("itemIds", position),
|
|
913
1314
|
"This question is already in a quiz: each question belongs to one quiz."
|
|
@@ -920,7 +1321,7 @@ function checkTimeline(draft) {
|
|
|
920
1321
|
for (const [itemId, index] of itemIndexById) {
|
|
921
1322
|
if (!placed.has(itemId)) {
|
|
922
1323
|
issues.push(
|
|
923
|
-
|
|
1324
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
924
1325
|
"ig_timeline_item_unplaced",
|
|
925
1326
|
["items", index],
|
|
926
1327
|
"Add this question to a quiz, or the video never shows it."
|
|
@@ -931,12 +1332,12 @@ function checkTimeline(draft) {
|
|
|
931
1332
|
const chapters = Array.isArray(timeline.chapters) ? timeline.chapters : [];
|
|
932
1333
|
let previousAt;
|
|
933
1334
|
chapters.forEach((chapter, index) => {
|
|
934
|
-
if (!
|
|
1335
|
+
if (!_chunkD4TOPSHVcjs.isRecord.call(void 0, chapter)) {
|
|
935
1336
|
return;
|
|
936
1337
|
}
|
|
937
|
-
if (
|
|
1338
|
+
if (_chunkD4TOPSHVcjs.isUnwritten.call(void 0, chapter.title)) {
|
|
938
1339
|
issues.push(
|
|
939
|
-
|
|
1340
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
940
1341
|
"ig_timeline_chapter_title",
|
|
941
1342
|
["timeline", "chapters", index, "title"],
|
|
942
1343
|
"Give this chapter a title."
|
|
@@ -946,7 +1347,7 @@ function checkTimeline(draft) {
|
|
|
946
1347
|
if (typeof chapter.at === "number" && Number.isFinite(chapter.at)) {
|
|
947
1348
|
if (previousAt !== void 0 && chapter.at <= previousAt) {
|
|
948
1349
|
issues.push(
|
|
949
|
-
|
|
1350
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
950
1351
|
"ig_timeline_chapter_order",
|
|
951
1352
|
["timeline", "chapters", index, "at"],
|
|
952
1353
|
"Chapters must start in order, each after the one before it."
|
|
@@ -962,7 +1363,7 @@ function checkGroupIdentity(draft) {
|
|
|
962
1363
|
const issues = [];
|
|
963
1364
|
if (draft.schemaVersion !== "1.0") {
|
|
964
1365
|
issues.push(
|
|
965
|
-
|
|
1366
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
966
1367
|
"schema_version_invalid",
|
|
967
1368
|
["schemaVersion"],
|
|
968
1369
|
'The draft must have schemaVersion "1.0". A draft from createItemGroupDraft has it.'
|
|
@@ -970,14 +1371,14 @@ function checkGroupIdentity(draft) {
|
|
|
970
1371
|
);
|
|
971
1372
|
}
|
|
972
1373
|
if (draft.type !== "item-group") {
|
|
973
|
-
issues.push(
|
|
1374
|
+
issues.push(_chunkD4TOPSHVcjs.issue.call(void 0, "type_mismatch", ["type"], `The draft's type must be "item-group".`));
|
|
974
1375
|
}
|
|
975
|
-
if (
|
|
976
|
-
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."));
|
|
977
1378
|
}
|
|
978
|
-
if (!
|
|
1379
|
+
if (!_chunkD4TOPSHVcjs.isUnset.call(void 0, draft.shuffle) && draft.shuffle !== "none" && draft.shuffle !== "within-group") {
|
|
979
1380
|
issues.push(
|
|
980
|
-
|
|
1381
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
981
1382
|
"ig_shuffle_invalid",
|
|
982
1383
|
["shuffle"],
|
|
983
1384
|
'Shuffling is either "none" or "within-group". Leave it out to keep the authored order.'
|
|
@@ -996,13 +1397,13 @@ var MEDIA_FOR_KIND = {
|
|
|
996
1397
|
function checkStimulus(stimulus) {
|
|
997
1398
|
const issues = [];
|
|
998
1399
|
const at = (...rest) => ["stimulus", ...rest];
|
|
999
|
-
if (
|
|
1000
|
-
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."));
|
|
1001
1402
|
}
|
|
1002
1403
|
const kind = stimulus.kind;
|
|
1003
|
-
if (
|
|
1404
|
+
if (_chunkD4TOPSHVcjs.isUnwritten.call(void 0, kind)) {
|
|
1004
1405
|
issues.push(
|
|
1005
|
-
|
|
1406
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1006
1407
|
"ig_stimulus_kind_required",
|
|
1007
1408
|
at("kind"),
|
|
1008
1409
|
"Choose what the questions are about: a text, a recording, a video, an image, or a mix."
|
|
@@ -1011,71 +1412,71 @@ function checkStimulus(stimulus) {
|
|
|
1011
1412
|
} else if (typeof kind !== "string" || !KINDS.has(kind)) {
|
|
1012
1413
|
if (typeof kind === "string") {
|
|
1013
1414
|
issues.push(
|
|
1014
|
-
|
|
1415
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1015
1416
|
"ig_stimulus_kind_invalid",
|
|
1016
1417
|
at("kind"),
|
|
1017
1418
|
`"${kind}" is not a stimulus kind. Use text, audio, video, image or mixed.`
|
|
1018
1419
|
)
|
|
1019
1420
|
);
|
|
1020
1421
|
}
|
|
1021
|
-
if (
|
|
1022
|
-
issues.push(...
|
|
1422
|
+
if (_chunkD4TOPSHVcjs.isRecord.call(void 0, stimulus.media)) {
|
|
1423
|
+
issues.push(..._chunkD4TOPSHVcjs.checkMedia.call(void 0, stimulus.media, at("media")));
|
|
1023
1424
|
}
|
|
1024
1425
|
return issues;
|
|
1025
1426
|
}
|
|
1026
1427
|
const hasBody = typeof stimulus.body === "string" && stimulus.body.trim() !== "";
|
|
1027
|
-
const htmlPresent = !
|
|
1428
|
+
const htmlPresent = !_chunkD4TOPSHVcjs.isUnset.call(void 0, stimulus.bodyHtml);
|
|
1028
1429
|
if (!hasBody && (kind === "text" || kind === "mixed" || htmlPresent)) {
|
|
1029
1430
|
issues.push(
|
|
1030
|
-
|
|
1431
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1031
1432
|
"ig_stimulus_body_required",
|
|
1032
1433
|
at("body"),
|
|
1033
|
-
|
|
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."
|
|
1034
1435
|
)
|
|
1035
1436
|
);
|
|
1036
1437
|
}
|
|
1037
|
-
if (kind !== "text" &&
|
|
1438
|
+
if (kind !== "text" && _chunkD4TOPSHVcjs.isUnset.call(void 0, stimulus.media)) {
|
|
1038
1439
|
issues.push(
|
|
1039
|
-
|
|
1440
|
+
_chunkD4TOPSHVcjs.issue.call(void 0, "ig_stimulus_media_required", at("media"), "Add the recording, video or image.")
|
|
1040
1441
|
);
|
|
1041
|
-
} else if (
|
|
1442
|
+
} else if (_chunkD4TOPSHVcjs.isRecord.call(void 0, stimulus.media)) {
|
|
1042
1443
|
const allowed = MEDIA_FOR_KIND[kind];
|
|
1043
1444
|
const mediaType = stimulus.media.type;
|
|
1044
1445
|
if (allowed !== void 0 && typeof mediaType === "string" && !allowed.includes(mediaType)) {
|
|
1045
1446
|
issues.push(
|
|
1046
|
-
|
|
1447
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1047
1448
|
"ig_stimulus_media_kind",
|
|
1048
1449
|
at("media", "type"),
|
|
1049
1450
|
`A "${kind}" stimulus cannot carry ${mediaType} media. Use ${allowed.join(" or ")}.`
|
|
1050
1451
|
)
|
|
1051
1452
|
);
|
|
1052
1453
|
}
|
|
1053
|
-
issues.push(...
|
|
1454
|
+
issues.push(..._chunkD4TOPSHVcjs.checkMedia.call(void 0, stimulus.media, at("media")));
|
|
1054
1455
|
}
|
|
1055
1456
|
return issues;
|
|
1056
1457
|
}
|
|
1057
1458
|
function checkItems(draft) {
|
|
1058
1459
|
const issues = [];
|
|
1059
|
-
const items =
|
|
1460
|
+
const items = _chunkD4TOPSHVcjs.isUnset.call(void 0, draft.items) ? [] : draft.items;
|
|
1060
1461
|
if (!Array.isArray(items)) {
|
|
1061
1462
|
return issues;
|
|
1062
1463
|
}
|
|
1063
1464
|
if (items.length === 0) {
|
|
1064
1465
|
issues.push(
|
|
1065
|
-
|
|
1466
|
+
_chunkD4TOPSHVcjs.issue.call(void 0, "ig_items_required", ["items"], "Add at least one question about this material.")
|
|
1066
1467
|
);
|
|
1067
1468
|
return issues;
|
|
1068
1469
|
}
|
|
1069
1470
|
const seen = /* @__PURE__ */ new Set();
|
|
1070
1471
|
const repeated = /* @__PURE__ */ new Set();
|
|
1071
1472
|
for (const [index, item] of items.entries()) {
|
|
1072
|
-
if (!
|
|
1473
|
+
if (!_chunkD4TOPSHVcjs.isRecord.call(void 0, item)) {
|
|
1073
1474
|
continue;
|
|
1074
1475
|
}
|
|
1075
1476
|
const ordinal = index + 1;
|
|
1076
|
-
if (
|
|
1477
|
+
if (_chunkD4TOPSHVcjs.isMissingId.call(void 0, item.id)) {
|
|
1077
1478
|
issues.push(
|
|
1078
|
-
|
|
1479
|
+
_chunkD4TOPSHVcjs.issue.call(void 0, "ig_item_id_required", ["items", index, "id"], `Question ${ordinal} has no id.`)
|
|
1079
1480
|
);
|
|
1080
1481
|
} else if (typeof item.id === "string") {
|
|
1081
1482
|
if (seen.has(item.id)) {
|
|
@@ -1085,7 +1486,7 @@ function checkItems(draft) {
|
|
|
1085
1486
|
}
|
|
1086
1487
|
if (item.type === "item-group") {
|
|
1087
1488
|
issues.push(
|
|
1088
|
-
|
|
1489
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1089
1490
|
"ig_item_nested_group",
|
|
1090
1491
|
["items", index, "type"],
|
|
1091
1492
|
"Groups do not nest: every item must be an activity."
|
|
@@ -1093,9 +1494,9 @@ function checkItems(draft) {
|
|
|
1093
1494
|
);
|
|
1094
1495
|
continue;
|
|
1095
1496
|
}
|
|
1096
|
-
if (
|
|
1497
|
+
if (_chunkD4TOPSHVcjs.isUnwritten.call(void 0, item.type)) {
|
|
1097
1498
|
issues.push(
|
|
1098
|
-
|
|
1499
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1099
1500
|
"ig_item_type_required",
|
|
1100
1501
|
["items", index, "type"],
|
|
1101
1502
|
`Choose what kind of question ${ordinal} is.`
|
|
@@ -1110,11 +1511,11 @@ function checkItems(draft) {
|
|
|
1110
1511
|
try {
|
|
1111
1512
|
result = validateDraft(item.type, item);
|
|
1112
1513
|
} catch (error) {
|
|
1113
|
-
if (!(error instanceof
|
|
1514
|
+
if (!(error instanceof _chunkD4TOPSHVcjs.UnknownActivityTypeError) || error.activityType !== item.type) {
|
|
1114
1515
|
throw error;
|
|
1115
1516
|
}
|
|
1116
1517
|
issues.push(
|
|
1117
|
-
|
|
1518
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1118
1519
|
"ig_item_type_unknown",
|
|
1119
1520
|
["items", index, "type"],
|
|
1120
1521
|
`"${item.type}" is not a registered activity type.`
|
|
@@ -1128,7 +1529,7 @@ function checkItems(draft) {
|
|
|
1128
1529
|
}
|
|
1129
1530
|
for (const id of repeated) {
|
|
1130
1531
|
issues.push(
|
|
1131
|
-
|
|
1532
|
+
_chunkD4TOPSHVcjs.issue.call(void 0, "ig_item_id_duplicate", ["items"], `More than one question has the id "${id}".`)
|
|
1132
1533
|
);
|
|
1133
1534
|
}
|
|
1134
1535
|
return issues;
|
|
@@ -1136,30 +1537,30 @@ function checkItems(draft) {
|
|
|
1136
1537
|
|
|
1137
1538
|
// src/authoring/index.ts
|
|
1138
1539
|
function validateDraft(type, draft) {
|
|
1139
|
-
return
|
|
1540
|
+
return _chunkD4TOPSHVcjs.withValidationScope.call(void 0, () => validateDraftInScope(type, draft));
|
|
1140
1541
|
}
|
|
1141
1542
|
function validateDraftInScope(type, draft) {
|
|
1142
|
-
const descriptor =
|
|
1543
|
+
const descriptor = _chunkD4TOPSHVcjs.getActivityTypeDescriptor.call(void 0, type);
|
|
1143
1544
|
if (descriptor === void 0) {
|
|
1144
|
-
throw new (0,
|
|
1545
|
+
throw new (0, _chunkD4TOPSHVcjs.UnknownActivityTypeError)(String(type));
|
|
1145
1546
|
}
|
|
1146
|
-
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) : [];
|
|
1147
1548
|
const issues = [...reported];
|
|
1148
1549
|
const parsed = descriptor.schema.safeParse(draft, { reportInput: true });
|
|
1149
1550
|
if (!parsed.success) {
|
|
1150
|
-
const covered =
|
|
1551
|
+
const covered = _chunkD4TOPSHVcjs.coveredPathsOf.call(void 0, reported);
|
|
1151
1552
|
const reportedEmpty = /* @__PURE__ */ new Set();
|
|
1152
1553
|
for (const schemaIssue of parsed.error.issues) {
|
|
1153
1554
|
const path = schemaIssue.path.map(String);
|
|
1154
|
-
if (covered.has(
|
|
1555
|
+
if (covered.has(_chunkD4TOPSHVcjs.pathKey.call(void 0, path))) {
|
|
1155
1556
|
continue;
|
|
1156
1557
|
}
|
|
1157
|
-
if (path.length > 0 &&
|
|
1558
|
+
if (path.length > 0 && _chunkD4TOPSHVcjs.refusesEmpty.call(void 0, draft, schemaIssue)) {
|
|
1158
1559
|
const key = JSON.stringify(path);
|
|
1159
1560
|
if (!reportedEmpty.has(key)) {
|
|
1160
1561
|
reportedEmpty.add(key);
|
|
1161
1562
|
issues.push(
|
|
1162
|
-
|
|
1563
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1163
1564
|
"null_not_allowed",
|
|
1164
1565
|
path,
|
|
1165
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."
|
|
@@ -1183,11 +1584,11 @@ function validateDraftInScope(type, draft) {
|
|
|
1183
1584
|
return { status: invalid ? "invalid" : "incomplete", issues };
|
|
1184
1585
|
}
|
|
1185
1586
|
function createDraft(type, context) {
|
|
1186
|
-
const descriptor =
|
|
1587
|
+
const descriptor = _chunkD4TOPSHVcjs.getActivityTypeDescriptor.call(void 0, type);
|
|
1187
1588
|
if (descriptor === void 0) {
|
|
1188
|
-
throw new (0,
|
|
1589
|
+
throw new (0, _chunkD4TOPSHVcjs.UnknownActivityTypeError)(String(type));
|
|
1189
1590
|
}
|
|
1190
|
-
const create = _optionalChain([descriptor, 'access',
|
|
1591
|
+
const create = _optionalChain([descriptor, 'access', _46 => _46.authoring, 'optionalAccess', _47 => _47.createDraft]);
|
|
1191
1592
|
if (create === void 0) {
|
|
1192
1593
|
throw new Error(
|
|
1193
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.`
|
|
@@ -1210,7 +1611,7 @@ function createDraft(type, context) {
|
|
|
1210
1611
|
return create({ newId });
|
|
1211
1612
|
}
|
|
1212
1613
|
function normalise(found) {
|
|
1213
|
-
const documented = Object.hasOwn(
|
|
1614
|
+
const documented = Object.hasOwn(_chunkD4TOPSHVcjs.DRAFT_ISSUE_SEVERITY, found.code) ? _chunkD4TOPSHVcjs.DRAFT_ISSUE_SEVERITY[found.code] : void 0;
|
|
1214
1615
|
return {
|
|
1215
1616
|
...found,
|
|
1216
1617
|
path: found.path.map(String),
|
|
@@ -1219,11 +1620,11 @@ function normalise(found) {
|
|
|
1219
1620
|
}
|
|
1220
1621
|
|
|
1221
1622
|
// src/redact.ts
|
|
1222
|
-
function mergePolicy(
|
|
1623
|
+
function mergePolicy(base2, overrides) {
|
|
1223
1624
|
if (overrides === void 0) {
|
|
1224
|
-
return
|
|
1625
|
+
return base2;
|
|
1225
1626
|
}
|
|
1226
|
-
const merged = { ...
|
|
1627
|
+
const merged = { ...base2 };
|
|
1227
1628
|
for (const [key, override] of Object.entries(overrides)) {
|
|
1228
1629
|
const current = merged[key];
|
|
1229
1630
|
merged[key] = typeof override === "object" && typeof current === "object" ? { ...current, ...override } : override;
|
|
@@ -1274,9 +1675,9 @@ function redactValue(value, policy, reveal) {
|
|
|
1274
1675
|
}
|
|
1275
1676
|
function redact(data, options = {}) {
|
|
1276
1677
|
const reveal = _nullishCoalesce(options.reveal, () => ( "none"));
|
|
1277
|
-
const descriptor =
|
|
1678
|
+
const descriptor = _chunkD4TOPSHVcjs.getActivityTypeDescriptor.call(void 0, data.type);
|
|
1278
1679
|
if (descriptor === void 0) {
|
|
1279
|
-
throw new (0,
|
|
1680
|
+
throw new (0, _chunkD4TOPSHVcjs.UnknownActivityTypeError)(String(data.type));
|
|
1280
1681
|
}
|
|
1281
1682
|
if (descriptor.fieldPolicy === void 0) {
|
|
1282
1683
|
throw new Error(
|
|
@@ -1289,7 +1690,7 @@ function redact(data, options = {}) {
|
|
|
1289
1690
|
if (reveal === "none" && descriptor.redactedSchema !== void 0) {
|
|
1290
1691
|
const parsed = descriptor.redactedSchema.safeParse(result);
|
|
1291
1692
|
if (!parsed.success) {
|
|
1292
|
-
throw new (0,
|
|
1693
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)(
|
|
1293
1694
|
descriptor.type,
|
|
1294
1695
|
parsed.error.issues.map((issue2) => ({
|
|
1295
1696
|
path: issue2.path.map(String),
|
|
@@ -1303,13 +1704,13 @@ function redact(data, options = {}) {
|
|
|
1303
1704
|
}
|
|
1304
1705
|
function assertRedacted(data) {
|
|
1305
1706
|
if (typeof data !== "object" || data === null) {
|
|
1306
|
-
throw new (0,
|
|
1707
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)("unknown", [
|
|
1307
1708
|
{ path: [], message: "Redacted activity data must be an object.", code: "invalid_type" }
|
|
1308
1709
|
]);
|
|
1309
1710
|
}
|
|
1310
1711
|
const candidate = data;
|
|
1311
1712
|
if (candidate.redacted !== true) {
|
|
1312
|
-
throw new (0,
|
|
1713
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)(String(_nullishCoalesce(candidate.type, () => ( "unknown"))), [
|
|
1313
1714
|
{
|
|
1314
1715
|
path: ["redacted"],
|
|
1315
1716
|
message: "Missing redacted marker \u2014 this payload is not a redact() projection.",
|
|
@@ -1318,12 +1719,12 @@ function assertRedacted(data) {
|
|
|
1318
1719
|
]);
|
|
1319
1720
|
}
|
|
1320
1721
|
const type = typeof candidate.type === "string" ? candidate.type : "";
|
|
1321
|
-
const descriptor =
|
|
1722
|
+
const descriptor = _chunkD4TOPSHVcjs.getActivityTypeDescriptor.call(void 0, type);
|
|
1322
1723
|
if (descriptor === void 0) {
|
|
1323
|
-
throw new (0,
|
|
1724
|
+
throw new (0, _chunkD4TOPSHVcjs.UnknownActivityTypeError)(type);
|
|
1324
1725
|
}
|
|
1325
1726
|
if (descriptor.redactedSchema === void 0) {
|
|
1326
|
-
throw new (0,
|
|
1727
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)(descriptor.type, [
|
|
1327
1728
|
{
|
|
1328
1729
|
path: [],
|
|
1329
1730
|
message: `Activity type "${descriptor.type}" registers no redactedSchema; assertRedacted cannot prove this payload is learner-safe.`,
|
|
@@ -1333,7 +1734,7 @@ function assertRedacted(data) {
|
|
|
1333
1734
|
}
|
|
1334
1735
|
const parsed = descriptor.redactedSchema.safeParse(candidate);
|
|
1335
1736
|
if (!parsed.success) {
|
|
1336
|
-
throw new (0,
|
|
1737
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)(
|
|
1337
1738
|
descriptor.type,
|
|
1338
1739
|
parsed.error.issues.map((issue2) => ({
|
|
1339
1740
|
path: issue2.path.map(String),
|
|
@@ -1349,7 +1750,7 @@ var STIMULUS_FIELD_POLICY = {
|
|
|
1349
1750
|
title: "public",
|
|
1350
1751
|
body: "public",
|
|
1351
1752
|
bodyHtml: "public",
|
|
1352
|
-
media:
|
|
1753
|
+
media: _chunkD4TOPSHVcjs.MEDIA_FIELD_POLICY,
|
|
1353
1754
|
locale: "public",
|
|
1354
1755
|
attribution: "public",
|
|
1355
1756
|
transcript: "author-only"
|
|
@@ -1393,9 +1794,9 @@ function redactItemGroup(group, options = {}) {
|
|
|
1393
1794
|
redacted: true
|
|
1394
1795
|
};
|
|
1395
1796
|
if (reveal === "none") {
|
|
1396
|
-
const parsed =
|
|
1797
|
+
const parsed = _chunk2CV6NU32cjs.RedactedItemGroupSchema.safeParse(result);
|
|
1397
1798
|
if (!parsed.success) {
|
|
1398
|
-
throw new (0,
|
|
1799
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)(
|
|
1399
1800
|
"item-group",
|
|
1400
1801
|
parsed.error.issues.map((issue2) => ({
|
|
1401
1802
|
path: issue2.path.map(String),
|
|
@@ -1409,13 +1810,13 @@ function redactItemGroup(group, options = {}) {
|
|
|
1409
1810
|
}
|
|
1410
1811
|
function assertRedactedItemGroup(data) {
|
|
1411
1812
|
if (typeof data !== "object" || data === null) {
|
|
1412
|
-
throw new (0,
|
|
1813
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)("item-group", [
|
|
1413
1814
|
{ path: [], message: "Redacted item group must be an object.", code: "invalid_type" }
|
|
1414
1815
|
]);
|
|
1415
1816
|
}
|
|
1416
1817
|
const candidate = data;
|
|
1417
1818
|
if (candidate.redacted !== true) {
|
|
1418
|
-
throw new (0,
|
|
1819
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)("item-group", [
|
|
1419
1820
|
{
|
|
1420
1821
|
path: ["redacted"],
|
|
1421
1822
|
message: "Missing redacted marker \u2014 this payload is not a redactItemGroup() projection.",
|
|
@@ -1423,9 +1824,9 @@ function assertRedactedItemGroup(data) {
|
|
|
1423
1824
|
}
|
|
1424
1825
|
]);
|
|
1425
1826
|
}
|
|
1426
|
-
const parsed =
|
|
1827
|
+
const parsed = _chunk2CV6NU32cjs.RedactedItemGroupSchema.safeParse(candidate);
|
|
1427
1828
|
if (!parsed.success) {
|
|
1428
|
-
throw new (0,
|
|
1829
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)(
|
|
1429
1830
|
"item-group",
|
|
1430
1831
|
parsed.error.issues.map((issue2) => ({
|
|
1431
1832
|
path: issue2.path.map(String),
|
|
@@ -1438,8 +1839,8 @@ function assertRedactedItemGroup(data) {
|
|
|
1438
1839
|
try {
|
|
1439
1840
|
assertRedacted(item);
|
|
1440
1841
|
} catch (error) {
|
|
1441
|
-
if (error instanceof
|
|
1442
|
-
throw new (0,
|
|
1842
|
+
if (error instanceof _chunkD4TOPSHVcjs.ActivitySchemaError) {
|
|
1843
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)(
|
|
1443
1844
|
"item-group",
|
|
1444
1845
|
error.errors.map((issue2) => ({
|
|
1445
1846
|
...issue2,
|
|
@@ -1462,7 +1863,7 @@ function readMediaProgress(value, duration) {
|
|
|
1462
1863
|
return null;
|
|
1463
1864
|
}
|
|
1464
1865
|
({ progressVersion: version, at, furthest } = value);
|
|
1465
|
-
} catch (
|
|
1866
|
+
} catch (e2) {
|
|
1466
1867
|
return null;
|
|
1467
1868
|
}
|
|
1468
1869
|
if (version !== "1.0" || typeof at !== "number" || !Number.isFinite(at)) {
|
|
@@ -1484,7 +1885,7 @@ function composeTimelineScore(entryKey, items, policy) {
|
|
|
1484
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.`
|
|
1485
1886
|
);
|
|
1486
1887
|
}
|
|
1487
|
-
return
|
|
1888
|
+
return _chunkXNMKDFPWcjs.composeAssessmentScore.call(void 0, [{ id: entryKey, weight: 1, items: own }], policy);
|
|
1488
1889
|
}
|
|
1489
1890
|
|
|
1490
1891
|
|
|
@@ -1632,5 +2033,19 @@ function composeTimelineScore(entryKey, items, policy) {
|
|
|
1632
2033
|
|
|
1633
2034
|
|
|
1634
2035
|
|
|
1635
|
-
|
|
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;
|
|
1636
2051
|
//# sourceMappingURL=index.cjs.map
|