(Broken) ranking computation

This commit is contained in:
Alayan-stk-2 2018-05-15 04:22:23 +02:00 committed by GitHub
parent 1fc3e0916e
commit 9f18c0e2c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 141 additions and 0 deletions

View File

@ -751,6 +751,9 @@ void ServerLobby::checkRaceFinished()
total->addUInt32(last_score).addUInt32(cur_score)
.addFloat(overall_time);
}
if (NetworkConfig::get()->isRankedServer())
computeNewRankings();
}
else if (race_manager->modeHasLaps())
{
@ -770,6 +773,137 @@ void ServerLobby::checkRaceFinished()
} // checkRaceFinished
//-----------------------------------------------------------------------------
/** Compute the new player's rankings in ranked servers
*/
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.
//TODO : make some numerical parts of the formulas
// depend of a single constant value
// 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();
std::vector<double> ranking_change;
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 !
//FIXME : can't use a weak_ptr like that
int player1_ranking = players[i]->getRankingPoints();
float player1_time = race_manager->getKartRaceTime(i);
float player1_factor = computeRankingFactor(i);
for (unsigned j = 0; j < players.size(); i++)
{
// Don't compare a player with itself
if (i == j)
continue;
double result = 0.0f;
double expected_result = 0.0f;
double ranking_importance = 0.0f;
// No change between two quitting players
if (!players[i].lock() && !players[j].lock())
continue;
int player2_ranking = players[i]->getRankingPoints();
float player2_time = race_manager->getKartRaceTime(j);
// Compute the expected result
double diff = (double) player2_ranking - player1_ranking;
expected_result = 1.0f/(1.0f+std::pow(10.0f, diff/(BASE_RANKING_POINTS/2.0f)));
// Compute the result and race ranking importance
float player_factors = std::max(player1_factor,
computeRankingFactor(j) );
if (!players[i].lock())
{
result = 0.0f;
ranking_importance = (MAX_SCALING_TIME/20.0f)*player_factors;
}
else if (!players[j].lock())
{
result = 1.0f;
ranking_importance = (MAX_SCALING_TIME/20.0f)*player_factors;
}
else
{
// If time difference > 2,5% ; the result is 1 or 0
// Otherwise, it is averaged between 0 and 1.
if (player1_time <= player2_time)
{
result = (player2_time - player1_time)/(player1_time/20);
result = std::min( (double) 1.0f, 0.5f + result);
}
else
{
result = (player1_time - player2_time)/(player2_time/20);
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;
}
// 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
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]));
}
} //computeNewRankings
//-----------------------------------------------------------------------------
/** Compute the ranking factor, used to make top rankings more stable
* and to allow new players to faster get to an appropriate ranking
*/
float ServerLobby::computeRankingFactor(unsigned int player_id)
{
auto& players = m_game_setup->getPlayers();
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;
else if (max_points >= (int) (BASE_RANKING_POINTS * 1.75f) || num_races > 500)
return 1.25f;
else if (max_points >= (int) (BASE_RANKING_POINTS * 1.5f) || num_races > 250)
return 1.5f;
else if (max_points >= (int) (BASE_RANKING_POINTS * 1.25f) || num_races > 100)
return 1.75f;
// 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
return 2.5f;
} //computeRankingFactor
//-----------------------------------------------------------------------------
/** Stop any race currently in server, should only be called in main thread.
*/

View File

@ -78,6 +78,11 @@ private:
TransportAddress m_server_address;
/* Ranking related variables */
const float BASE_RANKING_POINTS = 4000.0f;
const float MAX_SCALING_TIME = 600.0f;
// connection management
void clientDisconnected(Event* event);
void connectionRequested(Event* event);
@ -126,6 +131,8 @@ private:
}
std::tuple<std::string, uint8_t, bool, bool> handleVote();
void stopCurrentRace();
void computeNewRankings();
float computeRankingFactor(unsigned int player_id);
public:
ServerLobby();