[games/chessament] src: Update players ratings from rating list
Manuel Alcaraz Zambrano <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit fc084b50699a1d10ed12984548f6707c1d2507ec by Manuel Alcaraz Zambrano.
Committed on 28/07/2026 at 21:09.
Pushed by manuelal into branch 'master'.
Update players ratings from rating list
M +1 -0 src/CMakeLists.txt
M +15 -0 src/playersmodel.cpp
M +3 -0 src/playersmodel.h
M +9 -0 src/qml/PlayersPage.qml
A +41 -0 src/qml/UpdateRatingsDialog.qml [License: GPL(v3.0+)]
M +74 -44 src/tournament/ratinglists/ratinglist.cpp
M +9 -0 src/tournament/ratinglists/ratinglist.h
M +22 -0 src/tournament/tournament.cpp
M +2 -0 src/tournament/tournament.h
https://invent.kde.org/games/chessament/-/commit/fc084b50699a1d10ed12984548f6707c1d2507ec
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 95c89ee..cc8d068 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -35,6 +35,7 @@ ecm_add_qml_module(chessament_static
qml/PairRoundDialog.qml
qml/PlayersPage.qml
qml/PlayersPageTableDelegate.qml
+ qml/UpdateRatingsDialog.qml
qml/WelcomePage.qml
# Player details
diff --git a/src/playersmodel.cpp b/src/playersmodel.cpp
index 432f79e..ada0b85 100644
--- a/src/playersmodel.cpp
+++ b/src/playersmodel.cpp
@@ -300,6 +300,21 @@ void PlayersModel::deletePlayer(const QModelIndex &index)
endRemoveRows();
}
+void PlayersModel::updateRatings(int listId)
+{
+ m_tournament->updateRatings(listId);
+
+ const int ratingColumn = static_cast<int>(m_columns.indexOf(PlayersModel::Columns::Rating));
+ if (ratingColumn >= 0) {
+ Q_EMIT dataChanged(index(0, ratingColumn), index(rowCount() - 1, ratingColumn));
+ }
+
+ const int nationalRatingColumn = static_cast<int>(m_columns.indexOf(PlayersModel::Columns::NationalRating));
+ if (nationalRatingColumn >= 0) {
+ Q_EMIT dataChanged(index(0, nationalRatingColumn), index(rowCount() - 1, nationalRatingColumn));
+ }
+}
+
void PlayersModel::updatePlayer(Player *player)
{
Q_EMIT dataChanged(index(player->startingRank() - 1, 0), index(player->startingRank() - 1, columnCount() - 1), {});
diff --git a/src/playersmodel.h b/src/playersmodel.h
index fe8ed17..c76dd1d 100644
--- a/src/playersmodel.h
+++ b/src/playersmodel.h
@@ -61,6 +61,9 @@ public:
const QString &origin,
const QString &gender);
Q_INVOKABLE void deletePlayer(const QModelIndex &index);
+
+ Q_INVOKABLE void updateRatings(int listId);
+
void updatePlayer(Player *player);
Q_SIGNALS:
diff --git a/src/qml/PlayersPage.qml b/src/qml/PlayersPage.qml
index 6d92719..5114100 100644
--- a/src/qml/PlayersPage.qml
+++ b/src/qml/PlayersPage.qml
@@ -108,6 +108,15 @@ TablePage {
enabled: root.tableView.currentRow >= 0
onTriggered: root.openPlayerDetails()
},
+ Kirigami.Action {
+ icon.name: "view-refresh-symbolic"
+ text: KI18n.i18nc("@action Update players ratings", "Update ratings…")
+ enabled: Config.developer && root.tableView.rows > 0
+ onTriggered: {
+ const dialog = Qt.createComponent("org.kde.chessament", "UpdateRatingsDialog").createObject(root.Controls.ApplicationWindow.window, {}) as UpdateRatingsDialog;
+ dialog.open();
+ }
+ },
Kirigami.Action {
icon.name: "view-sort-symbolic"
text: KI18n.i18nc("@action:intoolbar", "Sort Players…")
diff --git a/src/qml/UpdateRatingsDialog.qml b/src/qml/UpdateRatingsDialog.qml
new file mode 100644
index 0000000..3c0f6f4
--- /dev/null
+++ b/src/qml/UpdateRatingsDialog.qml
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+// SPDX-FileCopyrightText: 2026 Manuel Alcaraz Zambrano <[email protected]>
+
+pragma ComponentBehavior: Bound
+
+import QtQuick
+import QtQuick.Controls as Controls
+
+import org.kde.ki18n
+import org.kde.kirigamiaddons.formcard as FormCard
+
+import org.kde.chessament
+
+FormCard.FormCardDialog {
+ id: root
+
+ title: KI18n.i18nc("@title", "Update Ratings")
+
+ onAccepted: {
+ Controller.playersModel.updateRatings(ratingList.currentValue);
+ }
+
+ FormCard.FormComboBoxDelegate {
+ id: ratingList
+ text: KI18n.i18nc("@label:listbox", "Choose a rating list:")
+ model: RatingListModel {}
+ textRole: "name"
+ valueRole: "listId"
+ }
+
+ footer: Controls.DialogButtonBox {
+ standardButtons: Controls.Dialog.Cancel
+
+ Controls.Button {
+ text: KI18n.i18nc("@action:button Update players ratings", "Update")
+ icon.name: "view-refresh-symbolic"
+ enabled: ratingList.currentValue > 0
+ Controls.DialogButtonBox.buttonRole: Controls.DialogButtonBox.AcceptRole
+ }
+ }
+}
diff --git a/src/tournament/ratinglists/ratinglist.cpp b/src/tournament/ratinglists/ratinglist.cpp
index bfa342d..c2627cb 100644
--- a/src/tournament/ratinglists/ratinglist.cpp
+++ b/src/tournament/ratinglists/ratinglist.cpp
@@ -371,8 +371,6 @@ std::expected<QList<RatingListPlayer>, QString> RatingList::searchPlayers(const
return std::unexpected(db.error());
}
- QList<RatingListPlayer> players{};
-
QSqlQuery query(*db);
query.prepare(SEARCH_PLAYERS_QUERY);
query.bindValue(u":search"_s, u"%%1%"_s.arg(text));
@@ -381,54 +379,32 @@ std::expected<QList<RatingListPlayer>, QString> RatingList::searchPlayers(const
return std::unexpected(query.lastError().text());
}
- const int idNo = query.record().indexOf("playerId");
- const int nameNo = query.record().indexOf("name");
- const int federationNo = query.record().indexOf("federation");
- const int genderNo = query.record().indexOf("gender");
- const int titleNo = query.record().indexOf("title");
- const int birthDayNo = query.record().indexOf("birthday");
- const int standardNo = query.record().indexOf("standard");
- const int rapidNo = query.record().indexOf("rapid");
- const int blitzNo = query.record().indexOf("blitz");
- const int nationalIdNo = query.record().indexOf("nationalId");
- const int nationalRatingNo = query.record().indexOf("nationalRating");
- const int extraNo = query.record().indexOf("extra");
+ return loadPlayers(query);
+}
- while (query.next()) {
- const auto id = query.value(idNo).toString();
- const auto name = query.value(nameNo).toString();
- const auto federation = query.value(federationNo).toString();
- const auto gender = query.value(genderNo).toString();
- const auto title = query.value(titleNo).toString();
- const auto birthDate = query.value(birthDayNo).toString();
- const auto standardRating = query.value(standardNo).toInt();
- const auto rapidRating = query.value(rapidNo).toInt();
- const auto blitzRating = query.value(blitzNo).toInt();
- const auto nationalId = query.value(nationalIdNo).toString();
- const auto nationalRating = query.value(nationalRatingNo).toInt();
+std::optional<RatingListPlayer> RatingList::searchPlayer(const QString &playerId, int listId)
+{
+ auto db = getDb();
+ if (!db) {
+ return std::nullopt;
+ }
- const auto extra = query.value(extraNo).toByteArray();
- const auto extraJson = QJsonDocument::fromJson(extra);
+ QSqlQuery query(*db);
+ query.prepare(SEARCH_PLAYER_QUERY);
+ query.bindValue(u":playerId"_s, playerId);
+ query.bindValue(u":listId"_s, listId);
- const auto player = RatingListPlayer{
- id,
- name,
- federation,
- gender,
- title,
- birthDate,
- standardRating,
- rapidRating,
- blitzRating,
- nationalId,
- nationalRating,
- extraJson.object(),
- };
+ if (!query.exec()) {
+ return std::nullopt;
+ }
- players << player;
+ const auto players = loadPlayers(query);
+
+ if (players.isEmpty()) {
+ return std::nullopt;
}
- return players;
+ return players.first();
}
std::expected<void, QString> RatingList::savePlayers(const QList<RatingListPlayer> &players)
@@ -498,4 +474,58 @@ std::expected<void, QString> RatingList::savePlayers(const QList<RatingListPlaye
return {};
}
+QList<RatingListPlayer> RatingList::loadPlayers(QSqlQuery &query)
+{
+ QList<RatingListPlayer> players{};
+
+ const int idNo = query.record().indexOf("playerId");
+ const int nameNo = query.record().indexOf("name");
+ const int federationNo = query.record().indexOf("federation");
+ const int genderNo = query.record().indexOf("gender");
+ const int titleNo = query.record().indexOf("title");
+ const int birthDayNo = query.record().indexOf("birthday");
+ const int standardNo = query.record().indexOf("standard");
+ const int rapidNo = query.record().indexOf("rapid");
+ const int blitzNo = query.record().indexOf("blitz");
+ const int nationalIdNo = query.record().indexOf("nationalId");
+ const int nationalRatingNo = query.record().indexOf("nationalRating");
+ const int extraNo = query.record().indexOf("extra");
+
+ while (query.next()) {
+ const auto id = query.value(idNo).toString();
+ const auto name = query.value(nameNo).toString();
+ const auto federation = query.value(federationNo).toString();
+ const auto gender = query.value(genderNo).toString();
+ const auto title = query.value(titleNo).toString();
+ const auto birthDate = query.value(birthDayNo).toString();
+ const auto standardRating = query.value(standardNo).toInt();
+ const auto rapidRating = query.value(rapidNo).toInt();
+ const auto blitzRating = query.value(blitzNo).toInt();
+ const auto nationalId = query.value(nationalIdNo).toString();
+ const auto nationalRating = query.value(nationalRatingNo).toInt();
+
+ const auto extra = query.value(extraNo).toByteArray();
+ const auto extraJson = QJsonDocument::fromJson(extra);
+
+ const auto player = RatingListPlayer{
+ id,
+ name,
+ federation,
+ gender,
+ title,
+ birthDate,
+ standardRating,
+ rapidRating,
+ blitzRating,
+ nationalId,
+ nationalRating,
+ extraJson.object(),
+ };
+
+ players << player;
+ }
+
+ return players;
+}
+
#include "moc_ratinglist.cpp"
diff --git a/src/tournament/ratinglists/ratinglist.h b/src/tournament/ratinglists/ratinglist.h
index 18e48ca..1fef506 100644
--- a/src/tournament/ratinglists/ratinglist.h
+++ b/src/tournament/ratinglists/ratinglist.h
@@ -14,6 +14,7 @@
#include "ratinglistplayer.h"
class QSqlDatabase;
+class QSqlQuery;
class RatingListReader;
using namespace Qt::StringLiterals;
@@ -65,6 +66,10 @@ constexpr auto ADD_RATING_LIST_PLAYER_QUERY =
static const auto SEARCH_PLAYERS_QUERY =
u"SELECT playerId, name, federation, gender, title, birthday, standard, rapid, blitz, nationalId, nationalRating, json(extra) as extra FROM players WHERE name LIKE :search LIMIT 20;"_s;
+static const QString SEARCH_PLAYER_QUERY =
+ u"SELECT playerId, name, federation, gender, title, birthday, standard, rapid, blitz, nationalId, nationalRating, json(extra) as extra "
+ "FROM players WHERE list = :listId AND playerId = :playerId LIMIT 1;"_s;
+
static constexpr auto RATING_LISTS_DB_CONNECTION_NAME = "rating-lists"_L1;
static constexpr auto RATING_LISTS_DB_CONNECTION_NAME_WRITER = "rating-lists-writer"_L1;
@@ -93,6 +98,8 @@ public:
static std::expected<QList<RatingListPlayer>, QString> searchPlayers(const QString &text);
+ static std::optional<RatingListPlayer> searchPlayer(const QString &playerId, int listId);
+
public Q_SLOTS:
void setExtra(const QByteArray &extra);
@@ -107,6 +114,8 @@ private:
std::expected<uint, QString> processFile(QByteArray content, const QMimeType &mime);
std::expected<void, QString> savePlayers(const QList<RatingListPlayer> &players);
+ static QList<RatingListPlayer> loadPlayers(QSqlQuery &query);
+
int m_id{};
QString m_name;
QString m_url;
diff --git a/src/tournament/tournament.cpp b/src/tournament/tournament.cpp
index 08bb980..128a361 100644
--- a/src/tournament/tournament.cpp
+++ b/src/tournament/tournament.cpp
@@ -12,6 +12,7 @@
#include "db.h"
#include "event.h"
+#include "ratinglists/ratinglist.h"
#include "state.h"
#include "tiebreaks/aob.h"
#include "tiebreaks/buchholz.h"
@@ -333,6 +334,27 @@ void Tournament::sortPlayers()
}
}
+void Tournament::updateRatings(int listId)
+{
+ const auto &players = m_players;
+ for (const auto &player : players) {
+ const auto listPlayer = RatingList::searchPlayer(player->playerId(), listId);
+
+ if (!listPlayer) {
+ continue;
+ }
+
+ if (listPlayer->standardRating() == player->rating() && listPlayer->nationalRating() == player->nationalRating()) {
+ continue;
+ }
+
+ player->setRating(listPlayer->standardRating());
+ player->setNationalRating(listPlayer->nationalRating());
+
+ savePlayer(player.get());
+ }
+}
+
int Tournament::changePlayerStartingRank(Player *player, int startingRank)
{
Q_ASSERT(startingRank >= 1);
diff --git a/src/tournament/tournament.h b/src/tournament/tournament.h
index 7572819..1654ce2 100644
--- a/src/tournament/tournament.h
+++ b/src/tournament/tournament.h
@@ -140,6 +140,8 @@ public:
*/
void sortPlayers();
+ void updateRatings(int listId);
+
/*!
* Changes the starting rank of \a player to \a startingRank.
*