rapid-router 7.5.22__py2.py3-none-any.whl → 7.6.0__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -70,6 +70,7 @@ INSTALLED_APPS = (
70
70
  "django.contrib.sessions",
71
71
  "django.contrib.messages",
72
72
  "django.contrib.staticfiles",
73
+ "django_extensions",
73
74
  "django_reverse_js",
74
75
  "django_otp",
75
76
  "django_otp.plugins.otp_static",
game/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "7.5.22"
1
+ __version__ = "7.6.0"
game/messages.py CHANGED
@@ -80,6 +80,19 @@ def no_data_to_show_level_moderation():
80
80
  )
81
81
 
82
82
 
83
+ """ Strings used on the Python Den worksheet page. """
84
+
85
+
86
+ def no_permission_python_den_worksheet_title():
87
+ return "No permission"
88
+
89
+
90
+ def no_permission_python_den_worksheet_page():
91
+ return (
92
+ "This content is only available to logged in users. Please log in to access this page."
93
+ )
94
+
95
+
83
96
  """ String messages used as level tips in the game view. """
84
97
 
85
98
 
@@ -2566,6 +2579,11 @@ def hint_level109():
2566
2579
 
2567
2580
  # PYTHON DEN
2568
2581
 
2582
+ # Worksheets starter code
2583
+
2584
+ def worksheet_starter_code():
2585
+ return "# Write your code below"
2586
+
2569
2587
  # Episode 12, Levels 110 - 122
