srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/data
diff options
context:
space:
mode:
authorsrdusr <[email protected]>2025-09-13 21:11:00 +0200
committersrdusr <[email protected]>2025-09-13 21:11:00 +0200
commit0d3864bcebcdba1b1743367d0f84389fd53e37e1 (patch)
tree54a5c028b9fe9b965ffc0240f734b2b5ac81046b /data
parent29992fe40703cf567177d70f152811bfedb0caad (diff)
downloadtyperpunk-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')
-rw-r--r--data/packs/programming.json210
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