Skip to content

Commit 6841af5

Browse files
authored
Merge pull request #3 from CnCNet/feature/improved-duplicates
Feature/improved duplicates
2 parents 6be210a + 4e3861a commit 6841af5

File tree

11 files changed

+325
-133
lines changed

11 files changed

+325
-133
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
cmake_minimum_required(VERSION 3.14)
3-
project(CnCNet_ELO VERSION 1.0.3 LANGUAGES CXX)
3+
project(CnCNet_ELO VERSION 1.0.4 LANGUAGES CXX)
44

55
set(CMAKE_CXX_STANDARD 23)
66
set(CMAKE_CXX_STANDARD_REQUIRED ON)

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,3 +298,25 @@ In short:
298298
- **Games against unknown players have little to no effect.**
299299

300300
If you want to climb, you’ll need to prove your skill against a variety of active, stable opponents.
301+
302+
# Version history
303+
304+
### 1.0.0
305+
306+
- Initial version
307+
308+
### 1.0.1
309+
310+
- Sets day change to UTC+9
311+
312+
### 1.0.2
313+
314+
- Minor timezone fix
315+
316+
### 1.0.3
317+
318+
- Write ratings to database (user_ratings)
319+
320+
### 1.0.4
321+
322+
- Uses confirmed duplicates from CnCNet by default, can still use old algorithm to detect duplicates or ignore duplicates at all

databaseconnection.cpp

