export type BuiltinPlayer = { id: string; name: string; position: string; country: string; filename: string; }; const BUILTIN_PLAYER_FILENAMES = [ '何塞·曼努埃尔·洛佩斯-前锋-阿根廷.jpg', '佩德里-中场-西班牙.jpg', '卢卡·莫德里奇-中场-克罗地亚.jpg', '华金·皮克雷斯-中场-乌拉圭.jpg', '乔治亚·德·阿拉斯凯塔-中场-乌拉圭.jpg', '乌古尔坎·卡基尔-守門員-土耳其.jpg', '亚历杭德罗·曾德哈斯-前锋-美国.jpg', '恩德里克-前锋-巴西.jpg', '克里斯蒂亚诺·罗纳尔多-前锋-葡萄牙.jpg', '克里斯蒂安·罗梅罗-后卫-阿根廷.jpg', '内马尔-前锋-巴西.jpg', '凯南·耶尔德兹-前锋-土耳其.jpg', '卡塞米罗-中场-巴西.jpg', '卢卡斯·帕奎塔-中场-巴西.jpg', '基利安·姆巴佩-前锋-法国.jpg', '孟菲斯·德派-前锋-荷兰.jpg', '奥斯曼·登贝莱-前锋-法国.jpg', '布鲁诺·吉马良斯-中场-巴西.jpg', '布鲁诺·费尔南德斯-中场-葡萄牙.jpg', '布卡约·萨卡-前锋-英格兰.jpg', '德尼兹·居尔-前锋-土耳其.jpg', '德尼兹·温达夫-前锋-德国.jpg', '拉斐尔·迪亚斯·贝洛利-前锋-巴西.jpg', '拉明·亚马尔-前锋-西班牙.jpg', '朱利安·阿尔瓦雷斯-前锋-阿根廷.jpg', '梅西-前锋-阿根廷.jpg', '迈克尔·奥利塞-前锋-法国.jpg', '穆罕默德·萨拉赫-前锋-埃及.jpg', '维尼修斯·儒尼奥尔-前锋-巴西.jpg', '维克托·哲凯赖什-前锋-瑞典.jpg', '圣地亚哥·吉梅内斯-前锋-墨西哥.jpg', '埃德森·阿尔瓦雷斯-后卫-墨西哥.jpg', '埃贝雷奇·埃泽-中场-英格兰.jpg', '埃尔林·哈兰德-前锋-挪威.jpg', '蒂博·库尔图瓦-守門員-比利时.jpg', '曼努埃尔·诺伊尔-守門員-德国.jpg', '祖德·贝林厄姆-中场-英格兰.jpg', '伦纳特·卡尔-中场-德国.jpg', '费德里科·巴尔韦德-中场-乌拉圭.jpg', '贾马尔·慕斯拉-中场-德国.jpg', '路易斯·迪亚斯-前锋-哥伦比亚.jpg', '阿什拉夫·哈基米-后卫-摩洛哥.jpg', '阿利松·贝克尔-守門員-巴西.jpg', '阿尔达·居莱尔-前锋-土耳其.jpg', '马西斯·拉扬·切尔基-中场-法国.jpg', '马库斯·拉什福德-前锋-英格兰.jpg', '哈里·凯恩-前锋-英格兰.jpg', '尼科·威廉斯-前锋-西班牙.jpg', '巴勃罗·加维-中场-西班牙.jpg', '吉列尔莫·奥乔亚-守門員-墨西哥.jpg', ] as const; function parsePlayerFilename(filename: string): BuiltinPlayer { const base = filename.replace(/\.jpg$/i, ''); const parts = base.split('-'); const country = parts.pop() ?? ''; const position = parts.pop() ?? ''; const name = parts.join('-'); return { id: base, name, position, country, filename }; } export const BUILTIN_PLAYERS: BuiltinPlayer[] = BUILTIN_PLAYER_FILENAMES.map(parsePlayerFilename); const AVATAR_KEY_SET = new Set(BUILTIN_PLAYERS.map((p) => p.id)); export function isValidAvatarKey(key: string | null | undefined): boolean { if (!key) return true; return AVATAR_KEY_SET.has(key); } export function playerAvatarUrl(key: string | null | undefined): string | null { if (!key) return null; const player = BUILTIN_PLAYERS.find((p) => p.id === key); if (!player) return null; return `/球员/${player.filename}`; } export function getBuiltinPlayer(key: string | null | undefined): BuiltinPlayer | null { if (!key) return null; return BUILTIN_PLAYERS.find((p) => p.id === key) ?? null; } /** 按 seed 稳定随机,无 seed 时完全随机 */ export function randomAvatarKey(seed?: string | number | null): string { if (!BUILTIN_PLAYERS.length) return ''; if (seed === undefined || seed === null || seed === '') { return BUILTIN_PLAYERS[Math.floor(Math.random() * BUILTIN_PLAYERS.length)].id; } const text = String(seed); let hash = 0; for (let i = 0; i < text.length; i += 1) { hash = (hash * 31 + text.charCodeAt(i)) >>> 0; } return BUILTIN_PLAYERS[hash % BUILTIN_PLAYERS.length].id; }