Fix/update ranking computation
This commit is contained in:
parent
8da8390773
commit
b026b24e4a
@ -775,34 +775,43 @@ void ServerLobby::checkRaceFinished()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Compute the new player's rankings in ranked servers
|
||||
* //FIXME : this function assumes that m_rankings,
|
||||
* m_num_ranked_races and m_max_ranking
|
||||
* are correctly filled before
|
||||
* It also assumes that the data stored by them
|
||||
* is written back to the main list after the GP
|
||||
*/
|
||||
void ServerLobby::computeNewRankings()
|
||||
{
|
||||
//TODO : this is overall a rather naive implementation
|
||||
// several possibilities to speed up the computation exist,
|
||||
// though this is minor in importance as it's not done
|
||||
// during racing.
|
||||
auto players = m_game_setup->getConnectedPlayers(true/*same_index_for_disconnected*/);
|
||||
|
||||
//TODO : make some numerical parts of the formulas
|
||||
// depend of a single constant value
|
||||
assert (m_rankings.size() == players.size() &&
|
||||
m_num_ranked_races.size() == players.size() &&
|
||||
m_max_ranking.size() == players.size() );
|
||||
|
||||
// No ranking yet for battle mode
|
||||
// TODO : separate rankings for time-trial and normal and FTL ??
|
||||
if (!race_manager->modeHasLaps())
|
||||
return;
|
||||
|
||||
auto& players = m_game_setup->getPlayers();
|
||||
|
||||
// Using a vector of vector, it would be possible to fill
|
||||
// all j < i v[i][j] with -v[j][i]
|
||||
// Would this be worth it ?
|
||||
std::vector<double> ranking_change;
|
||||
|
||||
for (unsigned i = 0; i < players.size(); i++)
|
||||
{
|
||||
m_rankings[i] += distributeBasePoints(i);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < players.size(); i++)
|
||||
{
|
||||
ranking_change.push_back(0);
|
||||
|
||||
//FIXME : if the players have been kicked out, there is no way to retrieve the data !
|
||||
int player1_ranking = m_rankings[i];
|
||||
|
||||
//FIXME : can't use a weak_ptr like that
|
||||
int player1_ranking = players[i]->getRankingPoints();
|
||||
// If the player has quitted before the race end,
|
||||
// the value will be incorrect, but it will not be used
|
||||
float player1_time = race_manager->getKartRaceTime(i);
|
||||
float player1_factor = computeRankingFactor(i);
|
||||
|
||||
@ -817,13 +826,13 @@ void ServerLobby::computeNewRankings()
|
||||
double ranking_importance = 0.0f;
|
||||
|
||||
// No change between two quitting players
|
||||
if (!players[i].lock() && !players[j].lock())
|
||||
if (!players[i] && !players[j])
|
||||
continue;
|
||||
|
||||
int player2_ranking = players[i]->getRankingPoints();
|
||||
int player2_ranking = m_rankings[j];
|
||||
float player2_time = race_manager->getKartRaceTime(j);
|
||||
|
||||
// Compute the expected result
|
||||
// Compute the expected result using an ELO-like function
|
||||
double diff = (double) player2_ranking - player1_ranking;
|
||||
expected_result = 1.0f/(1.0f+std::pow(10.0f, diff/(BASE_RANKING_POINTS/2.0f)));
|
||||
|
||||
@ -831,15 +840,17 @@ void ServerLobby::computeNewRankings()
|
||||
float player_factors = std::max(player1_factor,
|
||||
computeRankingFactor(j) );
|
||||
|
||||
if (!players[i].lock())
|
||||
if (!players[i])
|
||||
{
|
||||
result = 0.0f;
|
||||
ranking_importance = (MAX_SCALING_TIME/20.0f)*player_factors;
|
||||
ranking_importance =
|
||||
MAX_SCALING_TIME*MAX_POINTS_PER_SECOND*player_factors;
|
||||
}
|
||||
else if (!players[j].lock())
|
||||
else if (!players[j])
|
||||
{
|
||||
result = 1.0f;
|
||||
ranking_importance = (MAX_SCALING_TIME/20.0f)*player_factors;
|
||||
ranking_importance =
|
||||
MAX_SCALING_TIME*MAX_POINTS_PER_SECOND*player_factors;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -856,21 +867,22 @@ void ServerLobby::computeNewRankings()
|
||||
result = std::max( (double) 0.0f, 0.5f - result);
|
||||
}
|
||||
ranking_importance = std::min ( std::max (player1_time, player2_time),
|
||||
MAX_SCALING_TIME ) * player_factors/20.0f;
|
||||
MAX_SCALING_TIME ) * MAX_POINTS_PER_SECOND * player_factors;
|
||||
}
|
||||
// Compute the ranking change
|
||||
ranking_change[i] += ranking_importance * (result - expected_result);
|
||||
}
|
||||
}
|
||||
|
||||
// Don't merge it in the main loop as long as getRankingPoints
|
||||
// is called in it
|
||||
// Don't merge it in the main loop as m_rankings value are used there
|
||||
for (unsigned i = 0; i < players.size(); i++)
|
||||
{
|
||||
// Add or substract 0.5f so that the cast to int acts like rounding
|
||||
ranking_change[i] += (ranking_change[i] > 0 ) ? 0.5f : -0.5f;
|
||||
int old_ranking_points = players[i]->getRankingPoints();
|
||||
players[i]->setRankingPoints(old_ranking_points + ((int) ranking_change[i]));
|
||||
m_rankings[i] += ranking_change[i];
|
||||
// This isn't entirely correct when rankings are negatives, but
|
||||
// the max will always be positive
|
||||
if ((int) (m_rankings[i]+0.5f) > m_max_ranking[i])
|
||||
m_max_ranking[i] = (int) (m_rankings[i]+0.5f);
|
||||
m_num_ranked_races[i]++;
|
||||
}
|
||||
} //computeNewRankings
|
||||
|
||||
@ -880,30 +892,42 @@ void ServerLobby::computeNewRankings()
|
||||
*/
|
||||
float ServerLobby::computeRankingFactor(unsigned int player_id)
|
||||
{
|
||||
auto& players = m_game_setup->getPlayers();
|
||||
int max_points = m_max_ranking[player_id];
|
||||
int num_races = m_num_ranked_races[player_id];
|
||||
|
||||
assert(player_id < players.size());
|
||||
|
||||
int max_points = players[player_id].getMaxRankingPoints();
|
||||
int num_races = players[player_id].getNumRankedRaces();
|
||||
|
||||
if (max_points >= (int) (BASE_RANKING_POINTS * 2.0f))
|
||||
return 1.0f;
|
||||
if ( max_points >= (int) (BASE_RANKING_POINTS * 2.0f))
|
||||
return 0.4f;
|
||||
else if (max_points >= (int) (BASE_RANKING_POINTS * 1.75f) || num_races > 500)
|
||||
return 1.25f;
|
||||
return 0.5f;
|
||||
else if (max_points >= (int) (BASE_RANKING_POINTS * 1.5f) || num_races > 250)
|
||||
return 1.5f;
|
||||
return 0.6f;
|
||||
else if (max_points >= (int) (BASE_RANKING_POINTS * 1.25f) || num_races > 100)
|
||||
return 1.75f;
|
||||
return 0.7f;
|
||||
// The base ranking points are not distributed all at once
|
||||
// So it's not guaranteed a player reach them
|
||||
else if (max_points >= (int) (BASE_RANKING_POINTS ) || num_races > 50)
|
||||
return 2.0f;
|
||||
else if (max_points >= (int) (BASE_RANKING_POINTS ) || num_races > 50)
|
||||
return 0.8f;
|
||||
else
|
||||
return 2.5f;
|
||||
return 1.0f;
|
||||
|
||||
} //computeRankingFactor
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Manages the distribution of the base points.
|
||||
* Gives half of the points immediately and the other half progressively
|
||||
* by smaller and smaller chuncks from race 1 to 46.
|
||||
*/
|
||||
float ServerLobby::distributeBasePoints(unsigned int player_id)
|
||||
{
|
||||
int num_races = m_num_ranked_races[player_id];
|
||||
if (num_races == 0)
|
||||
return BASE_RANKING_POINTS/2.0f;
|
||||
else if (num_races <= 45)
|
||||
return (BASE_RANKING_POINTS/2000.0f * std::max((45-num_races),4)*2.0f);
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Stop any race currently in server, should only be called in main thread.
|
||||
*/
|
||||
|
@ -80,8 +80,13 @@ private:
|
||||
|
||||
/* Ranking related variables */
|
||||
|
||||
const float BASE_RANKING_POINTS = 4000.0f;
|
||||
const float MAX_SCALING_TIME = 600.0f;
|
||||
const float BASE_RANKING_POINTS = 4000.0f;
|
||||
const float MAX_SCALING_TIME = 600.0f;
|
||||
const float MAX_POINTS_PER_SECOND = 0.125f;
|
||||
|
||||
std::vector<double> m_rankings; // TODO : convert from and to int when communicating with the server. Think to round it correctly
|
||||
std::vector<unsigned int> m_num_ranked_races;
|
||||
std::vector<int> m_max_ranking;
|
||||
|
||||
// connection management
|
||||
void clientDisconnected(Event* event);
|
||||
@ -133,6 +138,7 @@ private:
|
||||
void stopCurrentRace();
|
||||
void computeNewRankings();
|
||||
float computeRankingFactor(unsigned int player_id);
|
||||
float distributeBasePoints(unsigned int player_id);
|
||||
|
||||
public:
|
||||
ServerLobby();
|
||||
|
Loading…
Reference in New Issue
Block a user