Insane progress, all gamebreaking bugs are fixed

This commit is contained in:
Walter 2025-02-07 15:31:19 +01:00
parent d07c7f73da
commit 515a270cf3
43 changed files with 618 additions and 147 deletions

View File

@ -5,6 +5,7 @@ from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from bloonsa_game.models import Level
from users.models import Player, Bloonsa_LevelRating
from users.util import tag_player
@ -15,40 +16,71 @@ class CSRFexemptTemplateView(TemplateView):
class LoadLevel(CSRFexemptTemplateView):
def post(self, request, *args, **kwargs):
tag_player(request=request)
levelNum = request.POST.get("level_num")
if levelNum is None or not levelNum.isdigit():
levelId = request.POST.get("levelId")
if levelId is None or not levelId.isdigit():
return HttpResponseBadRequest()
level = Level.objects.filter(id=int(levelNum)).first()
level = Level.objects.filter(levelId=int(levelId)).first()
if level is None:
return HttpResponseBadRequest()
if request.user.is_authenticated:
tag_player(request=request)
player = Player.objects.get(user=request.user)
player.bloonsa_levelsPlayed.add(level)
flashVars = level.getFlashVars(seperator="&")
return HttpResponse(flashVars)
class RandomLevel(CSRFexemptTemplateView):
def post(self, request, *args, **kwargs):
tag_player(request=request)
level = Level.objects.order_by("?").first()
flashVars = level.getFlashVars(seperator="&")
if request.user.is_authenticated:
tag_player(request=request)
player = Player.objects.get(user=request.user)
player.bloonsa_levelsPlayed.add(level)
return HttpResponse(flashVars)
def get(self, request, *args, **kwargs):
tag_player(request=request)
level = Level.objects.order_by("?").first()
flashVars = level.getFlashVars(seperator="&")
return HttpResponse(flashVars)
return self.post(request=request, *args, **kwargs)
class CompleteLevel(CSRFexemptTemplateView):
def post(self, request, *args, **kwargs):
tag_player(request=request)
pass
if request.user.is_authenticated:
tag_player(request=request)
levelId = int(request.POST.get("levelId"))
level = Level.objects.get(levelId=levelId)
player = Player.objects.get(user=request.user)
player.bloonsa_levelsBeaten.add(level)
# Sending empty content means error in as3
return HttpResponse(content="GG", status=200)
class RateLevel(CSRFexemptTemplateView):
def post(self, request, *args, **kwargs):
tag_player(request=request)
pass
if request.user.is_authenticated:
tag_player(request=request)
rating = int(request.POST.get("rating"))
levelId = int(request.POST.get("levelId"))
level = Level.objects.get(levelId=levelId)
player = Player.objects.get(user=request.user)
ratingObject = Bloonsa_LevelRating.objects.filter(player=player,
level=level).first()
if ratingObject:
ratingObject.rating = rating
ratingObject.save()
return HttpResponse(content="OK", status=200)
else:
rating = Bloonsa_LevelRating.objects.create(player=player,
level=level,
rating=rating)
rating.save()
return HttpResponse(content="OK", status=200)
return HttpResponse(status=400)

View File

@ -1,5 +1,6 @@
# Generated by Django 3.2.7 on 2021-09-28 17:44
# Generated by Django 5.1.6 on 2025-02-07 00:21
import django.db.models.deletion
from django.db import migrations, models
@ -12,19 +13,11 @@ class Migration(migrations.Migration):
operations = [
migrations.CreateModel(
name='Level',
name='Author',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('author', models.TextField()),
('title', models.CharField(max_length=16)),
('author_id', models.IntegerField()),
('level_id', models.IntegerField()),
('darts', models.IntegerField()),
('target', models.IntegerField()),
('plays', models.IntegerField()),
('completions', models.IntegerField()),
('rating', models.IntegerField(blank=True, null=True)),
('data', models.CharField(max_length=288)),
('name', models.CharField(max_length=255)),
('authorId', models.IntegerField()),
],
),
migrations.CreateModel(
@ -33,4 +26,19 @@ class Migration(migrations.Migration):
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
],
),
migrations.CreateModel(
name='Level',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=16)),
('levelId', models.IntegerField()),
('darts', models.IntegerField()),
('target', models.IntegerField()),
('plays', models.IntegerField()),
('completions', models.IntegerField()),
('rating', models.FloatField(blank=True, null=True)),
('data', models.CharField(max_length=288)),
('author', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='bloonsa_game.author')),
],
),
]

