Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Python Den scoreboard #1726

Merged
merged 11 commits into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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