rapid-router 5.4.1__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 (354) hide show
  1. example_project/rapid_router_test_settings.py +164 -0
  2. example_project/settings.py +152 -0
  3. example_project/urls.py +15 -0
  4. example_project/{example_project/wsgi.py → wsgi.py} +2 -1
  5. game/__init__.py +1 -1
  6. game/admin.py +43 -4
  7. game/app_settings.py +3 -7
  8. game/character.py +26 -18
  9. game/decor.py +172 -97
  10. game/end_to_end_tests/base_game_test.py +44 -33
  11. game/end_to_end_tests/editor_page.py +17 -2
  12. game/end_to_end_tests/game_page.py +127 -45
  13. game/end_to_end_tests/selenium_test_case.py +1 -20
  14. game/end_to_end_tests/test_cow_crashes.py +3 -5
  15. game/end_to_end_tests/test_language_dropdown.py +14 -0
  16. game/end_to_end_tests/test_level_editor.py +290 -0
  17. game/end_to_end_tests/test_level_failures.py +1 -1
  18. game/end_to_end_tests/test_level_selection.py +79 -0
  19. game/end_to_end_tests/test_play_through.py +240 -102
  20. game/end_to_end_tests/test_python_levels.py +44 -13
  21. game/end_to_end_tests/test_saving_workspace.py +22 -0
  22. game/forms.py +9 -2
  23. game/level_management.py +38 -29
  24. game/messages.py +1218 -203
  25. game/migrations/0001_squashed_0025_levels_ordering_pt1.py +19 -1
  26. game/migrations/0026_levels_pt2.py +13 -2
  27. game/migrations/0032_cannot_turn_left_level.py +13 -2
  28. game/migrations/0033_recursion_level.py +13 -2
  29. game/migrations/0034_joes_level.py +13 -2
  30. game/migrations/0035_disable_route_score_level_70.py +0 -2
  31. game/migrations/0036_level_score_73.py +0 -2
  32. game/migrations/0037_level_score_79.py +0 -2
  33. game/migrations/0038_level_score_40.py +0 -1
  34. game/migrations/0042_level_score_73.py +0 -2
  35. game/migrations/0048_add_cow_field_and_blocks.py +0 -2
  36. game/migrations/0049_level_score_34.py +0 -2
  37. game/migrations/0050_level_score_40.py +0 -2
  38. game/migrations/0051_level_score_49.py +0 -1
  39. game/migrations/0076_level_locked_for_class.py +19 -0
  40. game/migrations/0077_alter_level_next_level.py +52 -0
  41. game/migrations/0078_add_block_types.py +23 -0
  42. game/migrations/0079_populate_block_type_add_cow_blocks.py +60 -0
  43. game/migrations/0080_level_disable_algorithm_score.py +18 -0
  44. game/migrations/0081_first_12_levels_no_algo_score.py +29 -0
  45. game/migrations/0082_level_43_solution.py +16 -0
  46. game/migrations/0083_add_cows_to_existing_levels.py +195 -0
  47. game/migrations/0084_alter_block_block_type.py +18 -0
  48. game/migrations/0085_add_new_blocks.py +53 -0
  49. game/migrations/0086_loop_levels.py +482 -0
  50. game/migrations/0087_workspace_python_view_enabled.py +18 -0
  51. game/migrations/0088_rename_episodes.py +35 -0
  52. game/migrations/0089_episodes_in_development.py +30 -0
  53. game/migrations/0090_add_missing_model_solutions.py +144 -0
  54. game/migrations/0091_disable_algo_score_if_no_model_solution.py +46 -0
  55. game/migrations/0092_disable_algo_score_in_custom_levels.py +28 -0
  56. game/migrations/0093_alter_level_character_name.py +18 -0
  57. game/migrations/0094_add_hint_lesson_subtitle_to_levels.py +28 -0
  58. game/migrations/0095_level_commands.py +18 -0
  59. game/migrations/0096_alter_level_commands.py +18 -0
  60. game/migrations/0097_add_python_den_levels.py +1515 -0
  61. game/migrations/0098_add_episode_link_fields.py +44 -0
  62. game/migrations/0099_python_episodes_links.py +103 -0
  63. game/migrations/0100_reorder_python_levels.py +179 -0
  64. game/migrations/0101_rename_episodes.py +45 -0
  65. game/migrations/0102_reoder_episodes_13_14.py +136 -0
  66. game/migrations/0103_level_1015_solution.py +26 -0
  67. game/migrations/0104_remove_level_direct_drive.py +17 -0
  68. game/migrations/0105_delete_invalid_attempts.py +18 -0
  69. game/migrations/0106_fields_to_snake_case.py +48 -0
  70. game/migrations/0107_rename_worksheet_link_episode_student_worksheet_link.py +18 -0
  71. game/migrations/0108_episode_indy_worksheet_link.py +18 -0
  72. game/migrations/0109_create_episodes_23_and_24.py +99 -0
  73. game/migrations/0110_remove_episode_indy_worksheet_link_and_more.py +100 -0
  74. game/migrations/0111_create_worksheets.py +149 -0
  75. game/migrations/0112_worksheet_locked_classes.py +21 -0
  76. game/migrations/0113_level_needs_approval.py +18 -0
  77. game/migrations/0114_default_and_non_student_levels_no_approval.py +31 -0
  78. game/migrations/0115_level_level__default_does_not_need_approval.py +22 -0
  79. game/migrations/0116_update_worksheet_video_links.py +68 -0
  80. game/migrations/0117_update_solutions_to_if_else.py +61 -0
  81. game/models.py +157 -16
  82. game/permissions.py +34 -19
  83. game/python_den_urls.py +26 -0
  84. game/random_road.py +43 -127
  85. game/serializers.py +12 -17
  86. game/static/django_reverse_js/js/reverse.js +171 -0
  87. game/static/game/css/LilitaOne-Regular.ttf +0 -0
  88. game/static/game/css/backgrounds.css +14 -10
  89. game/static/game/css/dataTables.custom.css +4 -2
  90. game/static/game/css/dataTables.jqueryui.css +561 -320
  91. game/static/game/css/editor.css +47 -0
  92. game/static/game/css/game.css +43 -49
  93. game/static/game/css/game_screen.css +116 -53
  94. game/static/game/css/jquery.dataTables.css +455 -251
  95. game/static/game/css/level_editor.css +10 -1
  96. game/static/game/css/level_selection.css +32 -3
  97. game/static/game/css/level_share.css +6 -5
  98. game/static/game/css/skulpt/codemirror.css +1 -0
  99. game/static/game/image/Python_Den_hero_student.png +0 -0
  100. game/static/game/image/Python_levels_page.svg +1954 -0
  101. game/static/game/image/characters/front_view/Electric_van.svg +448 -0
  102. game/static/game/image/characters/top_view/Electric_van.svg +448 -0
  103. game/static/game/image/characters/top_view/Sleigh.svg +436 -0
  104. game/static/game/image/decor/city/solar_panel.svg +1200 -0
  105. game/static/game/image/decor/farm/solar_panel.svg +86 -0
  106. game/static/game/image/decor/grass/solar_panel.svg +86 -0
  107. game/static/game/image/decor/snow/barn.svg +1788 -0
  108. game/static/game/image/decor/snow/cfc.svg +1050 -147
  109. game/static/game/image/decor/snow/crops.svg +7370 -0
  110. game/static/game/image/decor/snow/hospital.svg +1220 -0
  111. game/static/game/image/decor/snow/house1.svg +971 -0
  112. game/static/game/image/decor/snow/house2.svg +1574 -0
  113. game/static/game/image/decor/snow/school.svg +1071 -0
  114. game/static/game/image/decor/snow/shop.svg +3211 -0
  115. game/static/game/image/decor/snow/solar_panel.svg +173 -0
  116. game/static/game/image/electric_van.svg +448 -0
  117. game/static/game/image/icons/add_house.svg +26 -0
  118. game/static/game/image/icons/delete_house.svg +26 -0
  119. game/static/game/image/icons/description.svg +1 -0
  120. game/static/game/image/icons/hint.svg +1 -0
  121. game/static/game/image/icons/if_else.svg +3 -0
  122. game/static/game/image/icons/python.svg +1 -1
  123. game/static/game/image/if_else_example.png +0 -0
  124. game/static/game/image/pigeon.svg +684 -0
  125. game/static/game/image/python_den_header.svg +19 -0
  126. game/static/game/js/animation.js +84 -28
  127. game/static/game/js/blockly/msg/js/bg.js +52 -1
  128. game/static/game/js/blockly/msg/js/ca.js +52 -1
  129. game/static/game/js/blockly/msg/js/en-gb.js +52 -1
  130. game/static/game/js/blockly/msg/js/en.js +52 -1
  131. game/static/game/js/blockly/msg/js/es.js +52 -1
  132. game/static/game/js/blockly/msg/js/fr.js +52 -1
  133. game/static/game/js/blockly/msg/js/hi.js +52 -1
  134. game/static/game/js/blockly/msg/js/it.js +52 -1
  135. game/static/game/js/blockly/msg/js/pl.js +52 -1
  136. game/static/game/js/blockly/msg/js/pt-br.js +52 -1
  137. game/static/game/js/blockly/msg/js/ru.js +52 -1
  138. game/static/game/js/blockly/msg/js/ur.js +52 -1
  139. game/static/game/js/blocklyCompiler.js +550 -392
  140. game/static/game/js/blocklyControl.js +335 -302
  141. game/static/game/js/blocklyCustomBlocks.js +691 -458
  142. game/static/game/js/blocklyCustomisations.js +3 -1
  143. game/static/game/js/button.js +12 -0
  144. game/static/game/js/cow.js +15 -130
  145. game/static/game/js/drawing.js +313 -201
  146. game/static/game/js/editor.js +23 -0
  147. game/static/game/js/game.js +148 -139
  148. game/static/game/js/jquery.dataTables.min.js +3 -159
  149. game/static/game/js/level_editor.js +823 -448
  150. game/static/game/js/level_moderation.js +33 -2
  151. game/static/game/js/level_selection.js +62 -25
  152. game/static/game/js/loadLanguages.js +21 -0
  153. game/static/game/js/map.js +106 -36
  154. game/static/game/js/model.js +55 -107
  155. game/static/game/js/pathFinder.js +73 -72
  156. game/static/game/js/program.js +184 -193
  157. game/static/game/js/pythonControl.js +14 -1
  158. game/static/game/js/scoreboard.js +0 -37
  159. game/static/game/js/scoreboardSharedLevels.js +48 -0
  160. game/static/game/js/sharing.js +22 -10
  161. game/static/game/js/skulpt/codemirror.js +5 -4
  162. game/static/game/js/skulpt/skulpt-stdlib.js +1 -1
  163. game/static/game/js/sound.js +52 -5
  164. game/static/game/js/van.js +0 -7
  165. game/static/game/raphael_image/characters/top_view/Electric_van.svg +448 -0
  166. game/static/game/raphael_image/characters/top_view/Sleigh.svg +436 -0
  167. game/static/game/raphael_image/decor/city/solar_panel.svg +1200 -0
  168. game/static/game/raphael_image/decor/farm/solar_panel.svg +86 -0
  169. game/static/game/raphael_image/decor/grass/solar_panel.svg +86 -0
  170. game/static/game/raphael_image/decor/snow/barn.svg +1788 -0
  171. game/static/game/raphael_image/decor/snow/cfc.svg +1050 -147
  172. game/static/game/raphael_image/decor/snow/crops.svg +7370 -0
  173. game/static/game/raphael_image/decor/snow/hospital.svg +1220 -0
  174. game/static/game/raphael_image/decor/snow/house1.svg +971 -0
  175. game/static/game/raphael_image/decor/snow/house2.svg +1574 -0
  176. game/static/game/raphael_image/decor/snow/school.svg +1071 -0
  177. game/static/game/raphael_image/decor/snow/shop.svg +3211 -0
  178. game/static/game/raphael_image/decor/snow/solar_panel.svg +173 -0
  179. game/static/game/raphael_image/pigeon.svg +685 -0
  180. game/static/game/raphael_image/sleigh_wreckage.svg +430 -0
  181. game/static/game/sass/game.scss +22 -6
  182. game/static/game/sound/clown_horn.mp3 +0 -0
  183. game/static/game/sound/clown_horn.ogg +0 -0
  184. game/static/game/sound/electric_van_starting.mp3 +0 -0
  185. game/static/game/sound/electric_van_starting.ogg +0 -0
  186. game/static/game/sound/pigeon.mp3 +0 -0
  187. game/static/game/sound/pigeon.ogg +0 -0
  188. game/static/game/sound/sleigh_bells.mp3 +0 -0
  189. game/static/game/sound/sleigh_bells.ogg +0 -0
  190. game/static/game/sound/sleigh_crash.mp3 +0 -0
  191. game/static/game/sound/sleigh_crash.ogg +0 -0
  192. game/templates/game/base.html +35 -15
  193. game/templates/game/basenonav.html +23 -17
  194. game/templates/game/game.html +236 -111
  195. game/templates/game/level_editor.html +353 -275
  196. game/templates/game/level_moderation.html +19 -6
  197. game/templates/game/level_selection.html +75 -62
  198. game/templates/game/python_den_level_selection.html +291 -0
  199. game/templates/game/python_den_worksheet.html +101 -0
  200. game/templates/game/scoreboard.html +88 -65
  201. game/tests/test_level_editor.py +210 -35
  202. game/tests/test_level_moderation.py +6 -20
  203. game/tests/test_level_selection.py +332 -11
  204. game/tests/test_python_den_worksheet.py +85 -0
  205. game/tests/test_scoreboard.py +258 -66
  206. game/tests/utils/level.py +43 -3
  207. game/tests/utils/teacher.py +2 -2
  208. game/theme.py +21 -21
  209. game/urls.py +125 -78
  210. game/views/language_code_conversions.py +90 -0
  211. game/views/level.py +201 -63
  212. game/views/level_editor.py +109 -48
  213. game/views/level_moderation.py +29 -6
  214. game/views/level_selection.py +179 -56
  215. game/views/level_solutions.py +600 -106
  216. game/views/scoreboard.py +181 -66
  217. game/views/worksheet.py +25 -0
  218. rapid_router-7.6.8.dist-info/METADATA +174 -0
  219. {rapid_router-5.4.1.dist-info → rapid_router-7.6.8.dist-info}/RECORD +222 -242
  220. {rapid_router-5.4.1.dist-info → rapid_router-7.6.8.dist-info}/WHEEL +1 -1
  221. rapid_router-7.6.8.dist-info/licenses/LICENSE.md +3 -0
  222. example_project/example_project/__init__.py +0 -1
  223. example_project/example_project/settings.py +0 -54
  224. example_project/example_project/urls.py +0 -16
  225. example_project/manage.py +0 -10
  226. game/autoconfig.py +0 -59
  227. game/csp_config.py +0 -23
  228. game/locale/ar_SA/LC_MESSAGES/django.mo +0 -0
  229. game/locale/ar_SA/LC_MESSAGES/django.po +0 -405
  230. game/locale/ar_SA/LC_MESSAGES/djangojs.mo +0 -0
  231. game/locale/ar_SA/LC_MESSAGES/djangojs.po +0 -743
  232. game/locale/bg_BG/LC_MESSAGES/django.mo +0 -0
  233. game/locale/bg_BG/LC_MESSAGES/django.po +0 -405
  234. game/locale/bg_BG/LC_MESSAGES/djangojs.mo +0 -0
  235. game/locale/bg_BG/LC_MESSAGES/djangojs.po +0 -739
  236. game/locale/ca_ES/LC_MESSAGES/django.mo +0 -0
  237. game/locale/ca_ES/LC_MESSAGES/django.po +0 -405
  238. game/locale/ca_ES/LC_MESSAGES/djangojs.mo +0 -0
  239. game/locale/ca_ES/LC_MESSAGES/djangojs.po +0 -740
  240. game/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
  241. game/locale/cs_CZ/LC_MESSAGES/django.po +0 -405
  242. game/locale/cs_CZ/LC_MESSAGES/djangojs.mo +0 -0
  243. game/locale/cs_CZ/LC_MESSAGES/djangojs.po +0 -741
  244. game/locale/cy_GB/LC_MESSAGES/django.mo +0 -0
  245. game/locale/cy_GB/LC_MESSAGES/django.po +0 -405
  246. game/locale/cy_GB/LC_MESSAGES/djangojs.mo +0 -0
  247. game/locale/cy_GB/LC_MESSAGES/djangojs.po +0 -743
  248. game/locale/de_DE/LC_MESSAGES/django.mo +0 -0
  249. game/locale/de_DE/LC_MESSAGES/django.po +0 -405
  250. game/locale/de_DE/LC_MESSAGES/djangojs.mo +0 -0
  251. game/locale/de_DE/LC_MESSAGES/djangojs.po +0 -739
  252. game/locale/el_GR/LC_MESSAGES/django.mo +0 -0
  253. game/locale/el_GR/LC_MESSAGES/django.po +0 -405
  254. game/locale/el_GR/LC_MESSAGES/djangojs.mo +0 -0
  255. game/locale/el_GR/LC_MESSAGES/djangojs.po +0 -739
  256. game/locale/en_GB/LC_MESSAGES/django.mo +0 -0
  257. game/locale/en_GB/LC_MESSAGES/django.po +0 -405
  258. game/locale/en_GB/LC_MESSAGES/djangojs.mo +0 -0
  259. game/locale/en_GB/LC_MESSAGES/djangojs.po +0 -739
  260. game/locale/es_ES/LC_MESSAGES/django.mo +0 -0
  261. game/locale/es_ES/LC_MESSAGES/django.po +0 -405
  262. game/locale/es_ES/LC_MESSAGES/djangojs.mo +0 -0
  263. game/locale/es_ES/LC_MESSAGES/djangojs.po +0 -739
  264. game/locale/fi_FI/LC_MESSAGES/django.mo +0 -0
  265. game/locale/fi_FI/LC_MESSAGES/django.po +0 -405
  266. game/locale/fi_FI/LC_MESSAGES/djangojs.mo +0 -0
  267. game/locale/fi_FI/LC_MESSAGES/djangojs.po +0 -739
  268. game/locale/fr_FR/LC_MESSAGES/django.mo +0 -0
  269. game/locale/fr_FR/LC_MESSAGES/django.po +0 -405
  270. game/locale/fr_FR/LC_MESSAGES/djangojs.mo +0 -0
  271. game/locale/fr_FR/LC_MESSAGES/djangojs.po +0 -739
  272. game/locale/gu_IN/LC_MESSAGES/django.mo +0 -0
  273. game/locale/gu_IN/LC_MESSAGES/django.po +0 -405
  274. game/locale/gu_IN/LC_MESSAGES/djangojs.mo +0 -0
  275. game/locale/gu_IN/LC_MESSAGES/djangojs.po +0 -739
  276. game/locale/hi_IN/LC_MESSAGES/django.mo +0 -0
  277. game/locale/hi_IN/LC_MESSAGES/django.po +0 -405
  278. game/locale/hi_IN/LC_MESSAGES/djangojs.mo +0 -0
  279. game/locale/hi_IN/LC_MESSAGES/djangojs.po +0 -739
  280. game/locale/id_ID/LC_MESSAGES/django.mo +0 -0
  281. game/locale/id_ID/LC_MESSAGES/django.po +0 -405
  282. game/locale/id_ID/LC_MESSAGES/djangojs.mo +0 -0
  283. game/locale/id_ID/LC_MESSAGES/djangojs.po +0 -738
  284. game/locale/it_IT/LC_MESSAGES/django.mo +0 -0
  285. game/locale/it_IT/LC_MESSAGES/django.po +0 -405
  286. game/locale/it_IT/LC_MESSAGES/djangojs.mo +0 -0
  287. game/locale/it_IT/LC_MESSAGES/djangojs.po +0 -739
  288. game/locale/ja_JP/LC_MESSAGES/django.mo +0 -0
  289. game/locale/ja_JP/LC_MESSAGES/django.po +0 -405
  290. game/locale/ja_JP/LC_MESSAGES/djangojs.mo +0 -0
  291. game/locale/ja_JP/LC_MESSAGES/djangojs.po +0 -738
  292. game/locale/lol_US/LC_MESSAGES/django.mo +0 -0
  293. game/locale/lol_US/LC_MESSAGES/django.po +0 -405
  294. game/locale/lol_US/LC_MESSAGES/djangojs.mo +0 -0
  295. game/locale/lol_US/LC_MESSAGES/djangojs.po +0 -739
  296. game/locale/nb_NO/LC_MESSAGES/django.mo +0 -0
  297. game/locale/nb_NO/LC_MESSAGES/django.po +0 -405
  298. game/locale/nb_NO/LC_MESSAGES/djangojs.mo +0 -0
  299. game/locale/nb_NO/LC_MESSAGES/djangojs.po +0 -739
  300. game/locale/nl_NL/LC_MESSAGES/django.mo +0 -0
  301. game/locale/nl_NL/LC_MESSAGES/django.po +0 -405
  302. game/locale/nl_NL/LC_MESSAGES/djangojs.mo +0 -0
  303. game/locale/nl_NL/LC_MESSAGES/djangojs.po +0 -739
  304. game/locale/pl_PL/LC_MESSAGES/django.mo +0 -0
  305. game/locale/pl_PL/LC_MESSAGES/django.po +0 -405
  306. game/locale/pl_PL/LC_MESSAGES/djangojs.mo +0 -0
  307. game/locale/pl_PL/LC_MESSAGES/djangojs.po +0 -741
  308. game/locale/pt_BR/LC_MESSAGES/django.mo +0 -0
  309. game/locale/pt_BR/LC_MESSAGES/django.po +0 -405
  310. game/locale/pt_BR/LC_MESSAGES/djangojs.mo +0 -0
  311. game/locale/pt_BR/LC_MESSAGES/djangojs.po +0 -739
  312. game/locale/pt_PT/LC_MESSAGES/django.mo +0 -0
  313. game/locale/pt_PT/LC_MESSAGES/django.po +0 -405
  314. game/locale/pt_PT/LC_MESSAGES/djangojs.mo +0 -0
  315. game/locale/pt_PT/LC_MESSAGES/djangojs.po +0 -739
  316. game/locale/ro_RO/LC_MESSAGES/django.mo +0 -0
  317. game/locale/ro_RO/LC_MESSAGES/django.po +0 -405
  318. game/locale/ro_RO/LC_MESSAGES/djangojs.mo +0 -0
  319. game/locale/ro_RO/LC_MESSAGES/djangojs.po +0 -740
  320. game/locale/ru_RU/LC_MESSAGES/django.mo +0 -0
  321. game/locale/ru_RU/LC_MESSAGES/django.po +0 -405
  322. game/locale/ru_RU/LC_MESSAGES/djangojs.mo +0 -0
  323. game/locale/ru_RU/LC_MESSAGES/djangojs.po +0 -741
  324. game/locale/sv_SE/LC_MESSAGES/django.mo +0 -0
  325. game/locale/sv_SE/LC_MESSAGES/django.po +0 -405
  326. game/locale/sv_SE/LC_MESSAGES/djangojs.mo +0 -0
  327. game/locale/sv_SE/LC_MESSAGES/djangojs.po +0 -739
  328. game/locale/tl_PH/LC_MESSAGES/django.mo +0 -0
  329. game/locale/tl_PH/LC_MESSAGES/django.po +0 -405
  330. game/locale/tl_PH/LC_MESSAGES/djangojs.mo +0 -0
  331. game/locale/tl_PH/LC_MESSAGES/djangojs.po +0 -739
  332. game/locale/tlh_AA/LC_MESSAGES/django.mo +0 -0
  333. game/locale/tlh_AA/LC_MESSAGES/django.po +0 -405
  334. game/locale/tlh_AA/LC_MESSAGES/djangojs.mo +0 -0
  335. game/locale/tlh_AA/LC_MESSAGES/djangojs.po +0 -739
  336. game/locale/tr_TR/LC_MESSAGES/django.mo +0 -0
  337. game/locale/tr_TR/LC_MESSAGES/django.po +0 -405
  338. game/locale/tr_TR/LC_MESSAGES/djangojs.mo +0 -0
  339. game/locale/tr_TR/LC_MESSAGES/djangojs.po +0 -740
  340. game/locale/ur_IN/LC_MESSAGES/django.mo +0 -0
  341. game/locale/ur_IN/LC_MESSAGES/django.po +0 -405
  342. game/locale/ur_IN/LC_MESSAGES/djangojs.mo +0 -0
  343. game/locale/ur_IN/LC_MESSAGES/djangojs.po +0 -739
  344. game/locale/ur_PK/LC_MESSAGES/django.mo +0 -0
  345. game/locale/ur_PK/LC_MESSAGES/django.po +0 -405
  346. game/locale/ur_PK/LC_MESSAGES/djangojs.mo +0 -0
  347. game/locale/ur_PK/LC_MESSAGES/djangojs.po +0 -739
  348. game/static/game/image/actions/go.svg +0 -18
  349. game/static/game/image/icons/destination.svg +0 -9
  350. game/static/game/js/pqselect.min.js +0 -9
  351. game/static/game/js/widget-scroller.js +0 -906
  352. rapid_router-5.4.1.dist-info/LICENSE.md +0 -577
  353. rapid_router-5.4.1.dist-info/METADATA +0 -24
  354. {rapid_router-5.4.1.dist-info → rapid_router-7.6.8.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,6 @@
1
1
  /* global showPopupConfirmation */
2
2
 
3
3
  var levelID;
4
- var classID;
5
4
  var students;
6
5
 
7
6
  var saving = new ocargo.Saving();
@@ -57,6 +56,27 @@ jQuery.extend(jQuery.fn.dataTableExt.oSort, {
57
56
  },
58
57
  });
