Files
noitu/web/src/lib/room-code.js
T
tiennm99 90cd679639 feat(web): state the rules, reach the chat from the top of the board, lint the tree
A /rules page says, in one place, what nothing in the app said before:
the chain rule, the clock, what a dead end costs, elimination and the last
player standing, how a word is scored and the reconnect window. Linked
from the landing page and from the board and lobby headers.

The chat control moves above the chain as a pill with the unread count,
where it can be reached on a phone mid-game, and the lobby's folded chat
now carries an unread badge too.

ESLint with the Svelte and JSDoc plugins, run in CI; the real findings
it turned up (missing each keys, untyped timer handles) are fixed.
2026-09-21 01:17:52 +07:00

53 lines
1.8 KiB
JavaScript

/**
* Room codes as the client has to handle them: typed by hand, or pasted from a
* chat message.
*
* The alphabet mirrors the server's. It omits 0/O and 1/I/L because those are
* the pairs people get wrong when reading a code out. A test checks this
* against the Go constant rather than trusting the copy.
*/
export const ROOM_CODE_ALPHABET = '23456789ABCDEFGHJKMNPQRSTUVWXYZ';
export const ROOM_CODE_LENGTH = 6;
/** Pulls the code out of a pasted invite link. */
const LINK_CODE = /[?&]code=([^&#\s]+)/i;
/** Separators people put inside or around a code when writing it down. */
const SEPARATORS = /[\s._-]+/g;
/**
* Turns whatever arrived into what the server would recognise.
*
* Two shapes are worth handling, because they are the two ways a code reaches
* a player: the code itself, in any case and spaced or hyphenated for reading,
* and a whole invite link pasted from a message.
*
* Only separators are removed. Dropping every character outside the alphabet
* instead would turn any sentence into six plausible letters, and the player
* would be told the room does not exist rather than that they pasted the wrong
* thing.
* @param {string} raw
* @returns {string}
*/
export function normalizeRoomCode(raw) {
const text = String(raw ?? '').trim();
const link = text.match(LINK_CODE);
const source = link ? link[1] : text;
return source.replace(SEPARATORS, '').toUpperCase();
}
/**
* Whether a normalized code is worth sending. Checking here saves a round trip
* and, more usefully, tells the player which of the two failures they have:
* a malformed code, or a room that is not there.
* @param {string} code
* @returns {boolean}
*/
export function isRoomCode(code) {
return (
code.length === ROOM_CODE_LENGTH && [...code].every((ch) => ROOM_CODE_ALPHABET.includes(ch))
);
}