Compare commits

..

2 Commits

Author SHA1 Message Date
Lukáš Kucharczyk 5052ca7dbf Add more stats
continuous-integration/drone/push Build is passing Details
* All finished games
* All finished 2023 games
* All finished games that were purchased this year
* Total sessions
* Days played
2023-11-08 16:24:22 +01:00
Lukáš Kucharczyk f408bfd927 stats: change overall stats table layout 2023-11-08 15:48:06 +01:00
3 changed files with 106 additions and 8 deletions

View File

@ -13,6 +13,12 @@
* Upon migration, this will be set to a year of any of the game's edition that has it set * Upon migration, this will be set to a year of any of the game's edition that has it set
* Purchase: Date Finished * Purchase: Date Finished
* Editions are now unique combination of name and platform * Editions are now unique combination of name and platform
* Add more stats:
* All finished games
* All finished 2023 games
* All finished games that were purchased this year
* Total sessions
* Days played
### Improved ### Improved
* game overview: simplify playtime range display * game overview: simplify playtime range display

View File

@ -19,20 +19,40 @@
<table class="responsive-table"> <table class="responsive-table">
<thead> <thead>
<tr> <tr>
<th class="px-2 sm:px-4 md:px-6 md:py-2">Hours</th> <th class="px-2 sm:px-4 md:px-6 md:py-2">Statistic</th>
<th class="px-2 sm:px-4 md:px-6 md:py-2">Games</th> <th class="px-2 sm:px-4 md:px-6 md:py-2">Value</th>
<th class="px-2 sm:px-4 md:px-6 md:py-2">Games ({{ year }})</th>
<th class="px-2 sm:px-4 md:px-6 md:py-2">Purchases</th>
<th class="px-2 sm:px-4 md:px-6 md:py-2">Spendings ({{ total_spent_currency }})</th>
<th class="px-2 sm:px-4 md:px-6 md:py-2">{{ total_spent_currency }}/game</th>
</tr> </tr>
<tbody> <tbody>
<tr> <tr>
<td class="px-2 sm:px-4 md:px-6 md:py-2">Hours</td>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ total_hours }}</td> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ total_hours }}</td>
</tr>
<tr>
<td class="px-2 sm:px-4 md:px-6 md:py-2">Sessions</td>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ total_sessions }}</td>
</tr>
<tr>
<td class="px-2 sm:px-4 md:px-6 md:py-2">Days Played</td>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ unique_days }} ({{ unique_days_percent }}%)</td>
</tr>
<tr>
<td class="px-2 sm:px-4 md:px-6 md:py-2">Games</td>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ total_games }}</td> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ total_games }}</td>
</tr>
<tr>
<td class="px-2 sm:px-4 md:px-6 md:py-2">Games ({{ year }})</td>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ total_2023_games }}</td> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ total_2023_games }}</td>
</tr>
<tr>
<td class="px-2 sm:px-4 md:px-6 md:py-2">Purchases</td>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ all_purchased_this_year.count }}</td> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ all_purchased_this_year.count }}</td>
</tr>
<tr>
<td class="px-2 sm:px-4 md:px-6 md:py-2">Spendings ({{ total_spent_currency }})</td>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ total_spent }}</td> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ total_spent }}</td>
</tr>
<tr>
<td class="px-2 sm:px-4 md:px-6 md:py-2">{{ total_spent_currency }}/game</td>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ spent_per_game }}</td> <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ spent_per_game }}</td>
</tr> </tr>
</tbody> </tbody>
@ -75,7 +95,58 @@
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
<h1 class="text-5xl text-center my-6">Purchases</h1> <h1 class="text-5xl text-center my-6">Finished</h1>
<table class="responsive-table">
<thead>
<tr>
<th class="px-2 sm:px-4 md:px-6 md:py-2 purchase-name truncate max-w-20char">Name</th>
<th class="px-2 sm:px-4 md:px-6 md:py-2">Date</th>
</tr>
</thead>
<tbody>
{% for purchase in all_finished_this_year %}
<tr>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono"><a class="underline decoration-slate-500 sm:decoration-2" href="{% url 'edit_purchase' purchase.id %}">{{ purchase.edition.name }}</a></td>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ purchase.date_finished | date:"d/m/Y" }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<h1 class="text-5xl text-center my-6">Finished (2023 games)</h1>
<table class="responsive-table">
<thead>
<tr>
<th class="px-2 sm:px-4 md:px-6 md:py-2 purchase-name truncate max-w-20char">Name</th>
<th class="px-2 sm:px-4 md:px-6 md:py-2">Date</th>
</tr>
</thead>
<tbody>
{% for purchase in this_year_finished_this_year %}
<tr>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono"><a class="underline decoration-slate-500 sm:decoration-2" href="{% url 'edit_purchase' purchase.id %}">{{ purchase.edition.name }}</a></td>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ purchase.date_finished | date:"d/m/Y" }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<h1 class="text-5xl text-center my-6">Bought and Finished ({{ year }})</h1>
<table class="responsive-table">
<thead>
<tr>
<th class="px-2 sm:px-4 md:px-6 md:py-2 purchase-name truncate max-w-20char">Name</th>
<th class="px-2 sm:px-4 md:px-6 md:py-2">Date</th>
</tr>
</thead>
<tbody>
{% for purchase in purchased_this_year_finished_this_year %}
<tr>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono"><a class="underline decoration-slate-500 sm:decoration-2" href="{% url 'edit_purchase' purchase.id %}">{{ purchase.edition.name }}</a></td>
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ purchase.date_finished | date:"d/m/Y" }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<h1 class="text-5xl text-center my-6">All Purchases</h1>
<table class="responsive-table"> <table class="responsive-table">
<thead> <thead>
<tr> <tr>