View File

@ -0,0 +1,25 @@
# Generated by Django 5.1.6 on 2025-02-07 08:38
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('bloonsa_game', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Bloonsa_LevelRatings',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('rating', models.SmallIntegerField()),
('level', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='bloonsa_game.level')),
],
),
migrations.DeleteModel(
name='Player',
),
]

View File

@ -0,0 +1,17 @@
# Generated by Django 5.1.6 on 2025-02-07 08:43
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('bloonsa_game', '0002_bloonsa_levelratings_delete_player'),
]
operations = [
migrations.RemoveField(
model_name='bloonsa_levelratings',
name='level',
),
]

View File

@ -0,0 +1,17 @@
# Generated by Django 5.1.6 on 2025-02-07 08:43
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('bloonsa_game', '0003_remove_bloonsa_levelratings_level'),
('users', '0007_remove_player_bloonsa_levelratings_and_more'),
]
operations = [
migrations.DeleteModel(
name='Bloonsa_LevelRatings',
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 5.1.6 on 2025-02-07 10:21
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('bloonsa_game', '0004_delete_bloonsa_levelratings'),
]
operations = [
migrations.RemoveField(
model_name='level',
name='completions',
),
migrations.AlterField(
model_name='level',
name='author',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='bloonsa_game.author'),
),
]

View File

@ -0,0 +1,29 @@
# Generated by Django 5.1.6 on 2025-02-07 10:23
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('bloonsa_game', '0005_remove_level_completions_alter_level_author'),
]
operations = [
migrations.AlterField(
model_name='level',
name='author',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='bloonsa_game.author'),
),
migrations.AlterField(
model_name='level',
name='darts',
field=models.SmallIntegerField(),
),
migrations.AlterField(
model_name='level',
name='target',
field=models.SmallIntegerField(),
),
]

View File

@ -0,0 +1,29 @@
# Generated by Django 5.1.6 on 2025-02-07 10:32
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('bloonsa_game', '0006_alter_level_author_alter_level_darts_and_more'),
]
operations = [
migrations.AddField(
model_name='level',
name='beats',
field=models.IntegerField(null=True),
),
migrations.AlterField(
model_name='level',
name='author',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='bloonsa_game.author'),
),
migrations.AlterField(
model_name='level',
name='plays',
field=models.IntegerField(null=True),
),
]

View File

