changeset 93:d5efb81540b3

statistics: add graph! also now we have a VERY VERY simple graph widget that probably sucks and doesn't work half the time :)
author Paper <mrpapersonic@gmail.com>
date Wed, 01 Nov 2023 13:52:34 -0400
parents 2c27582a177c
children 2f373d48f889
files include/gui/pages/statistics.h include/gui/widgets/graph.h src/gui/pages/statistics.cc
diffstat 3 files changed, 101 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/include/gui/pages/statistics.h	Wed Nov 01 00:00:56 2023 -0400
+++ b/include/gui/pages/statistics.h	Wed Nov 01 13:52:34 2023 -0400
@@ -3,9 +3,10 @@
 
 #include <QFrame>
 #include <QWidget>
+#include "gui/widgets/graph.h"
 
 namespace TextWidgets {
-class Paragraph;
+class LabelledSection;
 }
 
 class StatisticsPage : public QFrame {
@@ -22,16 +23,11 @@
 		std::string MinutesToDateString(int minutes);
 		std::string SecondsToDateString(int seconds);
 
-		TextWidgets::Paragraph* anime_list_data;
+		std::shared_ptr<TextWidgets::LabelledSection> _anime_list;
 
-		// QPlainTextEdit* score_distribution_title;
-		// QPlainTextEdit* score_distribution_labels;
-		// wxStaticText* score_distribution_graph; // how am I gonna do this
+		std::shared_ptr<Graph<int>> _score_distribution_graph;
 
-		/* we don't HAVE a local database (yet ;)) */
-		// QPlainTextEdit* local_database_data;
-
-		TextWidgets::Paragraph* application_data;
+		std::shared_ptr<TextWidgets::LabelledSection> _application;
 };
 
 #endif // __gui__pages__statistics_h
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/gui/widgets/graph.h	Wed Nov 01 13:52:34 2023 -0400
@@ -0,0 +1,60 @@
+#ifndef __gui__widgets__graph_h
+#define __gui__widgets__graph_h
+#include <QWidget>
+#include <QSize>
+#include <QPaintEvent>
+#include <QSize>
+#include <QRect>
+#include <QPainter>
+#include <QPainterPath>
+#include <QPen>
+
+template <typename T> /* does this even work?? */
+class Graph final : public QWidget {
+public:
+	Graph(QWidget* parent = nullptr) : QWidget(parent) {};
+	void AddItem(T key, int val) { map[key] = val; update(); updateGeometry(); };
+	void Clear() { map.clear(); update(); updateGeometry(); };
+
+protected:
+	static constexpr int ITEM_HEIGHT = 20;
+	static constexpr int TEXT_WIDTH = 30;
+	inline int GetTotal() {
+		int count = 0;
+		for (const auto& item : map)
+			count += item.second;
+		return count;
+	}
+	QSize minimumSizeHint() const override { return QSize(100, ITEM_HEIGHT * map.size()); };
+	void paintEvent(QPaintEvent* event) override {
+		const QRect rect = event->rect();
+		const int height_of_each = rect.height() / map.size();
+		const int size = GetTotal();
+
+		/* now we do the actual painting */
+		QPainter painter(this);
+
+		int i = 0;
+		for (const auto& item : map) {
+			painter.drawText(QRect(0, i*ITEM_HEIGHT, TEXT_WIDTH, ITEM_HEIGHT), Qt::AlignRight | Qt::AlignVCenter, QString::number(item.first));
+
+			if (size) {
+				painter.save();
+
+				QPen pen(Qt::transparent, 0);
+				painter.setPen(pen);
+
+				QPainterPath path;
+				path.addRect(rect.x()+35, rect.y()+(i*ITEM_HEIGHT), (static_cast<double>(item.second)/size)*(rect.width()-35), ITEM_HEIGHT);
+				painter.fillPath(path, Qt::blue);
+				painter.drawPath(path);
+
+				painter.restore();
+			}
+			i++;
+		}
+	};
+	std::unordered_map<T, int> map = {};
+};
+
+#endif // __gui__widgets__graph_h
\ No newline at end of file
--- a/src/gui/pages/statistics.cc	Wed Nov 01 00:00:56 2023 -0400
+++ b/src/gui/pages/statistics.cc	Wed Nov 01 13:52:34 2023 -0400
@@ -3,6 +3,7 @@
 #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>
@@ -22,18 +23,31 @@
 	setPalette(pal);
 	setAutoFillBackground(true);
 
-	TextWidgets::LabelledSection* anime_list_paragraph = new TextWidgets::LabelledSection(
+	_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);
-	anime_list_data = anime_list_paragraph->GetParagraph();
+	    "", this));
+
+	/* spaghetti incoming */
+	QWidget* score_dist_widget = new QWidget(this);
+	QVBoxLayout* score_dist_layout = new QVBoxLayout(score_dist_widget);
 
-	TextWidgets::LabelledSection* application_paragraph =
-	    new TextWidgets::LabelledSection(tr("Minori"), tr("Uptime:\nRequests made:"), "\n\n", this);
-	application_data = application_paragraph->GetParagraph();
+	QWidget* content = new QWidget(score_dist_widget);
+	QVBoxLayout* content_layout = new QVBoxLayout(content);
+	score_dist_layout->addWidget(new TextWidgets::Header(tr("Score distribution"), content));
+	_score_distribution_graph.reset(new Graph<int>(content));
+	content_layout->addWidget(_score_distribution_graph.get());
+	content_layout->setContentsMargins(0, 0, 0, 0);
+	content->setContentsMargins(12, 0, 0, 0);
 
-	layout->addWidget(anime_list_paragraph);
-	layout->addWidget(application_paragraph);
+	score_dist_layout->addWidget(content);
+	score_dist_layout->setContentsMargins(0, 0, 0, 0);
+
+	_application.reset(new TextWidgets::LabelledSection(tr("Minori"), tr("Uptime:\nRequests made:"), "\n\n", this));
+
+	layout->addWidget(_anime_list.get());
+	layout->addWidget(score_dist_widget);
+	layout->addWidget(_application.get());
 	layout->addStretch();
 
 	QTimer* timer = new QTimer(this);
@@ -90,6 +104,14 @@
 }
 #undef ADD_TIME_SEGMENT
 
+inline int GetTotalWithScore(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 = "";
@@ -100,14 +122,18 @@
 	ts << MinutesToDateString(Anime::db.GetTotalPlannedAmount()).c_str() << '\n';
 	ts << Anime::db.GetAverageScore() << '\n';
 	ts << Anime::db.GetScoreDeviation();
-	anime_list_data->SetText(string);
+	_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 << QString::fromUtf8(SecondsToDateString(session.uptime() / 1000).c_str()) << '\n';
 	ts << session.GetRequests();
 	/* Application */
 	// UiUtils::SetPlainTextEditData(application_data, QString::number(session.uptime() / 1000));
-	application_data->SetText(string);
+	_application->GetParagraph()->SetText(string);
 }
 
 #include "gui/pages/moc_statistics.cpp"