Fix random choice of several equal votes in handleAllVotes

This commit is contained in:
kimden 2024-04-02 00:42:33 +04:00
parent 979077abab
commit 4ee7c51131
2 changed files with 45 additions and 55 deletions

View File

@ -4308,7 +4308,7 @@ bool ServerLobby::handleAllVotes(PeerVote* winner_vote,
}
std::string top_track = m_default_vote->m_track_name;
int top_laps = m_default_vote->m_num_laps;
unsigned top_laps = m_default_vote->m_num_laps;
bool top_reverse = m_default_vote->m_reverse;
std::map<std::string, unsigned> tracks;
@ -4319,7 +4319,6 @@ bool ServerLobby::handleAllVotes(PeerVote* winner_vote,
float tracks_rate = 0.0f;
float laps_rate = 0.0f;
float reverses_rate = 0.0f;
RandomGenerator rg;
for (auto& p : m_peers_votes)
{
@ -4340,57 +4339,9 @@ bool ServerLobby::handleAllVotes(PeerVote* winner_vote,
reverse_vote->second++;
}
unsigned vote = 0;
auto track_vote = tracks.begin();
// rg.get(2) == 0 will allow not always the "less" in map get picked
for (auto c_vote = tracks.begin(); c_vote != tracks.end(); c_vote++)
{
if (c_vote->second > vote ||
(c_vote->second >= vote && rg.get(2) == 0))
{
vote = c_vote->second;
track_vote = c_vote;
}
}
if (track_vote != tracks.end())
{
top_track = track_vote->first;
tracks_rate = float(track_vote->second) / cur_players;
}
vote = 0;
auto lap_vote = laps.begin();
for (auto c_vote = laps.begin(); c_vote != laps.end(); c_vote++)
{
if (c_vote->second > vote ||
(c_vote->second >= vote && rg.get(2) == 0))
{
vote = c_vote->second;
lap_vote = c_vote;
}
}
if (lap_vote != laps.end())
{
top_laps = lap_vote->first;
laps_rate = float(lap_vote->second) / cur_players;
}
vote = 0;
auto reverse_vote = reverses.begin();
for (auto c_vote = reverses.begin(); c_vote != reverses.end(); c_vote++)
{
if (c_vote->second > vote ||
(c_vote->second >= vote && rg.get(2) == 0))
{
vote = c_vote->second;
reverse_vote = c_vote;
}
}
if (reverse_vote != reverses.end())
{
top_reverse = reverse_vote->first;
reverses_rate = float(reverse_vote->second) / cur_players;
}
findMajorityValue<std::string>(tracks, cur_players, &top_track, &tracks_rate);
findMajorityValue<unsigned>(laps, cur_players, &top_laps, &laps_rate);
findMajorityValue<bool>(reverses, cur_players, &top_reverse, &reverses_rate);
// End early if there is majority agreement which is all entries rate > 0.5
it = m_peers_votes.begin();
@ -4424,10 +4375,10 @@ bool ServerLobby::handleAllVotes(PeerVote* winner_vote,
while (it != m_peers_votes.end())
{
if (it->second.m_track_name == top_track &&
std::abs((int)it->second.m_num_laps - top_laps) < diff)
std::abs((int)it->second.m_num_laps - (int)top_laps) < diff)
{
closest_lap = it;
diff = std::abs((int)it->second.m_num_laps - top_laps);
diff = std::abs((int)it->second.m_num_laps - (int)top_laps);
}
else
it++;
@ -4439,6 +4390,42 @@ bool ServerLobby::handleAllVotes(PeerVote* winner_vote,
return false;
} // handleAllVotes
// ----------------------------------------------------------------------------
template<typename T>
void ServerLobby::findMajorityValue(const std::map<T, unsigned>& choices, unsigned cur_players,
T* best_choice, float* rate)
{
RandomGenerator rg;
unsigned max_votes = 0;
auto best_iter = choices.begin();
unsigned best_iters_count = 1;
// Among choices with max votes, we need to pick one uniformly,
// thus we have to keep track of their number
for (auto iter = choices.begin(); iter != choices.end(); iter++)
{
if (iter->second > max_votes)
{
max_votes = iter->second;
best_iter = iter;
best_iters_count = 1;
}
else if (iter->second == max_votes)
{
best_iters_count++;
if (rg.get(best_iters_count) == 0)
{
max_votes = iter->second;
best_iter = iter;
}
}
}
if (best_iter != choices.end())
{
*best_choice = best_iter->first;
*rate = float(best_iter->second) / cur_players;
}
} // findMajorityValue
// ----------------------------------------------------------------------------
void ServerLobby::getHitCaptureLimit()
{

View File

@ -330,6 +330,9 @@ private:
const irr::core::stringw& online_name,
const std::string& country_code);
bool handleAllVotes(PeerVote* winner, uint32_t* winner_peer_id);
template<typename T>
void findMajorityValue(const std::map<T, unsigned>& choices, unsigned cur_players,
T* best_choice, float* rate);
void getRankingForPlayer(std::shared_ptr<NetworkPlayerProfile> p);
void submitRankingsToAddons();
void computeNewRankings();