Continue making use of improved duration handling
This commit is contained in:
parent
3c58851b88
commit
b29e4edd72
@ -13,7 +13,7 @@ durationformat_manual: str = "%H hours"
|
|||||||
|
|
||||||
|
|
||||||
def _safe_timedelta(duration: timedelta | int | None):
|
def _safe_timedelta(duration: timedelta | int | None):
|
||||||
if duration == None:
|
if duration is None:
|
||||||
return timedelta(0)
|
return timedelta(0)
|
||||||
elif isinstance(duration, int):
|
elif isinstance(duration, int):
|
||||||
return timedelta(seconds=duration)
|
return timedelta(seconds=duration)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<c-layouts.base>
|
<c-layouts.base>
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
{% load duration_formatter %}
|
||||||
{% partialdef purchase-name %}
|
{% partialdef purchase-name %}
|
||||||
{% if purchase.type != 'game' %}
|
{% if purchase.type != 'game' %}
|
||||||
<c-gamelink :game_id=purchase.first_game.id>
|
<c-gamelink :game_id=purchase.first_game.id>
|
||||||
@ -111,7 +112,7 @@
|
|||||||
{% for month in month_playtimes %}
|
{% for month in month_playtimes %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="px-2 sm:px-4 md:px-6 md:py-2">{{ month.month | date:"F" }}</td>
|
<td class="px-2 sm:px-4 md:px-6 md:py-2">{{ month.month | date:"F" }}</td>
|
||||||
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ month.playtime }}</td>
|
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ month.playtime | format_duration }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
@ -157,7 +158,7 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="px-2 sm:px-4 md:px-6 md:py-2">Name</th>
|
<th class="px-2 sm:px-4 md:px-6 md:py-2">Name</th>
|
||||||
<th class="px-2 sm:px-4 md:px-6 md:py-2">Playtime (hours)</th>
|
<th class="px-2 sm:px-4 md:px-6 md:py-2">Playtime</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@ -166,7 +167,7 @@
|
|||||||
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">
|
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">
|
||||||
<c-gamelink :game_id=game.id :name=game.name />
|
<c-gamelink :game_id=game.id :name=game.name />
|
||||||
</td>
|
</td>
|
||||||
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ game.formatted_playtime }}</td>
|
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ game.playtime | format_duration }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
@ -176,14 +177,14 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="px-2 sm:px-4 md:px-6 md:py-2">Platform</th>
|
<th class="px-2 sm:px-4 md:px-6 md:py-2">Platform</th>
|
||||||
<th class="px-2 sm:px-4 md:px-6 md:py-2">Playtime (hours)</th>
|
<th class="px-2 sm:px-4 md:px-6 md:py-2">Playtime</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for item in total_playtime_per_platform %}
|
{% for item in total_playtime_per_platform %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ item.platform_name }}</td>
|
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ item.platform_name }}</td>
|
||||||
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ item.formatted_playtime }}</td>
|
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ item.playtime | format_duration }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
@ -213,14 +214,14 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<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 purchase-name truncate max-w-20char">Name</th>
|
||||||
{% comment %} <th class="px-2 sm:px-4 md:px-6 md:py-2">Date</th> {% endcomment %}
|
<th class="px-2 sm:px-4 md:px-6 md:py-2">Date</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for purchase in this_year_finished_this_year %}
|
{% for purchase in this_year_finished_this_year %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{% partial purchase-name %}</td>
|
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{% partial purchase-name %}</td>
|
||||||
{% comment %} <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ purchase.date_finished | date:"d/m/Y" }}</td> {% endcomment %}
|
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ purchase.date_finished | date:"d/m/Y" }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
@ -232,14 +233,14 @@
|
|||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<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 purchase-name truncate max-w-20char">Name</th>
|
||||||
{% comment %} <th class="px-2 sm:px-4 md:px-6 md:py-2">Date</th> {% endcomment %}
|
<th class="px-2 sm:px-4 md:px-6 md:py-2">Date</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for purchase in purchased_this_year_finished_this_year %}
|
{% for purchase in purchased_this_year_finished_this_year %}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{% partial purchase-name %}</td>
|
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{% partial purchase-name %}</td>
|
||||||
{% comment %} <td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ purchase.date_finished | date:"d/m/Y" }}</td> {% endcomment %}
|
<td class="px-2 sm:px-4 md:px-6 md:py-2 font-mono">{{ purchase.date_finished | date:"d/m/Y" }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
|
12
games/templatetags/duration_formatter.py
Normal file
12
games/templatetags/duration_formatter.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
from django import template
|
||||||
|
|
||||||
|
from common.time import durationformat, format_duration
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
@register.filter(name="format_duration")
|
||||||
|
def filter_format_duration(duration: timedelta, argument: str = durationformat):
|
||||||
|
return format_duration(duration, format_string=argument)
|
@ -22,10 +22,10 @@ def model_counts(request: HttpRequest) -> dict[str, bool]:
|
|||||||
timestamp_start__day=this_day,
|
timestamp_start__day=this_day,
|
||||||
timestamp_start__month=this_month,
|
timestamp_start__month=this_month,
|
||||||
timestamp_start__year=this_year,
|
timestamp_start__year=this_year,
|
||||||
).aggregate(time=Sum(F("duration_calculated") + F("duration_manual")))["time"]
|
).aggregate(time=Sum(F("duration_total")))["time"]
|
||||||
last_7_played = Session.objects.filter(
|
last_7_played = Session.objects.filter(
|
||||||
timestamp_start__gte=(now - timedelta(days=7))
|
timestamp_start__gte=(now - timedelta(days=7))
|
||||||
).aggregate(time=Sum(F("duration_calculated") + F("duration_manual")))["time"]
|
).aggregate(time=Sum(F("duration_total")))["time"]
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"game_available": Game.objects.exists(),
|
"game_available": Game.objects.exists(),
|
||||||
@ -137,19 +137,13 @@ def stats_alltime(request: HttpRequest) -> HttpResponse:
|
|||||||
)
|
)
|
||||||
total_spent = this_year_spendings["total_spent"] or 0
|
total_spent = this_year_spendings["total_spent"] or 0
|
||||||
|
|
||||||
games_with_playtime = (
|
games_with_playtime = Game.objects.filter(
|
||||||
Game.objects.filter(sessions__in=this_year_sessions)
|
sessions__in=this_year_sessions
|
||||||
.annotate(
|
).distinct()
|
||||||
total_playtime=Sum(
|
|
||||||
F("sessions__duration_calculated") + F("sessions__duration_manual")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.values("id", "name", "total_playtime")
|
|
||||||
)
|
|
||||||
month_playtimes = (
|
month_playtimes = (
|
||||||
this_year_sessions.annotate(month=TruncMonth("timestamp_start"))
|
this_year_sessions.annotate(month=TruncMonth("timestamp_start"))
|
||||||
.values("month")
|
.values("month")
|
||||||
.annotate(playtime=Sum("duration_calculated"))
|
.annotate(playtime=Sum("duration_total"))
|
||||||
.order_by("month")
|
.order_by("month")
|
||||||
)
|
)
|
||||||
for month in month_playtimes:
|
for month in month_playtimes:
|
||||||
@ -162,18 +156,14 @@ def stats_alltime(request: HttpRequest) -> HttpResponse:
|
|||||||
.first()
|
.first()
|
||||||
)
|
)
|
||||||
top_10_games_by_playtime = games_with_playtime.order_by("-total_playtime")[:10]
|
top_10_games_by_playtime = games_with_playtime.order_by("-total_playtime")[:10]
|
||||||
for game in top_10_games_by_playtime:
|
|
||||||
game["formatted_playtime"] = format_duration(game["total_playtime"], "%2.0H")
|
|
||||||
|
|
||||||
total_playtime_per_platform = (
|
total_playtime_per_platform = (
|
||||||
this_year_sessions.values("game__platform__name")
|
this_year_sessions.values("game__platform__name")
|
||||||
.annotate(total_playtime=Sum(F("duration_calculated") + F("duration_manual")))
|
.annotate(playtime=Sum(F("duration_total")))
|
||||||
.annotate(platform_name=F("game__platform__name"))
|
.annotate(platform_name=F("game__platform__name"))
|
||||||
.values("platform_name", "total_playtime")
|
.values("platform_name", "playtime")
|
||||||
.order_by("-total_playtime")
|
.order_by("-playtime")
|
||||||
)
|
)
|
||||||
for item in total_playtime_per_platform:
|
|
||||||
item["formatted_playtime"] = format_duration(item["total_playtime"], "%2.0H")
|
|
||||||
|
|
||||||
backlog_decrease_count = (
|
backlog_decrease_count = (
|
||||||
Purchase.objects.all().intersection(purchases_finished_this_year).count()
|
Purchase.objects.all().intersection(purchases_finished_this_year).count()
|
||||||
@ -362,7 +352,11 @@ def stats(request: HttpRequest, year: int = 0) -> HttpResponse:
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
purchased_this_year_finished_this_year = (
|
purchased_this_year_finished_this_year = (
|
||||||
this_year_purchases_without_refunded.filter(games__playevents__ended__year=year)
|
this_year_purchases_without_refunded.filter(
|
||||||
|
games__playevents__ended__year=year
|
||||||
|
).annotate(
|
||||||
|
game_name=F("games__name"), date_finished=F("games__playevents__ended")
|
||||||
|
)
|
||||||
).order_by("games__playevents__ended")
|
).order_by("games__playevents__ended")
|
||||||
|
|
||||||
this_year_spendings = this_year_purchases_without_refunded.aggregate(
|
this_year_spendings = this_year_purchases_without_refunded.aggregate(
|
||||||
@ -370,23 +364,15 @@ def stats(request: HttpRequest, year: int = 0) -> HttpResponse:
|
|||||||
)
|
)
|
||||||
total_spent = this_year_spendings["total_spent"] or 0
|
total_spent = this_year_spendings["total_spent"] or 0
|
||||||
|
|
||||||
games_with_playtime = (
|
games_with_playtime = Game.objects.filter(
|
||||||
Game.objects.filter(sessions__in=this_year_sessions)
|
sessions__in=this_year_sessions
|
||||||
.annotate(
|
).distinct()
|
||||||
total_playtime=Sum(
|
|
||||||
F("sessions__duration_calculated") + F("sessions__duration_manual")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.values("id", "name", "total_playtime")
|
|
||||||
)
|
|
||||||
month_playtimes = (
|
month_playtimes = (
|
||||||
this_year_sessions.annotate(month=TruncMonth("timestamp_start"))
|
this_year_sessions.annotate(month=TruncMonth("timestamp_start"))
|
||||||
.values("month")
|
.values("month")
|
||||||
.annotate(playtime=Sum("duration_calculated"))
|
.annotate(playtime=Sum("duration_total"))
|
||||||
.order_by("month")
|
.order_by("month")
|
||||||
)
|
)
|
||||||
for month in month_playtimes:
|
|
||||||
month["playtime"] = format_duration(month["playtime"], "%2.0H")
|
|
||||||
|
|
||||||
highest_session_average_game = (
|
highest_session_average_game = (
|
||||||
Game.objects.filter(sessions__in=this_year_sessions)
|
Game.objects.filter(sessions__in=this_year_sessions)
|
||||||
@ -394,19 +380,15 @@ def stats(request: HttpRequest, year: int = 0) -> HttpResponse:
|
|||||||
.order_by("-session_average")
|
.order_by("-session_average")
|
||||||
.first()
|
.first()
|
||||||
)
|
)
|
||||||
top_10_games_by_playtime = games_with_playtime.order_by("-total_playtime")
|
top_10_games_by_playtime = games_with_playtime.order_by("-playtime")
|
||||||
for game in top_10_games_by_playtime:
|
|
||||||
game["formatted_playtime"] = format_duration(game["total_playtime"], "%2.0H")
|
|
||||||
|
|
||||||
total_playtime_per_platform = (
|
total_playtime_per_platform = (
|
||||||
this_year_sessions.values("game__platform__name")
|
this_year_sessions.values("game__platform__name")
|
||||||
.annotate(total_playtime=Sum(F("duration_calculated") + F("duration_manual")))
|
.annotate(playtime=Sum(F("duration_total")))
|
||||||
.annotate(platform_name=F("game__platform__name"))
|
.annotate(platform_name=F("game__platform__name"))
|
||||||
.values("platform_name", "total_playtime")
|
.values("platform_name", "playtime")
|
||||||
.order_by("-total_playtime")
|
.order_by("-playtime")
|
||||||
)
|
)
|
||||||
for item in total_playtime_per_platform:
|
|
||||||
item["formatted_playtime"] = format_duration(item["total_playtime"], "%2.0H")
|
|
||||||
|
|
||||||
backlog_decrease_count = (
|
backlog_decrease_count = (
|
||||||
Purchase.objects.filter(date_purchased__year__lt=year)
|
Purchase.objects.filter(date_purchased__year__lt=year)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user