Mercurial > minori
comparison src/core/anime_db.cc @ 173:de0a8d2f28b3
WILL NOT COMPILE: sample export ability for anime db
| author | Paper <mrpapersonic@gmail.com> |
|---|---|
| date | Tue, 28 Nov 2023 13:53:54 -0500 |
| parents | d02fdf1d6708 |
| children | f88eda79c60a |
comparison
equal
deleted
inserted
replaced
| 172:45a0967485f1 | 173:de0a8d2f28b3 |
|---|---|
| 1 #include "core/anime_db.h" | 1 #include "core/anime_db.h" |
| 2 #include "core/anime.h" | 2 #include "core/anime.h" |
| 3 #include "core/strings.h" | 3 #include "core/strings.h" |
| 4 #include "core/json.h" | |
| 5 | |
| 4 #include <QDebug> | 6 #include <QDebug> |
| 5 | 7 |
| 6 namespace Anime { | 8 namespace Anime { |
| 7 | 9 |
| 8 int Database::GetTotalAnimeAmount() { | 10 int Database::GetTotalAnimeAmount() { |
| 91 | 93 |
| 92 template <typename T, typename U> | 94 template <typename T, typename U> |
| 93 static T get_lowest_in_map(const std::unordered_map<T, U>& map) { | 95 static T get_lowest_in_map(const std::unordered_map<T, U>& map) { |
| 94 if (map.size() <= 0) | 96 if (map.size() <= 0) |
| 95 return 0; | 97 return 0; |
| 96 T id; | 98 |
| 99 T id = 0; | |
| 97 U ret = std::numeric_limits<U>::max(); | 100 U ret = std::numeric_limits<U>::max(); |
| 98 for (const auto& t : map) { | 101 for (const auto& t : map) { |
| 99 if (t.second < ret) { | 102 if (t.second < ret) { |
| 100 ret = t.second; | 103 ret = t.second; |
| 101 id = t.first; | 104 id = t.first; |
| 104 return id; | 107 return id; |
| 105 } | 108 } |
| 106 | 109 |
| 107 /* This is really fugly but WHO CARES :P | 110 /* This is really fugly but WHO CARES :P |
| 108 | 111 |
| 109 This sort of ""advanced"" algorithm is only in effect because | 112 This fairly basic algorithm is only in effect because |
| 110 there are some special cases, e.g. Another and Re:ZERO, where | 113 there are some special cases, e.g. Another and Re:ZERO, where |
| 111 we get the wrong match, so we have to create Advanced Techniques | 114 we get the wrong match, so we have to create Advanced Techniques |
| 112 to solve this | 115 to solve this |
| 113 | 116 |
| 114 This algorithm: | 117 This algorithm: |
| 115 1. searches each anime item for a match to the preferred title | 118 1. searches each anime item for a match to the preferred title |
| 116 AND all synonyms and marks those matches with | 119 AND all synonyms and marks those matches with |
| 117 `synonym.length() - (synonym.find(needle) + needle.length());` | 120 `synonym.length() - (synonym.find(needle) + needle.length());` |
| 118 which, on a title that exactly matches, will be 0 | 121 which should never be less than zero and will be zero if, and only if |
| 122 the titles match exactly. | |
| 119 2. returns the id of the match that is the lowest, which will most | 123 2. returns the id of the match that is the lowest, which will most |
| 120 definitely match anything that exactly matches the title of the | 124 definitely match anything that exactly matches the title of the |
| 121 filename */ | 125 filename */ |
| 122 int Database::GetAnimeFromTitle(const std::string& title) { | 126 int Database::GetAnimeFromTitle(const std::string& title) { |
| 123 if (title.empty()) | 127 if (title.empty()) |
| 124 return 0; | 128 return 0; |
| 125 std::unordered_map<int, long long> map; | 129 |
| 126 for (const auto& a : items) { | 130 std::unordered_map<int, size_t> map; |
| 127 long long ret = a.second.GetUserPreferredTitle().find(title); | 131 |
| 128 if (ret != static_cast<long long>(std::string::npos)) { | 132 auto process_title = [&map](const Anime& anime, const std::string& title, const std::string& needle) -> bool { |
| 129 map[a.second.GetId()] = a.second.GetUserPreferredTitle().length() - (ret + title.length()); | 133 size_t ret = title.find(needle); |
| 134 if (ret == std::string::npos) | |
| 135 return false; | |
| 136 | |
| 137 map[anime.GetId()] = title.length() - (ret + needle.length()); | |
| 138 return true; | |
| 139 }; | |
| 140 | |
| 141 for (const auto& [id, anime] : items) { | |
| 142 if (process_title(anime, anime.GetUserPreferredTitle(), title)) | |
| 130 continue; | 143 continue; |
| 131 } | 144 |
| 132 for (const auto& synonym : a.second.GetTitleSynonyms()) { | 145 for (const auto& synonym : anime.GetTitleSynonyms()) |
| 133 ret = synonym.find(title); | 146 if (process_title(anime, synonym, title)) |
| 134 if (ret != static_cast<long long>(std::string::npos)) { | |
| 135 map[a.second.GetId()] = synonym.length() - (ret + title.length()); | |
| 136 continue; | 147 continue; |
| 137 } | 148 } |
| 138 } | 149 |
| 139 } | |
| 140 return get_lowest_in_map(map); | 150 return get_lowest_in_map(map); |
| 141 } | 151 } |
| 142 | 152 |
| 153 static bool GetListDataAsJSON(const Anime& anime, nlohmann::json& json) { | |
| 154 if (!anime.IsInUserList()) | |
| 155 return false; | |
| 156 | |
| 157 json = { | |
| 158 {"status", Translate::ToString(anime.GetUserStatus())}, | |
| 159 {"progress", anime.GetUserProgress()}, | |
| 160 {"score", anime.GetUserScore()}, | |
| 161 //{"started", anime.GetUserDateStarted()}, | |
| 162 //{"completed", anime.GetUserDateCompleted()}, | |
| 163 {"private", anime.GetUserIsPrivate()}, | |
| 164 {"rewatched_times", anime.GetUserRewatchedTimes()}, | |
| 165 {"rewatching", anime.GetUserIsRewatching()}, | |
| 166 {"updated", anime.GetUserTimeUpdated()}, | |
| 167 {"notes", anime.GetUserNotes()} | |
| 168 }; | |
| 169 } | |
| 170 | |
| 171 static bool GetAnimeAsJSON(const Anime& anime, nlohmann::json& json) { | |
| 172 json = { | |
| 173 {"id", anime.GetId()}, | |
| 174 {"title", { | |
| 175 {"native", anime.GetNativeTitle()}, | |
| 176 {"romaji", anime.GetRomajiTitle()}, | |
| 177 {"english", anime.GetEnglishTitle()} | |
| 178 }}, | |
| 179 {"synonyms", anime.GetTitleSynonyms()}, | |
| 180 {"episodes", anime.GetEpisodes()}, | |
| 181 {"airing_status", anime.GetAiringStatus()}, | |
| 182 {"air_date", anime.GetAirDate()}, | |
| 183 {"genres", anime.GetGenres()}, | |
| 184 {"producers", anime.GetProducers()}, | |
| 185 {"format", anime.GetFormat()}, | |
| 186 {"season", anime.GetSeason()}, | |
| 187 {"audience_score", anime.GetAudienceScore()}, | |
| 188 {"synopsis", anime.GetSynopsis()}, | |
| 189 {"duration", anime.GetDuration()}, | |
| 190 {"poster_url", anime.GetPosterUrl()}, | |
| 191 {"service_url", anime.GetServiceUrl()} | |
| 192 }; | |
| 193 | |
| 194 nlohmann::json user; | |
| 195 if (GetListDataAsJSON(anime, user)) | |
| 196 json.push_back({"list_data", user}); | |
| 197 | |
| 198 return true; | |
| 199 } | |
| 200 | |
| 201 bool Database::GetDatabaseAsJSON(nlohmann::json& json) { | |
| 202 for (const auto& [id, anime] : items) { | |
| 203 nlohmann::json anime_json; | |
| 204 GetAnimeAsJSON(anime, anime_json); | |
| 205 json.push_back(anime_json); | |
| 206 } | |
| 207 return true; | |
| 208 } | |
| 209 | |
| 143 Database db; | 210 Database db; |
| 144 | 211 |
| 145 } // namespace Anime | 212 } // namespace Anime |
