@intellectif/lk-core 0.14.1 → 0.15.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.
Files changed (47) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +1 -0
  3. package/dist/{activity-BVkg9VDo.d.cts → activity-C7cR8U9n.d.cts} +35 -2
  4. package/dist/{activity-BVkg9VDo.d.ts → activity-C7cR8U9n.d.ts} +35 -2
  5. package/dist/{chunk-KTDOZR7Y.js → chunk-54XYQ3CS.js} +2 -2
  6. package/dist/{chunk-J5OIRIOW.cjs → chunk-5KWF34LJ.cjs} +31 -31
  7. package/dist/{chunk-J5OIRIOW.cjs.map → chunk-5KWF34LJ.cjs.map} +1 -1
  8. package/dist/{chunk-E7LPIZXI.cjs → chunk-7ETU6EXQ.cjs} +4 -4
  9. package/dist/{chunk-E7LPIZXI.cjs.map → chunk-7ETU6EXQ.cjs.map} +1 -1
  10. package/dist/{chunk-6RND47QE.js → chunk-DPHX4E7X.js} +62 -3
  11. package/dist/chunk-DPHX4E7X.js.map +1 -0
  12. package/dist/{chunk-NBADQ3JU.js → chunk-EEMVWBPP.js} +195 -4
  13. package/dist/chunk-EEMVWBPP.js.map +1 -0
  14. package/dist/{chunk-RTIR6R2U.js → chunk-L6YBQXSB.js} +2 -2
  15. package/dist/{chunk-VCXIPLEW.cjs → chunk-QFWEF5ST.cjs} +63 -4
  16. package/dist/chunk-QFWEF5ST.cjs.map +1 -0
  17. package/dist/chunk-W7AQP6AV.cjs +418 -0
  18. package/dist/chunk-W7AQP6AV.cjs.map +1 -0
  19. package/dist/{index-v2_-Fyn3.d.ts → index-BWyMDlUS.d.cts} +367 -2
  20. package/dist/{index-BE1bM2Wi.d.cts → index-D10NaztZ.d.ts} +367 -2
  21. package/dist/index.cjs +397 -96
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.cts +103 -7
  24. package/dist/index.d.ts +103 -7
  25. package/dist/index.js +310 -9
  26. package/dist/index.js.map +1 -1
  27. package/dist/schemas.cjs +11 -3
  28. package/dist/schemas.cjs.map +1 -1
  29. package/dist/schemas.d.cts +2 -2
  30. package/dist/schemas.d.ts +2 -2
  31. package/dist/schemas.js +10 -2
  32. package/dist/scoring.cjs +3 -3
  33. package/dist/scoring.d.cts +2 -2
  34. package/dist/scoring.d.ts +2 -2
  35. package/dist/scoring.js +2 -2
  36. package/dist/xapi.cjs +3 -3
  37. package/dist/xapi.d.cts +1 -1
  38. package/dist/xapi.d.ts +1 -1
  39. package/dist/xapi.js +2 -2
  40. package/package.json +1 -1
  41. package/dist/chunk-2NIALQEH.cjs +0 -227
  42. package/dist/chunk-2NIALQEH.cjs.map +0 -1
  43. package/dist/chunk-6RND47QE.js.map +0 -1
  44. package/dist/chunk-NBADQ3JU.js.map +0 -1
  45. package/dist/chunk-VCXIPLEW.cjs.map +0 -1
  46. /package/dist/{chunk-KTDOZR7Y.js.map → chunk-54XYQ3CS.js.map} +0 -0
  47. /package/dist/{chunk-RTIR6R2U.js.map → chunk-L6YBQXSB.js.map} +0 -0
package/dist/index.cjs CHANGED
@@ -16,14 +16,14 @@
16
16
 
17
17
 
18
18
 
19
- var _chunkJ5OIRIOWcjs = require('./chunk-J5OIRIOW.cjs');
19
+ var _chunk5KWF34LJcjs = require('./chunk-5KWF34LJ.cjs');
20
20
 
21
21
 
22
22
 
23
23
 
24
24
 
25
25
 
26
- var _chunkE7LPIZXIcjs = require('./chunk-E7LPIZXI.cjs');
26
+ var _chunk7ETU6EXQcjs = require('./chunk-7ETU6EXQ.cjs');
27
27
 
28
28
 
29
29
 
@@ -40,7 +40,6 @@ var _chunkE7LPIZXIcjs = require('./chunk-E7LPIZXI.cjs');
40
40
 
41
41
 
42
42
 
43
- var _chunk2NIALQEHcjs = require('./chunk-2NIALQEH.cjs');
44
43
 
45
44
 
46
45
 
@@ -50,6 +49,7 @@ var _chunk2NIALQEHcjs = require('./chunk-2NIALQEH.cjs');
50
49
 
51
50
 
52
51
 
52
+ var _chunkW7AQP6AVcjs = require('./chunk-W7AQP6AV.cjs');
53
53
 
54
54
 
55
55
 
@@ -124,7 +124,17 @@ var _chunk2NIALQEHcjs = require('./chunk-2NIALQEH.cjs');
124
124
 
125
125
 
126
126
 
127
- var _chunkVCXIPLEWcjs = require('./chunk-VCXIPLEW.cjs');
127
+
128
+
129
+
130
+
131
+
132
+
133
+
134
+
135
+
136
+
137
+ var _chunkQFWEF5STcjs = require('./chunk-QFWEF5ST.cjs');
128
138
 
129
139
  // src/content-hash.ts
130
140
  function canonicalJson(value, seen = /* @__PURE__ */ new Set()) {
@@ -226,6 +236,20 @@ function keyOf(entry) {
226
236
  }
227
237
  return key;
228
238
  }
239
+ function inQuizOrder(items, timeline) {
240
+ const placement = /* @__PURE__ */ new Map();
241
+ timeline.cues.forEach((cue, cueIndex) => {
242
+ cue.itemIds.forEach((itemId, position) => {
243
+ if (!placement.has(itemId)) {
244
+ placement.set(itemId, { at: cue.at, cue: cueIndex, position });
245
+ }
246
+ });
247
+ });
248
+ const unplaced = { at: Number.POSITIVE_INFINITY, cue: Number.POSITIVE_INFINITY, position: 0 };
249
+ return items.map((entry) => ({ entry, place: _nullishCoalesce(placement.get(entry.item.id), () => ( unplaced)) })).sort(
250
+ (a, b) => a.place.at - b.place.at || a.place.cue - b.place.cue || a.place.position - b.place.position || a.entry.itemIndex - b.entry.itemIndex
251
+ ).map(({ entry }) => entry);
252
+ }
229
253
  function flattenSequence(entries, options = {}) {
230
254
  const shuffleEntries = options.shuffleEntries === true;
231
255
  const needsSeed = shuffleEntries || entries.some((entry) => isItemGroup(entry) && entry.shuffle === "within-group");
@@ -249,11 +273,20 @@ function flattenSequence(entries, options = {}) {
249
273
  `flattenSequence: item group "${entry.id}" has no items. An empty group would silently remove its stimulus and its questions from the presented sequence.`
250
274
  );
251
275
  }
276
+ const timeline = entry.timeline;
277
+ if (timeline !== void 0 && entry.shuffle === "within-group") {
278
+ throw new Error(
279
+ `flattenSequence: item group "${entry.id}" has a timeline and shuffle: "within-group". An interactive video presents its questions in the order its quizzes open.`
280
+ );
281
+ }
252
282
  const items = entry.items.map((item, itemIndex) => ({ item, itemIndex }));
253
- const presented = entry.shuffle === "within-group" ? seededShuffle(items, `${seed}:group:${entry.id}`) : items;
283
+ const presented = timeline !== void 0 ? inQuizOrder(items, timeline) : entry.shuffle === "within-group" ? seededShuffle(items, `${seed}:group:${entry.id}`) : items;
254
284
  const size = presented.length;
255
285
  presented.forEach(({ item, itemIndex }, position) => {
286
+ const cue = _optionalChain([timeline, 'optionalAccess', _ => _.cues, 'access', _2 => _2.find, 'call', _3 => _3((candidate) => candidate.itemIds.includes(item.id))]);
256
287
  slots.push({
288
+ // Slot ids stay AUTHORED — the item's index or its key — whatever the
289
+ // presented order: moving a quiz must never re-map a stored answer.
257
290
  slotId: `${entryKey}.${_nullishCoalesce(keyOf(item), () => ( String(itemIndex)))}`,
258
291
  index: slots.length,
259
292
  activity: item,
@@ -262,7 +295,9 @@ function flattenSequence(entries, options = {}) {
262
295
  ...entry.title !== void 0 ? { title: entry.title } : {},
263
296
  stimulus: entry.stimulus,
264
297
  position,
265
- size
298
+ size,
299
+ ...timeline !== void 0 ? { timeline } : {},
300
+ ...cue !== void 0 ? { cue } : {}
266
301
  }
267
302
  });
268
303
  });
@@ -302,16 +337,16 @@ function stimulusMediaKey(slotId) {
302
337
  }
303
338
  function resolvePlaybackPolicy(media) {
304
339
  const p = media.playback;
305
- const budgeted = typeof _optionalChain([p, 'optionalAccess', _ => _.maxPlays]) === "number";
306
- const seek = _nullishCoalesce(_optionalChain([p, 'optionalAccess', _2 => _2.seek]), () => ( (budgeted ? "none" : "allow")));
307
- const rate = _nullishCoalesce(_optionalChain([p, 'optionalAccess', _3 => _3.rate]), () => ( "allow"));
308
- const controls = _nullishCoalesce(_optionalChain([p, 'optionalAccess', _4 => _4.controls]), () => ( (budgeted || seek === "none" || rate === "fixed" ? "minimal" : "native")));
340
+ const budgeted = typeof _optionalChain([p, 'optionalAccess', _4 => _4.maxPlays]) === "number";
341
+ const seek = _nullishCoalesce(_optionalChain([p, 'optionalAccess', _5 => _5.seek]), () => ( (budgeted ? "none" : "allow")));
342
+ const rate = _nullishCoalesce(_optionalChain([p, 'optionalAccess', _6 => _6.rate]), () => ( "allow"));
343
+ const controls = _nullishCoalesce(_optionalChain([p, 'optionalAccess', _7 => _7.controls]), () => ( (budgeted || seek === "none" || rate === "fixed" ? "minimal" : "native")));
309
344
  return {
310
345
  controls,
311
- maxPlays: budgeted ? _optionalChain([p, 'optionalAccess', _5 => _5.maxPlays]) : null,
346
+ maxPlays: budgeted ? _optionalChain([p, 'optionalAccess', _8 => _8.maxPlays]) : null,
312
347
  seek,
313
348
  rate,
314
- nativeControlHints: _nullishCoalesce(_optionalChain([p, 'optionalAccess', _6 => _6.nativeControlHints]), () => ( []))
349
+ nativeControlHints: _nullishCoalesce(_optionalChain([p, 'optionalAccess', _9 => _9.nativeControlHints]), () => ( []))
315
350
  };
316
351
  }