2570
2588
  (
2571
2589
  title_level1001,
game/python_den_urls.py CHANGED
@@ -3,6 +3,7 @@ from django.urls import re_path
3
3
  from game.views.level import play_default_python_level, start_python_episode
4
4
  from game.views.level_selection import python_levels
5
5
  from game.views.scoreboard import python_scoreboard
6
+ from game.views.worksheet import worksheet
6
7
 
7
8
  urlpatterns = [
8
9
  re_path(r"^$", python_levels, name="python_levels"),
@@ -16,5 +17,10 @@ urlpatterns = [
16
17
  start_python_episode,
17
18
  name="start_python_episode",
18
19
  ),
20
+ re_path(
21
+ r"^worksheet/(?P<worksheetId>[0-9]+)/$",
22
+ worksheet,
23
+ name="worksheet",
24
+ ),
19
25
  re_path(r"^scoreboard/$", python_scoreboard, name="python_scoreboard"),
20
26
  ]
@@ -0,0 +1,47 @@
1
+ editor-wc {
2
+ display: block;
3
+ width: 66%;
4
+ }
5
+
6
+ video,
7
+ iframe {
8
+ border: 1px solid black;
9
+ border-radius: 5px;
10
+ }
11
+
12
+ .tab-pane video,
13
+ .tab-pane iframe {
14
+ border-radius: 0 0 5px 5px;
15
+ }
16
+
17
+ .nav-tabs {
18
+ border-bottom: 0;
19
+ }
20
+
21
+ .nav-tabs > li > a {
22
+ text-decoration: none;
23
+ }
24
+
25
+ .nav-tabs > li > a,
26
+ .nav-tabs > li > a:hover,
27
+ .nav-tabs > li > a:focus {
28
+ border: 1px solid grey;
29
+ border-bottom-color: transparent;
30
+ font-weight: normal;
31
+ }
32
+
33
+ .nav-tabs > li.active > a,
34
+ .nav-tabs > li.active > a:hover,
35
+ .nav-tabs > li.active > a:focus {
36
+ border: 1px solid black;
37
+ border-bottom-color: transparent;
38
+ font-weight: bold;
39
+ text-decoration: none;
40
+ }
41
+
42
+ @media (max-width: 1000px) {
43
+ editor-wc {
44
+ height: 600px;
45
+ width: 100%;
46
+ }
47
+ }
@@ -0,0 +1,23 @@
1
+ $(document).ready(function () {
2
+ let shadowRoot = $("editor-wc")[0].shadowRoot;
3
+
4
+ // Set editor height and margin
5
+ $(shadowRoot).find("#root").css("height", "100%");
6
+ $(shadowRoot).find(".proj-container").css("margin", "0 10px 0 0");
7
+
8
+ // Fix project bar height
9
+ $(shadowRoot).find(".project-bar").css("block-size", "auto");
10
+
11
+ // Focus on text output tab
12
+ $(shadowRoot).find(".react-tabs__tab-text").click();
13
+
14
+ // Remove visual output and split view tabs
15
+ $(shadowRoot).find("#react-tabs-4").hide();
16
+ $(shadowRoot).find(".output-view-toggle").hide();
17
+
18
+ // Make editor font size not small
19
+ $(shadowRoot).find(".editor").removeClass("editor--small");
20
+
21
+ // Ensure window doesn't scroll to bottom of page
22
+ window.scrollTo(0, 0);
23
+ });
@@ -85,7 +85,7 @@
85
85
  </div>
86
86
  {% else %}
87
87
  <div class="col-sm-7 python-den-level">
88
- <a href="https://editor.raspberrypi.org/en/projects/blank-python-starter" target="_blank">{{episode.name}}{% if episode.worksheets|length > 1 %} pt. {{ worksheet.index }}{% endif %}</a>
88
+ <a href="{% url 'worksheet' worksheet.id %}">{{episode.name}}{% if episode.worksheets|length > 1 %} pt. {{ worksheet.index }}{% endif %}</a>
89
89
  </div>
90
90
  {% if user|is_logged_in_as_teacher %}
91
91
  <div class="col-sm-3 python-den-level">
@@ -169,7 +169,7 @@
169
169
  </div>
170
170
  {% else %}
171
171
  <div class="col-sm-7 python-den-level">
172
- <a href="https://editor.raspberrypi.org/en/projects/blank-python-starter" target="_blank">{{episode.name}}{% if episode.worksheets|length > 1 %} pt. {{ worksheet.index }}{% endif %}</a>
172
+ <a href="{% url 'worksheet' worksheet.id %}">{{episode.name}}{% if episode.worksheets|length > 1 %} pt. {{ worksheet.index }}{% endif %}</a>
173
173
  </div>
174
174
  {% if user|is_logged_in_as_teacher %}
175
175
  <div class="col-sm-3 python-den-level">
@@ -251,7 +251,7 @@
251
251
  </div>
252
252
  {% else %}
253
253
  <div class="col-sm-7 python-den-level">
254
- <a href="https://editor.raspberrypi.org/en/projects/blank-python-starter" target="_blank">{{episode.name}}{% if episode.worksheets|length > 1 %} pt. {{ worksheet.index }}{% endif %}</a>
254
+ <a href="{% url 'worksheet' worksheet.id %}">{{episode.name}}{% if episode.worksheets|length > 1 %} pt. {{ worksheet.index }}{% endif %}</a>
255
255
  </div>
256
256
  {% if user|is_logged_in_as_teacher %}
257
257
  <div class="col-sm-3 python-den-level">
@@ -0,0 +1,101 @@
1
+ {% extends 'game/base.html' %}
2
+
3
+ {% load static %}
4
+ {% load i18n %}
5
+ {% load app_tags %}
6
+
7
+ {% block scripts %}
8
+ {{block.super}}
9
+ <script type="text/javascript" src="https://editor-static.raspberrypi.org/releases/v0.29.1/web-component.js"></script>
10
+ <script type="text/javascript" src="{% static 'game/js/editor.js' %}"></script>
11
+
12
+ <script>
13
+ var EPISODE = "{{ worksheet.episode.name|escapejs }}"
14
+ </script>
15
+ {% endblock %}
16
+
17
+ {% block css %}
18
+ {{block.super}}
19
+ <link href="{% static 'game/css/level_selection.css' %}" rel="stylesheet" type="text/css">
20
+ <link href="{% static 'game/css/editor.css' %}" rel="stylesheet" type="text/css">
21
+ {% endblock %}
22
+
23
+ {% block header %}
24
+ <section class="banner">
25
+ {% if user|is_logged_in_as_student or user|is_independent_student %}
26
+ <img class="banner--python-den--image" title="Python Den logo" alt="Python Den logo" src="{% static 'game/image/Python_Den_hero_student.png' %}">
27
+ {% else %}
28
+ <img class="banner--python-den--image" title="Python Den logo" alt="Python Den logo" src="{% static 'game/image/Python_levels_page.svg' %}">
29
+ {% endif %}
30
+ </section>
31
+ {% endblock header %}
32
+
33
+ {% block content %}
34
+ <div class="container">
35
+ <h4 class="text-center">{{worksheet.episode.name}}</h4>
36
+ <p>You can write your code and see its output using the code editor below.</p>
37
+ <p>Next to it, you can view your worksheet - you can't write anything in it, but you can copy and paste from it.</p>
38
+ </div>
39
+
40
+ <div>
41
+ <div class="d-flex align-items-stretch justify-content-between m-5 flex-lg-row flex-md-column flex-sm-column">
42
+ <div class="d-flex align-items-stretch justify-content-center">
43
+ <a href="{% if user|is_independent_student %} {{worksheet.indy_worksheet_link}} {% else %} {{worksheet.student_worksheet_link}} {% endif %}"
44
+ class="button button--level button--icon hidden-md hidden-lg mb-5" target="_blank">
45
+ Worksheet<span class="iconify" data-icon="mdi:open-in-new"></span></a>
46
+ {% if not user|is_logged_in_as_student %}
47
+ <a href="{{worksheet.video_link}}" class="button button--level button--icon hidden-md hidden-lg mb-5 ml-5" target="_blank">
48
+ Video<span class="iconify" data-icon="mdi:open-in-new"></span></a>
49
+ {% endif %}
50
+ </div>
51
+
52
+ <editor-wc
53
+ code="{{starter_code}}"
54
+ use_editor_styles="true">
55
+ </editor-wc>
56
+
57
+ <div class="hidden-sm hidden-xs">
58
+ <div class="d-flex flex-column">
59
+ {% if user|is_logged_in_as_student %}
60
+ <iframe height="500" width="600" src="{{worksheet.student_worksheet_link}}"></iframe>
61
+ {% else %}
62
+ <ul class="nav nav-tabs" role="tablist">
63
+ <li role="presentation" class="active">
64
+ {% if user|is_independent_student %}
65
+ <a href="#worksheet" aria-controls="worksheet" role="tab" data-toggle="tab">Worksheet</a>
66
+ {% else %}
67
+ <a href="#student-worksheet" aria-controls="student_worksheet" role="tab" data-toggle="tab">Student Worksheet</a>
68
+ {% endif %}
69
+ </li>
70
+ {% if user|is_logged_in_as_teacher %}
71
+ <li role="presentation">
72
+ <a href="#worksheet" aria-controls="worksheet" role="tab" data-toggle="tab">Lesson plan</a>
73
+ </li>
74
+ {% endif %}
75
+ <li role="presentation">
76
+ <a href="#video" aria-controls="video" role="tab" data-toggle="tab">Video</a>
77
+ </li>
78
+ </ul>
79
+
80
+ <div class="tab-content">
81
+ {% if user|is_logged_in_as_teacher %}
82
+ <div role="tabpanel" class="tab-pane active" id="student-worksheet">
83
+ <iframe height="500" width="600" src="{{worksheet.student_worksheet_link}}"></iframe>
84
+ </div>
85
+ {% endif %}
86
+ <div role="tabpanel" class="tab-pane {% if user|is_independent_student %} active {% endif %}" id="worksheet">
87
+ <iframe height="500" width="600" src="{% if user|is_independent_student %} {{worksheet.indy_worksheet_link}} {% else %} {{worksheet.lesson_plan_link}} {% endif %}"></iframe>
88
+ </div>
89
+ <div role="tabpanel" class="tab-pane" id="video">
90
+ <video height="500" width="600"
91
+ src="{{worksheet.video_link}}" type="video/mp4" controls></video>
92
+ </div>
93
+ </div>
94
+ {% endif %}
95
+ </div>
96
+ </div>
97
+
98
+ </div>
99
+ </div>
100
+
101
+ {% endblock content %}
@@ -0,0 +1,85 @@
1
+ from deploy import captcha
2
+ from django.test.client import Client
3
+ from django.test.testcases import TestCase
4
+ from django.urls import reverse
5
+
6
+ from game import messages
7
+ from game.models import Worksheet
8
+
9
+
10
+ class PythonDenWorksheetTestCase(TestCase):
11
+ @classmethod
12
+ def setUpClass(cls):
13
+ cls.orig_captcha_enabled = captcha.CAPTCHA_ENABLED
14
+ captcha.CAPTCHA_ENABLED = False
15
+ super(PythonDenWorksheetTestCase, cls).setUpClass()
16
+
17
+ @classmethod
18
+ def tearDownClass(cls):
19
+ captcha.CAPTCHA_ENABLED = cls.orig_captcha_enabled
20
+ super(PythonDenWorksheetTestCase, cls).tearDownClass()
21
+
22
+ def setUp(self):
23
+ self.client = Client()
24
+
25
+ def login(self, email, password):
26
+ self.client.post(
27
+ reverse("teacher_login"),
28
+ {
29
+ "auth-username": email,
30
+ "auth-password": password,
31
+ "teacher_login_view-current_step": "auth",
32
+ },
33
+ follow=True,
34
+ )
35
+
36
+ def logout(self):
37
+ self.client.post(reverse("logout_view"), follow=True)
38
+
39
+ def student_login(self, name, access_code, password):
40
+ self.client.post(
41
+ reverse("student_login", kwargs={"access_code": access_code}),
42
+ {"username": name, "password": password},
43
+ follow=True,
44
+ )
45
+
46
+ def independent_student_login(self, email, password):
47
+ self.client.login(username=email, password=password)
48
+
49
+ def test_page_permissions(self):
50
+ response = self.client.get(reverse("worksheet", args="1"))
51
+
52
+ assert response.status_code == 200
53
+ assert (
54
+ response.context["title"]
55
+ == messages.no_permission_python_den_worksheet_title()
56
+ )
57
+ assert (
58
+ response.context["message"]
59
+ == messages.no_permission_python_den_worksheet_page()
60
+ )
61
+
62
+ self.login("alberteinstein@codeforlife.com", "Password1")
63
+
64
+ response = self.client.get(reverse("worksheet", args="1"))
65
+
66
+ assert response.status_code == 200
67
+ assert response.context["worksheet"] == Worksheet.objects.get(pk=1)
68
+
69
+ self.logout()
70
+ self.student_login("Leonardo", "AB123", "Password1")
71
+
72
+ response = self.client.get(reverse("worksheet", args="1"))
73
+
74
+ assert response.status_code == 200
75
+ assert response.context["worksheet"] == Worksheet.objects.get(pk=1)
76
+
77
+ self.logout()
78
+ self.independent_student_login("indianajones@codeforlife.com", "Password1")
79
+
80
+ response = self.client.get(reverse("worksheet", args="1"))
81
+
82
+ assert response.status_code == 200
83
+ assert response.context["worksheet"] == Worksheet.objects.get(pk=1)
84
+
85
+ self.logout()
@@ -0,0 +1,25 @@
1
+ from __future__ import absolute_import, division
2
+
3
+ from django.shortcuts import render
4
+
5
+ from game import messages
6
+ from game.models import Worksheet
7
+ from .helper import renderError
8
+
9
+
10
+ def worksheet(request, worksheetId):
11
+ if request.user.is_anonymous:
12
+ return renderError(
13
+ request,
14
+ messages.no_permission_python_den_worksheet_title(),
15
+ messages.no_permission_python_den_worksheet_page(),
16
+ )
17
+
18
+ worksheet = Worksheet.objects.get(pk=worksheetId)
19
+ starter_code = messages.worksheet_starter_code()
20
+
21
+ return render(
22
+ request,
23
+ "game/python_den_worksheet.html",
24
+ context={"worksheet": worksheet, "starter_code": starter_code},
25
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rapid-router
3
- Version: 7.5.22
3
+ Version: 7.6.0
4
4
  Classifier: Programming Language :: Python
5
5
  Classifier: Programming Language :: Python :: 3.12
6
6
  Classifier: Framework :: Django
@@ -9,7 +9,7 @@ Requires-Dist: asgiref==3.9.1; python_version >= "3.9"
9
9
  Requires-Dist: asttokens==3.0.0; python_version >= "3.8"
10
10
  Requires-Dist: certifi==2025.8.3; python_version >= "3.7"
11
11
  Requires-Dist: cffi==1.17.1; platform_python_implementation != "PyPy"
12
- Requires-Dist: cfl-common==8.8.2
12
+ Requires-Dist: cfl-common==8.9.1
13
13
  Requires-Dist: charset-normalizer==3.4.3; python_version >= "3.7"
14
14
  Requires-Dist: cryptography==44.0.1; python_version >= "3.7" and python_full_version not in "3.9.0, 3.9.1"
15
15
  Requires-Dist: decorator==5.2.1; python_version >= "3.8"
@@ -72,19 +72,20 @@ Requires-Dist: botocore==1.36.26; python_version >= "3.8" and extra == "dev"
72
72
  Requires-Dist: celery[sqs]==5.4.0; python_version >= "3.8" and extra == "dev"
73
73
  Requires-Dist: certifi==2025.8.3; python_version >= "3.7" and extra == "dev"
74
74
  Requires-Dist: cffi==1.17.1; platform_python_implementation != "PyPy" and extra == "dev"
75
- Requires-Dist: cfl-common==8.8.2; extra == "dev"
75
+ Requires-Dist: cfl-common==8.9.1; extra == "dev"
76
76
  Requires-Dist: charset-normalizer==3.4.3; python_version >= "3.7" and extra == "dev"
77
77
  Requires-Dist: click==8.2.1; python_version >= "3.10" and extra == "dev"
78
78
  Requires-Dist: click-didyoumean==0.3.1; python_full_version >= "3.6.2" and extra == "dev"
79
79
  Requires-Dist: click-plugins==1.1.1.2; extra == "dev"
80
80
  Requires-Dist: click-repl==0.3.0; python_version >= "3.6" and extra == "dev"
81
- Requires-Dist: codeforlife-portal==8.8.2; extra == "dev"
81
+ Requires-Dist: codeforlife-portal==8.9.1; extra == "dev"
82
82
  Requires-Dist: cryptography==44.0.1; (python_version >= "3.7" and python_full_version not in "3.9.0, 3.9.1") and extra == "dev"
83
83
  Requires-Dist: diff-match-patch==20241021; python_version >= "3.7" and extra == "dev"
84
84
  Requires-Dist: django==5.1.10; python_version >= "3.10" and extra == "dev"
85
85
  Requires-Dist: django-classy-tags==4.1.0; python_version >= "3.8" and extra == "dev"
86
86
  Requires-Dist: django-countries==7.6.1; extra == "dev"
87
87
  Requires-Dist: django-csp==3.8; extra == "dev"
88
+ Requires-Dist: django-extensions==4.1; python_version >= "3.9" and extra == "dev"
88
89
  Requires-Dist: django-formtools==2.5.1; python_version >= "3.8" and extra == "dev"
89
90
  Requires-Dist: django-import-export==4.2.0; python_version >= "3.9" and extra == "dev"
90
91
  Requires-Dist: django-otp==1.6.1; python_version >= "3.7" and extra == "dev"
@@ -109,6 +110,7 @@ Requires-Dist: isort==6.0.1; python_full_version >= "3.9.0" and extra == "dev"
109
110
  Requires-Dist: jmespath==1.0.1; python_version >= "3.7" and extra == "dev"
110
111
  Requires-Dist: kombu[sqs]==5.5.4; python_version >= "3.8" and extra == "dev"
111
112
  Requires-Dist: libsass==0.23.0; python_version >= "3.8" and extra == "dev"
113
+ Requires-Dist: markupsafe==3.0.2; python_version >= "3.9" and extra == "dev"
112
114
  Requires-Dist: more-itertools==8.7.0; python_version >= "3.5" and extra == "dev"
113
115
  Requires-Dist: mypy-extensions==1.1.0; python_version >= "3.8" and extra == "dev"
114
116
  Requires-Dist: numpy==2.3.2; python_version >= "3.11" and extra == "dev"
@@ -127,6 +129,7 @@ Requires-Dist: pycparser==2.22; python_version >= "3.8" and extra == "dev"
127
129
  Requires-Dist: pycurl==7.45.6; python_version >= "3.5" and extra == "dev"
128
130
  Requires-Dist: pygments==2.19.2; python_version >= "3.8" and extra == "dev"
129
131
  Requires-Dist: pyjwt==2.6.0; python_version >= "3.7" and extra == "dev"
132
+ Requires-Dist: pyopenssl==25.1.0; python_version >= "3.7" and extra == "dev"
130
133
  Requires-Dist: pypng==0.20220715.0; extra == "dev"
131
134
  Requires-Dist: pysocks==1.7.1; extra == "dev"
132
135
  Requires-Dist: pytest==8.4.1; python_version >= "3.9" and extra == "dev"
@@ -159,6 +162,7 @@ Requires-Dist: uvicorn-worker==0.2.0; python_version >= "3.8" and extra == "dev"
159
162
  Requires-Dist: vine==5.1.0; python_version >= "3.6" and extra == "dev"
160
163
  Requires-Dist: wcwidth==0.2.13; extra == "dev"
161
164
  Requires-Dist: websocket-client==1.8.0; python_version >= "3.8" and extra == "dev"
165
+ Requires-Dist: werkzeug==3.1.3; python_version >= "3.9" and extra == "dev"
162
166
  Requires-Dist: wheel==0.45.1; python_version >= "3.8" and extra == "dev"
163
167
  Requires-Dist: whitenoise==6.9.0; python_version >= "3.9" and extra == "dev"
164
168
  Requires-Dist: wsproto==1.2.0; python_full_version >= "3.7.0" and extra == "dev"
@@ -1,9 +1,9 @@
1
1
  example_project/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  example_project/rapid_router_test_settings.py,sha256=-8pBDGeDSM0ziu5BLUXVqB9J97ADGcUe_uAlPYyenSg,5030
3
- example_project/settings.py,sha256=0tXG2kHBxi1PoYPI63QmOMPd0S0MPqvDmIUjYc-hRH8,4574
3
+ example_project/settings.py,sha256=I_upxXh1PBbeX0aKttLeqjGbjPCDTfgMVJgBv7vcc0g,4599
4
4
  example_project/urls.py,sha256=XHug_cpNy21yOef3E1-wWT5VkTuxpl6ZXIlCj6jDjWA,422
5
5
  example_project/wsgi.py,sha256=U1W6WzZxZaIdYZ5tks7w9fqp5WS5qvn2iThsVcskrWw,829
6
- game/__init__.py,sha256=K6KD0ClxI-BwG6rOgDnY3EozzgSvyOcnFBNjwjmy-2Y,23
6
+ game/__init__.py,sha256=RS7ZvpeTsPTr9tY3yeVA3qW0ISlF5jRmARJfzG9UJLs,22
7
7
  game/admin.py,sha256=BLwwaqQYuqmMdwqnvhdan19iGxdcoBX4CXFk_ROG5-M,1431
8
8
  game/app_settings.py,sha256=mlg-1AiP7AR5JNOHAXXLuCrYWaZMmSihvSYk9c2c8YY,857
9
9
  game/cache.py,sha256=dtOiFl6Z4I2Q9-8Hz24ZI-5C0asXYSQhF2Be5q74N8g,2227
@@ -11,10 +11,10 @@ game/character.py,sha256=bdJ74jDN9zZnj-XaNYbCWmM8XiZY5q4zpqmHLcvE-ts,2397
11
11
  game/decor.py,sha256=VDY-kadOd0TSDo5znI5P3YzB3BFADCotIlp1g_eDOwQ,10096
12
12
  game/forms.py,sha256=7J9Ivn97qw4FC5B7WonDzi4Q5WHhF1I62eQWorUDv_o,2143
13
13
  game/level_management.py,sha256=wAKbu8JAVTHoM6YD6L3c7tPityKtWLGRNG32OX5SYRw,6289
14
- game/messages.py,sha256=W6ta1Aop8xTJXiO0Efej4BJXCVbafbPDFjl68hWQgs0,102172
14
+ game/messages.py,sha256=irfMKVnnB526e--GH0vPeUAat2We7WtWR0ifl5-0n_E,102565
15
15
  game/models.py,sha256=h_NS_6LL8uFoKVjg2CCZ53sE-FBv9QWM_dhCh4fIr5E,11446
16
16
  game/permissions.py,sha256=3dWQ_YYMNVm6OhI9gyZe36EiqsoyU5RzyxdIlfbZ2pM,7624
17
- game/python_den_urls.py,sha256=fO2U06_woa3dkdmWhYg6zR9hrqFyP2Cp9e5l-5dUEmc,637
17
+ game/python_den_urls.py,sha256=SgAoCwKeck-c8gGZadjKNhtq_-6PVc3m_he4NDSDw0Q,794
18
18
  game/random_road.py,sha256=1mCsfJJd5H3x6A4ZPtjPEMMA24kzXVZQJMb5DjlE95k,15458
19
19
  game/serializers.py,sha256=LiNXQVaUcW-Yzn4-TX6IOephTDMFyIvoqMUpDX3aqAY,5628
20
20
  game/theme.py,sha256=DgkOaCeMN0CJpZS0091ZWVeDXdz_E1WcGwPvuGTDX-E,1532
@@ -141,6 +141,7 @@ game/static/game/css/dataTables.custom.css,sha256=SXqJumyHKPFHgLDRo32iFiJ0_suXxS
141
141
  game/static/game/css/dataTables.fixedColumns.css,sha256=GyCgx04LPn0g6ANEzHzZA7TQO4wtlncHJszMTIUwqds,1121
142
142
  game/static/game/css/dataTables.jqueryui.css,sha256=RAit_2fXj0zOXq_IDQ94uKa3Q1pL_VntvloiurxN-ZU,28493
143
143
  game/static/game/css/dropdown.css,sha256=2S8AdwZ1rw6vKKHfuAiJflOm9j7669P-mCebJ7z2JlI,828
144
+ game/static/game/css/editor.css,sha256=uUWBkBhMZVZMUhIuDVtbZyBc69IfesGYI60YiOzaTn8,760
144
145
  game/static/game/css/game.css,sha256=kE3F1PzEzKZxbc38Q4d16lMUB2bZ_LQTbzK8YwdyI4s,6156
145
146
  game/static/game/css/game_screen.css,sha256=GPUDNIXWiXnJEE63d7fc3xf24XvZCR8AX2Nyjux3_cg,10174
146
147
  game/static/game/css/input.css,sha256=Ej7rAUydL38qmAOwGT15hamazDBcsjMcLG3x6yoLhvA,211
@@ -343,6 +344,7 @@ game/static/game/js/dataTables.fixedColumns.js,sha256=uaUCmQEzXC17dp9Mrv4pBnQI1U
343
344
  game/static/game/js/destination.js,sha256=9QJCvoIwiwWokxV3bUq1hTjASxnJPzcwfCPpUWf1c3M,221
344
345
  game/static/game/js/drawing.js,sha256=4VpHIWBtUbyscKynzecrACaMV6wpUUP-NvjxpUyZ2Zs,37091
345
346
  game/static/game/js/drawingConstants.js,sha256=U0BbcFBzNhBOIr-PiiKaRS4AtdOOk6NvB0boxvJQTSA,68
347
+ game/static/game/js/editor.js,sha256=V6DPBFbT50zPmY-U4kNQDBH11wnKAcmZzD6PFzZ4WWw,774
346
348
  game/static/game/js/event.js,sha256=VUGrUWxu1aWEk4AJFkzi7yZpXrIA6-9z4RIra3fhdvE,401
347
349
  game/static/game/js/fpsmeter.js,sha256=b6D2ZDaxxYEqMgrdy8gAE_wEJbndLCTRaM7kTVkA0Uw,8835
348
350
  game/static/game/js/game.js,sha256=6RGJ2SyWOPOV90E5cAc3Dij7F5wh-zjRNAjay81uDzU,38386
@@ -766,7 +768,8 @@ game/templates/game/level_editor.html,sha256=k8ogNMI8CUuwcTWfZvoURsTkjDwicC-oZyY
766
768
  game/templates/game/level_moderation.html,sha256=6JOutcJd9ZkkBppF4pKXdH5Q8dZpC2n1SUMHp7vVrEE,7299
767
769
  game/templates/game/level_selection.html,sha256=zDh59c8nE_T_tE3bvTwlxn96psYu0rROWdihMtcdNJI,11156
768
770
  game/templates/game/logged_students.html,sha256=WBTwdNb5YGopLdog7-vNDc9WO5_u8pqi3ehG12g8VOM,1471
769
- game/templates/game/python_den_level_selection.html,sha256=Tzqxk6qfxjS5NnwUEeVvQ36TAKS818tQPhFT8J5DhHs,21549
771
+ game/templates/game/python_den_level_selection.html,sha256=LiSBSG9DTzdfuow0bxkzTgLjusTFFMTb2Mf5Bx7qSRU,21414
772
+ game/templates/game/python_den_worksheet.html,sha256=E7CqfkLxI8RraCu-SwN5jn1zgPbXyV2qviWnfOBYv4M,4783
770
773
  game/templates/game/scoreboard.html,sha256=zv0spcadzAm_AOgkxkl-LvprO1DX29ruplokLdFMqYE,15784
771
774
  game/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
772
775
  game/templatetags/game/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -777,6 +780,7 @@ game/tests/test_level_editor.py,sha256=ttUMFpfpJp1Vc90X15v2i6AOItvPTwnA1BeuZ3sj9
777
780
  game/tests/test_level_moderation.py,sha256=OcU8nx0Ih4FCR9b_tp0w4n6zWVdJ3gzftz6fa0iz67U,7057
778
781
  game/tests/test_level_selection.py,sha256=IbrIPKDozvQ-05JAmLxHw9DsTfTwTBF2VJQPU8dn2XI,11800
779
782
  game/tests/test_models.py,sha256=L1F5yHtVdDmVuhw7uGDBiOOTYi9rgZVIjzd248-eqLc,2592
783
+ game/tests/test_python_den_worksheet.py,sha256=YSKMESqX4OJMNpwFCOp03pp-UV1rseVBKmGDcCy5QJ4,2691
780
784
  game/tests/test_random_road.py,sha256=vehN177IFKGwW2RvVOtR0X9N86cEyMmIpdhBg1mrJwo,7340
781
785
  game/tests/test_scoreboard.py,sha256=xvPkJbO8QWvc4pbou2AfE2WjPG1AsvpJt3y4isnd_z8,20101
782
786
  game/tests/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -799,8 +803,9 @@ game/views/level_selection.py,sha256=UI345nDv5iTRQ7VttiLKLzezJlaSlaKOnhlALZgMU9Q
799
803
  game/views/level_solutions.py,sha256=oYwx0p1LuY7609H2lid7lAq3QvcD6_K9cy5U_i6CwWg,96714
800
804
  game/views/scoreboard.py,sha256=Lxy7XtoG7VwWpTb-c22BGC6eN8uCmmOnQ2qjY-oXA3k,16914
801
805
  game/views/scoreboard_csv.py,sha256=yx4tOwx5QsHyU1S1BUPUqRBWIh5idq8QVtBID-NqZto,1768
802
- rapid_router-7.5.22.dist-info/licenses/LICENSE.md,sha256=9AbRlCDqD2D1tPibimysFv3zg3AIc49-eyv9aEsyq9w,115
803
- rapid_router-7.5.22.dist-info/METADATA,sha256=hnW8xd8ybqM8GrgHAEGesEcRgvzAV6SVe6ywdywXXH4,11362
804
- rapid_router-7.5.22.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
805
- rapid_router-7.5.22.dist-info/top_level.txt,sha256=rKP4ryr1t8Wcnx8grJHDViM3T5cMYH_0vygDjC04ArA,21
806
- rapid_router-7.5.22.dist-info/RECORD,,
806
+ game/views/worksheet.py,sha256=R7DgR3OhgITkmPHzkv0WLu_bkHvt3RGkcD7ySx3ippg,705
807
+ rapid_router-7.6.0.dist-info/licenses/LICENSE.md,sha256=9AbRlCDqD2D1tPibimysFv3zg3AIc49-eyv9aEsyq9w,115
808
+ rapid_router-7.6.0.dist-info/METADATA,sha256=1u5BissHxCfzBQtGdgl-smAZ-HDaF9VQ6k4Rn4oaq1E,11672
809
+ rapid_router-7.6.0.dist-info/WHEEL,sha256=JNWh1Fm1UdwIQV075glCn4MVuCRs0sotJIq-J6rbxCU,109
810
+ rapid_router-7.6.0.dist-info/top_level.txt,sha256=rKP4ryr1t8Wcnx8grJHDViM3T5cMYH_0vygDjC04ArA,21
811
+ rapid_router-7.6.0.dist-info/RECORD,,