Added dart_glitch field
This commit is contained in:
parent
c200728f51
commit
dec147f0ff
@ -49,7 +49,10 @@ class RandomLevel(CSRFexemptTemplateView):
|
||||
if request.user.is_authenticated:
|
||||
bloonsa_util.tag_player(request=request)
|
||||
player: Player = Player.objects.get(user=request.user)
|
||||
level.played_by.add(player)
|
||||
|
||||
if not player.bloonsa_levels_played.filter(pk=level.pk).exists():
|
||||
level.played_by.add(player)
|
||||
level.save()
|
||||
bloonsa_util.log(player=player,
|
||||
action=actions.bloonsa_load_random_level,
|
||||
note=level.level_id)
|
||||
@ -69,18 +72,21 @@ class CompleteLevel(CSRFexemptTemplateView):
|
||||
bloonsa_util.tag_player(request=request)
|
||||
level_id = int(request.POST.get("level_id"))
|
||||
darts_left = int(request.POST.get("darts_left"))
|
||||
dart_glitch = bool(request.POST.get("dart_glitch"))
|
||||
pops = int(request.POST.get("pops"))
|
||||
|
||||
level: Level = Level.objects.get(level_id=level_id)
|
||||
player: Player = Player.objects.get(user=request.user)
|
||||
|
||||
prevScore = player.bloonsa_level_scores.first()
|
||||
prevScore = LevelScore.objects.filter(player=player,
|
||||
level=level).first()
|
||||
if prevScore is None \
|
||||
or pops > prevScore.pops \
|
||||
or pops == prevScore.pops and darts_left > prevScore.darts_left:
|
||||
score = LevelScore.objects.create(level=level,
|
||||
clear=True,
|
||||
darts_left=darts_left,
|
||||
dart_glitch=dart_glitch,
|
||||
pops=pops)
|
||||
if prevScore:
|
||||
player.bloonsa_level_scores.remove(prevScore)
|
||||
@ -123,14 +129,15 @@ class RateLevel(CSRFexemptTemplateView):
|
||||
return HttpResponse(content="OK", status=200)
|
||||
|
||||
|
||||
|
||||
class GetStatusData(CSRFexemptTemplateView):
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
bloonsa_util.tag_player(request=request)
|
||||
level_id = int(json.loads(request.body).get("level_id"))
|
||||
level = Level.objects.get(level_id=level_id)
|
||||
player = Player.objects.get(user=request.user)
|
||||
level: Level = Level.objects.get(level_id=level_id)
|
||||
player: Player = Player.objects.get(user=request.user)
|
||||
score: LevelScore = LevelScore.objects.filter(player=player,
|
||||
level=level).first()
|
||||
total_levels = Level.objects.count()
|
||||
level_cleared = player.has_beaten_bloonsa_level(level=level)
|
||||
|
||||
@ -148,4 +155,11 @@ class GetStatusData(CSRFexemptTemplateView):
|
||||
"level_rating": level.rating,
|
||||
"level_cleared": level_cleared,
|
||||
}
|
||||
if score:
|
||||
jdata.update({
|
||||
"score_darts_left": score.darts_left,
|
||||
"score_dart_glitch": score.dart_glitch,
|
||||
"score_pops": score.pops,
|
||||
})
|
||||
|
||||
return JsonResponse(jdata)
|
||||
@ -1,7 +1,14 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import Level, Author, LevelScore
|
||||
from .models import Level, Author, LevelScore, LevelRating
|
||||
|
||||
@admin.register(LevelRating)
|
||||
class LevelRatingAdmin(admin.ModelAdmin):
|
||||
exclude = ("level",)
|
||||
|
||||
@admin.register(LevelScore)
|
||||
class LevelScoreAdmin(admin.ModelAdmin):
|
||||
exclude = ("level",)
|
||||
|
||||
admin.site.register(Level)
|
||||
admin.site.register(Author)
|
||||
admin.site.register(LevelScore)
|
||||
admin.site.register(Author)
|
||||
18
app/bloonsa_game/migrations/0019_levelscore_dart_glitch.py
Normal file
18
app/bloonsa_game/migrations/0019_levelscore_dart_glitch.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.1.6 on 2025-02-14 18:44
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('bloonsa_game', '0018_rename_authorid_author_author_id_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='levelscore',
|
||||
name='dart_glitch',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
||||
@ -0,0 +1,32 @@
|
||||
# Generated by Django 5.1.6 on 2025-02-14 20:46
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('bloonsa_game', '0019_levelscore_dart_glitch'),
|
||||
('users', '0023_alter_player_user'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='levelscore',
|
||||
name='darts_left',
|
||||
field=models.PositiveSmallIntegerField(default=0),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='levelscore',
|
||||
name='player',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='bloonsa_level_scores', to='users.player'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='levelscore',
|
||||
name='pops',
|
||||
field=models.PositiveSmallIntegerField(default=0),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
||||
@ -53,19 +53,20 @@ class LevelRating(models.Model):
|
||||
MaxValueValidator(10)])
|
||||
|
||||
def __str__(self):
|
||||
return (f"{self.player.user.username}"
|
||||
return (f"{self.player.user.username if self.player else ''}"
|
||||
f" - [<{int(self.rating) * '★'}> - {self.level.title}]")
|
||||
|
||||
# There should only be 1 score per player
|
||||
# Highest popcount wins
|
||||
class LevelScore(models.Model):
|
||||
player = models.ForeignKey(Player, on_delete=models.CASCADE, related_name="bloonsa_level_scores", null=True)
|
||||
player = models.ForeignKey(Player, on_delete=models.CASCADE, related_name="bloonsa_level_scores")
|
||||
level = models.ForeignKey(Level, on_delete=models.CASCADE)
|
||||
clear = models.BooleanField(default=True) # This is for if we ever submit scores for failed attempts
|
||||
darts_left = models.PositiveSmallIntegerField(null=True)
|
||||
pops = models.PositiveSmallIntegerField(null=True)
|
||||
darts_left = models.PositiveSmallIntegerField()
|
||||
dart_glitch = models.BooleanField(default=False) # This is triggered when the player lingers their last dart
|
||||
pops = models.PositiveSmallIntegerField()
|
||||
|
||||
def __str__(self):
|
||||
clearState = "✅" if self.clear else "❌"
|
||||
return (f"{self.player.user.username}'s {clearState} @ {self.level.title}: "
|
||||
return (f"{self.player.user.username if self.player else ''}'s {clearState} @ {self.level.title}: "
|
||||
f"🎈{self.pops} | 🎯{self.darts_left}")
|
||||
@ -28,23 +28,23 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#level-title,
|
||||
#level-id,
|
||||
#level-author,
|
||||
#level-author-id
|
||||
#level-clear-state {
|
||||
#level_title,
|
||||
#level_id,
|
||||
#level_author,
|
||||
#level_author-id
|
||||
#level_clear_state {
|
||||
white-space: break-spaces;
|
||||
float: left;
|
||||
padding-left: 0px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
#level-id,
|
||||
#level-author-id {
|
||||
#level_id,
|
||||
#level_author_id {
|
||||
color: #59b1ff;
|
||||
}
|
||||
|
||||
#current-level-container {
|
||||
#current_level_container {
|
||||
height: 110px;
|
||||
}
|
||||
|
||||
@ -61,6 +61,6 @@
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
#level-clear-state {
|
||||
#level_clear_state {
|
||||
|
||||
}
|
||||
@ -30,12 +30,14 @@ function bloonsa_update_data(level_id) {
|
||||
}
|
||||
|
||||
function bloonsa_update_html(r) {
|
||||
document.getElementById("level-title").textContent = r.level_title;
|
||||
document.getElementById("level-id").textContent = `(${r.level_id})`;
|
||||
document.getElementById("level-author").textContent = `by ${r.level_author_name}`;
|
||||
document.getElementById("level-author-id").textContent = `(${r.level_author_id})`;
|
||||
document.getElementById("level_title").textContent = r.level_title;
|
||||
document.getElementById("level_id").textContent = `(${r.level_id})`;
|
||||
document.getElementById("level_author").textContent = `by ${r.level_author_name}`;
|
||||
document.getElementById("level_author_id").textContent = `(${r.level_author_id})`;
|
||||
if (r.level_cleared) {
|
||||
document.getElementById("level-clear-state").textContent = `✅`;
|
||||
document.getElementById("level_clear_state").textContent = `✅`;
|
||||
} else {
|
||||
document.getElementById("level_clear_state").textContent = ``;
|
||||
}
|
||||
document.getElementById("levels_played").textContent = `${r.bloonsa_levels_played}`;
|
||||
document.getElementById("levels_beaten").textContent = `${r.bloonsa_levels_beaten}`;
|
||||
|
||||
Binary file not shown.
@ -68,10 +68,10 @@
|
||||
<div id="content">
|
||||
{% block content %}{% endblock content %}
|
||||
|
||||
<div id="current-level-container" class="wide left">
|
||||
<div id="current_level_container" class="wide left">
|
||||
<p>
|
||||
<h1 id="level-title"></h1><h1 id="level-id"></h1><h1 id="level-clear-state"></h1><h1></h1>
|
||||
<h3 id="level-author"></h3><h3 id="level-author-id"></h3><br>
|
||||
<h1 id="level_title"></h1><h1 id="level_id"></h1><h1 id="level_clear_state"></h1><h1></h1>
|
||||
<h3 id="level_author"></h3><h3 id="level_author_id"></h3><br>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
{% endblock title %}
|
||||
|
||||
{% block head %}
|
||||
|
||||
{% endblock head %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
@ -2,17 +2,5 @@ from django.contrib import admin
|
||||
from django.contrib.auth.admin import UserAdmin
|
||||
|
||||
from .models import Player, Log
|
||||
from bloonsa_game.models import LevelRating
|
||||
|
||||
@admin.register(Player)
|
||||
class PlayerAdmin(admin.ModelAdmin):
|
||||
# list_display = ("id", "user")
|
||||
# These lag too much
|
||||
# exclude = ("bloonsa_levels_played", "bloonsa_levels_beaten")
|
||||
|
||||
def get_played_levels(self, obj):
|
||||
return obj.bloonsa_levels_played.all()
|
||||
|
||||
|
||||
admin.site.register(LevelRating)
|
||||
admin.site.register(Log)
|
||||
|
||||
21
app/users/migrations/0023_alter_player_user.py
Normal file
21
app/users/migrations/0023_alter_player_user.py
Normal file
@ -0,0 +1,21 @@
|
||||
# Generated by Django 5.1.6 on 2025-02-14 20:46
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('users', '0022_rename_creationdate_player_creation_date_and_more'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='player',
|
||||
name='user',
|
||||
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='player', to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
@ -3,7 +3,7 @@ from django.utils import timezone
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
class Player(models.Model):
|
||||
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True, related_name="player")
|
||||
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="player")
|
||||
# Logging
|
||||
creation_ip = models.GenericIPAddressField()
|
||||
latest_ip = models.GenericIPAddressField()
|
||||
@ -26,7 +26,7 @@ class Player(models.Model):
|
||||
return self.bloonsa_level_scores.filter(clear=True).count()
|
||||
|
||||
def has_beaten_bloonsa_level(self, level):
|
||||
return bool(self.bloonsa_level_scores.filter(clear=True, level=level).first())
|
||||
return bool(self.bloonsa_level_scores.filter(clear=True, level=level).exists())
|
||||
|
||||
def __str__(self):
|
||||
statesDict = {
|
||||
|
||||
BIN
dev/designs/designs.free
Normal file
BIN
dev/designs/designs.free
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user