@ -0,0 +1,23 @@
# Generated by Django 5.1.6 on 2025-02-07 10:36
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('bloonsa_game', '0007_level_beats_alter_level_author_alter_level_plays'),
]
operations = [
migrations.AlterField(
model_name='level',
name='beats',
field=models.IntegerField(),
),
migrations.AlterField(
model_name='level',
name='plays',
field=models.IntegerField(),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 5.1.6 on 2025-02-07 10:38
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('bloonsa_game', '0008_alter_level_beats_alter_level_plays'),
]
operations = [
migrations.AlterField(
model_name='author',
name='authorId',
field=models.IntegerField(null=True),
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 5.1.6 on 2025-02-07 10:48
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('bloonsa_game', '0009_alter_author_authorid'),
]
operations = [
migrations.AlterField(
model_name='author',
name='authorId',
field=models.IntegerField(default=None),
preserve_default=False,
),
]

View File

@ -1,22 +1,20 @@
from django.db import models
# Create your models here.
class Author(models.Model):
name = models.CharField(max_length=255)
authorId = models.IntegerField()
def __str__(self):
return self.name
return f"{self.authorId} - {self.name}"
class Level(models.Model):
author = models.ForeignKey(Author, on_delete=models.DO_NOTHING)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
title = models.CharField(max_length=16)
levelId = models.IntegerField()
darts = models.IntegerField()
target = models.IntegerField()
darts = models.SmallIntegerField()
target = models.SmallIntegerField()
plays = models.IntegerField()
completions = models.IntegerField()
beats = models.IntegerField()
rating = models.FloatField(null=True, blank=True)
data = models.CharField(max_length=288)
@ -32,13 +30,8 @@ class Level(models.Model):
"target": self.target,
"data": self.data,
"authorID": self.author.authorId,
"numCompleted": self.completions,
"rating": self.rating if self.rating else 0.0,
}
flashVarsStr = f"{seperator}".join([f"{k}={v}"
for k, v in flashVars.items()])
return flashVarsStr
class Player(models.Model):
pass

View File

@ -0,0 +1,6 @@
<?xml version="1.0"?>
<cross-domain-policy>
<site-control permitted-cross-domain-policies="all"/>
<allow-access-from domain="*"/>
<allow-http-request-headers-from domain="*" headers="*"/>
</cross-domain-policy>

View File

@ -1,5 +1,8 @@
import os
from django.shortcuts import render
from django.views.generic import TemplateView
from django.views.static import serve
from bloonsa_game.models import Level
from users.util import tag_player

View File

@ -1,36 +0,0 @@
# Generated by Django 3.2.7 on 2021-09-28 18:06
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('game', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Author',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255)),
('authorId', models.IntegerField()),
],
),
migrations.RenameField(
model_name='level',
old_name='level_id',
new_name='levelId',
),
migrations.RemoveField(
model_name='level',
name='author_id',
),
migrations.AlterField(
model_name='level',
name='author',
field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='game.author'),
),
]

View File

