diff options
| author | srdusr <[email protected]> | 2025-09-13 21:11:00 +0200 |
|---|---|---|
| committer | srdusr <[email protected]> | 2025-09-13 21:11:00 +0200 |
| commit | 0d3864bcebcdba1b1743367d0f84389fd53e37e1 (patch) | |
| tree | 54a5c028b9fe9b965ffc0240f734b2b5ac81046b /data/packs/programming.json | |
| parent | 29992fe40703cf567177d70f152811bfedb0caad (diff) | |
| download | typerpunk-0d3864bcebcdba1b1743367d0f84389fd53e37e1.tar.gz typerpunk-0d3864bcebcdba1b1743367d0f84389fd53e37e1.zip | |
Rework the end screen figures, mode picker, corners and race view
End screen
- Every figure is now a dim label directly over its value, the two centred on
each other, grouped by what they qualify: RAW and PB under WPM, ERR and
CONSISTENCY under ACC, KEYSTROKES and CHARACTERS either side of TIME. The
row is a grid so TIME sits on the graph's exact centre line rather than
drifting with its neighbours' widths.
- Errors go back onto the wpm line. Their own y axis implied a magnitude a
mistake does not have; what matters is when one happened.
- Graph hover reads "wpm ... raw ... time" - the figures first, the second
they happened in as the qualifier.
Mode picker
- Opens from the Single Player button itself, and choosing a mode starts it:
picking what to type and starting it are one action. The control has now
been a chevron notched into that button, a caption between the two buttons,
a pill above them and a chip row below them; as the button's own menu it
needs no separate real estate at all.
Corners
- Settings and Store move to the bottom-left. The top-left is the wordmark's
alone.
- The global racer count is gone from the home screen - it is not something
you can act on there. The Friends control carries "N online" instead, which
is.
- Presence: users gain a last_seen column, touched at most once a minute per
active user on any authenticated request, and the friends list reports who
has been seen inside a five-minute window.
Multiplayer race view
- The standings move to the middle of the screen, the space the end screen's
graph occupies, and now include your own row rather than opponents only.
Pinned to the top-left corner they put what you are racing against in your
peripheral vision and left out the one bar you most need to see.
Programming mode
- Snippets carry an explanation of what the code does. Shown under the passage
while you type in single player; in multiplayer that space belongs to the
standings, so it waits for the end screen, where it appears either way.
Diffstat (limited to 'data/packs/programming.json')
| -rw-r--r-- | data/packs/programming.json | 210 |
1 files changed, 183 insertions, 27 deletions
diff --git a/data/packs/programming.json b/data/packs/programming.json index 4384c6b..fae99c2 100644 --- a/data/packs/programming.json +++ b/data/packs/programming.json @@ -1,28 +1,184 @@ [ - {"category":"programming","language":"javascript","attribution":"JavaScript","content":"const total = items.reduce((acc, item) => acc + item.price, 0);"}, - {"category":"programming","language":"javascript","attribution":"JavaScript","content":"const unique = [...new Set(values)].sort((a, b) => a - b);"}, - {"category":"programming","language":"javascript","attribution":"JavaScript","content":"export async function load(url) { const res = await fetch(url); return res.json(); }"}, - {"category":"programming","language":"javascript","attribution":"JavaScript","content":"document.querySelectorAll('.row').forEach(el => el.classList.toggle('active'));"}, - {"category":"programming","language":"javascript","attribution":"JavaScript","content":"if (typeof value !== 'string' || value.length === 0) { return null; }"}, - {"category":"programming","language":"javascript","attribution":"JavaScript","content":"const { id, name = 'anonymous', ...rest } = await request.json();"}, - {"category":"programming","language":"python","attribution":"Python","content":"squares = [n * n for n in range(1, 21) if n % 3 != 0]"}, - {"category":"programming","language":"python","attribution":"Python","content":"def fib(n): return n if n < 2 else fib(n - 1) + fib(n - 2)"}, - {"category":"programming","language":"python","attribution":"Python","content":"with open('data.csv', encoding='utf-8') as f: rows = [line.split(',') for line in f]"}, - {"category":"programming","language":"python","attribution":"Python","content":"counts = {word: text.count(word) for word in set(text.split())}"}, - {"category":"programming","language":"python","attribution":"Python","content":"try: value = int(raw) except ValueError: value = 0"}, - {"category":"programming","language":"rust","attribution":"Rust","content":"let mut counts: HashMap<String, usize> = HashMap::new();"}, - {"category":"programming","language":"rust","attribution":"Rust","content":"fn main() { println!(\"{}\", args().skip(1).collect::<Vec<_>>().join(\" \")); }"}, - {"category":"programming","language":"rust","attribution":"Rust","content":"let total: i64 = values.iter().filter(|v| **v > 0).sum();"}, - {"category":"programming","language":"rust","attribution":"Rust","content":"match result { Ok(v) => println!(\"{v}\"), Err(e) => eprintln!(\"error: {e}\") }"}, - {"category":"programming","language":"rust","attribution":"Rust","content":"pub struct Point { pub x: f64, pub y: f64 }"}, - {"category":"programming","language":"rust","attribution":"Rust","content":"impl Display for Token { fn fmt(&self, f: &mut Formatter) -> Result { write!(f, \"{}\", self.0) } }"}, - {"category":"programming","language":"clike","attribution":"C","content":"int *buf = malloc(len * sizeof(int)); if (!buf) return -1;"}, - {"category":"programming","language":"clike","attribution":"C","content":"for (int i = 0; i < n; i++) { sum += a[i] * b[i]; }"}, - {"category":"programming","language":"clike","attribution":"C","content":"struct node { int value; struct node *next; };"}, - {"category":"programming","language":"clike","attribution":"Go","content":"for i, v := range items { fmt.Printf(\"%d: %v\\n\", i, v) }"}, - {"category":"programming","language":"clike","attribution":"Go","content":"if err != nil { return fmt.Errorf(\"read config: %w\", err) }"}, - {"category":"programming","language":"clike","attribution":"Java","content":"public static void main(String[] args) { System.out.println(\"ready\"); }"}, - {"category":"programming","language":"shell","attribution":"Shell","content":"grep -rn \"TODO\" src/ | awk -F: '{print $1}' | sort -u"}, - {"category":"programming","language":"shell","attribution":"Shell","content":"for f in *.log; do gzip -9 \"$f\" && echo \"packed $f\"; done"}, - {"category":"programming","language":"shell","attribution":"Shell","content":"export PATH=\"$HOME/.local/bin:$PATH\" && command -v rg >/dev/null || echo missing"} -] + { + "category": "programming", + "language": "javascript", + "attribution": "JavaScript", + "content": "const total = items.reduce((acc, item) => acc + item.price, 0);", + "explanation": "reduce walks the array carrying a running value. The 0 is the starting total; drop it and an empty array throws." + }, + { + "category": "programming", + "language": "javascript", + "attribution": "JavaScript", + "content": "const unique = [...new Set(values)].sort((a, b) => a - b);", + "explanation": "A Set discards duplicates. Spreading it back to an array allows sorting; the comparator is required or numbers sort as text." + }, + { + "category": "programming", + "language": "javascript", + "attribution": "JavaScript", + "content": "export async function load(url) { const res = await fetch(url); return res.json(); }", + "explanation": "fetch resolves as soon as headers arrive, so .json() is a second await for the body. It does not throw on a 404 - check res.ok." + }, + { + "category": "programming", + "language": "javascript", + "attribution": "JavaScript", + "content": "document.querySelectorAll('.row').forEach(el => el.classList.toggle('active'));", + "explanation": "querySelectorAll returns a static NodeList, so it will not change as you mutate the elements in it." + }, + { + "category": "programming", + "language": "javascript", + "attribution": "JavaScript", + "content": "if (typeof value !== 'string' || value.length === 0) { return null; }", + "explanation": "A guard clause: reject the bad input first and return, instead of nesting the real work inside an if." + }, + { + "category": "programming", + "language": "javascript", + "attribution": "JavaScript", + "content": "const { id, name = 'anonymous', ...rest } = await request.json();", + "explanation": "Destructuring with a default and a rest property. The default applies only when the value is undefined, not when it is null." + }, + { + "category": "programming", + "language": "python", + "attribution": "Python", + "content": "squares = [n * n for n in range(1, 21) if n % 3 != 0]", + "explanation": "A list comprehension: the expression, the loop, then the filter. Faster and clearer than appending in a for loop." + }, + { + "category": "programming", + "language": "python", + "attribution": "Python", + "content": "def fib(n): return n if n < 2 else fib(n - 1) + fib(n - 2)", + "explanation": "Recursion with a base case. Correct but exponential - each call spawns two more, so it recomputes the same values repeatedly." + }, + { + "category": "programming", + "language": "python", + "attribution": "Python", + "content": "with open('data.csv', encoding='utf-8') as f: rows = [line.split(',') for line in f]", + "explanation": "with closes the file even if the body raises. Iterating a file yields lines without loading it all into memory." + }, + { + "category": "programming", + "language": "python", + "attribution": "Python", + "content": "counts = {word: text.count(word) for word in set(text.split())}", + "explanation": "A dict comprehension. Note it is quadratic: count rescans the whole string per word. collections.Counter is the right tool." + }, + { + "category": "programming", + "language": "python", + "attribution": "Python", + "content": "try: value = int(raw) except ValueError: value = 0", + "explanation": "Catching the specific exception, not a bare except - a bare one would also swallow KeyboardInterrupt." + }, + { + "category": "programming", + "language": "rust", + "attribution": "Rust", + "content": "let mut counts: HashMap<String, usize> = HashMap::new();", + "explanation": "mut because inserting mutates it. The type annotation is needed here since nothing yet tells the compiler what it holds." + }, + { + "category": "programming", + "language": "rust", + "attribution": "Rust", + "content": "fn main() { println!(\"{}\", args().skip(1).collect::<Vec<_>>().join(\" \")); }", + "explanation": "skip(1) drops the program name, which is always the first argument. Vec<_> lets the compiler infer the element type." + }, + { + "category": "programming", + "language": "rust", + "attribution": "Rust", + "content": "let total: i64 = values.iter().filter(|v| **v > 0).sum();", + "explanation": "iter() borrows rather than consuming. The double deref is because filter hands you a reference to the iterator's own reference." + }, + { + "category": "programming", + "language": "rust", + "attribution": "Rust", + "content": "match result { Ok(v) => println!(\"{v}\"), Err(e) => eprintln!(\"error: {e}\") }", + "explanation": "match on a Result must cover both arms - the compiler rejects it otherwise, which is how Rust stops an error going unhandled." + }, + { + "category": "programming", + "language": "rust", + "attribution": "Rust", + "content": "pub struct Point { pub x: f64, pub y: f64 }", + "explanation": "Fields are private by default in Rust, so each one needs its own pub - making the struct public does not publish its contents." + }, + { + "category": "programming", + "language": "rust", + "attribution": "Rust", + "content": "impl Display for Token { fn fmt(&self, f: &mut Formatter) -> Result { write!(f, \"{}\", self.0) } }", + "explanation": "Implementing Display is what makes a type usable in {}. self.0 is the first field of a tuple struct." + }, + { + "category": "programming", + "language": "clike", + "attribution": "C", + "content": "int *buf = malloc(len * sizeof(int)); if (!buf) return -1;", + "explanation": "malloc returns NULL when it fails, and checking is not optional. sizeof(int) rather than 4 keeps it correct across platforms." + }, + { + "category": "programming", + "language": "clike", + "attribution": "C", + "content": "for (int i = 0; i < n; i++) { sum += a[i] * b[i]; }", + "explanation": "A dot product. The bound is < n, not <= n; off-by-one here reads past the end of the array." + }, + { + "category": "programming", + "language": "clike", + "attribution": "C", + "content": "struct node { int value; struct node *next; };", + "explanation": "A linked-list node. It refers to its own type through a pointer, which is legal because a pointer has a known size." + }, + { + "category": "programming", + "language": "clike", + "attribution": "Go", + "content": "for i, v := range items { fmt.Printf(\"%d: %v\\n\", i, v) }", + "explanation": "range yields index and value. In Go before 1.22 the loop variable was reused each iteration, which surprised anyone capturing it in a closure." + }, + { + "category": "programming", + "language": "clike", + "attribution": "Go", + "content": "if err != nil { return fmt.Errorf(\"read config: %w\", err) }", + "explanation": "Go's error convention. %w wraps the original so errors.Is and errors.As can still see it further up." + }, + { + "category": "programming", + "language": "clike", + "attribution": "Java", + "content": "public static void main(String[] args) { System.out.println(\"ready\"); }", + "explanation": "Java's entry point. The signature is fixed: static so it runs without an instance, and taking the command-line arguments." + }, + { + "category": "programming", + "language": "shell", + "attribution": "Shell", + "content": "grep -rn \"TODO\" src/ | awk -F: '{print $1}' | sort -u", + "explanation": "grep -n prints file:line:text, awk splits on the colon to take the filename, sort -u removes the duplicates." + }, + { + "category": "programming", + "language": "shell", + "attribution": "Shell", + "content": "for f in *.log; do gzip -9 \"$f\" && echo \"packed $f\"; done", + "explanation": "The quotes around $f matter: without them a filename containing a space becomes two arguments." + }, + { + "category": "programming", + "language": "shell", + "attribution": "Shell", + "content": "export PATH=\"$HOME/.local/bin:$PATH\" && command -v rg >/dev/null || echo missing", + "explanation": "Prepending puts your own binaries ahead of the system ones. command -v is the portable test for whether something is installed." + } +]
\ No newline at end of file |