@vue-skuilder/db 0.2.10 → 0.2.11
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/dist/index.js +34 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +34 -19
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/study/services/ResponseProcessor.ts +56 -22
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
7
|
-
"version": "0.2.
|
|
7
|
+
"version": "0.2.11",
|
|
8
8
|
"description": "Database layer for vue-skuilder",
|
|
9
9
|
"main": "dist/index.js",
|
|
10
10
|
"module": "dist/index.mjs",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"@nilock2/pouchdb-authentication": "^1.0.2",
|
|
51
|
-
"@vue-skuilder/common": "0.2.
|
|
51
|
+
"@vue-skuilder/common": "0.2.11",
|
|
52
52
|
"cross-fetch": "^4.1.0",
|
|
53
53
|
"moment": "^2.29.4",
|
|
54
54
|
"pouchdb": "^9.0.0",
|
|
@@ -62,5 +62,5 @@
|
|
|
62
62
|
"vite": "^8.0.0",
|
|
63
63
|
"vitest": "^4.1.0"
|
|
64
64
|
},
|
|
65
|
-
"stableVersion": "0.2.
|
|
65
|
+
"stableVersion": "0.2.11"
|
|
66
66
|
}
|
|
@@ -189,7 +189,9 @@ export class ResponseProcessor {
|
|
|
189
189
|
const nullTags = tagKeys.filter((k) => taggedPerformance[k] === null);
|
|
190
190
|
const scoredTags = tagKeys.filter((k) => taggedPerformance[k] !== null);
|
|
191
191
|
logger.info(
|
|
192
|
-
`[
|
|
192
|
+
`[FirstContactElo] correct first-attempt per-tag ELO update for ${cardId} ` +
|
|
193
|
+
`(historyLen=${history.records.length}, priorAttemps=${cardRecord.priorAttemps}): ` +
|
|
194
|
+
`scored=[${scoredTags.join(', ')}] count-only=[${nullTags.join(', ')}]`
|
|
193
195
|
);
|
|
194
196
|
|
|
195
197
|
void this.eloService.updateUserAndCardEloPerTag(
|
|
@@ -225,7 +227,8 @@ export class ResponseProcessor {
|
|
|
225
227
|
);
|
|
226
228
|
}
|
|
227
229
|
logger.info(
|
|
228
|
-
|
|
230
|
+
`[FirstContactElo] correct first-attempt ELO update (score=${userScore.toFixed(3)}) ` +
|
|
231
|
+
`for ${cardId} (historyLen=${history.records.length}, priorAttemps=${cardRecord.priorAttemps})`
|
|
229
232
|
);
|
|
230
233
|
}
|
|
231
234
|
|
|
@@ -270,8 +273,17 @@ export class ResponseProcessor {
|
|
|
270
273
|
// Parse performance (may be numeric or structured)
|
|
271
274
|
const { taggedPerformance } = this.parsePerformance(cardRecord.performance);
|
|
272
275
|
|
|
273
|
-
//
|
|
274
|
-
|
|
276
|
+
// Tracks whether this response already produced an ELO update, so the
|
|
277
|
+
// dismiss-failed branch below doesn't double-penalize the same record (the
|
|
278
|
+
// two coincide when maxAttemptsPerView === 1: first contact and final
|
|
279
|
+
// failure land on one response).
|
|
280
|
+
let eloUpdated = false;
|
|
281
|
+
|
|
282
|
+
// Update ELO on the first attempt of a presentation — symmetric with the
|
|
283
|
+
// correct path. Previously this was gated on `history.records.length !== 1`,
|
|
284
|
+
// so first-EVER failures were skipped while first-ever successes updated,
|
|
285
|
+
// biasing cold-start ELO upward. See WORKING-first-contact-elo-asymmetry.md.
|
|
286
|
+
if (cardRecord.priorAttemps === 0) {
|
|
275
287
|
if (taggedPerformance) {
|
|
276
288
|
// Per-tag ELO update for incorrect response
|
|
277
289
|
void this.eloService.updateUserAndCardEloPerTag(
|
|
@@ -282,7 +294,9 @@ export class ResponseProcessor {
|
|
|
282
294
|
currentCard
|
|
283
295
|
);
|
|
284
296
|
logger.info(
|
|
285
|
-
`[
|
|
297
|
+
`[FirstContactElo] incorrect first-attempt per-tag ELO update for ${cardId} ` +
|
|
298
|
+
`(historyLen=${history.records.length}, priorAttemps=${cardRecord.priorAttemps}, ` +
|
|
299
|
+
`tags=${Object.keys(taggedPerformance).length - 1})`
|
|
286
300
|
);
|
|
287
301
|
} else {
|
|
288
302
|
// Standard single-score ELO update
|
|
@@ -293,32 +307,52 @@ export class ResponseProcessor {
|
|
|
293
307
|
courseRegistrationDoc,
|
|
294
308
|
currentCard
|
|
295
309
|
);
|
|
296
|
-
logger.info(
|
|
310
|
+
logger.info(
|
|
311
|
+
`[FirstContactElo] incorrect first-attempt ELO update (score=0) for ${cardId} ` +
|
|
312
|
+
`(historyLen=${history.records.length}, priorAttemps=${cardRecord.priorAttemps})`
|
|
313
|
+
);
|
|
297
314
|
}
|
|
315
|
+
eloUpdated = true;
|
|
298
316
|
} else {
|
|
299
|
-
logger.info(
|
|
317
|
+
logger.info(
|
|
318
|
+
`[FirstContactElo] incorrect retry — no ELO update for ${cardId} ` +
|
|
319
|
+
`(historyLen=${history.records.length}, priorAttemps=${cardRecord.priorAttemps})`
|
|
320
|
+
);
|
|
300
321
|
}
|
|
301
322
|
|
|
302
323
|
// Determine navigation based on attempt limits
|
|
303
324
|
if (currentCard.records.length >= maxAttemptsPerView) {
|
|
304
325
|
if (sessionViews >= maxSessionViews) {
|
|
305
|
-
// Too many session views - dismiss completely with ELO penalty
|
|
306
|
-
if
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
326
|
+
// Too many session views - dismiss completely with ELO penalty.
|
|
327
|
+
// Skip if this response already updated ELO above, to avoid a double
|
|
328
|
+
// penalty on the same record (happens when maxAttemptsPerView === 1).
|
|
329
|
+
if (!eloUpdated) {
|
|
330
|
+
if (taggedPerformance) {
|
|
331
|
+
// Use tagged performance for final failure
|
|
332
|
+
void this.eloService.updateUserAndCardEloPerTag(
|
|
333
|
+
taggedPerformance,
|
|
334
|
+
courseId,
|
|
335
|
+
cardId,
|
|
336
|
+
courseRegistrationDoc,
|
|
337
|
+
currentCard
|
|
338
|
+
);
|
|
339
|
+
} else {
|
|
340
|
+
void this.eloService.updateUserAndCardElo(
|
|
341
|
+
0,
|
|
342
|
+
courseId,
|
|
343
|
+
cardId,
|
|
344
|
+
courseRegistrationDoc,
|
|
345
|
+
currentCard
|
|
346
|
+
);
|
|
347
|
+
}
|
|
348
|
+
logger.info(
|
|
349
|
+
`[FirstContactElo] dismiss-failed final ELO penalty for ${cardId} ` +
|
|
350
|
+
`(historyLen=${history.records.length}, sessionViews=${sessionViews})`
|
|
314
351
|
);
|
|
315
352
|
} else {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
cardId,
|
|
320
|
-
courseRegistrationDoc,
|
|
321
|
-
currentCard
|
|
353
|
+
logger.info(
|
|
354
|
+
`[FirstContactElo] dismiss-failed — ELO already updated this response, ` +
|
|
355
|
+
`skipping double penalty for ${cardId}`
|
|
322
356
|
);
|
|
323
357
|
}
|
|
324
358
|
return {
|