View File

@ -1,7 +1,8 @@
from common.time import format_duration, now as now_with_tz from common.time import format_duration, now as now_with_tz
from datetime import datetime, timedelta from datetime import datetime, timedelta
from django.conf import settings from django.conf import settings
from django.db.models import Sum, F from django.db.models import Sum, F, Count
from django.db.models.functions import TruncDate
from django.http import HttpRequest, HttpResponse, HttpResponseRedirect from django.http import HttpRequest, HttpResponse, HttpResponseRedirect
from django.shortcuts import redirect, render from django.shortcuts import redirect, render
from django.urls import reverse from django.urls import reverse
@ -276,6 +277,12 @@ def stats(request, year: int = 0):
first_day_of_year = datetime(year, 1, 1) first_day_of_year = datetime(year, 1, 1)
last_day_of_year = datetime(year + 1, 1, 1) last_day_of_year = datetime(year + 1, 1, 1)
year_sessions = Session.objects.filter(timestamp_start__year=year) year_sessions = Session.objects.filter(timestamp_start__year=year)
unique_days = (
year_sessions.annotate(date=TruncDate("timestamp_start"))
.values("date")
.distinct()
.aggregate(dates=Count("date"))
)
year_played_purchases = Purchase.objects.filter( year_played_purchases = Purchase.objects.filter(
session__in=year_sessions session__in=year_sessions
).distinct() ).distinct()
@ -288,6 +295,14 @@ def stats(request, year: int = 0):
.order_by("date_purchased") .order_by("date_purchased")
) )
all_finished_this_year = Purchase.objects.filter(date_finished__year=year)
this_year_finished_this_year = Purchase.objects.filter(
date_finished__year=year
).filter(edition__year_released=year)
purchased_this_year_finished_this_year = all_purchased_this_year.filter(
date_finished__year=year
)
this_year_spendings = all_purchased_this_year.aggregate(total_spent=Sum(F("price"))) this_year_spendings = all_purchased_this_year.aggregate(total_spent=Sum(F("price")))
total_spent = this_year_spendings["total_spent"] total_spent = this_year_spendings["total_spent"]
@ -330,6 +345,12 @@ def stats(request, year: int = 0):
"total_spent_currency": selected_currency, "total_spent_currency": selected_currency,
"all_purchased_this_year": all_purchased_this_year, "all_purchased_this_year": all_purchased_this_year,
"spent_per_game": int(total_spent / all_purchased_this_year.count()), "spent_per_game": int(total_spent / all_purchased_this_year.count()),
"all_finished_this_year": all_finished_this_year,
"this_year_finished_this_year": this_year_finished_this_year,
"purchased_this_year_finished_this_year": purchased_this_year_finished_this_year,
"total_sessions": year_sessions.count(),
"unique_days": unique_days["dates"],
"unique_days_percent": int(unique_days["dates"] / 365 * 100),
} }
request.session["return_path"] = request.path request.session["return_path"] = request.path