annotate src/gui/pages/statistics.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 6d8da6e64d61
children 45a0967485f1
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
9
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
1 #include "gui/pages/statistics.h"
15
cde8f67a7c7d *: update, megacommit :)
Paper <mrpapersonic@gmail.com>
parents: 11
diff changeset
2 #include "core/anime_db.h"
cde8f67a7c7d *: update, megacommit :)
Paper <mrpapersonic@gmail.com>
parents: 11
diff changeset
3 #include "core/session.h"
9
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
4 #include "gui/pages/anime_list.h"
46
d0adc4aedfc8 *: update...
Paper <mrpapersonic@gmail.com>
parents: 37
diff changeset
5 #include "gui/widgets/text.h"
93
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
6 #include "gui/widgets/graph.h"
9
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
7 #include <QString>
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
8 #include <QTextDocument>
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
9 #include <QTextStream>
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
10 #include <QTimer>
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
11 #include <QVBoxLayout>
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
12 #include <QWidget>
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
13 #include <sstream>
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
14
64
fe719c109dbc *: update
Paper <mrpapersonic@gmail.com>
parents: 63
diff changeset
15 StatisticsPage::StatisticsPage(QWidget* parent) : QFrame(parent) {
fe719c109dbc *: update
Paper <mrpapersonic@gmail.com>
parents: 63
diff changeset
16 QVBoxLayout* layout = new QVBoxLayout(this);
9
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
17
64
fe719c109dbc *: update
Paper <mrpapersonic@gmail.com>
parents: 63
diff changeset
18 setFrameShape(QFrame::Box);
9
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
19 setFrameShadow(QFrame::Sunken);
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
20
46
d0adc4aedfc8 *: update...
Paper <mrpapersonic@gmail.com>
parents: 37
diff changeset
21 setAutoFillBackground(true);
37
9ae9365dd4ea window.cpp: fix sidebar on Linux
Paper <mrpapersonic@gmail.com>
parents: 15
diff changeset
22
93
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
23 _anime_list.reset(new TextWidgets::LabelledSection(
51
75c804f713b2 window: add about window,
Paper <mrpapersonic@gmail.com>
parents: 49
diff changeset
24 tr("Anime list"),
63
3d2decf093bb *: fix many clang warnings
Paper <mrpapersonic@gmail.com>
parents: 51
diff changeset
25 tr("Anime count:\nEpisode count:\nTime spent watching:\nTime to complete:\nAverage score:\nScore deviation:"),
93
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
26 "", this));
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
27
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
28 QWidget* score_dist_widget = new QWidget(this);
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
29 QVBoxLayout* score_dist_layout = new QVBoxLayout(score_dist_widget);
9
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
30
94
2f373d48f889 *: etc changes to graph stuff
Paper <mrpapersonic@gmail.com>
parents: 93
diff changeset
31 score_dist_layout->addWidget(new TextWidgets::Header(tr("Score distribution"), score_dist_widget));
2f373d48f889 *: etc changes to graph stuff
Paper <mrpapersonic@gmail.com>
parents: 93
diff changeset
32
2f373d48f889 *: etc changes to graph stuff
Paper <mrpapersonic@gmail.com>
parents: 93
diff changeset
33 /* I have to explain myself here: I hate this :). This makes a widget as a layer to create a margin,
2f373d48f889 *: etc changes to graph stuff
Paper <mrpapersonic@gmail.com>
parents: 93
diff changeset
34 similar to what I do in text.cc with sections. I hate it and it should really be put into a separate
2f373d48f889 *: etc changes to graph stuff
Paper <mrpapersonic@gmail.com>
parents: 93
diff changeset
35 class, but whatever. */
93
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
36 QWidget* content = new QWidget(score_dist_widget);
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
37 QVBoxLayout* content_layout = new QVBoxLayout(content);
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
38 _score_distribution_graph.reset(new Graph<int>(content));
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
39 content_layout->addWidget(_score_distribution_graph.get());
102
b315f3759c56 *: big patch
Paper <mrpapersonic@gmail.com>
parents: 94
diff changeset
40 content_layout->setSpacing(0);
b315f3759c56 *: big patch
Paper <mrpapersonic@gmail.com>
parents: 94
diff changeset
41 /* For some reason, when we set the margin to 12 on any paragraphs it
b315f3759c56 *: big patch
Paper <mrpapersonic@gmail.com>
parents: 94
diff changeset
42 actually doesn't draw them 12 pixels away. It draws them ~15 pixels
b315f3759c56 *: big patch
Paper <mrpapersonic@gmail.com>
parents: 94
diff changeset
43 away! I'm assuming this is just Qt's widgets being weird (they usually are)
b315f3759c56 *: big patch
Paper <mrpapersonic@gmail.com>
parents: 94
diff changeset
44 and I hope it's nothing I *really* have to worry about... */
b315f3759c56 *: big patch
Paper <mrpapersonic@gmail.com>
parents: 94
diff changeset
45 content_layout->setContentsMargins(15, 0, 0, 0);
b315f3759c56 *: big patch
Paper <mrpapersonic@gmail.com>
parents: 94
diff changeset
46 content->setContentsMargins(0, 0, 0, 0);
9
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
47
93
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
48 score_dist_layout->addWidget(content);
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
49 score_dist_layout->setContentsMargins(0, 0, 0, 0);
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
50
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
51 _application.reset(new TextWidgets::LabelledSection(tr("Minori"), tr("Uptime:\nRequests made:"), "\n\n", this));
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
52
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
53 layout->addWidget(_anime_list.get());
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
54 layout->addWidget(score_dist_widget);
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
55 layout->addWidget(_application.get());
64
fe719c109dbc *: update
Paper <mrpapersonic@gmail.com>
parents: 63
diff changeset
56 layout->addStretch();
9
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
57
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
58 QTimer* timer = new QTimer(this);
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
59 connect(timer, &QTimer::timeout, this, [this] {
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
60 if (isVisible())
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
61 UpdateStatistics();
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
62 });
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
63 timer->start(1000); // update statistics every second
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
64 }
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
65
64
fe719c109dbc *: update
Paper <mrpapersonic@gmail.com>
parents: 63
diff changeset
66 void StatisticsPage::showEvent(QShowEvent*) {
9
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
67 UpdateStatistics();
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
68 }
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
69
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
70 /* me abusing macros :) */
15
cde8f67a7c7d *: update, megacommit :)
Paper <mrpapersonic@gmail.com>
parents: 11
diff changeset
71 #define ADD_TIME_SEGMENT(r, x, s, p) \
64
fe719c109dbc *: update
Paper <mrpapersonic@gmail.com>
parents: 63
diff changeset
72 if (x > 0) \
fe719c109dbc *: update
Paper <mrpapersonic@gmail.com>
parents: 63
diff changeset
73 r << x << ((x == 1) ? s : p)
102
b315f3759c56 *: big patch
Paper <mrpapersonic@gmail.com>
parents: 94
diff changeset
74 std::string StatisticsPage::MinutesToDateString(const int minutes) {
9
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
75 /* ew */
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
76 int years = (minutes * (1 / 525949.2F));
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
77 int months = (minutes * (1 / 43829.1F)) - (years * 12);
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
78 int days = (minutes * (1 / 1440.0F)) - (years * 365.2425F) - (months * 30.436875F);
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
79 int hours = (minutes * (1 / 60.0F)) - (years * 8765.82F) - (months * 730.485F) - (days * 24);
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
80 int rest_minutes = (minutes) - (years * 525949.2F) - (months * 43829.1F) - (days * 1440) - (hours * 60);
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
81 std::ostringstream return_stream;
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
82 ADD_TIME_SEGMENT(return_stream, years, " year ", " years ");
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
83 ADD_TIME_SEGMENT(return_stream, months, " month ", " months ");
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
84 ADD_TIME_SEGMENT(return_stream, days, " day ", " days ");
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
85 ADD_TIME_SEGMENT(return_stream, hours, " hour ", " hours ");
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
86 if (rest_minutes > 0 || return_stream.str().size() == 0)
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
87 return_stream << rest_minutes << ((rest_minutes == 1) ? " minute" : " minutes");
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
88 return return_stream.str();
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
89 }
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
90
102
b315f3759c56 *: big patch
Paper <mrpapersonic@gmail.com>
parents: 94
diff changeset
91 std::string StatisticsPage::SecondsToDateString(const int sec) {
9
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
92 /* this is all fairly unnecessary, but works:tm: */
10
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
93 int years = sec * (1 / 31556952.0F);
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
94 int months = sec * (1 / 2629746.0F) - (years * 12);
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
95 int days = sec * (1 / 86400.0F) - (years * 365.2425F) - (months * 30.436875F);
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
96 int hours = sec * (1 / 3600.0F) - (years * 8765.82F) - (months * 730.485F) - (days * 24);
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
97 int minutes = (sec) * (1 / 60.0F) - (years * 525949.2F) - (months * 43829.1F) - (days * 1440.0F) - (hours * 60.0F);
15
cde8f67a7c7d *: update, megacommit :)
Paper <mrpapersonic@gmail.com>
parents: 11
diff changeset
98 int seconds =
cde8f67a7c7d *: update, megacommit :)
Paper <mrpapersonic@gmail.com>
parents: 11
diff changeset
99 sec - (years * 31556952.0F) - (months * 2629746.0F) - (days * 86400.0F) - (hours * 3600.0F) - (minutes * 60.0F);
9
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
100 std::ostringstream return_stream;
10
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
101 ADD_TIME_SEGMENT(return_stream, years, " year ", " years ");
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
102 ADD_TIME_SEGMENT(return_stream, months, " month ", " months ");
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
103 ADD_TIME_SEGMENT(return_stream, days, " day ", " days ");
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
104 ADD_TIME_SEGMENT(return_stream, hours, " hour ", " hours ");
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
105 ADD_TIME_SEGMENT(return_stream, minutes, " minute ", " minutes ");
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
106 if (seconds > 0 || return_stream.str().size() == 0)
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
107 return_stream << seconds << ((seconds == 1) ? " second" : " seconds");
9
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
108 return return_stream.str();
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
109 }
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
110 #undef ADD_TIME_SEGMENT
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
111
102
b315f3759c56 *: big patch
Paper <mrpapersonic@gmail.com>
parents: 94
diff changeset
112 inline int GetTotalWithScore(const int score) {
93
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
113 int count = 0;
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
114 for (const auto& item : Anime::db.items)
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
115 if (item.second.IsInUserList() && item.second.GetUserScore() == score)
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
116 count++;
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
117 return count;
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
118 }
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
119
64
fe719c109dbc *: update
Paper <mrpapersonic@gmail.com>
parents: 63
diff changeset
120 void StatisticsPage::UpdateStatistics() {
9
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
121 /* Anime list */
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
122 QString string = "";
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
123 QTextStream ts(&string);
10
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
124 ts << Anime::db.GetTotalAnimeAmount() << '\n';
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
125 ts << Anime::db.GetTotalEpisodeAmount() << '\n';
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
126 ts << MinutesToDateString(Anime::db.GetTotalWatchedAmount()).c_str() << '\n';
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
127 ts << MinutesToDateString(Anime::db.GetTotalPlannedAmount()).c_str() << '\n';
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
128 ts << Anime::db.GetAverageScore() << '\n';
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
129 ts << Anime::db.GetScoreDeviation();
93
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
130 _anime_list->GetParagraph()->SetText(string);
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
131
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
132 _score_distribution_graph->Clear();
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
133 for (int i = 10; i <= 100; i += 10)
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
134 _score_distribution_graph->AddItem(i, GetTotalWithScore(i));
9
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
135
47
d8eb763e6661 information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents: 46
diff changeset
136 string = "";
d8eb763e6661 information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents: 46
diff changeset
137 ts << QString::fromUtf8(SecondsToDateString(session.uptime() / 1000).c_str()) << '\n';
d8eb763e6661 information.cpp: add widgets to the list tab, and add an
Paper <mrpapersonic@gmail.com>
parents: 46
diff changeset
138 ts << session.GetRequests();
9
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
139 /* Application */
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
140 // UiUtils::SetPlainTextEditData(application_data, QString::number(session.uptime() / 1000));
93
d5efb81540b3 statistics: add graph!
Paper <mrpapersonic@gmail.com>
parents: 83
diff changeset
141 _application->GetParagraph()->SetText(string);
9
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
142 }
5c0397762b53 INCOMPLETE: megacommit :)
Paper <mrpapersonic@gmail.com>
parents:
diff changeset
143
10
Paper <mrpapersonic@gmail.com>
parents: 9
diff changeset
144 #include "gui/pages/moc_statistics.cpp"