lvl12.html (8557B)
1 <head> 2 3 <meta charset="utf-8"/> 4 5 <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"/> 6 7 <style> 8 h1,h2 { 9 font-family: Sans; 10 } 11 12 .stderr { 13 background-color: #fee; 14 color: #900; 15 } 16 17 .stderr, .stdout { 18 /* display: contents; */ /* uncomment to make print( end='') work */ 19 margin: 0px; 20 padding: 0px 0.3em; 21 } 22 23 .console { 24 max-height: 20em; 25 overflow: auto; 26 border: medium solid black; 27 } 28 29 .console:empty { 30 display: none; 31 } 32 33 #feedback { 34 border: solid #aaa; 35 background-color: #eee; 36 } 37 38 #feedback:empty { 39 display: none; 40 } 41 42 #edcontainer { 43 display: flex; 44 } 45 .edcolumn { 46 flex: 50%; 47 } 48 #breditor { 49 width: 100%; 50 } 51 52 53 </style> 54 55 <!-- 56 <script src="https://cdn.jsdelivr.net/npm/phaser@3.55.0/dist/phaser.min.js"></script> 57 <script src="https://unpkg.com/brython@3.9.3/brython.js"></script> 58 <script src="https://unpkg.com/brython@3.9.3/brython_stdlib.js"></script> 59 <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.min.js"></script> 60 <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/mode-python.min.js"></script> 61 --> 62 <script src="lib/phaser/phaser.min.js"></script> 63 <script src="lib/brython/brython.js"></script> 64 <script src="lib/brython/brython_stdlib.js"></script> 65 <script src="lib/ace/ace.js"></script> 66 <script src="lib/ace/mode-python.js"></script> 67 68 69 <script type="text/javascript"> 70 71 code = "# Le retour ..."; 72 73 score = 0; 74 75 API = window.API || window.parent.API; 76 77 function loadSCO() { 78 if (API) { 79 API.LMSInitialize(""); 80 81 suspend_data = API.LMSGetValue("cmi.suspend_data"); 82 83 if (suspend_data) { 84 code = suspend_data; 85 } 86 } 87 } 88 89 function sendSCO() { 90 if (API) { 91 API.LMSSetValue("cmi.core.score.raw", score); 92 API.LMSSetValue("cmi.suspend_data", code); 93 API.LMSSetValue("cmi.core.score.lesson_status", "completed"); 94 95 API.LMSCommit(""); 96 } 97 } 98 99 function nextSCO() { 100 if (API) { 101 API.LMSSetValue("nav.event","continue"); // Probably Moodle specific 102 API.LMSFinish(""); 103 } 104 } 105 106 // Phaser stuff 107 108 var tilesize = 32; 109 var delay = 250; 110 111 var movetime = 0; 112 var delayed_moves = []; 113 114 var config = { 115 type: Phaser.AUTO, 116 width: tilesize*10, 117 height: tilesize*10, 118 parent: "game", 119 scene: { 120 preload: preload, 121 create: create 122 } 123 }; 124 125 function preload() { 126 this.load.image("tilemap", "img/tilemap.png") 127 this.load.image("bot", "img/bot.png") 128 this.load.tilemapCSV('map', 'lvl/lvl12.csv'); 129 } 130 131 function create() { 132 map = this.make.tilemap({ key: 'map', tileWidth: 32, tileHeight: 32 }); 133 var tileset = map.addTilesetImage('tilemap'); 134 layer = map.createLayer(0, tileset, 0, 0); 135 136 bot = this.add.image(tilesize * 1.5, tilesize * 1.5, "bot") 137 } 138 139 function get_tile_at(x,y) { 140 return layer.getTileAtWorldXY(x*tilesize, y*tilesize, true).index; 141 } 142 143 function reset_board() { 144 movetime = 0; 145 bot.x = tilesize * 1.5; 146 bot.y = tilesize * 1.5; 147 bot.angle = 0; 148 149 for (move of delayed_moves){ 150 clearTimeout(move) 151 } 152 153 delayed_moves = [] 154 } 155 156 function move_left() { 157 delayed_moves.push( 158 setTimeout( 159 function() { 160 bot.x -= tilesize; 161 bot.angle = 180; 162 }, movetime) 163 ); 164 movetime += delay; 165 } 166 167 function move_right() { 168 delayed_moves.push( 169 setTimeout( 170 function() { 171 bot.x += tilesize; 172 bot.angle = 0; 173 }, movetime) 174 ); 175 movetime += delay; 176 } 177 178 function move_up() { 179 delayed_moves.push( 180 setTimeout( 181 function() { 182 bot.y -= tilesize; 183 bot.angle = -90; 184 }, movetime) 185 ); 186 movetime += delay; 187 } 188 189 function move_down() { 190 delayed_moves.push( 191 setTimeout( 192 function() { 193 bot.y += tilesize; 194 bot.angle = 90; 195 }, movetime) 196 ); 197 movetime += delay; 198 } 199 200 window.onload = function() { 201 loadSCO(); 202 document.getElementById("code").textContent = code; 203 204 game = new Phaser.Game(config); 205 206 brython(); 207 } 208 </script> 209 210 <script type="text/python"> 211 # Requires Brython and Ace editor 212 213 from browser import document, window, html 214 from sys import stderr, stdout, settrace 215 from traceback import print_exc, extract_stack, extract_tb 216 217 def make_max_line_tracer(maxlines): 218 lines = 0 219 def tracer(frame, event, arg): 220 nonlocal lines 221 if event == 'line': 222 lines += 1 223 if lines >= maxlines: 224 raise TimeoutError 225 return tracer 226 return tracer 227 228 def exec_code(editor, id): 229 reset() 230 feedback("Le drapeau n'est pas encore atteint") 231 232 code_lines = editor.session.getLength() 233 if code_lines > max_code_lines: 234 feedback("Trop de lignes utilisées ( " + str(code_lines) + "/" + str(max_code_lines) + ")") 235 return 236 237 console = document[id + "_console"] 238 console.clear() 239 stderr.write = lambda data : console_target(data, console, True) 240 stdout.write = lambda data : console_target(data, console) 241 242 code = editor.getValue() 243 try: 244 compiled = compile(code, "<" + id + ">", "exec") 245 except SyntaxError: 246 print_exc(limit=0) 247 return 248 249 settrace(make_max_line_tracer(10000)) # increase to allow longer execution 250 try: 251 exec(code) 252 except TimeoutError: 253 settrace(None) 254 print("L'exécution prend trop de temps, abandon.", file=stderr) 255 except Exception as e: 256 settrace(None) 257 tb_len = len(extract_tb(e.__traceback__)) - len(extract_stack()) 258 print_exc(limit=-tb_len) 259 finally: 260 settrace(None) 261 262 window.code = code 263 #window.score = check() 264 window.sendSCO() 265 266 def console_target(data, elt, err=False): 267 elt <= html.PRE(data, Class="stderr" if err else "stdout") 268 elt.scrollTop = elt.scrollHeight 269 270 breditors = document.select(".breditor") 271 272 max_code_lines = 20 273 274 for ed_elt in breditors: 275 editor = window.ace.edit(ed_elt.id) 276 editor.session.setMode("ace/mode/python") 277 #editor.setOption('fontSize', '14px') 278 editor.setOption('maxLines', max_code_lines) 279 editor.setOption('minLines', max_code_lines) 280 281 console = html.DIV(Class="console", id=ed_elt.id + "_console") 282 283 ed_elt.insertAdjacentElement('afterend', console) 284 285 exec_button = html.BUTTON("Exécuter →") 286 exec_button.bind("click", lambda ev : exec_code(editor, ed_elt.id)) 287 ed_elt.insertAdjacentElement('afterend', exec_button) 288 289 def feedback(msg): 290 document["feedback"].clear() 291 document["feedback"] <= msg 292 293 coords = [1,1] 294 295 def reset(): 296 global coords 297 window.reset_board() 298 coords = [1,1] 299 300 def gauche(): 301 if coords[0] >= 0: 302 tile = window.get_tile_at(coords[0]-1, coords[1]) 303 if tile in (0,1,3): 304 window.move_left() 305 coords[0] -= 1 306 if tile == 1: 307 win() 308 elif tile == 3: 309 fall() 310 311 def droite(): 312 if coords[0] < 10: 313 tile = window.get_tile_at(coords[0]+1, coords[1]) 314 if tile in (0,1,3): 315 window.move_right() 316 coords[0] += 1 317 if tile == 1: 318 win() 319 elif tile == 3: 320 fall() 321 322 def haut(): 323 if coords[1] >= 0: 324 tile = window.get_tile_at(coords[0], coords[1]-1) 325 if tile in (0,1,3): 326 window.move_up() 327 coords[1] -= 1 328 if tile == 1: 329 win() 330 elif tile == 3: 331 fall() 332 333 def bas(): 334 if coords[1] < 10: 335 tile = window.get_tile_at(coords[0], coords[1]+1) 336 if tile in (0,1,3): 337 window.move_down() 338 coords[1] += 1 339 if tile == 1: 340 win() 341 elif tile == 3: 342 fall() 343 344 def fall(): 345 feedback("Le robot est tombé dans le vide !") 346 raise Exception("Le robot est tombé dans le vide") 347 348 349 def win(): 350 window.score = 100 351 feedback("Bravo !") 352 document["feedback"] <= html.BUTTON("Passer à la suite", onclick="nextSCO();") 353 354 355 </script> 356 357 </head> 358 359 <body> 360 361 <h1>Niveau 12</h1> 362 363 Vous disposez des fonctions 364 <code>droite()</code>, 365 <code>gauche()</code>, 366 <code>haut()</code>, et 367 <code>bas()</code> 368 pour faire avancer le robot. 369 370 <div id="edcontainer"> 371 <div class="edcolumn"> 372 Code python : 373 <pre id="code" class="breditor"></pre> 374 <div id="feedback"></div> 375 </div> 376 <div class="edcolumn"> 377 Plateau : 378 <div id="game"></div> 379 </div> 380 </div> 381 382 383 384 385 386 387 </body> 388 </html>