Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 60x 58x 58x 58x 60x 60x 3x 3x 52x 52x | /**
* The abacus identity triple — the shared vocabulary between the
* player_abacus_identity table, its API route, and the studio UI.
*
* Deliberately framework- and drizzle-free so client components can import
* the constants without dragging the DB schema into the bundle.
*/
export const ABACUS_COLOR_SCHEMES = [
'monochrome',
'place-value',
'heaven-earth',
'alternating',
] as const
export const ABACUS_COLOR_PALETTES = [
'default',
'colorblind',
'mnemonic',
'grayscale',
'nature',
] as const
export type AbacusColorScheme = (typeof ABACUS_COLOR_SCHEMES)[number]
export type AbacusColorPalette = (typeof ABACUS_COLOR_PALETTES)[number]
/** The player-bound "my abacus": style (scheme + palette) and form (columns) */
export interface AbacusIdentity {
colorScheme: AbacusColorScheme
colorPalette: AbacusColorPalette
columns: number
}
/** What a player without a saved row shows: the stock abacus */
export const DEFAULT_ABACUS_IDENTITY: AbacusIdentity = {
colorScheme: 'place-value',
colorPalette: 'default',
columns: 4,
}
/** Runtime guard for API input and loose string fields (returns null on any mismatch) */
export function parseAbacusIdentity(input: unknown): AbacusIdentity | null {
if (typeof input !== 'object' || input === null) return null
const { colorScheme, colorPalette, columns } = input as Record<string, unknown>
const scheme = ABACUS_COLOR_SCHEMES.find((s) => s === colorScheme)
const palette = ABACUS_COLOR_PALETTES.find((p) => p === colorPalette)
if (!scheme || !palette) return null
if (typeof columns !== 'number' || !Number.isInteger(columns) || columns < 1 || columns > 21) {
return null
}
return { colorScheme: scheme, colorPalette: palette, columns }
}
|