98 lines
5.6 KiB
Plaintext
98 lines
5.6 KiB
Plaintext
|
|
Elo Rating System
|
|||
|
|
AI Handoff Specification <20> Hallucinate Game
|
|||
|
|
|
|||
|
|
1. B?i c?nh & M?c ti<74>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<74>n m<>n h<>nh Profile v<> ?i?u ph?i matchmaking.
|
|||
|
|
|
|||
|
|
Y<EFBFBD>u c?u c?t l<>i:
|
|||
|
|
<EFBFBD> T<>nh to<74>n Elo sau m?i tr?n 1v1 ho<68>n th<74>nh
|
|||
|
|
<EFBFBD> K-factor ??ng theo s? tr?n v<> rating hi?n t?i
|
|||
|
|
<EFBFBD> Persist rating l<>n server (kh<6B>ng ?? client t? t<>nh)
|
|||
|
|
<EFBFBD> Tr? v? rating m?i cho c? 2 ng??i ch?i sau tr?n
|
|||
|
|
<EFBFBD> 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 ?<3F> Result: Th?ng = 1.0 | Thua = 0.0 | H<>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 <20> thay ??i nhi?u h?n
1200 ? Rating < 2000
24
Tier trung b<>nh <20> c<>n b?ng
Rating ? 2000
16
Tier cao <20> ?n ??nh, thay ??i ch?m
|
|||
|
|
2.4. V<> d? t<>nh to<74>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 <20> (UI)
Iron
< 800
#8A8A8A
Bronze
800 <20> 999
#CD7F32
Silver
1000 <20> 1199
#C0C0C0
Gold
1200 <20> 1499
#FFD700
Platinum
1500 <20> 1799
#4DC8A0
Diamond
1800 <20> 2099
#7B6EE8
Master
? 2100
#E84D8A
|
|||
|
|
Rating kh?i ??u (m?c ??nh): 1000. Rating s<>n (floor): 100 <20> kh<6B>ng xu?ng d??i gi<67> tr? n<>y.
|
|||
|
|
|
|||
|
|
4. Placement Matches
|
|||
|
|
<EFBFBD> 30 tr?n ??u ti<74>n l<> Placement Period (gamesPlayed < 30)
|
|||
|
|
<EFBFBD> K = 40 trong giai ?o?n n<>y ?? rating h?i t? nhanh v? ?<3F>ng v? tr<74>
|
|||
|
|
<EFBFBD> T<>y ch?n: kh<6B>ng hi?n th? rank badge trong 30 tr?n ??u, ch? hi?n th? '?' ho?c 'Unranked'
|
|||
|
|
<EFBFBD> Sau tr?n 30, K-factor chuy?n sang b?ng ??ng ? m?c 2.3
|
|||
|
|
|
|||
|
|
5. Ki?n tr<74>c & Lu?ng d? li?u
|
|||
|
|
5.1. Nguy<75>n t?c quan tr?ng
|
|||
|
|
KH<EFBFBD>NG ?? client t? t<>nh Elo r?i g?i l<>n. Ph?i t<>nh tr<74>n Host/Server ?? tr<74>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<74>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<74>
Tr<54>ch nhi?m
EloSystem.cs
/Assets/Scripts/Game/
Pure static class <20> c<>ng th?c Elo, kh<6B>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/
?<3F> c<> <20> th<74>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 <20> th<74>m h<>m
|
|||
|
|
public void UpdateEloDisplay(int newRating, int delta) {
|
|||
|
|
root.Q<Label>("EloLabel").text = newRating.ToString();
|
|||
|
|
root.Q<Label>("EloDelta").text = (delta >= 0 ? "+" : "") + delta;
|
|||
|
|
root.Q<Label>("RankLabel").text = EloSystem.GetRank(newRating);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
7. T<>ch h?p v<>o Profile UI
|
|||
|
|
C<EFBFBD>c element UXML c?n c<> trong Profile.uxml:
|
|||
|
|
Element Name
Type
Hi?n th?
EloLabel
Label
Rating hi?n t?i, VD: 1504
EloDelta
Label
Thay ??i sau tr?n, VD: +12 ho?c -8 (m<>u xanh/??)
RankLabel
Label
T<>n rank, VD: Gold
WinRateBar
ProgressBar
value = winRate (0.0 - 1.0)
WinRateText
Label
VD: 58.3%
GamesPlayed
Label
T?ng s? tr?n
|
|||
|
|
CSS class g?i <20> cho EloDelta:
|
|||
|
|
.elo-delta-positive { color: #4DC8A0; } /* teal <20> th?ng */
|
|||
|
|
.elo-delta-negative { color: #E84D8A; } /* h?ng <20> thua */
|
|||
|
|
|
|||
|
|
8. Checklist tri?n khai
|
|||
|
|
#
Task
File li<6C>n quan
Done?
1
T?o EloSystem.cs v?i Calculate() v<> GetRank()
EloSystem.cs
[ ]
2
T?o EloResult struct
EloData.cs
[ ]
3
Th<54>m RPC g?i k?t qu? tr?n l<>n Host
MatchResultRPC.cs
[ ]
4
Host g?i EloSystem.Calculate() sau khi nh?n RPC
MatchResultRPC.cs
[ ]
5
Persist rating l<>n backend
Backend / Cloud Save
[ ]
6
Host broadcast EloResult v? client qua RPC
MatchResultRPC.cs
[ ]
7
ProfileController.UpdateEloDisplay() nh?n data m?i
ProfileController.cs
[ ]
8
Th<54>m c<>c UXML element v<>o Profile.uxml
Profile.uxml
[ ]
9
Style EloDelta (xanh/??) trong Global.uss
Global.uss
[ ]
10
Unit test EloSystem v?i c<>c tr??ng h?p bi<62>n
Test/
[ ]
|
|||
|
|
9. L?u <20> & Edge Cases
|
|||
|
|
<EFBFBD> Tr?n b? disconnect gi?a ch?ng: kh<6B>ng t<>nh Elo, ho?c t<>nh thua cho b<>n disconnect (quy?t ??nh t<>y game design)
|
|||
|
|
<EFBFBD> Tr?n qu<71> ng?n (< X gi<67>y): c<> th? b? qua ?? tr<74>nh farming/griefing
|
|||
|
|
<EFBFBD> Rating floor = 100: Mathf.Max(100, newRating) <20> ?<3F> c<> trong spec
|
|||
|
|
<EFBFBD> Kh<4B>ng c<> rating cap (ceiling) <20> Master+ ti?p t?c t?ng v<> h?n
|
|||
|
|
<EFBFBD> H<>a (draw): resultA = 0.5f <20> game c?n quy?t ??nh c<> h? tr? kh<6B>ng
|
|||
|
|
<EFBFBD> Backend sync: l?u c? gamesPlayed c<>ng v?i rating ?? K-factor t<>nh ?<3F>ng
|