feat(drills): which shapes you get right, per kind - #94
Merged
Conversation
Part of drills part B (technology#55): the per-kind progress piece.
The kind's totals were already on /stats. What was not anywhere is the
question a player has after twenty spots, which is which of these am I
getting wrong. `DrillRecord` gains a per-shape split of the same two
counters, counted in `recordDrill` off `drill.settledBy`, and /stats
prints it as the fraction it is ("7 of 21", never 33%).
No claim is made, so no confidence is needed. A percentage hides its
sample size and invites a comparison between rows that eleven answers
cannot support; a fraction carries the sample size in it. Nothing is
ranked, coloured or called a weakness, and a shape you have not seen is
absent rather than shown at zero.
The rows are driven by the kind's ladder in lib/drills/standing.ts, so
the breakdown and the standing sentence call a shape the same thing, a
retired shape sitting in an old profile cannot render a row with no
label, and pot odds gets its breakdown for free the day it lands.
Measured rather than assumed, over 2,000 seeds a kind: which-hand-wins
deals category 50%, kicker 23%, rank 21%, split 5.5%; count-your-outs
deals one-draw 56%, two-draws 38%, many-draws 5.9%. The rarest shape is
the hardest one on both ladders, so the row a player most wants needs
about 200 answers to clear the floor of 10. A test holds every shape
above 2% of spots, because a generator change that drops one to nearly
never would leave a row that quietly cannot exist.
PERSIST_VERSION 16. Existing records migrate to an empty breakdown and
cannot do anything else: the totals do not record which shapes they
were, and splitting them by the measured frequencies would put numbers
on the screen that describe the generator rather than the player.
The sync merge takes the per-shape counters shape by shape, so neither
device loses a shape the other has never seen, and `correct <= answered`
survives on every row.
Deploying pip-web with
|
| Latest commit: |
77568aa
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://2a98ec4e.pip-web-9oj.pages.dev |
| Branch Preview URL: | https://feat-drills-shape-breakdown.pip-web-9oj.pages.dev |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The per-kind progress piece of drills part B (technology#55). The kind's totals were already on
/stats. What was nowhere is the question a player actually has after twenty spots, which is which of these am I getting wrong.The thing #55 asked for that I did not build, and why
The spec names "you are reading pot odds better than you were". I measured whether that sentence can be said honestly and it cannot, at any volume a player will reach.
The rating is a mean-reverting random walk, so for a player whose reading has not changed at all, the rating still moves. Simulated against both kinds' real difficulty spreads at three skill levels, 60 runs each, reading the change over the last 20 answers once
answered >= 50:There is no setting that is both quiet on a settled player and awake to a real one, because the rating's climb through a genuine improvement is transient: widen the window to keep the signal in view and the noise widens with it (|Δ| p95 goes 65 at W=20 to 98 at W=60). The information floor is about 100 spots per half, roughly 200 answers, to separate a 100-point change from noise. That sentence is a mood ring at the volumes we have. Written up on technology#55 with the numbers so nobody rebuilds it.
What is here instead, and it is a count rather than an inference
DrillRecordgains a per-shape split of the two counters it already keeps, incremented inrecordDrilloffdrill.settledBy(the same reading that set the answer and the difficulty)./statsprints each shape as the fraction it is:"7 of 21", never 33%. A percentage hides its sample size and invites a comparison between rows that eleven answers cannot support; a fraction carries the sample size in it and lets a player weigh their own numbers. Nothing is ranked, coloured or called a weakness. A shape you have never seen is absent rather than shown at zero. Still a mirror: no clock, no target, nothing to complete.
Rows are driven by the kind's ladder in
lib/drills/standing.tsrather than by the keys on the record. Three things fall out: the row and the standing sentence call a shape the same thing, a retired or renamed shape sitting in a year-old profile cannot render a row with no label, and pot odds gets its breakdown for free the day #93 lands.The generators were measured, not assumed
Over 2,000 seeds a kind:
which-hand-winsdeals category 50%, kicker 23%, rank 21%, split 5.5%;count-your-outsdeals one-draw 56%, two-draws 38%, many-draws 5.9%.The rarest shape is the hardest one on both ladders, so the row a player would most want is the one that takes longest to appear: at one spot in eighteen,
splitandmany-drawsneed around 200 answers to clear a floor of 10. That is a real property of the generators and it is the number to change if we ever want the hard shapes readable sooner. A test holds every shape above 2% of spots, because a generator change that drops one to nearly never would leave a row that quietly cannot exist and nothing else would notice.PERSIST_VERSION16Existing records migrate to an empty breakdown, and cannot do anything else: the totals do not record which shapes they were. Splitting them by the measured frequencies above would put four rows on the screen that describe the generator rather than the player.
The sync merge takes the per-shape counters shape by shape rather than wholesale from the busier device, so neither side loses a shape the other has never seen, and
correct <= answeredsurvives on every row (it holds on each side, and the larger of twocorrectcannot exceed the larger of twoanswered).The gate, and what it does not cover
pnpm test:allgreen, 515 tests (up from 505), andpnpm buildgreen.The tests were checked by breaking the code they cover, not by reading them. Five mutants, all killed: iterating the record instead of the ladder (kills the order test and the drop test), never incrementing a shape's
correct, deleting the v16 migration branch, takingshapeswholesale from the busier side, and taking a shape'scorrectfrom a different side than itsanswered.The UI half is unverified. This ran in a runner with no browser and no device, so the rows under each drill card on
/statshave not been looked at on a screen: not the spacing, not the truncation of a long shape label at narrow widths, not how the card reads with four rows under it. That needs a human to click.One thing worth a real player's eye: the free kind's
splitrow will not appear until about 200 answers, and until then the breakdown shows three rows out of four with no explanation of the fourth's absence. I think silence is right (a row you have not earned is not a row), but it is a judgement and somebody should disagree with it if they want to.Conflicts with nothing in #93: that touches
DrillRunner's render,rating.ts,standing.ts,types.tsand the drills config; this touches the store, the merge,/statsand one line ofDrillRunner'spick.