# HG changeset patch # User Paper # Date 1701801923 18000 # Node ID 62e336597bb76004e37499fc9824dad84697636b # Parent 09492158bcc54d350c817a377153d05950a1a5d2 anime list: add support for different score formats diff -r 09492158bcc5 -r 62e336597bb7 include/core/anime.h --- a/include/core/anime.h Mon Dec 04 13:44:42 2023 -0500 +++ b/include/core/anime.h Tue Dec 05 13:45:23 2023 -0500 @@ -62,10 +62,18 @@ NB_SERVICES }; +enum class ScoreFormat { + POINT_100, // 0-100 + POINT_10_DECIMAL, // 0.0-10.0 + POINT_10, // 0-10 + POINT_5, // 0-5, should be represented in stars + POINT_3 // 1-3, should be represented in smileys +}; + struct ListInformation { int id = 0; int progress = 0; - int score = 0; // always in the AniList 100-based form internally + int score = 0; // note that this will ALWAYS be in POINT_100 format and must be converted ListStatus status = ListStatus::NOT_IN_LIST; Date started; Date completed; @@ -103,6 +111,7 @@ ListStatus GetUserStatus() const; int GetUserProgress() const; int GetUserScore() const; + std::string GetUserPresentableScore() const; Date GetUserDateStarted() const; Date GetUserDateCompleted() const; bool GetUserIsPrivate() const; diff -r 09492158bcc5 -r 62e336597bb7 include/core/config.h --- a/include/core/config.h Mon Dec 04 13:44:42 2023 -0500 +++ b/include/core/config.h Tue Dec 05 13:45:23 2023 -0500 @@ -28,6 +28,7 @@ struct { public: Anime::TitleLanguage language; + Anime::ScoreFormat score_format; bool display_aired_episodes; bool display_available_episodes; bool highlight_anime_if_available; diff -r 09492158bcc5 -r 62e336597bb7 include/gui/translate/anime.h --- a/include/gui/translate/anime.h Mon Dec 04 13:44:42 2023 -0500 +++ b/include/gui/translate/anime.h Tue Dec 05 13:45:23 2023 -0500 @@ -1,3 +1,6 @@ +#ifndef __gui__translate__anime_h +#define __gui__translate__anime_h + #include "core/anime.h" namespace Translate { @@ -8,6 +11,7 @@ std::string ToString(const Anime::SeriesStatus status); std::string ToString(const Anime::Services service); std::string ToString(const Anime::TitleLanguage language); +std::string ToString(const Anime::ScoreFormat format); std::string ToLocalString(const Anime::ListStatus status); std::string ToLocalString(const Anime::SeriesFormat format); @@ -22,5 +26,8 @@ Anime::SeriesStatus ToSeriesStatus(const std::string& str); Anime::Services ToService(const std::string& str); Anime::TitleLanguage ToLanguage(const std::string& str); +Anime::ScoreFormat ToScoreFormat(const std::string& str); } // namespace Translate + +#endif // __gui__translate__anime_h diff -r 09492158bcc5 -r 62e336597bb7 src/core/anime.cc --- a/src/core/anime.cc Mon Dec 04 13:44:42 2023 -0500 +++ b/src/core/anime.cc Tue Dec 05 13:45:23 2023 -0500 @@ -42,6 +42,45 @@ return list_info_->score; } +std::string Anime::GetUserPresentableScore() const { + assert(list_info_.get()); + const int score = list_info_->score; + if (score == 0) + return ""; + + switch (session.config.anime_list.score_format) { + case ScoreFormat::POINT_10_DECIMAL: { + std::ostringstream out; + out.precision(1); + out << std::fixed << (static_cast(score) / 10); + return std::move(out).str(); + } + case ScoreFormat::POINT_10: + return std::to_string(score / 10); + case ScoreFormat::POINT_5: { + std::string stars = ""; + + for (int i = 0; i < 100; i += 20) + stars.append((i <= score) ? "★" : "☆"); + + return stars; + } + case ScoreFormat::POINT_3: { + if (score >= 100) + return ":)"; + else if (score >= 66) + return ":|"; + else if (score >= 33) + return ":("; + else + return ""; + } + default: + case ScoreFormat::POINT_100: + return std::to_string(score); + } +} + Date Anime::GetUserDateStarted() const { assert(list_info_.get()); return list_info_->started; diff -r 09492158bcc5 -r 62e336597bb7 src/core/config.cc --- a/src/core/config.cc Mon Dec 04 13:44:42 2023 -0500 +++ b/src/core/config.cc Tue Dec 05 13:45:23 2023 -0500 @@ -35,6 +35,7 @@ service = Translate::ToService(INI::GetIniValue(ini, "General", "Service", "None")); + anime_list.score_format = Translate::ToScoreFormat(INI::GetIniValue(ini, "Anime List", "Score format", "POINT_100")); anime_list.language = Translate::ToLanguage(INI::GetIniValue(ini, "Anime List", "Title language", "Romaji")); anime_list.display_aired_episodes = INI::GetIniValue(ini, "Anime List", "Display only aired episodes", true); anime_list.display_available_episodes = INI::GetIniValue(ini, "Anime List", "Display only available episodes in library", true); @@ -68,9 +69,8 @@ return false; recognition.players.reserve(players.size()); - for (const auto& player : players) { + for (const auto& player : players) recognition.players.push_back({true, player}); - } } for (auto& [enabled, player] : recognition.players) { @@ -103,6 +103,7 @@ INI::SetIniValue(ini, "General", "Service", service); INI::SetIniValue(ini, "General", "Locale", locale.GetLocale().name()); + INI::SetIniValue(ini, "Anime List", "Score format", Translate::ToString(anime_list.score_format)); INI::SetIniValue(ini, "Anime List", "Title language", anime_list.language); INI::SetIniValue(ini, "Anime List", "Display only aired episodes", anime_list.display_aired_episodes); INI::SetIniValue(ini, "Anime List", "Display only available episodes in library", anime_list.display_available_episodes); diff -r 09492158bcc5 -r 62e336597bb7 src/gui/pages/anime_list.cc --- a/src/gui/pages/anime_list.cc Mon Dec 04 13:44:42 2023 -0500 +++ b/src/gui/pages/anime_list.cc Tue Dec 05 13:45:23 2023 -0500 @@ -107,12 +107,12 @@ switch (role) { case Qt::DisplayRole: switch (index.column()) { - case AL_TITLE: return QString::fromUtf8(list[index.row()].GetUserPreferredTitle().c_str()); + case AL_TITLE: return Strings::ToQString(list[index.row()].GetUserPreferredTitle()); case AL_PROGRESS: return QString::number(list[index.row()].GetUserProgress()) + "/" + QString::number(list[index.row()].GetEpisodes()); case AL_EPISODES: return list[index.row()].GetEpisodes(); - case AL_SCORE: return list[index.row()].GetUserScore(); + case AL_SCORE: return Strings::ToQString(list[index.row()].GetUserPresentableScore()); case AL_TYPE: return Strings::ToQString(Translate::ToString(list[index.row()].GetFormat())); case AL_SEASON: return Strings::ToQString(Translate::ToString(list[index.row()].GetSeason())) + " " + @@ -124,15 +124,16 @@ if (list[index.row()].GetUserTimeUpdated() == 0) return QString("-"); Time::Duration duration(Time::GetSystemTime() - list[index.row()].GetUserTimeUpdated()); - return QString::fromUtf8(duration.AsRelativeString().c_str()); + return Strings::ToQString(duration.AsRelativeString()); } - case AL_NOTES: return QString::fromUtf8(list[index.row()].GetUserNotes().c_str()); + case AL_NOTES: return Strings::ToQString(list[index.row()].GetUserNotes()); default: return ""; } break; case Qt::UserRole: switch (index.column()) { case AL_PROGRESS: return list[index.row()].GetUserProgress(); + case AL_SCORE: return list[index.row()].GetUserScore(); case AL_TYPE: return static_cast(list[index.row()].GetFormat()); case AL_SEASON: return list[index.row()].GetAirDate().GetAsQDate(); case AL_AVG_SCORE: return list[index.row()].GetAudienceScore(); diff -r 09492158bcc5 -r 62e336597bb7 src/gui/translate/anime.cc --- a/src/gui/translate/anime.cc Mon Dec 04 13:44:42 2023 -0500 +++ b/src/gui/translate/anime.cc Tue Dec 05 13:45:23 2023 -0500 @@ -71,6 +71,17 @@ } } +std::string ToString(const Anime::ScoreFormat format) { + switch (format) { + case Anime::ScoreFormat::POINT_3: return "POINT_3"; + case Anime::ScoreFormat::POINT_5: return "POINT_5"; + case Anime::ScoreFormat::POINT_10: return "POINT_10"; + case Anime::ScoreFormat::POINT_10_DECIMAL: return "POINT_10_DECIMAL"; + default: + case Anime::ScoreFormat::POINT_100: return "POINT_100"; + } +} + Anime::ListStatus ToListStatus(const std::string& str) { const std::unordered_map map = { {"Currently watching", Anime::ListStatus::CURRENT}, @@ -150,6 +161,20 @@ return map.at(str); } +Anime::ScoreFormat ToScoreFormat(const std::string& str) { + const std::unordered_map map = { + {"POINT_3", Anime::ScoreFormat::POINT_3}, + {"POINT_5", Anime::ScoreFormat::POINT_5}, + {"POINT_10", Anime::ScoreFormat::POINT_10}, + {"POINT_10_DECIMAL", Anime::ScoreFormat::POINT_10_DECIMAL}, + {"POINT_100", Anime::ScoreFormat::POINT_100} + }; + + if (map.find(str) == map.end()) + return Anime::ScoreFormat::POINT_100; + return map.at(str); +} + /* Localized versions of ToString() functions */ std::string ToLocalString(const Anime::ListStatus status) { diff -r 09492158bcc5 -r 62e336597bb7 src/services/anilist.cc --- a/src/services/anilist.cc Mon Dec 04 13:44:42 2023 -0500 +++ b/src/services/anilist.cc Tue Dec 05 13:45:23 2023 -0500 @@ -18,13 +18,13 @@ #include -#define CLIENT_ID "13706" - using namespace nlohmann::literals::json_literals; namespace Services { namespace AniList { +constexpr int CLIENT_ID = 13706; + class Account { public: std::string Username() const { return session.config.auth.anilist.username; } @@ -305,7 +305,7 @@ bool AuthorizeUser() { /* Prompt for PIN */ QDesktopServices::openUrl( - QUrl("https://anilist.co/api/v2/oauth/authorize?client_id=" CLIENT_ID "&response_type=token")); + QUrl(Strings::ToQString("https://anilist.co/api/v2/oauth/authorize?client_id=" + std::to_string(CLIENT_ID) + "&response_type=token"))); bool ok; QString token = QInputDialog::getText(