Skip to content
Browse files

Core/Arena: A more accurate implementation of rating gain/loss. This …

…fixes the strange behaviour personal rating could have, as well as implements the bigger rating scale added in patch 3.1.

Fixes #230
  • Loading branch information...
1 parent b2d3706 commit 6cfb87639cbceee3a182a0431d8b789193228802 @tbaart tbaart committed Jul 30, 2011
View
91 src/server/game/Battlegrounds/ArenaTeam.cpp
@@ -606,43 +606,59 @@ float ArenaTeam::GetChanceAgainst(uint32 ownRating, uint32 opponentRating)
{
// Returns the chance to win against a team with the given rating, used in the rating adjustment calculation
// ELO system
- return 1.0f / (1.0f + exp(log(10.0f) * (float)((float)opponentRating - (float)ownRating) / 400.0f));
+ return 1.0f / (1.0f + exp(log(10.0f) * (float)((float)opponentRating - (float)ownRating) / 650.0f));
}
-int32 ArenaTeam::GetRatingMod(uint32 ownRating, uint32 opponentRating, bool won, bool calculateMatchMakerRating)
+int32 ArenaTeam::GetMatchmakerRatingMod(uint32 ownRating, uint32 opponentRating, bool won /*, float& confidence_factor*/)
{
// 'Chance' calculation - to beat the opponent
+ // This is a simulation. Not much info on how it really works
+ float chance = GetChanceAgainst(ownRating, opponentRating);
+ float won_mod = (won) ? 1.0f : 0.0f;
+ float mod = won_mod - chance;
+
+ // Work in progress:
+ /*
+ // This is a simulation, as there is not much info on how it really works
+ float confidence_mod = min(1.0f - fabs(mod), 0.5f);
+
+ // Apply confidence factor to the mod:
+ mod *= confidence_factor
+
+ // And only after that update the new confidence factor
+ confidence_factor -= ((confidence_factor - 1.0f) * confidence_mod) / confidence_factor;
+ */
+
+ // Real rating modification
+ mod *= 24.0f;
+
+ return (int32)ceil(mod);
+}
+
+int32 ArenaTeam::GetRatingMod(uint32 ownRating, uint32 opponentRating, bool won /*, float confidence_factor*/)
+{
+ // 'Chance' calculation - to beat the opponent
+ // This is a simulation. Not much info on how it really works
float chance = GetChanceAgainst(ownRating, opponentRating);
float won_mod = (won) ? 1.0f : 0.0f;
// Calculate the rating modification
- // Simulation on how it works. Not much info on how it really works
float mod;
- if (won && !calculateMatchMakerRating)
+ // TODO: Replace this hack with using the confidence factor (limiting the factor to 2.0f)
+ if (won && ownRating < 1300)
{
if (ownRating < 1000)
mod = 48.0f * (won_mod - chance);
- else if (ownRating < 1300)
- mod = (24.0f + (24.0f * (1300.0f - int32(ownRating)) / 300.0f)) * (won_mod - chance);
else
- mod = 24.0f * (won_mod - chance);
+ mod = (24.0f + (24.0f * (1300.0f - float(ownRating)) / 300.0f)) * (won_mod - chance);
}
else
mod = 24.0f * (won_mod - chance);
return (int32)ceil(mod);
}
-int32 ArenaTeam::GetPersonalRatingMod(int32 baseRating, uint32 ownRating, uint32 opponentRating)
-{
- // Max (2 * team rating gain/loss), min 0 gain/loss
- float chance = GetChanceAgainst(ownRating, opponentRating);
- chance *= 2.0f;
-
- return (int32)ceil(float(baseRating) * chance);
-}
-
void ArenaTeam::FinishGame(int32 mod)
{
// Rating can only drop to 0
@@ -672,14 +688,17 @@ void ArenaTeam::FinishGame(int32 mod)
}
}
-int32 ArenaTeam::WonAgainst(uint32 againstRating)
+int32 ArenaTeam::WonAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change)
{
// Called when the team has won
- // Own team rating versus opponents matchmaker rating
- int32 mod = GetRatingMod(Stats.Rating, againstRating, true);
+ // Change in Matchmaker rating
+ int32 mod = GetMatchmakerRatingMod(Own_MMRating, Opponent_MMRating, true);
+
+ // Change in Team Rating
+ rating_change = GetRatingMod(Stats.Rating, Opponent_MMRating, true);
// Modify the team stats accordingly
- FinishGame(mod);
+ FinishGame(rating_change);
// Update number of wins per season and week
Stats.WeekWins += 1;
@@ -689,33 +708,35 @@ int32 ArenaTeam::WonAgainst(uint32 againstRating)
return mod;
}
-int32 ArenaTeam::LostAgainst(uint32 againstRating)
+int32 ArenaTeam::LostAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change)
{
// Called when the team has lost
- // Own team rating versus opponents matchmaker rating
- int32 mod = GetRatingMod(Stats.Rating, againstRating, false);
+ // Change in Matchmaker Rating
+ int32 mod = GetMatchmakerRatingMod(Own_MMRating, Opponent_MMRating, false);
+
+ // Change in Team Rating
+ rating_change = GetRatingMod(Stats.Rating, Opponent_MMRating, false);
// Modify the team stats accordingly
- FinishGame(mod);
+ FinishGame(rating_change);
// return the rating change, used to display it on the results screen
return mod;
}
-void ArenaTeam::MemberLost(Player* plr, uint32 againstMatchmakerRating, int32 teamratingchange)
+void ArenaTeam::MemberLost(Player* plr, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange)
{
// Called for each participant of a match after losing
for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
{
if (itr->Guid == plr->GetGUID())
{
// Update personal rating
- int32 mod = GetPersonalRatingMod(teamratingchange, itr->PersonalRating, (Stats.Rating - teamratingchange));
+ int32 mod = GetRatingMod(itr->PersonalRating, againstMatchmakerRating, false);
itr->ModifyPersonalRating(plr, mod, GetSlot());
// Update matchmaker rating
- mod = GetRatingMod(itr->MatchMakerRating, againstMatchmakerRating, false, true);
- itr->ModifyMatchmakerRating(mod, GetSlot());
+ itr->ModifyMatchmakerRating(MatchmakerRatingChange, GetSlot());
// Update personal played stats
itr->WeekGames +=1;
@@ -729,20 +750,19 @@ void ArenaTeam::MemberLost(Player* plr, uint32 againstMatchmakerRating, int32 te
}
}
-void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstMatchMakerRating, int32 ratingChange)
+void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange)
{
// Called for offline player after ending rated arena match!
for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
{
if (itr->Guid == guid)
{
// update personal rating
- int32 mod = GetPersonalRatingMod(ratingChange, itr->PersonalRating, (Stats.Rating - ratingChange));
+ int32 mod = GetRatingMod(itr->PersonalRating, againstMatchmakerRating, false);
itr->ModifyPersonalRating(NULL, mod, GetSlot());
// update matchmaker rating
- mod = GetRatingMod(itr->MatchMakerRating, againstMatchMakerRating, false, true);
- itr->ModifyMatchmakerRating(mod, GetSlot());
+ itr->ModifyMatchmakerRating(MatchmakerRatingChange, GetSlot());
// update personal played stats
itr->WeekGames += 1;
@@ -752,20 +772,19 @@ void ArenaTeam::OfflineMemberLost(uint64 guid, uint32 againstMatchMakerRating, i
}
}
-void ArenaTeam::MemberWon(Player* plr, uint32 againstMatchMakerRating, int32 ratingChange)
+void ArenaTeam::MemberWon(Player* plr, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange)
{
// called for each participant after winning a match
for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
{
if (itr->Guid == plr->GetGUID())
{
// update personal rating
- int32 mod = GetPersonalRatingMod(ratingChange, (Stats.Rating - ratingChange), itr->PersonalRating);
+ int32 mod = GetRatingMod(itr->PersonalRating, againstMatchmakerRating, true);
itr->ModifyPersonalRating(plr, mod, GetSlot());
// update matchmaker rating
- mod = GetRatingMod(itr->MatchMakerRating, againstMatchMakerRating, true, true);
- itr->ModifyMatchmakerRating(mod, GetSlot());
+ itr->ModifyMatchmakerRating(MatchmakerRatingChange, GetSlot());
// update personal stats
itr->WeekGames +=1;
View
14 src/server/game/Battlegrounds/ArenaTeam.h
@@ -164,14 +164,14 @@ class ArenaTeam
void Inspect(WorldSession* session, uint64 guid);
uint32 GetPoints(uint32 MemberRating);
- int32 GetRatingMod(uint32 ownRating, uint32 opponentRating, bool won, bool calculating_mmr = false);
- int32 GetPersonalRatingMod(int32 base_rating, uint32 ownRating, uint32 opponentRating);
+ int32 GetMatchmakerRatingMod(uint32 ownRating, uint32 opponentRating, bool won);
+ int32 GetRatingMod(uint32 ownRating, uint32 opponentRating, bool won);
float GetChanceAgainst(uint32 ownRating, uint32 opponentRating);
- int32 WonAgainst(uint32 againstRating);
- void MemberWon(Player* plr, uint32 againstMatchmakerRating, int32 teamratingchange = 12);
- int32 LostAgainst(uint32 againstRating);
- void MemberLost(Player* plr, uint32 againstMatchmakerRating, int32 teamratingchange = -12);
- void OfflineMemberLost(uint64 guid, uint32 againstMatchmakerRating, int32 teamratingchange = -12);
+ int32 WonAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change);
+ void MemberWon(Player* plr, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange);
+ int32 LostAgainst(uint32 Own_MMRating, uint32 Opponent_MMRating, int32& rating_change);
+ void MemberLost(Player* plr, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange = -12);
+ void OfflineMemberLost(uint64 guid, uint32 againstMatchmakerRating, int32 MatchmakerRatingChange = -12);
void UpdateArenaPointsHelper(std::map<uint32, uint32> & PlayerPoints);
View
20 src/server/game/Battlegrounds/Battleground.cpp
@@ -656,9 +656,11 @@ void Battleground::EndBattleground(uint32 winner)
uint32 loser_team_rating = 0;
uint32 loser_matchmaker_rating = 0;
int32 loser_change = 0;
+ int32 loser_matchmaker_change = 0;
uint32 winner_team_rating = 0;
uint32 winner_matchmaker_rating = 0;
int32 winner_change = 0;
+ int32 winner_matchmaker_change = 0;
WorldPacket data;
int32 winmsg_id = 0;
@@ -700,10 +702,12 @@ void Battleground::EndBattleground(uint32 winner)
loser_matchmaker_rating = GetArenaMatchmakerRating(GetOtherTeam(winner));
winner_team_rating = winner_arena_team->GetRating();
winner_matchmaker_rating = GetArenaMatchmakerRating(winner);
- winner_change = winner_arena_team->WonAgainst(loser_matchmaker_rating);
- loser_change = loser_arena_team->LostAgainst(winner_matchmaker_rating);
- sLog->outArena("--- Winner rating: %u, Loser rating: %u, Winner MMR: %u, Loser MMR: %u, Winner change: %d, Loser change: %d ---", winner_team_rating, loser_team_rating,
- winner_matchmaker_rating, loser_matchmaker_rating, winner_change, loser_change);
+ winner_matchmaker_change = winner_arena_team->WonAgainst(winner_matchmaker_rating, loser_matchmaker_rating, winner_change);
+ loser_matchmaker_change = loser_arena_team->LostAgainst(loser_matchmaker_rating, winner_matchmaker_rating, loser_change);
+ sLog->outArena("--- Winner: old rating: %u, rating gain: %d, old MMR: %u, MMR gain: %d --- Loser: old rating: %u, rating loss: %d, old MMR: %u, MMR loss: %d ---", winner_team_rating, winner_change, winner_matchmaker_rating,
+ winner_matchmaker_change, loser_team_rating, loser_change, loser_matchmaker_rating, loser_matchmaker_change);
+ SetArenaMatchmakerRating(winner, winner_matchmaker_rating + winner_matchmaker_change);
+ SetArenaMatchmakerRating(GetOtherTeam(winner), loser_matchmaker_rating + loser_matchmaker_change);
SetArenaTeamRatingChangeForTeam(winner, winner_change);
SetArenaTeamRatingChangeForTeam(GetOtherTeam(winner), loser_change);
sLog->outArena("Arena match Type: %u for Team1Id: %u - Team2Id: %u ended. WinnerTeamId: %u. Winner rating: +%d, Loser rating: %d", m_ArenaType, m_ArenaTeamIds[BG_TEAM_ALLIANCE], m_ArenaTeamIds[BG_TEAM_HORDE], winner_arena_team->GetId(), winner_change, loser_change);
@@ -738,9 +742,9 @@ void Battleground::EndBattleground(uint32 winner)
if (isArena() && isRated() && winner_arena_team && loser_arena_team && winner_arena_team != loser_arena_team)
{
if (team == winner)
- winner_arena_team->OfflineMemberLost(itr->first, loser_matchmaker_rating, winner_change);
+ winner_arena_team->OfflineMemberLost(itr->first, loser_matchmaker_rating, winner_matchmaker_change);
else
- loser_arena_team->OfflineMemberLost(itr->first, winner_matchmaker_rating, loser_change);
+ loser_arena_team->OfflineMemberLost(itr->first, winner_matchmaker_rating, loser_matchmaker_change);
}
continue;
}
@@ -778,11 +782,11 @@ void Battleground::EndBattleground(uint32 winner)
if (member)
plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, member->PersonalRating);
- winner_arena_team->MemberWon(plr, loser_matchmaker_rating, winner_change);
+ winner_arena_team->MemberWon(plr, loser_matchmaker_rating, winner_matchmaker_change);
}
else
{
- loser_arena_team->MemberLost(plr, winner_matchmaker_rating, loser_change);
+ loser_arena_team->MemberLost(plr, winner_matchmaker_rating, loser_matchmaker_change);
// Arena lost => reset the win_rated_arena having the "no_lose" condition
plr->GetAchievementMgr().ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE);

0 comments on commit 6cfb876

Please sign in to comment.
Something went wrong with that request. Please try again.