@ -1,22 +0,0 @@
# Generated by Django 3.2.7 on 2021-09-28 18:39
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('game', '0002_auto_20210928_2006'),
]
operations = [
migrations.RemoveField(
model_name='level',
name='rating',
),
migrations.AddField(
model_name='level',
name='rating9',
field=models.IntegerField(blank=True, null=True),
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 3.2.7 on 2021-09-28 18:39
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('game', '0003_auto_20210928_2039'),
]
operations = [
migrations.RenameField(
model_name='level',
old_name='rating9',
new_name='rating',
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 3.2.7 on 2021-09-28 18:43
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('game', '0004_rename_rating9_level_rating'),
]
operations = [
migrations.AlterField(
model_name='level',
name='rating',
field=models.FloatField(blank=True, null=True),
),
]

View File

@ -1,3 +1,5 @@
django==5.1.*
django-crispy-forms
crispy-bulma
django-extensions
django-cors-headers

0
app/scripts/__init__.py Normal file
View File

View File

@ -0,0 +1,36 @@
import sqlite3
import django
django.setup()
from tqdm import tqdm
from bloonsa_game.models import Level, Author
def run():
print("yes")
with sqlite3.connect("bloonsworld_levels.db") as db:
cursor = db.cursor()
cursor.execute("SELECT * FROM Levels")
for (levelNum, title, authorname, authorID, numPlays, numCompleted, rating, target, darts, data) in tqdm(cursor.fetchall()):
authorObj = Author.objects.filter(authorId=authorID).first()
if not authorObj:
authorObj = Author.objects.create(authorId=authorID,
name=authorname)
authorObj.save()
levelObj = Level.objects.filter(levelId=levelNum).first()
if not levelObj:
levelObj = Level.objects.create(author=authorObj,
levelId=levelNum,
title=title,
plays=numPlays,
beats=numCompleted,
rating=rating,
target=target,
darts=darts,
data=data)
levelObj.save()

View File

@ -25,8 +25,7 @@ SECRET_KEY = 'django-insecure-)e!wy4)=xinnd!d(iuw6*-tf^-)ptiwnttwf+9ql%*jy63wtd8
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
ALLOWED_HOSTS = ["*"]
# Application definition
@ -41,6 +40,7 @@ INSTALLED_APPS = [
# Plugins
"crispy_forms",
"crispy_bulma",
"django_extensions",
# Global
"users",
@ -139,3 +139,5 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
CRISPY_ALLOWED_TEMPLATE_PACKS = ("bulma",)
CRISPY_TEMPLATE_PACK = 'bulma'

View File

@ -14,11 +14,17 @@ Including another URLconf
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include
from django.urls import path, include, re_path
from django.views.generic.base import RedirectView
crossdomain_view = RedirectView.as_view(url='/static/bloonsa_game/misc/crossdomain.xml', permanent=True)
urlpatterns = [
path('admin/', admin.site.urls),
path("web_service/", include("bloonsa_api.urls", namespace="bloonsa_api")),
path("bloonsa_api/", include("bloonsa_api.urls", namespace="bloonsa_api")),
path("a/", include("bloonsa_game.urls", namespace="bloonsa_game")),
path("users/", include("users.urls", namespace="users"))
path("users/", include("users.urls", namespace="users")),
re_path(r'^crossdomain\.xml$', crossdomain_view)
]

View File

@ -1,5 +1,6 @@
from django.contrib import admin
from .models import Player, User
from .models import Player, Bloonsa_LevelRating
admin.site.register(Player)
admin.site.register(Bloonsa_LevelRating)

View File

@ -0,0 +1,52 @@
# Generated by Django 5.1.6 on 2025-02-07 01:25
import django.contrib.auth.models
import django.db.models.deletion
import django.utils.timezone
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
('bloonsa_game', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='CustomUser',
fields=[
('user_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'user',
'verbose_name_plural': 'users',
'abstract': False,
},
bases=('auth.user',),
managers=[
('objects', django.contrib.auth.models.UserManager()),
],
),
migrations.CreateModel(
name='Player',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('creationIP', models.GenericIPAddressField()),
('latestIP', models.GenericIPAddressField()),
('creationDate', models.DateTimeField(default=django.utils.timezone.now)),
('latestActivity', models.DateTimeField(default=django.utils.timezone.now)),
('suspectedCheater', models.BooleanField(default=False)),
('suspended', models.BooleanField(default=False)),
('banned', models.BooleanField(default=False)),
('admin', models.BooleanField(default=False)),
('levelsBeaten', models.ManyToManyField(blank=True, related_name='levelsBeaten', to='bloonsa_game.level')),
('levelsPlayed', models.ManyToManyField(blank=True, related_name='levelsPlayed', to='bloonsa_game.level')),
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='users.customuser')),
],
),
]

View File

@ -0,0 +1,24 @@
# Generated by Django 5.1.6 on 2025-02-07 02:15
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AlterField(
model_name='player',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.DeleteModel(
name='CustomUser',
),
]

View File

@ -0,0 +1,37 @@
# Generated by Django 5.1.6 on 2025-02-07 05:12
import django.contrib.auth.models
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
('users', '0002_alter_player_user_delete_customuser'),
]
operations = [
migrations.CreateModel(
name='CustomUser',
fields=[
('user_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'user',
'verbose_name_plural': 'users',
'abstract': False,
},
bases=('auth.user',),
managers=[
('objects', django.contrib.auth.models.UserManager()),
],
),
migrations.AlterField(
model_name='player',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='users.customuser'),
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 5.1.6 on 2025-02-07 05:17
from django.conf import settings
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('users', '0003_customuser_alter_player_user'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.RenameModel(
old_name='CustomUser',
new_name='BloonsUser',
),
]

View File

@ -0,0 +1,24 @@
# Generated by Django 5.1.6 on 2025-02-07 05:50
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0004_rename_customuser_bloonsuser'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AlterField(
model_name='player',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.DeleteModel(
name='BloonsUser',
),
]

View File

@ -0,0 +1,30 @@
# Generated by Django 5.1.6 on 2025-02-07 08:38
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('bloonsa_game', '0002_bloonsa_levelratings_delete_player'),
('users', '0005_alter_player_user_delete_bloonsuser'),
]
operations = [
migrations.RenameField(
model_name='player',
old_name='levelsBeaten',
new_name='bloonsa_levelsBeaten',
),
migrations.RenameField(
model_name='player',
old_name='levelsPlayed',
new_name='bloonsa_levelsPlayed',
),
migrations.AddField(
model_name='player',
name='bloonsa_levelRatings',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='bloonsa_levelRatings', to='bloonsa_game.bloonsa_levelratings'),
),
]

