@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
|
@@ -223,16 +223,27 @@ const ROUNDING_MODES = [
|
|
|
223
223
|
const MAX_ROUNDING_DP = 15;
|
|
224
224
|
/**
|
|
225
225
|
* The rounding policy `value` holds, or `undefined` for none (`undefined` or
|
|
226
|
-
* `null`)
|
|
227
|
-
*
|
|
226
|
+
* `null`): the check for an optional `rounding`. Anything else is checked by
|
|
227
|
+
* {@link requireRoundingPolicy}.
|
|
228
228
|
*
|
|
229
|
-
* Internal
|
|
230
|
-
*
|
|
231
|
-
* does not re-export it.
|
|
229
|
+
* Internal, as is {@link requireRoundingPolicy}: `scoring/index.ts` re-exports
|
|
230
|
+
* neither.
|
|
232
231
|
*/
|
|
233
232
|
function roundingPolicyOf(value) {
|
|
234
|
-
|
|
235
|
-
|
|
233
|
+
return value === void 0 || value === null ? void 0 : requireRoundingPolicy(value);
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* The rounding policy `value` holds. A malformed one would reach the rounding
|
|
237
|
+
* as `10 ** undefined` and turn a perfect score into a fail with no error, so
|
|
238
|
+
* it throws here instead; so does a missing one, `undefined` or `null`, where a
|
|
239
|
+
* policy is required.
|
|
240
|
+
*
|
|
241
|
+
* Every function that takes a policy, as an argument or a `rounding` option,
|
|
242
|
+
* checks it here or through {@link roundingPolicyOf}, so each refuses the same
|
|
243
|
+
* policies with the same message.
|
|
244
|
+
*/
|
|
245
|
+
function requireRoundingPolicy(value) {
|
|
246
|
+
const { mode, dp } = value ?? {};
|
|
236
247
|
if (!ROUNDING_MODES.includes(mode) || typeof dp !== "number" || !Number.isInteger(dp) || dp < 0 || dp > MAX_ROUNDING_DP) {
|
|
237
248
|
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}`;
|
|
238
249
|
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} }.`);
|
|
@@ -263,8 +274,9 @@ function scaled(value, dp) {
|
|
|
263
274
|
* Normalises `-0` to `0` without touching anything else. `-0` JSON-serialises
|
|
264
275
|
* as `0` but fails `Object.is(-0, 0)`, which surprises a strict-equality
|
|
265
276
|
* gradebook comparison. Deliberately NOT `|| 0`: that also swallowed `NaN`
|
|
266
|
-
* (
|
|
267
|
-
* turned a visible failure into a plausible-looking
|
|
277
|
+
* (reached with an absurd `dp`, where `10 ** dp` overflows to Infinity, before
|
|
278
|
+
* policies were checked) and turned a visible failure into a plausible-looking
|
|
279
|
+
* grade of zero.
|
|
268
280
|
*/
|
|
269
281
|
function noNegZero(value) {
|
|
270
282
|
return Object.is(value, -0) ? 0 : value;
|
|
@@ -275,8 +287,15 @@ function noNegZero(value) {
|
|
|
275
287
|
* Idempotent for every mode: rounding an already-rounded value returns it
|
|
276
288
|
* unchanged. That matters because a composed score is rounded once and then
|
|
277
289
|
* compared through {@link gte}, which rounds again.
|
|
290
|
+
*
|
|
291
|
+
* @throws RangeError when `policy` is not a {@link RoundingPolicy} — for a
|
|
292
|
+
* non-finite `value` too, which a policy returns unchanged.
|
|
278
293
|
*/
|
|
279
294
|
function roundGrade(value, policy) {
|
|
295
|
+
return round(value, requireRoundingPolicy(policy));
|
|
296
|
+
}
|
|
297
|
+
/** {@link roundGrade} under a policy {@link requireRoundingPolicy} returned. */
|
|
298
|
+
function round(value, policy) {
|
|
280
299
|
if (!Number.isFinite(value)) return value;
|
|
281
300
|
const factor = 10 ** policy.dp;
|
|
282
301
|
const raw = scaled(value, policy.dp);
|
|
@@ -307,9 +326,13 @@ function halfAway(raw) {
|
|
|
307
326
|
* shown one number and recorded against another. Rounding both sides — and
|
|
308
327
|
* allowing an epsilon — makes "what the learner sees" and "what the gradebook
|
|
309
328
|
* decides" the same comparison.
|
|
329
|
+
*
|
|
330
|
+
* @throws RangeError when `policy` is not a {@link RoundingPolicy}. It is read
|
|
331
|
+
* once, so both sides are rounded under the same one.
|
|
310
332
|
*/
|
|
311
333
|
function gte(value, threshold, policy) {
|
|
312
|
-
|
|
334
|
+
const checked = requireRoundingPolicy(policy);
|
|
335
|
+
return round(value, checked) >= round(threshold, checked) - EPSILON;
|
|
313
336
|
}
|
|
314
337
|
/**
|
|
315
338
|
* Classifies a value into a band by **flooring**: the highest band whose `min`
|
|
@@ -338,10 +361,16 @@ const DEFAULT_PASS_THRESHOLD = .7;
|
|
|
338
361
|
* the rounding band, and this SDK does not alter historical grades without an
|
|
339
362
|
* explicit decision. Absent, the comparison is the exact raw `>=` it has
|
|
340
363
|
* always been.
|
|
364
|
+
*
|
|
365
|
+
* The policy is checked at the call, as `score()`'s `rounding` option is:
|
|
366
|
+
* `null` reads as no policy, and one that cannot be applied — an unknown
|
|
367
|
+
* `mode`, or a `dp` that is not a whole number from 0 to 15 — throws a
|
|
368
|
+
* `RangeError` instead of quietly failing the comparison.
|
|
341
369
|
*/
|
|
342
370
|
function computePassThreshold(activityData, score, rounding) {
|
|
371
|
+
const policy = roundingPolicyOf(rounding);
|
|
343
372
|
const threshold = activityData.passThreshold ?? .7;
|
|
344
|
-
return
|
|
373
|
+
return policy === void 0 ? score >= threshold : gte(score, threshold, policy);
|
|
345
374
|
}
|
|
346
375
|
/**
|
|
347
376
|
* Selects the authored overall feedback for a result: `feedback.correct` when
|
|
@@ -1162,8 +1191,11 @@ function rejectedField(slotIds) {
|
|
|
1162
1191
|
* until every item has a grade. An outcome whose score cannot be a grade out of
|
|
1163
1192
|
* its `maxScore` is not a grade either: it is held the same way and named in
|
|
1164
1193
|
* `rejectedSlotIds`.
|
|
1194
|
+
*
|
|
1195
|
+
* @throws RangeError when `policy.rounding` is not a `RoundingPolicy`.
|
|
1165
1196
|
*/
|
|
1166
1197
|
function composeAssessmentScore(sections, policy) {
|
|
1198
|
+
const rounding = requireRoundingPolicy(policy.rounding);
|
|
1167
1199
|
const pendingAll = [];
|
|
1168
1200
|
const rejectedAll = [];
|
|
1169
1201
|
const unscorableAll = [];
|
|
@@ -1201,7 +1233,7 @@ function composeAssessmentScore(sections, policy) {
|
|
|
1201
1233
|
earnedPoints,
|
|
1202
1234
|
gradedMaxPoints,
|
|
1203
1235
|
maxPoints,
|
|
1204
|
-
score: roundGrade(raw,
|
|
1236
|
+
score: roundGrade(raw, rounding),
|
|
1205
1237
|
appliedThreshold,
|
|
1206
1238
|
pendingSlotIds,
|
|
1207
1239
|
rejectedSlotIds,
|
|
@@ -1218,13 +1250,13 @@ function composeAssessmentScore(sections, policy) {
|
|
|
1218
1250
|
gradedMaxPoints: partial.gradedMaxPoints,
|
|
1219
1251
|
maxPoints: partial.maxPoints,
|
|
1220
1252
|
score: partial.score,
|
|
1221
|
-
passed: partial.appliedThreshold === null || partial.gradedMaxPoints === 0 ? true : gte(partial.score, partial.appliedThreshold,
|
|
1253
|
+
passed: partial.appliedThreshold === null || partial.gradedMaxPoints === 0 ? true : gte(partial.score, partial.appliedThreshold, rounding),
|
|
1222
1254
|
appliedThreshold: partial.appliedThreshold,
|
|
1223
1255
|
pendingSlotIds: partial.pendingSlotIds,
|
|
1224
1256
|
...rejectedField(partial.rejectedSlotIds),
|
|
1225
1257
|
unscorableSlotIds: partial.unscorableSlotIds
|
|
1226
1258
|
}));
|
|
1227
|
-
const score = roundGrade(scored.reduce((sum, section) => sum + section.score * section.normalizedWeight, 0),
|
|
1259
|
+
const score = roundGrade(scored.reduce((sum, section) => sum + section.score * section.normalizedWeight, 0), rounding);
|
|
1228
1260
|
const status = pendingAll.length > 0 ? "provisional" : "final";
|
|
1229
1261
|
if (status === "provisional") return {
|
|
1230
1262
|
sections: scored,
|
|
@@ -1246,7 +1278,7 @@ function composeAssessmentScore(sections, policy) {
|
|
|
1246
1278
|
...rejectedField(rejectedAll),
|
|
1247
1279
|
unscorableSlotIds: unscorableAll
|
|
1248
1280
|
};
|
|
1249
|
-
const overallOk = gte(score, policy.passThreshold,
|
|
1281
|
+
const overallOk = gte(score, policy.passThreshold, rounding);
|
|
1250
1282
|
const sectionsOk = scored.every((section) => section.passed);
|
|
1251
1283
|
const passed = overallOk && sectionsOk;
|
|
1252
1284
|
return {
|
|
@@ -2639,4 +2671,4 @@ Object.defineProperty(exports, "validateSpeechAssessment", {
|
|
|
2639
2671
|
}
|
|
2640
2672
|
});
|
|
2641
2673
|
|
|
2642
|
-
//# sourceMappingURL=scoring-
|
|
2674
|
+
//# sourceMappingURL=scoring-Bmfu8RS5.cjs.map
|