Elo Rating System AI Handoff Specification — Hallucinate Game 1. B?i c?nh & M?c tiêu Game Hallucinate là game PvP online 1v1 (real-time), dùng Photon Fusion / Unity Relay làm backend m?ng. H? th?ng Elo ???c yêu c?u ?? x?p h?ng ng??i ch?i sau m?i tr?n solo, hi?n th? trên màn h́nh Profile và ?i?u ph?i matchmaking. Yêu c?u c?t lơi: • Tính toán Elo sau m?i tr?n 1v1 hoàn thành • K-factor ??ng theo s? tr?n và rating hi?n t?i • Persist rating lên server (không ?? client t? tính) • Tr? v? rating m?i cho c? 2 ng??i ch?i sau tr?n • Hi?n th? lên ProfileController.cs qua data binding 2. Công th?c Elo 2.1. Expected Score E(A) = 1 / (1 + 10 ^ ((RatingB - RatingA) / 400)) E(B) = 1 - E(A) 2.2. Rating m?i NewRating(A) = OldRating(A) + K * (Result - E(A)) Trong ?ó Result: Th?ng = 1.0 | Thua = 0.0 | Ḥa = 0.5 2.3. K-Factor ??ng ?i?u ki?n K Value Lư do D??i 30 tr?n (Placement) 40 Rating ch?a ?n ??nh, c?n h?i t? nhanh Rating < 1200 32 Tier th?p — thay ??i nhi?u h?n 1200 ? Rating < 2000 24 Tier trung b́nh — cân b?ng Rating ? 2000 16 Tier cao — ?n ??nh, thay ??i ch?m 2.4. Ví d? tính toán A (1500) vs B (1200), A th?ng: E(A) = 1 / (1 + 10^((1200-1500)/400)) = 0.849 E(B) = 0.151 NewRating(A) = 1500 + 24*(1 - 0.849) = 1500 + 3.6 ? 1504 NewRating(B) = 1200 + 32*(0 - 0.151) = 1200 - 4.8 ? 1195 3. Rank Tiers Rank Rating Range Màu g?i ư (UI) Iron < 800 #8A8A8A Bronze 800 – 999 #CD7F32 Silver 1000 – 1199 #C0C0C0 Gold 1200 – 1499 #FFD700 Platinum 1500 – 1799 #4DC8A0 Diamond 1800 – 2099 #7B6EE8 Master ? 2100 #E84D8A Rating kh?i ??u (m?c ??nh): 1000. Rating sàn (floor): 100 — không xu?ng d??i giá tr? này. 4. Placement Matches • 30 tr?n ??u tiên là Placement Period (gamesPlayed < 30) • K = 40 trong giai ?o?n này ?? rating h?i t? nhanh v? ?úng v? trí • Tùy ch?n: không hi?n th? rank badge trong 30 tr?n ??u, ch? hi?n th? '?' ho?c 'Unranked' • Sau tr?n 30, K-factor chuy?n sang b?ng ??ng ? m?c 2.3 5. Ki?n trúc & Lu?ng d? li?u 5.1. Nguyên t?c quan tr?ng KHÔNG ?? client t? tính Elo r?i g?i lên. Ph?i tính trên Host/Server ?? tránh cheat. 5.2. Lu?ng x? lư B??c Th?c hi?n b?i Mô t? 1 Client A & B Tr?n k?t thúc, g?i k?t qu? lên Host qua RPC 2 Host (Photon Fusion) Nh?n k?t qu?, xác minh h?p l? 3 Host G?i EloSystem.Calculate() v?i rating c?a 2 ng??i 4 Host ? Backend G?i rating m?i lên server (UGS / Photon Cloud / custom) 5 Backend Persist vào database, tr? v? k?t qu? 6 Host ? Client Broadcast rating m?i v? cho c? 2 client qua RPC 7 Client ProfileController c?p nh?t UI v?i rating m?i 5.3. File c?n t?o File V? trí Trách nhi?m EloSystem.cs /Assets/Scripts/Game/ Pure static class — công th?c Elo, không dependency EloData.cs /Assets/Scripts/Game/ Struct/class l?u RatingResult (newRatingA, newRatingB, delta) MatchResultRPC.cs /Assets/Scripts/Network/ Photon RPC g?i/nh?n k?t qu? tr?n ProfileController.cs /Assets/Scripts/UI/ ?ă có — thêm hàm UpdateEloDisplay(int newRating, int delta) 6. C# Implementation Spec 6.1. EloSystem.cs public static class EloSystem { public static EloResult Calculate( int ratingA, int ratingB, int gamesPlayedA, int gamesPlayedB, float resultA) // 1=win, 0=lose, 0.5=draw { float eA = 1f / (1f + Mathf.Pow(10f, (ratingB - ratingA) / 400f)); int kA = GetK(ratingA, gamesPlayedA); int kB = GetK(ratingB, gamesPlayedB); int nA = Mathf.Max(100, Mathf.RoundToInt(ratingA + kA * (resultA - eA))); int nB = Mathf.Max(100, Mathf.RoundToInt(ratingB + kB * ((1-resultA) - (1-eA)))); return new EloResult(nA, nB, nA - ratingA, nB - ratingB); } private static int GetK(int r, int g) => g < 30 ? 40 : r < 1200 ? 32 : r < 2000 ? 24 : 16; } 6.2. EloResult struct public readonly struct EloResult { public int NewRatingA, NewRatingB, DeltaA, DeltaB; // Constructor... } 6.3. ProfileController — thêm hàm public void UpdateEloDisplay(int newRating, int delta) { root.Q