/** * Player Identifier Management * * Generates and manages a unique player identifier (UUID) that is stored * in localStorage. This identifier is used to sync game states across * different domains (hoerdle.de and hördle.de). */ const STORAGE_KEY = 'hoerdle_player_id'; /** * Generate a UUID v4 */ function generatePlayerId(): string { // UUID v4 format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { const r = Math.random() * 16 | 0; const v = c === 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } /** * Try to find an existing player ID from the backend * * @param genreKey - Genre key to search for * @returns Player ID if found, null otherwise */ async function findExistingPlayerId(genreKey: string): Promise { try { const response = await fetch('/api/player-id/suggest', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ genreKey }), }); if (response.ok) { const data = await response.json(); if (data.playerId) { return data.playerId; } } } catch (error) { console.warn('[playerId] Failed to find existing player ID:', error); } return null; } /** * Get or create a player identifier * * If no identifier exists in localStorage, tries to find an existing one from the backend * (based on recently updated states). If none found, generates a new UUID. * This enables cross-domain synchronization between hoerdle.de and hördle.de. * * @param genreKey - Optional genre key to search for existing player ID * @returns Player identifier (UUID v4) */ export async function getOrCreatePlayerIdAsync(genreKey?: string): Promise { if (typeof window === 'undefined') { // Server-side: return empty string (not used on server) return ''; } let playerId = localStorage.getItem(STORAGE_KEY); if (!playerId) { // Try to find an existing player ID from backend if genreKey is provided if (genreKey) { const existingId = await findExistingPlayerId(genreKey); if (existingId) { playerId = existingId; localStorage.setItem(STORAGE_KEY, playerId); return playerId; } } // Generate new UUID if no existing ID found playerId = generatePlayerId(); localStorage.setItem(STORAGE_KEY, playerId); } return playerId; } /** * Get or create a player identifier (synchronous version) * * This is the legacy synchronous version. For cross-domain sync, use getOrCreatePlayerIdAsync instead. * * @returns Player identifier (UUID v4) */ export function getOrCreatePlayerId(): string { if (typeof window === 'undefined') { // Server-side: return empty string (not used on server) return ''; } let playerId = localStorage.getItem(STORAGE_KEY); if (!playerId) { playerId = generatePlayerId(); localStorage.setItem(STORAGE_KEY, playerId); } return playerId; } /** * Get the current player identifier without creating a new one * * @returns Player identifier or null if not set */ export function getPlayerId(): string | null { if (typeof window === 'undefined') { return null; } return localStorage.getItem(STORAGE_KEY); }