Skip to content

Commit

Permalink
feat: Python Den scoreboard (#1726)
Browse files Browse the repository at this point in the history
* feat: Python Den scoreboard

* Properly use new reverse app

* Swap order of episodes 13 and 14

* Fix migration

* Improve levelless episode check

* Fix typo

* Update episodes in tests

* Migration fix

* Improve check even more
  • Loading branch information
faucomte97 authored Sep 6, 2024
1 parent 0bdd773 commit 6a3c526
Show file tree
Hide file tree
Showing 17 changed files with 518 additions and 138 deletions.
8 changes: 4 additions & 4 deletions game/end_to_end_tests/test_play_through.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,8 +343,8 @@ def test_python_level_013(self):
13, check_algorithm_score=False, from_python_den=True
)

def test_episode_14(self):
self._complete_episode(14, 14, from_python_den=True)
def test_episode_13(self):
self._complete_episode(13, 14, from_python_den=True)

def test_python_level_014(self):
self._complete_level(14, from_python_den=True)
Expand Down Expand Up @@ -396,8 +396,8 @@ def test_python_level_025(self):
25, check_algorithm_score=False, from_python_den=True
)

def test_episode_13(self):
self._complete_episode(13, 26, from_python_den=True)
def test_episode_14(self):
self._complete_episode(14, 26, from_python_den=True)

def test_python_level_026(self):
self._complete_level(26, from_python_den=True)
Expand Down
8 changes: 7 additions & 1 deletion game/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,24 @@
class ScoreboardForm(forms.Form):
def __init__(self, *args, **kwargs):
classes = kwargs.pop("classes")
language = kwargs.pop("language")
super(ScoreboardForm, self).__init__(*args, **kwargs)
classes_choices = [(c.id, c.name) for c in classes]

self.fields["classes"] = forms.MultipleChoiceField(
choices=classes_choices, widget=forms.CheckboxSelectMultiple()
)

episodes_range = (
range(1, 10) if language == "blockly" else range(12, 16)
)

