Compare commits
No commits in common. "5052ca7dbfbad82be1d0759a54760c6318d7900c" and "666dee33ba87dfc722ab8ac4c5598bc6cd50146d" have entirely different histories.
5052ca7dbf
...
666dee33ba
|
@ -13,12 +13,6 @@
|
||||||
* 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
|
||||||
|
|
|
@ -19,40 +19,20 @@
|
||||||
<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">Statistic</th>
|
<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">Value</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">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>
|
||||||
|
@ -95,58 +75,7 @@
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<h1 class="text-5xl text-center my-6">Finished</h1>
|
<h1 class="text-5xl text-center my-6">Purchases</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>
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
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, Count
|
from django.db.models import Sum, F
|
||||||
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
|
||||||
|
@ -277,12 +276,6 @@ 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()
|
||||||
|
@ -295,14 +288,6 @@ 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"]
|
||||||
|
|
||||||
|
@ -345,12 +330,6 @@ 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
|
||||||
|
|
Loading…
Reference in New Issue