@intellectif/lk-core 1.10.0 → 1.10.1
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 +16 -0
- package/dist/ai-check.cjs +2 -2
- package/dist/ai-check.js +2 -2
- package/dist/{ai-writing-DLvzBiZN.js → ai-writing-BaaiuU5t.js} +2 -2
- package/dist/{ai-writing-DLvzBiZN.js.map → ai-writing-BaaiuU5t.js.map} +1 -1
- package/dist/{ai-writing-B1pKVkG7.cjs → ai-writing-_wciTWaI.cjs} +2 -2
- package/dist/{ai-writing-B1pKVkG7.cjs.map → ai-writing-_wciTWaI.cjs.map} +1 -1
- package/dist/{index-DLsUnGHt.d.cts → index-BBmID0a6.d.cts} +24 -2
- package/dist/index-BBmID0a6.d.cts.map +1 -0
- package/dist/{index-CxkqS62X.d.ts → index-DGmcCid6.d.ts} +24 -2
- package/dist/index-DGmcCid6.d.ts.map +1 -0
- package/dist/index.cjs +4 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/{scoring-Db1CZeAn.cjs → scoring-Bmfu8RS5.cjs} +48 -16
- package/dist/scoring-Bmfu8RS5.cjs.map +1 -0
- package/dist/{scoring-BGKdff2i.js → scoring-hMsEMhCU.js} +48 -16
- package/dist/scoring-hMsEMhCU.js.map +1 -0
- package/dist/scoring.cjs +1 -1
- package/dist/scoring.d.cts +1 -1
- package/dist/scoring.d.ts +1 -1
- package/dist/scoring.js +1 -1
- package/package.json +1 -1
- package/dist/index-CxkqS62X.d.ts.map +0 -1
- package/dist/index-DLsUnGHt.d.cts.map +0 -1
- package/dist/scoring-BGKdff2i.js.map +0 -1
- package/dist/scoring-Db1CZeAn.cjs.map +0 -1
|
@@ -222,16 +222,27 @@ const ROUNDING_MODES = [
|
|
|
222
222
|
const MAX_ROUNDING_DP = 15;
|
|
223
223
|
/**
|
|
224
224
|
* The rounding policy `value` holds, or `undefined` for none (`undefined` or
|
|
225
|
-
* `null`)
|
|
226
|
-
*
|
|
225
|
+
* `null`): the check for an optional `rounding`. Anything else is checked by
|
|
226
|
+
* {@link requireRoundingPolicy}.
|
|
227
227
|
*
|
|
228
|
-
* Internal
|
|
229
|
-
*
|
|
230
|
-
* does not re-export it.
|
|
228
|
+
* Internal, as is {@link requireRoundingPolicy}: `scoring/index.ts` re-exports
|
|
229
|
+
* neither.
|
|
231
230
|
*/
|
|
232
231
|
function roundingPolicyOf(value) {
|
|
233
|
-
|
|
234
|
-
|
|
232
|
+
return value === void 0 || value === null ? void 0 : requireRoundingPolicy(value);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* The rounding policy `value` holds. A malformed one would reach the rounding
|
|
236
|
+
* as `10 ** undefined` and turn a perfect score into a fail with no error, so
|
|
237
|
+
* it throws here instead; so does a missing one, `undefined` or `null`, where a
|
|
238
|
+
* policy is required.
|
|
239
|
+
*
|
|
240
|
+
* Every function that takes a policy, as an argument or a `rounding` option,
|
|
241
|
+
* checks it here or through {@link roundingPolicyOf}, so each refuses the same
|
|
242
|
+
* policies with the same message.
|
|
243
|
+
*/
|
|
244
|
+
function requireRoundingPolicy(value) {
|
|
245
|
+
const { mode, dp } = value ?? {};
|
|
235
246
|
if (!ROUNDING_MODES.includes(mode) || typeof dp !== "number" || !Number.isInteger(dp) || dp < 0 || dp > MAX_ROUNDING_DP) {
|
|
236
247
|
const describe = (field) => typeof field === "string" ? JSON.stringify(field) : typeof field === "number" || field === void 0 ? String(field) : typeof field === "object" ? "an object" : `a ${typeof field}`;
|
|
237
248
|
throw new RangeError(`Invalid rounding policy (mode ${describe(mode)}, dp ${describe(dp)}): expected { mode: 'half-up' | 'half-even' | 'floor' | 'ceil', dp: a whole number from 0 to ${MAX_ROUNDING_DP} }.`);
|
|
@@ -262,8 +273,9 @@ function scaled(value, dp) {
|
|
|
262
273
|
* Normalises `-0` to `0` without touching anything else. `-0` JSON-serialises
|
|
263
274
|
* as `0` but fails `Object.is(-0, 0)`, which surprises a strict-equality
|
|
264
275
|
* gradebook comparison. Deliberately NOT `|| 0`: that also swallowed `NaN`
|
|
265
|
-
* (
|
|
266
|
-
* turned a visible failure into a plausible-looking
|
|
276
|
+
* (reached with an absurd `dp`, where `10 ** dp` overflows to Infinity, before
|
|
277
|
+
* policies were checked) and turned a visible failure into a plausible-looking
|
|
278
|
+
* grade of zero.
|
|
267
279
|
*/
|
|
268
280
|
function noNegZero(value) {
|
|
269
281
|
return Object.is(value, -0) ? 0 : value;
|
|
@@ -274,8 +286,15 @@ function noNegZero(value) {
|
|
|
274
286
|
* Idempotent for every mode: rounding an already-rounded value returns it
|
|
275
287
|
* unchanged. That matters because a composed score is rounded once and then
|
|
276
288
|
* compared through {@link gte}, which rounds again.
|
|
289
|
+
*
|
|
290
|
+
* @throws RangeError when `policy` is not a {@link RoundingPolicy} — for a
|
|
291
|
+
* non-finite `value` too, which a policy returns unchanged.
|
|
277
292
|
*/
|
|
278
293
|
function roundGrade(value, policy) {
|
|
294
|
+
return round(value, requireRoundingPolicy(policy));
|
|
295
|
+
}
|
|
296
|
+
/** {@link roundGrade} under a policy {@link requireRoundingPolicy} returned. */
|
|
297
|
+
function round(value, policy) {
|
|
279
298
|
if (!Number.isFinite(value)) return value;
|
|
280
299
|
const factor = 10 ** policy.dp;
|
|
281
300
|
const raw = scaled(value, policy.dp);
|
|
@@ -306,9 +325,13 @@ function halfAway(raw) {
|
|
|
306
325
|
* shown one number and recorded against another. Rounding both sides — and
|
|
307
326
|
* allowing an epsilon — makes "what the learner sees" and "what the gradebook
|
|
308
327
|
* decides" the same comparison.
|
|
328
|
+
*
|
|
329
|
+
* @throws RangeError when `policy` is not a {@link RoundingPolicy}. It is read
|
|
330
|
+
* once, so both sides are rounded under the same one.
|
|
309
331
|
*/
|
|
310
332
|
function gte(value, threshold, policy) {
|
|
311
|
-
|
|
333
|
+
const checked = requireRoundingPolicy(policy);
|
|
334
|
+
return round(value, checked) >= round(threshold, checked) - EPSILON;
|
|
312
335
|
}
|
|
313
336
|
/**
|
|
314
337
|
* Classifies a value into a band by **flooring**: the highest band whose `min`
|
|
@@ -337,10 +360,16 @@ const DEFAULT_PASS_THRESHOLD = .7;
|
|
|
337
360
|
* the rounding band, and this SDK does not alter historical grades without an
|
|
338
361
|
* explicit decision. Absent, the comparison is the exact raw `>=` it has
|
|
339
362
|
* always been.
|
|
363
|
+
*
|
|
364
|
+
* The policy is checked at the call, as `score()`'s `rounding` option is:
|
|
365
|
+
* `null` reads as no policy, and one that cannot be applied — an unknown
|
|
366
|
+
* `mode`, or a `dp` that is not a whole number from 0 to 15 — throws a
|
|
367
|
+
* `RangeError` instead of quietly failing the comparison.
|
|
340
368
|
*/
|
|
341
369
|
function computePassThreshold(activityData, score, rounding) {
|
|
370
|
+
const policy = roundingPolicyOf(rounding);
|
|
342
371
|
const threshold = activityData.passThreshold ?? .7;
|
|
343
|
-
return
|
|
372
|
+
return policy === void 0 ? score >= threshold : gte(score, threshold, policy);
|
|
344
373
|
}
|
|
345
374
|
/**
|
|
346
375
|
* Selects the authored overall feedback for a result: `feedback.correct` when
|
|
@@ -1161,8 +1190,11 @@ function rejectedField(slotIds) {
|
|
|
1161
1190
|
* until every item has a grade. An outcome whose score cannot be a grade out of
|
|
1162
1191
|
* its `maxScore` is not a grade either: it is held the same way and named in
|
|
1163
1192
|
* `rejectedSlotIds`.
|
|
1193
|
+
*
|
|
1194
|
+
* @throws RangeError when `policy.rounding` is not a `RoundingPolicy`.
|
|
1164
1195
|
*/
|
|
1165
1196
|
function composeAssessmentScore(sections, policy) {
|
|
1197
|
+
const rounding = requireRoundingPolicy(policy.rounding);
|
|
1166
1198
|
const pendingAll = [];
|
|
1167
1199
|
const rejectedAll = [];
|
|
1168
1200
|
const unscorableAll = [];
|
|
@@ -1200,7 +1232,7 @@ function composeAssessmentScore(sections, policy) {
|
|
|
1200
1232
|
earnedPoints,
|
|
1201
1233
|
gradedMaxPoints,
|
|
1202
1234
|
maxPoints,
|
|
1203
|
-
score: roundGrade(raw,
|
|
1235
|
+
score: roundGrade(raw, rounding),
|
|
1204
1236
|
appliedThreshold,
|
|
1205
1237
|
pendingSlotIds,
|
|
1206
1238
|
rejectedSlotIds,
|
|
@@ -1217,13 +1249,13 @@ function composeAssessmentScore(sections, policy) {
|
|
|
1217
1249
|
gradedMaxPoints: partial.gradedMaxPoints,
|
|
1218
1250
|
maxPoints: partial.maxPoints,
|
|
1219
1251
|
score: partial.score,
|
|
1220
|
-
passed: partial.appliedThreshold === null || partial.gradedMaxPoints === 0 ? true : gte(partial.score, partial.appliedThreshold,
|
|
1252
|
+
passed: partial.appliedThreshold === null || partial.gradedMaxPoints === 0 ? true : gte(partial.score, partial.appliedThreshold, rounding),
|
|
1221
1253
|
appliedThreshold: partial.appliedThreshold,
|
|
1222
1254
|
pendingSlotIds: partial.pendingSlotIds,
|
|
1223
1255
|
...rejectedField(partial.rejectedSlotIds),
|
|
1224
1256
|
unscorableSlotIds: partial.unscorableSlotIds
|
|
1225
1257
|
}));
|
|
1226
|
-
const score = roundGrade(scored.reduce((sum, section) => sum + section.score * section.normalizedWeight, 0),
|
|
1258
|
+
const score = roundGrade(scored.reduce((sum, section) => sum + section.score * section.normalizedWeight, 0), rounding);
|
|
1227
1259
|
const status = pendingAll.length > 0 ? "provisional" : "final";
|
|
1228
1260
|
if (status === "provisional") return {
|
|
1229
1261
|
sections: scored,
|
|
@@ -1245,7 +1277,7 @@ function composeAssessmentScore(sections, policy) {
|
|
|
1245
1277
|
...rejectedField(rejectedAll),
|
|
1246
1278
|
unscorableSlotIds: unscorableAll
|
|
1247
1279
|
};
|
|
1248
|
-
const overallOk = gte(score, policy.passThreshold,
|
|
1280
|
+
const overallOk = gte(score, policy.passThreshold, rounding);
|
|
1249
1281
|
const sectionsOk = scored.every((section) => section.passed);
|
|
1250
1282
|
const passed = overallOk && sectionsOk;
|
|
1251
1283
|
return {
|
|
@@ -2423,4 +2455,4 @@ function costed(data, opening, graded, rules, rounding) {
|
|
|
2423
2455
|
}
|
|
2424
2456
|
export { roundGrade as A, canonicalJson as C, computePassThreshold as D, DEFAULT_PASS_THRESHOLD as E, validateItemScoringPolicy as F, isGradeInRange as I, ITEM_SCORING_MAX_RETRIES as M, resolveItemScoringPolicy as N, classifyBand as O, scoreTries as P, graderConfiguration as S, fingerprint as T, gradeFromJudgement as _, inspectWav as a, outcomeFromGrade as b, alignReadAloud as c, composeAssessmentScore as d, inAuditSample as f, seededShuffle as g, hashSeed as h, outcomeFromUnscorable as i, DEFAULT_ITEM_SCORING_POLICY as j, gte as k, validateSpeechAssessment as l, routeGrade as m, evaluateTries as n, gradeSpeakingResponse as o, outcomeFromRoutedGrade as p, score as r, gradeReadAloud as s, evaluate as t, diffDictationChars as u, gradeFromRubric as v, contentHash as w, calibrationReport as x, hasGrade as y };
|
|
2425
2457
|
|
|
2426
|
-
//# sourceMappingURL=scoring-
|
|
2458
|
+
//# sourceMappingURL=scoring-hMsEMhCU.js.map
|