# Each tuple in choices has two elements, id and name of each level
# First element is the actual value set on the model
# Second element is the string displayed on the dropdown menu
episodes_choices = (
(episode.id, episode.name)
for episode in Episode.objects.filter(pk__in=range(1, 10))
for episode in Episode.objects.filter(pk__in=episodes_range)
)
self.fields["episodes"] = forms.MultipleChoiceField(
choices=itertools.chain(episodes_choices),
Expand Down
4 changes: 2 additions & 2 deletions game/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -3329,8 +3329,8 @@ def get_episode_title(episode_id):
10: "Introduction to Python",
11: "Python",
12: "Counted Loops Using While",
13: "Indeterminate Loops",
14: "Selection in a Loop",
13: "Selection in a Loop",
14: "Indeterminate Loops",
15: "For Loops",
16: "Output, Operators, and Data",
17: "Variables, Input, and Casting",
Expand Down
136 changes: 136 additions & 0 deletions game/migrations/0102_reoder_episodes_13_14.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
from django.apps.registry import Apps
from django.db import migrations


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

episode12 = Episode.objects.get(pk=12)
episode13 = Episode.objects.get(pk=13)
episode14 = Episode.objects.get(pk=14)
episode20 = Episode.objects.get(pk=20)

episode13_levels = Level.objects.filter(
default=True, name__in=range(1026, 1041)
)
episode14_levels = Level.objects.filter(
default=True, name__in=range(1014, 1026)
)

episode13_levels.update(episode=episode14)
episode14_levels.update(episode=episode13)

old_episode13_name = episode13.name
old_episode13_lesson_plan_link = episode13.lesson_plan_link
old_episode13_slides_link = episode13.slides_link
old_episode13_worksheet_link = episode13.worksheet_link
old_episode13_video_link = episode13.video_link
old_episode14_name = episode14.name
old_episode14_lesson_plan_link = episode14.lesson_plan_link
old_episode14_slides_link = episode14.slides_link
old_episode14_worksheet_link = episode14.worksheet_link
old_episode14_video_link = episode14.video_link

episode13.name = old_episode14_name
episode13.lesson_plan_link = old_episode14_lesson_plan_link
episode13.slides_link = old_episode14_slides_link
episode13.worksheet_link = old_episode14_worksheet_link
episode13.video_link = old_episode14_video_link
episode14.name = old_episode13_name
episode14.lesson_plan_link = old_episode13_lesson_plan_link
episode14.slides_link = old_episode13_slides_link
episode14.worksheet_link = old_episode13_worksheet_link
episode14.video_link = old_episode13_video_link

episode12.next_episode = episode13
episode13.next_episode = episode14
episode14.next_episode = episode20

episode12.save()
episode13.save()
episode14.save()

episode12_last_level = episode12.level_set.first()
episode13_last_level = episode13.level_set.last()
episode14_last_level = episode14.level_set.last()

episode12_last_level.next_level = episode13.level_set.all()[0]
episode13_last_level.next_level = episode14.level_set.all()[0]
episode14_last_level.next_level = None

episode12_last_level.save()
episode13_last_level.save()
episode14_last_level.save()


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

episode12 = Episode.objects.get(pk=12)
episode13 = Episode.objects.get(pk=13)
episode14 = Episode.objects.get(pk=14)
episode20 = Episode.objects.get(pk=20)

episode13_levels = Level.objects.filter(
default=True, name__in=range(1014, 1026)
)
episode14_levels = Level.objects.filter(
default=True, name__in=range(1026, 1041)
)

episode13_levels.update(episode=episode14)
episode14_levels.update(episode=episode13)

old_episode13_name = episode13.name
old_episode13_lesson_plan_link = episode13.lesson_plan_link
old_episode13_slides_link = episode13.slides_link
old_episode13_worksheet_link = episode13.worksheet_link
old_episode13_video_link = episode13.video_link
old_episode14_name = episode14.name
old_episode14_lesson_plan_link = episode14.lesson_plan_link
old_episode14_slides_link = episode14.slides_link
old_episode14_worksheet_link = episode14.worksheet_link
old_episode14_video_link = episode14.video_link

episode13.name = old_episode14_name
episode13.lesson_plan_link = old_episode14_lesson_plan_link
episode13.slides_link = old_episode14_slides_link
episode13.worksheet_link = old_episode14_worksheet_link
episode13.video_link = old_episode14_video_link
episode14.name = old_episode13_name
episode14.lesson_plan_link = old_episode13_lesson_plan_link
episode14.slides_link = old_episode13_slides_link
episode14.worksheet_link = old_episode13_worksheet_link
episode14.video_link = old_episode13_video_link

episode12.next_episode = episode14
episode14.next_episode = episode13
episode13.next_episode = episode20

episode12.save()
episode13.save()
episode14.save()

episode12_last_level = episode12.level_set.first()
episode13_last_level = episode13.level_set.last()
episode14_last_level = episode14.level_set.last()

episode12_last_level.next_level = episode14.level_set.all()[0]
episode14_last_level.next_level = episode13.level_set.all()[0]
episode13_last_level.next_level = None

episode12_last_level.save()
episode13_last_level.save()
episode14_last_level.save()


class Migration(migrations.Migration):
dependencies = [("game", "0101_rename_episodes")]

operations = [
migrations.RunPython(
code=swap_episodes_13_14, reverse_code=unswap_episodes_13_14
)
]
2 changes: 2 additions & 0 deletions game/python_den_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from game.views.level import play_default_python_level, start_python_episode
from game.views.level_selection import python_levels
from game.views.scoreboard import python_scoreboard

urlpatterns = [
url(r"^$", python_levels, name="python_levels"),
Expand All @@ -15,4 +16,5 @@
start_python_episode,
name="start_python_episode",
),
url(r"^scoreboard/$", python_scoreboard, name="python_scoreboard"),
]
171 changes: 171 additions & 0 deletions game/static/django_reverse_js/js/reverse.js

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions game/static/game/css/backgrounds.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,7 @@
.bg--late-python {
background-color: #152584;
}

.banner--python-den--image {
width: 100%;
}
8 changes: 2 additions & 6 deletions game/static/game/css/level_selection.css
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,13 @@
margin-left: 15px;
}

