rapid-router 5.18.0__py2.py3-none-any.whl → 7.6.8__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.
- example_project/rapid_router_test_settings.py +19 -7
- example_project/settings.py +21 -8
- example_project/urls.py +5 -6
- game/__init__.py +1 -1
- game/admin.py +7 -2
- game/character.py +8 -0
- game/decor.py +40 -0
- game/end_to_end_tests/base_game_test.py +34 -27
- game/end_to_end_tests/editor_page.py +15 -0
- game/end_to_end_tests/game_page.py +88 -20
- game/end_to_end_tests/selenium_test_case.py +1 -20
- game/end_to_end_tests/test_cow_crashes.py +3 -5
- game/end_to_end_tests/test_level_editor.py +273 -10
- game/end_to_end_tests/test_level_selection.py +25 -3
- game/end_to_end_tests/test_play_through.py +222 -127
- game/end_to_end_tests/test_python_levels.py +41 -7
- game/end_to_end_tests/test_saving_workspace.py +2 -1
- game/forms.py +7 -1
- game/level_management.py +26 -11
- game/messages.py +899 -337
- game/migrations/0001_squashed_0025_levels_ordering_pt1.py +19 -1
- game/migrations/0026_levels_pt2.py +13 -2
- game/migrations/0032_cannot_turn_left_level.py +13 -2
- game/migrations/0033_recursion_level.py +13 -2
- game/migrations/0034_joes_level.py +13 -2
- game/migrations/0035_disable_route_score_level_70.py +0 -2
- game/migrations/0036_level_score_73.py +0 -2
- game/migrations/0037_level_score_79.py +0 -2
- game/migrations/0038_level_score_40.py +0 -1
- game/migrations/0042_level_score_73.py +0 -2
- game/migrations/0048_add_cow_field_and_blocks.py +0 -2
- game/migrations/0049_level_score_34.py +0 -2
- game/migrations/0050_level_score_40.py +0 -2
- game/migrations/0051_level_score_49.py +0 -1
- game/migrations/0086_loop_levels.py +13 -2
- game/migrations/0092_disable_algo_score_in_custom_levels.py +28 -0
- game/migrations/0093_alter_level_character_name.py +18 -0
- game/migrations/0094_add_hint_lesson_subtitle_to_levels.py +28 -0
- game/migrations/0095_level_commands.py +18 -0
- game/migrations/0096_alter_level_commands.py +18 -0
- game/migrations/0097_add_python_den_levels.py +1515 -0
- game/migrations/0098_add_episode_link_fields.py +44 -0
- game/migrations/0099_python_episodes_links.py +103 -0
- game/migrations/0100_reorder_python_levels.py +179 -0
- game/migrations/0101_rename_episodes.py +45 -0
- game/migrations/0102_reoder_episodes_13_14.py +136 -0
- game/migrations/0103_level_1015_solution.py +26 -0
- game/migrations/0104_remove_level_direct_drive.py +17 -0
- game/migrations/0105_delete_invalid_attempts.py +18 -0
- game/migrations/0106_fields_to_snake_case.py +48 -0
- game/migrations/0107_rename_worksheet_link_episode_student_worksheet_link.py +18 -0
- game/migrations/0108_episode_indy_worksheet_link.py +18 -0
- game/migrations/0109_create_episodes_23_and_24.py +99 -0
- game/migrations/0110_remove_episode_indy_worksheet_link_and_more.py +100 -0
- game/migrations/0111_create_worksheets.py +149 -0
- game/migrations/0112_worksheet_locked_classes.py +21 -0
- game/migrations/0113_level_needs_approval.py +18 -0
- game/migrations/0114_default_and_non_student_levels_no_approval.py +31 -0
- game/migrations/0115_level_level__default_does_not_need_approval.py +22 -0
- game/migrations/0116_update_worksheet_video_links.py +68 -0
- game/migrations/0117_update_solutions_to_if_else.py +61 -0
- game/models.py +127 -17
- game/permissions.py +51 -19
- game/python_den_urls.py +26 -0
- game/random_road.py +9 -9
- game/serializers.py +12 -17
- game/static/django_reverse_js/js/reverse.js +171 -0
- game/static/game/css/LilitaOne-Regular.ttf +0 -0
- game/static/game/css/backgrounds.css +8 -12
- game/static/game/css/dataTables.custom.css +3 -2
- game/static/game/css/editor.css +47 -0
- game/static/game/css/game.css +37 -43
- game/static/game/css/game_screen.css +16 -0
- game/static/game/css/level_editor.css +5 -0
- game/static/game/css/level_selection.css +17 -2
- game/static/game/image/Python_Den_hero_student.png +0 -0
- game/static/game/image/Python_levels_page.svg +1954 -0
- game/static/game/image/characters/front_view/Electric_van.svg +448 -0
- game/static/game/image/characters/top_view/Electric_van.svg +448 -0
- game/static/game/image/decor/city/solar_panel.svg +1200 -0
- game/static/game/image/decor/farm/solar_panel.svg +86 -0
- game/static/game/image/decor/grass/solar_panel.svg +86 -0
- game/static/game/image/decor/snow/solar_panel.svg +173 -0
- game/static/game/image/electric_van.svg +448 -0
- game/static/game/image/icons/description.svg +1 -0
- game/static/game/image/icons/hint.svg +1 -0
- game/static/game/image/icons/python.svg +1 -1
- game/static/game/image/pigeon.svg +684 -0
- game/static/game/image/python_den_header.svg +19 -0
- game/static/game/js/animation.js +65 -24
- game/static/game/js/blockly/msg/js/bg.js +52 -1
- game/static/game/js/blockly/msg/js/ca.js +52 -1
- game/static/game/js/blockly/msg/js/en-gb.js +2 -0
- game/static/game/js/blockly/msg/js/en.js +2 -0
- game/static/game/js/blockly/msg/js/es.js +52 -1
- game/static/game/js/blockly/msg/js/fr.js +2 -0
- game/static/game/js/blockly/msg/js/hi.js +2 -0
- game/static/game/js/blockly/msg/js/it.js +52 -1
- game/static/game/js/blockly/msg/js/pl.js +52 -1
- game/static/game/js/blockly/msg/js/pt-br.js +52 -1
- game/static/game/js/blockly/msg/js/ru.js +52 -1
- game/static/game/js/blockly/msg/js/ur.js +52 -1
- game/static/game/js/blocklyCustomBlocks.js +93 -52
- game/static/game/js/button.js +12 -0
- game/static/game/js/cow.js +11 -7
- game/static/game/js/drawing.js +68 -29
- game/static/game/js/editor.js +23 -0
- game/static/game/js/game.js +74 -110
- game/static/game/js/level_editor.js +646 -274
- game/static/game/js/level_moderation.js +33 -2
- game/static/game/js/level_selection.js +1 -1
- game/static/game/js/loadLanguages.js +2 -2
- game/static/game/js/model.js +32 -2
- game/static/game/js/pythonControl.js +14 -1
- game/static/game/js/scoreboard.js +0 -37
- game/static/game/js/scoreboardSharedLevels.js +48 -0
- game/static/game/js/skulpt/skulpt-stdlib.js +1 -1
- game/static/game/js/sound.js +52 -5
- game/static/game/raphael_image/characters/top_view/Electric_van.svg +448 -0
- game/static/game/raphael_image/decor/city/solar_panel.svg +1200 -0
- game/static/game/raphael_image/decor/farm/solar_panel.svg +86 -0
- game/static/game/raphael_image/decor/grass/solar_panel.svg +86 -0
- game/static/game/raphael_image/decor/snow/solar_panel.svg +173 -0
- game/static/game/raphael_image/pigeon.svg +685 -0
- game/static/game/sass/game.scss +2 -2
- game/static/game/sound/clown_horn.mp3 +0 -0
- game/static/game/sound/clown_horn.ogg +0 -0
- game/static/game/sound/electric_van_starting.mp3 +0 -0
- game/static/game/sound/electric_van_starting.ogg +0 -0
- game/static/game/sound/pigeon.mp3 +0 -0
- game/static/game/sound/pigeon.ogg +0 -0
- game/static/game/sound/sleigh_bells.mp3 +0 -0
- game/static/game/sound/sleigh_bells.ogg +0 -0
- game/static/game/sound/sleigh_crash.mp3 +0 -0
- game/static/game/sound/sleigh_crash.ogg +0 -0
- game/templates/game/base.html +34 -14
- game/templates/game/basenonav.html +11 -5
- game/templates/game/game.html +142 -38
- game/templates/game/level_editor.html +340 -236
- game/templates/game/level_moderation.html +19 -6
- game/templates/game/level_selection.html +18 -110
- game/templates/game/python_den_level_selection.html +291 -0
- game/templates/game/python_den_worksheet.html +101 -0
- game/templates/game/scoreboard.html +83 -64
- game/tests/test_level_editor.py +94 -26
- game/tests/test_level_selection.py +149 -46
- game/tests/test_python_den_worksheet.py +85 -0
- game/tests/test_scoreboard.py +34 -7
- game/tests/utils/level.py +32 -26
- game/theme.py +5 -5
- game/urls.py +199 -61
- game/views/language_code_conversions.py +86 -86
- game/views/level.py +155 -63
- game/views/level_editor.py +88 -55
- game/views/level_moderation.py +23 -0
- game/views/level_selection.py +116 -47
- game/views/level_solutions.py +491 -106
- game/views/scoreboard.py +76 -51
- game/views/worksheet.py +25 -0
- rapid_router-7.6.8.dist-info/METADATA +174 -0
- {rapid_router-5.18.0.dist-info → rapid_router-7.6.8.dist-info}/RECORD +164 -104
- {rapid_router-5.18.0.dist-info → rapid_router-7.6.8.dist-info}/WHEEL +1 -1
- example_project/manage.py +0 -10
- game/static/game/image/actions/go.svg +0 -18
- game/static/game/js/js-reverse.js +0 -14
- game/static/game/js/pqselect.min.js +0 -9
- game/static/game/js/widget-scroller.js +0 -906
- rapid_router-5.18.0.dist-info/METADATA +0 -17
- {rapid_router-5.18.0.dist-info → rapid_router-7.6.8.dist-info/licenses}/LICENSE.md +0 -0
- {rapid_router-5.18.0.dist-info → rapid_router-7.6.8.dist-info}/top_level.txt +0 -0
game/views/level_selection.py
CHANGED
|
@@ -2,16 +2,15 @@ from __future__ import absolute_import, division
|
|
|
2
2
|
|
|
3
3
|
from builtins import str
|
|
4
4
|
|
|
5
|
+
import game.level_management as level_management
|
|
6
|
+
import game.messages as messages
|
|
5
7
|
from django.core.cache import cache
|
|
6
8
|
from django.db.models import Max
|
|
7
9
|
from django.shortcuts import render
|
|
8
10
|
from django.utils.safestring import mark_safe
|
|
9
|
-
|
|
10
|
-
import game.level_management as level_management
|
|
11
|
-
import game.messages as messages
|
|
12
11
|
from game import app_settings, random_road
|
|
13
12
|
from game.cache import cached_episode
|
|
14
|
-
from game.models import Attempt, Episode, Level
|
|
13
|
+
from game.models import Attempt, Episode, Level, Worksheet
|
|
15
14
|
|
|
16
15
|
from .level_editor import play_anonymous_level
|
|
17
16
|
|
|
@@ -28,7 +27,7 @@ def max_score(level):
|
|
|
28
27
|
def fetch_episode_data_from_database(early_access, start, end):
|
|
29
28
|
episode_data = []
|
|
30
29
|
episode = Episode.objects.get(pk=start)
|
|
31
|
-
|
|
30
|
+
|
|
32
31
|
while episode is not None:
|
|
33
32
|
if episode.in_development and not early_access:
|
|
34
33
|
break
|
|
@@ -62,12 +61,12 @@ def fetch_episode_data_from_database(early_access, start, end):
|
|
|
62
61
|
}
|
|
63
62
|
|
|
64
63
|
episode_data.append(e)
|
|
65
|
-
episode = episode.next_episode
|
|
66
64
|
|
|
67
|
-
|
|
68
|
-
if current > end:
|
|
65
|
+
if episode.id == end:
|
|
69
66
|
break
|
|
70
67
|
|
|
68
|
+
episode = episode.next_episode
|
|
69
|
+
|
|
71
70
|
return episode_data
|
|
72
71
|
|
|
73
72
|
|
|
@@ -80,17 +79,56 @@ def fetch_episode_data(early_access, start=1, end=12):
|
|
|
80
79
|
if data is None:
|
|
81
80
|
data = fetch_episode_data_from_database(early_access, start, end)
|
|
82
81
|
cache.set(key, data)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
82
|
+
|
|
83
|
+
def worksheet_to_dict(index, worksheet):
|
|
84
|
+
return {
|
|
85
|
+
"id": worksheet.id,
|
|
86
|
+
"index": index,
|
|
87
|
+
"before_level": worksheet.before_level_id,
|
|
88
|
+
"lesson_plan_link": worksheet.lesson_plan_link,
|
|
89
|
+
"slides_link": worksheet.slides_link,
|
|
90
|
+
"student_worksheet_link": worksheet.student_worksheet_link,
|
|
91
|
+
"indy_worksheet_link": worksheet.indy_worksheet_link,
|
|
92
|
+
"video_link": worksheet.video_link,
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
episodes = []
|
|
96
|
+
for episode in data:
|
|
97
|
+
worksheets = [
|
|
98
|
+
worksheet_to_dict(index, worksheet)
|
|
99
|
+
for index, worksheet in enumerate(
|
|
100
|
+
Worksheet.objects.filter(
|
|
101
|
+
episode=episode["id"],
|
|
102
|
+
before_level__isnull=False,
|
|
103
|
+
).order_by("before_level"),
|
|
104
|
+
start=1,
|
|
105
|
+
)
|
|
106
|
+
]
|
|
107
|
+
|
|
108
|
+
worksheets += [
|
|
109
|
+
worksheet_to_dict(index, worksheet)
|
|
110
|
+
for index, worksheet in enumerate(
|
|
111
|
+
Worksheet.objects.filter(
|
|
112
|
+
episode=episode["id"],
|
|
113
|
+
before_level__isnull=True,
|
|
114
|
+
),
|
|
115
|
+
start=1 + len(worksheets),
|
|
116
|
+
)
|
|
117
|
+
]
|
|
118
|
+
|
|
119
|
+
episodes.append(
|
|
120
|
+
dict(
|
|
121
|
+
episode,
|
|
122
|
+
name=messages.get_episode_title(episode["id"]),
|
|
123
|
+
levels=[
|
|
124
|
+
dict(level, title=get_level_title(level["name"]))
|
|
125
|
+
for level in episode["levels"]
|
|
126
|
+
],
|
|
127
|
+
worksheets=worksheets,
|
|
128
|
+
)
|
|
91
129
|
)
|
|
92
|
-
|
|
93
|
-
|
|
130
|
+
|
|
131
|
+
return episodes
|
|
94
132
|
|
|
95
133
|
|
|
96
134
|
def get_level_title(i):
|
|
@@ -115,7 +153,10 @@ def is_teacher(user):
|
|
|
115
153
|
|
|
116
154
|
|
|
117
155
|
def is_admin_teacher(user):
|
|
118
|
-
return
|
|
156
|
+
return (
|
|
157
|
+
hasattr(user.userprofile, "teacher")
|
|
158
|
+
and user.userprofile.teacher.is_admin
|
|
159
|
+
)
|
|
119
160
|
|
|
120
161
|
|
|
121
162
|
def get_blockly_episodes(request):
|
|
@@ -123,10 +164,12 @@ def get_blockly_episodes(request):
|
|
|
123
164
|
|
|
124
165
|
|
|
125
166
|
def get_python_episodes(request):
|
|
126
|
-
return fetch_episode_data(
|
|
167
|
+
return fetch_episode_data(
|
|
168
|
+
app_settings.EARLY_ACCESS_FUNCTION(request), 16, 24
|
|
169
|
+
)
|
|
127
170
|
|
|
128
171
|
|
|
129
|
-
def levels(request):
|
|
172
|
+
def levels(request, language):
|
|
130
173
|
"""Loads a page with all levels listed.
|
|
131
174
|
|
|
132
175
|
**Context**
|
|
@@ -151,27 +194,13 @@ def levels(request):
|
|
|
151
194
|
else:
|
|
152
195
|
attempts = {}
|
|
153
196
|
|
|
154
|
-
blockly_episodes = get_blockly_episodes(request)
|
|
155
|
-
for episode in blockly_episodes:
|
|
156
|
-
for level in episode["levels"]:
|
|
157
|
-
attach_attempts_to_level(attempts, level)
|
|
158
|
-
level["locked_for_class"] = Level.objects.get(
|
|
159
|
-
id=level["id"]
|
|
160
|
-
).locked_for_class
|
|
161
|
-
|
|
162
|
-
python_episodes = get_python_episodes(request)
|
|
163
|
-
for episode in python_episodes:
|
|
164
|
-
for level in episode["levels"]:
|
|
165
|
-
attach_attempts_to_level(attempts, level)
|
|
166
|
-
level["locked_for_class"] = Level.objects.get(
|
|
167
|
-
id=level["id"]
|
|
168
|
-
).locked_for_class
|
|
169
|
-
|
|
170
197
|
owned_level_data = []
|
|
171
198
|
directly_shared_levels = []
|
|
172
199
|
indirectly_shared_levels = {}
|
|
173
200
|
if not request.user.is_anonymous:
|
|
174
|
-
owned_levels, shared_levels = level_management.get_loadable_levels(
|
|
201
|
+
owned_levels, shared_levels = level_management.get_loadable_levels(
|
|
202
|
+
request.user
|
|
203
|
+
)
|
|
175
204
|
|
|
176
205
|
for level in owned_levels:
|
|
177
206
|
owned_level_data.append(
|
|
@@ -218,17 +247,57 @@ def levels(request):
|
|
|
218
247
|
# if user is a student or a standard teacher, just get levels shared with them directly.
|
|
219
248
|
else:
|
|
220
249
|
directly_shared_levels.append(get_shared_level(level, attempts))
|
|
250
|
+
|
|
251
|
+
context = {
|
|
252
|
+
"owned_levels": owned_level_data,
|
|
253
|
+
"directly_shared_levels": directly_shared_levels,
|
|
254
|
+
"indirectly_shared_levels": indirectly_shared_levels,
|
|
255
|
+
"scores": attempts,
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if language == "blockly":
|
|
259
|
+
blockly_episodes = get_blockly_episodes(request)
|
|
260
|
+
|
|
261
|
+
for episode in blockly_episodes:
|
|
262
|
+
for level in episode["levels"]:
|
|
263
|
+
attach_attempts_to_level(attempts, level)
|
|
264
|
+
level["locked_for_class"] = Level.objects.get(
|
|
265
|
+
id=level["id"]
|
|
266
|
+
).locked_for_class
|
|
267
|
+
|
|
268
|
+
context["blocklyEpisodes"] = blockly_episodes
|
|
269
|
+
|
|
270
|
+
elif language == "python":
|
|
271
|
+
python_episodes = get_python_episodes(request)
|
|
272
|
+
|
|
273
|
+
for episode in python_episodes:
|
|
274
|
+
for level in episode["levels"]:
|
|
275
|
+
attach_attempts_to_level(attempts, level)
|
|
276
|
+
level["locked_for_class"] = Level.objects.get(
|
|
277
|
+
id=level["id"]
|
|
278
|
+
).locked_for_class
|
|
279
|
+
|
|
280
|
+
for worksheet in episode["worksheets"]:
|
|
281
|
+
worksheet["locked_classes"] = Worksheet.objects.get(
|
|
282
|
+
id=worksheet["id"]
|
|
283
|
+
).locked_classes
|
|
284
|
+
|
|
285
|
+
context["pythonEpisodes"] = python_episodes
|
|
286
|
+
|
|
287
|
+
return context
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def blockly_levels(request):
|
|
291
|
+
return render(
|
|
292
|
+
request, "game/level_selection.html", context=levels(request, "blockly")
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
def python_levels(request):
|
|
221
297
|
return render(
|
|
222
298
|
request,
|
|
223
|
-
"game/
|
|
224
|
-
context=
|
|
225
|
-
"blocklyEpisodes": blockly_episodes,
|
|
226
|
-
"pythonEpisodes": python_episodes,
|
|
227
|
-
"owned_levels": owned_level_data,
|
|
228
|
-
"directly_shared_levels": directly_shared_levels,
|
|
229
|
-
"indirectly_shared_levels": indirectly_shared_levels,
|
|
230
|
-
"scores": attempts,
|
|
231
|
-
},
|
|
299
|
+
"game/python_den_level_selection.html",
|
|
300
|
+
context=levels(request, "python"),
|
|
232
301
|
)
|
|
233
302
|
|
|
234
303
|
|