Mercurial > minori
view src/gui/pages/statistics.cc @ 198:bc1ae1810855
dep/animia: switch from using classes to global functions
the old idea was ok, but sort of hackish; this method doesn't use classes
at all, and this way (especially important!) we can do wayland stuff AND x11
at the same time, which wasn't really possible without stupid workarounds in
the other method
author | Paper <mrpapersonic@gmail.com> |
---|---|
date | Sun, 24 Dec 2023 02:59:42 -0500 |
parents | 649786bae914 |
children | 4d461ef7d424 |
line wrap: on
line source
#include "gui/pages/statistics.h" #include "core/anime_db.h" #include "core/strings.h" #include "core/session.h" #include "gui/pages/anime_list.h" #include "gui/widgets/text.h" #include "gui/widgets/graph.h" #include <QString> #include <QTextDocument> #include <QTextStream> #include <QTimer> #include <QVBoxLayout> #include <QWidget> #include <sstream> StatisticsPage::StatisticsPage(QWidget* parent) : QFrame(parent) { QVBoxLayout* layout = new QVBoxLayout(this); setFrameShape(QFrame::Box); setFrameShadow(QFrame::Sunken); setAutoFillBackground(true); _anime_list.reset(new TextWidgets::LabelledSection( tr("Anime list"), tr("Anime count:\nEpisode count:\nTime spent watching:\nTime to complete:\nAverage score:\nScore deviation:"), "", this)); layout->addWidget(_anime_list.get()); { QWidget* score_dist_widget = new QWidget(this); QVBoxLayout* score_dist_layout = new QVBoxLayout(score_dist_widget); score_dist_layout->addWidget(new TextWidgets::Header(tr("Score distribution"), score_dist_widget)); /* Ew */ { QWidget* score_graph_parent = new QWidget(score_dist_widget); QVBoxLayout* score_parent_layout = new QVBoxLayout(score_graph_parent); _score_distribution_graph.reset(new Graph<int>(score_graph_parent)); score_parent_layout->addWidget(_score_distribution_graph.get()); score_parent_layout->setSpacing(0); score_parent_layout->setContentsMargins(12, 0, 0, 0); score_graph_parent->setContentsMargins(3, 0, 0, 0); score_dist_layout->addWidget(score_graph_parent); } score_dist_layout->setContentsMargins(0, 0, 0, 0); layout->addWidget(score_dist_widget); } _application.reset(new TextWidgets::LabelledSection(tr("Minori"), tr("Uptime:\nRequests made:"), "\n\n", this)); layout->addWidget(_application.get()); layout->addStretch(); QTimer* timer = new QTimer(this); connect(timer, &QTimer::timeout, this, [this] { if (isVisible()) UpdateStatistics(); }); timer->start(1000); // update statistics every second } void StatisticsPage::showEvent(QShowEvent*) { UpdateStatistics(); } /* me abusing macros :) */ static void add_time_segment(std::ostringstream& str, int x, const std::string_view& s, const std::string_view& p) { if (x > 0) str << x << ((x == 1) ? s : p); } std::string StatisticsPage::MinutesToDateString(const int minutes) { /* ew */ int years = (minutes * (1 / 525949.2F)); int months = (minutes * (1 / 43829.1F)) - (years * 12); int days = (minutes * (1 / 1440.0F)) - (years * 365.2425F) - (months * 30.436875F); int hours = (minutes * (1 / 60.0F)) - (years * 8765.82F) - (months * 730.485F) - (days * 24); int rest_minutes = (minutes) - (years * 525949.2F) - (months * 43829.1F) - (days * 1440) - (hours * 60); std::ostringstream return_stream; add_time_segment(return_stream, years, " year ", " years "); add_time_segment(return_stream, months, " month ", " months "); add_time_segment(return_stream, days, " day ", " days "); add_time_segment(return_stream, hours, " hour ", " hours "); if (rest_minutes > 0 || return_stream.str().size() == 0) return_stream << rest_minutes << ((rest_minutes == 1) ? " minute" : " minutes"); return return_stream.str(); } std::string StatisticsPage::SecondsToDateString(const int sec) { /* this is all fairly unnecessary, but works:tm: */ int years = sec * (1 / 31556952.0F); int months = sec * (1 / 2629746.0F) - (years * 12); int days = sec * (1 / 86400.0F) - (years * 365.2425F) - (months * 30.436875F); int hours = sec * (1 / 3600.0F) - (years * 8765.82F) - (months * 730.485F) - (days * 24); int minutes = (sec) * (1 / 60.0F) - (years * 525949.2F) - (months * 43829.1F) - (days * 1440.0F) - (hours * 60.0F); int seconds = sec - (years * 31556952.0F) - (months * 2629746.0F) - (days * 86400.0F) - (hours * 3600.0F) - (minutes * 60.0F); std::ostringstream return_stream; add_time_segment(return_stream, years, " year ", " years "); add_time_segment(return_stream, months, " month ", " months "); add_time_segment(return_stream, days, " day ", " days "); add_time_segment(return_stream, hours, " hour ", " hours "); add_time_segment(return_stream, minutes, " minute ", " minutes "); if (seconds > 0 || return_stream.str().size() == 0) return_stream << seconds << ((seconds == 1) ? " second" : " seconds"); return return_stream.str(); } inline int GetTotalWithScore(const int score) { int count = 0; for (const auto& item : Anime::db.items) if (item.second.IsInUserList() && item.second.GetUserScore() == score) count++; return count; } void StatisticsPage::UpdateStatistics() { /* Anime list */ QString string = ""; QTextStream ts(&string); ts << Anime::db.GetTotalAnimeAmount() << '\n'; ts << Anime::db.GetTotalEpisodeAmount() << '\n'; ts << MinutesToDateString(Anime::db.GetTotalWatchedAmount()).c_str() << '\n'; ts << MinutesToDateString(Anime::db.GetTotalPlannedAmount()).c_str() << '\n'; ts << Anime::db.GetAverageScore() << '\n'; ts << Anime::db.GetScoreDeviation(); _anime_list->GetParagraph()->SetText(string); _score_distribution_graph->Clear(); for (int i = 10; i <= 100; i += 10) _score_distribution_graph->AddItem(i, GetTotalWithScore(i)); string = ""; ts << Strings::ToQString(SecondsToDateString(session.uptime() / 1000)) << '\n'; ts << session.GetRequests(); /* Application */ // UiUtils::SetPlainTextEditData(application_data, QString::number(session.uptime() / 1000)); _application->GetParagraph()->SetText(string); } #include "gui/pages/moc_statistics.cpp"