Several improvements to the ranking formula

This commit is contained in:
Alayan 2019-01-06 02:35:01 +01:00
parent e2d5e350cf
commit aeeb4afd63
2 changed files with 67 additions and 28 deletions

View File

@ -1651,6 +1651,7 @@ void ServerLobby::computeNewRankings()
double result = 0.0;
double expected_result = 0.0;
double ranking_importance = 0.0;
double max_time = 0.0;
// No change between two quitting players
if (w->getKart(i)->isEliminated() &&
@ -1660,13 +1661,8 @@ void ServerLobby::computeNewRankings()
double player2_scores = new_scores[j];
double player2_time = race_manager->getKartRaceTime(j);
// Compute the expected result using an ELO-like function
double diff = player2_scores - player1_scores;
expected_result = 1.0/ (1.0 + std::pow(10.0,
diff / (BASE_RANKING_POINTS * getModeSpread() / 2.0)));
// Compute the result and race ranking importance
double player_factors = std::max(player1_factor,
double player_factors = std::min(player1_factor,
computeRankingFactor(
race_manager->getKartInfo(j).getOnlineId()));
@ -1675,14 +1671,14 @@ void ServerLobby::computeNewRankings()
if (w->getKart(i)->isEliminated())
{
result = 0.0;
ranking_importance = mode_factor *
scalingValueForTime(MAX_SCALING_TIME) * player_factors;
player1_time = player2_time; // for getTimeSpread
max_time = MAX_SCALING_TIME;
}
else if (w->getKart(j)->isEliminated())
{
result = 1.0;
ranking_importance = mode_factor *
scalingValueForTime(MAX_SCALING_TIME) * player_factors;
player2_time = player1_time;
max_time = MAX_SCALING_TIME;
}
else
{
@ -1701,11 +1697,25 @@ void ServerLobby::computeNewRankings()
result = std::max(0.0, 0.5 - result);
}
double max_time = std::min(std::max(player1_time, player2_time),
max_time = std::min(std::max(player1_time, player2_time),
MAX_SCALING_TIME);
ranking_importance = mode_factor *
scalingValueForTime(max_time) * player_factors;
}
ranking_importance = mode_factor *
scalingValueForTime(max_time) * player_factors;
// Compute the expected result using an ELO-like function
double diff = player2_scores - player1_scores;
double uncertainty = std::max(getUncertaintySpread(race_manager->getKartInfo(i).getOnlineId()),
getUncertaintySpread(race_manager->getKartInfo(j).getOnlineId()) );
expected_result = 1.0/ (1.0 + std::pow(10.0,
diff / ( BASE_RANKING_POINTS / 2.0
* getModeSpread()
* getTimeSpread(std::min(player1_time, player2_time))
* uncertainty )));
// Compute the ranking change
scores_change[i] +=
ranking_importance * (result - expected_result);
@ -1733,19 +1743,19 @@ double ServerLobby::computeRankingFactor(uint32_t online_id)
unsigned num_races = m_num_ranked_races.at(online_id);
if (max_points >= (BASE_RANKING_POINTS * 2.0))
return 0.4;
else if (max_points >= (BASE_RANKING_POINTS * 1.75) || num_races > 500)
return 0.5;
else if (max_points >= (BASE_RANKING_POINTS * 1.5) || num_races > 250)
return 0.6;
else if (max_points >= (BASE_RANKING_POINTS * 1.25) || num_races > 100)
else if (max_points >= (BASE_RANKING_POINTS * 1.75) || num_races > 500)
return 0.7;
else if (max_points >= (BASE_RANKING_POINTS * 1.5) || num_races > 250)
return 0.8;
else if (max_points >= (BASE_RANKING_POINTS * 1.25) || num_races > 100)
return 1.0;
// The base ranking points are not distributed all at once
// So it's not guaranteed a player reach them
else if (max_points >= (BASE_RANKING_POINTS) || num_races > 50)
return 0.8;
return 1.2;
else
return 1.0;
return 1.5;
} // computeRankingFactor
@ -1757,7 +1767,7 @@ double ServerLobby::getModeFactor()
{
if (race_manager->isTimeTrialMode())
return 1.0;
return 0.4;
return 0.7;
} // getModeFactor
//-----------------------------------------------------------------------------
@ -1773,31 +1783,58 @@ double ServerLobby::getModeSpread()
// When hard data to the spread tendencies of time-trial
// and normal mode becomes available, update this to make
// the spreads more comparable
return 1.4;
return 1.5;
} // getModeSpread
//-----------------------------------------------------------------------------
/** Returns the time spread factor.
* Short races are more random, so the expected result changes depending
* on race duration.
*/
double ServerLobby::getTimeSpread(double time)
{
return sqrt(120.0 / time);
} // getTimeSpread
//-----------------------------------------------------------------------------
/** Returns the uncertainty spread factor.
* The ranking of new players is not yet reliable,
* so weight the expected results twoards 0.5 by using a > 1 spread
*/
double ServerLobby::getUncertaintySpread(uint32_t online_id)
{
unsigned num_races = m_num_ranked_races.at(online_id);
if (num_races <= 60)
return 0.5 + (4.0/sqrt(num_races+3));
else
return 1.0;
} // getUncertaintySpread
//-----------------------------------------------------------------------------
/** Compute the scaling value of a given time
* Short races are more random, so we don't use strict proportionality
* This is linear to race duration, getTimeSpread takes care
* of expecting a more random result in shorter races.
*/
double ServerLobby::scalingValueForTime(double time)
{
return time * sqrt(time / 120.0) * MAX_POINTS_PER_SECOND;
return time * MAX_POINTS_PER_SECOND;
} // scalingValueForTime
//-----------------------------------------------------------------------------
/** Manages the distribution of the base points.
* Gives half of the points progressively
* by smaller and smaller chuncks from race 1 to 45.
* by smaller and smaller chuncks from race 1 to 60.
* The race count is incremented after this is called, so num_races
* is between 0 and 59.
* The first half is distributed when the player enters
* for the first time in the ranked server.
* for the first time in a ranked server.
*/
double ServerLobby::distributeBasePoints(uint32_t online_id)
{
unsigned num_races = m_num_ranked_races.at(online_id);
if (num_races <= 45)
if (num_races < 60)
{
return BASE_RANKING_POINTS / 2000.0 * std::max((45u - num_races), 4u);
return BASE_RANKING_POINTS / 8000.0 * std::max((96u - num_races), 41u);
}
else
return 0.0;

View File

@ -263,6 +263,8 @@ private:
double distributeBasePoints(uint32_t online_id);
double getModeFactor();
double getModeSpread();
double getTimeSpread(double time);
double getUncertaintySpread(uint32_t online_id);
double scalingValueForTime(double time);
void checkRaceFinished();
void getHitCaptureLimit(float num_karts);