// Converts a Steam2 id ("STEAM_0:1:12345678", as stored by the plugin) into // a Steam64 id, which is what profile URLs and avatar lookups need. const STEAM64_BASE = 76561197960265728n; export function steam2ToSteam64(steamId2: string): string | null { const match = /^STEAM_[0-5]:([01]):(\d+)$/.exec(steamId2.trim()); if (!match) return null; const y = BigInt(match[1]); const z = BigInt(match[2]); return (STEAM64_BASE + y + z * 2n).toString(); } export function steamProfileUrl(steamId2: string): string | null { const id64 = steam2ToSteam64(steamId2); return id64 ? `https://steamcommunity.com/profiles/${id64}` : null; } // Formats total minutes as "123h 45m" for display. Negative values (which // shouldn't be possible, but have shown up from anomalous underlying data — // e.g. a player_time counter that decreased between two session snapshots) // are shown as "—" rather than a nonsensical negative duration. export function formatMinutes(totalMinutes: number | null): string { if (totalMinutes == null || Number.isNaN(totalMinutes) || totalMinutes < 0) return '—'; const h = Math.floor(totalMinutes / 60); const m = totalMinutes % 60; return `${h}h ${m}m`; } // ISO 3166-1 alpha-2 -> flag emoji, e.g. "DE" -> "🇩🇪". No external assets needed. export function countryCodeToFlag(code: string | null): string { if (!code || code.length !== 2) return '🏳️'; const codePoints = [...code.toUpperCase()].map((c) => 0x1f1a5 + c.charCodeAt(0)); return String.fromCodePoint(...codePoints); } // ISO 3166-1 alpha-2 -> English display name, e.g. "DE" -> "Germany". // Uses the built-in Intl.DisplayNames (Node 14+ / all modern browsers) — // no extra dependency or lookup table needed. const regionNames = new Intl.DisplayNames(['en'], { type: 'region' }); export function countryCodeToName(code: string | null): string { if (!code || code.length !== 2) return 'Unknown'; try { return regionNames.of(code.toUpperCase()) ?? code; } catch { return code; } }