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,99 @@
1
+ from django.apps.registry import Apps
2
+ from django.db import migrations
3
+
4
+
5
+ def create_episodes_23_and_24(apps: Apps, *args):
6
+ Episode = apps.get_model("game", "Episode")
7
+
8
+ episode_23 = Episode.objects.create(
9
+ pk=23,
10
+ name="2D Lists",
11
+ student_worksheet_link="https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-12-2d-lists",
12
+ indy_worksheet_link="https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-12-2d-lists",
13
+ video_link="https://www.youtube.com/watch?v=MBU49ivZk6w",
14
+ lesson_plan_link="https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/EMEzsyyl4uRclyA9LDGN/python-12-2d-lists",
15
+ slides_link="https://4077022412-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2F3Q4X7ZDk1TNej5c2e7LW%2FPython%2012%202D%20Lists.pptx?alt=media&token=847d9d69-4610-4c67-a649-0c6e0f88d372",
16
+ )
17
+
18
+ episode_24 = Episode.objects.create(
19
+ pk=24,
20
+ name="Procedures and Functions",
21
+ student_worksheet_link="https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-13-procedures-and-functions",
22
+ indy_worksheet_link="https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-13-procedures-and-functions",
23
+ video_link="https://www.youtube.com/watch?v=LJMfI7P3Dzk",
24
+ lesson_plan_link="https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/EMEzsyyl4uRclyA9LDGN/python-13-procedures-and-functions",
25
+ slides_link="https://4077022412-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2Fmr6FvFzY3LVuaGT1zd6d%2FPython%2013%20Procedures%20and%20Functions.pptx?alt=media&token=c5835e00-8d42-4567-8cf4-868b0f23dc0a",
26
+ )
27
+
28
+ episode_23.next_episode = episode_24
29
+ episode_23.save()
30
+
31
+ episode_16 = Episode.objects.get(pk=16)
32
+ episode_16.indy_worksheet_link = "https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-1-output-operators-and-data"
33
+ episode_16.save()
34
+
35
+ episode_17 = Episode.objects.get(pk=17)
36
+ episode_17.indy_worksheet_link = "https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-2-variables-input-and-casting"
37
+ episode_17.save()
38
+
39
+ episode_18 = Episode.objects.get(pk=18)
40
+ episode_18.indy_worksheet_link = "https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-3-selection"
41
+ episode_18.save()
42
+
43
+ episode_19 = Episode.objects.get(pk=19)
44
+ episode_19.indy_worksheet_link = "https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-4-complex-selection"
45
+ episode_19.save()
46
+
47
+ episode_12 = Episode.objects.get(pk=12)
48
+ episode_12.indy_worksheet_link = "https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-5-iteration-part-1"
49
+ episode_12.save()
50
+
51
+ episode_13 = Episode.objects.get(pk=13)
52
+ episode_13.indy_worksheet_link = "https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-7-selection-in-a-loop"
53
+ episode_13.save()
54
+
55
+ episode_14 = Episode.objects.get(pk=14)
56
+ episode_14.indy_worksheet_link = "https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-8-indeterminate-loops"
57
+ episode_14.save()
58
+
59
+ episode_20 = Episode.objects.get(pk=20)
60
+ episode_20.indy_worksheet_link = "https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-9-string-manipulation"
61
+ episode_20.save()
62
+
63
+ episode_21 = Episode.objects.get(pk=21)
64
+ episode_21.indy_worksheet_link = "https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-10-1d-lists"
65
+ episode_21.save()
66
+
67
+ episode_15 = Episode.objects.get(pk=15)
68
+ episode_15.next_episode = episode_23
69
+ episode_15.indy_worksheet_link = "https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-11-using-for-loops"
70
+ episode_15.save()
71
+
72
+
73
+ def delete_episodes_23_and_24(apps: Apps, *args):
74
+ Episode = apps.get_model("game", "Episode")
75
+
76
+ episode_15 = Episode.objects.get(pk=15)
77
+ episode_15.next_episode = None
78
+ episode_15.indy_worksheet_link = None
79
+ episode_15.save()
80
+
81
+ Episode.objects.filter(pk__in=[
82
+ 16, 17, 18, 19, 12, 13, 14, 20, 21
83
+ ]).update(indy_worksheet_link=None)
84
+
85
+ Episode.objects.filter(pk__in=[23, 24]).delete()
86
+
87
+
88
+ class Migration(migrations.Migration):
89
+
90
+ dependencies = [
91
+ ("game", "0108_episode_indy_worksheet_link"),
92
+ ]
93
+
94
+ operations = [
95
+ migrations.RunPython(
96
+ code=create_episodes_23_and_24,
97
+ reverse_code=delete_episodes_23_and_24,
98
+ )
99
+ ]
@@ -0,0 +1,100 @@
1
+ # Generated by Django 4.2.16 on 2024-12-02 15:17
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", "0109_create_episodes_23_and_24"),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.RemoveField(
15
+ model_name="episode",
16
+ name="indy_worksheet_link",
17
+ ),
18
+ migrations.RemoveField(
19
+ model_name="episode",
20
+ name="lesson_plan_link",
21
+ ),
22
+ migrations.RemoveField(
23
+ model_name="episode",
24
+ name="slides_link",
25
+ ),
26
+ migrations.RemoveField(
27
+ model_name="episode",
28
+ name="student_worksheet_link",
29
+ ),
30
+ migrations.RemoveField(
31
+ model_name="episode",
32
+ name="video_link",
33
+ ),
34
+ migrations.CreateModel(
35
+ name="Worksheet",
36
+ fields=[
37
+ (
38
+ "id",
39
+ models.AutoField(
40
+ auto_created=True,
41
+ primary_key=True,
42
+ serialize=False,
43
+ verbose_name="ID",
44
+ ),
45
+ ),
46
+ (
47
+ "lesson_plan_link",
48
+ models.CharField(
49
+ blank=True, default=None, max_length=500, null=True
50
+ ),
51
+ ),
52
+ (
53
+ "slides_link",
54
+ models.CharField(
55
+ blank=True, default=None, max_length=500, null=True
56
+ ),
57
+ ),
58
+ (
59
+ "student_worksheet_link",
60
+ models.CharField(
61
+ blank=True, default=None, max_length=500, null=True
62
+ ),
63
+ ),
64
+ (
65
+ "indy_worksheet_link",
66
+ models.CharField(
67
+ blank=True, default=None, max_length=500, null=True
68
+ ),
69
+ ),
70
+ (
71
+ "video_link",
72
+ models.CharField(
73
+ blank=True, default=None, max_length=500, null=True
74
+ ),
75
+ ),
76
+ (
77
+ "before_level",
78
+ models.OneToOneField(
79
+ blank=True,
80
+ default=None,
81
+ null=True,
82
+ on_delete=django.db.models.deletion.PROTECT,
83
+ related_name="after_worksheet",
84
+ to="game.level",
85
+ ),
86
+ ),
87
+ (
88
+ "episode",
89
+ models.ForeignKey(
90
+ blank=True,
91
+ default=None,
92
+ null=True,
93
+ on_delete=django.db.models.deletion.PROTECT,
94
+ related_name="worksheets",
95
+ to="game.episode",
96
+ ),
97
+ ),
98
+ ],
99
+ ),
100
+ ]
@@ -0,0 +1,149 @@
1
+ from django.apps.registry import Apps
2
+ from django.db import migrations
3
+
4
+
5
+ def create_worksheets(apps: Apps, *args):
6
+ Episode = apps.get_model("game", "Episode")
7
+ Worksheet = apps.get_model("game", "Worksheet")
8
+ Level = apps.get_model("game", "Level")
9
+
10
+ Worksheet.objects.bulk_create(
11
+ [
12
+ Worksheet(
13
+ episode=Episode.objects.get(pk=16),
14
+ before_level=None,
15
+ lesson_plan_link="https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/DGiFT28ihVJK7ghZQHqu/python-1-output-operators-and-data",
16
+ 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",
17
+ student_worksheet_link="https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-1-output-operators-and-data",
18
+ indy_worksheet_link="https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-1-output-operators-and-data",
19
+ video_link="https://youtu.be/ve0RTsLGli0",
20
+ ),
21
+ Worksheet(
22
+ episode=Episode.objects.get(pk=17),
23
+ before_level=None,
24
+ lesson_plan_link="https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/DGiFT28ihVJK7ghZQHqu/python-2-variables-input-and-casting",
25
+ 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",
26
+ student_worksheet_link="https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-2-variables-input-and-casting",
27
+ indy_worksheet_link="https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-2-variables-input-and-casting",
28
+ video_link="https://www.youtube.com/watch?v=H8askW-zd3I",
29
+ ),
30
+ Worksheet(
31
+ episode=Episode.objects.get(pk=18),
32
+ before_level=None,
33
+ lesson_plan_link="https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/DGiFT28ihVJK7ghZQHqu/python-3-selection",
34
+ 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",
35
+ student_worksheet_link="https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-3-selection",
36
+ indy_worksheet_link="https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-3-selection",
37
+ video_link="https://www.youtube.com/watch?v=3XiQ97kP7H8",
38
+ ),
39
+ Worksheet(
40
+ episode=Episode.objects.get(pk=19),
41
+ before_level=None,
42
+ lesson_plan_link="https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/DGiFT28ihVJK7ghZQHqu/python-4-complex-selection",
43
+ 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",
44
+ student_worksheet_link="https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-4-complex-selection",
45
+ indy_worksheet_link="https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-4-complex-selection",
46
+ video_link="https://youtu.be/QOe5G-ZvWoc",
47
+ ),
48
+ Worksheet(
49
+ episode=Episode.objects.get(pk=12),
50
+ before_level=Level.objects.get(default=True, name="1001"),
51
+ lesson_plan_link="https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/DGiFT28ihVJK7ghZQHqu/python-5-iteration-part-1",
52
+ 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",
53
+ student_worksheet_link="https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-5-iteration-part-1",
54
+ indy_worksheet_link="https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-5-iteration-part-1",
55
+ video_link="https://youtu.be/nJm3cWSkoi0",
56
+ ),
57
+ Worksheet(
58
+ episode=Episode.objects.get(pk=12),
59
+ before_level=None,
60
+ lesson_plan_link="https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/DGiFT28ihVJK7ghZQHqu/python-6-iteration-part-2",
61
+ slides_link="https://4077022412-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2FcEO90C76g4N17ss2K5PN%2FPython%206%20-%20Iteration%202.pptx?alt=media&token=df237a62-21ad-44a8-a4fe-bc9eed24092b",
62
+ student_worksheet_link="https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-6-iteration-part-2",
63
+ indy_worksheet_link="https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-6-iteration-part-2",
64
+ video_link="https://youtu.be/kf-EavpnBNg",
65
+ ),
66
+ Worksheet(
67
+ episode=Episode.objects.get(pk=13),
68
+ before_level=Level.objects.get(default=True, name="1014"),
69
+ lesson_plan_link="https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/DGiFT28ihVJK7ghZQHqu/python-7-selection-in-a-loop",
70
+ 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",
71
+ student_worksheet_link="https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-7-selection-in-a-loop",
72
+ indy_worksheet_link="https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-7-selection-in-a-loop",
73
+ video_link="https://www.youtube.com/watch?v=WV_PLCcohMg",
74
+ ),
75
+ Worksheet(
76
+ episode=Episode.objects.get(pk=14),
77
+ before_level=Level.objects.get(default=True, name="1026"),
78
+ lesson_plan_link="https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/DGiFT28ihVJK7ghZQHqu/python-8-indeterminate-loops",
79
+ 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",
80
+ student_worksheet_link="https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-8-indeterminate-loops",
81
+ indy_worksheet_link="https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-8-indeterminate-loops",
82
+ video_link="https://www.youtube.com/watch?v=XgMGI8UzMDM",
83
+ ),
84
+ Worksheet(
85
+ episode=Episode.objects.get(pk=20),
86
+ before_level=None,
87
+ lesson_plan_link="https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/DGiFT28ihVJK7ghZQHqu/python-9-string-manipulation",
88
+ 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",
89
+ student_worksheet_link="https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-9-string-manipulation",
90
+ indy_worksheet_link="https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-9-string-manipulation",
91
+ video_link="https://www.youtube.com/watch?v=E4AMg57_eoI",
92
+ ),
93
+ Worksheet(
94
+ episode=Episode.objects.get(pk=21),
95
+ before_level=None,
96
+ lesson_plan_link="https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/DGiFT28ihVJK7ghZQHqu/python-10-1d-lists",
97
+ 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",
98
+ student_worksheet_link="https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-10-1d-lists",
99
+ indy_worksheet_link="https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-10-1d-lists",
100
+ video_link="https://www.youtube.com/watch?v=Kb_-7IqWV0E",
101
+ ),
102
+ Worksheet(
103
+ episode=Episode.objects.get(pk=15),
104
+ before_level=Level.objects.get(default=True, name="1041"),
105
+ lesson_plan_link="https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/DGiFT28ihVJK7ghZQHqu/python-11-using-for-loops",
106
+ 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",
107
+ student_worksheet_link="https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-11-for-loops",
108
+ indy_worksheet_link="https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-11-using-for-loops",
109
+ video_link="https://www.youtube.com/watch?v=jNT_gQx9-k8",
110
+ ),
111
+ Worksheet(
112
+ episode=Episode.objects.get(pk=23),
113
+ before_level=None,
114
+ lesson_plan_link="https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/EMEzsyyl4uRclyA9LDGN/python-12-2d-lists",
115
+ slides_link="https://4077022412-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2F3Q4X7ZDk1TNej5c2e7LW%2FPython%2012%202D%20Lists.pptx?alt=media&token=847d9d69-4610-4c67-a649-0c6e0f88d372",
116
+ student_worksheet_link="https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-12-2d-lists",
117
+ indy_worksheet_link="https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-12-2d-lists",
118
+ video_link="https://www.youtube.com/watch?v=MBU49ivZk6w",
119
+ ),
120
+ Worksheet(
121
+ episode=Episode.objects.get(pk=24),
122
+ before_level=None,
123
+ lesson_plan_link="https://code-for-life.gitbook.io/python-lessons-with-raspberry-pi-ide/EMEzsyyl4uRclyA9LDGN/python-13-procedures-and-functions",
124
+ slides_link="https://4077022412-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2Fmr6FvFzY3LVuaGT1zd6d%2FPython%2013%20Procedures%20and%20Functions.pptx?alt=media&token=c5835e00-8d42-4567-8cf4-868b0f23dc0a",
125
+ student_worksheet_link="https://code-for-life.gitbook.io/student-resources/python-den-student-resources/worksheet-13-procedures-and-functions",
126
+ indy_worksheet_link="https://code-for-life.gitbook.io/independent-student-resources/python-den-resources-beta/session-13-procedures-and-functions",
127
+ video_link="https://www.youtube.com/watch?v=LJMfI7P3Dzk",
128
+ ),
129
+ ]
130
+ )
131
+
132
+
133
+ def delete_worksheets(apps: Apps, *args):
134
+ Worksheet = apps.get_model("game", "Worksheet")
135
+ Worksheet.objects.all().delete()
136
+
137
+
138
+ class Migration(migrations.Migration):
139
+
140
+ dependencies = [
141
+ ("game", "0110_remove_episode_indy_worksheet_link_and_more"),
142
+ ]
143
+
144
+ operations = [
145
+ migrations.RunPython(
146
+ code=create_worksheets,
147
+ reverse_code=delete_worksheets,
148
+ )
149
+ ]
@@ -0,0 +1,21 @@
1
+ # Generated by Django 4.2.16 on 2024-12-03 11:01
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("common", "0055_alter_schoolteacherinvitation_token"),
10
+ ("game", "0111_create_worksheets"),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.AddField(
15
+ model_name="worksheet",
16
+ name="locked_classes",
17
+ field=models.ManyToManyField(
18
+ blank=True, related_name="locked_worksheets", to="common.class"
19
+ ),
20
+ ),
21
+ ]
@@ -0,0 +1,18 @@
1
+ # Generated by Django 4.2.18 on 2025-02-10 20:18
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("game", "0112_worksheet_locked_classes"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddField(
14
+ model_name="level",
15
+ name="needs_approval",
16
+ field=models.BooleanField(default=True),
17
+ ),
18
+ ]
@@ -0,0 +1,31 @@
1
+ from django.apps.registry import Apps
2
+ from django.db import migrations
3
+ from django.db.models import Q
4
+
5
+
6
+ def mark_default_and_non_student_levels_as_not_needing_approval(apps: Apps, *args):
7
+ Level = apps.get_model("game", "Level")
8
+
9
+ Level.objects.filter(Q(default=True) | Q(owner__user__email__isnull=False)).update(
10
+ needs_approval=False
11
+ )
12
+
13
+
14
+ def unmark_default_and_non_student_levels_as_not_needing_approval(apps: Apps, *args):
15
+ Level = apps.get_model("game", "Level")
16
+
17
+ Level.objects.filter(Q(default=True) | Q(owner__user__email__isnull=False)).update(
18
+ needs_approval=True
19
+ )
20
+
21
+
22
+ class Migration(migrations.Migration):
23
+
24
+ dependencies = [("game", "0113_level_needs_approval")]
25
+
26
+ operations = [
27
+ migrations.RunPython(
28
+ code=mark_default_and_non_student_levels_as_not_needing_approval,
29
+ reverse_code=unmark_default_and_non_student_levels_as_not_needing_approval,
30
+ )
31
+ ]
@@ -0,0 +1,22 @@
1
+ # Generated by Django 4.2.18 on 2025-02-14 15:40
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ("game", "0114_default_and_non_student_levels_no_approval"),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AddConstraint(
14
+ model_name="level",
15
+ constraint=models.CheckConstraint(
16
+ check=models.Q(
17
+ ("default", True), ("needs_approval", True), _negated=True
18
+ ),
19
+ name="level__default_does_not_need_approval",
20
+ ),
21
+ ),
22
+ ]
@@ -0,0 +1,68 @@
1
+ from django.apps.registry import Apps
2
+ from django.db import migrations
3
+
4
+
5
+ def update_video_links_to_gitbook(apps: Apps, *args):
6
+ Worksheet = apps.get_model("game", "Worksheet")
7
+
8
+ gitbook_links = {
9
+ 1: "https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2FDK3lKfWsWXseNCfGjvbW%2FPython%20-%201.mp4?alt=media",
10
+ 2: "https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2FSm6U98LfPiX29BHxiV6K%2FPython%20Den%202_%20Variables%2C%20Input%20and%20Casting.mp4?alt=media",
11
+ 3: "https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2FBOgSQVurnqF8wAvujZfU%2FPython%20Den%20Session%203_%20Selection.mp4?alt=media",
12
+ 4: "https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2FbCvmsaMKoSB1YnWpY6Q0%2FPython%20-%204.mp4?alt=media",
13
+ 5: "https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2FJ316sUFw7gDae6DqN6ic%2FPython%20Den%20Session%205%20-%20Iteration%2C%20Part%201.mp4?alt=media",
14
+ 6: "https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2FAejhabL6uQNcH267vHVP%2FPython%20Den%20Session%206_%20Iteration%2C%20part%202.mp4?alt=media",
15
+ 7: "https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2FtOt5a50oebdFciVmzACB%2FPython%20Den%20Session%207_%20Selection%20in%20a%20Loop.mp4?alt=media",
16
+ 8: "https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2F8p5qyWb2trqu4ar5LKP8%2FPython%20Den%20Session%208_%20Indeterminate%20Loops.mp4?alt=media",
17
+ 9: "https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2FRhMHYNbPaR4cdmFxQHSJ%2FPython%20Den%20Session%209_%20String%20Manipulation.mp4?alt=media",
18
+ 10: "https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2F31nxEQMiyUex576uO1QV%2FPython%20Den%20Session%2010_%201D%20Lists.mp4?alt=media",
19
+ 11: "https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2FcwLKAhjeFxoZwxrc4KiY%2FPython%20Den%20Session%2011_%20Using%20for%20loops.mp4?alt=media",
20
+ 12: "https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2F6FoQVGJyqMmiZxxg3pQQ%2FPython%20Den%20Session%2012_%202D%20Lists.mp4?alt=media",
21
+ 13: "https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FwAuC4Q5WQz4ea2O2b2JP%2Fuploads%2Fs0V186tQxn3G3fmRAP9D%2FPython%20Den%20Session%2013_%20Procedures%20and%20Functions.mp4?alt=media",
22
+ }
23
+
24
+ worksheets = Worksheet.objects.all()
25
+
26
+ for worksheet in worksheets:
27
+ worksheet.video_link = gitbook_links[worksheet.id]
28
+ worksheet.save()
29
+
30
+
31
+ def update_video_links_to_youtube(apps: Apps, *args):
32
+ Worksheet = apps.get_model("game", "Worksheet")
33
+
34
+ youtube_links = {
35
+ 1: "https://www.youtube.com/watch?v=PiSxeThHztY",
36
+ 2: "https://www.youtube.com/watch?v=NkShv_bSB3I",
37
+ 3: "https://www.youtube.com/watch?v=jQ7RceRVapo",
38
+ 4: "https://www.youtube.com/watch?v=yMu_0-ryf_s",
39
+ 5: "https://www.youtube.com/watch?v=ihFg81V9aNE",
40
+ 6: "https://www.youtube.com/watch?v=Xhibd1JxPrU",
41
+ 7: "https://www.youtube.com/watch?v=WV_PLCcohMg",
42
+ 8: "https://www.youtube.com/watch?v=RkWu2wV8Bt0",
43
+ 9: "https://www.youtube.com/watch?v=E4AMg57_eoI",
44
+ 10: "https://www.youtube.com/watch?v=Kb_-7IqWV0E",
45
+ 11: "https://www.youtube.com/watch?v=jNT_gQx9-k8",
46
+ 12: "https://www.youtube.com/watch?v=MBU49ivZk6w",
47
+ 13: "https://www.youtube.com/watch?v=LJMfI7P3Dzk",
48
+ }
49
+
50
+ worksheets = Worksheet.objects.all()
51
+
52
+ for worksheet in worksheets:
53
+ worksheet.video_link = youtube_links[worksheet.id]
54
+ worksheet.save()
55
+
56
+
57
+ class Migration(migrations.Migration):
58
+
59
+ dependencies = [
60
+ ("game", "0115_level_level__default_does_not_need_approval"),
61
+ ]
62
+
63
+ operations = [
64
+ migrations.RunPython(
65
+ code=update_video_links_to_gitbook,
66
+ reverse_code=update_video_links_to_youtube,
67
+ )
68
+ ]
@@ -0,0 +1,61 @@
1
+ from django.apps.registry import Apps
2
+ from django.db import migrations
3
+
4
+ new_model_solutions_per_level = {
5
+ 34: "[6]",
6
+ 35: "[8]",
7
+ 36: "[8]",
8
+ 37: "[8]",
9
+ 40: "[6]",
10
+ 41: "[8]",
11
+ 44: "[6]",
12
+ 45: "[6]",
13
+ 46: "[8]",
14
+ 48: "[14]",
15
+ 49: "[10]",
16
+ }
17
+
18
+ old_model_solutions_per_level = {
19
+ 34: "[8,7,6]",
20
+ 35: "[11,9,8]",
21
+ 36: "[11,9,8]",
22
+ 37: "[11,9,8]",
23
+ 40: "[6,7]",
24
+ 41: "[8,9]",
25
+ 44: "[5,6]",
26
+ 45: "[6,7]",
27
+ 46: "[8,9]",
28
+ 48: "[14,15]",
29
+ 49: "[10,11,12,13,17]",
30
+ }
31
+
32
+
33
+ def update_model_solutions(apps, model_solutions_per_level):
34
+ Level = apps.get_model("game", "Level")
35
+
36
+ for level_id, model_solution in model_solutions_per_level.items():
37
+ level = Level.objects.get(pk=level_id)
38
+ level.model_solution = model_solution
39
+ level.save()
40
+
41
+
42
+ def update_solutions_to_if_else(apps: Apps, *args):
43
+ update_model_solutions(apps, new_model_solutions_per_level)
44
+
45
+
46
+ def revert_to_old_solutions(apps: Apps, *args):
47
+ update_model_solutions(apps, old_model_solutions_per_level)
48
+
49
+
50
+ class Migration(migrations.Migration):
51
+
52
+ dependencies = [
53
+ ("game", "0116_update_worksheet_video_links"),
54
+ ]
55
+
56
+ operations = [
57
+ migrations.RunPython(
58
+ code=update_solutions_to_if_else,
59
+ reverse_code=revert_to_old_solutions,
60
+ )
61
+ ]