Repository navigation
Score multi-answer Numeric and Text entry questions with a single-cardinality mapping - #6265
Conversation
e7dd067 to
f11f8b8
Compare
f11f8b8 to
3cbfe33
Compare
|
Rebased onto
|
| for (const a of answers) { | ||
| // Trimmed to match how _extractAnswers reads <qti-value> text back. | ||
| let mapKey = a.value.trim(); | ||
| const number = isString ? null : parseXsdDouble(mapKey); |
There was a problem hiding this comment.
This was not asked in the issue. The previous behavior is the intended behavior. Values are always, always kept the same as the user input; this must not change.
There was a problem hiding this comment.
Removed the Number#toString normalization; map keys and the correct response are the author's input again (trimmed only, as before). Searched textEntry/parse.js and the serializers for other value rewrites: one place matched, now removed. Tests updated to assert as-authored keys. (f0ea4027e)
| /** | ||
| * Build a float `<qti-base-value>`. Whole numbers keep a decimal (`1.0`, not `1`) so the | ||
| * value reads as a float wherever it is written. | ||
| * Whole numbers keep a decimal (`1.0`, not `1`) so the value reads as a float wherever | ||
| * it is written. | ||
| * | ||
| * @param {number} value | ||
| * @returns {string} | ||
| */ | ||
| export function formatFloat(value) { | ||
| return Number.isInteger(value) ? value.toFixed(1) : String(value); | ||
| } |
There was a problem hiding this comment.
Hmm, this does not make any difference in the QTI Schema; we can just write numbers as "1" or "1.0", right? If we introduce this function, it'd be hard to remember to use it everywhere.
There was a problem hiding this comment.
Agreed, 1 and 1.0 are equivalent in the schema. Reverted formatFloat and its uses in mapping.js entirely (the whole "float literals" commit); buildFloatNode is back to its original form. Searched for other formatFloat callers: only mapping.js (4 sites), all reverted. (ff9d2dac2)
…ity mapping - Response declaration is always cardinality="single"; correct response holds the first answer - Every accepted answer gets a map entry, so items are scored by map_response - Answers are read from the mapping; items saved as "multiple" still open with all answers - A Text item with no mapping reads back as case-sensitive Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
3cbfe33 to
bfc239e
Compare
AlexVelezLl
left a comment
There was a problem hiding this comment.
Code changes look good and manual QA checks out!
Summary
cardinality="single", the first answer as<qti-correct-response>, and a<qti-mapping>of every answer (map_response).cardinality="multiple"items and Text items without a mapping (read as case-sensitive) open with every answer and save in the new shape.Number#toString(1, not the issue's1.0), the form Kolibri looks responses up by (convert.py:_format_number). Repeated, blank and unreadable numeric answers each keep their own map entry, so the editor still flags them on reopen.References
Fixes #6187
Reviewer guidance
pnpm devsetup, seeded admin, "Sample Empty Exercise" (Published Channel).single,map_response, onemapped-value="1.0"entry per answer; keys2.0→2,0x10as typed.QA steps
Paris, thencolor,Colour,kolorwith Case-sensitive onColouronly; bold a prompt word; CLOSE, reload, Edit each. Answers in typed order, onlyColourticked, bold kept, no error.2, blank,2+1e,2.50+3via Add acceptable answer; CLOSE. Blank rows show "Must be a valid number (e.g. 12, 0.5, -3.14)" and Incomplete;1enone. Reload, Edit each: blank +2, blank,2+1,2.5+3.2+2.0, then2+0x10; CLOSE, Edit each. Rows in typed order;2and2.0show "Duplicate answers are not allowed";0x10, not16, shows "Must be a valid number (e.g. 12, 0.5, -3.14)". After reload,2.0reads2.unstable, "Sample Empty Exercise", Questions tab: add Numeric1,2.5,3and Text entryParis,paris,Lutèce. On this branch, same tab: Edit, CLOSE, reload, Edit each. Every answer appears in the order typed; Text answers ticked Case-sensitive.Evidence
Numeric duplicates and invalid numbers
2+2.0: both flagged duplicate2+2.0reloaded:2,2, both flagged2+0x10reloaded:0x10kept, flaggedText entry
Paris, bold prompt, no errorParisreloadedColouronlyMore captures (7)
2+2.0reopened before reload2+0x10unsaved:0x10flagged2: hint, Incomplete2+1e: no error2.50+3AI usage
Implemented with Claude Code from a plan approved on the issue, test first. I reviewed the diff; the QTIEditor Jest suite passes.
🤖 Generated with Claude Code
Written by rtibblesbot, an LLM-based coding agent.
🟡 Waiting for feedback
Last updated: 2026-10-05 15:56 UTC