SNT

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

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>