317
352
  function planMediaBudgets(plan) {
@@ -326,7 +361,7 @@ function planMediaBudgets(plan) {
326
361
  function assertEntry(key, entry) {
327
362
  if (entry === null || typeof entry !== "object" || !Number.isInteger(entry.plays) || entry.plays < 0) {
328
363
  throw new Error(
329
- `serializeMediaPlayLedger: play count for ${JSON.stringify(key)} is ${JSON.stringify(_optionalChain([entry, 'optionalAccess', _7 => _7.plays]))}. A count must be a non-negative integer; Number(a NULL column) is the usual cause.`
364
+ `serializeMediaPlayLedger: play count for ${JSON.stringify(key)} is ${JSON.stringify(_optionalChain([entry, 'optionalAccess', _10 => _10.plays]))}. A count must be a non-negative integer; Number(a NULL column) is the usual cause.`
330
365
  );
331
366
  }
332
367
  if (entry.at !== void 0 && (!Number.isFinite(entry.at) || entry.at < 0)) {
@@ -399,7 +434,7 @@ function mediaBudgetsOf(slot) {
399
434
  budgets.push({ key: slotMediaKey(slot.slotId), maxPlays });
400
435
  }
401
436
  }
402
- const stimulusMedia = _optionalChain([slot, 'access', _8 => _8.group, 'optionalAccess', _9 => _9.stimulus, 'access', _10 => _10.media]);
437
+ const stimulusMedia = _optionalChain([slot, 'access', _11 => _11.group, 'optionalAccess', _12 => _12.stimulus, 'access', _13 => _13.media]);
403
438
  if (stimulusMedia !== void 0) {
404
439
  const maxPlays = resolvePlaybackPolicy(stimulusMedia).maxPlays;
405
440
  if (maxPlays !== null) {
@@ -445,7 +480,14 @@ function planSlot(slot, points) {
445
480
  group: {
446
481
  id: slot.group.id,
447
482
  ...slot.group.title !== void 0 ? { title: slot.group.title } : {},
448
- stimulusHash: contentHash(slot.group.stimulus)
483
+ stimulusHash: contentHash(slot.group.stimulus),
484
+ ...slot.group.cue !== void 0 ? {
485
+ cue: {
486
+ id: slot.group.cue.id,
487
+ at: slot.group.cue.at,
488
+ ...slot.group.cue.required !== void 0 ? { required: slot.group.cue.required } : {}
489
+ }
490
+ } : {}
449
491
  }
450
492
  } : {},
451
493
  ...mediaBudgets !== void 0 ? { mediaBudgets } : {}
@@ -458,7 +500,7 @@ function planAttempt(entries, options = {}) {
458
500
  ...seed !== void 0 ? { seed } : {}
459
501
  });
460
502
  assertNoSplitBudgets(slots);
461
- const planned = slots.map((slot) => planSlot(slot, _nullishCoalesce(_optionalChain([points, 'optionalCall', _11 => _11(slot)]), () => ( 1))));
503
+ const planned = slots.map((slot) => planSlot(slot, _nullishCoalesce(_optionalChain([points, 'optionalCall', _14 => _14(slot)]), () => ( 1))));
462
504
  const totalPoints = planned.reduce((sum, slot) => sum + slot.points, 0);
463
505
  return {
464
506
  planVersion: "1.0",
@@ -479,6 +521,7 @@ function verifyAttemptPlan(plan, current) {
479
521
  const addedSlotIds = current.slots.filter((s) => !before.has(s.slotId)).map((s) => s.slotId);
480
522
  const changedSlotIds = [];
481
523
  const changedStimulusSlotIds = [];
524
+ const changedCueSlotIds = [];
482
525
  const changedPointsSlotIds = [];
483
526
  const reorderedSlotIds = [];
484
527
  for (const slot of plan.slots) {
@@ -489,9 +532,12 @@ function verifyAttemptPlan(plan, current) {
489
532
  if (now.contentHash !== slot.contentHash) {
490
533
  changedSlotIds.push(slot.slotId);
491
534
  }
492
- if (_optionalChain([now, 'access', _12 => _12.group, 'optionalAccess', _13 => _13.stimulusHash]) !== _optionalChain([slot, 'access', _14 => _14.group, 'optionalAccess', _15 => _15.stimulusHash])) {
535
+ if (_optionalChain([now, 'access', _15 => _15.group, 'optionalAccess', _16 => _16.stimulusHash]) !== _optionalChain([slot, 'access', _17 => _17.group, 'optionalAccess', _18 => _18.stimulusHash])) {
493
536
  changedStimulusSlotIds.push(slot.slotId);
494
537
  }
538
+ if (contentHash(_nullishCoalesce(_optionalChain([now, 'access', _19 => _19.group, 'optionalAccess', _20 => _20.cue]), () => ( null))) !== contentHash(_nullishCoalesce(_optionalChain([slot, 'access', _21 => _21.group, 'optionalAccess', _22 => _22.cue]), () => ( null)))) {
539
+ changedCueSlotIds.push(slot.slotId);
540
+ }
495
541
  if (now.points !== slot.points) {
496
542
  changedPointsSlotIds.push(slot.slotId);
497
543
  }
@@ -500,11 +546,12 @@ function verifyAttemptPlan(plan, current) {
500
546
  }
501
547
  }
502
548
  return {
503
- matches: missingSlotIds.length === 0 && addedSlotIds.length === 0 && changedSlotIds.length === 0 && changedStimulusSlotIds.length === 0 && changedPointsSlotIds.length === 0 && reorderedSlotIds.length === 0,
549
+ matches: missingSlotIds.length === 0 && addedSlotIds.length === 0 && changedSlotIds.length === 0 && changedStimulusSlotIds.length === 0 && changedCueSlotIds.length === 0 && changedPointsSlotIds.length === 0 && reorderedSlotIds.length === 0,
504
550
  missingSlotIds,
505
551
  addedSlotIds,
506
552
  changedSlotIds,
507
553
  changedStimulusSlotIds,
554
+ changedCueSlotIds,
508
555
  changedPointsSlotIds,
509
556
  reorderedSlotIds
510
557
  };
@@ -652,23 +699,31 @@ function createItemGroupDraft(context) {
652
699
  items: []
653
700
  };
654
701
  }
702
+ function createInteractiveVideoDraft(context) {
703
+ const draft = createItemGroupDraft(context);
704
+ return {
705
+ ...draft,
706
+ stimulus: { id: draft.stimulus.id, kind: "video", media: { type: "video", url: "" } },
707
+ timeline: { cues: [] }
708
+ };
709
+ }
655
710
  function validateItemGroupDraft(draft) {
656
- return _chunkVCXIPLEWcjs.withValidationScope.call(void 0, () => validateItemGroupDraftInScope(draft));
711
+ return _chunkQFWEF5STcjs.withValidationScope.call(void 0, () => validateItemGroupDraftInScope(draft));
657
712
  }
658
713
  function validateItemGroupDraftInScope(draft) {
659
714
  const issues = [];
660
- if (!_chunkVCXIPLEWcjs.isRecord.call(void 0, draft)) {
715
+ if (!_chunkQFWEF5STcjs.isRecord.call(void 0, draft)) {
661
716
  issues.push(
662
- _chunkVCXIPLEWcjs.issue.call(void 0, "ig_not_an_object", [], "A group must be an object with a stimulus and its items.")
717
+ _chunkQFWEF5STcjs.issue.call(void 0, "ig_not_an_object", [], "A group must be an object with a stimulus and its items.")
663
718
  );
664
719
  return { status: "invalid", issues };
665
720
  }
666
721
  issues.push(...checkGroupIdentity(draft));
667
- if (_chunkVCXIPLEWcjs.isRecord.call(void 0, draft.stimulus)) {
722
+ if (_chunkQFWEF5STcjs.isRecord.call(void 0, draft.stimulus)) {
668
723
  issues.push(...checkStimulus(draft.stimulus));
669
- } else if (_chunkVCXIPLEWcjs.isUnset.call(void 0, draft.stimulus)) {
724
+ } else if (_chunkQFWEF5STcjs.isUnset.call(void 0, draft.stimulus)) {
670
725
  issues.push(
671
- _chunkVCXIPLEWcjs.issue.call(void 0,
726
+ _chunkQFWEF5STcjs.issue.call(void 0,
672
727
  "ig_stimulus_required",
673
728
  ["stimulus"],
674
729
  "Add the passage, recording or image the questions are about."
@@ -676,25 +731,28 @@ function validateItemGroupDraftInScope(draft) {
676
731
  );
677
732
  }
678
733
  issues.push(...checkItems(draft));
679
- if (_chunkVCXIPLEWcjs.groupCaptionsRevealDictation.call(void 0, draft, (captionsUrl) => !_chunkVCXIPLEWcjs.isUnwritten.call(void 0, captionsUrl))) {
734
+ if (draft.timeline !== void 0 && draft.timeline !== null) {
735
+ issues.push(...checkTimeline(draft));
736
+ }
737
+ if (_chunkQFWEF5STcjs.groupCaptionsRevealDictation.call(void 0, draft, (captionsUrl) => !_chunkQFWEF5STcjs.isUnwritten.call(void 0, captionsUrl))) {
680
738
  issues.push(
681
- _chunkVCXIPLEWcjs.issue.call(void 0,
739
+ _chunkQFWEF5STcjs.issue.call(void 0,
682
740
  "dc_captions_not_allowed",
683
741
  ["stimulus", "media", "captionsUrl"],
684
- _chunkVCXIPLEWcjs.GROUP_CAPTIONS_REVEAL_DICTATION
742
+ _chunkQFWEF5STcjs.GROUP_CAPTIONS_REVEAL_DICTATION
685
743
  )
686
744
  );
687
745
  }
688
- const parsed = _chunk2NIALQEHcjs.ItemGroupSchema.safeParse(draft, { reportInput: true });
746
+ const parsed = _chunkW7AQP6AVcjs.ItemGroupSchema.safeParse(draft, { reportInput: true });
689
747
  if (!parsed.success) {
690
748
  for (const schemaIssue of parsed.error.issues) {
691
749
  const path = schemaIssue.path.map(String);
692
- if (issues.some((known) => _chunkVCXIPLEWcjs.covers.call(void 0, known.path, path))) {
750
+ if (issues.some((known) => _chunkQFWEF5STcjs.covers.call(void 0, known.path, path))) {
693
751
  continue;
694
752
  }
695
- if (path.length > 0 && _chunkVCXIPLEWcjs.refusesEmpty.call(void 0, draft, schemaIssue)) {
753
+ if (path.length > 0 && _chunkQFWEF5STcjs.refusesEmpty.call(void 0, draft, schemaIssue)) {
696
754
  issues.push(
697
- _chunkVCXIPLEWcjs.issue.call(void 0,
755
+ _chunkQFWEF5STcjs.issue.call(void 0,
698
756
  "null_not_allowed",
699
757
  path,
700
758
  "This field cannot be null. Leave it out if it is optional, or give it a value."
@@ -710,7 +768,7 @@ function validateItemGroupDraftInScope(draft) {
710
768
  });
711
769
  }
712
770
  }
713
- const stored = _chunk2NIALQEHcjs.validateItemGroup.call(void 0, draft);
771
+ const stored = _chunkW7AQP6AVcjs.validateItemGroup.call(void 0, draft);
714
772
  if (issues.length === 0 && stored.success) {
715
773
  return { status: "complete", data: stored.data, issues };
716
774
  }
@@ -722,11 +780,188 @@ function validateItemGroupDraftInScope(draft) {
722
780
  const invalid = issues.some((found) => found.severity !== "incomplete");
723
781
  return { status: invalid ? "invalid" : "incomplete", issues };
724
782
  }
783
+ function checkTimeline(draft) {
784
+ const issues = [];
785
+ const timeline = draft.timeline;
786
+ if (!_chunkQFWEF5STcjs.isRecord.call(void 0, timeline)) {
787
+ return issues;
788
+ }
789
+ const stimulus = _chunkQFWEF5STcjs.isRecord.call(void 0, draft.stimulus) ? draft.stimulus : void 0;
790
+ if (stimulus !== void 0 && !_chunkQFWEF5STcjs.isUnwritten.call(void 0, stimulus.kind) && stimulus.kind !== "video") {
791
+ issues.push(
792
+ _chunkQFWEF5STcjs.issue.call(void 0,
793
+ "ig_timeline_stimulus_kind",
794
+ ["stimulus", "kind"],
795
+ "An interactive video needs a video: quizzes open at moments of it."
796
+ )
797
+ );
798
+ } else if (stimulus !== void 0 && _chunkQFWEF5STcjs.isRecord.call(void 0, stimulus.media) && !_chunkQFWEF5STcjs.isUnwritten.call(void 0, stimulus.media.type) && stimulus.media.type !== "video") {
799
+ issues.push(
800
+ _chunkQFWEF5STcjs.issue.call(void 0,
801
+ "ig_timeline_stimulus_kind",
802
+ ["stimulus", "media", "type"],
803
+ "Upload a video file. An embedded player from another site cannot be paused when a quiz opens."
804
+ )
805
+ );
806
+ }
807
+ if (draft.shuffle === "within-group") {
808
+ issues.push(
809
+ _chunkQFWEF5STcjs.issue.call(void 0,
810
+ "ig_timeline_shuffle",
811
+ ["shuffle"],
812
+ "The questions of an interactive video appear in the order their quizzes open, so they cannot be shuffled."
813
+ )
814
+ );
815
+ }
816
+ const items = Array.isArray(draft.items) ? draft.items : [];
817
+ const itemIndexById = /* @__PURE__ */ new Map();
818
+ items.forEach((item, index) => {
819
+ if (!_chunkQFWEF5STcjs.isRecord.call(void 0, item)) {
820
+ return;
821
+ }
822
+ if (typeof item.id === "string" && item.id !== "") {
823
+ itemIndexById.set(item.id, index);
824
+ }
825
+ const type = item.type;
826
+ if (typeof type === "string" && type !== "" && type !== "item-group" && !_chunkW7AQP6AVcjs.isInteractiveVideoItemType.call(void 0, type) && _chunkQFWEF5STcjs.getActivityTypeDescriptor.call(void 0, type) !== void 0) {
827
+ issues.push(
828
+ _chunkQFWEF5STcjs.issue.call(void 0,
829
+ "ig_timeline_item_type",
830
+ ["items", index, "type"],
831
+ `An interactive video can hold ${_chunkW7AQP6AVcjs.INTERACTIVE_VIDEO_ITEM_TYPES.join(", ")} questions only.`
832
+ )
833
+ );
834
+ }
835
+ if (type === "dictation" && _chunkQFWEF5STcjs.isUnset.call(void 0, item.media)) {
836
+ issues.push(
837
+ _chunkQFWEF5STcjs.issue.call(void 0,
838
+ "ig_timeline_dictation_media",
839
+ ["items", index, "media"],
840
+ "Add the recording this dictation plays: inside a video it cannot play the video."
841
+ )
842
+ );
843
+ }
844
+ });
845
+ const cues = Array.isArray(timeline.cues) ? timeline.cues : [];
846
+ const quizIds = /* @__PURE__ */ new Set();
847
+ const placed = /* @__PURE__ */ new Set();
848
+ cues.forEach((cue, cueIndex) => {
849
+ if (!_chunkQFWEF5STcjs.isRecord.call(void 0, cue)) {
850
+ return;
851
+ }
852
+ const at = (field, ...rest) => [
853
+ "timeline",
854
+ "cues",
855
+ cueIndex,
856
+ field,
857
+ ...rest
858
+ ];
859
+ if (_chunkQFWEF5STcjs.isMissingId.call(void 0, cue.id)) {
860
+ issues.push(_chunkQFWEF5STcjs.issue.call(void 0, "ig_timeline_quiz_id_required", at("id"), "This quiz has no id."));
861
+ } else if (typeof cue.id === "string") {
862
+ if (quizIds.has(cue.id)) {
863
+ issues.push(
864
+ _chunkQFWEF5STcjs.issue.call(void 0, "ig_timeline_quiz_id_duplicate", at("id"), `Two quizzes share the id "${cue.id}".`)
865
+ );
866
+ }
867
+ quizIds.add(cue.id);
868
+ }
869
+ if (_chunkQFWEF5STcjs.isUnset.call(void 0, cue.at)) {
870
+ issues.push(
871
+ _chunkQFWEF5STcjs.issue.call(void 0,
872
+ "ig_timeline_quiz_time_required",
873
+ at("at"),
874
+ "Choose when in the video this quiz opens."
875
+ )
876
+ );
877
+ } else if (typeof cue.at !== "number" || !Number.isFinite(cue.at) || cue.at < 0) {
878
+ issues.push(
879
+ _chunkQFWEF5STcjs.issue.call(void 0,
880
+ "ig_timeline_quiz_time_invalid",
881
+ at("at"),
882
+ "A quiz opens at a number of seconds, 0 or more."
883
+ )
884
+ );
885
+ }
886
+ if (_chunkQFWEF5STcjs.isUnset.call(void 0, cue.itemIds) || Array.isArray(cue.itemIds) && cue.itemIds.length === 0) {
887
+ issues.push(
888
+ _chunkQFWEF5STcjs.issue.call(void 0, "ig_timeline_quiz_empty", at("itemIds"), "Add at least one question to this quiz.")
889
+ );
890
+ return;
891
+ }
892
+ if (!Array.isArray(cue.itemIds)) {
893
+ return;
894
+ }
895
+ cue.itemIds.forEach((itemId, position) => {
896
+ if (typeof itemId !== "string") {
897
+ return;
898
+ }
899
+ if (!itemIndexById.has(itemId)) {
900
+ issues.push(
901
+ _chunkQFWEF5STcjs.issue.call(void 0,
902
+ "ig_timeline_quiz_unknown_item",
903
+ at("itemIds", position),
904
+ `This quiz names a question that is not in the video ("${itemId}").`
905
+ )
906
+ );
907
+ } else if (placed.has(itemId)) {
908
+ issues.push(
909
+ _chunkQFWEF5STcjs.issue.call(void 0,
910
+ "ig_timeline_item_duplicate",
911
+ at("itemIds", position),
912
+ "This question is already in a quiz: each question belongs to one quiz."
913
+ )
914
+ );
915
+ }
916
+ placed.add(itemId);
917
+ });
918
+ });
919
+ for (const [itemId, index] of itemIndexById) {
920
+ if (!placed.has(itemId)) {
921
+ issues.push(
922
+ _chunkQFWEF5STcjs.issue.call(void 0,
923
+ "ig_timeline_item_unplaced",
924
+ ["items", index],
925
+ "Add this question to a quiz, or the video never shows it."
926
+ )
927
+ );
928
+ }
929
+ }
930
+ const chapters = Array.isArray(timeline.chapters) ? timeline.chapters : [];
931
+ let previousAt;
932
+ chapters.forEach((chapter, index) => {
933
+ if (!_chunkQFWEF5STcjs.isRecord.call(void 0, chapter)) {
934
+ return;
935
+ }
936
+ if (_chunkQFWEF5STcjs.isUnwritten.call(void 0, chapter.title)) {
937
+ issues.push(
938
+ _chunkQFWEF5STcjs.issue.call(void 0,
939
+ "ig_timeline_chapter_title",
940
+ ["timeline", "chapters", index, "title"],
941
+ "Give this chapter a title."
942
+ )
943
+ );
944
+ }
945
+ if (typeof chapter.at === "number" && Number.isFinite(chapter.at)) {
946
+ if (previousAt !== void 0 && chapter.at <= previousAt) {
947
+ issues.push(
948
+ _chunkQFWEF5STcjs.issue.call(void 0,
949
+ "ig_timeline_chapter_order",
950
+ ["timeline", "chapters", index, "at"],
951
+ "Chapters must start in order, each after the one before it."
952
+ )
953
+ );
954
+ }
955
+ previousAt = chapter.at;
956
+ }
957
+ });
958
+ return issues;
959
+ }
725
960
  function checkGroupIdentity(draft) {
726
961
  const issues = [];
727
962
  if (draft.schemaVersion !== "1.0") {
728
963
  issues.push(
729
- _chunkVCXIPLEWcjs.issue.call(void 0,
964
+ _chunkQFWEF5STcjs.issue.call(void 0,
730
965
  "schema_version_invalid",
731
966
  ["schemaVersion"],
732
967
  'The draft must have schemaVersion "1.0". A draft from createItemGroupDraft has it.'
@@ -734,14 +969,14 @@ function checkGroupIdentity(draft) {
734
969
  );
735
970
  }
736
971
  if (draft.type !== "item-group") {
737
- issues.push(_chunkVCXIPLEWcjs.issue.call(void 0, "type_mismatch", ["type"], `The draft's type must be "item-group".`));
972
+ issues.push(_chunkQFWEF5STcjs.issue.call(void 0, "type_mismatch", ["type"], `The draft's type must be "item-group".`));
738
973
  }
739
- if (_chunkVCXIPLEWcjs.isMissingId.call(void 0, draft.id)) {
740
- issues.push(_chunkVCXIPLEWcjs.issue.call(void 0, "id_required", ["id"], "The group has no id."));
974
+ if (_chunkQFWEF5STcjs.isMissingId.call(void 0, draft.id)) {
975
+ issues.push(_chunkQFWEF5STcjs.issue.call(void 0, "id_required", ["id"], "The group has no id."));
741
976
  }
742
- if (!_chunkVCXIPLEWcjs.isUnset.call(void 0, draft.shuffle) && draft.shuffle !== "none" && draft.shuffle !== "within-group") {
977
+ if (!_chunkQFWEF5STcjs.isUnset.call(void 0, draft.shuffle) && draft.shuffle !== "none" && draft.shuffle !== "within-group") {
743
978
  issues.push(
744
- _chunkVCXIPLEWcjs.issue.call(void 0,
979
+ _chunkQFWEF5STcjs.issue.call(void 0,
745
980
  "ig_shuffle_invalid",
746
981
  ["shuffle"],
747
982
  'Shuffling is either "none" or "within-group". Leave it out to keep the authored order.'
@@ -760,13 +995,13 @@ var MEDIA_FOR_KIND = {
760
995
  function checkStimulus(stimulus) {
761
996
  const issues = [];
762
997
  const at = (...rest) => ["stimulus", ...rest];
763
- if (_chunkVCXIPLEWcjs.isMissingId.call(void 0, stimulus.id)) {
764
- issues.push(_chunkVCXIPLEWcjs.issue.call(void 0, "ig_stimulus_id_required", at("id"), "The stimulus has no id."));
998
+ if (_chunkQFWEF5STcjs.isMissingId.call(void 0, stimulus.id)) {
999
+ issues.push(_chunkQFWEF5STcjs.issue.call(void 0, "ig_stimulus_id_required", at("id"), "The stimulus has no id."));
765
1000
  }
766
1001
  const kind = stimulus.kind;
767
- if (_chunkVCXIPLEWcjs.isUnwritten.call(void 0, kind)) {
1002
+ if (_chunkQFWEF5STcjs.isUnwritten.call(void 0, kind)) {
768
1003
  issues.push(
769
- _chunkVCXIPLEWcjs.issue.call(void 0,
1004
+ _chunkQFWEF5STcjs.issue.call(void 0,
770
1005
  "ig_stimulus_kind_required",
771
1006
  at("kind"),
772
1007
  "Choose what the questions are about: a text, a recording, a video, an image, or a mix."
@@ -775,71 +1010,71 @@ function checkStimulus(stimulus) {
775
1010
  } else if (typeof kind !== "string" || !KINDS.has(kind)) {
776
1011
  if (typeof kind === "string") {
777
1012
  issues.push(
778
- _chunkVCXIPLEWcjs.issue.call(void 0,
1013
+ _chunkQFWEF5STcjs.issue.call(void 0,
779
1014
  "ig_stimulus_kind_invalid",
780
1015
  at("kind"),
781
1016
  `"${kind}" is not a stimulus kind. Use text, audio, video, image or mixed.`
782
1017
  )
783
1018
  );
784
1019
  }
785
- if (_chunkVCXIPLEWcjs.isRecord.call(void 0, stimulus.media)) {
786
- issues.push(..._chunkVCXIPLEWcjs.checkMedia.call(void 0, stimulus.media, at("media")));
1020
+ if (_chunkQFWEF5STcjs.isRecord.call(void 0, stimulus.media)) {
1021
+ issues.push(..._chunkQFWEF5STcjs.checkMedia.call(void 0, stimulus.media, at("media")));
787
1022
  }
788
1023
  return issues;
789
1024
  }
790
1025
  const hasBody = typeof stimulus.body === "string" && stimulus.body.trim() !== "";
791
- const htmlPresent = !_chunkVCXIPLEWcjs.isUnset.call(void 0, stimulus.bodyHtml);
1026
+ const htmlPresent = !_chunkQFWEF5STcjs.isUnset.call(void 0, stimulus.bodyHtml);
792
1027
  if (!hasBody && (kind === "text" || kind === "mixed" || htmlPresent)) {
793
1028
  issues.push(
794
- _chunkVCXIPLEWcjs.issue.call(void 0,
1029
+ _chunkQFWEF5STcjs.issue.call(void 0,
795
1030
  "ig_stimulus_body_required",
796
1031
  at("body"),
797
- _chunkVCXIPLEWcjs.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."
1032
+ _chunkQFWEF5STcjs.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."
798
1033
  )
799
1034
  );
800
1035
  }
801
- if (kind !== "text" && _chunkVCXIPLEWcjs.isUnset.call(void 0, stimulus.media)) {
1036
+ if (kind !== "text" && _chunkQFWEF5STcjs.isUnset.call(void 0, stimulus.media)) {
802
1037
  issues.push(
803
- _chunkVCXIPLEWcjs.issue.call(void 0, "ig_stimulus_media_required", at("media"), "Add the recording, video or image.")
1038
+ _chunkQFWEF5STcjs.issue.call(void 0, "ig_stimulus_media_required", at("media"), "Add the recording, video or image.")
804
1039
  );
805
- } else if (_chunkVCXIPLEWcjs.isRecord.call(void 0, stimulus.media)) {
1040
+ } else if (_chunkQFWEF5STcjs.isRecord.call(void 0, stimulus.media)) {
806
1041
  const allowed = MEDIA_FOR_KIND[kind];
807
1042
  const mediaType = stimulus.media.type;
808
1043
  if (allowed !== void 0 && typeof mediaType === "string" && !allowed.includes(mediaType)) {
809
1044
  issues.push(
810
- _chunkVCXIPLEWcjs.issue.call(void 0,
1045
+ _chunkQFWEF5STcjs.issue.call(void 0,
811
1046
  "ig_stimulus_media_kind",
812
1047
  at("media", "type"),
813
1048
  `A "${kind}" stimulus cannot carry ${mediaType} media. Use ${allowed.join(" or ")}.`
814
1049
  )
815
1050
  );
816
1051
  }
817
- issues.push(..._chunkVCXIPLEWcjs.checkMedia.call(void 0, stimulus.media, at("media")));
1052
+ issues.push(..._chunkQFWEF5STcjs.checkMedia.call(void 0, stimulus.media, at("media")));
818
1053
  }
819
1054
  return issues;
820
1055
  }
821
1056
  function checkItems(draft) {
822
1057
  const issues = [];
823
- const items = _chunkVCXIPLEWcjs.isUnset.call(void 0, draft.items) ? [] : draft.items;
1058
+ const items = _chunkQFWEF5STcjs.isUnset.call(void 0, draft.items) ? [] : draft.items;
824
1059
  if (!Array.isArray(items)) {
825
1060
  return issues;
826
1061
  }
827
1062
  if (items.length === 0) {
828
1063
  issues.push(
829
- _chunkVCXIPLEWcjs.issue.call(void 0, "ig_items_required", ["items"], "Add at least one question about this material.")
1064
+ _chunkQFWEF5STcjs.issue.call(void 0, "ig_items_required", ["items"], "Add at least one question about this material.")
830
1065
  );
831
1066
  return issues;
832
1067
  }
833
1068
  const seen = /* @__PURE__ */ new Set();
834
1069
  const repeated = /* @__PURE__ */ new Set();
835
1070
  for (const [index, item] of items.entries()) {
836
- if (!_chunkVCXIPLEWcjs.isRecord.call(void 0, item)) {
1071
+ if (!_chunkQFWEF5STcjs.isRecord.call(void 0, item)) {
837
1072
  continue;
838
1073
  }
839
1074
  const ordinal = index + 1;
840
- if (_chunkVCXIPLEWcjs.isMissingId.call(void 0, item.id)) {
1075
+ if (_chunkQFWEF5STcjs.isMissingId.call(void 0, item.id)) {
841
1076
  issues.push(
842
- _chunkVCXIPLEWcjs.issue.call(void 0, "ig_item_id_required", ["items", index, "id"], `Question ${ordinal} has no id.`)
1077
+ _chunkQFWEF5STcjs.issue.call(void 0, "ig_item_id_required", ["items", index, "id"], `Question ${ordinal} has no id.`)
843
1078
  );
844
1079
  } else if (typeof item.id === "string") {
845
1080
  if (seen.has(item.id)) {
@@ -849,7 +1084,7 @@ function checkItems(draft) {
849
1084
  }
850
1085
  if (item.type === "item-group") {
851
1086
  issues.push(
852
- _chunkVCXIPLEWcjs.issue.call(void 0,
1087
+ _chunkQFWEF5STcjs.issue.call(void 0,
853
1088
  "ig_item_nested_group",
854
1089
  ["items", index, "type"],
855
1090
  "Groups do not nest: every item must be an activity."
@@ -857,9 +1092,9 @@ function checkItems(draft) {
857
1092
  );
858
1093
  continue;
859
1094
  }
860
- if (_chunkVCXIPLEWcjs.isUnwritten.call(void 0, item.type)) {
1095
+ if (_chunkQFWEF5STcjs.isUnwritten.call(void 0, item.type)) {
861
1096
  issues.push(
862
- _chunkVCXIPLEWcjs.issue.call(void 0,
1097
+ _chunkQFWEF5STcjs.issue.call(void 0,
863
1098
  "ig_item_type_required",
864
1099
  ["items", index, "type"],
865
1100
  `Choose what kind of question ${ordinal} is.`
@@ -874,11 +1109,11 @@ function checkItems(draft) {
874
1109
  try {
875
1110
  result = validateDraft(item.type, item);
876
1111
  } catch (error) {
877
- if (!(error instanceof _chunkVCXIPLEWcjs.UnknownActivityTypeError) || error.activityType !== item.type) {
1112
+ if (!(error instanceof _chunkQFWEF5STcjs.UnknownActivityTypeError) || error.activityType !== item.type) {
878
1113
  throw error;
879
1114
  }
880
1115
  issues.push(
881
- _chunkVCXIPLEWcjs.issue.call(void 0,
1116
+ _chunkQFWEF5STcjs.issue.call(void 0,
882
1117
  "ig_item_type_unknown",
883
1118
  ["items", index, "type"],
884
1119
  `"${item.type}" is not a registered activity type.`
@@ -892,7 +1127,7 @@ function checkItems(draft) {
892
1127
  }
893
1128
  for (const id of repeated) {
894
1129
  issues.push(
895
- _chunkVCXIPLEWcjs.issue.call(void 0, "ig_item_id_duplicate", ["items"], `More than one question has the id "${id}".`)
1130
+ _chunkQFWEF5STcjs.issue.call(void 0, "ig_item_id_duplicate", ["items"], `More than one question has the id "${id}".`)
896
1131
  );
897
1132
  }
898
1133
  return issues;
@@ -900,30 +1135,30 @@ function checkItems(draft) {
900
1135
 
901
1136
  // src/authoring/index.ts
902
1137
  function validateDraft(type, draft) {
903
- return _chunkVCXIPLEWcjs.withValidationScope.call(void 0, () => validateDraftInScope(type, draft));
1138
+ return _chunkQFWEF5STcjs.withValidationScope.call(void 0, () => validateDraftInScope(type, draft));
904
1139
  }
905
1140
  function validateDraftInScope(type, draft) {
906
- const descriptor = _chunkVCXIPLEWcjs.getActivityTypeDescriptor.call(void 0, type);
1141
+ const descriptor = _chunkQFWEF5STcjs.getActivityTypeDescriptor.call(void 0, type);
907
1142
  if (descriptor === void 0) {
908
- throw new (0, _chunkVCXIPLEWcjs.UnknownActivityTypeError)(String(type));
1143
+ throw new (0, _chunkQFWEF5STcjs.UnknownActivityTypeError)(String(type));
909
1144
  }
910
- const reported = _chunkVCXIPLEWcjs.isRecord.call(void 0, draft) && _optionalChain([descriptor, 'access', _16 => _16.authoring, 'optionalAccess', _17 => _17.checkDraft]) !== void 0 ? descriptor.authoring.checkDraft(draft).map(normalise) : [];
1145
+ const reported = _chunkQFWEF5STcjs.isRecord.call(void 0, draft) && _optionalChain([descriptor, 'access', _23 => _23.authoring, 'optionalAccess', _24 => _24.checkDraft]) !== void 0 ? descriptor.authoring.checkDraft(draft).map(normalise) : [];
911
1146
  const issues = [...reported];
912
1147
  const parsed = descriptor.schema.safeParse(draft, { reportInput: true });
913
1148
  if (!parsed.success) {
914
- const covered = _chunkVCXIPLEWcjs.coveredPathsOf.call(void 0, reported);
1149
+ const covered = _chunkQFWEF5STcjs.coveredPathsOf.call(void 0, reported);
915
1150
  const reportedEmpty = /* @__PURE__ */ new Set();
916
1151
  for (const schemaIssue of parsed.error.issues) {
917
1152
  const path = schemaIssue.path.map(String);
918
- if (covered.has(_chunkVCXIPLEWcjs.pathKey.call(void 0, path))) {
1153
+ if (covered.has(_chunkQFWEF5STcjs.pathKey.call(void 0, path))) {
919
1154
  continue;
920
1155
  }
921
- if (path.length > 0 && _chunkVCXIPLEWcjs.refusesEmpty.call(void 0, draft, schemaIssue)) {
1156
+ if (path.length > 0 && _chunkQFWEF5STcjs.refusesEmpty.call(void 0, draft, schemaIssue)) {
922
1157
  const key = JSON.stringify(path);
923
1158
  if (!reportedEmpty.has(key)) {
924
1159
  reportedEmpty.add(key);
925
1160
  issues.push(
926
- _chunkVCXIPLEWcjs.issue.call(void 0,
1161
+ _chunkQFWEF5STcjs.issue.call(void 0,
927
1162
  "null_not_allowed",
928
1163
  path,
929
1164
  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."
@@ -947,11 +1182,11 @@ function validateDraftInScope(type, draft) {
947
1182
  return { status: invalid ? "invalid" : "incomplete", issues };
948
1183
  }
949
1184
  function createDraft(type, context) {
950
- const descriptor = _chunkVCXIPLEWcjs.getActivityTypeDescriptor.call(void 0, type);
1185
+ const descriptor = _chunkQFWEF5STcjs.getActivityTypeDescriptor.call(void 0, type);
951
1186
  if (descriptor === void 0) {
952
- throw new (0, _chunkVCXIPLEWcjs.UnknownActivityTypeError)(String(type));
1187
+ throw new (0, _chunkQFWEF5STcjs.UnknownActivityTypeError)(String(type));
953
1188
  }
954
- const create = _optionalChain([descriptor, 'access', _18 => _18.authoring, 'optionalAccess', _19 => _19.createDraft]);
1189
+ const create = _optionalChain([descriptor, 'access', _25 => _25.authoring, 'optionalAccess', _26 => _26.createDraft]);
955
1190
  if (create === void 0) {
956
1191
  throw new Error(
957
1192
  `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.`
@@ -974,7 +1209,7 @@ function createDraft(type, context) {
974
1209
  return create({ newId });
975
1210
  }
976
1211
  function normalise(found) {
977
- const documented = Object.hasOwn(_chunkVCXIPLEWcjs.DRAFT_ISSUE_SEVERITY, found.code) ? _chunkVCXIPLEWcjs.DRAFT_ISSUE_SEVERITY[found.code] : void 0;
1212
+ const documented = Object.hasOwn(_chunkQFWEF5STcjs.DRAFT_ISSUE_SEVERITY, found.code) ? _chunkQFWEF5STcjs.DRAFT_ISSUE_SEVERITY[found.code] : void 0;
978
1213
  return {
979
1214
  ...found,
980
1215
  path: found.path.map(String),
@@ -1038,9 +1273,9 @@ function redactValue(value, policy, reveal) {
1038
1273
  }
1039
1274
  function redact(data, options = {}) {
1040
1275
  const reveal = _nullishCoalesce(options.reveal, () => ( "none"));
1041
- const descriptor = _chunkVCXIPLEWcjs.getActivityTypeDescriptor.call(void 0, data.type);
1276
+ const descriptor = _chunkQFWEF5STcjs.getActivityTypeDescriptor.call(void 0, data.type);
1042
1277
  if (descriptor === void 0) {
1043
- throw new (0, _chunkVCXIPLEWcjs.UnknownActivityTypeError)(String(data.type));
1278
+ throw new (0, _chunkQFWEF5STcjs.UnknownActivityTypeError)(String(data.type));
1044
1279
  }
1045
1280
  if (descriptor.fieldPolicy === void 0) {
1046
1281
  throw new Error(
@@ -1053,7 +1288,7 @@ function redact(data, options = {}) {
1053
1288
  if (reveal === "none" && descriptor.redactedSchema !== void 0) {
1054
1289
  const parsed = descriptor.redactedSchema.safeParse(result);
1055
1290
  if (!parsed.success) {
1056
- throw new (0, _chunkVCXIPLEWcjs.ActivitySchemaError)(
1291
+ throw new (0, _chunkQFWEF5STcjs.ActivitySchemaError)(
1057
1292
  descriptor.type,
1058
1293
  parsed.error.issues.map((issue2) => ({
1059
1294
  path: issue2.path.map(String),
@@ -1067,13 +1302,13 @@ function redact(data, options = {}) {
1067
1302
  }
1068
1303
  function assertRedacted(data) {
1069
1304
  if (typeof data !== "object" || data === null) {
1070
- throw new (0, _chunkVCXIPLEWcjs.ActivitySchemaError)("unknown", [
1305
+ throw new (0, _chunkQFWEF5STcjs.ActivitySchemaError)("unknown", [
1071
1306
  { path: [], message: "Redacted activity data must be an object.", code: "invalid_type" }
1072
1307
  ]);
1073
1308
  }
1074
1309
  const candidate = data;
1075
1310
  if (candidate.redacted !== true) {
1076
- throw new (0, _chunkVCXIPLEWcjs.ActivitySchemaError)(String(_nullishCoalesce(candidate.type, () => ( "unknown"))), [
1311
+ throw new (0, _chunkQFWEF5STcjs.ActivitySchemaError)(String(_nullishCoalesce(candidate.type, () => ( "unknown"))), [
1077
1312
  {
1078
1313
  path: ["redacted"],
1079
1314
  message: "Missing redacted marker \u2014 this payload is not a redact() projection.",
@@ -1082,12 +1317,12 @@ function assertRedacted(data) {
1082
1317
  ]);
1083
1318
  }
1084
1319
  const type = typeof candidate.type === "string" ? candidate.type : "";
1085
- const descriptor = _chunkVCXIPLEWcjs.getActivityTypeDescriptor.call(void 0, type);
1320
+ const descriptor = _chunkQFWEF5STcjs.getActivityTypeDescriptor.call(void 0, type);
1086
1321
  if (descriptor === void 0) {
1087
- throw new (0, _chunkVCXIPLEWcjs.UnknownActivityTypeError)(type);
1322
+ throw new (0, _chunkQFWEF5STcjs.UnknownActivityTypeError)(type);
1088
1323
  }
1089
1324
  if (descriptor.redactedSchema === void 0) {
1090
- throw new (0, _chunkVCXIPLEWcjs.ActivitySchemaError)(descriptor.type, [
1325
+ throw new (0, _chunkQFWEF5STcjs.ActivitySchemaError)(descriptor.type, [
1091
1326
  {
1092
1327
  path: [],
1093
1328
  message: `Activity type "${descriptor.type}" registers no redactedSchema; assertRedacted cannot prove this payload is learner-safe.`,
@@ -1097,7 +1332,7 @@ function assertRedacted(data) {
1097
1332
  }
1098
1333
  const parsed = descriptor.redactedSchema.safeParse(candidate);
1099
1334
  if (!parsed.success) {
1100
- throw new (0, _chunkVCXIPLEWcjs.ActivitySchemaError)(
1335
+ throw new (0, _chunkQFWEF5STcjs.ActivitySchemaError)(
1101
1336
  descriptor.type,
1102
1337
  parsed.error.issues.map((issue2) => ({
1103
1338
  path: issue2.path.map(String),
@@ -1113,7 +1348,7 @@ var STIMULUS_FIELD_POLICY = {
1113
1348
  title: "public",
1114
1349
  body: "public",
1115
1350
  bodyHtml: "public",
1116
- media: _chunkVCXIPLEWcjs.MEDIA_FIELD_POLICY,
1351
+ media: _chunkQFWEF5STcjs.MEDIA_FIELD_POLICY,
1117
1352
  locale: "public",
1118
1353
  attribution: "public",
1119
1354
  transcript: "author-only"
@@ -1127,7 +1362,25 @@ var ITEM_GROUP_FIELD_POLICY = {
1127
1362
  // and identity has to cross the redaction boundary intact.
1128
1363
  slotKey: "public",
1129
1364
  shuffle: "public",
1130
- stimulus: STIMULUS_FIELD_POLICY
1365
+ stimulus: STIMULUS_FIELD_POLICY,
1366
+ // Public, and classified key by key rather than as one leaf: the learner's
1367
+ // player needs every part of it, none of it is a key — and a leaf would hand
1368
+ // over the author's object by reference, with whatever else was parked in it.
1369
+ timeline: {
1370
+ // Applies to every element of the array.
1371
+ cues: {
1372
+ id: "public",
1373
+ at: "public",
1374
+ itemIds: "public",
1375
+ title: "public",
1376
+ required: "public"
1377
+ },
1378
+ chapters: {
1379
+ at: "public",
1380
+ title: "public"
1381
+ },
1382
+ navigation: "public"
1383
+ }
1131
1384
  };
1132
1385
  function redactItemGroup(group, options = {}) {
1133
1386
  const reveal = _nullishCoalesce(options.reveal, () => ( "none"));
@@ -1139,9 +1392,9 @@ function redactItemGroup(group, options = {}) {
1139
1392
  redacted: true
1140
1393
  };
1141
1394
  if (reveal === "none") {
1142
- const parsed = _chunk2NIALQEHcjs.RedactedItemGroupSchema.safeParse(result);
1395
+ const parsed = _chunkW7AQP6AVcjs.RedactedItemGroupSchema.safeParse(result);
1143
1396
  if (!parsed.success) {
1144
- throw new (0, _chunkVCXIPLEWcjs.ActivitySchemaError)(
1397
+ throw new (0, _chunkQFWEF5STcjs.ActivitySchemaError)(
1145
1398
  "item-group",
1146
1399
  parsed.error.issues.map((issue2) => ({
1147
1400
  path: issue2.path.map(String),
@@ -1155,13 +1408,13 @@ function redactItemGroup(group, options = {}) {
1155
1408
  }
1156
1409
  function assertRedactedItemGroup(data) {
1157
1410
  if (typeof data !== "object" || data === null) {
1158
- throw new (0, _chunkVCXIPLEWcjs.ActivitySchemaError)("item-group", [
1411
+ throw new (0, _chunkQFWEF5STcjs.ActivitySchemaError)("item-group", [
1159
1412
  { path: [], message: "Redacted item group must be an object.", code: "invalid_type" }
1160
1413
  ]);
1161
1414
  }
1162
1415
  const candidate = data;
1163
1416
  if (candidate.redacted !== true) {
1164
- throw new (0, _chunkVCXIPLEWcjs.ActivitySchemaError)("item-group", [
1417
+ throw new (0, _chunkQFWEF5STcjs.ActivitySchemaError)("item-group", [
1165
1418
  {
1166
1419
  path: ["redacted"],
1167
1420
  message: "Missing redacted marker \u2014 this payload is not a redactItemGroup() projection.",
@@ -1169,9 +1422,9 @@ function assertRedactedItemGroup(data) {
1169
1422
  }
1170
1423
  ]);
1171
1424
  }
1172
- const parsed = _chunk2NIALQEHcjs.RedactedItemGroupSchema.safeParse(candidate);
1425
+ const parsed = _chunkW7AQP6AVcjs.RedactedItemGroupSchema.safeParse(candidate);
1173
1426
  if (!parsed.success) {
1174
- throw new (0, _chunkVCXIPLEWcjs.ActivitySchemaError)(
1427
+ throw new (0, _chunkQFWEF5STcjs.ActivitySchemaError)(
1175
1428
  "item-group",
1176
1429
  parsed.error.issues.map((issue2) => ({
1177
1430
  path: issue2.path.map(String),
@@ -1184,8 +1437,8 @@ function assertRedactedItemGroup(data) {
1184
1437
  try {
1185
1438
  assertRedacted(item);
1186
1439
  } catch (error) {
1187
- if (error instanceof _chunkVCXIPLEWcjs.ActivitySchemaError) {
1188
- throw new (0, _chunkVCXIPLEWcjs.ActivitySchemaError)(
1440
+ if (error instanceof _chunkQFWEF5STcjs.ActivitySchemaError) {
1441
+ throw new (0, _chunkQFWEF5STcjs.ActivitySchemaError)(
1189
1442
  "item-group",
1190
1443
  error.errors.map((issue2) => ({
1191
1444
  ...issue2,
@@ -1198,6 +1451,54 @@ function assertRedactedItemGroup(data) {
1198
1451
  });
1199
1452
  }
1200
1453
 
1454
+ // src/timeline.ts
1455
+ function readMediaProgress(value, duration) {
1456
+ let version;
1457
+ let at;
1458
+ let furthest;
1459
+ try {
1460
+ if (typeof value !== "object" || value === null) {
1461
+ return null;
1462
+ }
1463
+ ({ progressVersion: version, at, furthest } = value);
1464
+ } catch (e) {
1465
+ return null;
1466
+ }
1467
+ if (version !== "1.0" || typeof at !== "number" || !Number.isFinite(at)) {
1468
+ return null;
1469
+ }
1470
+ const end = typeof duration === "number" && Number.isFinite(duration) && duration >= 0 ? duration : Number.POSITIVE_INFINITY;
1471
+ const clampedAt = Math.min(Math.max(0, at), end);
1472
+ const reached = typeof furthest === "number" && Number.isFinite(furthest) ? furthest : clampedAt;
1473
+ return {
1474
+ progressVersion: "1.0",
1475
+ at: clampedAt,
1476
+ furthest: Math.min(Math.max(clampedAt, reached), end)
1477
+ };
1478
+ }
1479
+ function composeTimelineScore(entryKey, items, policy) {
1480
+ const own = items.filter((item) => entryKeyOf(item.slotId) === entryKey);
1481
+ if (own.length === 0) {
1482
+ throw new Error(
1483
+ `composeTimelineScore: no scored item belongs to entry "${entryKey}". Pass the video's slotKey (or its position in the sequence), and the items of the attempt that holds it.`
1484
+ );
1485
+ }
1486
+ return _chunk5KWF34LJcjs.composeAssessmentScore.call(void 0, [{ id: entryKey, weight: 1, items: own }], policy);
1487
+ }
1488
+
1489
+
1490
+
1491
+
1492
+
1493
+
1494
+
1495
+
1496
+
1497
+
1498
+
1499
+
1500
+
1501
+
1201
1502
 
1202
1503
 
1203
1504
 
@@ -1330,5 +1631,5 @@ function assertRedactedItemGroup(data) {
1330
1631
 
1331
1632
 
1332
1633
 
1333
- exports.ActivitySchemaError = _chunkVCXIPLEWcjs.ActivitySchemaError; exports.BlankConfigSchema = _chunkVCXIPLEWcjs.BlankConfigSchema; exports.DEFAULT_PASS_THRESHOLD = _chunkJ5OIRIOWcjs.DEFAULT_PASS_THRESHOLD; exports.DICTATION_MAX_ACCEPTED_TRANSCRIPTS = _chunkVCXIPLEWcjs.DICTATION_MAX_ACCEPTED_TRANSCRIPTS; exports.DICTATION_MAX_EQUIVALENCES = _chunkVCXIPLEWcjs.DICTATION_MAX_EQUIVALENCES; exports.DICTATION_MAX_EQUIVALENCE_LENGTH = _chunkVCXIPLEWcjs.DICTATION_MAX_EQUIVALENCE_LENGTH; exports.DICTATION_MAX_TEXT_LENGTH = _chunkVCXIPLEWcjs.DICTATION_MAX_TEXT_LENGTH; exports.DICTATION_MAX_TRANSCRIPT_LENGTH = _chunkVCXIPLEWcjs.DICTATION_MAX_TRANSCRIPT_LENGTH; exports.DeferredScoringError = _chunkVCXIPLEWcjs.DeferredScoringError; exports.DictationDataSchema = _chunkVCXIPLEWcjs.DictationDataSchema; exports.DictationEquivalenceSchema = _chunkVCXIPLEWcjs.DictationEquivalenceSchema; exports.DictationSlowMediaSchema = _chunkVCXIPLEWcjs.DictationSlowMediaSchema; exports.DictationToleranceSchema = _chunkVCXIPLEWcjs.DictationToleranceSchema; exports.FeedbackSchema = _chunkVCXIPLEWcjs.FeedbackSchema; exports.FillInTheBlanksDataSchema = _chunkVCXIPLEWcjs.FillInTheBlanksDataSchema; exports.GapSelectBankSchema = _chunkVCXIPLEWcjs.GapSelectBankSchema; exports.GapSelectChoiceSchema = _chunkVCXIPLEWcjs.GapSelectChoiceSchema; exports.GapSelectDataSchema = _chunkVCXIPLEWcjs.GapSelectDataSchema; exports.GapSelectGapSchema = _chunkVCXIPLEWcjs.GapSelectGapSchema; exports.ItemGroupSchema = _chunk2NIALQEHcjs.ItemGroupSchema; exports.MediaPlaybackSchema = _chunkVCXIPLEWcjs.MediaPlaybackSchema; exports.MediaSchema = _chunkVCXIPLEWcjs.MediaSchema; exports.MediaUrlSchema = _chunkVCXIPLEWcjs.MediaUrlSchema; exports.MultipleChoiceDataSchema = _chunkVCXIPLEWcjs.MultipleChoiceDataSchema; exports.MultipleChoiceOptionMediaSchema = _chunkVCXIPLEWcjs.MultipleChoiceOptionMediaSchema; exports.MultipleChoiceOptionSchema = _chunkVCXIPLEWcjs.MultipleChoiceOptionSchema; exports.NativeControlHintSchema = _chunkVCXIPLEWcjs.NativeControlHintSchema; exports.READ_ALOUD_MAX_DIMENSION_WEIGHT = _chunkVCXIPLEWcjs.READ_ALOUD_MAX_DIMENSION_WEIGHT; exports.READ_ALOUD_MAX_REFERENCE_LENGTH = _chunkVCXIPLEWcjs.READ_ALOUD_MAX_REFERENCE_LENGTH; exports.READ_ALOUD_MAX_SECONDS = _chunkVCXIPLEWcjs.READ_ALOUD_MAX_SECONDS; exports.READ_ALOUD_MAX_TAKES = _chunkVCXIPLEWcjs.READ_ALOUD_MAX_TAKES; exports.ReadAloudDataSchema = _chunkVCXIPLEWcjs.ReadAloudDataSchema; exports.ReadAloudSlowMediaSchema = _chunkVCXIPLEWcjs.ReadAloudSlowMediaSchema; exports.RedactedBlankConfigSchema = _chunkVCXIPLEWcjs.RedactedBlankConfigSchema; exports.RedactedDictationDataSchema = _chunkVCXIPLEWcjs.RedactedDictationDataSchema; exports.RedactedDictationSlowMediaSchema = _chunkVCXIPLEWcjs.RedactedDictationSlowMediaSchema; exports.RedactedFillInTheBlanksDataSchema = _chunkVCXIPLEWcjs.RedactedFillInTheBlanksDataSchema; exports.RedactedGapSelectBankSchema = _chunkVCXIPLEWcjs.RedactedGapSelectBankSchema; exports.RedactedGapSelectChoiceSchema = _chunkVCXIPLEWcjs.RedactedGapSelectChoiceSchema; exports.RedactedGapSelectDataSchema = _chunkVCXIPLEWcjs.RedactedGapSelectDataSchema; exports.RedactedGapSelectGapSchema = _chunkVCXIPLEWcjs.RedactedGapSelectGapSchema; exports.RedactedItemGroupSchema = _chunk2NIALQEHcjs.RedactedItemGroupSchema; exports.RedactedMediaSchema = _chunkVCXIPLEWcjs.RedactedMediaSchema; exports.RedactedMultipleChoiceDataSchema = _chunkVCXIPLEWcjs.RedactedMultipleChoiceDataSchema; exports.RedactedMultipleChoiceOptionMediaSchema = _chunkVCXIPLEWcjs.RedactedMultipleChoiceOptionMediaSchema; exports.RedactedMultipleChoiceOptionSchema = _chunkVCXIPLEWcjs.RedactedMultipleChoiceOptionSchema; exports.RedactedReadAloudDataSchema = _chunkVCXIPLEWcjs.RedactedReadAloudDataSchema; exports.RedactedScoringError = _chunkVCXIPLEWcjs.RedactedScoringError; exports.RedactedStimulusSchema = _chunk2NIALQEHcjs.RedactedStimulusSchema; exports.RedactedWrittenResponseDataSchema = _chunkVCXIPLEWcjs.RedactedWrittenResponseDataSchema; exports.SPEECH_ASSESSMENT_MAX_WORDS = _chunkVCXIPLEWcjs.SPEECH_ASSESSMENT_MAX_WORDS; exports.StimulusSchema = _chunk2NIALQEHcjs.StimulusSchema; exports.TextMatchPolicySchema = _chunkVCXIPLEWcjs.TextMatchPolicySchema; exports.UnknownActivityTypeError = _chunkVCXIPLEWcjs.UnknownActivityTypeError; exports.WrittenResponseDataSchema = _chunkVCXIPLEWcjs.WrittenResponseDataSchema; exports.WrittenResponseRubricCriterionSchema = _chunkVCXIPLEWcjs.WrittenResponseRubricCriterionSchema; exports.WrittenResponseRubricSchema = _chunkVCXIPLEWcjs.WrittenResponseRubricSchema; exports.XAPIVerb = _chunkE7LPIZXIcjs.XAPIVerb; exports.XAPI_VERB_DISPLAY = _chunkE7LPIZXIcjs.XAPI_VERB_DISPLAY; exports.alignDictation = _chunkVCXIPLEWcjs.alignDictation; exports.alignReadAloud = _chunkJ5OIRIOWcjs.alignReadAloud; exports.assertRedacted = assertRedacted; exports.assertRedactedItemGroup = assertRedactedItemGroup; exports.canonicalJson = canonicalJson; exports.classifyBand = _chunkJ5OIRIOWcjs.classifyBand; exports.composeAssessmentScore = _chunkJ5OIRIOWcjs.composeAssessmentScore; exports.computePassThreshold = _chunkJ5OIRIOWcjs.computePassThreshold; exports.contentHash = contentHash; exports.countWords = _chunkVCXIPLEWcjs.countWords; exports.createDraft = createDraft; exports.createItemGroupDraft = createItemGroupDraft; exports.defineActivityType = _chunkVCXIPLEWcjs.defineActivityType; exports.dictationJsonSchema = _chunk2NIALQEHcjs.dictationJsonSchema; exports.dictationReferenceWords = _chunkVCXIPLEWcjs.dictationReferenceWords; exports.dictationType = _chunkVCXIPLEWcjs.dictationType; exports.diffDictationChars = _chunkJ5OIRIOWcjs.diffDictationChars; exports.diffResponses = diffResponses; exports.entryKeyOf = entryKeyOf; exports.evaluate = _chunkJ5OIRIOWcjs.evaluate; exports.fillInTheBlanksJsonSchema = _chunk2NIALQEHcjs.fillInTheBlanksJsonSchema; exports.fillInTheBlanksType = _chunkVCXIPLEWcjs.fillInTheBlanksType; exports.fingerprint = fingerprint; exports.flattenSequence = flattenSequence; exports.gapSelectJsonSchema = _chunk2NIALQEHcjs.gapSelectJsonSchema; exports.gapSelectType = _chunkVCXIPLEWcjs.gapSelectType; exports.getActivityTypeDescriptor = _chunkVCXIPLEWcjs.getActivityTypeDescriptor; exports.gradeFromRubric = _chunkJ5OIRIOWcjs.gradeFromRubric; exports.gradeReadAloud = _chunkJ5OIRIOWcjs.gradeReadAloud; exports.gte = _chunkJ5OIRIOWcjs.gte; exports.hasGrade = _chunkJ5OIRIOWcjs.hasGrade; exports.hashSeed = hashSeed; exports.inspectWav = _chunkJ5OIRIOWcjs.inspectWav; exports.isItemGroup = isItemGroup; exports.itemGroupJsonSchema = _chunk2NIALQEHcjs.itemGroupJsonSchema; exports.jsonSchemaFor = _chunk2NIALQEHcjs.jsonSchemaFor; exports.levenshteinDistance = _chunkVCXIPLEWcjs.levenshteinDistance; exports.matchText = _chunkVCXIPLEWcjs.matchText; exports.multipleChoiceJsonSchema = _chunk2NIALQEHcjs.multipleChoiceJsonSchema; exports.multipleChoiceType = _chunkVCXIPLEWcjs.multipleChoiceType; exports.outcomeFromGrade = _chunkJ5OIRIOWcjs.outcomeFromGrade; exports.outcomeFromUnscorable = _chunkJ5OIRIOWcjs.outcomeFromUnscorable; exports.planAttempt = planAttempt; exports.planMediaBudgets = planMediaBudgets; exports.readAloudJsonSchema = _chunk2NIALQEHcjs.readAloudJsonSchema; exports.readAloudType = _chunkVCXIPLEWcjs.readAloudType; exports.redact = redact; exports.redactItemGroup = redactItemGroup; exports.registerActivityType = _chunkVCXIPLEWcjs.registerActivityType; exports.registeredActivityTypes = _chunkVCXIPLEWcjs.registeredActivityTypes; exports.resolvePlaybackPolicy = resolvePlaybackPolicy; exports.restoreAttemptState = restoreAttemptState; exports.restoreMediaPlayLedger = restoreMediaPlayLedger; exports.roundGrade = _chunkJ5OIRIOWcjs.roundGrade; exports.score = _chunkJ5OIRIOWcjs.score; exports.scoredItemsFromPlan = scoredItemsFromPlan; exports.seededShuffle = seededShuffle; exports.serializeAttemptState = serializeAttemptState; exports.serializeMediaPlayLedger = serializeMediaPlayLedger; exports.slotMediaKey = slotMediaKey; exports.stimulusJsonSchema = _chunk2NIALQEHcjs.stimulusJsonSchema; exports.stimulusMediaKey = stimulusMediaKey; exports.validateActivity = _chunk2NIALQEHcjs.validateActivity; exports.validateDraft = validateDraft; exports.validateItemGroup = _chunk2NIALQEHcjs.validateItemGroup; exports.validateItemGroupDraft = validateItemGroupDraft; exports.validateSpeechAssessment = _chunkJ5OIRIOWcjs.validateSpeechAssessment; exports.validateXAPIStatement = _chunkE7LPIZXIcjs.validateXAPIStatement; exports.verifyAttemptPlan = verifyAttemptPlan; exports.writtenResponseJsonSchema = _chunk2NIALQEHcjs.writtenResponseJsonSchema; exports.writtenResponseType = _chunkVCXIPLEWcjs.writtenResponseType; exports.xAPIBuilder = _chunkE7LPIZXIcjs.xAPIBuilder; exports.xapiDefinitionFor = _chunkE7LPIZXIcjs.xapiDefinitionFor;
1634
+ exports.ActivitySchemaError = _chunkQFWEF5STcjs.ActivitySchemaError; exports.BlankConfigSchema = _chunkQFWEF5STcjs.BlankConfigSchema; exports.DEFAULT_PASS_THRESHOLD = _chunk5KWF34LJcjs.DEFAULT_PASS_THRESHOLD; exports.DICTATION_MAX_ACCEPTED_TRANSCRIPTS = _chunkQFWEF5STcjs.DICTATION_MAX_ACCEPTED_TRANSCRIPTS; exports.DICTATION_MAX_EQUIVALENCES = _chunkQFWEF5STcjs.DICTATION_MAX_EQUIVALENCES; exports.DICTATION_MAX_EQUIVALENCE_LENGTH = _chunkQFWEF5STcjs.DICTATION_MAX_EQUIVALENCE_LENGTH; exports.DICTATION_MAX_TEXT_LENGTH = _chunkQFWEF5STcjs.DICTATION_MAX_TEXT_LENGTH; exports.DICTATION_MAX_TRANSCRIPT_LENGTH = _chunkQFWEF5STcjs.DICTATION_MAX_TRANSCRIPT_LENGTH; exports.DeferredScoringError = _chunkQFWEF5STcjs.DeferredScoringError; exports.DictationDataSchema = _chunkQFWEF5STcjs.DictationDataSchema; exports.DictationEquivalenceSchema = _chunkQFWEF5STcjs.DictationEquivalenceSchema; exports.DictationSlowMediaSchema = _chunkQFWEF5STcjs.DictationSlowMediaSchema; exports.DictationToleranceSchema = _chunkQFWEF5STcjs.DictationToleranceSchema; exports.FeedbackSchema = _chunkQFWEF5STcjs.FeedbackSchema; exports.FillInTheBlanksDataSchema = _chunkQFWEF5STcjs.FillInTheBlanksDataSchema; exports.GapSelectBankSchema = _chunkQFWEF5STcjs.GapSelectBankSchema; exports.GapSelectChoiceSchema = _chunkQFWEF5STcjs.GapSelectChoiceSchema; exports.GapSelectDataSchema = _chunkQFWEF5STcjs.GapSelectDataSchema; exports.GapSelectGapSchema = _chunkQFWEF5STcjs.GapSelectGapSchema; exports.INTERACTIVE_VIDEO_ITEM_TYPES = _chunkW7AQP6AVcjs.INTERACTIVE_VIDEO_ITEM_TYPES; exports.ItemGroupSchema = _chunkW7AQP6AVcjs.ItemGroupSchema; exports.MediaPlaybackSchema = _chunkQFWEF5STcjs.MediaPlaybackSchema; exports.MediaSchema = _chunkQFWEF5STcjs.MediaSchema; exports.MediaTimelineSchema = _chunkW7AQP6AVcjs.MediaTimelineSchema; exports.MediaTrackSchema = _chunkQFWEF5STcjs.MediaTrackSchema; exports.MediaUrlSchema = _chunkQFWEF5STcjs.MediaUrlSchema; exports.MultipleChoiceDataSchema = _chunkQFWEF5STcjs.MultipleChoiceDataSchema; exports.MultipleChoiceOptionMediaSchema = _chunkQFWEF5STcjs.MultipleChoiceOptionMediaSchema; exports.MultipleChoiceOptionSchema = _chunkQFWEF5STcjs.MultipleChoiceOptionSchema; exports.NativeControlHintSchema = _chunkQFWEF5STcjs.NativeControlHintSchema; exports.READ_ALOUD_MAX_DIMENSION_WEIGHT = _chunkQFWEF5STcjs.READ_ALOUD_MAX_DIMENSION_WEIGHT; exports.READ_ALOUD_MAX_REFERENCE_LENGTH = _chunkQFWEF5STcjs.READ_ALOUD_MAX_REFERENCE_LENGTH; exports.READ_ALOUD_MAX_SECONDS = _chunkQFWEF5STcjs.READ_ALOUD_MAX_SECONDS; exports.READ_ALOUD_MAX_TAKES = _chunkQFWEF5STcjs.READ_ALOUD_MAX_TAKES; exports.ReadAloudDataSchema = _chunkQFWEF5STcjs.ReadAloudDataSchema; exports.ReadAloudSlowMediaSchema = _chunkQFWEF5STcjs.ReadAloudSlowMediaSchema; exports.RedactedBlankConfigSchema = _chunkQFWEF5STcjs.RedactedBlankConfigSchema; exports.RedactedDictationDataSchema = _chunkQFWEF5STcjs.RedactedDictationDataSchema; exports.RedactedDictationSlowMediaSchema = _chunkQFWEF5STcjs.RedactedDictationSlowMediaSchema; exports.RedactedFillInTheBlanksDataSchema = _chunkQFWEF5STcjs.RedactedFillInTheBlanksDataSchema; exports.RedactedGapSelectBankSchema = _chunkQFWEF5STcjs.RedactedGapSelectBankSchema; exports.RedactedGapSelectChoiceSchema = _chunkQFWEF5STcjs.RedactedGapSelectChoiceSchema; exports.RedactedGapSelectDataSchema = _chunkQFWEF5STcjs.RedactedGapSelectDataSchema; exports.RedactedGapSelectGapSchema = _chunkQFWEF5STcjs.RedactedGapSelectGapSchema; exports.RedactedItemGroupSchema = _chunkW7AQP6AVcjs.RedactedItemGroupSchema; exports.RedactedMediaSchema = _chunkQFWEF5STcjs.RedactedMediaSchema; exports.RedactedMultipleChoiceDataSchema = _chunkQFWEF5STcjs.RedactedMultipleChoiceDataSchema; exports.RedactedMultipleChoiceOptionMediaSchema = _chunkQFWEF5STcjs.RedactedMultipleChoiceOptionMediaSchema; exports.RedactedMultipleChoiceOptionSchema = _chunkQFWEF5STcjs.RedactedMultipleChoiceOptionSchema; exports.RedactedReadAloudDataSchema = _chunkQFWEF5STcjs.RedactedReadAloudDataSchema; exports.RedactedScoringError = _chunkQFWEF5STcjs.RedactedScoringError; exports.RedactedStimulusSchema = _chunkW7AQP6AVcjs.RedactedStimulusSchema; exports.RedactedWrittenResponseDataSchema = _chunkQFWEF5STcjs.RedactedWrittenResponseDataSchema; exports.SPEECH_ASSESSMENT_MAX_WORDS = _chunkQFWEF5STcjs.SPEECH_ASSESSMENT_MAX_WORDS; exports.StimulusSchema = _chunkW7AQP6AVcjs.StimulusSchema; exports.TIMELINE_MAX_CHAPTERS = _chunkW7AQP6AVcjs.TIMELINE_MAX_CHAPTERS; exports.TIMELINE_MAX_ITEMS = _chunkW7AQP6AVcjs.TIMELINE_MAX_ITEMS; exports.TIMELINE_MAX_QUIZZES = _chunkW7AQP6AVcjs.TIMELINE_MAX_QUIZZES; exports.TIMELINE_MAX_TITLE_LENGTH = _chunkW7AQP6AVcjs.TIMELINE_MAX_TITLE_LENGTH; exports.TextMatchPolicySchema = _chunkQFWEF5STcjs.TextMatchPolicySchema; exports.TimelineChapterSchema = _chunkW7AQP6AVcjs.TimelineChapterSchema; exports.TimelineCueSchema = _chunkW7AQP6AVcjs.TimelineCueSchema; exports.UnknownActivityTypeError = _chunkQFWEF5STcjs.UnknownActivityTypeError; exports.WrittenResponseDataSchema = _chunkQFWEF5STcjs.WrittenResponseDataSchema; exports.WrittenResponseRubricCriterionSchema = _chunkQFWEF5STcjs.WrittenResponseRubricCriterionSchema; exports.WrittenResponseRubricSchema = _chunkQFWEF5STcjs.WrittenResponseRubricSchema; exports.XAPIVerb = _chunk7ETU6EXQcjs.XAPIVerb; exports.XAPI_VERB_DISPLAY = _chunk7ETU6EXQcjs.XAPI_VERB_DISPLAY; exports.alignDictation = _chunkQFWEF5STcjs.alignDictation; exports.alignReadAloud = _chunk5KWF34LJcjs.alignReadAloud; exports.assertRedacted = assertRedacted; exports.assertRedactedItemGroup = assertRedactedItemGroup; exports.canonicalJson = canonicalJson; exports.classifyBand = _chunk5KWF34LJcjs.classifyBand; exports.composeAssessmentScore = _chunk5KWF34LJcjs.composeAssessmentScore; exports.composeTimelineScore = composeTimelineScore; exports.computePassThreshold = _chunk5KWF34LJcjs.computePassThreshold; exports.contentHash = contentHash; exports.countWords = _chunkQFWEF5STcjs.countWords; exports.createDraft = createDraft; exports.createInteractiveVideoDraft = createInteractiveVideoDraft; exports.createItemGroupDraft = createItemGroupDraft; exports.defineActivityType = _chunkQFWEF5STcjs.defineActivityType; exports.dictationJsonSchema = _chunkW7AQP6AVcjs.dictationJsonSchema; exports.dictationReferenceWords = _chunkQFWEF5STcjs.dictationReferenceWords; exports.dictationType = _chunkQFWEF5STcjs.dictationType; exports.diffDictationChars = _chunk5KWF34LJcjs.diffDictationChars; exports.diffResponses = diffResponses; exports.entryKeyOf = entryKeyOf; exports.evaluate = _chunk5KWF34LJcjs.evaluate; exports.fillInTheBlanksJsonSchema = _chunkW7AQP6AVcjs.fillInTheBlanksJsonSchema; exports.fillInTheBlanksType = _chunkQFWEF5STcjs.fillInTheBlanksType; exports.fingerprint = fingerprint; exports.flattenSequence = flattenSequence; exports.gapSelectJsonSchema = _chunkW7AQP6AVcjs.gapSelectJsonSchema; exports.gapSelectType = _chunkQFWEF5STcjs.gapSelectType; exports.getActivityTypeDescriptor = _chunkQFWEF5STcjs.getActivityTypeDescriptor; exports.gradeFromRubric = _chunk5KWF34LJcjs.gradeFromRubric; exports.gradeReadAloud = _chunk5KWF34LJcjs.gradeReadAloud; exports.gte = _chunk5KWF34LJcjs.gte; exports.hasGrade = _chunk5KWF34LJcjs.hasGrade; exports.hashSeed = hashSeed; exports.inspectWav = _chunk5KWF34LJcjs.inspectWav; exports.isInteractiveVideoItemType = _chunkW7AQP6AVcjs.isInteractiveVideoItemType; exports.isItemGroup = isItemGroup; exports.itemGroupJsonSchema = _chunkW7AQP6AVcjs.itemGroupJsonSchema; exports.jsonSchemaFor = _chunkW7AQP6AVcjs.jsonSchemaFor; exports.levenshteinDistance = _chunkQFWEF5STcjs.levenshteinDistance; exports.matchText = _chunkQFWEF5STcjs.matchText; exports.multipleChoiceJsonSchema = _chunkW7AQP6AVcjs.multipleChoiceJsonSchema; exports.multipleChoiceType = _chunkQFWEF5STcjs.multipleChoiceType; exports.outcomeFromGrade = _chunk5KWF34LJcjs.outcomeFromGrade; exports.outcomeFromUnscorable = _chunk5KWF34LJcjs.outcomeFromUnscorable; exports.planAttempt = planAttempt; exports.planMediaBudgets = planMediaBudgets; exports.readAloudJsonSchema = _chunkW7AQP6AVcjs.readAloudJsonSchema; exports.readAloudType = _chunkQFWEF5STcjs.readAloudType; exports.readMediaProgress = readMediaProgress; exports.redact = redact; exports.redactItemGroup = redactItemGroup; exports.registerActivityType = _chunkQFWEF5STcjs.registerActivityType; exports.registeredActivityTypes = _chunkQFWEF5STcjs.registeredActivityTypes; exports.resolvePlaybackPolicy = resolvePlaybackPolicy; exports.restoreAttemptState = restoreAttemptState; exports.restoreMediaPlayLedger = restoreMediaPlayLedger; exports.roundGrade = _chunk5KWF34LJcjs.roundGrade; exports.score = _chunk5KWF34LJcjs.score; exports.scoredItemsFromPlan = scoredItemsFromPlan; exports.seededShuffle = seededShuffle; exports.serializeAttemptState = serializeAttemptState; exports.serializeMediaPlayLedger = serializeMediaPlayLedger; exports.slotMediaKey = slotMediaKey; exports.stimulusJsonSchema = _chunkW7AQP6AVcjs.stimulusJsonSchema; exports.stimulusMediaKey = stimulusMediaKey; exports.validateActivity = _chunkW7AQP6AVcjs.validateActivity; exports.validateDraft = validateDraft; exports.validateItemGroup = _chunkW7AQP6AVcjs.validateItemGroup; exports.validateItemGroupDraft = validateItemGroupDraft; exports.validateSpeechAssessment = _chunk5KWF34LJcjs.validateSpeechAssessment; exports.validateXAPIStatement = _chunk7ETU6EXQcjs.validateXAPIStatement; exports.verifyAttemptPlan = verifyAttemptPlan; exports.writtenResponseJsonSchema = _chunkW7AQP6AVcjs.writtenResponseJsonSchema; exports.writtenResponseType = _chunkQFWEF5STcjs.writtenResponseType; exports.xAPIBuilder = _chunk7ETU6EXQcjs.xAPIBuilder; exports.xapiDefinitionFor = _chunk7ETU6EXQcjs.xapiDefinitionFor;
1334
1635
  //# sourceMappingURL=index.cjs.map