@intellectif/lk-core 0.16.0 → 0.18.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 +75 -0
- package/README.md +2 -2
- package/dist/{activity-DcxtpX7Z.d.cts → activity-HH8dxN1v.d.cts} +234 -4
- package/dist/{activity-DcxtpX7Z.d.ts → activity-HH8dxN1v.d.ts} +234 -4
- 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-6P6XK2LI.cjs → chunk-COBK2RUX.cjs} +74 -39
- package/dist/chunk-COBK2RUX.cjs.map +1 -0
- 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-MMEQKFFQ.js} +44 -9
- package/dist/chunk-MMEQKFFQ.js.map +1 -0
- package/dist/{chunk-OXF7VT7S.js → chunk-X5DAXBJI.js} +2 -2
- 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-DRJqwO2y.d.ts → index-BrBBUb1i.d.ts} +141 -83
- package/dist/{index-BWpwZRQw.d.cts → index-DejnxQpK.d.cts} +141 -83
- package/dist/index.cjs +547 -127
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +145 -9
- package/dist/index.d.ts +145 -9
- package/dist/index.js +427 -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 +33 -5
- package/dist/scoring.d.ts +33 -5
- 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/vectors/README.md +9 -3
- package/vectors/scoring.json +1258 -10
- package/dist/chunk-6P6XK2LI.cjs.map +0 -1
- package/dist/chunk-F7UOLKWV.cjs.map +0 -1
- package/dist/chunk-IRUD73IQ.js.map +0 -1
- package/dist/chunk-S63IOKFP.js.map +0 -1
- /package/dist/{chunk-OXF7VT7S.js.map → chunk-X5DAXBJI.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -16,15 +16,15 @@
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
var _chunk6P6XK2LIcjs = require('./chunk-6P6XK2LI.cjs');
|
|
20
19
|
|
|
20
|
+
var _chunkCOBK2RUXcjs = require('./chunk-COBK2RUX.cjs');
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
|
|
26
|
-
var _chunkVFTVZJO5cjs = require('./chunk-VFTVZJO5.cjs');
|
|
27
26
|
|
|
27
|
+
var _chunkEOFWSGLUcjs = require('./chunk-EOFWSGLU.cjs');
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
|
|
@@ -49,8 +49,8 @@ var _chunkVFTVZJO5cjs = require('./chunk-VFTVZJO5.cjs');
|
|
|
49
49
|
|
|
50
50
|
|
|
51
51
|
|
|
52
|
-
var _chunkFJJ2GVBAcjs = require('./chunk-FJJ2GVBA.cjs');
|
|
53
52
|
|
|
53
|
+
var _chunk2CV6NU32cjs = require('./chunk-2CV6NU32.cjs');
|
|
54
54
|
|
|
55
55
|
|
|
56
56
|
|
|
@@ -134,7 +134,413 @@ var _chunkFJJ2GVBAcjs = require('./chunk-FJJ2GVBA.cjs');
|
|
|
134
134
|
|
|
135
135
|
|
|
136
136
|
|
|
137
|
-
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
var _chunkD4TOPSHVcjs = require('./chunk-D4TOPSHV.cjs');
|
|
141
|
+
|
|
142
|
+
// src/ai.ts
|
|
143
|
+
var AI_EXPLANATION_TYPES = [
|
|
144
|
+
"multiple-choice",
|
|
145
|
+
"fill-in-the-blanks",
|
|
146
|
+
"gap-select",
|
|
147
|
+
"dictation"
|
|
148
|
+
];
|
|
149
|
+
var AI_HINT_TYPES = [
|
|
150
|
+
"multiple-choice",
|
|
151
|
+
"fill-in-the-blanks",
|
|
152
|
+
"gap-select"
|
|
153
|
+
];
|
|
154
|
+
var AI_TEXT_MAX_LENGTH = 2e3;
|
|
155
|
+
function aiSupports(activityType, feature) {
|
|
156
|
+
const types = feature === "hint" ? AI_HINT_TYPES : AI_EXPLANATION_TYPES;
|
|
157
|
+
return types.includes(activityType);
|
|
158
|
+
}
|
|
159
|
+
function aiAllowedByContent(data, feature) {
|
|
160
|
+
const permissions = data.ai;
|
|
161
|
+
if (typeof permissions !== "object" || permissions === null) {
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
const key = feature === "hint" ? "hints" : "explanations";
|
|
165
|
+
return permissions[key] !== false;
|
|
166
|
+
}
|
|
167
|
+
function aiGradeOf(result) {
|
|
168
|
+
const ratio = result.maxScore > 0 ? result.score / result.maxScore : 0;
|
|
169
|
+
let category = "partly-correct";
|
|
170
|
+
if (ratio >= 1 - 1e-9) {
|
|
171
|
+
category = "correct";
|
|
172
|
+
} else if (ratio <= 1e-9) {
|
|
173
|
+
category = "incorrect";
|
|
174
|
+
}
|
|
175
|
+
return { score: result.score, maxScore: result.maxScore, passed: result.passed, category };
|
|
176
|
+
}
|
|
177
|
+
function placeholderOrder(passage) {
|
|
178
|
+
return [...passage.matchAll(_chunkD4TOPSHVcjs.PLACEHOLDER_RE)].map((match) => match[1]);
|
|
179
|
+
}
|
|
180
|
+
function numberedPassage(passage) {
|
|
181
|
+
let position = 0;
|
|
182
|
+
return passage.replace(_chunkD4TOPSHVcjs.PLACEHOLDER_RE, () => {
|
|
183
|
+
position += 1;
|
|
184
|
+
return `[${position}]`;
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
function isAnswerOption(detail, chosen) {
|
|
188
|
+
switch (detail.outcome) {
|
|
189
|
+
case "correct":
|
|
190
|
+
case "incorrect-omission":
|
|
191
|
+
return true;
|
|
192
|
+
case "incorrect":
|
|
193
|
+
case "correct-omission":
|
|
194
|
+
return false;
|
|
195
|
+
default:
|
|
196
|
+
return chosen ? detail.correct : !detail.correct;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
var firstString = (value) => Array.isArray(value) ? value[0] : value;
|
|
200
|
+
var listOf = (value) => value === void 0 ? null : Array.isArray(value) ? [...value] : [value];
|
|
201
|
+
function emptyResponse(type) {
|
|
202
|
+
switch (type) {
|
|
203
|
+
case "multiple-choice":
|
|
204
|
+
return { type: "multiple-choice", selectedOptionIds: [] };
|
|
205
|
+
case "fill-in-the-blanks":
|
|
206
|
+
return { type: "fill-in-the-blanks", answers: {} };
|
|
207
|
+
case "gap-select":
|
|
208
|
+
return { type: "gap-select", selections: {} };
|
|
209
|
+
case "dictation":
|
|
210
|
+
return { type: "dictation", text: "" };
|
|
211
|
+
default:
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
var base = (data) => ({
|
|
216
|
+
activityId: data.id,
|
|
217
|
+
title: data.title,
|
|
218
|
+
...typeof data.locale === "string" ? { locale: data.locale } : {}
|
|
219
|
+
});
|
|
220
|
+
function buildAiFacts(data, response, details) {
|
|
221
|
+
const byId = new Map((_nullishCoalesce(details, () => ( []))).map((detail) => [detail.itemId, detail]));
|
|
222
|
+
const full = data.redacted !== true;
|
|
223
|
+
switch (data.type) {
|
|
224
|
+
case "multiple-choice": {
|
|
225
|
+
const item = data;
|
|
226
|
+
const chosen = new Set(
|
|
227
|
+
_optionalChain([response, 'optionalAccess', _ => _.type]) === "multiple-choice" ? response.selectedOptionIds : []
|
|
228
|
+
);
|
|
229
|
+
return {
|
|
230
|
+
...base(data),
|
|
231
|
+
activityType: "multiple-choice",
|
|
232
|
+
question: item.question,
|
|
233
|
+
mode: item.mode,
|
|
234
|
+
options: item.options.map((option) => {
|
|
235
|
+
const detail = byId.get(option.id);
|
|
236
|
+
const wasChosen = chosen.has(option.id);
|
|
237
|
+
let correct = null;
|
|
238
|
+
if (full && typeof option.isCorrect === "boolean") {
|
|
239
|
+
correct = option.isCorrect;
|
|
240
|
+
} else if (detail !== void 0) {
|
|
241
|
+
correct = isAnswerOption(detail, wasChosen);
|
|
242
|
+
}
|
|
243
|
+
return {
|
|
244
|
+
id: option.id,
|
|
245
|
+
text: option.text,
|
|
246
|
+
chosen: wasChosen,
|
|
247
|
+
correct,
|
|
248
|
+
...typeof option.feedback === "string" ? { feedback: option.feedback } : {}
|
|
249
|
+
};
|
|
250
|
+
})
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
case "fill-in-the-blanks": {
|
|
254
|
+
const item = data;
|
|
255
|
+
const answers = _optionalChain([response, 'optionalAccess', _2 => _2.type]) === "fill-in-the-blanks" ? response.answers : {};
|
|
256
|
+
const blanks = new Map(item.blanks.map((blank) => [blank.id, blank]));
|
|
257
|
+
return {
|
|
258
|
+
...base(data),
|
|
259
|
+
activityType: "fill-in-the-blanks",
|
|
260
|
+
passage: numberedPassage(item.passage),
|
|
261
|
+
blanks: placeholderOrder(item.passage).map((id, index) => {
|
|
262
|
+
const blank = blanks.get(id);
|
|
263
|
+
const detail = byId.get(id);
|
|
264
|
+
const accepted = full && Array.isArray(_optionalChain([blank, 'optionalAccess', _3 => _3.acceptedAnswers])) ? [...blank.acceptedAnswers] : listOf(_optionalChain([detail, 'optionalAccess', _4 => _4.correctResponse]));
|
|
265
|
+
return {
|
|
266
|
+
id,
|
|
267
|
+
position: index + 1,
|
|
268
|
+
typed: typeof answers[id] === "string" ? answers[id] : "",
|
|
269
|
+
accepted,
|
|
270
|
+
correct: detail === void 0 ? null : detail.correct,
|
|
271
|
+
...typeof _optionalChain([blank, 'optionalAccess', _5 => _5.hint]) === "string" ? { hint: blank.hint } : {},
|
|
272
|
+
...typeof _optionalChain([blank, 'optionalAccess', _6 => _6.feedback]) === "string" ? { feedback: blank.feedback } : {}
|
|
273
|
+
};
|
|
274
|
+
})
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
case "gap-select": {
|
|
278
|
+
const item = data;
|
|
279
|
+
const selections = _optionalChain([response, 'optionalAccess', _7 => _7.type]) === "gap-select" ? response.selections : {};
|
|
280
|
+
const gaps = new Map(item.gaps.map((gap) => [gap.id, gap]));
|
|
281
|
+
const banks = new Map((_nullishCoalesce(item.banks, () => ( []))).map((bank) => [bank.id, bank]));
|
|
282
|
+
return {
|
|
283
|
+
...base(data),
|
|
284
|
+
activityType: "gap-select",
|
|
285
|
+
passage: numberedPassage(item.passage),
|
|
286
|
+
gaps: placeholderOrder(item.passage).map((id, index) => {
|
|
287
|
+
const gap = gaps.get(id);
|
|
288
|
+
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]), () => ( [])))));
|
|
289
|
+
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));
|
|
290
|
+
const detail = byId.get(id);
|
|
291
|
+
const answerId = full && typeof _optionalChain([gap, 'optionalAccess', _16 => _16.correctChoiceId]) === "string" ? gap.correctChoiceId : firstString(_optionalChain([detail, 'optionalAccess', _17 => _17.correctResponse]));
|
|
292
|
+
return {
|
|
293
|
+
id,
|
|
294
|
+
position: index + 1,
|
|
295
|
+
choices: choices.map((choice) => choice.text),
|
|
296
|
+
chosen: textOf(selections[id]),
|
|
297
|
+
answer: textOf(answerId),
|
|
298
|
+
correct: detail === void 0 ? null : detail.correct,
|
|
299
|
+
...typeof _optionalChain([gap, 'optionalAccess', _18 => _18.feedback]) === "string" ? { feedback: gap.feedback } : {}
|
|
300
|
+
};
|
|
301
|
+
})
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
case "dictation": {
|
|
305
|
+
const item = data;
|
|
306
|
+
const typed = _optionalChain([response, 'optionalAccess', _19 => _19.type]) === "dictation" ? response.text : "";
|
|
307
|
+
const hasKey = full && typeof item.transcript === "string";
|
|
308
|
+
let words = null;
|
|
309
|
+
if (hasKey) {
|
|
310
|
+
words = _chunkD4TOPSHVcjs.alignDictation.call(void 0, item, typed).words.map((word) => ({
|
|
311
|
+
expected: word.reference,
|
|
312
|
+
typed: word.attempt,
|
|
313
|
+
status: word.status
|
|
314
|
+
}));
|
|
315
|
+
} else if (details !== null && details.length > 0) {
|
|
316
|
+
words = details.map((detail) => {
|
|
317
|
+
const expected = _nullishCoalesce(firstString(detail.correctResponse), () => ( ""));
|
|
318
|
+
const attempt = _nullishCoalesce(firstString(detail.learnerResponse), () => ( ""));
|
|
319
|
+
let status = "incorrect";
|
|
320
|
+
if (detail.correct) {
|
|
321
|
+
status = "correct";
|
|
322
|
+
} else if (attempt === "") {
|
|
323
|
+
status = "missing";
|
|
324
|
+
} else if (expected === "") {
|
|
325
|
+
status = "extra";
|
|
326
|
+
}
|
|
327
|
+
return { expected, typed: attempt, status };
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
return {
|
|
331
|
+
...base(data),
|
|
332
|
+
activityType: "dictation",
|
|
333
|
+
transcript: hasKey ? item.transcript : null,
|
|
334
|
+
typed,
|
|
335
|
+
words
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
default:
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
function gradeLocally(data, response) {
|
|
343
|
+
if (data.redacted === true) {
|
|
344
|
+
return null;
|
|
345
|
+
}
|
|
346
|
+
try {
|
|
347
|
+
const result = _chunkCOBK2RUXcjs.score.call(void 0, data.type, data, response);
|
|
348
|
+
return { details: result.details, grade: aiGradeOf(result) };
|
|
349
|
+
} catch (e) {
|
|
350
|
+
return null;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
function aiExplanationRequest(input) {
|
|
354
|
+
const { data, response, outcome, learnerLocale } = input;
|
|
355
|
+
if (!aiSupports(data.type, "explanation") || !aiAllowedByContent(data, "explanation")) {
|
|
356
|
+
return null;
|
|
357
|
+
}
|
|
358
|
+
let details = null;
|
|
359
|
+
let grade = null;
|
|
360
|
+
if (_optionalChain([outcome, 'optionalAccess', _20 => _20.status]) === "scored") {
|
|
361
|
+
const { score: recorded, maxScore, passed } = outcome;
|
|
362
|
+
if (!_chunkCOBK2RUXcjs.isGradeInRange.call(void 0, recorded, maxScore)) {
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
details = outcome.details;
|
|
366
|
+
grade = aiGradeOf({ score: recorded, maxScore, passed });
|
|
367
|
+
} else if (response !== null) {
|
|
368
|
+
const local = gradeLocally(data, response);
|
|
369
|
+
if (local !== null) {
|
|
370
|
+
details = local.details;
|
|
371
|
+
grade = local.grade;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
if (grade === null) {
|
|
375
|
+
return null;
|
|
376
|
+
}
|
|
377
|
+
const facts = buildAiFacts(data, response, details);
|
|
378
|
+
if (facts === null) {
|
|
379
|
+
return null;
|
|
380
|
+
}
|
|
381
|
+
return {
|
|
382
|
+
feature: "explanation",
|
|
383
|
+
facts,
|
|
384
|
+
grade,
|
|
385
|
+
...learnerLocale !== void 0 ? { learnerLocale } : {}
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
function aiHintRequest(input) {
|
|
389
|
+
const { data, previousHints, learnerLocale } = input;
|
|
390
|
+
if (!aiSupports(data.type, "hint") || !aiAllowedByContent(data, "hint") || data.redacted === true) {
|
|
391
|
+
return null;
|
|
392
|
+
}
|
|
393
|
+
const response = _nullishCoalesce(input.response, () => ( emptyResponse(data.type)));
|
|
394
|
+
const local = response === null ? null : gradeLocally(data, response);
|
|
395
|
+
const facts = buildAiFacts(data, response, _nullishCoalesce(_optionalChain([local, 'optionalAccess', _21 => _21.details]), () => ( null)));
|
|
396
|
+
if (facts === null) {
|
|
397
|
+
return null;
|
|
398
|
+
}
|
|
399
|
+
return {
|
|
400
|
+
feature: "hint",
|
|
401
|
+
facts,
|
|
402
|
+
hintNumber: previousHints.length + 1,
|
|
403
|
+
previousHints: [...previousHints],
|
|
404
|
+
...learnerLocale !== void 0 ? { learnerLocale } : {}
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
var VERDICTS = ["correct", "partly-correct", "incorrect"];
|
|
408
|
+
function provenanceOf(raw) {
|
|
409
|
+
if (typeof raw !== "object" || raw === null) {
|
|
410
|
+
return void 0;
|
|
411
|
+
}
|
|
412
|
+
const kept = {};
|
|
413
|
+
for (const key of ["model", "promptHash", "generatedAt"]) {
|
|
414
|
+
const value = raw[key];
|
|
415
|
+
if (typeof value === "string" && value.length > 0 && value.length <= 200) {
|
|
416
|
+
kept[key] = value;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
return Object.keys(kept).length > 0 ? kept : void 0;
|
|
420
|
+
}
|
|
421
|
+
function cleanText(text) {
|
|
422
|
+
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();
|
|
423
|
+
}
|
|
424
|
+
function readAiTextResult(raw) {
|
|
425
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
426
|
+
return { ok: false, refusal: "malformed" };
|
|
427
|
+
}
|
|
428
|
+
const record = raw;
|
|
429
|
+
if (typeof record.text !== "string") {
|
|
430
|
+
return { ok: false, refusal: "malformed" };
|
|
431
|
+
}
|
|
432
|
+
if (record.verdict !== void 0 && !VERDICTS.includes(record.verdict)) {
|
|
433
|
+
return { ok: false, refusal: "malformed" };
|
|
434
|
+
}
|
|
435
|
+
const text = cleanText(record.text);
|
|
436
|
+
if (text === "") {
|
|
437
|
+
return { ok: false, refusal: "empty" };
|
|
438
|
+
}
|
|
439
|
+
if ([...text].length > AI_TEXT_MAX_LENGTH) {
|
|
440
|
+
return { ok: false, refusal: "too-long" };
|
|
441
|
+
}
|
|
442
|
+
const provenance = provenanceOf(record.provenance);
|
|
443
|
+
return {
|
|
444
|
+
ok: true,
|
|
445
|
+
result: {
|
|
446
|
+
text,
|
|
447
|
+
...record.verdict !== void 0 ? { verdict: record.verdict } : {},
|
|
448
|
+
...provenance !== void 0 ? { provenance } : {}
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
function checkAiExplanation(raw, request) {
|
|
453
|
+
const read = readAiTextResult(raw);
|
|
454
|
+
if (!read.ok) {
|
|
455
|
+
return read;
|
|
456
|
+
}
|
|
457
|
+
if (read.result.verdict !== void 0 && read.result.verdict !== request.grade.category) {
|
|
458
|
+
return { ok: false, refusal: "contradicts-grade" };
|
|
459
|
+
}
|
|
460
|
+
return read;
|
|
461
|
+
}
|
|
462
|
+
function checkAiHint(raw, request) {
|
|
463
|
+
const read = readAiTextResult(raw);
|
|
464
|
+
if (!read.ok) {
|
|
465
|
+
return read;
|
|
466
|
+
}
|
|
467
|
+
if (hintRevealsAnswer(request.facts, read.result.text)) {
|
|
468
|
+
return { ok: false, refusal: "reveals-answer" };
|
|
469
|
+
}
|
|
470
|
+
return read;
|
|
471
|
+
}
|
|
472
|
+
function fold(text) {
|
|
473
|
+
const folded = text.normalize("NFKD").replace(/\p{M}/gu, "").toLowerCase().replace(/[^\p{L}\p{N}]+/gu, " ").trim();
|
|
474
|
+
return folded === "" ? [] : folded.split(" ");
|
|
475
|
+
}
|
|
476
|
+
function containsWords(haystack, needle) {
|
|
477
|
+
if (needle.length === 0 || needle.length > haystack.length) {
|
|
478
|
+
return false;
|
|
479
|
+
}
|
|
480
|
+
for (let start = 0; start + needle.length <= haystack.length; start += 1) {
|
|
481
|
+
let match = true;
|
|
482
|
+
for (let offset = 0; offset < needle.length; offset += 1) {
|
|
483
|
+
if (haystack[start + offset] !== needle[offset]) {
|
|
484
|
+
match = false;
|
|
485
|
+
break;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
if (match) {
|
|
489
|
+
return true;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
return false;
|
|
493
|
+
}
|
|
494
|
+
var isShort = (words) => words.length === 1 && [...words[0]].length < 4;
|
|
495
|
+
function neighbours(passage, position) {
|
|
496
|
+
const marker = `[${position}]`;
|
|
497
|
+
const at = passage.indexOf(marker);
|
|
498
|
+
if (at === -1) {
|
|
499
|
+
return {};
|
|
500
|
+
}
|
|
501
|
+
const strip = (text) => text.replace(/\[\d+\]/g, " ");
|
|
502
|
+
const left = fold(strip(passage.slice(0, at)));
|
|
503
|
+
const right = fold(strip(passage.slice(at + marker.length)));
|
|
504
|
+
const before = left[left.length - 1];
|
|
505
|
+
const after = right[0];
|
|
506
|
+
return {
|
|
507
|
+
...before !== void 0 ? { before } : {},
|
|
508
|
+
...after !== void 0 ? { after } : {}
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
function hintRevealsAnswer(facts, hint) {
|
|
512
|
+
const words = fold(hint);
|
|
513
|
+
const reveals = (answer, passage, position) => {
|
|
514
|
+
const needle = fold(answer);
|
|
515
|
+
if (needle.length === 0) {
|
|
516
|
+
return false;
|
|
517
|
+
}
|
|
518
|
+
if (!isShort(needle) || passage === void 0 || position === void 0) {
|
|
519
|
+
return containsWords(words, needle);
|
|
520
|
+
}
|
|
521
|
+
const { before, after } = neighbours(passage, position);
|
|
522
|
+
if (before === void 0 && after === void 0) {
|
|
523
|
+
return containsWords(words, needle);
|
|
524
|
+
}
|
|
525
|
+
return before !== void 0 && containsWords(words, [before, ...needle]) || after !== void 0 && containsWords(words, [...needle, after]);
|
|
526
|
+
};
|
|
527
|
+
switch (facts.activityType) {
|
|
528
|
+
case "multiple-choice":
|
|
529
|
+
return facts.options.some((option) => option.correct === true && reveals(option.text));
|
|
530
|
+
case "fill-in-the-blanks":
|
|
531
|
+
return facts.blanks.some(
|
|
532
|
+
(blank) => (_nullishCoalesce(blank.accepted, () => ( []))).some((answer) => reveals(answer, facts.passage, blank.position))
|
|
533
|
+
);
|
|
534
|
+
case "gap-select":
|
|
535
|
+
return facts.gaps.some(
|
|
536
|
+
(gap) => gap.answer !== null && reveals(gap.answer, facts.passage, gap.position)
|
|
537
|
+
);
|
|
538
|
+
case "dictation":
|
|
539
|
+
return false;
|
|
540
|
+
default:
|
|
541
|
+
return false;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
138
544
|
|
|
139
545
|
// src/content-hash.ts
|
|
140
546
|
function canonicalJson(value, seen = /* @__PURE__ */ new Set()) {
|
|
@@ -283,7 +689,7 @@ function flattenSequence(entries, options = {}) {
|
|
|
283
689
|
const presented = timeline !== void 0 ? inQuizOrder(items, timeline) : entry.shuffle === "within-group" ? seededShuffle(items, `${seed}:group:${entry.id}`) : items;
|
|
284
690
|
const size = presented.length;
|
|
285
691
|
presented.forEach(({ item, itemIndex }, position) => {
|
|
286
|
-
const cue = _optionalChain([timeline, 'optionalAccess',
|
|
692
|
+
const cue = _optionalChain([timeline, 'optionalAccess', _22 => _22.cues, 'access', _23 => _23.find, 'call', _24 => _24((candidate) => candidate.itemIds.includes(item.id))]);
|
|
287
693
|
slots.push({
|
|
288
694
|
// Slot ids stay AUTHORED — the item's index or its key — whatever the
|
|
289
695
|
// presented order: moving a quiz must never re-map a stored answer.
|
|
@@ -337,16 +743,16 @@ function stimulusMediaKey(slotId) {
|
|
|
337
743
|
}
|
|
338
744
|
function resolvePlaybackPolicy(media) {
|
|
339
745
|
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',
|
|
746
|
+
const budgeted = typeof _optionalChain([p, 'optionalAccess', _25 => _25.maxPlays]) === "number";
|
|
747
|
+
const seek = _nullishCoalesce(_optionalChain([p, 'optionalAccess', _26 => _26.seek]), () => ( (budgeted ? "none" : "allow")));
|
|
748
|
+
const rate = _nullishCoalesce(_optionalChain([p, 'optionalAccess', _27 => _27.rate]), () => ( "allow"));
|
|
749
|
+
const controls = _nullishCoalesce(_optionalChain([p, 'optionalAccess', _28 => _28.controls]), () => ( (budgeted || seek === "none" || rate === "fixed" ? "minimal" : "native")));
|
|
344
750
|
return {
|
|
345
751
|
controls,
|
|
346
|
-
maxPlays: budgeted ? _optionalChain([p, 'optionalAccess',
|
|
752
|
+
maxPlays: budgeted ? _optionalChain([p, 'optionalAccess', _29 => _29.maxPlays]) : null,
|
|
347
753
|
seek,
|
|
348
754
|
rate,
|
|
349
|
-
nativeControlHints: _nullishCoalesce(_optionalChain([p, 'optionalAccess',
|
|
755
|
+
nativeControlHints: _nullishCoalesce(_optionalChain([p, 'optionalAccess', _30 => _30.nativeControlHints]), () => ( []))
|
|
350
756
|
};
|
|
351
757
|
}
|
|
352
758
|
function planMediaBudgets(plan) {
|
|
@@ -361,7 +767,7 @@ function planMediaBudgets(plan) {
|
|
|
361
767
|
function assertEntry(key, entry) {
|
|
362
768
|
if (entry === null || typeof entry !== "object" || !Number.isInteger(entry.plays) || entry.plays < 0) {
|
|
363
769
|
throw new Error(
|
|
364
|
-
`serializeMediaPlayLedger: play count for ${JSON.stringify(key)} is ${JSON.stringify(_optionalChain([entry, 'optionalAccess',
|
|
770
|
+
`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
771
|
);
|
|
366
772
|
}
|
|
367
773
|
if (entry.at !== void 0 && (!Number.isFinite(entry.at) || entry.at < 0)) {
|
|
@@ -434,7 +840,7 @@ function mediaBudgetsOf(slot) {
|
|
|
434
840
|
budgets.push({ key: slotMediaKey(slot.slotId), maxPlays });
|
|
435
841
|
}
|
|
436
842
|
}
|
|
437
|
-
const stimulusMedia = _optionalChain([slot, 'access',
|
|
843
|
+
const stimulusMedia = _optionalChain([slot, 'access', _32 => _32.group, 'optionalAccess', _33 => _33.stimulus, 'access', _34 => _34.media]);
|
|
438
844
|
if (stimulusMedia !== void 0) {
|
|
439
845
|
const maxPlays = resolvePlaybackPolicy(stimulusMedia).maxPlays;
|
|
440
846
|
if (maxPlays !== null) {
|
|
@@ -500,7 +906,7 @@ function planAttempt(entries, options = {}) {
|
|
|
500
906
|
...seed !== void 0 ? { seed } : {}
|
|
501
907
|
});
|
|
502
908
|
assertNoSplitBudgets(slots);
|
|
503
|
-
const planned = slots.map((slot) => planSlot(slot, _nullishCoalesce(_optionalChain([points, 'optionalCall',
|
|
909
|
+
const planned = slots.map((slot) => planSlot(slot, _nullishCoalesce(_optionalChain([points, 'optionalCall', _35 => _35(slot)]), () => ( 1))));
|
|
504
910
|
const totalPoints = planned.reduce((sum, slot) => sum + slot.points, 0);
|
|
505
911
|
return {
|
|
506
912
|
planVersion: "1.0",
|
|
@@ -532,10 +938,10 @@ function verifyAttemptPlan(plan, current) {
|
|
|
532
938
|
if (now.contentHash !== slot.contentHash) {
|
|
533
939
|
changedSlotIds.push(slot.slotId);
|
|
534
940
|
}
|
|
535
|
-
if (_optionalChain([now, 'access',
|
|
941
|
+
if (_optionalChain([now, 'access', _36 => _36.group, 'optionalAccess', _37 => _37.stimulusHash]) !== _optionalChain([slot, 'access', _38 => _38.group, 'optionalAccess', _39 => _39.stimulusHash])) {
|
|
536
942
|
changedStimulusSlotIds.push(slot.slotId);
|
|
537
943
|
}
|
|
538
|
-
if (contentHash(_nullishCoalesce(_optionalChain([now, 'access',
|
|
944
|
+
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
945
|
changedCueSlotIds.push(slot.slotId);
|
|
540
946
|
}
|
|
541
947
|
if (now.points !== slot.points) {
|
|
@@ -708,22 +1114,22 @@ function createInteractiveVideoDraft(context) {
|
|
|
708
1114
|
};
|
|
709
1115
|
}
|
|
710
1116
|
function validateItemGroupDraft(draft) {
|
|
711
|
-
return
|
|
1117
|
+
return _chunkD4TOPSHVcjs.withValidationScope.call(void 0, () => validateItemGroupDraftInScope(draft));
|
|
712
1118
|
}
|
|
713
1119
|
function validateItemGroupDraftInScope(draft) {
|
|
714
1120
|
const issues = [];
|
|
715
|
-
if (!
|
|
1121
|
+
if (!_chunkD4TOPSHVcjs.isRecord.call(void 0, draft)) {
|
|
716
1122
|
issues.push(
|
|
717
|
-
|
|
1123
|
+
_chunkD4TOPSHVcjs.issue.call(void 0, "ig_not_an_object", [], "A group must be an object with a stimulus and its items.")
|
|
718
1124
|
);
|
|
719
1125
|
return { status: "invalid", issues };
|
|
720
1126
|
}
|
|
721
1127
|
issues.push(...checkGroupIdentity(draft));
|
|
722
|
-
if (
|
|
1128
|
+
if (_chunkD4TOPSHVcjs.isRecord.call(void 0, draft.stimulus)) {
|
|
723
1129
|
issues.push(...checkStimulus(draft.stimulus));
|
|
724
|
-
} else if (
|
|
1130
|
+
} else if (_chunkD4TOPSHVcjs.isUnset.call(void 0, draft.stimulus)) {
|
|
725
1131
|
issues.push(
|
|
726
|
-
|
|
1132
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
727
1133
|
"ig_stimulus_required",
|
|
728
1134
|
["stimulus"],
|
|
729
1135
|
"Add the passage, recording or image the questions are about."
|
|
@@ -734,26 +1140,26 @@ function validateItemGroupDraftInScope(draft) {
|
|
|
734
1140
|
if (draft.timeline !== void 0 && draft.timeline !== null) {
|
|
735
1141
|
issues.push(...checkTimeline(draft));
|
|
736
1142
|
}
|
|
737
|
-
const captions =
|
|
1143
|
+
const captions = _chunkD4TOPSHVcjs.groupCaptionsField.call(void 0, draft, (captionsUrl) => !_chunkD4TOPSHVcjs.isUnwritten.call(void 0, captionsUrl));
|
|
738
1144
|
if (captions !== void 0) {
|
|
739
1145
|
issues.push(
|
|
740
|
-
|
|
1146
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
741
1147
|
"dc_captions_not_allowed",
|
|
742
1148
|
["stimulus", "media", captions],
|
|
743
|
-
|
|
1149
|
+
_chunkD4TOPSHVcjs.GROUP_CAPTIONS_REVEAL_DICTATION
|
|
744
1150
|
)
|
|
745
1151
|
);
|
|
746
1152
|
}
|
|
747
|
-
const parsed =
|
|
1153
|
+
const parsed = _chunk2CV6NU32cjs.ItemGroupSchema.safeParse(draft, { reportInput: true });
|
|
748
1154
|
if (!parsed.success) {
|
|
749
1155
|
for (const schemaIssue of parsed.error.issues) {
|
|
750
1156
|
const path = schemaIssue.path.map(String);
|
|
751
|
-
if (issues.some((known) =>
|
|
1157
|
+
if (issues.some((known) => _chunkD4TOPSHVcjs.covers.call(void 0, known.path, path))) {
|
|
752
1158
|
continue;
|
|
753
1159
|
}
|
|
754
|
-
if (path.length > 0 &&
|
|
1160
|
+
if (path.length > 0 && _chunkD4TOPSHVcjs.refusesEmpty.call(void 0, draft, schemaIssue)) {
|
|
755
1161
|
issues.push(
|
|
756
|
-
|
|
1162
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
757
1163
|
"null_not_allowed",
|
|
758
1164
|
path,
|
|
759
1165
|
"This field cannot be null. Leave it out if it is optional, or give it a value."
|
|
@@ -769,7 +1175,7 @@ function validateItemGroupDraftInScope(draft) {
|
|
|
769
1175
|
});
|
|
770
1176
|
}
|
|
771
1177
|
}
|
|
772
|
-
const stored =
|
|
1178
|
+
const stored = _chunk2CV6NU32cjs.validateItemGroup.call(void 0, draft);
|
|
773
1179
|
if (issues.length === 0 && stored.success) {
|
|
774
1180
|
return { status: "complete", data: stored.data, issues };
|
|
775
1181
|
}
|
|
@@ -784,21 +1190,21 @@ function validateItemGroupDraftInScope(draft) {
|
|
|
784
1190
|
function checkTimeline(draft) {
|
|
785
1191
|
const issues = [];
|
|
786
1192
|
const timeline = draft.timeline;
|
|
787
|
-
if (!
|
|
1193
|
+
if (!_chunkD4TOPSHVcjs.isRecord.call(void 0, timeline)) {
|
|
788
1194
|
return issues;
|
|
789
1195
|
}
|
|
790
|
-
const stimulus =
|
|
791
|
-
if (stimulus !== void 0 && !
|
|
1196
|
+
const stimulus = _chunkD4TOPSHVcjs.isRecord.call(void 0, draft.stimulus) ? draft.stimulus : void 0;
|
|
1197
|
+
if (stimulus !== void 0 && !_chunkD4TOPSHVcjs.isUnwritten.call(void 0, stimulus.kind) && stimulus.kind !== "video") {
|
|
792
1198
|
issues.push(
|
|
793
|
-
|
|
1199
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
794
1200
|
"ig_timeline_stimulus_kind",
|
|
795
1201
|
["stimulus", "kind"],
|
|
796
1202
|
"An interactive video needs a video: quizzes open at moments of it."
|
|
797
1203
|
)
|
|
798
1204
|
);
|
|
799
|
-
} else if (stimulus !== void 0 &&
|
|
1205
|
+
} 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
1206
|
issues.push(
|
|
801
|
-
|
|
1207
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
802
1208
|
"ig_timeline_stimulus_kind",
|
|
803
1209
|
["stimulus", "media", "type"],
|
|
804
1210
|
"Upload a video file. An embedded player from another site cannot be paused when a quiz opens."
|
|
@@ -807,7 +1213,7 @@ function checkTimeline(draft) {
|
|
|
807
1213
|
}
|
|
808
1214
|
if (draft.shuffle === "within-group") {
|
|
809
1215
|
issues.push(
|
|
810
|
-
|
|
1216
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
811
1217
|
"ig_timeline_shuffle",
|
|
812
1218
|
["shuffle"],
|
|
813
1219
|
"The questions of an interactive video appear in the order their quizzes open, so they cannot be shuffled."
|
|
@@ -817,25 +1223,25 @@ function checkTimeline(draft) {
|
|
|
817
1223
|
const items = Array.isArray(draft.items) ? draft.items : [];
|
|
818
1224
|
const itemIndexById = /* @__PURE__ */ new Map();
|
|
819
1225
|
items.forEach((item, index) => {
|
|
820
|
-
if (!
|
|
1226
|
+
if (!_chunkD4TOPSHVcjs.isRecord.call(void 0, item)) {
|
|
821
1227
|
return;
|
|
822
1228
|
}
|
|
823
1229
|
if (typeof item.id === "string" && item.id !== "") {
|
|
824
1230
|
itemIndexById.set(item.id, index);
|
|
825
1231
|
}
|
|
826
1232
|
const type = item.type;
|
|
827
|
-
if (typeof type === "string" && type !== "" && type !== "item-group" && !
|
|
1233
|
+
if (typeof type === "string" && type !== "" && type !== "item-group" && !_chunk2CV6NU32cjs.isInteractiveVideoItemType.call(void 0, type) && _chunkD4TOPSHVcjs.getActivityTypeDescriptor.call(void 0, type) !== void 0) {
|
|
828
1234
|
issues.push(
|
|
829
|
-
|
|
1235
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
830
1236
|
"ig_timeline_item_type",
|
|
831
1237
|
["items", index, "type"],
|
|
832
|
-
`An interactive video can hold ${
|
|
1238
|
+
`An interactive video can hold ${_chunk2CV6NU32cjs.INTERACTIVE_VIDEO_ITEM_TYPES.join(", ")} questions only.`
|
|
833
1239
|
)
|
|
834
1240
|
);
|
|
835
1241
|
}
|
|
836
|
-
if (type === "dictation" &&
|
|
1242
|
+
if (type === "dictation" && _chunkD4TOPSHVcjs.isUnset.call(void 0, item.media)) {
|
|
837
1243
|
issues.push(
|
|
838
|
-
|
|
1244
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
839
1245
|
"ig_timeline_dictation_media",
|
|
840
1246
|
["items", index, "media"],
|
|
841
1247
|
"Add the recording this dictation plays: inside a video it cannot play the video."
|
|
@@ -847,7 +1253,7 @@ function checkTimeline(draft) {
|
|
|
847
1253
|
const quizIds = /* @__PURE__ */ new Set();
|
|
848
1254
|
const placed = /* @__PURE__ */ new Set();
|
|
849
1255
|
cues.forEach((cue, cueIndex) => {
|
|
850
|
-
if (!
|
|
1256
|
+
if (!_chunkD4TOPSHVcjs.isRecord.call(void 0, cue)) {
|
|
851
1257
|
return;
|
|
852
1258
|
}
|
|
853
1259
|
const at = (field, ...rest) => [
|
|
@@ -857,19 +1263,19 @@ function checkTimeline(draft) {
|
|
|
857
1263
|
field,
|
|
858
1264
|
...rest
|
|
859
1265
|
];
|
|
860
|
-
if (
|
|
861
|
-
issues.push(
|
|
1266
|
+
if (_chunkD4TOPSHVcjs.isMissingId.call(void 0, cue.id)) {
|
|
1267
|
+
issues.push(_chunkD4TOPSHVcjs.issue.call(void 0, "ig_timeline_quiz_id_required", at("id"), "This quiz has no id."));
|
|
862
1268
|
} else if (typeof cue.id === "string") {
|
|
863
1269
|
if (quizIds.has(cue.id)) {
|
|
864
1270
|
issues.push(
|
|
865
|
-
|
|
1271
|
+
_chunkD4TOPSHVcjs.issue.call(void 0, "ig_timeline_quiz_id_duplicate", at("id"), `Two quizzes share the id "${cue.id}".`)
|
|
866
1272
|
);
|
|
867
1273
|
}
|
|
868
1274
|
quizIds.add(cue.id);
|
|
869
1275
|
}
|
|
870
|
-
if (
|
|
1276
|
+
if (_chunkD4TOPSHVcjs.isUnset.call(void 0, cue.at)) {
|
|
871
1277
|
issues.push(
|
|
872
|
-
|
|
1278
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
873
1279
|
"ig_timeline_quiz_time_required",
|
|
874
1280
|
at("at"),
|
|
875
1281
|
"Choose when in the video this quiz opens."
|
|
@@ -877,16 +1283,16 @@ function checkTimeline(draft) {
|
|
|
877
1283
|
);
|
|
878
1284
|
} else if (typeof cue.at !== "number" || !Number.isFinite(cue.at) || cue.at < 0) {
|
|
879
1285
|
issues.push(
|
|
880
|
-
|
|
1286
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
881
1287
|
"ig_timeline_quiz_time_invalid",
|
|
882
1288
|
at("at"),
|
|
883
1289
|
"A quiz opens at a number of seconds, 0 or more."
|
|
884
1290
|
)
|
|
885
1291
|
);
|
|
886
1292
|
}
|
|
887
|
-
if (
|
|
1293
|
+
if (_chunkD4TOPSHVcjs.isUnset.call(void 0, cue.itemIds) || Array.isArray(cue.itemIds) && cue.itemIds.length === 0) {
|
|
888
1294
|
issues.push(
|
|
889
|
-
|
|
1295
|
+
_chunkD4TOPSHVcjs.issue.call(void 0, "ig_timeline_quiz_empty", at("itemIds"), "Add at least one question to this quiz.")
|
|
890
1296
|
);
|
|
891
1297
|
return;
|
|
892
1298
|
}
|
|
@@ -899,7 +1305,7 @@ function checkTimeline(draft) {
|
|
|
899
1305
|
}
|
|
900
1306
|
if (!itemIndexById.has(itemId)) {
|
|
901
1307
|
issues.push(
|
|
902
|
-
|
|
1308
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
903
1309
|
"ig_timeline_quiz_unknown_item",
|
|
904
1310
|
at("itemIds", position),
|
|
905
1311
|
`This quiz names a question that is not in the video ("${itemId}").`
|
|
@@ -907,7 +1313,7 @@ function checkTimeline(draft) {
|
|
|
907
1313
|
);
|
|
908
1314
|
} else if (placed.has(itemId)) {
|
|
909
1315
|
issues.push(
|
|
910
|
-
|
|
1316
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
911
1317
|
"ig_timeline_item_duplicate",
|
|
912
1318
|
at("itemIds", position),
|
|
913
1319
|
"This question is already in a quiz: each question belongs to one quiz."
|
|
@@ -920,7 +1326,7 @@ function checkTimeline(draft) {
|
|
|
920
1326
|
for (const [itemId, index] of itemIndexById) {
|
|
921
1327
|
if (!placed.has(itemId)) {
|
|
922
1328
|
issues.push(
|
|
923
|
-
|
|
1329
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
924
1330
|
"ig_timeline_item_unplaced",
|
|
925
1331
|
["items", index],
|
|
926
1332
|
"Add this question to a quiz, or the video never shows it."
|
|
@@ -931,12 +1337,12 @@ function checkTimeline(draft) {
|
|
|
931
1337
|
const chapters = Array.isArray(timeline.chapters) ? timeline.chapters : [];
|
|
932
1338
|
let previousAt;
|
|
933
1339
|
chapters.forEach((chapter, index) => {
|
|
934
|
-
if (!
|
|
1340
|
+
if (!_chunkD4TOPSHVcjs.isRecord.call(void 0, chapter)) {
|
|
935
1341
|
return;
|
|
936
1342
|
}
|
|
937
|
-
if (
|
|
1343
|
+
if (_chunkD4TOPSHVcjs.isUnwritten.call(void 0, chapter.title)) {
|
|
938
1344
|
issues.push(
|
|
939
|
-
|
|
1345
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
940
1346
|
"ig_timeline_chapter_title",
|
|
941
1347
|
["timeline", "chapters", index, "title"],
|
|
942
1348
|
"Give this chapter a title."
|
|
@@ -946,7 +1352,7 @@ function checkTimeline(draft) {
|
|
|
946
1352
|
if (typeof chapter.at === "number" && Number.isFinite(chapter.at)) {
|
|
947
1353
|
if (previousAt !== void 0 && chapter.at <= previousAt) {
|
|
948
1354
|
issues.push(
|
|
949
|
-
|
|
1355
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
950
1356
|
"ig_timeline_chapter_order",
|
|
951
1357
|
["timeline", "chapters", index, "at"],
|
|
952
1358
|
"Chapters must start in order, each after the one before it."
|
|
@@ -962,7 +1368,7 @@ function checkGroupIdentity(draft) {
|
|
|
962
1368
|
const issues = [];
|
|
963
1369
|
if (draft.schemaVersion !== "1.0") {
|
|
964
1370
|
issues.push(
|
|
965
|
-
|
|
1371
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
966
1372
|
"schema_version_invalid",
|
|
967
1373
|
["schemaVersion"],
|
|
968
1374
|
'The draft must have schemaVersion "1.0". A draft from createItemGroupDraft has it.'
|
|
@@ -970,14 +1376,14 @@ function checkGroupIdentity(draft) {
|
|
|
970
1376
|
);
|
|
971
1377
|
}
|
|
972
1378
|
if (draft.type !== "item-group") {
|
|
973
|
-
issues.push(
|
|
1379
|
+
issues.push(_chunkD4TOPSHVcjs.issue.call(void 0, "type_mismatch", ["type"], `The draft's type must be "item-group".`));
|
|
974
1380
|
}
|
|
975
|
-
if (
|
|
976
|
-
issues.push(
|
|
1381
|
+
if (_chunkD4TOPSHVcjs.isMissingId.call(void 0, draft.id)) {
|
|
1382
|
+
issues.push(_chunkD4TOPSHVcjs.issue.call(void 0, "id_required", ["id"], "The group has no id."));
|
|
977
1383
|
}
|
|
978
|
-
if (!
|
|
1384
|
+
if (!_chunkD4TOPSHVcjs.isUnset.call(void 0, draft.shuffle) && draft.shuffle !== "none" && draft.shuffle !== "within-group") {
|
|
979
1385
|
issues.push(
|
|
980
|
-
|
|
1386
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
981
1387
|
"ig_shuffle_invalid",
|
|
982
1388
|
["shuffle"],
|
|
983
1389
|
'Shuffling is either "none" or "within-group". Leave it out to keep the authored order.'
|
|
@@ -996,13 +1402,13 @@ var MEDIA_FOR_KIND = {
|
|
|
996
1402
|
function checkStimulus(stimulus) {
|
|
997
1403
|
const issues = [];
|
|
998
1404
|
const at = (...rest) => ["stimulus", ...rest];
|
|
999
|
-
if (
|
|
1000
|
-
issues.push(
|
|
1405
|
+
if (_chunkD4TOPSHVcjs.isMissingId.call(void 0, stimulus.id)) {
|
|
1406
|
+
issues.push(_chunkD4TOPSHVcjs.issue.call(void 0, "ig_stimulus_id_required", at("id"), "The stimulus has no id."));
|
|
1001
1407
|
}
|
|
1002
1408
|
const kind = stimulus.kind;
|
|
1003
|
-
if (
|
|
1409
|
+
if (_chunkD4TOPSHVcjs.isUnwritten.call(void 0, kind)) {
|
|
1004
1410
|
issues.push(
|
|
1005
|
-
|
|
1411
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1006
1412
|
"ig_stimulus_kind_required",
|
|
1007
1413
|
at("kind"),
|
|
1008
1414
|
"Choose what the questions are about: a text, a recording, a video, an image, or a mix."
|
|
@@ -1011,71 +1417,71 @@ function checkStimulus(stimulus) {
|
|
|
1011
1417
|
} else if (typeof kind !== "string" || !KINDS.has(kind)) {
|
|
1012
1418
|
if (typeof kind === "string") {
|
|
1013
1419
|
issues.push(
|
|
1014
|
-
|
|
1420
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1015
1421
|
"ig_stimulus_kind_invalid",
|
|
1016
1422
|
at("kind"),
|
|
1017
1423
|
`"${kind}" is not a stimulus kind. Use text, audio, video, image or mixed.`
|
|
1018
1424
|
)
|
|
1019
1425
|
);
|
|
1020
1426
|
}
|
|
1021
|
-
if (
|
|
1022
|
-
issues.push(...
|
|
1427
|
+
if (_chunkD4TOPSHVcjs.isRecord.call(void 0, stimulus.media)) {
|
|
1428
|
+
issues.push(..._chunkD4TOPSHVcjs.checkMedia.call(void 0, stimulus.media, at("media")));
|
|
1023
1429
|
}
|
|
1024
1430
|
return issues;
|
|
1025
1431
|
}
|
|
1026
1432
|
const hasBody = typeof stimulus.body === "string" && stimulus.body.trim() !== "";
|
|
1027
|
-
const htmlPresent = !
|
|
1433
|
+
const htmlPresent = !_chunkD4TOPSHVcjs.isUnset.call(void 0, stimulus.bodyHtml);
|
|
1028
1434
|
if (!hasBody && (kind === "text" || kind === "mixed" || htmlPresent)) {
|
|
1029
1435
|
issues.push(
|
|
1030
|
-
|
|
1436
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1031
1437
|
"ig_stimulus_body_required",
|
|
1032
1438
|
at("body"),
|
|
1033
|
-
|
|
1439
|
+
_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
1440
|
)
|
|
1035
1441
|
);
|
|
1036
1442
|
}
|
|
1037
|
-
if (kind !== "text" &&
|
|
1443
|
+
if (kind !== "text" && _chunkD4TOPSHVcjs.isUnset.call(void 0, stimulus.media)) {
|
|
1038
1444
|
issues.push(
|
|
1039
|
-
|
|
1445
|
+
_chunkD4TOPSHVcjs.issue.call(void 0, "ig_stimulus_media_required", at("media"), "Add the recording, video or image.")
|
|
1040
1446
|
);
|
|
1041
|
-
} else if (
|
|
1447
|
+
} else if (_chunkD4TOPSHVcjs.isRecord.call(void 0, stimulus.media)) {
|
|
1042
1448
|
const allowed = MEDIA_FOR_KIND[kind];
|
|
1043
1449
|
const mediaType = stimulus.media.type;
|
|
1044
1450
|
if (allowed !== void 0 && typeof mediaType === "string" && !allowed.includes(mediaType)) {
|
|
1045
1451
|
issues.push(
|
|
1046
|
-
|
|
1452
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1047
1453
|
"ig_stimulus_media_kind",
|
|
1048
1454
|
at("media", "type"),
|
|
1049
1455
|
`A "${kind}" stimulus cannot carry ${mediaType} media. Use ${allowed.join(" or ")}.`
|
|
1050
1456
|
)
|
|
1051
1457
|
);
|
|
1052
1458
|
}
|
|
1053
|
-
issues.push(...
|
|
1459
|
+
issues.push(..._chunkD4TOPSHVcjs.checkMedia.call(void 0, stimulus.media, at("media")));
|
|
1054
1460
|
}
|
|
1055
1461
|
return issues;
|
|
1056
1462
|
}
|
|
1057
1463
|
function checkItems(draft) {
|
|
1058
1464
|
const issues = [];
|
|
1059
|
-
const items =
|
|
1465
|
+
const items = _chunkD4TOPSHVcjs.isUnset.call(void 0, draft.items) ? [] : draft.items;
|
|
1060
1466
|
if (!Array.isArray(items)) {
|
|
1061
1467
|
return issues;
|
|
1062
1468
|
}
|
|
1063
1469
|
if (items.length === 0) {
|
|
1064
1470
|
issues.push(
|
|
1065
|
-
|
|
1471
|
+
_chunkD4TOPSHVcjs.issue.call(void 0, "ig_items_required", ["items"], "Add at least one question about this material.")
|
|
1066
1472
|
);
|
|
1067
1473
|
return issues;
|
|
1068
1474
|
}
|
|
1069
1475
|
const seen = /* @__PURE__ */ new Set();
|
|
1070
1476
|
const repeated = /* @__PURE__ */ new Set();
|
|
1071
1477
|
for (const [index, item] of items.entries()) {
|
|
1072
|
-
if (!
|
|
1478
|
+
if (!_chunkD4TOPSHVcjs.isRecord.call(void 0, item)) {
|
|
1073
1479
|
continue;
|
|
1074
1480
|
}
|
|
1075
1481
|
const ordinal = index + 1;
|
|
1076
|
-
if (
|
|
1482
|
+
if (_chunkD4TOPSHVcjs.isMissingId.call(void 0, item.id)) {
|
|
1077
1483
|
issues.push(
|
|
1078
|
-
|
|
1484
|
+
_chunkD4TOPSHVcjs.issue.call(void 0, "ig_item_id_required", ["items", index, "id"], `Question ${ordinal} has no id.`)
|
|
1079
1485
|
);
|
|
1080
1486
|
} else if (typeof item.id === "string") {
|
|
1081
1487
|
if (seen.has(item.id)) {
|
|
@@ -1085,7 +1491,7 @@ function checkItems(draft) {
|
|
|
1085
1491
|
}
|
|
1086
1492
|
if (item.type === "item-group") {
|
|
1087
1493
|
issues.push(
|
|
1088
|
-
|
|
1494
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1089
1495
|
"ig_item_nested_group",
|
|
1090
1496
|
["items", index, "type"],
|
|
1091
1497
|
"Groups do not nest: every item must be an activity."
|
|
@@ -1093,9 +1499,9 @@ function checkItems(draft) {
|
|
|
1093
1499
|
);
|
|
1094
1500
|
continue;
|
|
1095
1501
|
}
|
|
1096
|
-
if (
|
|
1502
|
+
if (_chunkD4TOPSHVcjs.isUnwritten.call(void 0, item.type)) {
|
|
1097
1503
|
issues.push(
|
|
1098
|
-
|
|
1504
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1099
1505
|
"ig_item_type_required",
|
|
1100
1506
|
["items", index, "type"],
|
|
1101
1507
|
`Choose what kind of question ${ordinal} is.`
|
|
@@ -1110,11 +1516,11 @@ function checkItems(draft) {
|
|
|
1110
1516
|
try {
|
|
1111
1517
|
result = validateDraft(item.type, item);
|
|
1112
1518
|
} catch (error) {
|
|
1113
|
-
if (!(error instanceof
|
|
1519
|
+
if (!(error instanceof _chunkD4TOPSHVcjs.UnknownActivityTypeError) || error.activityType !== item.type) {
|
|
1114
1520
|
throw error;
|
|
1115
1521
|
}
|
|
1116
1522
|
issues.push(
|
|
1117
|
-
|
|
1523
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1118
1524
|
"ig_item_type_unknown",
|
|
1119
1525
|
["items", index, "type"],
|
|
1120
1526
|
`"${item.type}" is not a registered activity type.`
|
|
@@ -1128,7 +1534,7 @@ function checkItems(draft) {
|
|
|
1128
1534
|
}
|
|
1129
1535
|
for (const id of repeated) {
|
|
1130
1536
|
issues.push(
|
|
1131
|
-
|
|
1537
|
+
_chunkD4TOPSHVcjs.issue.call(void 0, "ig_item_id_duplicate", ["items"], `More than one question has the id "${id}".`)
|
|
1132
1538
|
);
|
|
1133
1539
|
}
|
|
1134
1540
|
return issues;
|
|
@@ -1136,30 +1542,30 @@ function checkItems(draft) {
|
|
|
1136
1542
|
|
|
1137
1543
|
// src/authoring/index.ts
|
|
1138
1544
|
function validateDraft(type, draft) {
|
|
1139
|
-
return
|
|
1545
|
+
return _chunkD4TOPSHVcjs.withValidationScope.call(void 0, () => validateDraftInScope(type, draft));
|
|
1140
1546
|
}
|
|
1141
1547
|
function validateDraftInScope(type, draft) {
|
|
1142
|
-
const descriptor =
|
|
1548
|
+
const descriptor = _chunkD4TOPSHVcjs.getActivityTypeDescriptor.call(void 0, type);
|
|
1143
1549
|
if (descriptor === void 0) {
|
|
1144
|
-
throw new (0,
|
|
1550
|
+
throw new (0, _chunkD4TOPSHVcjs.UnknownActivityTypeError)(String(type));
|
|
1145
1551
|
}
|
|
1146
|
-
const reported =
|
|
1552
|
+
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
1553
|
const issues = [...reported];
|
|
1148
1554
|
const parsed = descriptor.schema.safeParse(draft, { reportInput: true });
|
|
1149
1555
|
if (!parsed.success) {
|
|
1150
|
-
const covered =
|
|
1556
|
+
const covered = _chunkD4TOPSHVcjs.coveredPathsOf.call(void 0, reported);
|
|
1151
1557
|
const reportedEmpty = /* @__PURE__ */ new Set();
|
|
1152
1558
|
for (const schemaIssue of parsed.error.issues) {
|
|
1153
1559
|
const path = schemaIssue.path.map(String);
|
|
1154
|
-
if (covered.has(
|
|
1560
|
+
if (covered.has(_chunkD4TOPSHVcjs.pathKey.call(void 0, path))) {
|
|
1155
1561
|
continue;
|
|
1156
1562
|
}
|
|
1157
|
-
if (path.length > 0 &&
|
|
1563
|
+
if (path.length > 0 && _chunkD4TOPSHVcjs.refusesEmpty.call(void 0, draft, schemaIssue)) {
|
|
1158
1564
|
const key = JSON.stringify(path);
|
|
1159
1565
|
if (!reportedEmpty.has(key)) {
|
|
1160
1566
|
reportedEmpty.add(key);
|
|
1161
1567
|
issues.push(
|
|
1162
|
-
|
|
1568
|
+
_chunkD4TOPSHVcjs.issue.call(void 0,
|
|
1163
1569
|
"null_not_allowed",
|
|
1164
1570
|
path,
|
|
1165
1571
|
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 +1589,11 @@ function validateDraftInScope(type, draft) {
|
|
|
1183
1589
|
return { status: invalid ? "invalid" : "incomplete", issues };
|
|
1184
1590
|
}
|
|
1185
1591
|
function createDraft(type, context) {
|
|
1186
|
-
const descriptor =
|
|
1592
|
+
const descriptor = _chunkD4TOPSHVcjs.getActivityTypeDescriptor.call(void 0, type);
|
|
1187
1593
|
if (descriptor === void 0) {
|
|
1188
|
-
throw new (0,
|
|
1594
|
+
throw new (0, _chunkD4TOPSHVcjs.UnknownActivityTypeError)(String(type));
|
|
1189
1595
|
}
|
|
1190
|
-
const create = _optionalChain([descriptor, 'access',
|
|
1596
|
+
const create = _optionalChain([descriptor, 'access', _46 => _46.authoring, 'optionalAccess', _47 => _47.createDraft]);
|
|
1191
1597
|
if (create === void 0) {
|
|
1192
1598
|
throw new Error(
|
|
1193
1599
|
`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 +1616,7 @@ function createDraft(type, context) {
|
|
|
1210
1616
|
return create({ newId });
|
|
1211
1617
|
}
|
|
1212
1618
|
function normalise(found) {
|
|
1213
|
-
const documented = Object.hasOwn(
|
|
1619
|
+
const documented = Object.hasOwn(_chunkD4TOPSHVcjs.DRAFT_ISSUE_SEVERITY, found.code) ? _chunkD4TOPSHVcjs.DRAFT_ISSUE_SEVERITY[found.code] : void 0;
|
|
1214
1620
|
return {
|
|
1215
1621
|
...found,
|
|
1216
1622
|
path: found.path.map(String),
|
|
@@ -1219,11 +1625,11 @@ function normalise(found) {
|
|
|
1219
1625
|
}
|
|
1220
1626
|
|
|
1221
1627
|
// src/redact.ts
|
|
1222
|
-
function mergePolicy(
|
|
1628
|
+
function mergePolicy(base2, overrides) {
|
|
1223
1629
|
if (overrides === void 0) {
|
|
1224
|
-
return
|
|
1630
|
+
return base2;
|
|
1225
1631
|
}
|
|
1226
|
-
const merged = { ...
|
|
1632
|
+
const merged = { ...base2 };
|
|
1227
1633
|
for (const [key, override] of Object.entries(overrides)) {
|
|
1228
1634
|
const current = merged[key];
|
|
1229
1635
|
merged[key] = typeof override === "object" && typeof current === "object" ? { ...current, ...override } : override;
|
|
@@ -1274,9 +1680,9 @@ function redactValue(value, policy, reveal) {
|
|
|
1274
1680
|
}
|
|
1275
1681
|
function redact(data, options = {}) {
|
|
1276
1682
|
const reveal = _nullishCoalesce(options.reveal, () => ( "none"));
|
|
1277
|
-
const descriptor =
|
|
1683
|
+
const descriptor = _chunkD4TOPSHVcjs.getActivityTypeDescriptor.call(void 0, data.type);
|
|
1278
1684
|
if (descriptor === void 0) {
|
|
1279
|
-
throw new (0,
|
|
1685
|
+
throw new (0, _chunkD4TOPSHVcjs.UnknownActivityTypeError)(String(data.type));
|
|
1280
1686
|
}
|
|
1281
1687
|
if (descriptor.fieldPolicy === void 0) {
|
|
1282
1688
|
throw new Error(
|
|
@@ -1289,7 +1695,7 @@ function redact(data, options = {}) {
|
|
|
1289
1695
|
if (reveal === "none" && descriptor.redactedSchema !== void 0) {
|
|
1290
1696
|
const parsed = descriptor.redactedSchema.safeParse(result);
|
|
1291
1697
|
if (!parsed.success) {
|
|
1292
|
-
throw new (0,
|
|
1698
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)(
|
|
1293
1699
|
descriptor.type,
|
|
1294
1700
|
parsed.error.issues.map((issue2) => ({
|
|
1295
1701
|
path: issue2.path.map(String),
|
|
@@ -1303,13 +1709,13 @@ function redact(data, options = {}) {
|
|
|
1303
1709
|
}
|
|
1304
1710
|
function assertRedacted(data) {
|
|
1305
1711
|
if (typeof data !== "object" || data === null) {
|
|
1306
|
-
throw new (0,
|
|
1712
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)("unknown", [
|
|
1307
1713
|
{ path: [], message: "Redacted activity data must be an object.", code: "invalid_type" }
|
|
1308
1714
|
]);
|
|
1309
1715
|
}
|
|
1310
1716
|
const candidate = data;
|
|
1311
1717
|
if (candidate.redacted !== true) {
|
|
1312
|
-
throw new (0,
|
|
1718
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)(String(_nullishCoalesce(candidate.type, () => ( "unknown"))), [
|
|
1313
1719
|
{
|
|
1314
1720
|
path: ["redacted"],
|
|
1315
1721
|
message: "Missing redacted marker \u2014 this payload is not a redact() projection.",
|
|
@@ -1318,12 +1724,12 @@ function assertRedacted(data) {
|
|
|
1318
1724
|
]);
|
|
1319
1725
|
}
|
|
1320
1726
|
const type = typeof candidate.type === "string" ? candidate.type : "";
|
|
1321
|
-
const descriptor =
|
|
1727
|
+
const descriptor = _chunkD4TOPSHVcjs.getActivityTypeDescriptor.call(void 0, type);
|
|
1322
1728
|
if (descriptor === void 0) {
|
|
1323
|
-
throw new (0,
|
|
1729
|
+
throw new (0, _chunkD4TOPSHVcjs.UnknownActivityTypeError)(type);
|
|
1324
1730
|
}
|
|
1325
1731
|
if (descriptor.redactedSchema === void 0) {
|
|
1326
|
-
throw new (0,
|
|
1732
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)(descriptor.type, [
|
|
1327
1733
|
{
|
|
1328
1734
|
path: [],
|
|
1329
1735
|
message: `Activity type "${descriptor.type}" registers no redactedSchema; assertRedacted cannot prove this payload is learner-safe.`,
|
|
@@ -1333,7 +1739,7 @@ function assertRedacted(data) {
|
|
|
1333
1739
|
}
|
|
1334
1740
|
const parsed = descriptor.redactedSchema.safeParse(candidate);
|
|
1335
1741
|
if (!parsed.success) {
|
|
1336
|
-
throw new (0,
|
|
1742
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)(
|
|
1337
1743
|
descriptor.type,
|
|
1338
1744
|
parsed.error.issues.map((issue2) => ({
|
|
1339
1745
|
path: issue2.path.map(String),
|
|
@@ -1349,7 +1755,7 @@ var STIMULUS_FIELD_POLICY = {
|
|
|
1349
1755
|
title: "public",
|
|
1350
1756
|
body: "public",
|
|
1351
1757
|
bodyHtml: "public",
|
|
1352
|
-
media:
|
|
1758
|
+
media: _chunkD4TOPSHVcjs.MEDIA_FIELD_POLICY,
|
|
1353
1759
|
locale: "public",
|
|
1354
1760
|
attribution: "public",
|
|
1355
1761
|
transcript: "author-only"
|
|
@@ -1393,9 +1799,9 @@ function redactItemGroup(group, options = {}) {
|
|
|
1393
1799
|
redacted: true
|
|
1394
1800
|
};
|
|
1395
1801
|
if (reveal === "none") {
|
|
1396
|
-
const parsed =
|
|
1802
|
+
const parsed = _chunk2CV6NU32cjs.RedactedItemGroupSchema.safeParse(result);
|
|
1397
1803
|
if (!parsed.success) {
|
|
1398
|
-
throw new (0,
|
|
1804
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)(
|
|
1399
1805
|
"item-group",
|
|
1400
1806
|
parsed.error.issues.map((issue2) => ({
|
|
1401
1807
|
path: issue2.path.map(String),
|
|
@@ -1409,13 +1815,13 @@ function redactItemGroup(group, options = {}) {
|
|
|
1409
1815
|
}
|
|
1410
1816
|
function assertRedactedItemGroup(data) {
|
|
1411
1817
|
if (typeof data !== "object" || data === null) {
|
|
1412
|
-
throw new (0,
|
|
1818
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)("item-group", [
|
|
1413
1819
|
{ path: [], message: "Redacted item group must be an object.", code: "invalid_type" }
|
|
1414
1820
|
]);
|
|
1415
1821
|
}
|
|
1416
1822
|
const candidate = data;
|
|
1417
1823
|
if (candidate.redacted !== true) {
|
|
1418
|
-
throw new (0,
|
|
1824
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)("item-group", [
|
|
1419
1825
|
{
|
|
1420
1826
|
path: ["redacted"],
|
|
1421
1827
|
message: "Missing redacted marker \u2014 this payload is not a redactItemGroup() projection.",
|
|
@@ -1423,9 +1829,9 @@ function assertRedactedItemGroup(data) {
|
|
|
1423
1829
|
}
|
|
1424
1830
|
]);
|
|
1425
1831
|
}
|
|
1426
|
-
const parsed =
|
|
1832
|
+
const parsed = _chunk2CV6NU32cjs.RedactedItemGroupSchema.safeParse(candidate);
|
|
1427
1833
|
if (!parsed.success) {
|
|
1428
|
-
throw new (0,
|
|
1834
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)(
|
|
1429
1835
|
"item-group",
|
|
1430
1836
|
parsed.error.issues.map((issue2) => ({
|
|
1431
1837
|
path: issue2.path.map(String),
|
|
@@ -1438,8 +1844,8 @@ function assertRedactedItemGroup(data) {
|
|
|
1438
1844
|
try {
|
|
1439
1845
|
assertRedacted(item);
|
|
1440
1846
|
} catch (error) {
|
|
1441
|
-
if (error instanceof
|
|
1442
|
-
throw new (0,
|
|
1847
|
+
if (error instanceof _chunkD4TOPSHVcjs.ActivitySchemaError) {
|
|
1848
|
+
throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)(
|
|
1443
1849
|
"item-group",
|
|
1444
1850
|
error.errors.map((issue2) => ({
|
|
1445
1851
|
...issue2,
|
|
@@ -1462,7 +1868,7 @@ function readMediaProgress(value, duration) {
|
|
|
1462
1868
|
return null;
|
|
1463
1869
|
}
|
|
1464
1870
|
({ progressVersion: version, at, furthest } = value);
|
|
1465
|
-
} catch (
|
|
1871
|
+
} catch (e2) {
|
|
1466
1872
|
return null;
|
|
1467
1873
|
}
|
|
1468
1874
|
if (version !== "1.0" || typeof at !== "number" || !Number.isFinite(at)) {
|
|
@@ -1484,7 +1890,7 @@ function composeTimelineScore(entryKey, items, policy) {
|
|
|
1484
1890
|
`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
1891
|
);
|
|
1486
1892
|
}
|
|
1487
|
-
return
|
|
1893
|
+
return _chunkCOBK2RUXcjs.composeAssessmentScore.call(void 0, [{ id: entryKey, weight: 1, items: own }], policy);
|
|
1488
1894
|
}
|
|
1489
1895
|
|
|
1490
1896
|
|
|
@@ -1632,5 +2038,19 @@ function composeTimelineScore(entryKey, items, policy) {
|
|
|
1632
2038
|
|
|
1633
2039
|
|
|
1634
2040
|
|
|
1635
|
-
|
|
2041
|
+
|
|
2042
|
+
|
|
2043
|
+
|
|
2044
|
+
|
|
2045
|
+
|
|
2046
|
+
|
|
2047
|
+
|
|
2048
|
+
|
|
2049
|
+
|
|
2050
|
+
|
|
2051
|
+
|
|
2052
|
+
|
|
2053
|
+
|
|
2054
|
+
|
|
2055
|
+
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 = _chunkCOBK2RUXcjs.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 = _chunkCOBK2RUXcjs.alignReadAloud; exports.assertRedacted = assertRedacted; exports.assertRedactedItemGroup = assertRedactedItemGroup; exports.buildAiFacts = buildAiFacts; exports.canonicalJson = canonicalJson; exports.checkAiExplanation = checkAiExplanation; exports.checkAiHint = checkAiHint; exports.classifyBand = _chunkCOBK2RUXcjs.classifyBand; exports.composeAssessmentScore = _chunkCOBK2RUXcjs.composeAssessmentScore; exports.composeTimelineScore = composeTimelineScore; exports.computePassThreshold = _chunkCOBK2RUXcjs.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 = _chunkCOBK2RUXcjs.diffDictationChars; exports.diffResponses = diffResponses; exports.entryKeyOf = entryKeyOf; exports.evaluate = _chunkCOBK2RUXcjs.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 = _chunkCOBK2RUXcjs.gradeFromRubric; exports.gradeReadAloud = _chunkCOBK2RUXcjs.gradeReadAloud; exports.gte = _chunkCOBK2RUXcjs.gte; exports.hasGrade = _chunkCOBK2RUXcjs.hasGrade; exports.hashSeed = hashSeed; exports.hintRevealsAnswer = hintRevealsAnswer; exports.inspectWav = _chunkCOBK2RUXcjs.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 = _chunkCOBK2RUXcjs.outcomeFromGrade; exports.outcomeFromUnscorable = _chunkCOBK2RUXcjs.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 = _chunkCOBK2RUXcjs.roundGrade; exports.score = _chunkCOBK2RUXcjs.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 = _chunkCOBK2RUXcjs.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
2056
|
//# sourceMappingURL=index.cjs.map
|