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
@@ -0,0 +1,44 @@
1
+ # Generated by Django 3.2.25 on 2024-08-23 23:31
2
+
3
+ from django.db import migrations, models
4
+ import django.db.models.deletion
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ('game', '0097_add_python_den_levels'),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AddField(
15
+ model_name='episode',
16
+ name='lesson_plan_link',
17
+ field=models.CharField(blank=True, default=None, max_length=500, null=True),
18
+ ),
19
+ migrations.AddField(
20
+ model_name='episode',
21
+ name='slides_link',
22
+ field=models.CharField(blank=True, default=None, max_length=500, null=True),
23
+ ),
24
+ migrations.AddField(
25
+ model_name='episode',
26
+ name='video_link',
27
+ field=models.CharField(blank=True, default=None, max_length=500, null=True),
28
+ ),
29
+ migrations.AddField(
30
+ model_name='episode',
31
+ name='worksheet_link',
32
+ field=models.CharField(blank=True, default=None, max_length=500, null=True),
33
+ ),
34
+ migrations.AlterField(
35
+ model_name='episode',
36
+ name='next_episode',
37
+ field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to='game.episode'),
38
+ ),
39
+ migrations.AlterField(
40
+ model_name='level',
41
+ name='next_level',
42
+ field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='prev_level', to='game.level'),
43
+ ),
44
+ ]
@@ -0,0 +1,103 @@
1
+ from django.apps.registry import Apps
2
+ from django.db import migrations
3
+
4
+
5
+ def add_resource_links_to_episodes(apps: Apps, *args):
6
+ Episode = apps.get_model("game", "Episode")
7
+
8
+ episode16 = Episode.objects.get(pk=16)
9
+ episode16.worksheet_link = "https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-1-output-operators-and-data"
10
+ episode16.video_link = "https://youtu.be/ve0RTsLGli0"
11
+ episode16.lesson_plan_link = "https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/DGiFT28ihVJK7ghZQHqu/python-1-output-operators-and-data"
12
+ episode16.slides_link = "https://4077022412-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2FEPwYyCp6pw2WqdeV84OY%2FPython%201%20-%20Output%2C%20Operators%20and%20Data.pptx?alt=media&token=771964a8-acab-4503-aa3d-034f24a93d3d"
13
+
14
+ episode17 = Episode.objects.get(pk=17)
15
+ episode17.worksheet_link = "https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-2-variables-input-and-casting"
16
+ episode17.video_link = "https://www.youtube.com/watch?v=H8askW-zd3I"
17
+ episode17.lesson_plan_link = "https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/DGiFT28ihVJK7ghZQHqu/python-2-variables-input-and-casting"
18
+ episode17.slides_link = "https://4077022412-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2FLFOUoXuOPUmeOdZ09cHW%2FPython%202%20-%20Variables%2C%20Input%20and%20Casting.pptx?alt=media&token=ef6d1581-36bd-4885-9a99-4dac53eee4c3"
19
+
20
+ episode18 = Episode.objects.get(pk=18)
21
+ episode18.worksheet_link = "https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-3-selection"
22
+ episode18.video_link = "https://www.youtube.com/watch?v=3XiQ97kP7H8"
23
+ episode18.lesson_plan_link = "https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/DGiFT28ihVJK7ghZQHqu/python-3-selection"
24
+ episode18.slides_link = "https://4077022412-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2F2mfkW4jWmJutkItlEnje%2FPython%203%20-%20Selection.pptx?alt=media&token=f6056de3-ef31-4031-aab8-be95da17d4cd"
25
+
26
+ episode19 = Episode.objects.get(pk=19)
27
+ episode19.worksheet_link = "https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-4-complex-selection"
28
+ episode19.video_link = "https://youtu.be/QOe5G-ZvWoc"
29
+ episode19.lesson_plan_link = "https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/DGiFT28ihVJK7ghZQHqu/python-4-complex-selection"
30
+ episode19.slides_link = "https://4077022412-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2Fgx68HomHKoxDxcoC72n6%2FPython%204%20-%20Complex%20Selection.pptx?alt=media&token=7d7c2c77-57a8-42a9-980b-015ff9b5b818"
31
+
32
+ episode12 = Episode.objects.get(pk=12)
33
+ episode12.worksheet_link = "https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-5-iteration-part-1"
34
+ episode12.video_link = "https://youtu.be/nJm3cWSkoi0"
35
+ episode12.lesson_plan_link = "https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/DGiFT28ihVJK7ghZQHqu/python-5-iteration-part-1"
36
+ episode12.slides_link = "https://4077022412-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2FG1pLAqvXg6s6hGtnb5ss%2FPython%205%20-%20Iteration%201.pptx?alt=media&token=d9bf3e3f-bf12-4227-89b7-70515e16dcc9"
37
+
38
+ episode14 = Episode.objects.get(pk=14)
39
+ episode14.worksheet_link = "https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-7-selection-in-a-loop"
40
+ episode14.video_link = "https://www.youtube.com/watch?v=WV_PLCcohMg"
41
+ episode14.lesson_plan_link = "https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/DGiFT28ihVJK7ghZQHqu/python-7-selection-in-a-loop"
42
+ episode14.slides_link = "https://4077022412-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2FPtj4c6IjIafaUPN8k4u1%2FPython%207%20-%20Selection%20in%20a%20loop.pptx?alt=media&token=9f5fce8e-bb72-4e38-8715-89ec7bcc6d6c"
43
+
44
+ episode13 = Episode.objects.get(pk=13)
45
+ episode13.worksheet_link = "https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-8-indeterminate-loops"
46
+ episode13.video_link = "https://www.youtube.com/watch?v=XgMGI8UzMDM"
47
+ episode13.lesson_plan_link = "https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/DGiFT28ihVJK7ghZQHqu/python-8-indeterminate-loops"
48
+ episode13.slides_link = "https://4077022412-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2FkxewOibLrvKLpJpuDBRH%2FPython%208%20-%20Indeterminate%20Loops.pptx?alt=media&token=ddf212d5-f0a7-47b2-8a6b-420ca2cccc12"
49
+
50
+ episode20 = Episode.objects.get(pk=20)
51
+ episode20.worksheet_link = "https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-9-string-manipulation"
52
+ episode20.video_link = "https://www.youtube.com/watch?v=E4AMg57_eoI"
53
+ episode20.lesson_plan_link = "https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/DGiFT28ihVJK7ghZQHqu/python-9-string-manipulation"
54
+ episode20.slides_link = "https://4077022412-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2FOAj7ngrHzqNAJgcYLz55%2FPython%209%20-%20String%20manipulation.pptx?alt=media&token=a7bdb069-6321-4828-8218-d4eabf4605ad"
55
+
56
+ episode21 = Episode.objects.get(pk=21)
57
+ episode21.worksheet_link = "https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-10-1d-lists"
58
+ episode21.video_link = "https://www.youtube.com/watch?v=Kb_-7IqWV0E"
59
+ episode21.lesson_plan_link = "https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/DGiFT28ihVJK7ghZQHqu/python-10-1d-lists"
60
+ episode21.slides_link = "https://4077022412-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2FZdt2shodTgZjNH4ai7ky%2FPython%2010%20-1D%20Lists.pptx?alt=media&token=66bdc866-2144-4203-b55e-93fa04b977a3"
61
+
62
+ episode15 = Episode.objects.get(pk=15)
63
+ episode15.worksheet_link = "https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-11-for-loops"
64
+ episode15.video_link = "https://www.youtube.com/watch?v=jNT_gQx9-k8"
65
+ episode15.lesson_plan_link = "https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/DGiFT28ihVJK7ghZQHqu/python-11-using-for-loops"
66
+ episode15.slides_link = "https://4077022412-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2F8AjR4b5mO4yOzEIVNI4V%2FPython%2011%20-%20For%20loops.pptx?alt=media&token=5eaa671c-a5eb-43a3-9f13-3478349027e5"
67
+
68
+ episode16.save()
69
+ episode17.save()
70
+ episode18.save()
71
+ episode19.save()
72
+ episode12.save()
73
+ episode14.save()
74
+ episode13.save()
75
+ episode20.save()
76
+ episode21.save()
77
+ episode15.save()
78
+
79
+
80
+ def remove_resource_links_from_episodes(apps: Apps, *args):
81
+ Episode = apps.get_model("game", "Episode")
82
+
83
+ for i in range(12, 21):
84
+ episode = Episode.objects.get(pk=i)
85
+ episode.worksheet_link = None
86
+ episode.video_link = None
87
+ episode.lesson_plan_link = None
88
+ episode.slides_link = None
89
+ episode.save()
90
+
91
+
92
+ class Migration(migrations.Migration):
93
+
94
+ dependencies = [
95
+ ("game", "0098_add_episode_link_fields"),
96
+ ]
97
+
98
+ operations = [
99
+ migrations.RunPython(
100
+ code=add_resource_links_to_episodes,
101
+ reverse_code=remove_resource_links_from_episodes,
102
+ )
103
+ ]
@@ -0,0 +1,179 @@
1
+ from django.apps.registry import Apps
2
+ from django.db import migrations
3
+ from django.db.models import F, IntegerField, CharField
4
+ from django.db.models.functions import Cast
5
+
6
+
7
+ def adjust_python_den_episodes(apps: Apps, *args):
8
+ Episode = apps.get_model("game", "Episode")
9
+ Level = apps.get_model("game", "Level")
10
+
11
+ episode12 = Episode.objects.get(pk=12)
12
+ episode13 = Episode.objects.get(pk=13)
13
+ episode14 = Episode.objects.get(pk=14)
14
+ episode15 = Episode.objects.get(pk=15)
15
+
16
+ episode12.next_episode = episode14
17
+ episode14.next_episode = episode13
18
+ episode13.next_episode = Episode.objects.get(pk=20)
19
+
20
+ episode12.in_development = False
21
+ episode13.in_development = False
22
+ episode14.in_development = False
23
+ episode15.in_development = False
24
+
25
+ episode12.save()
26
+ episode13.save()
27
+ episode14.save()
28
+ episode15.save()
29
+
30
+ Level.objects.filter(default=True, name__in=range(1014, 1026)).update(
31
+ episode=episode14
32
+ )
33
+ Level.objects.filter(default=True, name__in=range(1026, 1041)).update(
34
+ episode=episode13
35
+ )
36
+
37
+
38
+ def undo_adjust_python_den_episodes(apps: Apps, *args):
39
+ Episode = apps.get_model("game", "Episode")
40
+ Level = apps.get_model("game", "Level")
41
+
42
+ episode12 = Episode.objects.get(pk=12)
43
+ episode13 = Episode.objects.get(pk=13)
44
+ episode14 = Episode.objects.get(pk=14)
45
+ episode15 = Episode.objects.get(pk=15)
46
+
47
+ episode12.next_episode = episode13
48
+ episode13.next_episode = episode14
49
+ episode14.next_episode = Episode.objects.get(pk=20)
50
+
51
+ episode12.in_development = True
52
+ episode13.in_development = True
53
+ episode14.in_development = True
54
+ episode15.in_development = True
55
+
56
+ episode12.save()
57
+ episode13.save()
58
+ episode14.save()
59
+ episode15.save()
60
+
61
+ Level.objects.filter(default=True, name__in=range(1014, 1026)).update(
62
+ episode=episode13
63
+ )
64
+ Level.objects.filter(default=True, name__in=range(1026, 1041)).update(
65
+ episode=episode14
66
+ )
67
+
68
+
69
+ def rename_episode_12_levels(apps: Apps, *args):
70
+ Level = apps.get_model("game", "Level")
71
+
72
+ Level.objects.filter(default=True, name__in=range(110, 123)).update(
73
+ name=Cast(
74
+ Cast(F("name"), output_field=IntegerField()) + 891,
75
+ output_field=CharField()
76
+ )
77
+ )
78
+
79
+
80
+ def undo_rename_episode_12_levels(apps: Apps, *args):
81
+ Level = apps.get_model("game", "Level")
82
+
83
+ Level.objects.filter(default=True, name__in=range(1001, 1014)).update(
84
+ name=Cast(
85
+ Cast(F("name"), output_field=IntegerField()) - 891,
86
+ output_field=CharField()
87
+ )
88
+ )
89
+
90
+
91
+ def set_level_order(apps: Apps, *args):
92
+ Level = apps.get_model("game", "Level")
93
+
94
+ level79 = Level.objects.get(name="79", default=True)
95
+ level79.next_level = None
96
+ level79.save()
97
+
98
+ level109 = Level.objects.get(name="109", default=True)
99
+ level109.next_level = None
100
+ level109.save()
101
+
102
+ level1013 = Level.objects.get(name="1013", default=True)
103
+ level1013.next_level = Level.objects.get(name="1014", default=True)
104
+ level1013.save()
105
+
106
+ level1040 = Level.objects.get(default=True, name="1040")
107
+ level1040.next_level = None
108
+ level1040.save()
109
+
110
+
111
+ def reset_level_order(apps: Apps, *args):
112
+ Level = apps.get_model("game", "Level")
113
+
114
+ level79 = Level.objects.get(name="79", default=True)
115
+ level79.next_level = Level.objects.get(name="80", default=True)
116
+ level79.save()
117
+
118
+ level109 = Level.objects.get(name="109", default=True)
119
+ level109.next_level = Level.objects.get(name="1001", default=True)
120
+ level109.save()
121
+
122
+ level1013 = Level.objects.get(name="1013", default=True)
123
+ level1013.next_level = None
124
+ level1013.save()
125
+
126
+ level1040 = Level.objects.get(default=True, name="1040")
127
+ level1040.next_level = Level.objects.get(default=True, name="1041")
128
+ level1040.save()
129
+
130
+
131
+ def update_level_score_fields(apps: Apps, *args):
132
+ Level = apps.get_model("game", "Level")
133
+
134
+ level1001 = Level.objects.get(name="1001", default=True)
135
+ level1001.disable_algorithm_score = False
136
+ level1001.model_solution = "[5]"
137
+ level1001.save()
138
+
139
+ level1002 = Level.objects.get(name="1002", default=True)
140
+ level1002.disable_algorithm_score = False
141
+ level1002.model_solution = "[10]"
142
+ level1002.save()
143
+
144
+
145
+ def revert_level_score_fields(apps: Apps, *args):
146
+ Level = apps.get_model("game", "Level")
147
+
148
+ level1001 = Level.objects.get(name="1001", default=True)
149
+ level1001.disable_algorithm_score = True
150
+ level1001.model_solution = ""
151
+ level1001.save()
152
+
153
+ level1002 = Level.objects.get(name="1002", default=True)
154
+ level1002.disable_algorithm_score = True
155
+ level1002.model_solution = ""
156
+ level1002.save()
157
+
158
+
159
+ class Migration(migrations.Migration):
160
+
161
+ dependencies = [("game", "0099_python_episodes_links")]
162
+
163
+ operations = [
164
+ migrations.RunPython(
165
+ code=adjust_python_den_episodes,
166
+ reverse_code=undo_adjust_python_den_episodes,
167
+ ),
168
+ migrations.RunPython(
169
+ code=rename_episode_12_levels,
170
+ reverse_code=undo_rename_episode_12_levels,
171
+ ),
172
+ migrations.RunPython(
173
+ code=set_level_order, reverse_code=reset_level_order
174
+ ),
175
+ migrations.RunPython(
176
+ code=update_level_score_fields,
177
+ reverse_code=revert_level_score_fields,
178
+ ),
179
+ ]
@@ -0,0 +1,45 @@
1
+ from django.apps.registry import Apps
2
+ from django.db import migrations
3
+
4
+
5
+ def rename_episodes(apps: Apps, *args):
6
+ Episode = apps.get_model("game", "Episode")
7
+
8
+ episode13 = Episode.objects.get(pk=13)
9
+ episode14 = Episode.objects.get(pk=14)
10
+ episode15 = Episode.objects.get(pk=15)
11
+
12
+ episode13.name = "Indeterminate Loops"
13
+ episode14.name = "Selection in a Loop"
14
+ episode15.name = "For Loops"
15
+
16
+ episode13.save()
17
+ episode14.save()
18
+ episode15.save()
19
+
20
+
21
+ def unrename_episodes(apps: Apps, *args):
22
+ Episode = apps.get_model("game", "Episode")
23
+
24
+ episode13 = Episode.objects.get(pk=13)
25
+ episode14 = Episode.objects.get(pk=14)
26
+ episode15 = Episode.objects.get(pk=15)
27
+
28
+ episode13.name = "Indeterminate While Loops - coming soon"
29
+ episode14.name = "Selection in a Loop - coming soon"
30
+ episode15.name = "For Loops - coming soon"
31
+
32
+ episode13.save()
33
+ episode14.save()
34
+ episode15.save()
35
+
36
+
37
+ class Migration(migrations.Migration):
38
+
39
+ dependencies = [("game", "0100_reorder_python_levels")]
40
+
41
+ operations = [
42
+ migrations.RunPython(
43
+ code=rename_episodes, reverse_code=unrename_episodes
44
+ )
45
+ ]
@@ -0,0 +1,136 @@
1
+ from django.apps.registry import Apps
2
+ from django.db import migrations
3
+
4
+
5
+ def swap_episodes_13_14(apps: Apps, *args):
6
+ Episode = apps.get_model("game", "Episode")
7
+ Level = apps.get_model("game", "Level")
8
+
9
+ episode12 = Episode.objects.get(pk=12)
10
+ episode13 = Episode.objects.get(pk=13)
11
+ episode14 = Episode.objects.get(pk=14)
12
+ episode20 = Episode.objects.get(pk=20)
13
+
14
+ episode13_levels = Level.objects.filter(
15
+ default=True, name__in=range(1026, 1041)
16
+ )
17
+ episode14_levels = Level.objects.filter(
18
+ default=True, name__in=range(1014, 1026)
19
+ )
20
+
21
+ episode13_levels.update(episode=episode14)
22
+ episode14_levels.update(episode=episode13)
23
+
24
+ old_episode13_name = episode13.name
25
+ old_episode13_lesson_plan_link = episode13.lesson_plan_link
26
+ old_episode13_slides_link = episode13.slides_link
27
+ old_episode13_worksheet_link = episode13.worksheet_link
28
+ old_episode13_video_link = episode13.video_link
29
+ old_episode14_name = episode14.name
30
+ old_episode14_lesson_plan_link = episode14.lesson_plan_link
31
+ old_episode14_slides_link = episode14.slides_link
32
+ old_episode14_worksheet_link = episode14.worksheet_link
33
+ old_episode14_video_link = episode14.video_link
34
+
35
+ episode13.name = old_episode14_name
36
+ episode13.lesson_plan_link = old_episode14_lesson_plan_link
37
+ episode13.slides_link = old_episode14_slides_link
38
+ episode13.worksheet_link = old_episode14_worksheet_link
39
+ episode13.video_link = old_episode14_video_link
40
+ episode14.name = old_episode13_name
41
+ episode14.lesson_plan_link = old_episode13_lesson_plan_link
42
+ episode14.slides_link = old_episode13_slides_link
43
+ episode14.worksheet_link = old_episode13_worksheet_link
44
+ episode14.video_link = old_episode13_video_link
45
+
46
+ episode12.next_episode = episode13
47
+ episode13.next_episode = episode14
48
+ episode14.next_episode = episode20
49
+
50
+ episode12.save()
51
+ episode13.save()
52
+ episode14.save()
53
+
54
+ episode12_last_level = episode12.level_set.first()
55
+ episode13_last_level = episode13.level_set.last()
56
+ episode14_last_level = episode14.level_set.last()
57
+
58
+ episode12_last_level.next_level = episode13.level_set.all()[0]
59
+ episode13_last_level.next_level = episode14.level_set.all()[0]
60
+ episode14_last_level.next_level = None
61
+
62
+ episode12_last_level.save()
63
+ episode13_last_level.save()
64
+ episode14_last_level.save()
65
+
66
+
67
+ def unswap_episodes_13_14(apps: Apps, *args):
68
+ Episode = apps.get_model("game", "Episode")
69
+ Level = apps.get_model("game", "Level")
70
+
71
+ episode12 = Episode.objects.get(pk=12)
72
+ episode13 = Episode.objects.get(pk=13)
73
+ episode14 = Episode.objects.get(pk=14)
74
+ episode20 = Episode.objects.get(pk=20)
75
+
76
+ episode13_levels = Level.objects.filter(
77
+ default=True, name__in=range(1014, 1026)
78
+ )
79
+ episode14_levels = Level.objects.filter(
80
+ default=True, name__in=range(1026, 1041)
81
+ )
82
+
83
+ episode13_levels.update(episode=episode14)
84
+ episode14_levels.update(episode=episode13)
85
+
86
+ old_episode13_name = episode13.name
87
+ old_episode13_lesson_plan_link = episode13.lesson_plan_link
88
+ old_episode13_slides_link = episode13.slides_link
89
+ old_episode13_worksheet_link = episode13.worksheet_link
90
+ old_episode13_video_link = episode13.video_link
91
+ old_episode14_name = episode14.name
92
+ old_episode14_lesson_plan_link = episode14.lesson_plan_link
93
+ old_episode14_slides_link = episode14.slides_link
94
+ old_episode14_worksheet_link = episode14.worksheet_link
95
+ old_episode14_video_link = episode14.video_link
96
+
97
+ episode13.name = old_episode14_name
98
+ episode13.lesson_plan_link = old_episode14_lesson_plan_link
99
+ episode13.slides_link = old_episode14_slides_link
100
+ episode13.worksheet_link = old_episode14_worksheet_link
101
+ episode13.video_link = old_episode14_video_link
102
+ episode14.name = old_episode13_name
103
+ episode14.lesson_plan_link = old_episode13_lesson_plan_link
104
+ episode14.slides_link = old_episode13_slides_link
105
+ episode14.worksheet_link = old_episode13_worksheet_link
106
+ episode14.video_link = old_episode13_video_link
107
+
108
+ episode12.next_episode = episode14
109
+ episode14.next_episode = episode13
110
+ episode13.next_episode = episode20
111
+
112
+ episode12.save()
113
+ episode13.save()
114
+ episode14.save()
115
+
116
+ episode12_last_level = episode12.level_set.first()
117
+ episode13_last_level = episode13.level_set.last()
118
+ episode14_last_level = episode14.level_set.last()
119
+
120
+ episode12_last_level.next_level = episode14.level_set.all()[0]
121
+ episode14_last_level.next_level = episode13.level_set.all()[0]
122
+ episode13_last_level.next_level = None
123
+
124
+ episode12_last_level.save()
125
+ episode13_last_level.save()
126
+ episode14_last_level.save()
127
+
128
+
129
+ class Migration(migrations.Migration):
130
+ dependencies = [("game", "0101_rename_episodes")]
131
+
132
+ operations = [
133
+ migrations.RunPython(
134
+ code=swap_episodes_13_14, reverse_code=unswap_episodes_13_14
135
+ )
136
+ ]
@@ -0,0 +1,26 @@
1
+ from django.apps.registry import Apps
2
+ from django.db import migrations
3
+
4
+
5
+ def update_level_model_solution(apps: Apps, *args):
6
+ Level = apps.get_model("game", "Level")
7
+ level43 = Level.objects.get(name="1015", default=True)
8
+ level43.model_solution = "[11,12]"
9
+ level43.save()
10
+
11
+
12
+ def revert_level_model_solution(apps: Apps, *args):
13
+ Level = apps.get_model("game", "Level")
14
+ level43 = Level.objects.get(name="1015", default=True)
15
+ level43.model_solution = "[11]"
16
+ level43.save()
17
+
18
+
19
+ class Migration(migrations.Migration):
20
+ dependencies = [("game", "0102_reoder_episodes_13_14")]
21
+ operations = [
22
+ migrations.RunPython(
23
+ update_level_model_solution,
24
+ reverse_code=revert_level_model_solution,
25
+ )
26
+ ]
@@ -0,0 +1,17 @@
1
+ # Generated by Django 3.2.25 on 2024-10-15 07:54
2
+
3
+ from django.db import migrations
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('game', '0103_level_1015_solution'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.RemoveField(
14
+ model_name='level',
15
+ name='direct_drive',
16
+ ),
17
+ ]
@@ -0,0 +1,18 @@
1
+ from django.apps.registry import Apps
2
+ from django.db import migrations
3
+
4
+
5
+ def delete_invalid_attempts(apps: Apps, *args):
6
+ Attempt = apps.get_model("game", "Attempt")
7
+
8
+ Attempt.objects.filter(start_time__isnull=True).delete()
9
+
10
+
11
+ class Migration(migrations.Migration):
12
+ dependencies = [("game", "0104_remove_level_direct_drive")]
13
+ operations = [
14
+ migrations.RunPython(
15
+ delete_invalid_attempts,
16
+ reverse_code=migrations.RunPython.noop,
17
+ )
18
+ ]
@@ -0,0 +1,48 @@
1
+ # Generated by Django 3.2.25 on 2024-11-01 13:12
2
+
3
+ from django.db import migrations
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('game', '0105_delete_invalid_attempts'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.RenameField(
14
+ model_name='episode',
15
+ old_name='r_blocklyEnabled',
16
+ new_name='r_blockly_enabled',
17
+ ),
18
+ migrations.RenameField(
19
+ model_name='episode',
20
+ old_name='r_pythonEnabled',
21
+ new_name='r_python_enabled',
22
+ ),
23
+ migrations.RenameField(
24
+ model_name='episode',
25
+ old_name='r_trafficLights',
26
+ new_name='r_traffic_lights',
27
+ ),
28
+ migrations.RenameField(
29
+ model_name='level',
30
+ old_name='blocklyEnabled',
31
+ new_name='blockly_enabled',
32
+ ),
33
+ migrations.RenameField(
34
+ model_name='level',
35
+ old_name='pythonEnabled',
36
+ new_name='python_enabled',
37
+ ),
38
+ migrations.RenameField(
39
+ model_name='level',
40
+ old_name='pythonViewEnabled',
41
+ new_name='python_view_enabled',
42
+ ),
43
+ migrations.RenameField(
44
+ model_name='leveldecor',
45
+ old_name='decorName',
46
+ new_name='decor_name',
47
+ ),
48
+ ]
@@ -0,0 +1,18 @@
1
+ # Generated by Django 4.2.16 on 2024-11-27 15:43
2
+
3
+ from django.db import migrations
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("game", "0106_fields_to_snake_case"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.RenameField(
14
+ model_name="episode",
15
+ old_name="worksheet_link",
16
+ new_name="student_worksheet_link",
17
+ ),
18
+ ]
@@ -0,0 +1,18 @@
1
+ # Generated by Django 4.2.16 on 2024-11-27 15:44
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("game", "0107_rename_worksheet_link_episode_student_worksheet_link"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddField(
14
+ model_name="episode",
15
+ name="indy_worksheet_link",
16
+ field=models.CharField(blank=True, default=None, max_length=500, null=True),
17
+ ),
18
+ ]