feat(learn): the reference screens as the reworked artifact has them

읽기 연습. Each mode opens with what the round is and a Start button; the
round is timed, and a finished one reports accuracy and time, keeps the
best per mode and says when it was beaten. In sound mode the written
spelling is among the options — reading it as written is the habit the
drill exists to break, so it is the distractor that matters. Answers stay
marked 450ms when right, 900ms when a rule is shown, 1400ms when wrong.
The best rounds sync (trainer.drill), merged mode by mode: the higher
accuracy, then the faster time.

문법. An All chip, a count on every category, 반말 selected first — it is
what manhwa speech is made of — and each row names its category, so the
list still reads under All.

활용 연습. Words come in random order, not the pool's; the running score
comes back after a reload; a wrong answer shows what was typed beside what
it should have been, then the rule. The pool adds the roadmap's own verbs
and adjectives to the deck's. A form lib/conjugation.js cannot build no
longer leaves the Check button stuck.

문장. The artifact's lesson on the ending word and the 서술어 legend, a count
on each level, and every sentence's place in review — as far along as its
least-known chunk, since the chunks are the cards.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-09-16 22:12:05 +02:00
parent ede8f295a2
commit 57fd6e5087
10 changed files with 646 additions and 223 deletions

View File

@@ -97,6 +97,20 @@ describe("meta", () => {
expect(mergedValue(r)).toEqual({ a: true, b: true });
});
it("keeps the better reading-drill round for each mode", () => {
const r = resolve(
"meta",
live({ k: "trainer.drill", v: JSON.stringify({ sound: { acc: 92, sec: 40 }, speed: { acc: 75, sec: 30 } }) }),
live({ k: "trainer.drill", v: JSON.stringify({ sound: { acc: 92, sec: 55 }, sentence: { acc: 58, sec: 70 } }) }),
ctx,
);
expect(mergedValue(r)).toEqual({
sound: { acc: 92, sec: 40 }, // the same accuracy, faster
speed: { acc: 75, sec: 30 },
sentence: { acc: 58, sec: 70 },
});
});
it("keeps the longer of two versions of one note", () => {
const r = resolve(
"meta",