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
@@ -351,13 +351,13 @@
351
351
  cursor: pointer;
352
352
  }
353
353
 
354
- #myModal:not(:target) {
354
+ #myModal {
355
355
  opacity: 0;
356
356
  visibility: hidden;
357
357
  transition: opacity 0.4s ease, visibility 0.4s ease-in-out;
358
358
  }
359
359
 
360
- #myModal:target {
360
+ #myModal.show {
361
361
  opacity: 1;
362
362
  visibility: visible;
363
363
  transition: opacity 0.4s ease, visibility 0.4s ease-in-out;
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -3,7 +3,25 @@
3
3
  {% load i18n %}
4
4
  {% load app_tags %}
5
5
 
6
- {% block title %}Code for Life - Rapid Router{% endblock %}
6
+ {% block scripts %}
7
+ {{block.super}}
8
+ <script defer id="data">
9
+ var PATH = {{request.path}}
10
+ </script>
11
+
12
+ <script type='text/javascript' src="{% static 'django_reverse_js/js/reverse.js' %}"></script>
13
+ <script type='text/javascript' src="{% static 'game/js/foundation/vendor/js.cookie.min.js' %}"></script>
14
+ <script type='text/javascript' src="{% url 'rapid-router/javascript-catalog' %}"></script>
15
+ <script type='text/javascript' src="{% static 'game/js/jquery.touchy.min.js' %}"></script>
16
+ {% endblock %}
17
+
18
+ {% block title %}
19
+ {% if "rapidrouter" in request.path %}
20
+ Code for Life - Rapid Router
21
+ {% else %}
22
+ Code for Life - Python Den
23
+ {% endif %}
24
+ {% endblock %}
7
25
 
8
26
  {% block head %}
9
27
  {% include 'game/crowdin.html' %}
@@ -44,20 +62,30 @@
44
62
  {% endif %}
45
63
 
46
64
  {% block nav_ocargo_levels %}
47
- <a class="button button--secondary button--secondary--light" href="{% url 'levels' %}">{% trans "Levels" %}</a>
65
+ {% if "/pythonden/" in request.path %}
66
+ <a class="button button--secondary button--secondary--light" href="{% url 'python_levels' %}">{% trans "Levels" %}</a>
67
+ {% else %}
68
+ <a class="button button--secondary button--secondary--light" href="{% url 'levels' %}">{% trans "Levels" %}</a>
69
+ {% endif %}
48
70
  {% endblock nav_ocargo_levels %}
49
71
 
50
- {% block nav_ocargo_create %}
51
- <a class="button button--secondary button--secondary--light" href="{% url 'level_editor' %}">{% trans "Create" %}</a>
52
- {% endblock nav_ocargo_create %}
72
+ {% if "/pythonden/" not in request.path %}
73
+ {% block nav_ocargo_create %}
74
+ <a class="button button--secondary button--secondary--light" href="{% url 'level_editor' %}">{% trans "Create" %}</a>
75
+ {% endblock nav_ocargo_create %}
76
+ {% endif %}
53
77
 
54
78
  {% if user|is_logged_in_as_school_user %}
55
79
  {% block nav_ocargo_scoreboard %}
80
+ {% if "/pythonden/" in request.path %}
81
+ <a class="button button--secondary button--secondary--light" href="{% url 'python_scoreboard' %}">{% trans "Scoreboard" %}</a>
82
+ {% else %}
56
83
  <a class="button button--secondary button--secondary--light" href="{% url 'scoreboard' %}">{% trans "Scoreboard" %}</a>
84
+ {% endif %}
57
85
  {% endblock nav_ocargo_scoreboard %}
58
86
  {% endif %}
59
87
 
60
- {% if user|is_logged_in_as_teacher %}
88
+ {% if user|is_logged_in_as_teacher and "/pythonden/" not in request.path %}
61
89
  {% block nav_ocargo_moderate %}
62
90
  <a class="button button--secondary button--secondary--light" href="{% url 'level_moderation' %}">{% trans "Moderate" %}</a>
63
91
  {% endblock nav_ocargo_moderate %}
@@ -67,11 +95,3 @@
67
95
  {% endblock subNav %}
68
96
 
69
97
  {% block content %}{% endblock %}
