SNT

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

lvl10.html (10062B)


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