SNT

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

lvl4.html (10322B)


      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 = "print(\"plus de x :(\")\nprint(y)";
     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 var target_x = 0;
    110 var target_y = 0;
    111 
    112 var movetime = 0;
    113 var delayed_moves = [];
    114 
    115 var config = {
    116     type: Phaser.AUTO,
    117     width: tilesize*10,
    118     height: tilesize*10,
    119     parent: "game",
    120     scene: {
    121         preload: preload,
    122         create: create
    123     }
    124 };
    125 
    126 function preload() {
    127     this.load.image("tilemap", "img/tilemap.png")
    128     this.load.image("bot", "img/bot.png")
    129     this.load.tilemapCSV('map', 'lvl/lvl4.csv');
    130 }
    131 
    132 function create() {
    133     map = this.make.tilemap({ key: 'map', tileWidth: 32, tileHeight: 32 });
    134     var tileset = map.addTilesetImage('tilemap');
    135     layer = map.createLayer(0, tileset, 0, 0);
    136     
    137     bot = this.add.image(tilesize * 1.5, tilesize * 1.5, "bot");
    138 }
    139 
    140 function gen_tiles() {
    141     for (var i = 0 ; i < 10 ; i++) {
    142         tiles[i] = [];
    143         for (var j = 0 ; j < 10 ; j++) {
    144             var id = map.getTileAt(i,j).index;
    145             if (id == 4)
    146                 id = 0;
    147             tiles[i][j] = id;
    148         }
    149     }
    150 
    151     target_x = Math.floor(Math.random()*8);
    152     target_y = Math.floor(Math.random()*7)+1;
    153 
    154     var cnt = 0;
    155     for (var i = 1 ; i < 8 ; i++) {
    156         if (cnt < target_x && Math.random() < 0.5) {
    157             cnt++;
    158             tiles[i][0] = 1;
    159         } else {
    160             tiles[i][0] = 0;
    161         }
    162     }
    163     tiles[8][0] = target_x - cnt;
    164     tiles[target_x+1][target_y+1] = 1;
    165 }
    166 
    167 function get_tile_at(x,y) {
    168     return tiles[x][y];
    169 }
    170 
    171 function reset_board() {
    172     movetime = 0;
    173     bot.x = tilesize * 1.5;
    174     bot.y = tilesize * 1.5;
    175     bot.angle = 0;
    176 
    177     for (move of delayed_moves){
    178         clearTimeout(move)
    179     }
    180 
    181     delayed_moves = []
    182 
    183     gen_tiles()
    184 }
    185 
    186 function move_left() {
    187     delayed_moves.push(
    188         setTimeout(
    189             function() {
    190                 bot.x -= tilesize;
    191                 bot.angle = 180;
    192             }, movetime)
    193         );
    194     movetime += delay;
    195 }
    196 
    197 function move_right() {
    198     delayed_moves.push(
    199         setTimeout(
    200             function() {
    201                 bot.x += tilesize;
    202                 bot.angle = 0;
    203             }, movetime)
    204         );
    205     movetime += delay;
    206 }
    207 
    208 function move_up() {
    209     delayed_moves.push(
    210         setTimeout(
    211             function() {
    212                 bot.y -= tilesize;
    213                 bot.angle = -90;
    214             }, movetime)
    215         );
    216     movetime += delay;
    217 }
    218 
    219 function move_down() {
    220     delayed_moves.push(
    221         setTimeout(
    222             function() {
    223                 bot.y += tilesize;
    224                 bot.angle = 90;
    225             }, movetime)
    226         );
    227     movetime += delay;
    228 }
    229 
    230 window.onload = function() {
    231     loadSCO();
    232     document.getElementById("code").textContent = code;
    233 
    234     game = new Phaser.Game(config);
    235     
    236     brython();
    237 }
    238 </script>
    239 
    240 <script type="text/python">
    241 # Requires Brython and Ace editor
    242 
    243 from browser import document, window, html
    244 from sys import stderr, stdout, settrace
    245 from traceback import print_exc, extract_stack, extract_tb
    246 
    247 def make_max_line_tracer(maxlines):
    248     lines = 0
    249     def tracer(frame, event, arg):
    250         nonlocal lines
    251         if event == 'line':
    252             lines += 1
    253             if lines >= maxlines:
    254                 raise TimeoutError
    255         return tracer
    256     return tracer
    257 
    258 def exec_code(editor, id):
    259     global x, y
    260     reset()
    261     #x = window.target_x
    262     y = window.target_y
    263     
    264     feedback("Le drapeau n'est pas encore atteint")
    265 
    266     code_lines = editor.session.getLength()
    267     if code_lines > max_code_lines:
    268         feedback("Trop de lignes utilisées ( " + str(code_lines) + "/" + str(max_code_lines) + ")")
    269         return
    270     
    271     console = document[id + "_console"]
    272     console.clear()
    273     stderr.write = lambda data : console_target(data, console, True)
    274     stdout.write = lambda data : console_target(data, console)
    275 
    276     code = editor.getValue()
    277     try:
    278         compiled = compile(code, "<" + id + ">", "exec")
    279     except SyntaxError:
    280         print_exc(limit=0)
    281         return
    282 
    283     settrace(make_max_line_tracer(10000)) # increase to allow longer execution
    284     try:
    285         exec(code)
    286     except TimeoutError:
    287         settrace(None)
    288         print("L'exécution prend trop de temps, abandon.", file=stderr)
    289     except Exception as e:
    290         settrace(None)
    291         tb_len = len(extract_tb(e.__traceback__)) - len(extract_stack())
    292         print_exc(limit=-tb_len)
    293     finally:
    294         settrace(None)
    295 
    296     window.code = code
    297     #window.score = check()
    298     window.sendSCO()
    299 
    300 def console_target(data, elt, err=False):
    301     elt <= html.PRE(data, Class="stderr" if err else "stdout")
    302     elt.scrollTop = elt.scrollHeight
    303 
    304 breditors = document.select(".breditor")
    305 
    306 max_code_lines = 15
    307 
    308 for ed_elt in breditors:
    309     editor = window.ace.edit(ed_elt.id)
    310     editor.session.setMode("ace/mode/python")
    311     #editor.setOption('fontSize', '14px')
    312     editor.setOption('maxLines', max_code_lines)
    313     editor.setOption('minLines', max_code_lines)
    314 
    315     console = html.DIV(Class="console", id=ed_elt.id + "_console")
    316 
    317     ed_elt.insertAdjacentElement('afterend', console)
    318 
    319     exec_button = html.BUTTON("Exécuter →")
    320     exec_button.bind("click", lambda ev : exec_code(editor, ed_elt.id))
    321     ed_elt.insertAdjacentElement('afterend', exec_button)
    322 
    323 def feedback(msg):
    324     document["feedback"].clear()
    325     document["feedback"] <= msg
    326 
    327 coords = [1,1]
    328 
    329 def reset():
    330     global coords
    331     window.reset_board()
    332     coords = [1,1]
    333 
    334 def gauche():
    335     if coords[0] >= 0:
    336         move_to(coords[0]-1, coords[1], -1, 0, window.move_left)
    337 
    338 def droite():
    339     if coords[0] < 10:
    340         move_to(coords[0]+1, coords[1], 1, 0, window.move_right)
    341 
    342 def haut():
    343     if coords[1] >= 0:
    344         move_to(coords[0], coords[1]-1, 0, -1, window.move_up)
    345 
    346 def bas():
    347     if coords[1] < 10:
    348         move_to(coords[0], coords[1]+1, 0 , 1, window.move_down)
    349 
    350 def move_to(x, y, dx, dy, move):
    351     tile = window.get_tile_at(x, y)
    352     if tile in (0,1,3):
    353         move()
    354         coords[0] += dx
    355         coords[1] += dy
    356         if tile == 1:
    357             win()
    358         elif tile == 3:
    359             fall()
    360         else:
    361             feedback("Le robot n'est pas sur un drapeau")
    362             window.score = 0
    363     
    364 
    365 def voir_gauche():
    366     if coords[0] == 0:
    367         return 3
    368     else:
    369         return voir(coords[0]-1, coords[1])
    370 
    371 def voir_droite():
    372     if coords[0] == 10:
    373         return 3
    374     else:
    375         return voir(coords[0]+1, coords[1])
    376 
    377 def voir_haut():
    378     if coords[1] == 0:
    379         return 3
    380     else:
    381         return voir(coords[0], coords[1]-1)
    382 
    383 def voir_bas():
    384     if coords[1] == 10:
    385         return 3
    386     else:
    387         return voir(coords[0], coords[1]+1)
    388 
    389 def voir(x,y):
    390     return window.get_tile_at(x,y)
    391 
    392 def fall():
    393     feedback("Le robot est tombé dans le vide !")
    394     raise Exception("Le robot est tombé dans le vide")
    395     
    396 
    397 def win():
    398     window.score = 100
    399     feedback("Bravo ! (exécutez plusieurs fois avant de continuer)")
    400     document["feedback"] <= html.BUTTON("Passer à la suite", onclick="nextSCO();")
    401     
    402 
    403 </script>
    404 
    405 </head>
    406 
    407 <body>
    408 
    409 <h1>Niveau 4</h1>
    410 
    411 <p>
    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 </p>
    419 
    420 <p>
    421 Le drapeau est caché parmis ces points d'interrogation,
    422 mais cette fois-ci vous n'avez plus la variable
    423 <code>x</code>
    424 (la variable
    425 <code>y</code>
    426 est encore là).
    427 </p>
    428 
    429 <p>
    430 Les cases
    431 <code><i>i</i></code>
    432 contiennent un nombre qu'on peut voir en regardant leur contenu avec
    433 les fonctions
    434 <code>voir_droite()</code>,
    435 <code>voir_gauche()</code>,
    436 <code>voir_haut()</code>, ou
    437 <code>voir_bas()</code>.
    438 </p>
    439 
    440 <p>
    441 Cette fois-ci il faudra additionner le contenu de toutes les cases
    442 <code><i>i</i></code>
    443 du haut pour obtenir le déplacement x,
    444 puis revenir au point de départ pour appliquer ce déplacement.
    445 </p>
    446 
    447 <p>
    448 Exemples avec des variables :
    449 <pre><code># on crée des variables
    450 lol = 42
    451 lul = "truc"
    452 lel = lol + 2
    453 
    454 # on modifie des variables
    455 lol = 4
    456 lel = lel - 2
    457 
    458 # on utilise des variables
    459 print(lul)
    460 
    461 for i in range(lol):
    462     print("salut")
    463 
    464 if lel == 42:
    465    print("ok")
    466 </code></pre>
    467 </p>
    468 
    469 
    470 <div id="edcontainer">
    471     <div class="edcolumn">
    472         Code python :
    473         <pre id="code" class="breditor"></pre>
    474         <div id="feedback"></div>
    475     </div>
    476     <div class="edcolumn">
    477         Plateau :
    478         <div id="game"></div>
    479     </div>
    480 </div>
    481 
    482 </body>
    483 </html>