70
-
71
- {% block scripts %}
72
- {{block.super}}
73
- <script type='text/javascript' src="{% static 'game/js/foundation/vendor/js.cookie.min.js' %}"></script>
74
- <script type='text/javascript' src="{% static 'game/js/js-reverse.js' %}"></script>
75
- <script type='text/javascript' src="{% url 'rapid-router/javascript-catalog' %}"></script>
76
- <script type='text/javascript' src="{% static 'game/js/jquery.touchy.min.js' %}"></script>
77
- {% endblock %}
@@ -8,14 +8,20 @@
8
8
  {% endblock head %}
9
9
 
10
10
  {% block css %}
11
- <link href="{% static 'game.css' %}" type="text/css" rel="stylesheet">
12
- <link href="{% static 'popup.css' %}" type="text/css" rel="stylesheet">
11
+ <link href="{% static 'game/css/gamestyles.css' %}" type="text/css" rel="stylesheet">
12
+ <link href="{% static 'portal/css/popup.css' %}" type="text/css" rel="stylesheet">
13
13
  <link href="{% static 'game/css/backgrounds.css' %}" rel="stylesheet" type="text/css">
14
14
  <link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500&display=swap" rel="stylesheet">
15
15
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
16
16
  {% endblock css %}
17
17
 
18
- {% block title %}Code for Life - Rapid Router{% endblock %}
18
+ {% block title %}
19
+ {% if "rapidrouter" in request.path %}
20
+ Code for Life - Rapid Router
21
+ {% else %}
22
+ Code for Life - Python Den
23
+ {% endif %}
24
+ {% endblock %}
19
25
 
20
26
  {% block topBar %}
21
27
  {% endblock topBar %}
@@ -48,7 +54,7 @@
48
54
  <span>Close</span>
49
55
  </button>
50
56
  </div>
51
- <a class="close-reveal-modal" id="close-modal" href="#">&#215;</a>
57
+ <a class="close-reveal-modal" id="close-modal" href="javascript:void(0);">&#215;</a>
52
58
  </div>
53
59
  </div>
54
60
  </div>
@@ -69,6 +75,6 @@
69
75
  <script type='text/javascript' src="{% static 'game/js/handlebars.runtime-v4.7.7.js' %}"></script>
70
76
  <script type='text/javascript' src="{% static 'game/js/templates.js' %}"></script>
71
77
  <script type='text/javascript' src="{% static 'game/js/button.js' %}"></script>
72
- <script type='text/javascript' src="{% static 'game/js/js-reverse.js' %}"></script>
78
+ <script type='text/javascript' src="{% static 'django_reverse_js/js/reverse.js' %}"></script>
73
79
  <script type='text/javascript' src="{% url 'rapid-router/javascript-catalog' %}"></script>
74
80
  {% endblock %}
@@ -7,15 +7,15 @@
7
7
 
8
8
  {% block scripts %}
9
9
  {{block.super}}
10
- <script defer id="data"
11
- data-path="{{level.path|trim}}"
12
- data-origin="{{level.origin|trim}}"
13
- data-destinations="{{level.destinations|trim}}"
14
- data-traffic-lights="{{level.traffic_lights|trim}}"
15
- data-cows="{{level.cows|trim}}"
16
- data-episode="{{level.episode.id|trim}}"
17
- data-level-id="{{level.id|default_if_none:''|trim}}"
18
- data-level-name="{{level.name|trim}}"
10
+ <script defer id="data"
11
+ data-path="{{level.path|trim}}"
12
+ data-origin="{{level.origin|trim}}"
13
+ data-destinations="{{level.destinations|trim}}"
14
+ data-traffic-lights="{{level.traffic_lights|trim}}"
15
+ data-cows="{{level.cows|trim}}"
16
+ data-episode="{{level.episode.id|trim}}"
17
+ data-level-id="{{level.id|default_if_none:''|trim}}"
18
+ data-level-name="{{level.name|trim}}"
19
19
  >
20
20
  var ANONYMOUS = {{level.anonymous|booltojs}}
21
21
  var PATH = $('#data').data('path')
@@ -35,8 +35,10 @@
35
35
  var MODEL_SOLUTION = {{model_solution|default:"[]"}}
36
36
  var DISABLE_ROUTE_SCORE = {{level.disable_route_score|booltojs}}
37
37
  var DISABLE_ALGORITHM_SCORE = {{level.disable_algorithm_score|booltojs}}
38
+ var SUBTITLE = "{{subtitle|escapejs}}"
38
39
  var LESSON = "{{lesson|escapejs}}"
39
40
  var HINT = "{{hint|escapejs}}"
41
+ var COMMANDS = "{{commands|escapejs}}"
40
42
  var DEFAULT_LEVEL = {{level.default|booltojs}}
