@intellectif/lk-core 0.13.0 → 0.14.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 +35 -0
- package/README.md +1 -1
- package/dist/{activity-DfAmJ1sl.d.cts → activity-BVkg9VDo.d.cts} +153 -4
- package/dist/{activity-DfAmJ1sl.d.ts → activity-BVkg9VDo.d.ts} +153 -4
- package/dist/{chunk-DQKJUMUW.cjs → chunk-2NIALQEH.cjs} +24 -19
- package/dist/chunk-2NIALQEH.cjs.map +1 -0
- package/dist/{chunk-XKKKWKRH.js → chunk-6RND47QE.js} +694 -126
- package/dist/chunk-6RND47QE.js.map +1 -0
- package/dist/{chunk-FT7SAC3X.cjs → chunk-CZRUMHKW.cjs} +4 -4
- package/dist/{chunk-FT7SAC3X.cjs.map → chunk-CZRUMHKW.cjs.map} +1 -1
- package/dist/chunk-J5OIRIOW.cjs +1034 -0
- package/dist/chunk-J5OIRIOW.cjs.map +1 -0
- package/dist/{chunk-Y36S3X3L.js → chunk-NBADQ3JU.js} +7 -2
- package/dist/chunk-NBADQ3JU.js.map +1 -0
- package/dist/{chunk-PYP3HCRQ.js → chunk-R7PV3XIC.js} +2 -2
- package/dist/chunk-RTIR6R2U.js +1034 -0
- package/dist/chunk-RTIR6R2U.js.map +1 -0
- package/dist/{chunk-XONKWL6D.cjs → chunk-VCXIPLEW.cjs} +585 -17
- package/dist/chunk-VCXIPLEW.cjs.map +1 -0
- package/dist/{index-Bz9wUigA.d.cts → index-BE1bM2Wi.d.cts} +225 -3
- package/dist/{index-CJbbVE9o.d.ts → index-v2_-Fyn3.d.ts} +225 -3
- package/dist/index.cjs +113 -80
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -17
- package/dist/index.d.ts +50 -17
- package/dist/index.js +39 -6
- package/dist/index.js.map +1 -1
- package/dist/schemas.cjs +11 -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 +10 -2
- package/dist/scoring.cjs +23 -3
- package/dist/scoring.cjs.map +1 -1
- package/dist/scoring.d.cts +471 -16
- package/dist/scoring.d.ts +471 -16
- package/dist/scoring.js +24 -4
- 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 +63 -3
- package/vectors/replay.d.mts +7 -2
- package/vectors/replay.mjs +83 -1
- package/vectors/scoring.json +10875 -2
- package/dist/chunk-DQKJUMUW.cjs.map +0 -1
- package/dist/chunk-FGN4LLSP.js +0 -387
- package/dist/chunk-FGN4LLSP.js.map +0 -1
- package/dist/chunk-UHQVIC3P.cjs +0 -387
- package/dist/chunk-UHQVIC3P.cjs.map +0 -1
- package/dist/chunk-XKKKWKRH.js.map +0 -1
- package/dist/chunk-XONKWL6D.cjs.map +0 -1
- package/dist/chunk-Y36S3X3L.js.map +0 -1
- /package/dist/{chunk-PYP3HCRQ.js.map → chunk-R7PV3XIC.js.map} +0 -0
|
@@ -20,7 +20,7 @@ var UnknownActivityTypeError = class extends Error {
|
|
|
20
20
|
var RedactedScoringError = class extends Error {
|
|
21
21
|
constructor(activityType) {
|
|
22
22
|
super(
|
|
23
|
-
`Activity data for "${activityType}" carries no answer key (it looks redacted), so it cannot be scored. Score against the full activity data server-side
|
|
23
|
+
`Activity data for "${activityType}" carries no answer key (it looks redacted), so it cannot be scored. Score against the full activity data server-side. evaluate() answers this input without throwing, but it never grades it.`
|
|
24
24
|
);
|
|
25
25
|
this.activityType = activityType;
|
|
26
26
|
this.name = "RedactedScoringError";
|
|
@@ -220,6 +220,10 @@ var SPACE_BESIDE_UNSPACED_RE = new RegExp(
|
|
|
220
220
|
);
|
|
221
221
|
var WORD_RE = new RegExp(`^[\\p{L}\\p{M}\\p{N}${JOINERS}]$`, "u");
|
|
222
222
|
var UNSPACED_CHARACTER_RE = new RegExp(`^${UNSPACED_CHARACTER}$`, "u");
|
|
223
|
+
var UNSPACED_LETTER_RE = new RegExp(`(?=\\p{L})${UNSPACED_CHARACTER}`, "u");
|
|
224
|
+
function containsUnspacedScript(text) {
|
|
225
|
+
return UNSPACED_LETTER_RE.test(text);
|
|
226
|
+
}
|
|
223
227
|
var EXTENDING_RE = new RegExp(`^[\\p{M}${JOINERS}${TAGS}]$`, "u");
|
|
224
228
|
var WORD = 1;
|
|
225
229
|
var UNSPACED = 2;
|
|
@@ -1341,6 +1345,168 @@ var MultipleChoiceDataSchema = _v4.z.looseObject({
|
|
|
1341
1345
|
path: ["options"]
|
|
1342
1346
|
});
|
|
1343
1347
|
|
|
1348
|
+
// src/scoring/speech/limits.ts
|
|
1349
|
+
var READ_ALOUD_MAX_REFERENCE_LENGTH = DICTATION_MAX_TRANSCRIPT_LENGTH;
|
|
1350
|
+
var READ_ALOUD_MAX_SECONDS = 300;
|
|
1351
|
+
var READ_ALOUD_MAX_TAKES = 20;
|
|
1352
|
+
var READ_ALOUD_MAX_DIMENSION_WEIGHT = 1e3;
|
|
1353
|
+
var SPEECH_ASSESSMENT_MAX_WORDS = 1e3;
|
|
1354
|
+
var SPEECH_ASSESSMENT_MAX_TEXT_LENGTH = DICTATION_MAX_TEXT_LENGTH;
|
|
1355
|
+
|
|
1356
|
+
// src/schemas/read-aloud.ts
|
|
1357
|
+
|
|
1358
|
+
|
|
1359
|
+
// src/scoring/speech/locale.ts
|
|
1360
|
+
var CANONICAL_LOCALE_RE = /^[a-z]{2,3}(?:-[A-Z][a-z]{3})?-(?:[A-Z]{2}|[0-9]{3})$/;
|
|
1361
|
+
|
|
1362
|
+
// src/schemas/read-aloud.ts
|
|
1363
|
+
var READ_ALOUD_DIMENSIONS = ["accuracy", "fluency", "completeness", "prosody"];
|
|
1364
|
+
var READ_ALOUD_MAX_DIMENSIONS = READ_ALOUD_DIMENSIONS.length;
|
|
1365
|
+
var ReadAloudSlowMediaSchema = _v4.z.strictObject({
|
|
1366
|
+
type: _v4.z.literal("audio"),
|
|
1367
|
+
url: MediaUrlSchema,
|
|
1368
|
+
alt: _v4.z.string().min(1).optional()
|
|
1369
|
+
});
|
|
1370
|
+
var ReferenceTextSchema = _v4.z.string().min(1).refine((text) => text.trim() !== "", {
|
|
1371
|
+
error: "The text to read aloud must contain something to read."
|
|
1372
|
+
}).meta({ maxLength: READ_ALOUD_MAX_REFERENCE_LENGTH });
|
|
1373
|
+
var RecordingBoundsSchema = _v4.z.looseObject({
|
|
1374
|
+
maxSeconds: _v4.z.number().gt(0).max(READ_ALOUD_MAX_SECONDS),
|
|
1375
|
+
minSeconds: _v4.z.number().min(0).optional(),
|
|
1376
|
+
maxTakes: _v4.z.number().int().min(1).max(READ_ALOUD_MAX_TAKES).optional()
|
|
1377
|
+
});
|
|
1378
|
+
var ReadAloudDimensionWeightSchema = _v4.z.looseObject({
|
|
1379
|
+
name: _v4.z.enum(READ_ALOUD_DIMENSIONS),
|
|
1380
|
+
weight: _v4.z.number().min(0).max(READ_ALOUD_MAX_DIMENSION_WEIGHT)
|
|
1381
|
+
});
|
|
1382
|
+
var ReadAloudScoringSchema = _v4.z.looseObject({
|
|
1383
|
+
dimensions: _v4.z.array(ReadAloudDimensionWeightSchema).min(1).max(READ_ALOUD_MAX_DIMENSIONS)
|
|
1384
|
+
});
|
|
1385
|
+
function checkEvenAfterIssues2(check) {
|
|
1386
|
+
const guard = new _v4.z.core.$ZodCheck({ check: "custom", when: () => true });
|
|
1387
|
+
guard._zod.check = check;
|
|
1388
|
+
return guard;
|
|
1389
|
+
}
|
|
1390
|
+
var ReadAloudDataShape = _v4.z.looseObject({
|
|
1391
|
+
schemaVersion: _v4.z.literal("1.0"),
|
|
1392
|
+
type: _v4.z.literal("read-aloud"),
|
|
1393
|
+
id: _v4.z.string().min(1),
|
|
1394
|
+
title: _v4.z.string().min(1),
|
|
1395
|
+
instructions: _v4.z.string().optional(),
|
|
1396
|
+
referenceText: ReferenceTextSchema,
|
|
1397
|
+
locale: _v4.z.string().regex(CANONICAL_LOCALE_RE, {
|
|
1398
|
+
error: `The locale must be a BCP 47 tag in canonical form, with a region: "en-US", "es-419", "zh-Hant-TW". Pronunciation is assessed against one locale's speech, and "en" does not say whose.`
|
|
1399
|
+
}),
|
|
1400
|
+
media: MediaSchema.optional(),
|
|
1401
|
+
slowMedia: ReadAloudSlowMediaSchema.optional(),
|
|
1402
|
+
recording: RecordingBoundsSchema,
|
|
1403
|
+
scoring: ReadAloudScoringSchema,
|
|
1404
|
+
passThreshold: _v4.z.number().min(0).max(1).optional(),
|
|
1405
|
+
feedback: FeedbackSchema.optional(),
|
|
1406
|
+
learningObjectives: _v4.z.array(_v4.z.string()).optional(),
|
|
1407
|
+
difficultyLevel: _v4.z.literal([1, 2, 3, 4, 5]).optional()
|
|
1408
|
+
});
|
|
1409
|
+
var ReadAloudDataSchema = ReadAloudDataShape.check(
|
|
1410
|
+
checkEvenAfterIssues2((ctx) => {
|
|
1411
|
+
if (ctx.issues.some((issue2) => (_nullishCoalesce(_optionalChain([issue2, 'access', _53 => _53.path, 'optionalAccess', _54 => _54.length]), () => ( 0))) === 0)) {
|
|
1412
|
+
return;
|
|
1413
|
+
}
|
|
1414
|
+
const data = ctx.value;
|
|
1415
|
+
const refused = new Set(ctx.issues.map((issue2) => String(_optionalChain([issue2, 'access', _55 => _55.path, 'optionalAccess', _56 => _56[0]]))));
|
|
1416
|
+
const report = (path, input, message) => {
|
|
1417
|
+
ctx.issues.push({ code: "custom", input, message, path: [...path] });
|
|
1418
|
+
};
|
|
1419
|
+
if (!refused.has("referenceText")) {
|
|
1420
|
+
const text = data.referenceText;
|
|
1421
|
+
const measured = dictationNormalizer(void 0).measure(text);
|
|
1422
|
+
if (measured.tooLong) {
|
|
1423
|
+
report(
|
|
1424
|
+
["referenceText"],
|
|
1425
|
+
text,
|
|
1426
|
+
`The text to read aloud is at most ${READ_ALOUD_MAX_REFERENCE_LENGTH} characters, before and after normalisation.`
|
|
1427
|
+
);
|
|
1428
|
+
}
|
|
1429
|
+
if (measured.normalized === "") {
|
|
1430
|
+
report(
|
|
1431
|
+
["referenceText"],
|
|
1432
|
+
text,
|
|
1433
|
+
"The text to read aloud must contain a word: after ignoring punctuation and spacing nothing is left, so no word would be marked and every reading would align as one insertion after another."
|
|
1434
|
+
);
|
|
1435
|
+
}
|
|
1436
|
+
if (containsUnspacedScript(text)) {
|
|
1437
|
+
report(
|
|
1438
|
+
["referenceText"],
|
|
1439
|
+
text,
|
|
1440
|
+
"A read-aloud item needs a script written with spaces between its words. The text is compared word by word, and a run of Han, kana, Thai, Lao, Khmer or Myanmar letters is one word however many it holds."
|
|
1441
|
+
);
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
const mediaParses = !refused.has("media");
|
|
1445
|
+
const slowParses = !refused.has("slowMedia");
|
|
1446
|
+
if (mediaParses && data.media !== void 0 && data.media.type !== "audio") {
|
|
1447
|
+
report(
|
|
1448
|
+
["media", "type"],
|
|
1449
|
+
data.media.type,
|
|
1450
|
+
"A read-aloud model is read aloud: its recording must be audio."
|
|
1451
|
+
);
|
|
1452
|
+
}
|
|
1453
|
+
if (mediaParses && slowParses && data.slowMedia !== void 0) {
|
|
1454
|
+
if (data.media === void 0) {
|
|
1455
|
+
report(
|
|
1456
|
+
["media"],
|
|
1457
|
+
data.media,
|
|
1458
|
+
"A slow model recording accompanies a recording: add `media` first."
|
|
1459
|
+
);
|
|
1460
|
+
}
|
|
1461
|
+
if (_optionalChain([data, 'access', _57 => _57.media, 'optionalAccess', _58 => _58.playback, 'optionalAccess', _59 => _59.maxPlays]) !== void 0) {
|
|
1462
|
+
report(
|
|
1463
|
+
["slowMedia"],
|
|
1464
|
+
data.slowMedia,
|
|
1465
|
+
"A play budget on `media` cannot coexist with an unbudgeted slow recording of the same content. Drop `slowMedia`, or drop `maxPlays`."
|
|
1466
|
+
);
|
|
1467
|
+
}
|
|
1468
|
+
if (typeof data.slowMedia.url === "string" && typeof _optionalChain([data, 'access', _60 => _60.media, 'optionalAccess', _61 => _61.url]) === "string" && data.slowMedia.url === data.media.url) {
|
|
1469
|
+
report(
|
|
1470
|
+
["slowMedia", "url"],
|
|
1471
|
+
data.slowMedia.url,
|
|
1472
|
+
"The slow model recording must be a different file from the recording."
|
|
1473
|
+
);
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
if (!refused.has("scoring")) {
|
|
1477
|
+
const dimensions = data.scoring.dimensions;
|
|
1478
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1479
|
+
for (const [index, dimension] of dimensions.entries()) {
|
|
1480
|
+
if (seen.has(dimension.name)) {
|
|
1481
|
+
report(
|
|
1482
|
+
["scoring", "dimensions", index, "name"],
|
|
1483
|
+
dimension.name,
|
|
1484
|
+
`"${dimension.name}" is already weighed: a dimension counted twice hides which weight the grade used.`
|
|
1485
|
+
);
|
|
1486
|
+
}
|
|
1487
|
+
seen.add(dimension.name);
|
|
1488
|
+
}
|
|
1489
|
+
if (dimensions.every((dimension) => dimension.weight === 0)) {
|
|
1490
|
+
report(
|
|
1491
|
+
["scoring", "dimensions"],
|
|
1492
|
+
dimensions,
|
|
1493
|
+
"At least one dimension must carry a weight above 0: with every weight at 0 there is no weighted total, and every take would be unscorable."
|
|
1494
|
+
);
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
if (!refused.has("recording")) {
|
|
1498
|
+
const { minSeconds, maxSeconds } = data.recording;
|
|
1499
|
+
if (minSeconds !== void 0 && minSeconds >= maxSeconds) {
|
|
1500
|
+
report(
|
|
1501
|
+
["recording", "minSeconds"],
|
|
1502
|
+
minSeconds,
|
|
1503
|
+
"The shortest take must be shorter than the longest."
|
|
1504
|
+
);
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
})
|
|
1508
|
+
);
|
|
1509
|
+
|
|
1344
1510
|
// src/count-words.ts
|
|
1345
1511
|
function countWords(text) {
|
|
1346
1512
|
if (typeof text !== "string") {
|
|
@@ -1377,7 +1543,7 @@ function resolveChoices(gap, banks) {
|
|
|
1377
1543
|
if (gap.bankId === void 0) {
|
|
1378
1544
|
return void 0;
|
|
1379
1545
|
}
|
|
1380
|
-
return _optionalChain([banks, 'access',
|
|
1546
|
+
return _optionalChain([banks, 'access', _62 => _62.find, 'call', _63 => _63((bank) => bank.id === gap.bankId), 'optionalAccess', _64 => _64.choices]);
|
|
1381
1547
|
}
|
|
1382
1548
|
function placeholderCounts(passage) {
|
|
1383
1549
|
const counts = /* @__PURE__ */ new Map();
|
|
@@ -1591,7 +1757,7 @@ var RedactedDictationDataSchema = _v4.z.strictObject({
|
|
|
1591
1757
|
hints: _v4.z.strictObject({ mode: _v4.z.literal("progressive-words") }).optional()
|
|
1592
1758
|
}).check((ctx) => {
|
|
1593
1759
|
const data = ctx.value;
|
|
1594
|
-
if (_optionalChain([data, 'access',
|
|
1760
|
+
if (_optionalChain([data, 'access', _65 => _65.media, 'optionalAccess', _66 => _66.captionsUrl]) !== void 0) {
|
|
1595
1761
|
ctx.issues.push({
|
|
1596
1762
|
code: "custom",
|
|
1597
1763
|
input: data.media.captionsUrl,
|
|
@@ -1599,7 +1765,7 @@ var RedactedDictationDataSchema = _v4.z.strictObject({
|
|
|
1599
1765
|
path: ["media", "captionsUrl"]
|
|
1600
1766
|
});
|
|
1601
1767
|
}
|
|
1602
|
-
if (data.slowMedia !== void 0 && _optionalChain([data, 'access',
|
|
1768
|
+
if (data.slowMedia !== void 0 && _optionalChain([data, 'access', _67 => _67.media, 'optionalAccess', _68 => _68.playback, 'optionalAccess', _69 => _69.maxPlays]) !== void 0) {
|
|
1603
1769
|
ctx.issues.push({
|
|
1604
1770
|
code: "custom",
|
|
1605
1771
|
input: data.slowMedia,
|
|
@@ -1616,6 +1782,61 @@ var RedactedDictationDataSchema = _v4.z.strictObject({
|
|
|
1616
1782
|
});
|
|
1617
1783
|
}
|
|
1618
1784
|
});
|
|
1785
|
+
var RedactedReadAloudDataSchema = _v4.z.strictObject({
|
|
1786
|
+
...redactedBase,
|
|
1787
|
+
type: _v4.z.literal("read-aloud"),
|
|
1788
|
+
locale: _v4.z.string().regex(CANONICAL_LOCALE_RE),
|
|
1789
|
+
instructions: _v4.z.string().optional(),
|
|
1790
|
+
referenceText: _v4.z.string().min(1),
|
|
1791
|
+
slowMedia: ReadAloudSlowMediaSchema.optional(),
|
|
1792
|
+
recording: _v4.z.strictObject({
|
|
1793
|
+
maxSeconds: _v4.z.number().gt(0).max(READ_ALOUD_MAX_SECONDS),
|
|
1794
|
+
minSeconds: _v4.z.number().min(0).optional(),
|
|
1795
|
+
maxTakes: _v4.z.number().int().min(1).max(READ_ALOUD_MAX_TAKES).optional()
|
|
1796
|
+
}),
|
|
1797
|
+
scoring: _v4.z.strictObject({
|
|
1798
|
+
dimensions: _v4.z.array(
|
|
1799
|
+
_v4.z.strictObject({
|
|
1800
|
+
name: _v4.z.enum(READ_ALOUD_DIMENSIONS),
|
|
1801
|
+
weight: _v4.z.number().min(0).max(READ_ALOUD_MAX_DIMENSION_WEIGHT)
|
|
1802
|
+
})
|
|
1803
|
+
).min(1).max(READ_ALOUD_DIMENSIONS.length)
|
|
1804
|
+
})
|
|
1805
|
+
}).check((ctx) => {
|
|
1806
|
+
const data = ctx.value;
|
|
1807
|
+
if (data.media !== void 0 && data.media.type !== "audio") {
|
|
1808
|
+
ctx.issues.push({
|
|
1809
|
+
code: "custom",
|
|
1810
|
+
input: data.media.type,
|
|
1811
|
+
message: "A read-aloud model recording must be audio, so this payload is not renderable.",
|
|
1812
|
+
path: ["media", "type"]
|
|
1813
|
+
});
|
|
1814
|
+
}
|
|
1815
|
+
if (data.slowMedia !== void 0 && data.media === void 0) {
|
|
1816
|
+
ctx.issues.push({
|
|
1817
|
+
code: "custom",
|
|
1818
|
+
input: data.slowMedia,
|
|
1819
|
+
message: "A slow model recording accompanies a recording: this payload has no `media`.",
|
|
1820
|
+
path: ["media"]
|
|
1821
|
+
});
|
|
1822
|
+
}
|
|
1823
|
+
if (data.slowMedia !== void 0 && _optionalChain([data, 'access', _70 => _70.media, 'optionalAccess', _71 => _71.playback, 'optionalAccess', _72 => _72.maxPlays]) !== void 0) {
|
|
1824
|
+
ctx.issues.push({
|
|
1825
|
+
code: "custom",
|
|
1826
|
+
input: data.slowMedia,
|
|
1827
|
+
message: "A play budget on `media` cannot coexist with an unbudgeted slow recording of the same content.",
|
|
1828
|
+
path: ["slowMedia"]
|
|
1829
|
+
});
|
|
1830
|
+
}
|
|
1831
|
+
if (data.slowMedia !== void 0 && data.slowMedia.url === _optionalChain([data, 'access', _73 => _73.media, 'optionalAccess', _74 => _74.url])) {
|
|
1832
|
+
ctx.issues.push({
|
|
1833
|
+
code: "custom",
|
|
1834
|
+
input: data.slowMedia.url,
|
|
1835
|
+
message: "The slow model recording must be a different file from the recording.",
|
|
1836
|
+
path: ["slowMedia", "url"]
|
|
1837
|
+
});
|
|
1838
|
+
}
|
|
1839
|
+
});
|
|
1619
1840
|
|
|
1620
1841
|
// src/scoring/dictation/edit-distance.ts
|
|
1621
1842
|
function codePoints(text) {
|
|
@@ -2037,7 +2258,27 @@ var DRAFT_ISSUE_SEVERITY = {
|
|
|
2037
2258
|
dc_hints_mode_invalid: "invalid",
|
|
2038
2259
|
dc_equivalence_from_required: "incomplete",
|
|
2039
2260
|
dc_equivalence_to_required: "incomplete",
|
|
2040
|
-
dc_tolerance_invalid: "invalid"
|
|
2261
|
+
dc_tolerance_invalid: "invalid",
|
|
2262
|
+
// read-aloud
|
|
2263
|
+
ra_reference_text_required: "incomplete",
|
|
2264
|
+
ra_reference_text_too_long: "invalid",
|
|
2265
|
+
ra_reference_text_unreadable: "invalid",
|
|
2266
|
+
ra_reference_text_unspaced_script: "invalid",
|
|
2267
|
+
ra_locale_required: "incomplete",
|
|
2268
|
+
ra_locale_invalid: "invalid",
|
|
2269
|
+
ra_max_seconds_required: "incomplete",
|
|
2270
|
+
ra_max_seconds_out_of_range: "invalid",
|
|
2271
|
+
ra_min_seconds_out_of_range: "invalid",
|
|
2272
|
+
ra_max_takes_out_of_range: "invalid",
|
|
2273
|
+
ra_dimensions_required: "incomplete",
|
|
2274
|
+
ra_dimension_name_invalid: "invalid",
|
|
2275
|
+
ra_dimension_duplicate: "invalid",
|
|
2276
|
+
ra_dimension_weight_invalid: "invalid",
|
|
2277
|
+
ra_dimension_weights_zero: "invalid",
|
|
2278
|
+
ra_media_kind: "invalid",
|
|
2279
|
+
ra_slow_media_without_media: "incomplete",
|
|
2280
|
+
ra_slow_media_same_recording: "invalid",
|
|
2281
|
+
ra_slow_media_beside_play_limit: "invalid"
|
|
2041
2282
|
};
|
|
2042
2283
|
function issue(code, path, message) {
|
|
2043
2284
|
return { path: path.map(String), message, code, severity: DRAFT_ISSUE_SEVERITY[code] };
|
|
@@ -3178,6 +3419,283 @@ function checkOptionMedia(media, index, ordinal) {
|
|
|
3178
3419
|
return checkMedia(media, path, MultipleChoiceOptionMediaSchema);
|
|
3179
3420
|
}
|
|
3180
3421
|
|
|
3422
|
+
// src/authoring/read-aloud.ts
|
|
3423
|
+
var readAloudAuthoring = {
|
|
3424
|
+
createDraft: ({ newId }) => ({
|
|
3425
|
+
schemaVersion: "1.0",
|
|
3426
|
+
type: "read-aloud",
|
|
3427
|
+
id: newId(),
|
|
3428
|
+
title: "",
|
|
3429
|
+
referenceText: "",
|
|
3430
|
+
locale: "",
|
|
3431
|
+
recording: { maxSeconds: 0 },
|
|
3432
|
+
scoring: { dimensions: [] }
|
|
3433
|
+
}),
|
|
3434
|
+
checkDraft: checkReadAloudDraft
|
|
3435
|
+
};
|
|
3436
|
+
function checkReadAloudDraft(draft) {
|
|
3437
|
+
const issues = checkIdentity(draft, "read-aloud");
|
|
3438
|
+
issues.push(...checkReferenceText(draft.referenceText));
|
|
3439
|
+
issues.push(...checkLocale(draft.locale));
|
|
3440
|
+
issues.push(...checkRecording2(draft.recording));
|
|
3441
|
+
issues.push(...checkDimensions(draft.scoring));
|
|
3442
|
+
issues.push(...checkModelRecording(draft.media));
|
|
3443
|
+
issues.push(...checkSlowRecording2(draft));
|
|
3444
|
+
issues.push(...checkSharedOptional(draft));
|
|
3445
|
+
return issues;
|
|
3446
|
+
}
|
|
3447
|
+
function checkReferenceText(referenceText) {
|
|
3448
|
+
if (isUnwritten(referenceText)) {
|
|
3449
|
+
return [
|
|
3450
|
+
issue("ra_reference_text_required", ["referenceText"], "Write the text to be read aloud.")
|
|
3451
|
+
];
|
|
3452
|
+
}
|
|
3453
|
+
if (typeof referenceText !== "string") {
|
|
3454
|
+
return [];
|
|
3455
|
+
}
|
|
3456
|
+
const issues = [];
|
|
3457
|
+
const measured = dictationNormalizer(void 0).measure(referenceText);
|
|
3458
|
+
if (measured.tooLong) {
|
|
3459
|
+
issues.push(
|
|
3460
|
+
issue(
|
|
3461
|
+
"ra_reference_text_too_long",
|
|
3462
|
+
["referenceText"],
|
|
3463
|
+
`The text is longer than ${READ_ALOUD_MAX_REFERENCE_LENGTH} characters, before or after normalisation. A read-aloud item is a sentence or a short paragraph.`
|
|
3464
|
+
)
|
|
3465
|
+
);
|
|
3466
|
+
}
|
|
3467
|
+
if (measured.normalized === "") {
|
|
3468
|
+
issues.push(
|
|
3469
|
+
issue(
|
|
3470
|
+
"ra_reference_text_unreadable",
|
|
3471
|
+
["referenceText"],
|
|
3472
|
+
"The text has no word to read: once punctuation and spacing are ignored, nothing is left. A reading of it would be marked against no word at all."
|
|
3473
|
+
)
|
|
3474
|
+
);
|
|
3475
|
+
}
|
|
3476
|
+
if (containsUnspacedScript(referenceText)) {
|
|
3477
|
+
issues.push(
|
|
3478
|
+
issue(
|
|
3479
|
+
"ra_reference_text_unspaced_script",
|
|
3480
|
+
["referenceText"],
|
|
3481
|
+
"The text is written in a script that does not separate its words with spaces. Each word is marked on its own, and a run of Han, kana, Thai, Lao, Khmer or Myanmar letters would be marked as one word."
|
|
3482
|
+
)
|
|
3483
|
+
);
|
|
3484
|
+
}
|
|
3485
|
+
return issues;
|
|
3486
|
+
}
|
|
3487
|
+
function checkLocale(locale) {
|
|
3488
|
+
if (isUnwritten(locale)) {
|
|
3489
|
+
return [
|
|
3490
|
+
issue(
|
|
3491
|
+
"ra_locale_required",
|
|
3492
|
+
["locale"],
|
|
3493
|
+
'Choose the language the learner reads in, with its region \u2014 "en-US", not "en".'
|
|
3494
|
+
)
|
|
3495
|
+
];
|
|
3496
|
+
}
|
|
3497
|
+
if (typeof locale !== "string" || CANONICAL_LOCALE_RE.test(locale)) {
|
|
3498
|
+
return [];
|
|
3499
|
+
}
|
|
3500
|
+
return [
|
|
3501
|
+
issue(
|
|
3502
|
+
"ra_locale_invalid",
|
|
3503
|
+
["locale"],
|
|
3504
|
+
`The language must be a BCP 47 tag in canonical form, with a region: "en-US", "es-419", "zh-Hant-TW". Pronunciation is assessed against one locale's speech.`
|
|
3505
|
+
)
|
|
3506
|
+
];
|
|
3507
|
+
}
|
|
3508
|
+
function checkRecording2(recording) {
|
|
3509
|
+
if (isUnset(recording)) {
|
|
3510
|
+
return [maxSecondsRequired()];
|
|
3511
|
+
}
|
|
3512
|
+
if (!isRecord(recording)) {
|
|
3513
|
+
return [];
|
|
3514
|
+
}
|
|
3515
|
+
const issues = [];
|
|
3516
|
+
const max = recording.maxSeconds;
|
|
3517
|
+
if (isUnset(max) || max === 0) {
|
|
3518
|
+
issues.push(maxSecondsRequired());
|
|
3519
|
+
} else if (typeof max === "number" && !(Number.isFinite(max) && max > 0 && max <= READ_ALOUD_MAX_SECONDS)) {
|
|
3520
|
+
issues.push(
|
|
3521
|
+
issue(
|
|
3522
|
+
"ra_max_seconds_out_of_range",
|
|
3523
|
+
["recording", "maxSeconds"],
|
|
3524
|
+
`A take is at most ${READ_ALOUD_MAX_SECONDS} seconds long.`
|
|
3525
|
+
)
|
|
3526
|
+
);
|
|
3527
|
+
}
|
|
3528
|
+
const min = recording.minSeconds;
|
|
3529
|
+
if (typeof min === "number" && !(Number.isFinite(min) && min >= 0)) {
|
|
3530
|
+
issues.push(minSecondsOutOfRange("The shortest take is a number of seconds, 0 or more."));
|
|
3531
|
+
} else if (typeof min === "number" && typeof max === "number" && max > 0 && min >= max) {
|
|
3532
|
+
issues.push(minSecondsOutOfRange("The shortest take must be shorter than the longest."));
|
|
3533
|
+
}
|
|
3534
|
+
const takes = recording.maxTakes;
|
|
3535
|
+
if (typeof takes === "number" && !(isWholeNumber(takes) && takes >= 1 && takes <= READ_ALOUD_MAX_TAKES)) {
|
|
3536
|
+
issues.push(
|
|
3537
|
+
issue(
|
|
3538
|
+
"ra_max_takes_out_of_range",
|
|
3539
|
+
["recording", "maxTakes"],
|
|
3540
|
+
`How many takes a learner may record is a whole number from 1 to ${READ_ALOUD_MAX_TAKES}.`
|
|
3541
|
+
)
|
|
3542
|
+
);
|
|
3543
|
+
}
|
|
3544
|
+
return issues;
|
|
3545
|
+
}
|
|
3546
|
+
function maxSecondsRequired() {
|
|
3547
|
+
return issue(
|
|
3548
|
+
"ra_max_seconds_required",
|
|
3549
|
+
["recording", "maxSeconds"],
|
|
3550
|
+
"Set how long a take may be, in seconds."
|
|
3551
|
+
);
|
|
3552
|
+
}
|
|
3553
|
+
function minSecondsOutOfRange(message) {
|
|
3554
|
+
return issue("ra_min_seconds_out_of_range", ["recording", "minSeconds"], message);
|
|
3555
|
+
}
|
|
3556
|
+
var DIMENSION_NAMES = READ_ALOUD_DIMENSIONS;
|
|
3557
|
+
function checkDimensions(scoring) {
|
|
3558
|
+
if (isUnset(scoring)) {
|
|
3559
|
+
return [dimensionsRequired()];
|
|
3560
|
+
}
|
|
3561
|
+
if (!isRecord(scoring)) {
|
|
3562
|
+
return [];
|
|
3563
|
+
}
|
|
3564
|
+
const dimensions = scoring.dimensions;
|
|
3565
|
+
if (isUnset(dimensions)) {
|
|
3566
|
+
return [dimensionsRequired()];
|
|
3567
|
+
}
|
|
3568
|
+
if (!Array.isArray(dimensions)) {
|
|
3569
|
+
return [];
|
|
3570
|
+
}
|
|
3571
|
+
if (dimensions.length === 0) {
|
|
3572
|
+
return [dimensionsRequired()];
|
|
3573
|
+
}
|
|
3574
|
+
const issues = [];
|
|
3575
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3576
|
+
let everyWeightUsable = true;
|
|
3577
|
+
let totalWeight = 0;
|
|
3578
|
+
for (const [index, dimension] of dimensions.entries()) {
|
|
3579
|
+
if (!isRecord(dimension)) {
|
|
3580
|
+
everyWeightUsable = false;
|
|
3581
|
+
continue;
|
|
3582
|
+
}
|
|
3583
|
+
const path = ["scoring", "dimensions", index];
|
|
3584
|
+
const name = dimension.name;
|
|
3585
|
+
if (!DIMENSION_NAMES.includes(name)) {
|
|
3586
|
+
issues.push(
|
|
3587
|
+
issue(
|
|
3588
|
+
"ra_dimension_name_invalid",
|
|
3589
|
+
[...path, "name"],
|
|
3590
|
+
`Choose what dimension ${index + 1} measures: ${READ_ALOUD_DIMENSIONS.join(", ")}.`
|
|
3591
|
+
)
|
|
3592
|
+
);
|
|
3593
|
+
} else if (seen.has(name)) {
|
|
3594
|
+
issues.push(
|
|
3595
|
+
issue(
|
|
3596
|
+
"ra_dimension_duplicate",
|
|
3597
|
+
[...path, "name"],
|
|
3598
|
+
`"${String(name)}" is already weighed. Remove this one, or measure something else.`
|
|
3599
|
+
)
|
|
3600
|
+
);
|
|
3601
|
+
} else {
|
|
3602
|
+
seen.add(name);
|
|
3603
|
+
}
|
|
3604
|
+
const weight = dimension.weight;
|
|
3605
|
+
if (typeof weight === "number" && Number.isFinite(weight) && weight >= 0 && weight <= READ_ALOUD_MAX_DIMENSION_WEIGHT) {
|
|
3606
|
+
totalWeight += weight;
|
|
3607
|
+
} else {
|
|
3608
|
+
everyWeightUsable = false;
|
|
3609
|
+
issues.push(
|
|
3610
|
+
issue(
|
|
3611
|
+
"ra_dimension_weight_invalid",
|
|
3612
|
+
[...path, "weight"],
|
|
3613
|
+
`Give dimension ${index + 1} a weight: a number from 0 to ${READ_ALOUD_MAX_DIMENSION_WEIGHT}.`
|
|
3614
|
+
)
|
|
3615
|
+
);
|
|
3616
|
+
}
|
|
3617
|
+
}
|
|
3618
|
+
if (everyWeightUsable && totalWeight === 0) {
|
|
3619
|
+
issues.push(
|
|
3620
|
+
issue(
|
|
3621
|
+
"ra_dimension_weights_zero",
|
|
3622
|
+
["scoring", "dimensions"],
|
|
3623
|
+
"Give at least one dimension a weight above 0. With every weight at 0 there is no weighted total, and every take would be unscorable."
|
|
3624
|
+
)
|
|
3625
|
+
);
|
|
3626
|
+
}
|
|
3627
|
+
return issues;
|
|
3628
|
+
}
|
|
3629
|
+
function dimensionsRequired() {
|
|
3630
|
+
return issue(
|
|
3631
|
+
"ra_dimensions_required",
|
|
3632
|
+
["scoring", "dimensions"],
|
|
3633
|
+
"Choose what the grade measures: at least one of accuracy, fluency, completeness or prosody, with a weight."
|
|
3634
|
+
);
|
|
3635
|
+
}
|
|
3636
|
+
function checkModelRecording(media) {
|
|
3637
|
+
if (!isRecord(media)) {
|
|
3638
|
+
return [];
|
|
3639
|
+
}
|
|
3640
|
+
const kind = media.type;
|
|
3641
|
+
return isUnwritten(kind) || kind === "audio" ? [] : [
|
|
3642
|
+
issue(
|
|
3643
|
+
"ra_media_kind",
|
|
3644
|
+
["media", "type"],
|
|
3645
|
+
"A read-aloud model is read aloud: its recording must be audio."
|
|
3646
|
+
)
|
|
3647
|
+
];
|
|
3648
|
+
}
|
|
3649
|
+
function checkSlowRecording2(draft) {
|
|
3650
|
+
const slow = draft.slowMedia;
|
|
3651
|
+
if (!isRecord(slow)) {
|
|
3652
|
+
return [];
|
|
3653
|
+
}
|
|
3654
|
+
const kind = slow.type;
|
|
3655
|
+
const wrongKind = !isUnwritten(kind) && kind !== "audio";
|
|
3656
|
+
const issues = wrongKind ? [issue("media_invalid", ["slowMedia", "type"], "The slow model recording must be audio.")] : [];
|
|
3657
|
+
issues.push(
|
|
3658
|
+
...checkMedia(
|
|
3659
|
+
wrongKind ? { ...slow, type: "audio" } : slow,
|
|
3660
|
+
["slowMedia"],
|
|
3661
|
+
ReadAloudSlowMediaSchema
|
|
3662
|
+
)
|
|
3663
|
+
);
|
|
3664
|
+
const media = draft.media;
|
|
3665
|
+
if (isUnset(media)) {
|
|
3666
|
+
issues.push(
|
|
3667
|
+
issue(
|
|
3668
|
+
"ra_slow_media_without_media",
|
|
3669
|
+
["media"],
|
|
3670
|
+
"A slow model recording accompanies a recording. Add the recording first."
|
|
3671
|
+
)
|
|
3672
|
+
);
|
|
3673
|
+
return issues;
|
|
3674
|
+
}
|
|
3675
|
+
if (!isRecord(media)) {
|
|
3676
|
+
return issues;
|
|
3677
|
+
}
|
|
3678
|
+
if (isRecord(media.playback) && media.playback.maxPlays !== void 0) {
|
|
3679
|
+
issues.push(
|
|
3680
|
+
issue(
|
|
3681
|
+
"ra_slow_media_beside_play_limit",
|
|
3682
|
+
["slowMedia"],
|
|
3683
|
+
"A play budget on the recording cannot coexist with a slow recording that has none. Remove the slow recording, or remove the play limit."
|
|
3684
|
+
)
|
|
3685
|
+
);
|
|
3686
|
+
}
|
|
3687
|
+
if (typeof slow.url === "string" && slow.url !== "" && slow.url === media.url) {
|
|
3688
|
+
issues.push(
|
|
3689
|
+
issue(
|
|
3690
|
+
"ra_slow_media_same_recording",
|
|
3691
|
+
["slowMedia", "url"],
|
|
3692
|
+
"The slow model recording is the same file as the recording. Point it at the slower reading."
|
|
3693
|
+
)
|
|
3694
|
+
);
|
|
3695
|
+
}
|
|
3696
|
+
return issues;
|
|
3697
|
+
}
|
|
3698
|
+
|
|
3181
3699
|
// src/authoring/written-response.ts
|
|
3182
3700
|
var writtenResponseAuthoring = {
|
|
3183
3701
|
createDraft: ({ newId }) => ({
|
|
@@ -3321,7 +3839,7 @@ function checkCriteria(criteria) {
|
|
|
3321
3839
|
|
|
3322
3840
|
// src/scoring/activity-scorers/dictation.ts
|
|
3323
3841
|
function scoreDictation(data, response) {
|
|
3324
|
-
const alignment = alignDictation(data, typeof _optionalChain([response, 'optionalAccess',
|
|
3842
|
+
const alignment = alignDictation(data, typeof _optionalChain([response, 'optionalAccess', _75 => _75.text]) === "string" ? response.text : "");
|
|
3325
3843
|
const details = [];
|
|
3326
3844
|
for (const word of alignment.words) {
|
|
3327
3845
|
if (word.status === "extra") {
|
|
@@ -3390,7 +3908,7 @@ function choicesFor(data, gap) {
|
|
|
3390
3908
|
if (gap.choices !== void 0) {
|
|
3391
3909
|
return gap.choices;
|
|
3392
3910
|
}
|
|
3393
|
-
return _nullishCoalesce(_optionalChain([data, 'access',
|
|
3911
|
+
return _nullishCoalesce(_optionalChain([data, 'access', _76 => _76.banks, 'optionalAccess', _77 => _77.find, 'call', _78 => _78((bank) => bank.id === gap.bankId), 'optionalAccess', _79 => _79.choices]), () => ( []));
|
|
3394
3912
|
}
|
|
3395
3913
|
function scoreGapSelect(data, response) {
|
|
3396
3914
|
const details = [];
|
|
@@ -3426,7 +3944,7 @@ function scoreMultipleChoice(data, response) {
|
|
|
3426
3944
|
let scoreValue;
|
|
3427
3945
|
if (data.scoringStrategy === "all-or-nothing") {
|
|
3428
3946
|
if (data.mode === "single") {
|
|
3429
|
-
scoreValue = response.selectedOptionIds.length === 1 && _optionalChain([optionById, 'access',
|
|
3947
|
+
scoreValue = response.selectedOptionIds.length === 1 && _optionalChain([optionById, 'access', _80 => _80.get, 'call', _81 => _81(response.selectedOptionIds[0]), 'optionalAccess', _82 => _82.isCorrect]) === true ? 1 : 0;
|
|
3430
3948
|
} else {
|
|
3431
3949
|
const correctIds = data.options.filter((o) => o.isCorrect).map((o) => o.id);
|
|
3432
3950
|
const allCorrectSelected = correctIds.every((id) => selected.has(id));
|
|
@@ -3437,7 +3955,7 @@ function scoreMultipleChoice(data, response) {
|
|
|
3437
3955
|
let incorrectSelected = 0;
|
|
3438
3956
|
for (const id of selected) {
|
|
3439
3957
|
const option = optionById.get(id);
|
|
3440
|
-
if (_optionalChain([option, 'optionalAccess',
|
|
3958
|
+
if (_optionalChain([option, 'optionalAccess', _83 => _83.isCorrect])) {
|
|
3441
3959
|
correctSelected += 1;
|
|
3442
3960
|
} else {
|
|
3443
3961
|
incorrectSelected += 1;
|
|
@@ -3608,7 +4126,7 @@ var multipleChoiceType = defineActivityType({
|
|
|
3608
4126
|
// exact optionals. Structurally identical at runtime — cast is type-level only.
|
|
3609
4127
|
schema: MultipleChoiceDataSchema,
|
|
3610
4128
|
scoring: { kind: "sync", score: scoreMultipleChoice },
|
|
3611
|
-
isAnswered: (response) => (_nullishCoalesce(_optionalChain([response, 'optionalAccess',
|
|
4129
|
+
isAnswered: (response) => (_nullishCoalesce(_optionalChain([response, 'optionalAccess', _84 => _84.selectedOptionIds, 'access', _85 => _85.length]), () => ( 0))) > 0,
|
|
3612
4130
|
fieldPolicy: MULTIPLE_CHOICE_FIELD_POLICY,
|
|
3613
4131
|
redactedSchema: RedactedMultipleChoiceDataSchema,
|
|
3614
4132
|
interop: {
|
|
@@ -3625,7 +4143,7 @@ var fillInTheBlanksType = defineActivityType({
|
|
|
3625
4143
|
type: "fill-in-the-blanks",
|
|
3626
4144
|
schema: FillInTheBlanksDataSchema,
|
|
3627
4145
|
scoring: { kind: "sync", score: scoreFillInTheBlanks },
|
|
3628
|
-
isAnswered: (response) => Object.values(_nullishCoalesce(_optionalChain([response, 'optionalAccess',
|
|
4146
|
+
isAnswered: (response) => Object.values(_nullishCoalesce(_optionalChain([response, 'optionalAccess', _86 => _86.answers]), () => ( {}))).some((answer) => answer.trim().length > 0),
|
|
3629
4147
|
fieldPolicy: FILL_IN_THE_BLANKS_FIELD_POLICY,
|
|
3630
4148
|
redactedSchema: RedactedFillInTheBlanksDataSchema,
|
|
3631
4149
|
interop: {
|
|
@@ -3648,14 +4166,14 @@ var writtenResponseType = defineActivityType({
|
|
|
3648
4166
|
kind: "deferred",
|
|
3649
4167
|
reason: "requires_async_grading",
|
|
3650
4168
|
partial: (data, response) => {
|
|
3651
|
-
const wordCount = countWords(_nullishCoalesce(_optionalChain([response, 'optionalAccess',
|
|
4169
|
+
const wordCount = countWords(_nullishCoalesce(_optionalChain([response, 'optionalAccess', _87 => _87.text]), () => ( "")));
|
|
3652
4170
|
return {
|
|
3653
4171
|
withinWordBounds: response !== void 0 && wordCount >= data.minWords && wordCount <= data.maxWords,
|
|
3654
4172
|
wordCount
|
|
3655
4173
|
};
|
|
3656
4174
|
}
|
|
3657
4175
|
},
|
|
3658
|
-
isAnswered: (response) => (_nullishCoalesce(_optionalChain([response, 'optionalAccess',
|
|
4176
|
+
isAnswered: (response) => (_nullishCoalesce(_optionalChain([response, 'optionalAccess', _88 => _88.text, 'access', _89 => _89.trim, 'call', _90 => _90(), 'access', _91 => _91.length]), () => ( 0))) > 0,
|
|
3659
4177
|
fieldPolicy: WRITTEN_RESPONSE_FIELD_POLICY,
|
|
3660
4178
|
redactedSchema: RedactedWrittenResponseDataSchema,
|
|
3661
4179
|
interop: {
|
|
@@ -3670,7 +4188,7 @@ var gapSelectType = defineActivityType({
|
|
|
3670
4188
|
type: "gap-select",
|
|
3671
4189
|
schema: GapSelectDataSchema,
|
|
3672
4190
|
scoring: { kind: "sync", score: scoreGapSelect },
|
|
3673
|
-
isAnswered: (response) => Object.values(_nullishCoalesce(_optionalChain([response, 'optionalAccess',
|
|
4191
|
+
isAnswered: (response) => Object.values(_nullishCoalesce(_optionalChain([response, 'optionalAccess', _92 => _92.selections]), () => ( {}))).some((choiceId) => choiceId !== ""),
|
|
3674
4192
|
fieldPolicy: GAP_SELECT_FIELD_POLICY,
|
|
3675
4193
|
redactedSchema: RedactedGapSelectDataSchema,
|
|
3676
4194
|
interop: {
|
|
@@ -3701,7 +4219,7 @@ var dictationType = defineActivityType({
|
|
|
3701
4219
|
// cut where the scorer cuts, so text past the cap never counts as an answer.
|
|
3702
4220
|
isAnswered: (response) => normalizeDictationText(
|
|
3703
4221
|
truncateCodePoints(
|
|
3704
|
-
typeof _optionalChain([response, 'optionalAccess',
|
|
4222
|
+
typeof _optionalChain([response, 'optionalAccess', _93 => _93.text]) === "string" ? response.text : "",
|
|
3705
4223
|
DICTATION_MAX_TEXT_LENGTH
|
|
3706
4224
|
)
|
|
3707
4225
|
) !== "",
|
|
@@ -3717,11 +4235,61 @@ var dictationType = defineActivityType({
|
|
|
3717
4235
|
interactions: ["text-changed", "hint-requested", "submitted"],
|
|
3718
4236
|
authoring: dictationAuthoring
|
|
3719
4237
|
});
|
|
4238
|
+
var READ_ALOUD_FIELD_POLICY = {
|
|
4239
|
+
...SHARED_PUBLIC_FIELDS,
|
|
4240
|
+
instructions: "public",
|
|
4241
|
+
referenceText: "public",
|
|
4242
|
+
recording: { maxSeconds: "public", minSeconds: "public", maxTakes: "public" },
|
|
4243
|
+
slowMedia: { type: "public", url: "public", alt: "public" },
|
|
4244
|
+
scoring: { dimensions: { name: "public", weight: "public" } },
|
|
4245
|
+
feedback: FEEDBACK_FIELD_POLICY
|
|
4246
|
+
};
|
|
4247
|
+
function hasRecording(response) {
|
|
4248
|
+
const recording = _optionalChain([response, 'optionalAccess', _94 => _94.recording]);
|
|
4249
|
+
return typeof recording === "object" && recording !== null && typeof recording.key === "string" && recording.key !== "";
|
|
4250
|
+
}
|
|
4251
|
+
var readAloudType = defineActivityType({
|
|
4252
|
+
type: "read-aloud",
|
|
4253
|
+
schema: ReadAloudDataSchema,
|
|
4254
|
+
scoring: {
|
|
4255
|
+
kind: "deferred",
|
|
4256
|
+
reason: "requires_async_grading",
|
|
4257
|
+
partial: (_data, response) => ({ hasRecording: hasRecording(response) })
|
|
4258
|
+
},
|
|
4259
|
+
isAnswered: (response) => hasRecording(response),
|
|
4260
|
+
fieldPolicy: READ_ALOUD_FIELD_POLICY,
|
|
4261
|
+
redactedSchema: RedactedReadAloudDataSchema,
|
|
4262
|
+
interop: {
|
|
4263
|
+
xapiActivityTypeIri: "http://adlnet.gov/expapi/activities/cmi.interaction",
|
|
4264
|
+
// `other`, not `performance`: xAPI's performance interaction describes a set
|
|
4265
|
+
// of steps with their own responses, and a reading has one. There is no
|
|
4266
|
+
// pattern to publish either — the "correct response" is a pronunciation, not
|
|
4267
|
+
// a string a statement can carry.
|
|
4268
|
+
xapiInteractionType: "other",
|
|
4269
|
+
correctResponsesPattern: () => []
|
|
4270
|
+
},
|
|
4271
|
+
interactions: ["recording-started", "recording-stopped", "recording-uploaded", "submitted"],
|
|
4272
|
+
authoring: readAloudAuthoring
|
|
4273
|
+
});
|
|
3720
4274
|
registerActivityType(multipleChoiceType);
|
|
3721
4275
|
registerActivityType(fillInTheBlanksType);
|
|
3722
4276
|
registerActivityType(writtenResponseType);
|
|
3723
4277
|
registerActivityType(gapSelectType);
|
|
3724
4278
|
registerActivityType(dictationType);
|
|
4279
|
+
registerActivityType(readAloudType);
|
|
4280
|
+
|
|
4281
|
+
|
|
4282
|
+
|
|
4283
|
+
|
|
4284
|
+
|
|
4285
|
+
|
|
4286
|
+
|
|
4287
|
+
|
|
4288
|
+
|
|
4289
|
+
|
|
4290
|
+
|
|
4291
|
+
|
|
4292
|
+
|
|
3725
4293
|
|
|
3726
4294
|
|
|
3727
4295
|
|
|
@@ -3799,5 +4367,5 @@ registerActivityType(dictationType);
|
|
|
3799
4367
|
|
|
3800
4368
|
|
|
3801
4369
|
|
|
3802
|
-
exports.ActivitySchemaError = ActivitySchemaError; exports.UnknownActivityTypeError = UnknownActivityTypeError; exports.RedactedScoringError = RedactedScoringError; exports.DeferredScoringError = DeferredScoringError; exports.withValidationScope = withValidationScope; exports.DICTATION_MAX_TRANSCRIPT_LENGTH = DICTATION_MAX_TRANSCRIPT_LENGTH; exports.DICTATION_MAX_TEXT_LENGTH = DICTATION_MAX_TEXT_LENGTH; exports.DICTATION_MAX_EQUIVALENCE_LENGTH = DICTATION_MAX_EQUIVALENCE_LENGTH; exports.DICTATION_MAX_EQUIVALENCES = DICTATION_MAX_EQUIVALENCES; exports.DICTATION_MAX_ACCEPTED_TRANSCRIPTS = DICTATION_MAX_ACCEPTED_TRANSCRIPTS; exports.FeedbackSchema = FeedbackSchema; exports.MediaUrlSchema = MediaUrlSchema; exports.NativeControlHintSchema = NativeControlHintSchema; exports.MediaPlaybackSchema = MediaPlaybackSchema; exports.MediaSchema = MediaSchema; exports.RedactedMediaSchema = RedactedMediaSchema; exports.DictationSlowMediaSchema = DictationSlowMediaSchema; exports.DictationEquivalenceSchema = DictationEquivalenceSchema; exports.DictationToleranceSchema = DictationToleranceSchema; exports.DictationDataSchema = DictationDataSchema; exports.groupCaptionsRevealDictation = groupCaptionsRevealDictation; exports.GROUP_CAPTIONS_REVEAL_DICTATION = GROUP_CAPTIONS_REVEAL_DICTATION; exports.DRAFT_ISSUE_SEVERITY = DRAFT_ISSUE_SEVERITY; exports.issue = issue; exports.isRecord = isRecord; exports.refusesEmpty = refusesEmpty; exports.isUnset = isUnset; exports.isUnwritten = isUnwritten; exports.isMissingId = isMissingId; exports.checkMedia = checkMedia; exports.covers = covers; exports.pathKey = pathKey; exports.coveredPathsOf = coveredPathsOf; exports.TextMatchPolicySchema = TextMatchPolicySchema; exports.BlankConfigSchema = BlankConfigSchema; exports.FillInTheBlanksDataSchema = FillInTheBlanksDataSchema; exports.MultipleChoiceOptionMediaSchema = MultipleChoiceOptionMediaSchema; exports.MultipleChoiceOptionSchema = MultipleChoiceOptionSchema; exports.MultipleChoiceDataSchema = MultipleChoiceDataSchema; exports.countWords = countWords; exports.GapSelectChoiceSchema = GapSelectChoiceSchema; exports.GapSelectBankSchema = GapSelectBankSchema; exports.GapSelectGapSchema = GapSelectGapSchema; exports.GapSelectDataSchema = GapSelectDataSchema; exports.WrittenResponseRubricCriterionSchema = WrittenResponseRubricCriterionSchema; exports.WrittenResponseRubricSchema = WrittenResponseRubricSchema; exports.WrittenResponseDataSchema = WrittenResponseDataSchema; exports.RedactedMultipleChoiceOptionMediaSchema = RedactedMultipleChoiceOptionMediaSchema; exports.RedactedMultipleChoiceOptionSchema = RedactedMultipleChoiceOptionSchema; exports.RedactedMultipleChoiceDataSchema = RedactedMultipleChoiceDataSchema; exports.RedactedBlankConfigSchema = RedactedBlankConfigSchema; exports.RedactedFillInTheBlanksDataSchema = RedactedFillInTheBlanksDataSchema; exports.RedactedGapSelectChoiceSchema = RedactedGapSelectChoiceSchema; exports.RedactedGapSelectBankSchema = RedactedGapSelectBankSchema; exports.RedactedGapSelectGapSchema = RedactedGapSelectGapSchema; exports.RedactedGapSelectDataSchema = RedactedGapSelectDataSchema; exports.RedactedWrittenResponseDataSchema = RedactedWrittenResponseDataSchema; exports.RedactedDictationSlowMediaSchema = RedactedDictationSlowMediaSchema; exports.RedactedDictationDataSchema = RedactedDictationDataSchema; exports.dictationReferenceWords = dictationReferenceWords; exports.alignDictation = alignDictation; exports.STEP = STEP; exports.alignSequences = alignSequences; exports.levenshteinDistance = levenshteinDistance; exports.matchText = matchText; exports.defineActivityType = defineActivityType; exports.registerActivityType = registerActivityType; exports.getActivityTypeDescriptor = getActivityTypeDescriptor; exports.registeredActivityTypes = registeredActivityTypes; exports.MEDIA_FIELD_POLICY = MEDIA_FIELD_POLICY; exports.multipleChoiceType = multipleChoiceType; exports.fillInTheBlanksType = fillInTheBlanksType; exports.writtenResponseType = writtenResponseType; exports.gapSelectType = gapSelectType; exports.dictationType = dictationType;
|
|
3803
|
-
//# sourceMappingURL=chunk-
|
|
4370
|
+
exports.ActivitySchemaError = ActivitySchemaError; exports.UnknownActivityTypeError = UnknownActivityTypeError; exports.RedactedScoringError = RedactedScoringError; exports.DeferredScoringError = DeferredScoringError; exports.withValidationScope = withValidationScope; exports.DICTATION_MAX_TRANSCRIPT_LENGTH = DICTATION_MAX_TRANSCRIPT_LENGTH; exports.DICTATION_MAX_TEXT_LENGTH = DICTATION_MAX_TEXT_LENGTH; exports.DICTATION_MAX_EQUIVALENCE_LENGTH = DICTATION_MAX_EQUIVALENCE_LENGTH; exports.DICTATION_MAX_EQUIVALENCES = DICTATION_MAX_EQUIVALENCES; exports.DICTATION_MAX_ACCEPTED_TRANSCRIPTS = DICTATION_MAX_ACCEPTED_TRANSCRIPTS; exports.codePointLength = codePointLength; exports.normalizeDictationText = normalizeDictationText; exports.FeedbackSchema = FeedbackSchema; exports.MediaUrlSchema = MediaUrlSchema; exports.NativeControlHintSchema = NativeControlHintSchema; exports.MediaPlaybackSchema = MediaPlaybackSchema; exports.MediaSchema = MediaSchema; exports.RedactedMediaSchema = RedactedMediaSchema; exports.DictationSlowMediaSchema = DictationSlowMediaSchema; exports.DictationEquivalenceSchema = DictationEquivalenceSchema; exports.DictationToleranceSchema = DictationToleranceSchema; exports.DictationDataSchema = DictationDataSchema; exports.groupCaptionsRevealDictation = groupCaptionsRevealDictation; exports.GROUP_CAPTIONS_REVEAL_DICTATION = GROUP_CAPTIONS_REVEAL_DICTATION; exports.DRAFT_ISSUE_SEVERITY = DRAFT_ISSUE_SEVERITY; exports.issue = issue; exports.isRecord = isRecord; exports.refusesEmpty = refusesEmpty; exports.isUnset = isUnset; exports.isUnwritten = isUnwritten; exports.isMissingId = isMissingId; exports.checkMedia = checkMedia; exports.covers = covers; exports.pathKey = pathKey; exports.coveredPathsOf = coveredPathsOf; exports.TextMatchPolicySchema = TextMatchPolicySchema; exports.BlankConfigSchema = BlankConfigSchema; exports.FillInTheBlanksDataSchema = FillInTheBlanksDataSchema; exports.MultipleChoiceOptionMediaSchema = MultipleChoiceOptionMediaSchema; exports.MultipleChoiceOptionSchema = MultipleChoiceOptionSchema; exports.MultipleChoiceDataSchema = MultipleChoiceDataSchema; exports.READ_ALOUD_MAX_REFERENCE_LENGTH = READ_ALOUD_MAX_REFERENCE_LENGTH; exports.READ_ALOUD_MAX_SECONDS = READ_ALOUD_MAX_SECONDS; exports.READ_ALOUD_MAX_TAKES = READ_ALOUD_MAX_TAKES; exports.READ_ALOUD_MAX_DIMENSION_WEIGHT = READ_ALOUD_MAX_DIMENSION_WEIGHT; exports.SPEECH_ASSESSMENT_MAX_WORDS = SPEECH_ASSESSMENT_MAX_WORDS; exports.SPEECH_ASSESSMENT_MAX_TEXT_LENGTH = SPEECH_ASSESSMENT_MAX_TEXT_LENGTH; exports.CANONICAL_LOCALE_RE = CANONICAL_LOCALE_RE; exports.ReadAloudSlowMediaSchema = ReadAloudSlowMediaSchema; exports.ReadAloudDataSchema = ReadAloudDataSchema; exports.countWords = countWords; exports.GapSelectChoiceSchema = GapSelectChoiceSchema; exports.GapSelectBankSchema = GapSelectBankSchema; exports.GapSelectGapSchema = GapSelectGapSchema; exports.GapSelectDataSchema = GapSelectDataSchema; exports.WrittenResponseRubricCriterionSchema = WrittenResponseRubricCriterionSchema; exports.WrittenResponseRubricSchema = WrittenResponseRubricSchema; exports.WrittenResponseDataSchema = WrittenResponseDataSchema; exports.RedactedMultipleChoiceOptionMediaSchema = RedactedMultipleChoiceOptionMediaSchema; exports.RedactedMultipleChoiceOptionSchema = RedactedMultipleChoiceOptionSchema; exports.RedactedMultipleChoiceDataSchema = RedactedMultipleChoiceDataSchema; exports.RedactedBlankConfigSchema = RedactedBlankConfigSchema; exports.RedactedFillInTheBlanksDataSchema = RedactedFillInTheBlanksDataSchema; exports.RedactedGapSelectChoiceSchema = RedactedGapSelectChoiceSchema; exports.RedactedGapSelectBankSchema = RedactedGapSelectBankSchema; exports.RedactedGapSelectGapSchema = RedactedGapSelectGapSchema; exports.RedactedGapSelectDataSchema = RedactedGapSelectDataSchema; exports.RedactedWrittenResponseDataSchema = RedactedWrittenResponseDataSchema; exports.RedactedDictationSlowMediaSchema = RedactedDictationSlowMediaSchema; exports.RedactedDictationDataSchema = RedactedDictationDataSchema; exports.RedactedReadAloudDataSchema = RedactedReadAloudDataSchema; exports.dictationReferenceWords = dictationReferenceWords; exports.alignDictation = alignDictation; exports.STEP = STEP; exports.alignSequences = alignSequences; exports.levenshteinDistance = levenshteinDistance; exports.matchText = matchText; exports.defineActivityType = defineActivityType; exports.registerActivityType = registerActivityType; exports.getActivityTypeDescriptor = getActivityTypeDescriptor; exports.registeredActivityTypes = registeredActivityTypes; exports.MEDIA_FIELD_POLICY = MEDIA_FIELD_POLICY; exports.multipleChoiceType = multipleChoiceType; exports.fillInTheBlanksType = fillInTheBlanksType; exports.writtenResponseType = writtenResponseType; exports.gapSelectType = gapSelectType; exports.dictationType = dictationType; exports.readAloudType = readAloudType;
|
|
4371
|
+
//# sourceMappingURL=chunk-VCXIPLEW.cjs.map
|