/** * Precomputed character pair and trio affinity. */ export interface Affinity { /** * First character in the relation. */ chara_a: number; /** * Second character in the relation. * chara_a < chara_b is an invariant. */ chara_b: number; /** * Third character in the relation, if it is a trio relation. * If defined, chara_b < chara_c is an invariant. */ chara_c?: number; /** * Total base compatibility between characters in the relation. */ affinity: number; } export async function affinity(): Promise { const resp = await fetch('/api/global/affinity'); return resp.json(); } export function lookup(aff: Affinity[], chara_a: number, chara_b: number, chara_c?: number): number { const [a, b, c] = [chara_a, chara_b, chara_c ?? Infinity].sort((a, b) => a - b); const r = aff.find((v) => v.chara_a === a && v.chara_b === b && (v.chara_c ?? Infinity) === c); return r?.affinity ?? 0; } /** * Individual affinity entry. */ export interface AffinityDetail { /** Character to which the entry applies. */ chara_id: number; /** Succession relation that the character has. */ relation: number; /** Value of the succession relation. */ affinity: number; } export async function affinityDetail(): Promise { const resp = await fetch('/api/global/affinity-detail'); return resp.json(); } export interface AffinityRelationDescription { name: string; note?: string; } export const AFFINITY_RELATION_DESCRIPTIONS = new Map([ [2001, { name: 'Shared Parent', note: 'Sunday Silence' }], [2002, { name: 'Shared Parent', note: 'Tony Bin' }], [2003, { name: 'Shared Parent', note: 'Sakura Yutaka O' }], [2004, { name: 'Shared Parent', note: 'Mejiro Ryan' }], [2005, { name: 'Shared Parent' }], [2006, { name: 'Shared Parent' }], [2007, { name: 'Shared Parent', note: 'Symboli Rudolf' }], [2008, { name: 'Shared Parent', note: 'Tosho Boy' }], [2009, { name: 'Shared Parent', note: "Brian's Time" }], [2010, { name: 'Shared Parent', note: 'Gold Allure' }], [2011, { name: 'Shared Parent', note: 'Soccer Boy' }], [2101, { name: 'Shared Grandparent', note: 'Sunday Silence (grandsire)' }], [2102, { name: 'Shared Grandparent', note: 'Maruzensky (damsire)' }], [2103, { name: 'Shared Grandparent', note: 'Roberto (grandsire)' }], [2104, { name: 'Shared Grandparent', note: 'Blushing Groom (damsire)' }], [2105, { name: 'Shared Grandparent', note: 'Tesco Boy (damsire)' }], [2106, { name: 'Shared Grandparent', note: 'Northern Taste (damsire)' }], [2107, { name: 'Shared Grandparent', note: 'Royal Ski (damsire)' }], [2108, { name: 'Shared Grandparent', note: 'Never Beat (damsire)' }], [2109, { name: 'Shared Grandparent', note: 'Affirmed (damsire)' }], [2110, { name: 'Shared Grandparent', note: 'Sancy (damsire)' }], [2111, { name: 'Shared Grandparent', note: 'Last Tycoon (grandsire)' }], [2201, { name: 'Parent/Child' }], [2202, { name: 'Parent/Child' }], [2203, { name: 'Grandparent/Grandchild' }], [2204, { name: 'Parent/Child' }], [2205, { name: 'Grandparent/Grandchild' }], [2206, { name: 'Parent/Child' }], [2208, { name: 'Parent/Child' }], [2209, { name: 'Parent/Child' }], [2210, { name: 'Parent/Child' }], [2211, { name: 'Grandparent/Grandchild' }], [2212, { name: 'Parent/Child' }], [2213, { name: 'Parent/Child' }], [2214, { name: 'Grandparent/Grandchild' }], [2215, { name: 'Grandparent/Grandchild' }], [2216, { name: 'Grandparent/Grandchild' }], [2217, { name: 'Grandparent/Grandchild' }], [2218, { name: 'Parent/Child' }], [2301, { name: 'Grandparent/Grandchild' }], [2302, { name: 'Grandparent/Grandchild' }], [2303, { name: 'Grandparent/Grandchild' }], [2401, { name: 'Racing Generation', note: 'Pre-1980' }], [2402, { name: 'Racing Generation', note: '1983-86' }], [2403, { name: 'Racing Generation', note: '1987-90' }], [2404, { name: 'Racing Generation', note: '1990-93' }], [2405, { name: 'Racing Generation', note: '1995-97' }], [2406, { name: 'Racing Generation', note: '1997-99' }], [2407, { name: 'Racing Generation', note: '1998-2004' }], [2408, { name: 'Racing Generation', note: '2001-04' }], [2409, { name: 'Racing Generation', note: '2006-10' }], [2410, { name: 'Racing Generation' }], [2411, { name: 'Racing Generation' }], [2412, { name: 'Racing Generation' }], [2413, { name: 'Racing Generation' }], [2501, { name: 'G1 Winner', note: 'February Stakes' }], [2502, { name: 'G1 Winner', note: 'Takamatsunomiya Kinen' }], [2503, { name: 'G1 Winner', note: 'Osaka Hai' }], [2504, { name: 'G1 Winner', note: 'Oka Sho' }], [2505, { name: 'G1 Winner', note: 'Satsuki Sho' }], [2506, { name: 'G1 Winner', note: 'Tenno Sho (Spring)' }], [2507, { name: 'G1 Winner', note: 'NHK Mile Cup' }], [2508, { name: 'G1 Winner', note: 'Victoria Mile' }], [2509, { name: 'G1 Winner', note: 'Japanese Oaks' }], [2510, { name: 'G1 Winner', note: 'Tokyo Yushun (Japanese Derby)' }], [2511, { name: 'G1 Winner', note: 'Yasuda Kinen' }], [2512, { name: 'G1 Winner', note: 'Takarazuka Kinen' }], [2513, { name: 'G1 Winner', note: 'Sprinters Stakes' }], [2514, { name: 'G1 Winner', note: 'Shuka Sho' }], [2515, { name: 'G1 Winner', note: 'Kikuka Sho' }], [2516, { name: 'G1 Winner', note: 'Tenno Sho (Autumn)' }], [2517, { name: 'G1 Winner', note: 'Queen Elizabeth II Cup' }], [2518, { name: 'G1 Winner', note: 'Mile Championship' }], [2519, { name: 'G1 Winner', note: 'Japan Cup' }], [2520, { name: 'G1 Winner', note: 'Champions Cup' }], [2521, { name: 'G1 Winner', note: 'Hanshin Juvenile Fillies' }], [2522, { name: 'G1 Winner', note: 'Asahi Hai Futurity Stakes' }], [2523, { name: 'G1 Winner', note: 'Arima Kinen' }], [2524, { name: 'G1 Winner', note: 'Hopeful Stakes' }], [2525, { name: 'G1 Winner', note: 'Teio Sho' }], [2526, { name: 'G1 Winner', note: 'Japan Dirt Derby' }], [2527, { name: 'G1 Winner', note: 'JBC Ladies’ Classic' }], [2528, { name: 'G1 Winner', note: 'JBC Sprint' }], [2529, { name: 'G1 Winner', note: 'JBC Classic' }], [2530, { name: 'G1 Winner', note: 'Tokyo Daishoten' }], [2531, { name: 'G1 Winner', note: 'Kawasaki Kinen' }], [2532, { name: 'G1 Winner', note: 'Mile Championship Nambu Hai' }], [2533, { name: 'G1 Winner', note: 'Kashiwa Kinen' }], [2534, { name: 'G1 Winner', note: 'Zen-Nippon Junior Yushun' }], [2601, { name: 'Stallion' }], [2602, { name: 'Mare' }], [2702, { name: '7 G1 + Triple Crown winner' }], [2801, { name: 'Classic Year', note: '1986' }], [2802, { name: 'Classic Year', note: '1987' }], [2803, { name: 'Classic Year', note: '1990' }], [2804, { name: 'Classic Year', note: '1991' }], [2805, { name: 'Classic Year', note: '1992' }], [2806, { name: 'Classic Year', note: '1993' }], [2807, { name: 'Classic Year', note: '1994' }], [2808, { name: 'Classic Year', note: '1995' }], [2809, { name: 'Classic Year', note: '1996' }], [2810, { name: 'Classic Year', note: '1997' }], [2811, { name: 'Classic Year', note: '1998' }], [2812, { name: 'Classic Year', note: '1999' }], [2813, { name: 'Classic Year', note: '2000' }], [2814, { name: 'Classic Year', note: '2001' }], [2815, { name: 'Classic Year', note: '2007' }], [2816, { name: 'Classic Year', note: '2009' }], [2817, { name: 'Classic Year', note: '2010' }], [2818, { name: 'Classic Year' }], [2819, { name: 'Classic Year' }], [2820, { name: 'Classic Year' }], [2821, { name: 'Classic Year' }], [2822, { name: 'Classic Year', note: '2002' }], [2823, { name: 'Classic Year' }], [2824, { name: 'Classic Year' }], [2825, { name: 'Classic Year' }], [2826, { name: 'Classic Year' }], [2827, { name: 'Classic Year' }], [2828, { name: 'Classic Year' }], [2829, { name: 'Classic Year' }], [2830, { name: 'Classic Year' }], [2831, { name: 'Classic Year' }], [2832, { name: 'Classic Year' }], [2833, { name: 'Classic Year' }], [3201, { name: 'Birth Month', note: 'January' }], [3202, { name: 'Birth Month', note: 'February' }], [3203, { name: 'Birth Month', note: 'March' }], [3204, { name: 'Birth Month', note: 'April' }], [3205, { name: 'Birth Month', note: 'May' }], [3206, { name: 'Birth Month', note: 'June' }], [3301, { name: 'No G1 Wins' }], [3501, { name: 'Classic Triple Crown Runner' }], [3502, { name: 'Triple Tiara Runner' }], [3503, { name: 'Spring Triple Crown Runner' }], [3504, { name: 'Autumn Triple Crown Runner' }], [101, { name: 'Tracen Class' }], [102, { name: 'Tracen Class' }], [103, { name: 'Tracen Class' }], [104, { name: 'Tracen Class' }], [105, { name: 'Tracen Class' }], [106, { name: 'Tracen Class' }], [107, { name: 'Tracen Class' }], [201, { name: 'Residence', note: 'Miho Dorm' }], [202, { name: 'Residence', note: 'Ritto Dorm' }], [203, { name: 'Residence', note: 'Lives Alone' }], [204, { name: 'Residence' }], [205, { name: 'Residence', note: 'Not In Dorm' }], [301, { name: 'Roommate' }], [302, { name: 'Roommate' }], [303, { name: 'Roommate' }], [304, { name: 'Roommate' }], [305, { name: 'Roommate' }], [306, { name: 'Roommate' }], [307, { name: 'Roommate' }], [308, { name: 'Roommate' }], [309, { name: 'Roommate' }], [310, { name: 'Roommate' }], [311, { name: 'Roommate' }], [312, { name: 'Roommate' }], [313, { name: 'Roommate' }], [314, { name: 'Roommate' }], [315, { name: 'Roommate' }], [316, { name: 'Roommate' }], [317, { name: 'Roommate' }], [318, { name: 'Roommate' }], [319, { name: 'Roommate' }], [320, { name: 'Roommate' }], [321, { name: 'Roommate' }], [322, { name: 'Roommate' }], [323, { name: 'Roommate' }], [324, { name: 'Roommate' }], [325, { name: 'Roommate' }], [326, { name: 'Roommate' }], [327, { name: 'Roommate' }], [328, { name: 'Roommate' }], [329, { name: 'Roommate' }], [330, { name: 'Roommate' }], [331, { name: 'Roommate' }], [332, { name: 'Roommate' }], [333, { name: 'Roommate' }], [334, { name: 'Roommate' }], [335, { name: 'Roommate' }], [336, { name: 'Roommate' }], [337, { name: 'Roommate' }], [338, { name: 'Roommate' }], [339, { name: 'Roommate' }], [340, { name: 'Roommate' }], [341, { name: 'Roommate' }], [342, { name: 'Roommate' }], [343, { name: 'Roommate' }], [344, { name: 'Roommate' }], [345, { name: 'Roommate' }], [346, { name: 'Roommate' }], [347, { name: 'Roommate' }], [348, { name: 'Roommate' }], [349, { name: 'Roommate' }], [350, { name: 'Roommate' }], [351, { name: 'Roommate' }], [352, { name: 'Roommate' }], [353, { name: 'Roommate' }], [354, { name: 'Roommate' }], [355, { name: 'Roommate' }], [356, { name: 'Roommate' }], [357, { name: 'Roommate' }], [358, { name: 'Roommate' }], [359, { name: 'Roommate' }], [360, { name: 'Roommate' }], [361, { name: 'Roommate' }], [362, { name: 'Roommate' }], [363, { name: 'Roommate' }], [364, { name: 'Roommate' }], [365, { name: 'Roommate' }], [366, { name: 'Roommate' }], [367, { name: 'Roommate' }], [368, { name: 'Roommate' }], [369, { name: 'Roommate' }], [370, { name: 'Roommate' }], [371, { name: 'Roommate' }], [372, { name: 'Roommate' }], [373, { name: 'Roommate' }], [374, { name: 'Roommate' }], [375, { name: 'Roommate' }], [376, { name: 'Roommate' }], [377, { name: 'Roommate' }], [378, { name: 'Roommate' }], [379, { name: 'Roommate' }], [380, { name: 'Roommate' }], [381, { name: 'Roommate' }], [382, { name: 'Roommate' }], [383, { name: 'Roommate' }], [384, { name: 'Roommate' }], [385, { name: 'Roommate' }], [386, { name: 'Roommate' }], [387, { name: 'Roommate' }], [388, { name: 'Roommate' }], [401, { name: 'Clique', note: 'Golden Generation' }], [402, { name: 'Clique' }], [403, { name: 'Clique' }], [404, { name: 'Clique' }], [405, { name: 'Clique' }], [406, { name: 'Clique', note: 'Old People' }], [407, { name: 'Clique' }], [408, { name: 'Clique' }], [409, { name: 'Clique' }], [410, { name: 'Clique' }], [411, { name: 'Clique' }], [412, { name: 'Clique' }], [413, { name: 'Clique' }], [414, { name: 'Clique' }], [415, { name: 'Clique' }], [416, { name: 'Clique' }], [417, { name: 'Clique' }], [418, { name: 'Clique' }], [419, { name: 'Clique' }], [420, { name: 'Clique' }], [421, { name: 'Clique' }], [422, { name: 'Clique' }], [423, { name: 'Clique' }], [424, { name: 'Clique' }], [501, { name: 'Story Group', note: 'Student Council' }], [502, { name: 'Story Group', note: 'Golden Generation' }], [503, { name: 'Story Group', note: 'Mejiro Family' }], [504, { name: 'Story Group', note: 'Rich People' }], [505, { name: 'Story Group', note: 'Dorm Leaders' }], [506, { name: 'Story Group', note: 'Heisei Big Three' }], [507, { name: 'Story Group', note: 'BNW' }], [511, { name: 'Story Group', note: '"Sakura"' }], [512, { name: 'Story Group' }], [513, { name: 'Story Group', note: 'Team Canopus' }], [514, { name: 'Story Group', note: 'Runaway Bakas' }], [515, { name: 'Story Group', note: 'Kita and Dia' }], [516, { name: 'Story Group', note: 'McQueen and Dia' }], [517, { name: 'Story Group', note: 'Teio and Kitasan' }], [518, { name: 'Story Group', note: 'Notable Front Runners' }], [519, { name: 'Story Group' }], [520, { name: 'Story Group', note: 'Notable Dirt Runners' }], [521, { name: 'Story Group' }], [522, { name: 'Story Group', note: 'Satono Family' }], [523, { name: 'Story Group', note: 'Team Sirius' }], [524, { name: 'Story Group', note: 'Team Rigil' }], [525, { name: 'Story Group', note: 'Team Spica' }], [526, { name: 'Story Group', note: 'Notable Runaways' }], [3505, { name: 'Ran on Dirt' }], [3506, { name: 'Overseas' }], [3508, { name: 'Ran a Sprint' }], [2901, { name: 'Strategy', note: 'Front Runner' }], [2902, { name: 'Strategy', note: 'Pace Chaser' }], [2903, { name: 'Strategy', note: 'Late Surger' }], [2904, { name: 'Strategy', note: 'End Closer' }], [3001, { name: 'Distance', note: 'Sprint' }], [3002, { name: 'Distance', note: 'Mile' }], [3003, { name: 'Distance', note: 'Medium' }], [3004, { name: 'Distance', note: 'Long' }], [3101, { name: 'Surface', note: 'Turf' }], [3102, { name: 'Surface', note: 'Dirt' }], [508, { name: 'Haru Urara', note: 'Haru Urara' }], [509, { name: 'Haru Urara', note: 'Haru Urara' }], [510, { name: 'Haru Urara', note: 'Haru Urara' }], [527, { name: 'Haru Urara', note: 'Haru Urara' }], [528, { name: 'Haru Urara', note: 'Haru Urara' }], [529, { name: 'Haru Urara', note: 'Haru Urara' }], [530, { name: 'Haru Urara', note: 'Haru Urara' }], [531, { name: 'Haru Urara', note: 'Haru Urara' }], [532, { name: 'Haru Urara', note: 'Haru Urara' }], [533, { name: 'Haru Urara', note: 'Haru Urara' }], [534, { name: 'Haru Urara', note: 'Haru Urara' }], [535, { name: 'Haru Urara', note: 'Haru Urara' }], [536, { name: 'Haru Urara', note: 'Haru Urara' }], [537, { name: 'Haru Urara', note: 'Haru Urara' }], [538, { name: 'Haru Urara', note: 'Haru Urara' }], [539, { name: 'Haru Urara', note: 'Haru Urara' }], [540, { name: 'Haru Urara', note: 'Haru Urara' }], [541, { name: 'Haru Urara', note: 'Haru Urara' }], [542, { name: 'Haru Urara', note: 'Haru Urara' }], [543, { name: 'Haru Urara', note: 'Haru Urara' }], [544, { name: 'Haru Urara', note: 'Haru Urara' }], [545, { name: 'Haru Urara', note: 'Haru Urara' }], [546, { name: 'Haru Urara', note: 'Haru Urara' }], [547, { name: 'Haru Urara', note: 'Haru Urara' }], [548, { name: 'Haru Urara', note: 'Haru Urara' }], [549, { name: 'Haru Urara', note: 'Haru Urara' }], [550, { name: 'Haru Urara', note: 'Haru Urara' }], [551, { name: 'Haru Urara', note: 'Haru Urara' }], ]);