#episodes .panel-header:not(.bg--loops-coming-soon) .collapsed.episode_range_text::after {
#episodes .panel-header .collapsed.episode_range_text::after {
content: "\e250";
font-family: "Glyphicons Halflings";
margin-left: 10px;
}

#episodes .panel-header:not(.bg--loops-coming-soon) .episode_range_text::after {
#episodes .panel-header .episode_range_text::after {
content: "\e252";
font-family: "Glyphicons Halflings";
margin-left: 10px;
Expand All @@ -95,10 +95,6 @@
text-decoration: none;
}

.banner--python-den--image {
width: 100%;
}

.button--level {
background-color: #f6be00;
padding: 5px 12px;
Expand Down
14 changes: 0 additions & 14 deletions game/static/game/js/js-reverse.js

This file was deleted.

13 changes: 8 additions & 5 deletions game/templates/game/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
</script>

<script type='text/javascript' src="{% static 'game/js/foundation/vendor/js.cookie.min.js' %}"></script>
<script type='text/javascript' src="{% static 'django_reverse_js/js/reverse.js' %}"></script>
<script type='text/javascript' src="{% url 'rapid-router/javascript-catalog' %}"></script>
<script type='text/javascript' src="{% static 'game/js/jquery.touchy.min.js' %}"></script>
{% endblock %}
Expand Down Expand Up @@ -56,26 +55,30 @@ <h4>Rapid router has been created to teach the first principles of computer prog
{% endif %}

{% block nav_ocargo_levels %}
{% if request.path == "/pythonden/" %}
{% if "/pythonden/" in request.path %}
<a class="button button--secondary button--secondary--light" href="{% url 'python_levels' %}">{% trans "Levels" %}</a>
{% else %}
<a class="button button--secondary button--secondary--light" href="{% url 'levels' %}">{% trans "Levels" %}</a>
{% endif %}
{% endblock nav_ocargo_levels %}

{% if request.path != "/pythonden/" %}
{% if "/pythonden/" not in request.path %}
{% block nav_ocargo_create %}
<a class="button button--secondary button--secondary--light" href="{% url 'level_editor' %}">{% trans "Create" %}</a>
{% endblock nav_ocargo_create %}
{% endif %}

{% if user|is_logged_in_as_school_user and request.path != "/pythonden/" %}
{% if user|is_logged_in_as_school_user %}
{% block nav_ocargo_scoreboard %}
{% if "/pythonden/" in request.path %}
<a class="button button--secondary button--secondary--light" href="{% url 'python_scoreboard' %}">{% trans "Scoreboard" %}</a>
{% else %}
<a class="button button--secondary button--secondary--light" href="{% url 'scoreboard' %}">{% trans "Scoreboard" %}</a>
{% endif %}
{% endblock nav_ocargo_scoreboard %}
{% endif %}

{% if user|is_logged_in_as_teacher and request.path != "/pythonden/" %}
{% if user|is_logged_in_as_teacher and "/pythonden/" not in request.path %}
{% block nav_ocargo_moderate %}
<a class="button button--secondary button--secondary--light" href="{% url 'level_moderation' %}">{% trans "Moderate" %}</a>
{% endblock nav_ocargo_moderate %}
Expand Down
2 changes: 1 addition & 1 deletion game/templates/game/basenonav.html
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,6 @@ <h2 id="myModal-title" class="ocargo-modal-title"></h2>
<script type='text/javascript' src="{% static 'game/js/handlebars.runtime-v4.7.7.js' %}"></script>
<script type='text/javascript' src="{% static 'game/js/templates.js' %}"></script>
<script type='text/javascript' src="{% static 'game/js/button.js' %}"></script>
<script type='text/javascript' src="{% static 'game/js/js-reverse.js' %}"></script>
<script type='text/javascript' src="{% static 'django_reverse_js/js/reverse.js' %}"></script>
<script type='text/javascript' src="{% url 'rapid-router/javascript-catalog' %}"></script>
{% endblock %}
Loading

0 comments on commit 6a3c526

Please sign in to comment.