41
43
  var FUEL_GAUGE = {{level.fuel_gauge|booltojs}}
42
44
  var CHARACTER_NAME = "{{character.name}}"
@@ -69,12 +71,11 @@
69
71
 
70
72
  BLOCKLY_XML += '</xml>'
71
73
  var MAX_FUEL = {{level.max_fuel}}
72
- var DIRECT_DRIVE = {{level.direct_drive|booltojs}}
73
74
  var NEXT_EPISODE = {% if level.episode.next_episode == None %}null{% else %}"{{level.episode.next_episode.id}}"{% endif %}
74
75
  var WORKSPACE = {% if workspace == None %}null{% else %}"{{workspace}}"{% endif %}
75
- var BLOCKLY_ENABLED = {{level.blocklyEnabled|booltojs}}
76
- var PYTHON_ENABLED = {{level.pythonEnabled|booltojs}}
77
- var PYTHON_VIEW_ENABLED = {{level.pythonViewEnabled|booltojs}}
76
+ var BLOCKLY_ENABLED = {{level.blockly_enabled|booltojs}}
77
+ var PYTHON_ENABLED = {{level.python_enabled|booltojs}}
78
+ var PYTHON_VIEW_ENABLED = {{level.python_view_enabled|booltojs}}
78
79
  var RETURN_URL = "{{return_url}}"
79
80
  var PYTHON_WORKSPACE = {% if python_workspace == None %}null{% else %}"{{python_workspace|linebreaksbr}}"{% endif %}
80
81
  </script>
@@ -150,18 +151,32 @@
150
151
  </div>
151
152
 
152
153
  <div id="wrapper" class="unselectable">
154
+ {% if level.python_view_enabled or level.python_enabled %}
155
+ <img src="{% static 'game/image/python_den_header.svg' %}" class="game-header">
156
+ {% endif %}
153
157
  <span id="game_page"></span>
154
158
 
155
159
  <div id="tabs" class='no-print bg--{{ level.difficulty }}'>
156
- <div id="blockly_tab" class="tab selectable {% if level.blocklyEnabled %}{% else %}hidden{% endif %}">
160
+
161
+ <div id="blockly_tab"
162
+ class="tab selectable {% if not level.blockly_enabled and not level.python_view_enabled %}hidden{% endif %}">
157
163
  <input type="radio" name="tabs" id="blockly_radio" checked>
158
164
  <label for="blockly_radio">
159
165
  <img src="{% static 'game/image/icons/blockly.svg' %}">
160
166
  <span>{% trans "Blockly" %}</span>
161
167
  </label>
162
168
  </div>
169
+
170
+ <div id="python_tab" class="tab selectable {% if not level.python_enabled %}hidden{% endif %}">
171
+ <input type="radio" name="tabs" id="python_radio">
172
+ <label for="python_radio">
173
+ <img src="{% static 'game/image/icons/python.svg' %}">
174
+ <span>{% trans "Python Den" %}</span>
175
+ </label>
176
+ </div>
177
+
163
178
  <div id="language_tab" class="tab">
164
- <select name="language_dropdown" class="tab selectable bg--{{level.difficulty}} {% if level.pythonEnabled %}hidden{% endif %}" id="language_dropdown" onchange="gameUpdateBlockLanguage(this.value)">
179
+ <select name="language_dropdown" class="tab selectable bg--{{level.difficulty}} {% if level.python_enabled %}hidden{% endif %}" id="language_dropdown" onchange="gameUpdateBlockLanguageAndCookie(this.value)">
165
180
  {% for language_code, language in available_language_dict.items %}
166
181
  <option id="language_dropdown_{{language_code}}" value="{{language_code}}">{{language}}</option>
167
182
  {% endfor %}
@@ -170,14 +185,6 @@
170
185
 
171
186
  <div class="tab_break"></div>
172
187
 
173
- <div id="python_tab" class="tab selectable {% if level.pythonEnabled %}{% else %}hidden{% endif %}">
174
- <input type="radio" name="tabs" id="python_radio">
175
- <label for="python_radio">
176
- <img src="{% static 'game/image/icons/python.svg' %}">
177
- <span>{% trans "Python" %}</span>
178
- </label>
179
- </div>
180
-
181
188
  <div id="clear_tab" class="tab">
182
189
  <input type="radio" name="tabs" id="clear_program_radio">
183
190
  <label for="clear_program_radio">
@@ -312,24 +319,24 @@
312
319
  <div id="blockly_pane" class="tab_pane">
313
320
  <div id="blockCountDiv"></div>
