implement rank system

This commit is contained in:
Walter 2025-02-24 15:07:38 +01:00
parent 65c924c3a8
commit 93a9ffb268
11 changed files with 187 additions and 23 deletions

View File

@ -51,7 +51,6 @@ class Level(models.Model):
result = list(self.bloonsa_level_ratings.aggregate(Avg("rating")).values())[0]
return 0 if result is None else round(result)
def __str__(self):
return f"{self.level_id}: {self.author.name} - {self.title}"

View File

@ -109,3 +109,10 @@
.invisible {
visibility: hidden;
}
#global-leaderboard-iframe {
height: 629px;
width: 160px;
overflow: hidden;
}

View File

@ -0,0 +1,72 @@
#glb-global {
height: 629px;
width: 160px;
font-family: "Comic Sans MS", "Comic Sans", cursive;
color: white;
font-size: 13px;
text-align: left;
white-space: nowrap;
margin: 0;
}
.rowa {
background-color: #563EAB;
}
.rowb {
background-color: #6B0047;
}
.glb-position {
color: #ffcf24;
}
.glb-username {
z-index: 100;
position: relative;
}
.glb-entry {
height: 56px;
width: 160px;
display: flex;
flex-direction: row;
}
.glb-main-info {
display: flex;
flex-direction: column;
width: 62px;
}
.glb-rank-box {
display: flex;
flex-direction: column;
}
.glb-avatar {
height: 48px;
width: 48px;
margin: 2px;
border-style: solid;
border-width: 2px;
border-color: black;
}
.glb-wins-img, .glb-darts-img {
height: 15px;
width: 15px;
margin: 0;
}
.glb-volforce {
font-size: 15px;
color: #FF00AA;
text-align: left;
}
.glb-rank-icon {
}
body {
margin: 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

View File

@ -27,6 +27,7 @@
<link rel="stylesheet" type="text/css" media="screen" href="{% static 'bloonsa_game/css/main.css' %}"/>
<link rel="stylesheet" type="text/css" media="screen" href="{% static 'bloonsa_game/css/append.css' %}"/>
{% block head %}{% endblock head %}
</head>
@ -47,6 +48,13 @@
</div>
<div class="skyscraper" id="skyscraper-l">
<iframe id="global-leaderboard-iframe"
frameborder="0"
scrolling="no"
sandbox="allow-same-origin"
onload="this.style.height=(this.contentWindow.document.body.scrollHeight+20)+'px';"
src="{% url 'bloonsa_game:leaderboard_global' %}"></iframe>
{% include 'bloonsa_game/modules/leaderboard_global.html' %}
</div>
<div id="content">
{% block content %}{% endblock content %}
@ -77,19 +85,9 @@
</div>
</div>
</div>
<div id="adholder1">
<script type="text/javascript"><!--
e9 = new Object();
e9.size = "728x90";
//--></script>
</div>
<div id="adholder1"></div>
<div id="adholder2"></div>
<div id="adholder3">
<script type="text/javascript"><!--
e9 = new Object();
e9.size = "160x600";
//--></script></div>
<div id="adholder3"></div>
<script type="text/javascript">
document.getElementById('adslot1').appendChild(document.getElementById('adholder1'));

View File

@ -0,0 +1,38 @@
{% load static %}
{% load bloonsa_game_tags %}
<link rel="stylesheet" type="text/css" media="screen" href="{% static 'bloonsa_game/css/leaderboard_global.css' %}"/>
<link rel="stylesheet" type="text/css" media="screen" href="{% static 'bloonsa_game/css/append.css' %}"/>
<div id="glb-global">
{% for player in players %}
<div class="rowa glb-entry">
<div class="glb-avatar-box">
<img class="glb-avatar" src="{{ player.avatar.url }}" height=48px width=48px>
</div>
<div class="glb-main-info">
<div class="glb-user">
<span class="glb-position">#{{ forloop.counter }}</span>
<span class="glb-username">{{ player.user.username }}</span>
</div>
<div class="glb-wins-box">
<object data="{% static 'bloonsa_game/img/levelinfo/wins.svg' %}"
class="filter-orange glb-wins-img"
type="image/svg+xml"></object>
<span>{{ player.bloonsa_levels_beaten_count }}</span>
</div>
<div class="glb-gdarts-box">
<object data="{% static 'bloonsa_game/img/levelinfo/dart.svg' %}"
class="filter-orange glb-darts-img"
type="image/svg+xml"></object>
<span>{{ player.bloonsa_dart_glitch_count }}</span>
</div>
</div>
<div class="glb-rank-box">
<img src="{% static 'bloonsa_game/img/ranks/'|concat:player.bloonsa_rank|concat:'.png' %}"
height=36px width=36px
class="glb-rank-icon">
<span class="glb-volforce">{{ player.bloonsa_volforce_rating }}</span>
</div>
</div>
{% endfor %}
</div>

View File

@ -12,3 +12,7 @@ def dummy(text):
@register.simple_tag(name="bloonsa_total_levels")
def total_levels():
return int(Level.objects.count())
@register.filter
def concat(arg1, arg2):
return str(arg1) + str(arg2)

View File

@ -1,14 +1,15 @@
from django.urls import path, include
from django.views.generic import RedirectView
from bloonsa_game.views import IndexView, TermsView, GameView, WIPView
from bloonsa_game.views import IndexView, TermsView, GameView, LeaderboardGlobalView
app_name = "bloonsa_game"
urlpatterns = [
path("", RedirectView.as_view(pattern_name="bloonsa_game:game", permanent=False), name="index"),
path("game", GameView.as_view(), name="game"),
path("game/<int:pk>", GameView.as_view(), name="gameSelect"),
path("game/<int:pk>", GameView.as_view(), name="game_select"),
path("leaderboard_global", LeaderboardGlobalView.as_view(), name="leaderboard_global")
# path("terms", TermsView.as_view(), name="terms"),
# path("contact", WIPView.as_view(), name="contact"),
]

View File

@ -1,7 +1,10 @@
from django.db.models import F, BooleanField, IntegerField, ExpressionWrapper, Count, Sum, DecimalField
from django.db.models.functions import Cast
from django.shortcuts import render
from django.views.generic import TemplateView
from bloonsa_game.models import Level
from users.models import Player
from users.util import bloonsa_util, actions
@ -33,13 +36,28 @@ class GameView(TemplateView):
"total_levels": total_levels,
"flashVars": level.get_flash_vars(seperator="&"),
})
return render(request, "bloonsa_game/game.html",
r = render(request, "bloonsa_game/game.html",
context={"total_levels": total_levels,})
r["x-frame-options"] = "sameorigin"
return r
class WIPView(TemplateView):
class LeaderboardGlobalView(TemplateView):
def get(self, request, *args, **kwargs):
return render(request, "bloonsa_game/error.html", context={})
def post(self, request, *args, **kwargs):
return render(request, "bloonsa_game/error.html", context={})
# Get top 100 best players
players = Player.objects.annotate(
clears=Count(F("bloonsa_level_scores__clear")),
golds=Count(F("bloonsa_level_scores__dart_glitch_ever"))
).annotate(
volforce=F("clears") + F("golds")
).order_by("-volforce")[:100]
for player in players:
print(player.bloonsa_volforce_rating)
r = render(request, "bloonsa_game/modules/leaderboard_global.html",
context={
"players": players
})
r["x-frame-options"] = "sameorigin"
return r

View File

@ -1,3 +1,5 @@
import math
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
@ -50,6 +52,31 @@ class Player(models.Model):
def has_beaten_bloonsa_level(self, level):
return bool(self.bloonsa_level_scores.filter(clear=True, level=level).exists())
@property
def bloonsa_dart_glitch_count(self):
return self.bloonsa_level_scores.filter(dart_glitch_ever=True).count()
@property
def bloonsa_volforce_rating(self):
total_levels = 66396
beaten_levels = self.bloonsa_levels_beaten_count
gold_levels = self.bloonsa_dart_glitch_count
estimated_limit = total_levels + ((total_levels / 100) * 20)
estimated_max_rank = 80.00
player_score = beaten_levels + gold_levels
player_volforce = player_score * (estimated_max_rank / estimated_limit)
import random
player_volforce = random.randint(100, 2700) / 100
return "{:.2f}".format(player_volforce)
@property
def bloonsa_rank(self):
return math.floor(float(self.bloonsa_volforce_rating) / 100) + 1
def __str__(self):
statesDict = {
"cheater": "😈" if self.suspected_cheater else "",

Binary file not shown.