// Game variants offered on New Game, and the gating of that choice by the // languages the sign-in service supports. Kept out of the .svelte screen so the // gating is unit-testable (the project's node-env Vitest layer). import type { MessageKey } from './i18n/index.svelte'; import type { Variant } from './model'; // VariantOption is a selectable game variant with its i18n label key. export interface VariantOption { id: Variant; label: MessageKey; } // ALL_VARIANTS lists every variant in display order. The labels are display names keyed by // the game's alphabet, not the interface language: the English-alphabet game is always // "Scrabble" and the Russian-alphabet Scrabble always "Скрэббл" (both unlocalized, so the // two never collide whatever the UI language); Erudit is localized "Erudite"/"Эрудит". export const ALL_VARIANTS: VariantOption[] = [ { id: 'scrabble_en', label: 'new.english' }, { id: 'scrabble_ru', label: 'new.russian' }, { id: 'erudit_ru', label: 'new.erudit' }, ]; // variantNameKey returns the i18n key for a variant's display name (used by the in-game // title and the lobby cards). export function variantNameKey(v: Variant): MessageKey { return ALL_VARIANTS.find((o) => o.id === v)?.label ?? 'new.english'; } // VARIANT_RULES is the i18n key for each variant's one-line rules summary on the New Game // buttons (bag size, the ё rule, bonus differences), sourced from the engine rulesets. export const VARIANT_RULES: Record = { scrabble_en: 'new.rulesEnglish', scrabble_ru: 'new.rulesRussian', erudit_ru: 'new.rulesErudit', }; // VARIANT_FLAG is the flag shown on a variant button: an emoji for the Scrabble variants; // Erudit uses the bundled USSR flag SVG (public/flag-ussr.svg), so its entry is empty. export const VARIANT_FLAG: Record = { scrabble_en: '🇺🇸', scrabble_ru: '🇷🇺', erudit_ru: '', }; // VARIANT_LANGUAGE maps each variant to its game language. en -> English; // ru -> Russian + Эрудит. export const VARIANT_LANGUAGE: Record = { scrabble_en: 'en', scrabble_ru: 'ru', erudit_ru: 'ru' }; // availableVariants gates ALL_VARIANTS by the session's supported languages. An empty // or absent set is ungated (a web/legacy session without a declared set), returning // every variant. export function availableVariants(supportedLanguages: string[] | undefined): VariantOption[] { const langs = supportedLanguages ?? []; if (langs.length === 0) return ALL_VARIANTS; return ALL_VARIANTS.filter((v) => langs.includes(VARIANT_LANGUAGE[v.id])); } // supportsMultipleWordsToggle reports whether the New Game "multiple words per turn" toggle // applies to a variant. Only Russian games choose the rule; English is always standard, so // its toggle is not shown. export function supportsMultipleWordsToggle(v: Variant): boolean { return VARIANT_LANGUAGE[v] === 'ru'; } // multipleWordsForRequest resolves the per-turn word rule sent when starting a game of the // variant: Russian games carry the toggle's value, English games are silently standard // (true), so matchmaking and game creation stay one uniform path. export function multipleWordsForRequest(v: Variant, toggle: boolean): boolean { return supportsMultipleWordsToggle(v) ? toggle : true; }