314
321
 
315
- <div id="blockly_holder" style='width: calc(100%); {% if level.pythonViewEnabled %} height: 50%; {% endif %}'></div>
322
+ <div id="blockly_holder" style='width: calc(100%); {% if level.python_view_enabled %} height: 50%; {% endif %}'></div>
316
323
 
317
- {% if level.pythonViewEnabled %}
324
+ {% if level.python_view_enabled %}
318
325
  <div id="pythonViewSlider" class="no-print"></div>
319
326
  {% endif %}
320
327
 
321
- <div id="pythonView_holder" {% if not level.pythonViewEnabled %} style="visibility: hidden" {% endif %}>
328
+ <div id="pythonView_holder" {% if not level.python_view_enabled %} style="visibility: hidden" {% endif %}>
322
329
  <p>{% trans "This is what your program would look like in Python:" %}</p>
323
330
  <textarea id="pythonView" cols="85" rows="25"></textarea>
324
331
  </div>
325
332
  </div>
326
333
 
327
334
  <div id="python_pane" class="tab_pane">
328
- <div id="pythonCode" {% if not level.pythonEnabled %} style="visibility: hidden" {% endif %}>
335
+ <div id="pythonCode" {% if not level.python_enabled %} style="visibility: hidden" {% endif %}>
329
336
  <div id="editor">
330
337
  <div class="description">
331
338
  <h3>{% trans "Python Program" %}
332
- {% if level.blocklyEnabled %}
339
+ {% if level.blockly_enabled %}
333
340
  <button class="navigation_button long_button" id="convert_from_blockly">
334
341
  <span>{% trans "Convert from Blockly" %}</span>
335
342
  </button>
@@ -475,16 +482,9 @@
475
482
 
476
483
  <div id="paper" class="col" style="background-color: {{level.theme.background}}"></div>
477
484
 
478
- <div id="direct_drive" class="unselectable no-print">
479
- <button class="direct_drive_button" id="moveForward" {% if not level.direct_drive %} style="visibility: hidden" {% endif %}></button>
480
- <button class="direct_drive_button" id="turnLeft" {% if not level.direct_drive %} style="visibility: hidden" {% endif %}></button>
481
- <button class="direct_drive_button" id="go" {% if not level.direct_drive %} style="visibility: hidden" {% endif %}></button>
482
- <button class="direct_drive_button" id="turnRight" {% if not level.direct_drive %} style="visibility: hidden" {% endif %}></button>
483
- </div>
484
-
485
485
  <div id="zoom_pan" >
486
- <button class="direct_drive_button" id="zoomOut" ></button>
487
- <button class="direct_drive_button" id="zoomIn"></button>
486
+ <button class="zoom_pan_button" id="zoomOut" ></button>
487
+ <button class="zoom_pan_button" id="zoomIn"></button>
488
488
  </div>
489
489
 
490
490
  <div id="fuelGauge" class="no-print unselectable">
@@ -494,6 +494,10 @@
494
494
  </div>
495
495
  </div>
496
496
 
497
+ <div id="electricFuelGauge" class="no-print unselectable">
498
+ <electric-gauge />
499
+ </div>
500
+
497
501
  <div id="consoleSlider" class="no-print"></div>
498
502
 
499
503
  </div>
@@ -507,4 +511,104 @@
507
511
  }
508
512
  </script>
509
513
 