Lines changed: 75 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ uint32_t DatabaseConnection::loadPlayerFromAlias(const std::string &alias, Playe
341341
// Nicks for all ladders. Not used. Processing one ladder at once.
342342
std::unique_ptr<sql::PreparedStatement> statement(
343343
_connection->prepareStatement(
344-
"SELECT players.user_id, users.alias, players.username, users.name, ladders.abbreviation "
344+
"SELECT players.user_id, users.primary_user_id, users.alias, players.username, users.name, ladders.abbreviation "
345345
"FROM players "
346346
"JOIN ladders ON players.ladder_id = ladders.id "
347347
"JOIN users ON users.id = players.user_id "
@@ -362,7 +362,8 @@ uint32_t DatabaseConnection::loadPlayerFromAlias(const std::string &alias, Playe
362362
if (userId == 0)
363363
{
364364
userId = result->getInt("user_id");
365-
player = Player(userId, result->getString("name"), _gameMode);
365+
uint32_t primaryUserId = result->getInt("primary_user_id");
366+
player = Player(userId, primaryUserId, result->getString("name"), _gameMode);
366367
player->setAlias(alias);
367368
}
368369

@@ -411,7 +412,7 @@ uint32_t DatabaseConnection::loadPlayer(
411412

412413
std::unique_ptr<sql::PreparedStatement> statement(
413414
_connection->prepareStatement(
414-
"SELECT players.user_id, players.username, ladders.abbreviation, users.alias, users.name "
415+
"SELECT players.user_id, players.username, ladders.abbreviation, users.alias, users.name, users.primary_user_id "
415416
"FROM players "
416417
"JOIN ladders ON players.ladder_id = ladders.id "
417418
"JOIN users ON players.user_id = users.id "
@@ -445,7 +446,8 @@ uint32_t DatabaseConnection::loadPlayer(
445446
if (userId == 0)
446447
{
447448
userId = result->getInt("user_id");
448-
player = Player(userId, result->getString("name"), _gameMode);
449+
uint32_t primaryUserId = result->getInt("primary_user_id");
450+
player = Player(userId, primaryUserId, result->getString("name"), _gameMode);
449451
}
450452
else if (userId != result->getInt("user_id") || player->account() != result->getString("name"))
451453
{
@@ -483,9 +485,10 @@ bool DatabaseConnection::loadPlayerWithNoUser(
483485
{
484486
std::unique_ptr<sql::PreparedStatement> stmt(
485487
_connection->prepareStatement(
486-
"SELECT players.user_id, players.username, ladders.abbreviation "
488+
"SELECT players.user_id, players.username, ladders.abbreviation, users.alias, users.primary_user_id "
487489
"FROM players "
488490
"JOIN ladders ON players.ladder_id = ladders.id "
491+
"JOIN users ON players.user_id = users.id "
489492
"WHERE players.user_id = ? "
490493
// "AND ladders.abbreviation = ? " <= User might not have played the current ladder.
491494
"ORDER BY players.username;"
@@ -503,7 +506,14 @@ bool DatabaseConnection::loadPlayerWithNoUser(
503506
{
504507
if (!player.has_value())
505508
{
506-
player = Player(userId, "", _gameMode);
509+
uint32_t primaryUserId = result->getInt("primary_user_id");
510+
player = Player(userId, primaryUserId, "", _gameMode);
511+
512+
std::string alias = result->getString("alias");
513+
if (!alias.empty())
514+
{
515+
player->setAlias(alias);
516+
}
507517
}
508518

509519
player->addName(result->getString("username"), result->getString("abbreviation"));
@@ -526,7 +536,7 @@ bool DatabaseConnection::loadPlayer(
526536
{
527537
std::unique_ptr<sql::PreparedStatement> stmt(
528538
_connection->prepareStatement(
529-
"SELECT players.user_id, players.username, ladders.abbreviation, users.alias, users.name "
539+
"SELECT players.user_id, players.username, ladders.abbreviation, users.alias, users.name, users.primary_user_id "
530540
"FROM players "
531541
"JOIN ladders ON players.ladder_id = ladders.id "
532542
"JOIN users ON players.user_id = users.id "
@@ -548,7 +558,8 @@ bool DatabaseConnection::loadPlayer(
548558
if (!player.has_value())
549559
{
550560
std::string accountName = result->getString("name");
551-
player = Player(userId, accountName, _gameMode);
561+
uint32_t primaryUserId = result->getInt("primary_user_id");
562+
player = Player(userId, primaryUserId, accountName, _gameMode);
552563

553564
std::string alias = result->getString("alias");
554565
if (!alias.empty())
@@ -581,6 +592,7 @@ std::map<uint32_t, Game> DatabaseConnection::fetchGames()
581592
SELECT
582593
games.id AS gameId,
583594
players.username AS playerUsername,
595+
players.user_id AS playerUserId,
584596
ladders.abbreviation AS ladderAbbreviation,
585597
player_game_reports.won AS playerWon,
586598
player_game_reports.points,
@@ -611,6 +623,7 @@ std::map<uint32_t, Game> DatabaseConnection::fetchGames()
611623
SELECT
612624
games.id AS gameId,
613625
players.username AS playerUsername,
626+
players.user_id AS playerUserId,
614627
ladders.abbreviation AS ladderAbbreviation,
615628
player_game_reports.won AS playerWon,
616629
player_game_reports.points,
@@ -643,6 +656,7 @@ std::map<uint32_t, Game> DatabaseConnection::fetchGames()
643656
"SELECT "
644657
" games.id AS gameId, "
645658
" players.username AS playerUsername, "
659+
" players.user_id AS playerUserId, "
646660
" ladders.abbreviation AS ladderAbbreviation, "
647661
" player_game_reports.won AS playerWon, "
648662
" player_game_reports.points, "
@@ -682,6 +696,7 @@ std::map<uint32_t, Game> DatabaseConnection::fetchGames()
682696
"SELECT "
683697
" games.id AS gameId, "
684698
" players.username AS playerUsername, "
699+
" players.user_id AS playerUserId, "
685700
" ladders.abbreviation AS ladderAbbreviation, "
686701
" player_game_reports.won AS playerWon, "
687702
" player_game_reports.points, "
@@ -766,6 +781,7 @@ std::map<uint32_t, Game> DatabaseConnection::fetchGames()
766781
std::string playerName = result->getString("playerUsername");
767782

768783
int32_t points = result->getInt("points");
784+
uint32_t userId = result->getInt("playerUserId");
769785
bool won = result->getBoolean("playerWon");
770786
std::string playerCountry = result->getString("playerCountry");
771787

@@ -776,7 +792,7 @@ std::map<uint32_t, Game> DatabaseConnection::fetchGames()
776792
continue;
777793
}
778794

779-
game->addPlayer(0, playerName, faction, won, points, 0.0, 0.0);
795+
game->addPlayer(userId, playerName, faction, won, points, 0.0, 0.0);
780796
}
781797

782798
return games;
@@ -855,7 +871,7 @@ void DatabaseConnection::writePlayerRatings(
855871
{
856872
// Check if expected columns exist.
857873
std::set<std::string> requiredColumns = {
858-
"user_id", "ladder_id", "rating", "elo_rank",
874+
"user_id", "ladder_id", "rating", "deviation", "elo_rank",
859875
"alltime_rank", "rated_games", "active", "created_at", "updated_at"
860876
};
861877

@@ -884,13 +900,6 @@ void DatabaseConnection::writePlayerRatings(
884900
}
885901
}
886902

887-
// Clear table.
888-
std::unique_ptr<sql::PreparedStatement> truncateStmt(
889-
_connection->prepareStatement("TRUNCATE TABLE user_ratings")
890-
);
891-
truncateStmt->execute();
892-
Log::info() << "Table 'user_ratings' truncated.";
893-
894903
// Get ladder id.
895904
uint32_t ladderId = 0;
896905
std::unique_ptr<sql::PreparedStatement> ladderStmt(
@@ -909,35 +918,60 @@ void DatabaseConnection::writePlayerRatings(
909918
return;
910919
}
911920

912-
// Prepare statement to save user data.
913-
std::unique_ptr<sql::PreparedStatement> insertStmt(
914-
_connection->prepareStatement(R"SQL(
915-
INSERT INTO user_ratings
916-
(user_id, ladder_id, rating, elo_rank, alltime_rank, rated_games, active, created_at, updated_at)
917-
VALUES (?, ?, ?, ?, ?, ?, ?, NOW(), NOW())
918-
)SQL")
919-
);
921+
_connection->setAutoCommit(false);
920922

921-
for (uint32_t userId : players.userIds())
923+
try
922924
{
923-
const Player &player = players[userId];
924-
uint32_t gameCount = player.gameCount();
925-
double elo = (gameMode == gamemodes::Blitz2v2) ? player.elo(factions::Combined) : player.maxRating(!player.isActive());
926-
if (elo < 0.0)
925+
// Remove old entries.
926+
std::unique_ptr<sql::PreparedStatement> removeStmt(
927+
_connection->prepareStatement("DELETE FROM user_ratings WHERE ladder_id = ?")
928+
);
929+
removeStmt->setUInt(1, ladderId);
930+
removeStmt->execute();
931+
Log::info() << "Removed old entries from 'user_ratings'.";
932+
933+
// Prepare statement to save user data.
934+
std::unique_ptr<sql::PreparedStatement> insertStmt(
935+
_connection->prepareStatement(R"SQL(
936+
INSERT INTO user_ratings
937+
(user_id, ladder_id, rating, deviation, elo_rank, alltime_rank, rated_games, active, created_at, updated_at)
938+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())
939+
)SQL")
940+
);
941+
942+
for (uint32_t userId : players.userIds())
927943
{
928-
// Try to get any rating, even if the player was never active.
929-
elo = player.elo(factions::Combined);
944+
const Player &player = players[userId];
945+
uint32_t gameCount = player.gameCount();
946+
factions::Faction faction = player.getBestFaction(false);
947+
948+
if (!player.isActive(faction) || gameMode == gamemodes::Blitz2v2)
949+
{
950+
// Try to get any rating.
951+
faction = factions::Combined;
952+
}
953+
954+
insertStmt->setUInt(1, userId);
955+
insertStmt->setUInt(2, ladderId);
956+
insertStmt->setInt(3, static_cast<int>(std::round(player.elo(faction))));
957+
insertStmt->setInt(4, static_cast<int>(std::round(player.deviation(faction))));
958+
insertStmt->setUInt(5, activeRanks.contains(userId) ? activeRanks[userId] : 0);
959+
insertStmt->setUInt(6, allTimeRanks.contains(userId) ? allTimeRanks[userId] : 0);
960+
insertStmt->setUInt(7, gameCount);
961+
insertStmt->setBoolean(8, player.isActive());
962+
963+
insertStmt->execute();
930964
}
931-
insertStmt->setUInt(1, userId);
932-
insertStmt->setUInt(2, ladderId);
933-
insertStmt->setInt(3, static_cast<int>(std::round(elo)));
934-
insertStmt->setUInt(4, activeRanks.contains(userId) ? activeRanks[userId] : 0);
935-
insertStmt->setUInt(5, allTimeRanks.contains(userId) ? allTimeRanks[userId] : 0);
936-
insertStmt->setUInt(6, gameCount);
937-
insertStmt->setBoolean(7, player.isActive());
938-
939-
insertStmt->execute();
965+
966+
_connection->commit();
940967
}
968+
catch (sql::SQLException &e)
969+
{
970+
_connection->rollback();
971+
Log::fatal() << "Error while writing user ratings: " << e.what();
972+
}
973+
974+
_connection->setAutoCommit(true);
941975

942976
Log::info() << "Player ratings written to 'user_ratings'.";
943977
}

gameoverlay.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ void GameOverlay::loadTournamentGames(
9898
{
9999
// Need to create a player with a fake id.
100100
userId1 = currentFakeUserId++;
101-
Player player(userId1, "?", gameMode);
101+
Player player(userId1, 0, "?", gameMode);
102102
Log::info() << "Manually created player " << userId1 << " with alias " << playerAlias1 << ".";
103103
player.setAlias(playerAlias1);
104104
players.add(player, ladderAbbreviation);
@@ -115,7 +115,7 @@ void GameOverlay::loadTournamentGames(
115115
{
116116
// Need to create a player with a fake id.
117117
userId2 = currentFakeUserId++;
118-
Player player(userId2, "?", gameMode);
118+
Player player(userId2, 0, "?", gameMode);
119119
player.setAlias(playerAlias2);
120120
Log::info() << "Manually created player " << userId2 << " with alias " << playerAlias2 << ".";
121121
players.add(player, ladderAbbreviation);

0 commit comments

Comments
 (0)