@@ -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 }
0 commit comments