View File

@ -0,0 +1,28 @@
# Generated by Django 5.1.6 on 2025-02-07 08:43
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('bloonsa_game', '0003_remove_bloonsa_levelratings_level'),
('users', '0006_rename_levelsbeaten_player_bloonsa_levelsbeaten_and_more'),
]
operations = [
migrations.RemoveField(
model_name='player',
name='bloonsa_levelRatings',
),
migrations.CreateModel(
name='Bloonsa_LevelRatings',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('rating', models.SmallIntegerField()),
('level', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='bloonsa_game.level')),
('player', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='users.player')),
],
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 5.1.6 on 2025-02-07 08:46
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('bloonsa_game', '0004_delete_bloonsa_levelratings'),
('users', '0007_remove_player_bloonsa_levelratings_and_more'),
]
operations = [
migrations.RenameModel(
old_name='Bloonsa_LevelRatings',
new_name='Bloonsa_LevelRating',
),
]

View File

@ -0,0 +1,19 @@
# Generated by Django 5.1.6 on 2025-02-07 10:57
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0008_rename_bloonsa_levelratings_bloonsa_levelrating'),
]
operations = [
migrations.AlterField(
model_name='bloonsa_levelrating',
name='player',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='users.player'),
),
]

View File

@ -0,0 +1,20 @@
# Generated by Django 5.1.6 on 2025-02-07 11:14
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('bloonsa_game', '0010_alter_author_authorid'),
('users', '0009_alter_bloonsa_levelrating_player'),
]
operations = [
migrations.AlterField(
model_name='bloonsa_levelrating',
name='level',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='bloonsa_game.level'),
),
]

View File

@ -5,14 +5,11 @@ from django.contrib.auth.models import User
from bloonsa_game.models import Level
class Player(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
# Savedata
levelsPlayed = models.ManyToManyField(Level, blank=True, related_name="levelsPlayed")
levelsBeaten = models.ManyToManyField(Level, blank=True, related_name="levelsBeaten")
# levelsRated = ...
bloonsa_levelsPlayed = models.ManyToManyField(Level, blank=True, related_name="levelsPlayed")
bloonsa_levelsBeaten = models.ManyToManyField(Level, blank=True, related_name="levelsBeaten")
# Logging
creationIP = models.GenericIPAddressField()
latestIP = models.GenericIPAddressField()
@ -26,3 +23,11 @@ class Player(models.Model):
def __str__(self):
return f"{self.user} - {self.latestIP}"
class Bloonsa_LevelRating(models.Model):
level = models.ForeignKey(Level, on_delete=models.CASCADE)
player = models.ForeignKey(Player, on_delete=models.CASCADE)
rating = models.SmallIntegerField()
def __str__(self):
return f"{self.player.user} <{self.rating}> {self.level}"

View File

@ -16,7 +16,7 @@ def get_ip(request):
def init_player(request, user):
if not user.is_authenticated:
return
player = Player.objects.get(user=request.user)
player = Player.objects.filter(user=user).first()
if player:
return
ip = get_ip(request=request)
@ -32,7 +32,7 @@ def tag_player(request, user=None):
user = user or request.user
if not user.is_authenticated:
return
player = Player.objects.get(user=request.user)
player = Player.objects.filter(user=request.user).first()
if not player:
init_player(request=request, user=user)
player.latestActivity = timezone.now()