Skip to content

Commit

Permalink
fix: fix scoring for custom levels (#1624)
Browse files Browse the repository at this point in the history
* fix scoring for custom levels

* debug test

* debug test

* debug test

* debug test

* debug test

* debug test

* debug test

* debug test

* debug test

* debug test

* debug test

* tidy code

* tidy code pt 2

* Merge branch 'master' into fix--fix-algorithm-score-in-created-levels

* address PR comments

* debug test

* debug test

* try patching

* debug test

* address PR comments, fix test

* add back line

* add migration, remove redundant line

* address PR comments

* add property

* fix typo

* add log lines

* debug test

* debug test

* test change to ajax url

* revert changes used for testing
  • Loading branch information
evemartin authored May 31, 2024
1 parent ce5c69e commit 0249354
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 34 deletions.
1 change: 1 addition & 0 deletions game/level_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ def save_level(level, data):
level.pythonViewEnabled = data.get("pythonViewEnabled", False)
level.theme = get_theme_by_pk(pk=data["theme"])
level.character = get_character_by_pk(pk=data["character"])
level.disable_algorithm_score = data.get("disable_algorithm_score", False)
level.save()

set_decor(level, data["decor"])
Expand Down
28 changes: 28 additions & 0 deletions game/migrations/0092_disable_algo_score_in_custom_levels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from django.apps.registry import Apps
from django.db import migrations

def disable_algo_score_for_existing_custom_levels(apps: Apps, *args):
Level = apps.get_model("game", "Level")

Level.objects.filter(
default=False
).update(disable_algorithm_score=True)

def enable_algo_score_for_existing_custom_levels(apps: Apps, *args):
Level = apps.get_model("game", "Level")

Level.objects.filter(
default=False
).update(disable_algorithm_score=False)

class Migration(migrations.Migration):
dependencies = [
("game", "0091_disable_algo_score_if_no_model_solution")
]

operations = [
migrations.RunPython(
disable_algo_score_for_existing_custom_levels,
reverse_code=enable_algo_score_for_existing_custom_levels
)
]
1 change: 1 addition & 0 deletions game/static/game/js/level_editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -2284,6 +2284,7 @@ ocargo.LevelEditor = function(levelId) {
// Other data
state.theme = currentTheme.id;
state.character = $('#character_select').val();
state.disable_algorithm_score = true;

return state;
}
Expand Down
18 changes: 9 additions & 9 deletions game/templates/game/game.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@

{% block scripts %}
{{block.super}}
<script defer id="data"
data-path="{{level.path|trim}}"
data-origin="{{level.origin|trim}}"
data-destinations="{{level.destinations|trim}}"
data-traffic-lights="{{level.traffic_lights|trim}}"
data-cows="{{level.cows|trim}}"
data-episode="{{level.episode.id|trim}}"
data-level-id="{{level.id|default_if_none:''|trim}}"
data-level-name="{{level.name|trim}}"
<script defer id="data"
data-path="{{level.path|trim}}"
data-origin="{{level.origin|trim}}"
data-destinations="{{level.destinations|trim}}"
data-traffic-lights="{{level.traffic_lights|trim}}"
data-cows="{{level.cows|trim}}"
data-episode="{{level.episode.id|trim}}"
data-level-id="{{level.id|default_if_none:''|trim}}"
data-level-name="{{level.name|trim}}"
>
var ANONYMOUS = {{level.anonymous|booltojs}}
var PATH = $('#data').data('path')
Expand Down
21 changes: 20 additions & 1 deletion game/tests/test_level_editor.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
from unittest.mock import patch

from common.models import Teacher
from common.tests.utils.classes import create_class_directly
Expand All @@ -13,7 +14,7 @@
from hamcrest import assert_that, equal_to

from game.models import Level
from game.tests.utils.level import create_save_level, create_save_level_with_multiple_houses
from game.tests.utils.level import create_save_level, create_save_level_with_multiple_houses, multiple_house_data
from game.tests.utils.teacher import add_teacher_to_school, create_school


Expand Down Expand Up @@ -392,6 +393,24 @@ def test_level_loading_with_multiple_houses(self):
assert response.status_code == 200
assert response_data["level"]["destinations"] == "[[3,4], [3,3]]"

@patch("game.level_management.save_level")
def test_custom_level_scoring(self, mock_save_level):
email1, password1 = signup_teacher_directly()

teacher1 = Teacher.objects.get(new_user__email=email1)

self.login(email1, password1)

level = create_save_level_with_multiple_houses(teacher1)

save_url = reverse("save_level_for_editor", kwargs={"levelId": level.id})
response = self.client.post(save_url, {"data": json.dumps(multiple_house_data)})

disable_algorithm_score = mock_save_level.call_args.args[1]["disable_algorithm_score"]

assert response.status_code == 200
assert disable_algorithm_score

def test_level_of_anonymised_teacher_is_hidden(self):
# Create 2 teacher accounts
email1, password1 = signup_teacher_directly()
Expand Down
48 changes: 25 additions & 23 deletions game/tests/utils/level.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,29 @@
from game.models import Level


multiple_house_data = {
"origin": '{"coordinate":[3,5],"direction":"S"}',
"pythonEnabled": False,
"decor": [],
"blocklyEnabled": True,
"blocks": [
{"type": "move_forwards"},
{"type": "turn_left"},
{"type": "turn_right"},
],
"max_fuel": "50",
"pythonViewEnabled": False,
"character": "3",
"name": "2",
"theme": 1,
"anonymous": False,
"cows": "[]",
"path": '[{"coordinate":[3,5],"connectedNodes":[1]},{"coordinate":[3,4],"connectedNodes":[0,2]}, {"coordinate": [3,3], "connectedNodes":[1]}]',
"traffic_lights": "[]",
"destinations": "[[3,4], [3,3]]",
}


def create_save_level(teacher_or_student, level_name="1", shared_with=None):
data = {
"origin": '{"coordinate":[3,5],"direction":"S"}',
Expand Down Expand Up @@ -37,30 +60,9 @@ def create_save_level(teacher_or_student, level_name="1", shared_with=None):
return level

def create_save_level_with_multiple_houses(teacher_or_student, level_name="2", shared_with=None):
data = {
"origin": '{"coordinate":[3,5],"direction":"S"}',
"pythonEnabled": False,
"decor": [],
"blocklyEnabled": True,
"blocks": [
{"type": "move_forwards"},
{"type": "turn_left"},
{"type": "turn_right"},
],
"max_fuel": "50",
"pythonViewEnabled": False,
"character": "3",
"name": level_name,
"theme": 1,
"anonymous": False,
"cows": "[]",
"path": '[{"coordinate":[3,5],"connectedNodes":[1]},{"coordinate":[3,4],"connectedNodes":[0,2]}, {"coordinate": [3,3], "connectedNodes":[1]}]',
"traffic_lights": "[]",
"destinations": "[[3,4], [3,3]]",
}
level = Level(default=False, anonymous=data["anonymous"])
level = Level(default=False, anonymous=multiple_house_data["anonymous"])
level.owner = teacher_or_student.user
level_management.save_level(level, data)
level_management.save_level(level, multiple_house_data)
level.save()

if shared_with is not None:
Expand Down
4 changes: 3 additions & 1 deletion game/views/level_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ def load_level_for_editor(request, levelID):
def save_level_for_editor(request, levelId=None):
"""Processes a request on creation of the map in the level editor"""
data = json.loads(request.POST["data"])
data["disable_algorithm_score"] = True

if ("character" not in data) or (not data["character"]):
# Set a default, to deal with issue #1158 "Cannot save custom level"
data["character"] = 1
Expand Down Expand Up @@ -269,7 +271,7 @@ def save_level_for_editor(request, levelId=None):

level.save()
response = {"id": level.id}
return HttpResponse(json.dumps(response), content_type="application/javascript")
return HttpResponse(json.dumps(response), content_type="application/json")
else:
return HttpResponseUnauthorized()

Expand Down

0 comments on commit 0249354

Please sign in to comment.