-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
305 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Generated by Django 5.1.2 on 2024-11-02 19:42 | ||
|
||
import django.contrib.postgres.fields | ||
import stats.models | ||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('stats', '0001_initial'), | ||
] | ||
|
||
operations = [ | ||
migrations.AddField( | ||
model_name='summonerchampion', | ||
name='version', | ||
field=models.GeneratedField(db_index=True, db_persist=True, expression=stats.models.ArrayConstructor(models.F('major'), models.F('minor')), output_field=django.contrib.postgres.fields.ArrayField(base_field=models.IntegerField(), size=2)), | ||
), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Generated by Django 5.1.2 on 2024-11-04 02:14 | ||
|
||
from django.db import migrations | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('stats', '0002_summonerchampion_version'), | ||
] | ||
|
||
operations = [ | ||
migrations.RemoveField( | ||
model_name='summonerchampion', | ||
name='dmpm', | ||
), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Generated by Django 5.1.2 on 2024-11-04 02:14 | ||
|
||
import django.db.models.expressions | ||
import django.db.models.functions.comparison | ||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('stats', '0003_remove_summonerchampion_dmpm'), | ||
] | ||
|
||
operations = [ | ||
migrations.AddField( | ||
model_name='summonerchampion', | ||
name='dmpm', | ||
field=models.GeneratedField(db_persist=True, expression=django.db.models.expressions.CombinedExpression(django.db.models.expressions.CombinedExpression(models.F('damage_mitigated'), '/', django.db.models.functions.comparison.Greatest(django.db.models.functions.comparison.Cast('total_seconds', models.FloatField()), 1.0)), '*', models.Value(60.0)), help_text='damage mitigated per minute', output_field=models.FloatField()), | ||
), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
from django.urls import path | ||
from . import views | ||
|
||
app_name = 'stats' | ||
|
||
urlpatterns = [ | ||
path("champions/<slug:puuid>/<int:queue>/<int:major>/<int:minor>/", views.champion_stats, name="champions-version"), | ||
path("champions/<slug:puuid>/<int:queue>/<int:major>/", views.champion_stats, name="champions-version"), | ||
path("champions/<slug:puuid>/", views.champion_stats, name="champions-default"), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,104 @@ | ||
from django.db.models.functions import Cast, Greatest | ||
from django.shortcuts import render | ||
from django.db.models import F, Sum | ||
from django.db import models | ||
|
||
# Create your views here. | ||
from stats.models import SummonerChampion | ||
from stats.tasks import add_all_matches_for_summoner_to_stats | ||
|
||
from data.models import Rito, Champion | ||
|
||
|
||
def champion_stats_context(puuid, major=None, minor=None, queue=420): | ||
versions = [] | ||
last_major = None | ||
for version in Rito.objects.first().minor_version_list: | ||
if version["major"] != last_major: | ||
last_major = version["major"] | ||
versions.append( | ||
{ | ||
"version": f"{version["major"]}.x", | ||
"major": version["major"], | ||
"minor": None, | ||
"patch": None, | ||
} | ||
) | ||
versions.append(version) | ||
if not major: | ||
major = int(versions[1]["major"]) | ||
minor = int(versions[1]["minor"]) | ||
|
||
add_all_matches_for_summoner_to_stats(puuid, major=major, minor=minor) | ||
|
||
qs = SummonerChampion.objects.filter(summoner__puuid=puuid) | ||
if major is not None: | ||
qs = qs.filter(major=major) | ||
if minor is not None: | ||
qs = qs.filter(minor=minor) | ||
if queue is not None: | ||
qs = qs.filter(queue=queue) | ||
|
||
qs = qs.values("summoner", "champion_key").annotate( | ||
kills=Sum("kills"), | ||
deaths=Sum("deaths"), | ||
assists=Sum("assists"), | ||
damage_to_champions=Sum("damage_to_champions"), | ||
damage_to_objectives=Sum("damage_to_objectives"), | ||
damage_to_turrets=Sum("damage_to_turrets"), | ||
damage_taken=Sum("damage_taken"), | ||
damage_mitigated=Sum("damage_mitigated"), | ||
vision_score=Sum("vision_score"), | ||
total_seconds=Sum("total_seconds"), | ||
wins=Sum("wins"), | ||
losses=Sum("losses"), | ||
vspm=F("vision_score") | ||
/ Greatest( | ||
Cast("total_seconds", models.FloatField()), | ||
1.0, | ||
output_field=models.FloatField(), | ||
) | ||
* 60.0, | ||
kda=(F("kills") + F("assists")) | ||
/ Greatest(Cast("deaths", models.FloatField()), 1.0), | ||
dpm=F("damage_to_champions") | ||
/ Greatest(Cast("total_seconds", models.FloatField()), 1.0) | ||
* 60.0, | ||
dtpm=F("damage_taken") | ||
/ Greatest(Cast("total_seconds", models.FloatField()), 1.0) | ||
* 60.0, | ||
dttpm=F("damage_to_turrets") | ||
/ Greatest(Cast("total_seconds", models.FloatField()), 1.0) | ||
* 60.0, | ||
dtopm=F("damage_to_objectives") | ||
/ Greatest(Cast("total_seconds", models.FloatField()), 1.0) | ||
* 60.0, | ||
dmpm=F("damage_mitigated") | ||
/ Greatest(Cast("total_seconds", models.FloatField()), 1.0) | ||
* 60.0, | ||
) | ||
|
||
qs = qs.annotate( | ||
game_count=F("wins") + F("losses"), | ||
).order_by("-game_count") | ||
|
||
keys = [x["champion_key"] for x in qs] | ||
champions = { | ||
x.key: x | ||
for x in Champion.objects.filter(key__in=keys).order_by("-key").distinct("key") | ||
} | ||
for cs in qs: | ||
cs["champion"] = champions.get(int(cs["champion_key"]), None) | ||
|
||
return { | ||
"championstats": qs, | ||
"major": major, | ||
"minor": minor, | ||
"queue": queue, | ||
"puuid": puuid, | ||
"versions": versions[:10], | ||
} | ||
|
||
|
||
def champion_stats(request, puuid, major=None, minor=None, queue=420): | ||
context = champion_stats_context(puuid, major, minor, queue) | ||
return render(request, "stats/_champions.html", context) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
{% load humanize %} | ||
<div class="bg-slate-700 rounded px-2 champion-stats"> | ||
<h3>Champion Stats ({{ major }}.{{ minor|default:"x" }})</h3> | ||
<div class="flex gap-x-2"> | ||
<div class="flex flex-col gap-y-2"> | ||
<button | ||
{% if minor is not None %} | ||
hx-get="{% url 'stats:champions-version' puuid=puuid major=major minor=minor queue=420 %}" | ||
{% else %} | ||
hx-get="{% url 'stats:champions-version' puuid=puuid major=major queue=420 %}" | ||
{% endif %} | ||
hx-target="closest .champion-stats" | ||
hx-swap="outerHTML" | ||
class="btn btn-default" | ||
> | ||
Solo Queue | ||
</button> | ||
<button | ||
{% if minor is not None %} | ||
hx-get="{% url 'stats:champions-version' puuid=puuid major=major minor=minor queue=440 %}" | ||
{% else %} | ||
hx-get="{% url 'stats:champions-version' puuid=puuid major=major queue=440 %}" | ||
{% endif %} | ||
hx-target="closest .champion-stats" | ||
hx-swap="outerHTML" | ||
class="btn btn-default" | ||
> | ||
Flex Queue | ||
</button> | ||
</div> | ||
<div class="flex flex-col gap-y-2 gap-x-1 h-[100px] flex-wrap"> | ||
{% for version in versions %} | ||
<button | ||
{% if version.minor %} | ||
hx-get="{% url 'stats:champions-version' puuid=puuid major=version.major minor=version.minor queue=queue %}" | ||
{% else %} | ||
hx-get="{% url 'stats:champions-version' puuid=puuid major=version.major queue=queue %}" | ||
{% endif %} | ||
hx-swap="outerHTML" | ||
hx-target="closest .champion-stats" | ||
class="btn btn-default"> | ||
{{ version.version }} | ||
</button> | ||
{% endfor %} | ||
</div> | ||
</div> | ||
<div class="flex gap-2 max-h-[400px] overflow-y-scroll flex-wrap"> | ||
{% for stat in championstats %} | ||
<div class="flex flex-col p-2 border border-white rounded"> | ||
<div class="flex gap-x-2"> | ||
<img src="{{ stat.champion.image_url }}" class="w-8 h-8" /> | ||
<div> | ||
{{ stat.champion.name }} ({{ stat.wins }} / {{ stat.losses }}) | ||
</div> | ||
</div> | ||
<div> | ||
<b>{{ stat.kda|floatformat:2 }}</b> KDA | ||
</div> | ||
<div> | ||
<b>{{ stat.dpm|intcomma|floatformat:0 }}</b> DPM | ||
</div> | ||
<div> | ||
<b>{{ stat.vspm|intcomma|floatformat:1 }}</b> VSPM | ||
</div> | ||
<div> | ||
<b>{{ stat.dtpm|intcomma|floatformat:0 }}</b> Damage Taken per Minute | ||
</div> | ||
<div> | ||
<b>{{ stat.dttpm|intcomma|floatformat:0 }}</b> Tower Damage per Minute | ||
</div> | ||
<div> | ||
<b>{{ stat.dtopm|intcomma|floatformat:0 }}</b> Objective Damage per Minute | ||
</div> | ||
</div> | ||
{% endfor %} | ||
</div> | ||
</div> |
Oops, something went wrong.