Progress on js exec stuff
This commit is contained in:
parent
53a4734cae
commit
919d4acf6f
@ -1,6 +1,8 @@
|
||||
from django.urls import path, include
|
||||
|
||||
from bloonsa_api.views import LoadLevel, RandomLevel, CompleteLevel, RateLevel
|
||||
from bloonsa_api.views import (LoadLevel, RandomLevel,
|
||||
CompleteLevel, RateLevel,
|
||||
GetStatusData)
|
||||
|
||||
app_name = "bloonsa_api"
|
||||
|
||||
@ -8,5 +10,7 @@ urlpatterns = [
|
||||
path("load_level", LoadLevel.as_view(), name="api-load_level"),
|
||||
path("get_random_level", RandomLevel.as_view(), name="api-get_random_level"),
|
||||
path("complete_level", CompleteLevel.as_view(), name="api-complete_level"),
|
||||
path("rate_level", RateLevel.as_view(), name="api-rate_level")
|
||||
path("rate_level", RateLevel.as_view(), name="api-rate_level"),
|
||||
|
||||
path("get_status_data", GetStatusData.as_view(), name="api-get_status_data")
|
||||
]
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
import json
|
||||
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.shortcuts import render, HttpResponse
|
||||
from django.http import HttpResponseBadRequest
|
||||
from django.http import HttpResponseBadRequest, JsonResponse
|
||||
from django.views.generic import TemplateView
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
@ -21,94 +25,127 @@ class LoadLevel(CSRFexemptTemplateView):
|
||||
if level_id is None or not level_id.isdigit():
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
level = Level.objects.filter(levelId=int(level_id)).first()
|
||||
level: Level = Level.objects.filter(level_id=int(level_id)).first()
|
||||
if level is None:
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
if request.user.is_authenticated:
|
||||
bloonsa_util.tag_player(request=request)
|
||||
player = Player.objects.get(user=request.user)
|
||||
player: Player = Player.objects.get(user=request.user)
|
||||
player.bloonsa_levels_played.add(level)
|
||||
bloonsa_util.log(player=player,
|
||||
action=actions.bloonsa_load_level_by_id,
|
||||
note=level.levelId)
|
||||
note=level.level_id)
|
||||
|
||||
flashVars = level.getFlashVars(seperator="&")
|
||||
flashVars = level.get_flash_vars(seperator="&")
|
||||
return HttpResponse(flashVars)
|
||||
|
||||
|
||||
class RandomLevel(CSRFexemptTemplateView):
|
||||
def post(self, request, *args, **kwargs):
|
||||
level = Level.objects.order_by("?").first()
|
||||
flashVars = level.getFlashVars(seperator="&")
|
||||
level: Level = Level.objects.order_by("?").first()
|
||||
flashVars = level.get_flash_vars(seperator="&")
|
||||
|
||||
if request.user.is_authenticated:
|
||||
bloonsa_util.tag_player(request=request)
|
||||
player = Player.objects.get(user=request.user)
|
||||
player: Player = Player.objects.get(user=request.user)
|
||||
level.played_by.add(player)
|
||||
bloonsa_util.log(player=player,
|
||||
action=actions.bloonsa_load_random_level,
|
||||
note=level.levelId)
|
||||
note=level.level_id)
|
||||
|
||||
return HttpResponse(flashVars)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
return self.post(request=request, *args, **kwargs)
|
||||
|
||||
|
||||
class CompleteLevel(CSRFexemptTemplateView):
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
if request.user.is_authenticated:
|
||||
bloonsa_util.tag_player(request=request)
|
||||
level_id = int(request.POST.get("level_id"))
|
||||
darts_left = int(request.POST.get("darts_left"))
|
||||
pops = int(request.POST.get("pops"))
|
||||
if not request.user.is_authenticated:
|
||||
return HttpResponse(content="GG", status=200)
|
||||
|
||||
level = Level.objects.get(levelId=level_id)
|
||||
player = Player.objects.get(user=request.user)
|
||||
bloonsa_util.tag_player(request=request)
|
||||
level_id = int(request.POST.get("level_id"))
|
||||
darts_left = int(request.POST.get("darts_left"))
|
||||
pops = int(request.POST.get("pops"))
|
||||
|
||||
prevScore = player.bloonsa_level_scores.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,
|
||||
pops=pops)
|
||||
if prevScore:
|
||||
player.bloonsa_level_scores.remove(prevScore)
|
||||
level: Level = Level.objects.get(level_id=level_id)
|
||||
player: Player = Player.objects.get(user=request.user)
|
||||
|
||||
player.bloonsa_level_scores.add(score)
|
||||
score.save()
|
||||
player.save()
|
||||
bloonsa_util.log(player=player,
|
||||
action=actions.bloonsa_submit_score,
|
||||
note=level.levelId)
|
||||
prevScore = player.bloonsa_level_scores.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,
|
||||
pops=pops)
|
||||
if prevScore:
|
||||
player.bloonsa_level_scores.remove(prevScore)
|
||||
|
||||
player.bloonsa_level_scores.add(score)
|
||||
score.save()
|
||||
player.save()
|
||||
bloonsa_util.log(player=player,
|
||||
action=actions.bloonsa_submit_score,
|
||||
note=level.level_id)
|
||||
|
||||
# Sending empty content means error in as3
|
||||
return HttpResponse(content="GG", status=200)
|
||||
|
||||
class RateLevel(CSRFexemptTemplateView):
|
||||
def post(self, request, *args, **kwargs):
|
||||
if request.user.is_authenticated:
|
||||
bloonsa_util.tag_player(request=request)
|
||||
rating = int(request.POST.get("rating"))
|
||||
level_id = int(request.POST.get("level_id"))
|
||||
level = Level.objects.get(levelId=level_id)
|
||||
player = Player.objects.get(user=request.user)
|
||||
ratingObject = Player.objects.filter(bloonsa_level_ratings__level=level).first()
|
||||
bloonsa_util.log(player=player,
|
||||
action=actions.bloonsa_rate_level,
|
||||
note=level.levelId)
|
||||
if ratingObject:
|
||||
ratingObject.rating = rating
|
||||
ratingObject.save()
|
||||
return HttpResponse(content="OK", status=200)
|
||||
|
||||
rating = LevelRating.objects.create(level=level,
|
||||
rating=rating)
|
||||
player.bloonsa_level_ratings.add(rating)
|
||||
rating.save()
|
||||
player.save()
|
||||
def post(self, request, *args, **kwargs):
|
||||
if not request.user.is_authenticated:
|
||||
return HttpResponse(content="OK", status=200)
|
||||
|
||||
return HttpResponse(status=400)
|
||||
bloonsa_util.tag_player(request=request)
|
||||
rating = int(request.POST.get("rating"))
|
||||
level_id = int(request.POST.get("level_id"))
|
||||
level: Level = Level.objects.get(level_id=level_id)
|
||||
player: Player = Player.objects.get(user=request.user)
|
||||
ratingObject = player.bloonsa_level_ratings.filter(level=level).first()
|
||||
bloonsa_util.log(player=player,
|
||||
action=actions.bloonsa_rate_level,
|
||||
note=level.level_id)
|
||||
if ratingObject:
|
||||
ratingObject.rating = rating
|
||||
ratingObject.save()
|
||||
return HttpResponse(content="OK", status=200)
|
||||
|
||||
rating = LevelRating.objects.create(level=level,
|
||||
rating=rating)
|
||||
player.bloonsa_level_ratings.add(rating)
|
||||
rating.save()
|
||||
player.save()
|
||||
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)
|
||||
total_levels = Level.objects.count()
|
||||
level_cleared = bool(player.bloonsa_level_scores.filter())
|
||||
|
||||
jdata = {
|
||||
"bloonsa_levels_played": player.bloonsa_levels_played_count,
|
||||
"bloonsa_levels_beaten": player.bloonsa_levels_beaten_count,
|
||||
"bloonsa_total_levels": total_levels,
|
||||
|
||||
"level_author_name": level.author.name,
|
||||
"level_author_id": level.author.id,
|
||||
"level_title": level.title,
|
||||
"level_id": level.level_id,
|
||||
"level_legacy_plays": level.plays,
|
||||
"level_plays": level.play_count,
|
||||
"level_rating": level.rating,
|
||||
"level_cleared": level_cleared,
|
||||
}
|
||||
return JsonResponse(jdata)
|
||||
@ -0,0 +1,23 @@
|
||||
# Generated by Django 5.1.6 on 2025-02-14 13:44
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('bloonsa_game', '0017_alter_levelrating_rating'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='author',
|
||||
old_name='authorId',
|
||||
new_name='author_id',
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='level',
|
||||
old_name='levelId',
|
||||
new_name='level_id',
|
||||
),
|
||||
]
|
||||
@ -6,36 +6,39 @@ from users.models import Player
|
||||
|
||||
class Author(models.Model):
|
||||
name = models.CharField(max_length=255)
|
||||
authorId = models.IntegerField()
|
||||
author_id = models.IntegerField()
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.authorId} - {self.name}"
|
||||
return f"{self.author_id} - {self.name}"
|
||||
|
||||
class Level(models.Model):
|
||||
author = models.ForeignKey(Author, on_delete=models.CASCADE)
|
||||
title = models.CharField(max_length=16)
|
||||
levelId = models.IntegerField()
|
||||
level_id = models.IntegerField()
|
||||
darts = models.SmallIntegerField()
|
||||
target = models.SmallIntegerField()
|
||||
plays = models.IntegerField()
|
||||
beats = models.IntegerField()
|
||||
beats = models.IntegerField() # TODO can be removed?
|
||||
rating = models.FloatField(null=True, blank=True)
|
||||
data = models.CharField(max_length=288)
|
||||
|
||||
played_by = models.ManyToManyField(Player, blank=True, related_name="bloonsa_levels_played")
|
||||
|
||||
@property
|
||||
def play_count(self):
|
||||
return self.played_by.count()
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.author} - {self.title}"
|
||||
|
||||
|
||||
def getFlashVars(self, seperator):
|
||||
def get_flash_vars(self, seperator):
|
||||
flashVars = {
|
||||
"levelNum": self.levelId,
|
||||
"levelNum": self.level_id,
|
||||
"title": self.title,
|
||||
"darts": self.darts,
|
||||
"target": self.target,
|
||||
"data": self.data,
|
||||
"authorID": self.author.authorId,
|
||||
"authorID": self.author.author_id,
|
||||
"rating": self.rating if self.rating else 0.0,
|
||||
}
|
||||
flashVarsStr = f"{seperator}".join([f"{k}={v}"
|
||||
|
||||
@ -26,4 +26,41 @@
|
||||
|
||||
.wide.centered {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#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 {
|
||||
color: #59b1ff;
|
||||
}
|
||||
|
||||
#current-level-container {
|
||||
height: 110px;
|
||||
}
|
||||
|
||||
#levels_played, #levels_beaten, #total_levels, .profile_text {
|
||||
white-space: break-spaces;
|
||||
float: left;
|
||||
padding-left: 0px;
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
#logout_button {
|
||||
float: left;
|
||||
display: block;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
#level-clear-state {
|
||||
|
||||
}
|
||||
@ -1,7 +1,46 @@
|
||||
function bloonsa_new_level_started(id) {
|
||||
console.log("new level started! id=" + id)
|
||||
function bloonsa_new_level_started(level_id) {
|
||||
console.log("call to new_level_started");
|
||||
bloonsa_update_data(level_id);
|
||||
}
|
||||
|
||||
function bloonsa_level_completed(id) {
|
||||
console.log("level completed! id=" + id)
|
||||
function bloonsa_level_completed(level_id) {
|
||||
bloonsa_update_data(level_id)
|
||||
}
|
||||
|
||||
function bloonsa_update_data(level_id) {
|
||||
const xhr = new XMLHttpRequest();
|
||||
console.log("call to update_data");
|
||||
xhr.open("POST", "/bloonsa_api/get_status_data", true);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.readyState === 4 && xhr.status === 200) {
|
||||
try {
|
||||
var r = JSON.parse(xhr.response);
|
||||
|
||||
bloonsa_update_html(r);
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error:", error);
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send(JSON.stringify({
|
||||
level_id: 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})`;
|
||||
if (r.level_cleared) {
|
||||
document.getElementById("level-clear-state").textContent = `✅`;
|
||||
}
|
||||
document.getElementById("levels_played").textContent = `${r.bloonsa_levels_played}`;
|
||||
document.getElementById("levels_beaten").textContent = `${r.bloonsa_levels_beaten}`;
|
||||
document.getElementById("total_levels").textContent = `${r.bloonsa_total_levels}`;
|
||||
|
||||
|
||||
|
||||
}
|
||||
Binary file not shown.
@ -68,11 +68,10 @@
|
||||
<div id="content">
|
||||
{% block content %}{% endblock content %}
|
||||
|
||||
<div class="wide left">
|
||||
<div id="current-level-container" class="wide left">
|
||||
<p>
|
||||
<h1 class="level-title-container"></h1>
|
||||
<h3 class="level-author-container"></h3><br>
|
||||
<p class="level-id-container"></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>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
{% load bloonsa_game_tags %}
|
||||
<div id="profile_box">
|
||||
<h3>{{ user }}</h3>
|
||||
<p>Levels played: {{ player.levels_played }}<br>
|
||||
Levels beaten: {{ player.levels_beaten }} / {{ total_levels }}</p>
|
||||
<h3><a href="/users/logout">Logout</a></h3>
|
||||
<h3 id="username">{{ user }}</h3>
|
||||
<div class="profile_text">Levels played: </div>
|
||||
<div id="levels_played">{{ player.bloonsa_levels_played_count }}</div><br>
|
||||
<div class="profile_text">Levels beaten: </div>
|
||||
<div id="levels_beaten">{{ player.bloonsa_levels_beaten_count }}</div>
|
||||
<div class="profile_text"> / </div><div id="total_levels">{{ total_levels }}</div><br>
|
||||
<a href="/users/logout" id="logout_button"><b>Logout</b></a>
|
||||
</div>
|
||||
@ -34,7 +34,7 @@ class GameView(TemplateView):
|
||||
return render(request, "bloonsa_game/level.html", context={
|
||||
"player": player,
|
||||
"total_levels": total_levels,
|
||||
"flashVars": level.getFlashVars(seperator="&"),
|
||||
"flashVars": level.get_flash_vars(seperator="&"),
|
||||
"levelTitle": level.title,
|
||||
"levelAuthor": level.author,
|
||||
})
|
||||
|
||||
@ -14,16 +14,16 @@ def run():
|
||||
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()
|
||||
authorObj = Author.objects.filter(author_id=authorID).first()
|
||||
if not authorObj:
|
||||
authorObj = Author.objects.create(authorId=authorID,
|
||||
authorObj = Author.objects.create(author_id=authorID,
|
||||
name=authorname)
|
||||
authorObj.save()
|
||||
|
||||
levelObj = Level.objects.filter(levelId=levelNum).first()
|
||||
levelObj = Level.objects.filter(level_id=levelNum).first()
|
||||
if not levelObj:
|
||||
levelObj = Level.objects.create(author=authorObj,
|
||||
levelId=levelNum,
|
||||
level_id=levelNum,
|
||||
title=title,
|
||||
plays=numPlays,
|
||||
beats=numCompleted,
|
||||
|
||||
@ -18,17 +18,15 @@ class Player(models.Model):
|
||||
|
||||
# If bloonsa_levels_played gets replaced then this needs to be updated
|
||||
@property
|
||||
def levels_played(self):
|
||||
def bloonsa_levels_played_count(self):
|
||||
return self.bloonsa_levels_played.count()
|
||||
|
||||
@property
|
||||
def levels_beaten(self):
|
||||
def bloonsa_levels_beaten_count(self):
|
||||
return self.bloonsa_level_scores.filter(clear=True).count()
|
||||
|
||||
@property
|
||||
def total_levels(self):
|
||||
# TODO
|
||||
return 0
|
||||
def has_beaten_level(self, level):
|
||||
bool(self.bloonsa_level_scores.filter(clear=True, level=level).first())
|
||||
|
||||
def __str__(self):
|
||||
statesDict = {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user