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.
Files changed (170) hide show
  1. example_project/rapid_router_test_settings.py +19 -7
  2. example_project/settings.py +21 -8
  3. example_project/urls.py +5 -6
  4. game/__init__.py +1 -1
  5. game/admin.py +7 -2
  6. game/character.py +8 -0
  7. game/decor.py +40 -0
  8. game/end_to_end_tests/base_game_test.py +34 -27
  9. game/end_to_end_tests/editor_page.py +15 -0
  10. game/end_to_end_tests/game_page.py +88 -20
  11. game/end_to_end_tests/selenium_test_case.py +1 -20
  12. game/end_to_end_tests/test_cow_crashes.py +3 -5
  13. game/end_to_end_tests/test_level_editor.py +273 -10
  14. game/end_to_end_tests/test_level_selection.py +25 -3
  15. game/end_to_end_tests/test_play_through.py +222 -127
  16. game/end_to_end_tests/test_python_levels.py +41 -7
  17. game/end_to_end_tests/test_saving_workspace.py +2 -1
  18. game/forms.py +7 -1
  19. game/level_management.py +26 -11
  20. game/messages.py +899 -337
  21. game/migrations/0001_squashed_0025_levels_ordering_pt1.py +19 -1
  22. game/migrations/0026_levels_pt2.py +13 -2
  23. game/migrations/0032_cannot_turn_left_level.py +13 -2
  24. game/migrations/0033_recursion_level.py +13 -2
  25. game/migrations/0034_joes_level.py +13 -2
  26. game/migrations/0035_disable_route_score_level_70.py +0 -2
  27. game/migrations/0036_level_score_73.py +0 -2
  28. game/migrations/0037_level_score_79.py +0 -2
  29. game/migrations/0038_level_score_40.py +0 -1
  30. game/migrations/0042_level_score_73.py +0 -2
  31. game/migrations/0048_add_cow_field_and_blocks.py +0 -2
  32. game/migrations/0049_level_score_34.py +0 -2
  33. game/migrations/0050_level_score_40.py +0 -2
  34. game/migrations/0051_level_score_49.py +0 -1
  35. game/migrations/0086_loop_levels.py +13 -2
  36. game/migrations/0092_disable_algo_score_in_custom_levels.py +28 -0
  37. game/migrations/0093_alter_level_character_name.py +18 -0
  38. game/migrations/0094_add_hint_lesson_subtitle_to_levels.py +28 -0
  39. game/migrations/0095_level_commands.py +18 -0
  40. game/migrations/0096_alter_level_commands.py +18 -0
  41. game/migrations/0097_add_python_den_levels.py +1515 -0
  42. game/migrations/0098_add_episode_link_fields.py +44 -0
  43. game/migrations/0099_python_episodes_links.py +103 -0
  44. game/migrations/0100_reorder_python_levels.py +179 -0
  45. game/migrations/0101_rename_episodes.py +45 -0
  46. game/migrations/0102_reoder_episodes_13_14.py +136 -0
  47. game/migrations/0103_level_1015_solution.py +26 -0
  48. game/migrations/0104_remove_level_direct_drive.py +17 -0
  49. game/migrations/0105_delete_invalid_attempts.py +18 -0
  50. game/migrations/0106_fields_to_snake_case.py +48 -0
  51. game/migrations/0107_rename_worksheet_link_episode_student_worksheet_link.py +18 -0
  52. game/migrations/0108_episode_indy_worksheet_link.py +18 -0
  53. game/migrations/0109_create_episodes_23_and_24.py +99 -0
  54. game/migrations/0110_remove_episode_indy_worksheet_link_and_more.py +100 -0
  55. game/migrations/0111_create_worksheets.py +149 -0
  56. game/migrations/0112_worksheet_locked_classes.py +21 -0
  57. game/migrations/0113_level_needs_approval.py +18 -0
  58. game/migrations/0114_default_and_non_student_levels_no_approval.py +31 -0
  59. game/migrations/0115_level_level__default_does_not_need_approval.py +22 -0
  60. game/migrations/0116_update_worksheet_video_links.py +68 -0
  61. game/migrations/0117_update_solutions_to_if_else.py +61 -0
  62. game/models.py +127 -17
  63. game/permissions.py +51 -19
  64. game/python_den_urls.py +26 -0
  65. game/random_road.py +9 -9
  66. game/serializers.py +12 -17
  67. game/static/django_reverse_js/js/reverse.js +171 -0
  68. game/static/game/css/LilitaOne-Regular.ttf +0 -0
  69. game/static/game/css/backgrounds.css +8 -12
  70. game/static/game/css/dataTables.custom.css +3 -2
  71. game/static/game/css/editor.css +47 -0
  72. game/static/game/css/game.css +37 -43
  73. game/static/game/css/game_screen.css +16 -0
  74. game/static/game/css/level_editor.css +5 -0
  75. game/static/game/css/level_selection.css +17 -2
  76. game/static/game/image/Python_Den_hero_student.png +0 -0
  77. game/static/game/image/Python_levels_page.svg +1954 -0
  78. game/static/game/image/characters/front_view/Electric_van.svg +448 -0
  79. game/static/game/image/characters/top_view/Electric_van.svg +448 -0
  80. game/static/game/image/decor/city/solar_panel.svg +1200 -0
  81. game/static/game/image/decor/farm/solar_panel.svg +86 -0
  82. game/static/game/image/decor/grass/solar_panel.svg +86 -0
  83. game/static/game/image/decor/snow/solar_panel.svg +173 -0
  84. game/static/game/image/electric_van.svg +448 -0
  85. game/static/game/image/icons/description.svg +1 -0
  86. game/static/game/image/icons/hint.svg +1 -0
  87. game/static/game/image/icons/python.svg +1 -1
  88. game/static/game/image/pigeon.svg +684 -0
  89. game/static/game/image/python_den_header.svg +19 -0
  90. game/static/game/js/animation.js +65 -24
  91. game/static/game/js/blockly/msg/js/bg.js +52 -1
  92. game/static/game/js/blockly/msg/js/ca.js +52 -1
  93. game/static/game/js/blockly/msg/js/en-gb.js +2 -0
  94. game/static/game/js/blockly/msg/js/en.js +2 -0
  95. game/static/game/js/blockly/msg/js/es.js +52 -1
  96. game/static/game/js/blockly/msg/js/fr.js +2 -0
  97. game/static/game/js/blockly/msg/js/hi.js +2 -0
  98. game/static/game/js/blockly/msg/js/it.js +52 -1
  99. game/static/game/js/blockly/msg/js/pl.js +52 -1
  100. game/static/game/js/blockly/msg/js/pt-br.js +52 -1
  101. game/static/game/js/blockly/msg/js/ru.js +52 -1
  102. game/static/game/js/blockly/msg/js/ur.js +52 -1
  103. game/static/game/js/blocklyCustomBlocks.js +93 -52
  104. game/static/game/js/button.js +12 -0
  105. game/static/game/js/cow.js +11 -7
  106. game/static/game/js/drawing.js +68 -29
  107. game/static/game/js/editor.js +23 -0
  108. game/static/game/js/game.js +74 -110
  109. game/static/game/js/level_editor.js +646 -274
  110. game/static/game/js/level_moderation.js +33 -2
  111. game/static/game/js/level_selection.js +1 -1
  112. game/static/game/js/loadLanguages.js +2 -2
  113. game/static/game/js/model.js +32 -2
  114. game/static/game/js/pythonControl.js +14 -1
  115. game/static/game/js/scoreboard.js +0 -37
  116. game/static/game/js/scoreboardSharedLevels.js +48 -0
  117. game/static/game/js/skulpt/skulpt-stdlib.js +1 -1
  118. game/static/game/js/sound.js +52 -5
  119. game/static/game/raphael_image/characters/top_view/Electric_van.svg +448 -0
  120. game/static/game/raphael_image/decor/city/solar_panel.svg +1200 -0
  121. game/static/game/raphael_image/decor/farm/solar_panel.svg +86 -0
  122. game/static/game/raphael_image/decor/grass/solar_panel.svg +86 -0
  123. game/static/game/raphael_image/decor/snow/solar_panel.svg +173 -0
  124. game/static/game/raphael_image/pigeon.svg +685 -0
  125. game/static/game/sass/game.scss +2 -2
  126. game/static/game/sound/clown_horn.mp3 +0 -0
  127. game/static/game/sound/clown_horn.ogg +0 -0
  128. game/static/game/sound/electric_van_starting.mp3 +0 -0
  129. game/static/game/sound/electric_van_starting.ogg +0 -0
  130. game/static/game/sound/pigeon.mp3 +0 -0
  131. game/static/game/sound/pigeon.ogg +0 -0
  132. game/static/game/sound/sleigh_bells.mp3 +0 -0
  133. game/static/game/sound/sleigh_bells.ogg +0 -0
  134. game/static/game/sound/sleigh_crash.mp3 +0 -0
  135. game/static/game/sound/sleigh_crash.ogg +0 -0
  136. game/templates/game/base.html +34 -14
  137. game/templates/game/basenonav.html +11 -5
  138. game/templates/game/game.html +142 -38
  139. game/templates/game/level_editor.html +340 -236
  140. game/templates/game/level_moderation.html +19 -6
  141. game/templates/game/level_selection.html +18 -110
  142. game/templates/game/python_den_level_selection.html +291 -0
  143. game/templates/game/python_den_worksheet.html +101 -0
  144. game/templates/game/scoreboard.html +83 -64
  145. game/tests/test_level_editor.py +94 -26
  146. game/tests/test_level_selection.py +149 -46
  147. game/tests/test_python_den_worksheet.py +85 -0
  148. game/tests/test_scoreboard.py +34 -7
  149. game/tests/utils/level.py +32 -26
  150. game/theme.py +5 -5
  151. game/urls.py +199 -61
  152. game/views/language_code_conversions.py +86 -86
  153. game/views/level.py +155 -63
  154. game/views/level_editor.py +88 -55
  155. game/views/level_moderation.py +23 -0
  156. game/views/level_selection.py +116 -47
  157. game/views/level_solutions.py +491 -106
  158. game/views/scoreboard.py +76 -51
  159. game/views/worksheet.py +25 -0
  160. rapid_router-7.6.8.dist-info/METADATA +174 -0
  161. {rapid_router-5.18.0.dist-info → rapid_router-7.6.8.dist-info}/RECORD +164 -104
  162. {rapid_router-5.18.0.dist-info → rapid_router-7.6.8.dist-info}/WHEEL +1 -1
  163. example_project/manage.py +0 -10
  164. game/static/game/image/actions/go.svg +0 -18
  165. game/static/game/js/js-reverse.js +0 -14
  166. game/static/game/js/pqselect.min.js +0 -9
  167. game/static/game/js/widget-scroller.js +0 -906
  168. rapid_router-5.18.0.dist-info/METADATA +0 -17
  169. {rapid_router-5.18.0.dist-info → rapid_router-7.6.8.dist-info/licenses}/LICENSE.md +0 -0
  170. {rapid_router-5.18.0.dist-info → rapid_router-7.6.8.dist-info}/top_level.txt +0 -0
@@ -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
- current = start
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
- current += 1
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
- return [
84
- dict(
85
- episode,
86
- name=messages.get_episode_title(episode["id"]),
87
- levels=[
88
- dict(level, title=get_level_title(level["name"]))
89
- for level in episode["levels"]
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
- for episode in data
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 hasattr(user.userprofile, "teacher") and user.userprofile.teacher.is_admin
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(app_settings.EARLY_ACCESS_FUNCTION(request), 10, 15)
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(request.user)
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/level_selection.html",
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