510
- {% endblock %}
514
+ <script>
515
+ customElements.define("electric-gauge", class extends HTMLElement {
516
+ connectedCallback() {
517
+ setTimeout(() => {
518
+ this.innerHTML = `<svg id="a" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 119.58 119.58">
519
+ <defs>
520
+ <linearGradient id="c" x1="2.5" y1="59.86" x2="117.08" y2="59.86" gradientTransform="translate(0 119.65) scale(1 -1)" gradientUnits="userSpaceOnUse">
521
+ <stop offset="0" stop-color="#050505"/>
522
+ <stop offset="1" stop-color="#111"/>
523
+ </linearGradient>
524
+ <linearGradient id="g" x1="30.57" y1="24.62" x2="38.29" y2="24.62" gradientTransform="translate(20.78 -15.45) rotate(35.62)" xlink:href="#c"/>
525
+ <linearGradient id="h" x1="12.95" y1="46.44" x2="24.09" y2="46.44" gradientTransform="translate(56.12 13.48) rotate(70.5)" xlink:href="#c"/>
526
+ <linearGradient id="i" x1="59.23" y1="16.37" x2="60.45" y2="16.37" gradientTransform="matrix(1,0,0,1,0,0)" xlink:href="#c"/>
527
+ <linearGradient id="j" x1="59.23" y1="103.05" x2="60.45" y2="103.05" gradientTransform="matrix(1,0,0,1,0,0)" xlink:href="#c"/>
528
+ <linearGradient id="k" x1="12.96" y1="73.1" x2="24.28" y2="73.1" gradientTransform="translate(23.5 -2.18) rotate(18)" xlink:href="#c"/>
529
+ <linearGradient id="l" x1="30.5" y1="94.77" x2="38.24" y2="94.77" gradientTransform="translate(90.82 11.25) rotate(53.99)" xlink:href="#c"/>
530
+ <linearGradient id="m" x1="81.28" y1="95.01" x2="89.02" y2="95.01" gradientTransform="translate(72.11 -31.9) rotate(36)" xlink:href="#c"/>
531
+ <linearGradient id="n" x1="81.29" y1="24.57" x2="89.01" y2="24.57" gradientTransform="translate(55.5 -58.95) rotate(54.36)" xlink:href="#c"/>
532
+ <linearGradient id="o" x1="95.49" y1="46.4" x2="106.63" y2="46.4" gradientTransform="translate(21.24 -31.02) rotate(19.47)" xlink:href="#c"/>
533
+ <linearGradient id="p" x1="95.3" y1="73.06" x2="106.61" y2="73.06" gradientTransform="translate(139.25 -45.53) rotate(72.01)" xlink:href="#c"/>
534
+ <linearGradient id="r" x1="59.79" y1="116.72" x2="59.79" y2="56.09" gradientTransform="translate(0 119.65) scale(1 -1)" gradientUnits="userSpaceOnUse">
535
+ <stop offset="0" stop-color="#fff" stop-opacity=".4"/>
536
+ <stop offset="1" stop-color="#fff" stop-opacity="0"/>
537
+ </linearGradient>
538
+ <radialGradient id="s" cx="59.25" cy="619.61" fx="59.25" fy="619.61" r="96.47" gradientTransform="translate(0 -88.24) scale(1 .28)" gradientUnits="userSpaceOnUse">
539
+ <stop offset=".29" stop-color="#fff" stop-opacity="0"/>
540
+ <stop offset="1" stop-color="#fff" stop-opacity=".4"/>
541
+ </radialGradient>
542
+ </defs>
543
+ <g id="b">
544
+ <circle fill="url(#c)" cx="59.79" cy="59.79" r="57.29"/>
545
+ <path fill="#141414" stroke-width="0px" d="M59.79,13.14c29.86,0,54.38,22.85,57.05,52.02.16-1.74.24-3.49.24-5.27,0-31.64-25.65-57.29-57.29-57.29S2.5,28.25,2.5,59.88c0,1.78.09,3.54.24,5.27C5.4,35.99,29.93,13.14,59.79,13.14Z"/>
546
+ <path stroke="#fff" fill="none" stroke-miterlimit="10" d="M59.79,109.9c-27.63,0-50.11-22.48-50.11-50.11S32.16,9.68,59.79,9.68s50.11,22.48,50.11,50.11-22.48,50.11-50.11,50.11Z"/>
547
+ <circle fill="none" stroke-miterlimit="10" stroke="#3a3a3a" stroke-width="5px" cx="59.79" cy="59.79" r="57.29"/>
548
+ </g>
549
+ <path id="d" fill="#fff" stroke-width="0px" d="M68.91,70.86h-7.35c-.28,0-.48-.26-.42-.53l2.49-10.37c.11-.46-.49-.74-.77-.35l-11.46,16.1c-.2.28,0,.68.35.68h7.35c.28,0,.48.26.42.53l-2.49,10.37c-.11.46.49.74.77.35l11.46-16.1c.2-.28,0-.68-.35-.68Z"/>
550
+ <g id="e" isolation="isolate">
551
+ <g isolation="isolate">
552
+ <text
553
+ id="Text_percentage"
554
+ data-name="Text percentage"
555
+ font-family="LilitaOne, 'Lilita One'"
556
+ font-size="16px"
557
+ transform="translate(43.2 48.2)"
558
+ fill="#4ba0dd">
559
+ <tspan id="Text_percentage_value" x="0" y="0">100%</tspan>
560
+ </text>
561
+ </g>
562
+ </g>
563
+ <path id="f" fill="#4ba0dd" stroke-width="0px" d="
564
+ M106.22,44.62
565
+ c-3.21-9.9-9.5-18.41-17.74-24.4-8.06-5.86-17.97-9.33-28.69-9.33s-20.64,3.47-28.69,9.33
566
+ c-8.24,6-14.53,14.5-17.74,24.4-1.54,4.75-2.39,9.82-2.39,15.09
567
+ s.84,10.33,2.39,15.09
568
+ c3.21,9.9,9.5,18.41,17.74,24.4,8.06,5.86,17.97,9.33,28.69,9.33
569
+ s20.64-3.47,28.69-9.33
570
+ c8.24-6,14.53-14.5,17.74-24.4,1.54-4.75,2.39-9.82,2.39-15.09
571
+ s-.84-10.33-2.39-15.09Z
572
+ M82.27,90.65
573
+ c-6.31,4.59-14.08,7.31-22.48,7.31
574
+ s-16.17-2.72-22.48-7.31
575
+ c-6.46-4.7-11.38-11.36-13.9-19.12-1.21-3.72-1.87-7.69-1.87-11.82s.66-8.1,1.87-11.82
576
+ c2.52-7.76,7.44-14.42,13.9-19.12,6.31-4.59,14.08-7.31,22.48-7.31
577
+ s16.17,2.72,22.48,7.31
578
+ c6.46,4.7,11.38,11.36,13.9,19.12,1.21,3.72,1.87,7.69,1.87,11.82
579
+ s-.66,8.1-1.87,11.82
580
+ c-2.52,7.76-7.44,14.42-13.9,19.12Z"
581
+ />
582
+ <circle
583
+ id="emptying_circle"
584
+ cx="59.79"
585
+ cy="59.79"
586
+ r="43.5"
587
+ stroke-width="11"
588
+ stroke="#213a47"
589
+ fill="transparent"
590
+ stroke-dasharray="273.18"
591
+ stroke-dashoffset="273.18"
592
+ transform="rotate(90, 59.79, 59.79)"
593
+ />
594
+ <rect fill="url(#g)" stroke-width="0px" x="33.82" y="18.84" width="1.22" height="11.56" transform="translate(-7.9 24.66) rotate(-35.62)"/>
595
+ <rect fill="url(#h)" stroke-width="0px" x="17.91" y="40.75" width="1.22" height="11.39" transform="translate(-31.44 48.4) rotate(-70.5)"/>
596
+ <rect fill="url(#i)" stroke-width="0px" x="59.23" y="10.63" width="1.22" height="11.5"/>
597
+ <rect fill="url(#j)" stroke-width="0px" x="59.23" y="97.3" width="1.22" height="11.5"/>
598
+ <rect fill="url(#k)" stroke-width="0px" x="12.87" y="72.49" width="11.5" height="1.22" transform="translate(-21.68 9.33) rotate(-18)"/>
599
+ <rect fill="url(#l)" stroke-width="0px" x="28.62" y="94.16" width="11.49" height="1.22" transform="translate(-62.5 66.86) rotate(-53.99)"/>
600
+ <rect fill="url(#m)" stroke-width="0px" x="84.54" y="89.26" width="1.22" height="11.49" transform="translate(-39.58 68.19) rotate(-36)"/>
601
+ <rect fill="url(#n)" stroke-width="0px" x="79.37" y="23.96" width="11.56" height="1.22" transform="translate(15.57 79.46) rotate(-54.36)"/>
602
+ <rect fill="url(#o)" stroke-width="0px" x="95.36" y="45.79" width="11.39" height="1.22" transform="translate(-9.69 36.33) rotate(-19.47)"/>
603
+ <rect fill="url(#p)" stroke-width="0px" x="100.35" y="67.31" width="1.22" height="11.5" transform="translate(.28 146.51) rotate(-72.01)"/>
604
+ <g id="q">
605
+ <path fill="url(#r)" stroke-width="0px" d="M109.8,47.55c0,27.62-20.9,6.09-50.02,6.09s-50.02,21.53-50.02-6.09C9.77,29.42,33.7,7.65,59.79,7.65s50.02,22.32,50.02,39.9Z"/>
606
+ <path fill="url(#s)" stroke-width="0px" d="M97.33,91.74c0-13.29-15.69-2.93-37.54-2.93s-37.55-10.36-37.55,2.93c0,8.73,17.96,20.18,37.55,20.18,19.58,0,37.54-11.72,37.54-20.18Z"/>
607
+ </g>
608
+ </svg>`
609
+ })
610
+ }
611
+ })
612
+ </script>
613
+
614
+ {% endblock %}