comparison src/gui/pages/statistics.cc @ 250:c130f47f6f48

*: many many changes e.g. the search page is actually implemented now!
author Paper <paper@paper.us.eu.org>
date Sun, 04 Feb 2024 21:17:17 -0500
parents 4d461ef7d424
children d14f8e0e40c3
comparison
equal deleted inserted replaced
249:6b2441c776dd 250:c130f47f6f48
12 #include <QTimer> 12 #include <QTimer>
13 #include <QVBoxLayout> 13 #include <QVBoxLayout>
14 #include <QWidget> 14 #include <QWidget>
15 15
16 #include <sstream> 16 #include <sstream>
17 #include <cmath>
18
19 enum class TimeUnits {
20 SECONDS,
21 MINUTES
22 };
17 23
18 StatisticsPage::StatisticsPage(QWidget* parent) : QFrame(parent) { 24 StatisticsPage::StatisticsPage(QWidget* parent) : QFrame(parent) {
19 QVBoxLayout* layout = new QVBoxLayout(this); 25 QVBoxLayout* layout = new QVBoxLayout(this);
20 26
21 setFrameShape(QFrame::Box); 27 setFrameShape(QFrame::Box);
72 78
73 void StatisticsPage::showEvent(QShowEvent*) { 79 void StatisticsPage::showEvent(QShowEvent*) {
74 UpdateStatistics(); 80 UpdateStatistics();
75 } 81 }
76 82
77 /* me abusing macros :) */ 83 /* [in] enum TimeUnits unit:
78 static void add_time_segment(std::ostringstream& str, int x, const std::string_view& s, const std::string_view& p) { 84 * which unit to stop on
79 if (x > 0) 85 * [in] int amount:
80 str << x << ((x == 1) ? s : p); 86 * amount of units to parse
81 } 87 * [in, defaults to 1.0] double unit_in_seconds:
88 * equivalent of one of 'amount' in seconds, e.g. minutes would be 60.0
89 */
90 static std::string TimeToDateString(TimeUnits unit, int amount, double unit_in_seconds = 1.0) {
91 /* avoid calculating this twice */
92 const double years_conv = (31556952.0 / unit_in_seconds);
93 const double months_conv = (2629746.0 / unit_in_seconds);
94 const double days_conv = (86400.0 / unit_in_seconds);
95 const double hours_conv = (3600.0 / unit_in_seconds);
96 const double minutes_conv = (60.0 / unit_in_seconds);
97 const double seconds_conv = (1.0 / unit_in_seconds);
82 98
83 std::string StatisticsPage::MinutesToDateString(const int minutes) { 99 const int years = amount / years_conv;
84 /* ew */ 100 const int months = std::fmod(amount, years_conv) / months_conv;
85 int years = (minutes * (1 / 525949.2F)); 101 const int days = std::fmod(amount, months_conv) / days_conv;
86 int months = (minutes * (1 / 43829.1F)) - (years * 12); 102 const int hours = std::fmod(amount, days_conv) / hours_conv;
87 int days = (minutes * (1 / 1440.0F)) - (years * 365.2425F) - (months * 30.436875F); 103 const int minutes = std::fmod(amount, hours_conv) / minutes_conv;
88 int hours = (minutes * (1 / 60.0F)) - (years * 8765.82F) - (months * 730.485F) - (days * 24); 104 const int seconds = std::fmod(amount, minutes_conv) / seconds_conv;
89 int rest_minutes = (minutes) - (years * 525949.2F) - (months * 43829.1F) - (days * 1440) - (hours * 60);
90 std::ostringstream return_stream;
91 add_time_segment(return_stream, years, " year ", " years ");
92 add_time_segment(return_stream, months, " month ", " months ");
93 add_time_segment(return_stream, days, " day ", " days ");
94 add_time_segment(return_stream, hours, " hour ", " hours ");
95 if (rest_minutes > 0 || return_stream.str().size() == 0)
96 return_stream << rest_minutes << ((rest_minutes == 1) ? " minute" : " minutes");
97 return return_stream.str();
98 }
99 105
100 std::string StatisticsPage::SecondsToDateString(const int sec) { 106 const auto add_time_segment = [](std::ostringstream& str, int amount, const std::string_view& singular, const std::string_view& plural, bool always = false) {
101 /* this is all fairly unnecessary, but works:tm: */ 107 if (amount > 0 || always)
102 int years = sec * (1 / 31556952.0F); 108 str << amount << ((amount == 1) ? singular : plural);
103 int months = sec * (1 / 2629746.0F) - (years * 12); 109 };
104 int days = sec * (1 / 86400.0F) - (years * 365.2425F) - (months * 30.436875F); 110
105 int hours = sec * (1 / 3600.0F) - (years * 8765.82F) - (months * 730.485F) - (days * 24); 111 std::ostringstream string;
106 int minutes = (sec) * (1 / 60.0F) - (years * 525949.2F) - (months * 43829.1F) - (days * 1440.0F) - (hours * 60.0F); 112 add_time_segment(string, years, " year ", " years ");
107 int seconds = 113 add_time_segment(string, months, " month ", " months ");
108 sec - (years * 31556952.0F) - (months * 2629746.0F) - (days * 86400.0F) - (hours * 3600.0F) - (minutes * 60.0F); 114 add_time_segment(string, days, " day ", " days ");
109 std::ostringstream return_stream; 115 add_time_segment(string, hours, " hour ", " hours ");
110 add_time_segment(return_stream, years, " year ", " years "); 116
111 add_time_segment(return_stream, months, " month ", " months "); 117 if (unit == TimeUnits::MINUTES) {
112 add_time_segment(return_stream, days, " day ", " days "); 118 add_time_segment(string, minutes, " minute", " minutes", true);
113 add_time_segment(return_stream, hours, " hour ", " hours "); 119 return string.str();
114 add_time_segment(return_stream, minutes, " minute ", " minutes "); 120 } else {
115 if (seconds > 0 || return_stream.str().size() == 0) 121 add_time_segment(string, minutes, " minute ", " minutes ");
116 return_stream << seconds << ((seconds == 1) ? " second" : " seconds"); 122 }
117 return return_stream.str(); 123
124 add_time_segment(string, seconds, " second", " seconds", true);
125 return string.str();
118 } 126 }
119 127
120 inline int GetTotalWithScore(const int score) { 128 inline int GetTotalWithScore(const int score) {
121 int count = 0; 129 int count = 0;
122 for (const auto& item : Anime::db.items) 130 for (const auto& item : Anime::db.items)
129 /* Anime list */ 137 /* Anime list */
130 QString string = ""; 138 QString string = "";
131 QTextStream ts(&string); 139 QTextStream ts(&string);
132 ts << Anime::db.GetTotalAnimeAmount() << '\n'; 140 ts << Anime::db.GetTotalAnimeAmount() << '\n';
133 ts << Anime::db.GetTotalEpisodeAmount() << '\n'; 141 ts << Anime::db.GetTotalEpisodeAmount() << '\n';
134 ts << MinutesToDateString(Anime::db.GetTotalWatchedAmount()).c_str() << '\n'; 142 ts << Strings::ToQString(TimeToDateString(TimeUnits::MINUTES, Anime::db.GetTotalWatchedAmount(), 60.0)) << '\n';
135 ts << MinutesToDateString(Anime::db.GetTotalPlannedAmount()).c_str() << '\n'; 143 ts << Strings::ToQString(TimeToDateString(TimeUnits::MINUTES, Anime::db.GetTotalPlannedAmount(), 60.0)) << '\n';
136 ts << Anime::db.GetAverageScore() << '\n'; 144 ts << Anime::db.GetAverageScore() << '\n';
137 ts << Anime::db.GetScoreDeviation(); 145 ts << Anime::db.GetScoreDeviation();
138 _anime_list->GetParagraph()->SetText(string); 146 _anime_list->GetParagraph()->SetText(string);
139 147
140 _score_distribution_graph->Clear(); 148 _score_distribution_graph->Clear();
141 for (int i = 10; i <= 100; i += 10) 149 for (int i = 10; i <= 100; i += 10)
142 _score_distribution_graph->AddItem(i, GetTotalWithScore(i)); 150 _score_distribution_graph->AddItem(i, GetTotalWithScore(i));
143 151
144 string = ""; 152 string = "";
145 ts << Strings::ToQString(SecondsToDateString(session.uptime() / 1000)) << '\n'; 153 ts << Strings::ToQString(TimeToDateString(TimeUnits::SECONDS, session.uptime() / 1000)) << '\n';
146 ts << session.GetRequests(); 154 ts << session.GetRequests();
147 /* Application */ 155 /* Application */
148 // UiUtils::SetPlainTextEditData(application_data, QString::number(session.uptime() / 1000)); 156 // UiUtils::SetPlainTextEditData(application_data, QString::number(session.uptime() / 1000));
149 _application->GetParagraph()->SetText(string); 157 _application->GetParagraph()->SetText(string);
150 } 158 }