SNT

Cours de SNT
git clone git://git.vgx.fr/SNT
Log | Files | Refs

lvl4.html (10319B)


      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 <script src="https://cdn.jsdelivr.net/npm/phaser@3.55.0/dist/phaser.min.js"></script>
     56 <script src="https://unpkg.com/brython@3.9.3/brython.js"></script>
     57 <script src="https://unpkg.com/brython@3.9.3/brython_stdlib.js"></script>
     58 <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.min.js"></script>
     59 <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/mode-python.min.js"></script>
     60 
     61 <script type="text/javascript">
     62 
     63 code = "# Écrivez votre code python ici :\nprint(\"Bonjour !\")";
     64 
     65 score = 0;
     66 
     67 API = window.API || window.parent.API;
     68 
     69 function loadSCO() {
     70     if (API) {
     71         API.LMSInitialize("");
     72 
     73         suspend_data = API.LMSGetValue("cmi.suspend_data");
     74 
     75         if (suspend_data) {
     76             code = suspend_data;
     77         }
     78     }
     79 }
     80 
     81 function sendSCO() {
     82     if (API) {
     83         API.LMSSetValue("cmi.core.score.raw", score);
     84         API.LMSSetValue("cmi.suspend_data", code);
     85         API.LMSSetValue("cmi.core.score.lesson_status", "completed");
     86 
     87         API.LMSCommit("");
     88     }
     89 }
     90 
     91 function nextSCO() {
     92     if (API) {
     93         API.LMSSetValue("nav.event","continue"); // Probably Moodle specific
     94         API.LMSFinish("");
     95     }
     96 }
     97 
     98 // Phaser stuff
     99 
    100 var tilesize = 32;
    101 var delay = 250;
    102 
    103 var tiles = [];
    104 
    105 var movetime = 0;
    106 var delayed_moves = [];
    107 
    108 var config = {
    109     type: Phaser.AUTO,
    110     width: tilesize*10,
    111     height: tilesize*10,
    112     parent: "game",
    113     scene: {
    114         preload: preload,
    115         create: create
    116     }
    117 };
    118 
    119 function preload() {
    120     this.load.image("tilemap", "img/tilemap.png")
    121     this.load.image("bot", "img/bot.png")
    122     this.load.tilemapCSV('map', 'lvl/lvl4.csv');
    123 }
    124 
    125 function create() {
    126     map = this.make.tilemap({ key: 'map', tileWidth: 32, tileHeight: 32 });
    127     var tileset = map.addTilesetImage('tilemap');
    128     layer = map.createLayer(0, tileset, 0, 0);
    129     
    130     bot = this.add.image(tilesize * 1.5, tilesize * 1.5, "bot");
    131 }
    132 
    133 function gen_tiles() {
    134     for (var i = 0 ; i < 10 ; i++) {
    135         tiles[i] = [];
    136         for (var j = 0 ; j < 10 ; j++) {
    137             var id = map.getTileAt(i,j).index;
    138             if (id == 4)
    139                 id = 3;
    140             tiles[i][j] = id;
    141         }
    142     }
    143 
    144     if (Math.random()<0.5)
    145         tiles[1][2] = 0;
    146     else
    147         tiles[5][2] = 0;
    148 
    149     if (Math.random()<0.5) {
    150         tiles[2][3] = 0;
    151         tiles[4][3] = 0;
    152     } else {
    153         tiles[2][5] = 0;
    154         tiles[4][5] = 0;
    155     }
    156 }
    157 
    158 function get_tile_at(x,y) {
    159     return tiles[x][y];
    160 }
    161 
    162 function reset_board() {
    163     movetime = 0;
    164     bot.x = tilesize * 1.5;
    165     bot.y = tilesize * 1.5;
    166     bot.angle = 0;
    167 
    168     for (move of delayed_moves){
    169         clearTimeout(move)
    170     }
    171 
    172     delayed_moves = []
    173 
    174     gen_tiles()
    175 }
    176 
    177 function move_left() {
    178     delayed_moves.push(
    179         setTimeout(
    180             function() {
    181                 bot.x -= tilesize;
    182                 bot.angle = 180;
    183             }, movetime)
    184         );
    185     movetime += delay;
    186 }
    187 
    188 function move_right() {
    189     delayed_moves.push(
    190         setTimeout(
    191             function() {
    192                 bot.x += tilesize;
    193                 bot.angle = 0;
    194             }, movetime)
    195         );
    196     movetime += delay;
    197 }
    198 
    199 function move_up() {
    200     delayed_moves.push(
    201         setTimeout(
    202             function() {
    203                 bot.y -= tilesize;
    204                 bot.angle = -90;
    205             }, movetime)
    206         );
    207     movetime += delay;
    208 }
    209 
    210 function move_down() {
    211     delayed_moves.push(
    212         setTimeout(
    213             function() {
    214                 bot.y += tilesize;
    215                 bot.angle = 90;
    216             }, movetime)
    217         );
    218     movetime += delay;
    219 }
    220 
    221 window.onload = function() {
    222     loadSCO();
    223     document.getElementById("code").textContent = code;
    224 
    225     game = new Phaser.Game(config);
    226     
    227     brython();
    228 }
    229 </script>
    230 
    231 <script type="text/python">
    232 # Requires Brython and Ace editor
    233 
    234 from browser import document, window, html
    235 from sys import stderr, stdout, settrace
    236 from traceback import print_exc, extract_stack, extract_tb
    237 
    238 def make_max_line_tracer(maxlines):
    239     lines = 0
    240     def tracer(frame, event, arg):
    241         nonlocal lines
    242         if event == 'line':
    243             lines += 1
    244             if lines >= maxlines:
    245                 raise TimeoutError
    246         return tracer
    247     return tracer
    248 
    249 def exec_code(editor, id):
    250     reset()
    251     feedback("Le drapeau n'est pas encore atteint")
    252 
    253     code_lines = editor.session.getLength()
    254     if code_lines > max_code_lines:
    255         feedback("Trop de lignes utilisées ( " + str(code_lines) + "/" + str(max_code_lines) + ")")
    256         return
    257     
    258     console = document[id + "_console"]
    259     console.clear()
    260     stderr.write = lambda data : console_target(data, console, True)
    261     stdout.write = lambda data : console_target(data, console)
    262 
    263     code = editor.getValue()
    264     try:
    265         compiled = compile(code, "<" + id + ">", "exec")
    266     except SyntaxError:
    267         print_exc(limit=0)
    268         return
    269 
    270     settrace(make_max_line_tracer(10000)) # increase to allow longer execution
    271     try:
    272         exec(code)
    273     except TimeoutError:
    274         settrace(None)
    275         print("L'exécution prend trop de temps, abandon.", file=stderr)
    276     except Exception as e:
    277         settrace(None)
    278         tb_len = len(extract_tb(e.__traceback__)) - len(extract_stack())
    279         print_exc(limit=-tb_len)
    280     finally:
    281         settrace(None)
    282 
    283     window.code = code
    284     #window.score = check()
    285     window.sendSCO()
    286 
    287 def console_target(data, elt, err=False):
    288     elt <= html.PRE(data, Class="stderr" if err else "stdout")
    289     elt.scrollTop = elt.scrollHeight
    290 
    291 breditors = document.select(".breditor")
    292 
    293 max_code_lines = 30
    294 
    295 for ed_elt in breditors:
    296     editor = window.ace.edit(ed_elt.id)
    297     editor.session.setMode("ace/mode/python")
    298     #editor.setOption('fontSize', '14px')
    299     editor.setOption('maxLines', max_code_lines)
    300     editor.setOption('minLines', max_code_lines)
    301 
    302     console = html.DIV(Class="console", id=ed_elt.id + "_console")
    303 
    304     ed_elt.insertAdjacentElement('afterend', console)
    305 
    306     exec_button = html.BUTTON("Exécuter →")
    307     exec_button.bind("click", lambda ev : exec_code(editor, ed_elt.id))
    308     ed_elt.insertAdjacentElement('afterend', exec_button)
    309 
    310 def feedback(msg):
    311     document["feedback"].clear()
    312     document["feedback"] <= msg
    313 
    314 coords = [1,1]
    315 
    316 def reset():
    317     global coords
    318     window.reset_board()
    319     coords = [1,1]
    320 
    321 def gauche():
    322     if coords[0] >= 0:
    323         tile = window.get_tile_at(coords[0]-1, coords[1])
    324         if tile in (0,1,3):
    325             window.move_left()
    326             coords[0] -= 1
    327             if tile == 1:
    328                 win()
    329             elif tile == 3:
    330                 fall()
    331 
    332 def droite():
    333     if coords[0] < 10:
    334         tile = window.get_tile_at(coords[0]+1, coords[1])
    335         if tile in (0,1,3):
    336             window.move_right()
    337             coords[0] += 1
    338             if tile == 1:
    339                 win()
    340             elif tile == 3:
    341                 fall()
    342 
    343 def haut():
    344     if coords[1] >= 0:
    345         tile = window.get_tile_at(coords[0], coords[1]-1)
    346         if tile in (0,1,3):
    347             window.move_up()
    348             coords[1] -= 1
    349             if tile == 1:
    350                 win()
    351             elif tile == 3:
    352                 fall()
    353 
    354 def bas():
    355     if coords[1] < 10:
    356         tile = window.get_tile_at(coords[0], coords[1]+1)
    357         if tile in (0,1,3):
    358             window.move_down()
    359             coords[1] += 1
    360             if tile == 1:
    361                 win()
    362             elif tile == 3:
    363                 fall()
    364 
    365 
    366 def voir_gauche():
    367     if coords[0] == 0:
    368         return 3
    369     else:
    370         return voir(coords[0]-1, coords[1])
    371 
    372 def voir_droite():
    373     if coords[0] == 10:
    374         return 3
    375     else:
    376         return voir(coords[0]+1, coords[1])
    377 
    378 def voir_haut():
    379     if coords[1] == 0:
    380         return 3
    381     else:
    382         return voir(coords[0], coords[1]-1)
    383 
    384 def voir_bas():
    385     if coords[1] == 10:
    386         return 3
    387     else:
    388         return voir(coords[0], coords[1]+1)
    389 
    390 def voir(x,y):
    391     return window.get_tile_at(x,y)
    392 
    393 def fall():
    394     feedback("Le robot est tombé dans le vide !")
    395     raise Exception("Le robot est tombé dans le vide")
    396     
    397 
    398 def win():
    399     window.score = 100
    400     feedback("Ça a l'air correct, mais exécutez plusieur fois pour voir si ça marche aussi dans d'autres cas.")
    401     document["feedback"] <= html.BUTTON("Passer à la suite", onclick="nextSCO();")
    402     
    403 
    404 </script>
    405 
    406 </head>
    407 
    408 <body>
    409 
    410 <h1>Niveau 4</h1>
    411 
    412 Vous disposez des fonctions
    413 <code>droite()</code>,
    414 <code>gauche()</code>,
    415 <code>haut()</code>, et
    416 <code>bas()</code>
    417 pour faire avancer le robot.
    418 
    419 </br>
    420 
    421 Vous pouvez aussi utiliser 
    422 <code>voir_droite()</code>,
    423 <code>voir_gauche()</code>,
    424 <code>voir_haut()</code>, et
    425 <code>voir_bas()</code>
    426 pour regarder les cases autour de vous,
    427 ces fonctions renvoient le type de la case :
    428 <ul>
    429     <li>0 pour un chemin</li>
    430     <li>1 pour une arrivée</li>
    431     <li>2 pour un mur</li>
    432     <li>3 pour du vide</li>
    433 </ul>
    434 
    435 <p>
    436 Les cases point d'interrogation ont un type caché qui est révélé
    437 losqu'on les regarde.
    438 </p>
    439 
    440 <p>
    441 Vous pouvez, si besoin, mettre un bloc if dans un bloc if ou else.
    442 </p>
    443 
    444 <!-- <p>
    445 Si on a envie de mettre un nouveau if dans la partie else,
    446 on peut utiliser le mot clé elif, exemple :
    447 <pre><code># ce code
    448 if voir_haut() == 0:
    449     haut()
    450 else:
    451     if voir_droite() == 0:
    452         droite()
    453 
    454 # est équivalent à ce code :
    455 if voir_haut() == 0:
    456     haut()
    457 elif voir_droite() == 0:
    458     droite()
    459 
    460 </code></pre>
    461 </p>-->
    462 
    463 
    464 <div id="edcontainer">
    465     <div class="edcolumn">
    466         Code python :
    467         <pre id="code" class="breditor"></pre>
    468         <div id="feedback"></div>
    469     </div>
    470     <div class="edcolumn">
    471         Plateau :
    472         <div id="game"></div>
    473     </div>
    474 </div>
    475 
    476 
    477 
    478 
    479 
    480 
    481 </body>
    482 </html>