annotate src/core/anime_db.cc @ 118:39521c47c7a3

*: another huge megacommit, SORRY The torrents page works a lot better now Added the edit option to the anime list right click menu Vectorized currently playing files Available player and extensions are now loaded at runtime from files in (dotpath)/players.json and (dotpath)/extensions.json These paths are not permanent and will likely be moved to (dotpath)/recognition ... ... ...
author Paper <mrpapersonic@gmail.com>
date Tue, 07 Nov 2023 23:40:54 -0500
parents d02fdf1d6708
children de0a8d2f28b3
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
10
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
1 #include "core/anime_db.h"
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
2 #include "core/anime.h"
64
fe719c109dbc *: update
Paper <mrpapersonic@gmail.com>
parents: 11
diff changeset
3 #include "core/strings.h"
fe719c109dbc *: update
Paper <mrpapersonic@gmail.com>
parents: 11
diff changeset
4 #include <QDebug>
10
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
5
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
6 namespace Anime {
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
7
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
8 int Database::GetTotalAnimeAmount() {
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
9 int total = 0;
11
fc1bf97c528b *: use C++11 standard
Paper <mrpapersonic@gmail.com>
parents: 10
diff changeset
10 for (const auto& a : items) {
fc1bf97c528b *: use C++11 standard
Paper <mrpapersonic@gmail.com>
parents: 10
diff changeset
11 if (a.second.IsInUserList())
10
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
12 total++;
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
13 }
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
14 return total;
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
15 }
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
16
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
17 int Database::GetListsAnimeAmount(ListStatus status) {
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
18 if (status == ListStatus::NOT_IN_LIST)
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
19 return 0;
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
20 int total = 0;
11
fc1bf97c528b *: use C++11 standard
Paper <mrpapersonic@gmail.com>
parents: 10
diff changeset
21 for (const auto& a : items) {
fc1bf97c528b *: use C++11 standard
Paper <mrpapersonic@gmail.com>
parents: 10
diff changeset
22 if (a.second.IsInUserList() && a.second.GetUserStatus() == status)
10
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
23 total++;
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
24 }
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
25 return total;
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
26 }
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
27
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
28 int Database::GetTotalEpisodeAmount() {
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
29 int total = 0;
11
fc1bf97c528b *: use C++11 standard
Paper <mrpapersonic@gmail.com>
parents: 10
diff changeset
30 for (const auto& a : items) {
fc1bf97c528b *: use C++11 standard
Paper <mrpapersonic@gmail.com>
parents: 10
diff changeset
31 if (a.second.IsInUserList()) {
fc1bf97c528b *: use C++11 standard
Paper <mrpapersonic@gmail.com>
parents: 10
diff changeset
32 total += a.second.GetUserRewatchedTimes() * a.second.GetEpisodes();
fc1bf97c528b *: use C++11 standard
Paper <mrpapersonic@gmail.com>
parents: 10
diff changeset
33 total += a.second.GetUserProgress();
10
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
34 }
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
35 }
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
36 return total;
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
37 }
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
38
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
39 /* Returns the total watched amount in minutes. */
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
40 int Database::GetTotalWatchedAmount() {
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
41 int total = 0;
11
fc1bf97c528b *: use C++11 standard
Paper <mrpapersonic@gmail.com>
parents: 10
diff changeset
42 for (const auto& a : items) {
fc1bf97c528b *: use C++11 standard
Paper <mrpapersonic@gmail.com>
parents: 10
diff changeset
43 if (a.second.IsInUserList()) {
fc1bf97c528b *: use C++11 standard
Paper <mrpapersonic@gmail.com>
parents: 10
diff changeset
44 total += a.second.GetDuration() * a.second.GetUserProgress();
fc1bf97c528b *: use C++11 standard
Paper <mrpapersonic@gmail.com>
parents: 10
diff changeset
45 total += a.second.GetEpisodes() * a.second.GetDuration() * a.second.GetUserRewatchedTimes();
10
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
46 }
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
47 }
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
48 return total;
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
49 }
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
50
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
51 /* Returns the total planned amount in minutes.
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
52 Note that we should probably limit progress to the
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
53 amount of episodes, as AniList will let you
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
54 set episode counts up to 32768. But that should
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
55 rather be handled elsewhere. */
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
56 int Database::GetTotalPlannedAmount() {
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
57 int total = 0;
11
fc1bf97c528b *: use C++11 standard
Paper <mrpapersonic@gmail.com>
parents: 10
diff changeset
58 for (const auto& a : items) {
fc1bf97c528b *: use C++11 standard
Paper <mrpapersonic@gmail.com>
parents: 10
diff changeset
59 if (a.second.IsInUserList())
fc1bf97c528b *: use C++11 standard
Paper <mrpapersonic@gmail.com>
parents: 10
diff changeset
60 total += a.second.GetDuration() * (a.second.GetEpisodes() - a.second.GetUserProgress());
10
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
61 }
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
62 return total;
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
63 }
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
64
83
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
65 /* In Taiga this is called a mean, but "average" is
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
66 what's primarily used in conversation, at least
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
67 in the U.S. */
10
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
68 double Database::GetAverageScore() {
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
69 double avg = 0;
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
70 int amt = 0;
11
fc1bf97c528b *: use C++11 standard
Paper <mrpapersonic@gmail.com>
parents: 10
diff changeset
71 for (const auto& a : items) {
fc1bf97c528b *: use C++11 standard
Paper <mrpapersonic@gmail.com>
parents: 10
diff changeset
72 if (a.second.IsInUserList() && a.second.GetUserScore()) {
fc1bf97c528b *: use C++11 standard
Paper <mrpapersonic@gmail.com>
parents: 10
diff changeset
73 avg += a.second.GetUserScore();
10
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
74 amt++;
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
75 }
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
76 }
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
77 return avg / amt;
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
78 }
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
79
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
80 double Database::GetScoreDeviation() {
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
81 double squares_sum = 0, avg = GetAverageScore();
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
82 int amt = 0;
11
fc1bf97c528b *: use C++11 standard
Paper <mrpapersonic@gmail.com>
parents: 10
diff changeset
83 for (const auto& a : items) {
fc1bf97c528b *: use C++11 standard
Paper <mrpapersonic@gmail.com>
parents: 10
diff changeset
84 if (a.second.IsInUserList() && a.second.GetUserScore()) {
64
fe719c109dbc *: update
Paper <mrpapersonic@gmail.com>
parents: 11
diff changeset
85 squares_sum += std::pow(static_cast<double>(a.second.GetUserScore()) - avg, 2);
10
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
86 amt++;
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
87 }
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
88 }
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
89 return (amt > 0) ? std::sqrt(squares_sum / amt) : 0;
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
90 }
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
91
83
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
92 template <typename T, typename U>
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
93 static T get_lowest_in_map(const std::unordered_map<T, U>& map) {
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
94 if (map.size() <= 0)
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
95 return 0;
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
96 T id;
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
97 U ret = std::numeric_limits<U>::max();
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
98 for (const auto& t : map) {
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
99 if (t.second < ret) {
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
100 ret = t.second;
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
101 id = t.first;
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
102 }
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
103 }
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
104 return id;
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
105 }
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
106
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
107 /* This is really fugly but WHO CARES :P
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
108
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
109 This sort of ""advanced"" algorithm is only in effect because
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
110 there are some special cases, e.g. Another and Re:ZERO, where
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
111 we get the wrong match, so we have to create Advanced Techniques
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
112 to solve this
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
113
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
114 This algorithm:
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
115 1. searches each anime item for a match to the preferred title
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
116 AND all synonyms and marks those matches with
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
117 `synonym.length() - (synonym.find(needle) + needle.length());`
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
118 which, on a title that exactly matches, will be 0
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
119 2. returns the id of the match that is the lowest, which will most
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
120 definitely match anything that exactly matches the title of the
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
121 filename */
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
122 int Database::GetAnimeFromTitle(const std::string& title) {
64
fe719c109dbc *: update
Paper <mrpapersonic@gmail.com>
parents: 11
diff changeset
123 if (title.empty())
fe719c109dbc *: update
Paper <mrpapersonic@gmail.com>
parents: 11
diff changeset
124 return 0;
83
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
125 std::unordered_map<int, long long> map;
64
fe719c109dbc *: update
Paper <mrpapersonic@gmail.com>
parents: 11
diff changeset
126 for (const auto& a : items) {
83
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
127 long long ret = a.second.GetUserPreferredTitle().find(title);
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
128 if (ret != static_cast<long long>(std::string::npos)) {
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
129 map[a.second.GetId()] = a.second.GetUserPreferredTitle().length() - (ret + title.length());
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
130 continue;
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
131 }
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
132 for (const auto& synonym : a.second.GetTitleSynonyms()) {
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
133 ret = synonym.find(title);
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
134 if (ret != static_cast<long long>(std::string::npos)) {
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
135 map[a.second.GetId()] = synonym.length() - (ret + title.length());
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
136 continue;
64
fe719c109dbc *: update
Paper <mrpapersonic@gmail.com>
parents: 11
diff changeset
137 }
fe719c109dbc *: update
Paper <mrpapersonic@gmail.com>
parents: 11
diff changeset
138 }
fe719c109dbc *: update
Paper <mrpapersonic@gmail.com>
parents: 11
diff changeset
139 }
83
d02fdf1d6708 *: huuuge update
Paper <mrpapersonic@gmail.com>
parents: 81
diff changeset
140 return get_lowest_in_map(map);
64
fe719c109dbc *: update
Paper <mrpapersonic@gmail.com>
parents: 11
diff changeset
141 }
fe719c109dbc *: update
Paper <mrpapersonic@gmail.com>
parents: 11
diff changeset
142
11
fc1bf97c528b *: use C++11 standard
Paper <mrpapersonic@gmail.com>
parents: 10
diff changeset
143 Database db;
fc1bf97c528b *: use C++11 standard
Paper <mrpapersonic@gmail.com>
parents: 10
diff changeset
144
9
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
145 } // namespace Anime