You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 1ebcae1
Browse filesBrowse the repository at this point in the historyBrowse files
Detect challenge links and bests recorded on different passage text
Challenge links (now version 2) and bests store a hash of the run's first
passage. When the seed no longer gives that passage after a change to
texts.js, a challenge is still played but without a ghost or winner, and a
best is not replayed until a new best is set. Version 1 links and bests
without a hash are played without the check.
Closes#43
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: README.md
+9-9Lines changed: 9 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -33,9 +33,9 @@ Serve the folder with `npm run serve` (see Development) or any static file serve
33
33
-**Stop on error**: with this setting on, a wrong key is counted as a mistake but does not move the caret, so each mistake has to be fixed with the right key before you can continue.
34
34
-**Caps Lock warning**: a notice below the text while Caps Lock is on.
35
35
-**Hard Mode**: blurs the characters you have already typed, so you cannot see your mistakes. The text ahead stays readable.
36
-
-**Ghost Mode**: records the timing of your best run and replays its position as a second cursor while you type. Bests record the seed their passages were drawn from, so with Ghost Mode on you type the same passages as your best run. In Time mode, when the ghost is on a later or earlier passage than you, its cursor waits at the end or start of yours with an arrow pointing the way. A line below the text shows how many characters ahead of or behind the ghost you are, or says that no ghost exists yet for the current settings. In Weak Keys, a ghost run uses the letters the best run practiced, and the note above the text says so.
36
+
-**Ghost Mode**: records the timing of your best run and replays its position as a second cursor while you type. Bests record the seed their passages were drawn from, so with Ghost Mode on you type the same passages as your best run. In Time mode, when the ghost is on a later or earlier passage than you, its cursor waits at the end or start of yours with an arrow pointing the way. A line below the text shows how many characters ahead of or behind the ghost you are, or says that no ghost exists yet for the current settings. In Weak Keys, a ghost run uses the letters the best run practiced, and the note above the text says so. Bests also record a hash of their first passage. If a change to `texts.js` means the seed no longer gives that passage, Ghost Mode says so and does not replay the best until a new best is set.
37
37
-**Results**: a modal with your WPM and accuracy; raw WPM (all typed characters, right or wrong); correct and wrong character counts; elapsed time; whether the run set a new best for its settings, and the previous best; the keys you missed most in this run; a line chart of WPM at the end of each second of the run; a line chart of your last ten runs at the current settings once you have two or more; a Share button; and, once you have missed letters often enough, a button that starts a Weak Keys run. The shared text has the WPM, accuracy, settings, and a link to the site. On touch devices it opens the system share sheet; elsewhere it copies to the clipboard.
38
-
-**Challenge links**: after a run of a second or longer, Copy challenge link puts a URL on the clipboard, or on touch devices opens the system share sheet. If copying fails, the link is shown, selected, in the result dialog. The URL's hash holds the run's settings, including Stop on error and Skip indentation, the seed of its passages, its WPM, and its keystroke timings, compressed. Opening it, also in a tab that already has the page open, starts a run on the same passages with that run as the ghost, and the result dialog says who was faster. The receiver's saved settings are not changed; after the run, Play Again goes back to them. Links made before a change to the passages in `texts.js`may show different text.
38
+
-**Challenge links**: after a run of a second or longer, Copy challenge link puts a URL on the clipboard, or on touch devices opens the system share sheet. If copying fails, the link is shown, selected, in the result dialog. The URL's hash holds the run's settings, including Stop on error and Skip indentation, the seed of its passages, its WPM, and its keystroke timings, compressed. Opening it, also in a tab that already has the page open, starts a run on the same passages with that run as the ghost, and the result dialog says who was faster. The receiver's saved settings are not changed; after the run, Play Again goes back to them. Links also carry a hash of the run's first passage. If a change to `texts.js`means the seed no longer gives that passage, the run is still played, but without a ghost, and the result dialog does not say who won. Links made before this hash was added are played without the check.
39
39
-**Stats dialog**: opened from the chart icon in the header, with your best WPM for every setting you have played, the average of your last ten runs, and a list of recorded runs. Export saves everything in `localStorage` to a JSON file, Import loads such a file and replaces the stored data, and Clear data (two clicks) removes history, bests, and key stats.
40
40
-**Themes**: System (follows the OS light/dark and increased-contrast settings), Dark, Light, and High contrast, chosen in Settings. `theme.js`, loaded in `<head>`, applies the saved theme before the page paints.
41
41
-**Offline and install**: `sw.js`, a service worker, saves the app's files on the first visit, so later visits load without a network connection. It tries the network first, so a new version is used as soon as you are online. `manifest.webmanifest` and the icons in `icons/` let browsers install the page as an app.
@@ -49,20 +49,20 @@ Pasting into the input is blocked, and the caret stays at the end: arrow keys, H
49
49
50
50
## Privacy
51
51
52
-
There is no account and no backend: GitHub Pages serves the static files, and the page makes no requests to other sites, which a test checks. Settings, run history, best scores, and key stats are stored in this browser's `localStorage`, under the keys listed below, and are not sent anywhere. Challenge links carry one run's settings, seed, WPM, and keystroke timings in the URL hash, which browsers do not send to the server; they leave the browser only if you share the link.
52
+
There is no account and no backend: GitHub Pages serves the static files, and the page makes no requests to other sites, which a test checks. Settings, run history, best scores, and key stats are stored in this browser's `localStorage`, under the keys listed below, and are not sent anywhere. Challenge links carry one run's settings, seed, first passage hash, WPM, and keystroke timings in the URL hash, which browsers do not send to the server; they leave the browser only if you share the link.
53
53
54
54
Clearing the browser's site data deletes everything. To keep a copy or move to another device, use Export in the Stats dialog and Import on the other side. Clear data in the same dialog removes history, bests, and key stats.
55
55
56
56
## Settings and data
57
57
58
58
Everything is stored in `localStorage` under these keys:
|`typingGameSettings`| mode, duration, word count, category, and the feature toggles |
63
-
|`typingGameHistory`| last 500 runs as `{wpm, accuracy, date, mode, key}`|
64
-
|`typingGameBests`| for each settings key, the best run as `{wpm, keystrokes, seed, weakKeys?}`: keystroke timings and the passage seed for Ghost Mode, and the letters practiced for Weak Keys runs |
65
-
|`typingGameKeyStats`| attempts and misses for each expected character across recorded runs |
|`typingGameSettings`| mode, duration, word count, category, and the feature toggles |
63
+
|`typingGameHistory`| last 500 runs as `{wpm, accuracy, date, mode, key}`|
64
+
|`typingGameBests`| for each settings key, the best run as `{wpm, keystrokes, seed, textHash, weakKeys?}`: keystroke timings, the passage seed, and a hash of the first passage for Ghost Mode, and the letters practiced for Weak Keys runs |
65
+
|`typingGameKeyStats`| attempts and misses for each expected character across recorded runs |
66
66
67
67
A settings key combines mode, length, and category, for example `time:60s:common` or `words:25w:code-python`. Common Words with punctuation or numbers adds them to the category, as in `time:30s:common+punctuation+numbers`. Code Snippets with Skip indentation off adds `+noindent`, and Stop on error adds `+stop`. Best scores, Ghost Mode, and the chart only compare runs with the same key. Runs that finish in under a second are shown but not saved.
0 commit comments