From afae18deccf7f333e20a74e295db37ced4687eb2 Mon Sep 17 00:00:00 2001 From: Markus Graf Date: Sun, 29 Mar 2026 11:06:22 +0200 Subject: [PATCH] feat(01-03): implement level definitions 1-6 with finger mappings - 6 levels per spec section 4.1 progression table - Finger-to-CSS-variable mapping per spec section 8.3 - getLevelByNumber and getKeysUpToLevel helper functions - All 14 tests passing Co-Authored-By: Claude Opus 4.6 (1M context) --- src/game/levels.ts | 110 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 src/game/levels.ts diff --git a/src/game/levels.ts b/src/game/levels.ts new file mode 100644 index 0000000..cae1808 --- /dev/null +++ b/src/game/levels.ts @@ -0,0 +1,110 @@ +import type { Level } from "../types"; + +// Finger color CSS variable mapping per spec section 8.3 +// Left hand: pinky=Q/A/Y/1, ring=W/S/X/2, mid=E/D/C/3, index=R/F/V/T/G/B/4/5 +// Right hand: index=U/J/M/Z/H/N/6/7, mid=I/K/,/8, ring=O/L/./9, pinky=P/Ö/Ä/Ü/0/ß +// Thumb: Space + +const fingerMap: Record = { + // Left pinky + q: "--finger-l-pinky", + a: "--finger-l-pinky", + y: "--finger-l-pinky", + // Left ring + w: "--finger-l-ring", + s: "--finger-l-ring", + x: "--finger-l-ring", + // Left middle + e: "--finger-l-mid", + d: "--finger-l-mid", + c: "--finger-l-mid", + // Left index + r: "--finger-l-index", + f: "--finger-l-index", + v: "--finger-l-index", + t: "--finger-l-index", + g: "--finger-l-index", + b: "--finger-l-index", + // Right index + u: "--finger-r-index", + j: "--finger-r-index", + m: "--finger-r-index", + z: "--finger-r-index", + h: "--finger-r-index", + n: "--finger-r-index", + // Right middle + i: "--finger-r-mid", + k: "--finger-r-mid", + // Right ring + o: "--finger-r-ring", + l: "--finger-r-ring", + // Right pinky + p: "--finger-r-pinky", + ö: "--finger-r-pinky", + ä: "--finger-r-pinky", + ü: "--finger-r-pinky", + // Thumb + " ": "--finger-thumb", +}; + +export const levels: Level[] = [ + { + level: 1, + newKeys: ["f", "j", " "], + allKeys: ["f", "j", " "], + fingerMap, + }, + { + level: 2, + newKeys: ["d", "k"], + allKeys: ["f", "j", " ", "d", "k"], + fingerMap, + }, + { + level: 3, + newKeys: ["s", "l"], + allKeys: ["f", "j", " ", "d", "k", "s", "l"], + fingerMap, + }, + { + level: 4, + newKeys: ["a", "ö"], + allKeys: ["f", "j", " ", "d", "k", "s", "l", "a", "ö"], + fingerMap, + }, + { + level: 5, + newKeys: ["g", "h"], + allKeys: ["f", "j", " ", "d", "k", "s", "l", "a", "ö", "g", "h"], + fingerMap, + }, + { + level: 6, + newKeys: ["e", "i"], + allKeys: [ + "f", + "j", + " ", + "d", + "k", + "s", + "l", + "a", + "ö", + "g", + "h", + "e", + "i", + ], + fingerMap, + }, +]; + +export function getLevelByNumber(n: number): Level | undefined { + return levels.find((l) => l.level === n); +} + +export function getKeysUpToLevel(n: number): string[] { + const level = getLevelByNumber(n); + return level ? level.allKeys : []; +}