59
58
 
59
+ approveLevel = function (id, callback, errorCallback) {
60
+ csrftoken = Cookies.get('csrftoken');
61
+ $.ajax({
62
+ url: Urls.approve_level(id),
63
+ type: 'POST',
64
+ dataType: 'json',
65
+ data: {csrfmiddlewaretoken: csrftoken},
66
+ beforeSend: function (xhr, settings) {
67
+ if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
68
+ xhr.setRequestHeader("X-CSRFToken", csrftoken);
69
+ }
70
+ },
71
+ success: function (json) {
72
+ callback();
73
+ },
74
+ error: function (xhr, errmsg, err) {
75
+ errorCallback(xhr.status + ": " + errmsg + " " + err + " " + xhr.responseText);
76
+ }
77
+ });
78
+ };
79
+
60
80
  $(document).ready(function () {
61
81
  $(".delete").click(function () {
62
82
  levelID = this.getAttribute("value");
@@ -67,6 +87,17 @@ $(document).ready(function () {
67
87
  window.location.href = Urls.play_custom_level(this.getAttribute("value"));
68
88
  });
69
89
 
90
+ $(".approve").click(function () {
91
+ levelID = this.getAttribute("value");
92
+ approveLevel(levelID)
93
+ // Waiting half a second before redirecting because otherwise the Approve button doesn't become disabled
94
+ setTimeout(
95
+ function(){
96
+ window.location.href = Urls.level_moderation();
97
+ },
98
+ 500);
99
+ });
100
+
70
101
  $("#clear-classes").on("click", () => {
71
102
  $('[id^="id_classes_"],#select-all-classes').prop("checked", false);
72
103
  });
@@ -105,7 +136,7 @@ $(document).ready(function () {
105
136
  {
106
137
  orderable: false,
107
138
  searchable: false,
108
- targets: [-1, -2], // Play and Delete columns
139
+ targets: [-1, -2, -3], // Play, Approve and Delete columns
109
140
  },
110
141
  {
111
142
  type: "student-with-teacher",
@@ -8,30 +8,30 @@ function setupCoins() {
8
8
 
9
9
  var minScore = 20;
10
10
  var episodeToOpen;
11
+ var ratios = [];
11
12
  for(var j = 0; j < episode.levels.length; j++) {
12
13
  var level = episode.levels[j];
13
-
14
- imageStr = getImageStr(level.score, level.maxScore);
15
- if(imageStr !== '') {
16
- $('.level_image.coin_image[value=' + level.name + ']').attr('src', imageStr);
17
- }
18
- else {
14
+ if (level.score === "None"){
19
15
  $('.level_image.coin_image[value=' + level.name + ']').remove();
20
- minScore = "None";
21
16
  if(!episodeToOpen) {
22
17
  episodeToOpen = episode;
23
18
  }
24
- }
25
-
26
- if(minScore != "None" && level.score < minScore) {
27
- minScore = level.score;
19
+ ratios.push(-1);
20
+ } else {
21
+ var ratio = level.score / level.maxScore;
22
+ ratios.push(ratio);
23
+ imageStr = getImageStr(ratio);
24
+ $('.level_image.coin_image[value=' + level.name + ']').attr('src', imageStr);
28
25
  }
29
26
  }
30
27
 
31
- if(minScore !== "None") {
32
- $('.episode_image.coin_image[value=' + episode.id + ']').attr('src', getImageStr(minScore))
33
- }
34
- else {
28
+ if (ratios.length > 0 && !ratios.includes(-1)){
29
+ var sum =0;
30
+ ratios.forEach ((item) => sum += item);
31
+ var ave_ratio = sum/ratios.length;
32
+ img = getImageStr(ave_ratio);
33
+ $('.episode_image.coin_image[value=' + episode.id + ']').attr('src', img)
34
+ } else {
35
35
  $('.episode_image.coin_image[value=' + episode.id + ']').remove();
36
36
  }
37
37
  }
@@ -39,7 +39,7 @@ function setupCoins() {
39
39
  for(var i = 0; i < OTHER_LEVELS.length; i++) {
40
40
  var level = OTHER_LEVELS[i];
41
41
 
42
- imageStr = getImageStr(level.score, level.maxScore);
42
+ imageStr = getImageStr(level.score / level.maxScore);
43
43
  if(imageStr !== '') {
44
44
  $('.level_image.coin_image[value=' + level.id + ']').attr('src', imageStr);
45
45
  }
@@ -52,21 +52,58 @@ function setupCoins() {
52
52
  $('#episode' + episodeToOpen.id).click();
53
53
  }
54
54
 
55
- function getImageStr(score, maxScore) {
55
+ function getImageStr(fraction) {
56
56
  var imageStr = "/static/game/image/coins/coin_";
57
- percentage = 100.0 * score / maxScore;
58
- if(score == "None") {
59
- return "";
60
- }
61
- else if(percentage >= 99.99999) {
57
+ if(fraction >= 0.99) {
62
58
  return imageStr + 'gold.svg';
63
59
  }
64
- else if(percentage > 0.5) {
60
+ else if(fraction > 0.5) {
65
61
  return imageStr + 'silver.svg';
66
62
  }
67
- else if(percentage >= 0.0) {
63
+ else if(fraction >= 0.0) {
68
64
  return imageStr + 'copper.svg';
69
65
  }
70
- return '';
71
66
  }
72
67
  }
68
+
69
+ document.addEventListener("DOMContentLoaded", function() {
70
+ const storedEpisode = localStorage.getItem('currentEpisode');
71
+ const allCollapsibles = document.querySelectorAll('.collapse');
72
+
73
+ // Function to close all except the given ID
74
+ function closeAllExcept(openId) {
75
+ allCollapsibles.forEach(function(collapsible) {
76
+ if (collapsible.id !== openId) {
77
+ collapsible.classList.remove('in');
78
+ const toggle = document.querySelector(`[data-target="#${collapsible.id}"]`);
79
+ toggle.classList.add('collapsed');
80
+ toggle.setAttribute('aria-expanded', 'false');
81
+ }
82
+ });
83
+ }
84
+
85
+ // Open the accordion for the stored episode
86
+ const accordionToOpen = storedEpisode ? document.querySelector(`#collapse-${storedEpisode}`) : null;
87
+ if (accordionToOpen) {
88
+ accordionToOpen.classList.add('in');
89
+ const toggle = document.querySelector(`[data-target="#${accordionToOpen.id}"]`);
90
+ toggle.classList.remove('collapsed');
91
+ toggle.setAttribute('aria-expanded', 'true');
92
+ } else {
93
+ closeAllExcept(); // Close all of no epissodes are stored
94
+ }
95
+
96
+ // Set up event listeners for accordion toggles
97
+ const accordionToggles = document.querySelectorAll('.episode-title');
98
+ accordionToggles.forEach(function(toggle) {
99
+ toggle.addEventListener('click', function() {
100
+ const collapseId = toggle.getAttribute('data-target').replace('#', '');
101
+ const isOpened = toggle.getAttribute('aria-expanded') === 'false'; // Notice the change here
102
+ localStorage.setItem('currentEpisode', isOpened ? collapseId.split('-')[1] : null);
103
+ if (isOpened) {
104
+ closeAllExcept(collapseId);
105
+ }
106
+ });
107
+ });
108
+
109
+ });
@@ -0,0 +1,21 @@
1
+ function loadLanguage(path, langStr, callback) {
2
+ var xobj = new XMLHttpRequest();
3
+ xobj.overrideMimeType("application/javascript");
4
+ xobj.open('GET', path + langStr + '.js', true);
5
+ xobj.onreadystatechange = function () {
6
+ if (xobj.readyState == 4 && xobj.status == "200") {
7
+ eval(xobj.responseText);
8
+ callback();
9
+ } else if (xobj.status == "404") {
10
+ loadLanguage(path, "en", callback);
11
+ }
12
+ };
13
+ xobj.send(null);
14
+ }
15
+
16
+ function reloadWorkspace(workspace) {
17
+ var blocklyDom = Blockly.Xml.workspaceToDom(workspace);
18
+ workspace.clear();
19
+ Blockly.Xml.domToWorkspace(blocklyDom, workspace);
20
+ workspace.updateToolbox(BLOCKLY_XML);
21
+ }
@@ -2,10 +2,6 @@
2
2
 
3
3
  var ocargo = ocargo || {};
4
4
 
5
- var forwardAngle = Math.PI;
6
- var leftCutoffAngle = 5 * Math.PI / 6;
7
- var rightCutoffAngle = 7 * Math.PI / 6;
8
-
9
5
  ocargo.Map = function(nodeData, origin, destinationCoordinates) {
10
6
  this.nodeData = nodeData;
11
7
  this.nodes = ocargo.Node.parsePathData(nodeData);
@@ -41,54 +37,128 @@ ocargo.Map.prototype.getDestinations = function() {
41
37
  ocargo.Map.prototype.isRoadForward = function(position) {
42
38
  var previousNode = position.previousNode;
43
39
  var currentNode = position.currentNode;
44
-
45
- var nextNode = null;
46
- var nextNodeDeviation = null;
47
-
48
- var nodes = currentNode.connectedNodes;
49
- for (var i = 0; i < nodes.length; i++) {
50
- var node = nodes[i];
51
- var angle = ocargo.calculateClockwiseNodeAngle(previousNode, currentNode, node);
52
- var deviation = Math.abs(forwardAngle - angle);
53
- if (angle >= leftCutoffAngle && angle <= rightCutoffAngle &&
54
- (nextNode === null || deviation < nextNodeDeviation)) {
55
- nextNode = node;
56
- nextNodeDeviation = deviation;
40
+ var nextCoordinates = {};
41
+ // Moving up, down or sideways?
42
+ var movingHorizontally = previousNode.coordinate.x != currentNode.coordinate.x;
43
+
44
+ if (movingHorizontally) {
45
+ nextCoordinates.y = currentNode.coordinate.y; // y-axis isn't changing
46
+ var movingRight = previousNode.coordinate.x < currentNode.coordinate.x; // going left or right?
47
+ if (movingRight){
48
+ nextCoordinates.x = currentNode.coordinate.x + 1;
49
+ if (nextCoordinates.x > 9) { // right-most extremity
50
+ return null;
51
+ }
52
+ } else { // moving left
53
+ nextCoordinates.x = currentNode.coordinate.x - 1
54
+ if (nextCoordinates.x < 0){ // left-most extremity
55
+ return null;
56
+ }
57
+ }
58
+ } else { // moving vertically
59
+ nextCoordinates.x = currentNode.coordinate.x;
60
+ var movingUpwards = previousNode.coordinate.y < currentNode.coordinate.y;
61
+ if (movingUpwards) {
62
+ nextCoordinates.y = currentNode.coordinate.y + 1;
63
+ if (nextCoordinates.y > 9) {
64
+ return null;
65
+ }
66
+ } else { // moving downwards
67
+ nextCoordinates.y = currentNode.coordinate.y - 1;
68
+ if (nextCoordinates.y < 0) {
69
+ return null;
70
+ }
71
+ }
72
+ }
73
+ var connected = currentNode.connectedNodes;
74
+ for (var i = 0; i < connected.length; i++){
75
+ var coordinate = connected[i].coordinate;
76
+ if (coordinate.x == nextCoordinates.x && coordinate.y == nextCoordinates.y){
77
+ return connected[i];
57
78
  }
58
79
  }
59
- return nextNode;
80
+ return null;
60
81
  };
61
82
 
62
83
  ocargo.Map.prototype.isRoadLeft = function(position) {
63
84
  var previousNode = position.previousNode;
64
85
  var currentNode = position.currentNode;
65
86
 
66
- var index = currentNode.connectedNodes.indexOf(previousNode) + 1;
67
- var nextNode;
68
- if (index === currentNode.connectedNodes.length) {
69
- nextNode = currentNode.connectedNodes[0];
70
- } else {
71
- nextNode = currentNode.connectedNodes[index];
87
+ var nextCoordinates = {};
88
+ // Moving up, down or sideways?
89
+ var movingHorizontally = previousNode.coordinate.x != currentNode.coordinate.x;
90
+ if (movingHorizontally){
91
+ nextCoordinates.x = currentNode.coordinate.x;
92
+ var movingRight = previousNode.coordinate.x < currentNode.coordinate.x;
93
+ if (movingRight) {
94
+ nextCoordinates.y = currentNode.coordinate.y + 1;
95
+ } else { // moving left
96
+ nextCoordinates.y = currentNode.coordinate.y - 1;
97
+ }
98
+ if (nextCoordinates.y < 0 || nextCoordinates.y > 9){
99
+ return null;
100
+ }
101
+ } else { // moving up and down
102
+ nextCoordinates.y = currentNode.coordinate.y;
103
+ var movingUp = previousNode.coordinate.y < currentNode.coordinate.y;
104
+ if (movingUp) {
105
+ nextCoordinates.x = previousNode.coordinate.x - 1;
106
+ } else { // moving down
107
+ nextCoordinates.x = previousNode.coordinate.x + 1;
108
+ }
109
+ if (nextCoordinates.x < 0 || nextCoordinates.x > 9){
110
+ return null;
111
+ }
72
112
  }
73
-
74
- var angle = ocargo.calculateClockwiseNodeAngle(previousNode, currentNode, nextNode);
75
- return (angle > 0 && angle < leftCutoffAngle) ? nextNode : null;
113
+ var connected = currentNode.connectedNodes;
114
+ for (var i = 0; i < connected.length; i++){
115
+ var coordinate = connected[i].coordinate;
116
+ if (coordinate.x == nextCoordinates.x && coordinate.y == nextCoordinates.y){
117
+ return connected[i];
118
+ }
119
+ }
120
+ return null;
76
121
  };
77
122
 
123
+
78
124
  ocargo.Map.prototype.isRoadRight = function(position) {
79
125
  var previousNode = position.previousNode;
80
126
  var currentNode = position.currentNode;
81
127
 
82
- var index = currentNode.connectedNodes.indexOf(previousNode) - 1;
83
- var nextNode;
84
- if (index === -1) {
85
- nextNode = currentNode.connectedNodes[currentNode.connectedNodes.length - 1];
86
- } else {
87
- nextNode = currentNode.connectedNodes[index];
128
+ var nextCoordinates = {};
129
+ // Moving up, down or sideways?
130
+ var movingHorizontally = previousNode.coordinate.x != currentNode.coordinate.x;
131
+ if (movingHorizontally){
132
+ nextCoordinates.x = currentNode.coordinate.x;
133
+ var movingRight = previousNode.coordinate.x < currentNode.coordinate.x;
134
+ if (movingRight) {
135
+ nextCoordinates.y = currentNode.coordinate.y - 1;
136
+ } else { // moving left
137
+ nextCoordinates.y = currentNode.coordinate.y + 1;
138
+ }
139
+ if (nextCoordinates.y < 0 || nextCoordinates.y > 9){
140
+ return null;
141
+ }
142
+ } else { // moving up and down
143
+ nextCoordinates.y = currentNode.coordinate.y;
144
+ var movingUp = previousNode.coordinate.y < currentNode.coordinate.y;
145
+ if (movingUp) {
146
+ nextCoordinates.x = previousNode.coordinate.x + 1;
147
+ } else { // moving down
148
+ nextCoordinates.x = previousNode.coordinate.x - 1;
149
+ }
150
+ if (nextCoordinates.x < 0 || nextCoordinates.x > 9){
151
+ return null;
152
+ }
88
153
  }
89
-
90
- var angle = ocargo.calculateClockwiseNodeAngle(previousNode, currentNode, nextNode);
91
- return (angle > rightCutoffAngle && angle < 2 * Math.PI) ? nextNode : null;
154
+ var connected = currentNode.connectedNodes;
155
+ for (var i = 0; i < connected.length; i++){
156
+ var coordinate = connected[i].coordinate;
157
+ if (coordinate.x == nextCoordinates.x && coordinate.y == nextCoordinates.y){
158
+ return connected[i];
159
+ }
160
+ }
161
+ return null;
92
162
  };
93
163
 
94
164
  ocargo.Map.prototype.isDeadEnd = function(position) {
@@ -25,9 +25,6 @@ ocargo.Model = function(nodeData, origin, destinations, trafficLightData, cowDat
25
25
  // false if evaluation of conditions etc. should be hidden from user.
26
26
  // used for evaluation of event handlers before each statement.
27
27
  this.shouldObserve = true;
28
-
29
- this.soundedHorn = {};
30
- this.puffedUp = {};
31
28
  };
32
29
 
33
30
  // Resets the entire model to how it was when it was just constructed
@@ -47,23 +44,11 @@ ocargo.Model.prototype.reset = function() {
47
44
  this.cows[j].reset();
48
45
  }
49
46
 
50
- // Display cow on origin node if exists
51
- var node = this.map.originCurrentNode;
52
- this.setCowsActive(node);
53
-
54
47
  this.timestamp = 0;
55
48
  this.movementTimestamp = 0;
56
49
  this.reasonForTermination = null;
57
- this.soundedHorn = {};
58
- this.puffedUp = {};
59
50
  };
60
51
 
61
- // Randomly chooses the cow positions, called by program.js
62
- ocargo.Model.prototype.chooseNewCowPositions = function() {
63
- for (var j = 0; j < this.cows.length; j++) {
64
- this.cows[j].chooseNewCowPositions();
65
- }
66
- };
67
52
 
68
53
  ///////////////////////
69
54
  // Begin observation function, each tests something about the model
@@ -103,18 +88,9 @@ ocargo.Model.prototype.isDeadEnd = function() {
103
88
  };
104
89
 
105
90
  ocargo.Model.prototype.isCowCrossing = function(type) {
106
- var result = false;
91
+ const currentNode = this.van.getPosition().currentNode;
107
92
  this.observe('cow crossing');
108
- var node = this.van.getPosition().currentNode;
109
- var nodes = this.getNodesAhead(node);
110
- for (var i = 0 ; i < nodes.length ; i++) {
111
- var cow = this.getCowForNode(nodes[i], ocargo.Cow.ACTIVE);
112
- if (cow != null && cow.type == type && cow.triggerEvent) {
113
- cow.triggerEvent = false;
114
- result = true;
115
- }
116
- }
117
- return result;
93
+ return this.getCowForNode(currentNode, [ocargo.Cow.ACTIVE, ocargo.Cow.READY]);
118
94
  };
119
95
 
120
96
  ocargo.Model.prototype.isTrafficLightRed = function() {
@@ -150,12 +126,12 @@ ocargo.Model.prototype.getPreviousCoordinate = function() {
150
126
  // true if it was a valid action or false otherwise
151
127
 
152
128
  ocargo.Model.prototype.moveVan = function(nextNode, action) {
153
- //Crash?
154
- let previousNodeCow = this.getCowForNode(this.van.getPosition().currentNode, ocargo.Cow.ACTIVE);
155
- let collisionWithCow = previousNodeCow && nextNode !== this.van.getPosition().currentNode;
129
+ // Crash?
130
+ let checkedNode = action == "WAIT" ? this.van.getPosition().previousNode : this.van.getPosition().currentNode
131
+ let currentNodeHasCow = this.getCowForNode(checkedNode, [ocargo.Cow.ACTIVE, ocargo.Cow.READY]);
156
132
 
157
- if (collisionWithCow) {
158
- handleCrash(this, gettext('You ran into a cow! Keep in mind that cows can appear anywhere on the map.'),
133
+ if (currentNodeHasCow) {
134
+ handleCrash(this, gettext('You ran into a cow! '),
159
135
  'COLLISION_WITH_COW', 'collision with cow van move action: ');
160
136
  return false;
161
137
  }
@@ -186,11 +162,13 @@ ocargo.Model.prototype.moveVan = function(nextNode, action) {
186
162
 
187
163
  ocargo.game.sendAttempt(0);
188
164
 
165
+ let noFuelMessage = CHARACTER_NAME == "Electric van" ? 'Your battery ran out of charge!' : 'You ran out of fuel!'
166
+
189
167
  ocargo.animation.appendAnimation({
190
168
  type: 'popup',
191
169
  popupType: 'FAIL',
192
170
  failSubtype: 'OUT_OF_FUEL',
193
- popupMessage: gettext('You ran out of fuel! Try to find a shorter route to the destination.'),
171
+ popupMessage: gettext(noFuelMessage + ' Try to find a shorter route to the destination.'),
194
172
  popupHint: ocargo.game.registerFailure(),
195
173
  description: 'no fuel popup'
196
174
  });
@@ -252,9 +230,6 @@ ocargo.Model.prototype.moveVan = function(nextNode, action) {
252
230
  return false;
253
231
  }
254
232
 
255
- // Display cow on node if exists
256
- this.setCowsActive(nextNode);
257
-
258
233
  this.van.move(nextNode);
259
234
 
260
235
  // Van movement animation
@@ -315,16 +290,6 @@ ocargo.Model.prototype.moveVan = function(nextNode, action) {
315
290
  }
316
291
  };
317
292
 
318
- ocargo.Model.prototype.setCowsActive = function(nextNode) {
319
- var nodes = this.getNodesAhead(nextNode);
320
- for (var i = 0 ; i < nodes.length ; i++){
321
- var cow = this.getCowForNode(nodes[i], ocargo.Cow.READY);
322
- if (cow){
323
- cow.setActive(this, nodes[i]);
324
- }
325
- }
326
- };
327
-
328
293
  ocargo.Model.prototype.makeDelivery = function(destination) {
329
294
  // We're at a destination node and making a delivery!
330
295
  destination.visited = true;
@@ -422,62 +387,50 @@ ocargo.Model.prototype.deliver = function() {
422
387
  return false;
423
388
  }
424
389
  this.makeDelivery(destination, 'DELIVER');
390
+ } else {
391
+ ocargo.game.sendAttempt(0);
392
+ ocargo.animation.appendAnimation({
393
+ type: 'popup',
394
+ popupType: 'FAIL',
395
+ failSubtype: 'DELIVER_NON_DESTINATION',
396
+ popupMessage: gettext("You tried to deliver to a destination that doesn't exist."),
397
+ popupHint: ocargo.game.registerFailure(),
398
+ description: 'tried to deliver at non-destination'
399
+ });
400
+
401
+ ocargo.animation.appendAnimation({
402
+ type: 'callable',
403
+ functionType: 'playSound',
404
+ functionCall: ocargo.sound.failure,
405
+ description: 'failure sound'
406
+ });
407
+
408
+ ocargo.event.sendEvent("DeliverNonDestination", { levelName: LEVEL_NAME,
409
+ defaultLevel: DEFAULT_LEVEL,
410
+ workspace: ocargo.blocklyControl.serialize(),
411
+ failures: this.failures,
412
+ pythonWorkspace: ocargo.pythonControl.getCode()
413
+ });
414
+ this.reasonForTermination = 'DELIVER_AT_NON_DESTINATION';
415
+ return false;
425
416
  }
426
417
  return destination;
427
418
  };
428
419
 
429
420
  ocargo.Model.prototype.sound_horn = function() {
430
- this.soundedHorn = {timestamp:this.movementTimestamp, coordinates:this.getCurrentCoordinate()};
421
+ const currentNode = this.van.getPosition().currentNode
431
422
  ocargo.animation.appendAnimation({
432
423
  type: 'callable',
433
424
  functionType: 'playSound',
434
425
  functionCall: ocargo.sound.sound_horn,
435
426
  description: 'van sound: sounding the horn'
436
427
  });
437
-
438
- return true;
439
- };
440
-
441
- ocargo.Model.prototype.puff_up = function(){
442
- if(!jQuery.isEmptyObject(this.puffedUp)){
443
- return this.remain_puff_up();
444
- }else{
445
- this.van.puffUp();
446
- this.puffedUp = {timestamp:this.movementTimestamp, coordinates:this.getCurrentCoordinate(), timeout:1};
447
- ocargo.animation.appendAnimation({
448
- type: 'van',
449
- vanAction: 'PUFFUP',
450
- fuel: this.van.getFuelPercentage(),
451
- description: 'van move action: puff up'
452
- });
453
- return this.puff_down();
428
+ let cow = this.getCowForNode(currentNode, [ocargo.Cow.ACTIVE, ocargo.Cow.READY]);
429
+ if (cow) {
430
+ cow.queueLeaveAnimation(this, currentNode);
431
+ cow.setInactive(this, currentNode);
454
432
  }
455
-
456
- };
457
-
458
- ocargo.Model.prototype.remain_puff_up = function(){
459
- this.puffedUp.coordinates = this.getCurrentCoordinate();
460
- this.puffedUp.timeout++;
461
-
462
- ocargo.animation.appendAnimation({
463
- type: 'van',
464
- vanAction: 'REMAINPUFFUP',
465
- fuel: this.van.getFuelPercentage(),
466
- description: 'van move action: remain puff up'
467
- });
468
-
469
- return true;
470
- };
471
-
472
- ocargo.Model.prototype.puff_down = function(){
473
-
474
- ocargo.animation.appendAnimation({
475
- type: 'van',
476
- vanAction: 'PUFFDOWN',
477
- fuel: this.van.getFuelPercentage(),
478
- description: 'van move action: puff down'
479
- });
480
-
433
+ this.moveVan(this.van.getPosition().currentNode, 'SOUND_HORN');
481
434
  return true;
482
435
  };
483
436
 
@@ -616,6 +569,7 @@ ocargo.Model.prototype.programExecutionEnded = function () {
616
569
  // A helper function which returns the traffic light associated
617
570
  // with a particular node and orientation
618
571
  ocargo.Model.prototype.getTrafficLightForNode = function(position) {
572
+
619
573
  for (var i = 0; i < this.trafficLights.length; i++) {
620
574
  var light = this.trafficLights[i];
621
575
  if (light.sourceNode === position.previousNode && light.controlledNode === position.currentNode) {
@@ -636,12 +590,21 @@ ocargo.Model.prototype.getDestinationForNode = function(node) {
636
590
  return null;
637
591
  };
638
592
 
639
- ocargo.Model.prototype.getCowForNode = function(node, status) {
593
+ ocargo.Model.prototype.getCowForNode = function(node, state) {
640
594
  var jsonCoordinate = JSON.stringify(node.coordinate);
641
595
  for(var i = 0; i < this.cows.length; i++) {
642
596
  var cow = this.cows[i];
643
- if (jsonCoordinate in cow.activeNodes && cow.activeNodes[jsonCoordinate] == status) {
644
- return cow;
597
+ if (jsonCoordinate in cow.activeNodes) {
598
+ if (state === undefined){
599
+ return cow;
600
+ } else {
601
+ if (typeof(state) === "string") {
602
+ state = [state];
603
+ }
604
+ if (state.includes(cow.activeNodes[jsonCoordinate])) {
605
+ return cow;
606
+ }
607
+ }
645
608
  }
646
609
  }
647
610
  return null;
@@ -660,7 +623,6 @@ ocargo.Model.prototype.incrementTime = function() {
660
623
 
661
624
  ocargo.animation.startNewTimestamp();
662
625
 
663
- this.incrementCowTime();
664
626
  };
665
627
 
666
628
  ocargo.Model.prototype.incrementTrafficLightsTime = function() {
@@ -669,19 +631,6 @@ ocargo.Model.prototype.incrementTrafficLightsTime = function() {
669
631
  }
670
632
  };
671
633
 
672
- ocargo.Model.prototype.incrementCowTime = function() {
673
- if(this.movementTimestamp - this.puffedUp.timestamp > this.puffedUp.timeout){
674
- this.puffedUp = {};
675
- this.van.puffDown();
676
- }
677
-
678
- for (var i = 0; i < this.cows.length; i++) {
679
- this.cows[i].incrementTime(this);
680
- }
681
- this.soundedHorn = {};
682
-
683
- };
684
-
685
634
  ocargo.Model.prototype.getNodesAhead = function(node) {
686
635
  var nodes = [];
687
636
  for (var i = 0 ; i < node.connectedNodes.length ; i++){
@@ -695,4 +644,3 @@ ocargo.Model.prototype.getNodesAhead = function(node) {
695
644
  ocargo.Model.prototype.startingPosition = function() {
696
645
  return this.map.startingPosition();
697
646
  };
698
-