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