SNT

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

commit 2b315b0db3aa242d52a0bde577117b221de8a0bd
parent 989cd26b633718f26f91aa0352e0c606f7347514
Author: Léo Villeveygoux <l@vgx.fr>
Date:   Wed, 19 May 2021 20:16:55 +0200

Ajout de l'activité SCORM de programmation sur les cartes numériques

Diffstat:
Ageo/prog/.gitignore | 1+
Ageo/prog/Makefile | 3+++
Ageo/prog/cercle.html | 295+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ageo/prog/imsmanifest.xml | 59+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ageo/prog/meridien.html | 318+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ageo/prog/pays.html | 304+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ageo/prog/point.html | 286+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ageo/prog/random.html | 259+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ageo/prog/souris.html | 296+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ageo/prog/suivi.html | 311+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10 files changed, 2132 insertions(+), 0 deletions(-)

diff --git a/geo/prog/.gitignore b/geo/prog/.gitignore @@ -0,0 +1 @@ +prog_carto.zip diff --git a/geo/prog/Makefile b/geo/prog/Makefile @@ -0,0 +1,3 @@ +prog_carto.zip: imsmanifest.xml point.html pays.html meridien.html cercle.html souris.html suivi.html random.html + apack $@ $^ + diff --git a/geo/prog/cercle.html b/geo/prog/cercle.html @@ -0,0 +1,295 @@ +<head> + +<meta charset="utf-8"/> + +<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"/> + +<style> +h1,h2 { + font-family: Sans; +} + +.stderr { + background-color: #fee; + color: #900; +} + +.stderr, .stdout { + /* display: contents; */ /* uncomment to make print( end='') work */ + margin: 0px; + padding: 0px 0.3em; +} + +.console { + max-height: 20em; + overflow: auto; + border: medium solid black; +} + +.console:empty { + display: none; +} + +#feedback { + border: solid #aaa; + background-color: #eee; +} + +#feedback:empty { + display: none; +} + +</style> + +<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script> +<script src="https://unpkg.com/brython@3.9.3/brython.js"></script> +<script src="https://unpkg.com/brython@3.9.3/brython_stdlib.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.min.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/mode-python.min.js"></script> + +<script type="text/javascript"> + +code = "# Écrivez votre code python ici :\nprint(\"Bonjour !\")"; + +score = 0; + +API = window.API || window.parent.API; + +function loadSCO() { + if (API) { + API.LMSInitialize(""); + + suspend_data = API.LMSGetValue("cmi.suspend_data"); + + if (suspend_data) { + code = suspend_data; + } + } +} + +function sendSCO() { + if (API) { + API.LMSSetValue("cmi.core.score.raw", score); + API.LMSSetValue("cmi.suspend_data", code); + API.LMSSetValue("cmi.core.score.lesson_status", "completed"); + + API.LMSCommit(""); + } +} + +function nextSCO() { + if (API) { + API.LMSSetValue("nav.event","continue"); // Probably Moodle specific + API.LMSFinish(""); + } +} + +// Leaflet stuff + +cognac = [45.69, -0.32]; + +markers = []; +click_latlng = {"lat":45.69, "lng":-0.32}; +click_func = function() {}; + +function clear_map() { + while (markers.length > 0) { + markers.pop().remove(); + } +} + +function on_map_click(e) { + document.getElementById("lastclick").innerHTML = e.latlng.lat+", "+e.latlng.lng; + click_latlng = e.latlng; + click_func(); +} + +window.onload = function() { + loadSCO(); + document.getElementById("code").textContent = code; + + map = L.map('map').setView(cognac, 11); + L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map); + map.on("click", on_map_click); + + brython(); +} +</script> + +<script type="text/python"> +# Requires Brython and Ace editor + +from browser import document, window, html +from sys import stderr, stdout, settrace +from traceback import print_exc, extract_stack, extract_tb + +def make_max_line_tracer(maxlines): + lines = 0 + def tracer(frame, event, arg): + nonlocal lines + if event == 'line': + lines += 1 + if lines >= maxlines: + raise TimeoutError + return tracer + return tracer + +def exec_code(editor, id): + effacer() + + console = document[id + "_console"] + console.clear() + stderr.write = lambda data : console_target(data, console, True) + stdout.write = lambda data : console_target(data, console) + + code = editor.getValue() + try: + compiled = compile(code, "<" + id + ">", "exec") + except SyntaxError: + print_exc(limit=0) + return + + settrace(make_max_line_tracer(10000)) # increase to allow longer execution + try: + exec(code) + except TimeoutError: + settrace(None) + print("L'exécution prend trop de temps, abandon.", file=stderr) + except Exception as e: + settrace(None) + tb_len = len(extract_tb(e.__traceback__)) - len(extract_stack()) + print_exc(limit=-tb_len) + finally: + settrace(None) + + window.code = code + window.score = check() + window.sendSCO() + +def console_target(data, elt, err=False): + elt <= html.PRE(data, Class="stderr" if err else "stdout") + elt.scrollTop = elt.scrollHeight + +breditors = document.select(".breditor") + +for ed_elt in breditors: + editor = window.ace.edit(ed_elt.id) + editor.session.setMode("ace/mode/python") + #editor.setOption('fontSize', '14px') + editor.setOption('maxLines', 15) + + console = html.DIV(Class="console", id=ed_elt.id + "_console") + + ed_elt.insertAdjacentElement('afterend', console) + + exec_button = html.BUTTON("Exécuter →") + exec_button.bind("click", lambda ev : exec_code(editor, ed_elt.id)) + ed_elt.insertAdjacentElement('afterend', exec_button) + +def feedback(msg): + document["feedback"].clear() + document["feedback"] <= msg + +markers = window.markers +L = window.L +map = window.map + +def marqueur(lat, lon, message=None): + mark=L.marker((lat, lon)).addTo(map) + markers.append(mark) + + if message: + mark.bindPopup(message) + +def cercle(lat, lon, rad, col='red', message=None): + mark=L.circle((lat, lon), + {"color": col, + "fillColor": col, + "fillOpacity": 0.5, + "radius": rad} + ).addTo(map) + markers.append(mark) + + if message: + mark.bindPopup(message) + + +def dernier_clic(): + return window.click_latlng["lat"], window.click_latlng["lng"] + +def au_clic(func): + window.click_func = func + +def effacer(): + window.clear_map() + +def check(): + score = 0 + + if len(markers) == 0: + feedback("Aucun marqueur ou cercle placé") + else: + exists = False + radius = 0 + for m in markers: + if "_radius" in m: + radius = m.getRadius() + exists = True + if not exists: + score = 30 + feedback("Il y a des marqueurs, mais pas de cercle") + elif radius != 10000: + score = 60 + feedback("Le rayon ne fait pas 10km") + else: + score = 100 + feedback("Le cercle semble correct, bravo ! ") + document["feedback"] <= html.BUTTON("Passer à la suite", onclick="nextSCO();") + + return score + +</script> + +</head> + +<body> + +<h1>Un cercle</h1> + +<div> +On peut aussi afficher des cercles : on utilise +la fonction <code>cercle(latitude, longitude, rayon)</code> +(le rayon est donné en mètres). +Ou alors la variante +<code>cercle(latitude, longitude, rayon, couleur)</code> +où couleur une du texte (en anglais), exemple : +</div> +<pre><code>cercle(45.69, -0.32, 2000, 'blue') +</code></pre> +<div> +<b> +Écrivez le code python qui dessine un cercle de 10km autour de chez vous. +</b> +(même si les mesures sanitaires n'imposent plus d'y rester ...) +</div> +<div> +<i>On pourra encore se servir du fait que les coordonnées du clic sont +affichées sous la carte. +</i> +</div> + +<h2>Carte OpenStreetMap</h2> + +<div id = "map" style = "width: 900px; height: 580px"></div> + +<button onclick="clear_map();">Tout effacer sur la carte</button> +Coordonnées du dernier clic : +<span id="lastclick"></span> + +<h2>Code Python</h2> + +<pre id="code" class="breditor"></pre> +<div id="feedback"></div> + +</body> +</html> diff --git a/geo/prog/imsmanifest.xml b/geo/prog/imsmanifest.xml @@ -0,0 +1,59 @@ +<manifest identifier="lvgx.SNT.geo.prog" version="1" xsi:schemaLocation="http://www.imsproject.org/xsd/imscp_rootv1p1p2 imscp_rootv1p1p2.xsd http://www.imsglobal.org/xsd/imsmd_rootv1p2p1 imsmd_rootv1p2p1.xsd http://www.adlnet.org/xsd/adlcp_rootv1p2 adlcp_rootv1p2.xsd"> + +<metadata> +<schema>ADL SCORM</schema> +<schemaversion>1.2</schemaversion> +</metadata> + +<organizations default="lvgx"> + <organization identifier="lvgx"> + <title>Programmation sur des cartes numériques</title> + <item identifier="point_item" identifierref="point_res"> + <title>Placer un point en python</title> + </item> + <item identifier="pays_item" identifierref="pays_res"> + <title>Des marqueurs avec des messages</title> + </item> + <item identifier="meridien_item" identifierref="meridien_res"> + <title>Une ligne de marqueurs</title> + </item> + <item identifier="cercle_item" identifierref="cercle_res"> + <title>Placer un cercle</title> + </item> + <item identifier="souris_item" identifierref="souris_res"> + <title>Un marqueur se met à la position de la souris</title> + </item> + <item identifier="suivi_item" identifierref="suivi_res"> + <title>Un marqueur suit la souris</title> + </item> + <item identifier="random_item" identifierref="random_res"> + <title>Fin de l'activité</title> + </item> + </organization> +</organizations> + +<resources> + <resource identifier="point_res" type="webcontent" adlcp:scormtype="sco" href="point.html"> + <file href="point.html"/> + </resource> + <resource identifier="pays_res" type="webcontent" adlcp:scormtype="sco" href="pays.html"> + <file href="pays.html"/> + </resource> + <resource identifier="meridien_res" type="webcontent" adlcp:scormtype="sco" href="meridien.html"> + <file href="meridien.html"/> + </resource> + <resource identifier="cercle_res" type="webcontent" adlcp:scormtype="sco" href="cercle.html"> + <file href="cercle.html"/> + </resource> + <resource identifier="souris_res" type="webcontent" adlcp:scormtype="sco" href="souris.html"> + <file href="souris.html"/> + </resource> + <resource identifier="suivi_res" type="webcontent" adlcp:scormtype="sco" href="suivi.html"> + <file href="suivi.html"/> + </resource> + <resource identifier="random_res" type="webcontent" adlcp:scormtype="sco" href="random.html"> + <file href="random.html"/> + </resource> +</resources> + +</manifest> diff --git a/geo/prog/meridien.html b/geo/prog/meridien.html @@ -0,0 +1,318 @@ +<head> + +<meta charset="utf-8"/> + +<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"/> + +<style> +h1,h2 { + font-family: Sans; +} + +.stderr { + background-color: #fee; + color: #900; +} + +.stderr, .stdout { + /* display: contents; */ /* uncomment to make print( end='') work */ + margin: 0px; + padding: 0px 0.3em; +} + +.console { + max-height: 20em; + overflow: auto; + border: medium solid black; +} + +.console:empty { + display: none; +} + +#feedback { + border: solid #aaa; + background-color: #eee; +} + +#feedback:empty { + display: none; +} + +</style> + +<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script> +<script src="https://unpkg.com/brython@3.9.3/brython.js"></script> +<script src="https://unpkg.com/brython@3.9.3/brython_stdlib.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.min.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/mode-python.min.js"></script> + +<script type="text/javascript"> + +code = "# Écrivez votre code python ici :\nprint(\"Bonjour !\")"; + +score = 0; + +API = window.API || window.parent.API; + +function loadSCO() { + if (API) { + API.LMSInitialize(""); + + suspend_data = API.LMSGetValue("cmi.suspend_data"); + + if (suspend_data) { + code = suspend_data; + } + } +} + +function sendSCO() { + if (API) { + API.LMSSetValue("cmi.core.score.raw", score); + API.LMSSetValue("cmi.suspend_data", code); + API.LMSSetValue("cmi.core.score.lesson_status", "completed"); + + API.LMSCommit(""); + } +} + +function nextSCO() { + if (API) { + API.LMSSetValue("nav.event","continue"); // Probably Moodle specific + API.LMSFinish(""); + } +} + +// Leaflet stuff + +cognac = [45.69, -0.32]; + +markers = []; +click_latlng = {"lat":45.69, "lng":-0.32}; +click_func = function() {}; + +function clear_map() { + while (markers.length > 0) { + markers.pop().remove(); + } +} + +function on_map_click(e) { + document.getElementById("lastclick").innerHTML = e.latlng.lat+", "+e.latlng.lng; + click_latlng = e.latlng; + click_func(); +} + +window.onload = function() { + loadSCO(); + document.getElementById("code").textContent = code; + + map = L.map('map').setView([0,0], 1); + L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map); + map.on("click", on_map_click); + + brython(); +} +</script> + +<script type="text/python"> +# Requires Brython and Ace editor + +from browser import document, window, html +from sys import stderr, stdout, settrace +from traceback import print_exc, extract_stack, extract_tb + +def make_max_line_tracer(maxlines): + lines = 0 + def tracer(frame, event, arg): + nonlocal lines + if event == 'line': + lines += 1 + if lines >= maxlines: + raise TimeoutError + return tracer + return tracer + +def exec_code(editor, id): + effacer() + + console = document[id + "_console"] + console.clear() + stderr.write = lambda data : console_target(data, console, True) + stdout.write = lambda data : console_target(data, console) + + code = editor.getValue() + try: + compiled = compile(code, "<" + id + ">", "exec") + except SyntaxError: + print_exc(limit=0) + return + + settrace(make_max_line_tracer(10000)) # increase to allow longer execution + try: + exec(code) + except TimeoutError: + settrace(None) + print("L'exécution prend trop de temps, abandon.", file=stderr) + except Exception as e: + settrace(None) + tb_len = len(extract_tb(e.__traceback__)) - len(extract_stack()) + print_exc(limit=-tb_len) + finally: + settrace(None) + + window.code = code + window.score = check() + window.sendSCO() + +def console_target(data, elt, err=False): + elt <= html.PRE(data, Class="stderr" if err else "stdout") + elt.scrollTop = elt.scrollHeight + +breditors = document.select(".breditor") + +for ed_elt in breditors: + editor = window.ace.edit(ed_elt.id) + editor.session.setMode("ace/mode/python") + #editor.setOption('fontSize', '14px') + editor.setOption('maxLines', 15) + + console = html.DIV(Class="console", id=ed_elt.id + "_console") + + ed_elt.insertAdjacentElement('afterend', console) + + exec_button = html.BUTTON("Exécuter →") + exec_button.bind("click", lambda ev : exec_code(editor, ed_elt.id)) + ed_elt.insertAdjacentElement('afterend', exec_button) + +def feedback(msg): + document["feedback"].clear() + document["feedback"] <= msg + +markers = window.markers +L = window.L +map = window.map + +def marqueur(lat, lon, message=None): + mark=L.marker((lat, lon)).addTo(map) + markers.append(mark) + + if message: + mark.bindPopup(message) + +def cercle(lat, lon, rad, col='red', message=None): + mark=L.circle((lat, lon), + {"color": col, + "fillColor": col, + "fillOpacity": 0.5, + "radius": rad} + ).addTo(map) + markers.append(mark) + + if message: + mark.bindPopup(message) + + +def dernier_clic(): + return window.click_latlng["lat"], window.click_latlng["lng"] + +def au_clic(func): + window.click_func = func + +def effacer(): + window.clear_map() + +def check(): + score = 0 + + if len(markers) == 0: + feedback("Aucun marqueur placé") + elif len(markers) < 80 : + score = 10 + feedback("Pas assez de marqueurs placés") + else: + bad_lon = 0 + + same = 0 + coords_set = set() + + for m in markers: + latlng = m.getLatLng() + coords = (latlng["lat"], latlng["lng"]) + if coords[0]<80 and coords in coords_set: + same += 1 + coords_set.add(coords) + if coords[1] != 0: + bad_lon+=1 + if bad_lon >0: + score = 30 + feedback("Des marqueurs ne sont pas sur le méridien de Greenwich (mauvaise longitude)") + elif same > 0: + score = 60 + feedback("Des marqueurs sont superposés (aux mêmes coordonnées)") + else: + score = 100 + feedback("Les marqueurs semblent bien placés, bravo ! ") + document["feedback"] <= html.BUTTON("Passer à la suite", onclick="nextSCO();") + + return score + +</script> + +</head> + +<body> + +<h1>Une ligne de marqueurs</h1> + +<div> +On veut faire une ligne de marqueurs depuis l'équateur jusqu'au pôle nord +en suivant le méridien de Greenwich, avec un marqueur par degré. +<br/> +Au niveau des coordonnées, ça veut dire que le premier sera à (0,0), le suivant +à (1,0), puis (2,0), etc. jusqu'à (86,0) (le pôle nord). +<br/> +On utilise toujours la fonction <code>marqueur(latitude, longitude)</code>, +et cette fois-ci il faudra aussi utiliser une boucle <code>for</code>, +rappel : +</div> +<pre><code>for i in range(10): + print(i) +</code></pre> +est équivalent à : +<pre><code> +print(0) +print(1) +print(2) +print(3) +print(4) +print(5) +print(6) +print(7) +print(8) +print(9) +</code></pre> +<div> +<b> +Écrivez le code python qui dessine la ligne décrite ci-dessus. +</b> +</div> +<div> +</div> + +<h2>Carte OpenStreetMap</h2> + +<div id = "map" style = "width: 900px; height: 580px"></div> + +<button onclick="clear_map();">Tout effacer sur la carte</button> +Coordonnées du dernier clic : +<span id="lastclick"></span> + +<h2>Code Python</h2> + +<pre id="code" class="breditor"></pre> +<div id="feedback"></div> + +</body> +</html> diff --git a/geo/prog/pays.html b/geo/prog/pays.html @@ -0,0 +1,304 @@ +<head> + +<meta charset="utf-8"/> + +<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"/> + +<style> +h1,h2 { + font-family: Sans; +} + +.stderr { + background-color: #fee; + color: #900; +} + +.stderr, .stdout { + /* display: contents; */ /* uncomment to make print( end='') work */ + margin: 0px; + padding: 0px 0.3em; +} + +.console { + max-height: 20em; + overflow: auto; + border: medium solid black; +} + +.console:empty { + display: none; +} + +#feedback { + border: solid #aaa; + background-color: #eee; +} + +#feedback:empty { + display: none; +} + +</style> + +<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script> +<script src="https://unpkg.com/brython@3.9.3/brython.js"></script> +<script src="https://unpkg.com/brython@3.9.3/brython_stdlib.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.min.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/mode-python.min.js"></script> + +<script type="text/javascript"> + +code = "# Écrivez votre code python ici :\nprint(\"Bonjour !\")"; + +score = 0; + +API = window.API || window.parent.API; + +function loadSCO() { + if (API) { + API.LMSInitialize(""); + + suspend_data = API.LMSGetValue("cmi.suspend_data"); + + if (suspend_data) { + code = suspend_data; + } + } +} + +function sendSCO() { + if (API) { + API.LMSSetValue("cmi.core.score.raw", score); + API.LMSSetValue("cmi.suspend_data", code); + API.LMSSetValue("cmi.core.score.lesson_status", "completed"); + + API.LMSCommit(""); + } +} + +function nextSCO() { + if (API) { + API.LMSSetValue("nav.event","continue"); // Probably Moodle specific + API.LMSFinish(""); + } +} + +// Leaflet stuff + +cognac = [45.69, -0.32]; + +markers = []; +click_latlng = {"lat":45.69, "lng":-0.32}; +click_func = function() {}; + +function clear_map() { + while (markers.length > 0) { + markers.pop().remove(); + } +} + +function on_map_click(e) { + document.getElementById("lastclick").innerHTML = e.latlng.lat+", "+e.latlng.lng; + click_latlng = e.latlng; + click_func(); +} + +window.onload = function() { + loadSCO(); + document.getElementById("code").textContent = code; + + map = L.map('map').setView([0,0], 1); + L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map); + map.on("click", on_map_click); + + brython(); +} +</script> + +<script type="text/python"> +# Requires Brython and Ace editor + +from browser import document, window, html +from sys import stderr, stdout, settrace +from traceback import print_exc, extract_stack, extract_tb + +def make_max_line_tracer(maxlines): + lines = 0 + def tracer(frame, event, arg): + nonlocal lines + if event == 'line': + lines += 1 + if lines >= maxlines: + raise TimeoutError + return tracer + return tracer + +def exec_code(editor, id): + effacer() + + console = document[id + "_console"] + console.clear() + stderr.write = lambda data : console_target(data, console, True) + stdout.write = lambda data : console_target(data, console) + + code = editor.getValue() + try: + compiled = compile(code, "<" + id + ">", "exec") + except SyntaxError: + print_exc(limit=0) + return + + settrace(make_max_line_tracer(10000)) # increase to allow longer execution + try: + exec(code) + except TimeoutError: + settrace(None) + print("L'exécution prend trop de temps, abandon.", file=stderr) + except Exception as e: + settrace(None) + tb_len = len(extract_tb(e.__traceback__)) - len(extract_stack()) + print_exc(limit=-tb_len) + finally: + settrace(None) + + window.code = code + window.score = check() + window.sendSCO() + +def console_target(data, elt, err=False): + elt <= html.PRE(data, Class="stderr" if err else "stdout") + elt.scrollTop = elt.scrollHeight + +breditors = document.select(".breditor") + +for ed_elt in breditors: + editor = window.ace.edit(ed_elt.id) + editor.session.setMode("ace/mode/python") + #editor.setOption('fontSize', '14px') + editor.setOption('maxLines', 15) + + console = html.DIV(Class="console", id=ed_elt.id + "_console") + + ed_elt.insertAdjacentElement('afterend', console) + + exec_button = html.BUTTON("Exécuter →") + exec_button.bind("click", lambda ev : exec_code(editor, ed_elt.id)) + ed_elt.insertAdjacentElement('afterend', exec_button) + +def feedback(msg): + document["feedback"].clear() + document["feedback"] <= msg + +markers = window.markers +L = window.L +map = window.map + +def marqueur(lat, lon, message=None): + mark=L.marker((lat, lon)).addTo(map) + markers.append(mark) + + if message: + mark.bindPopup(message) + +def cercle(lat, lon, rad, col='red', message=None): + mark=L.circle((lat, lon), + {"color": col, + "fillColor": col, + "fillOpacity": 0.5, + "radius": rad} + ).addTo(map) + markers.append(mark) + + if message: + mark.bindPopup(message) + + +def dernier_clic(): + return window.click_latlng["lat"], window.click_latlng["lng"] + +def au_clic(func): + window.click_func = func + +def effacer(): + window.clear_map() + +def check(): + score = 0 + + if len(markers) == 0: + feedback("Aucun marqueur placé") + elif len(markers) < 3 : + score = 10 + feedback("Pas assez de marqueurs placés") + else: + toggled = 0 + + same = 0 + coords_set = set() + + for m in markers: + if m.getPopup(): + toggled += 1 + latlng = m.getLatLng() + coords = (latlng["lat"], latlng["lng"]) + if coords in coords_set: + same += 1 + coords_set.add(coords) + + if toggled != len(markers): + score = 30 + feedback("Des marqueurs n'ont pas de message") + elif same > 0: + score = 60 + feedback("Des marqueurs sont superposés (aux mêmes coordonnées)") + else: + score = 100 + feedback("Les marqueurs semblent bien placés, bravo ! ") + document["feedback"] <= html.BUTTON("Passer à la suite", onclick="nextSCO();") + + return score + +</script> + +</head> + +<body> + +<h1>Placer des points pour plusieurs pays</h1> + +<div> +On veut placer plusieurs marqueurs, et leur faire afficher un +message quand on clique dessus. +<br/> +On peut utiliser la même fonction, mais avec un nouveau paramètre +<code>marqueur(latitude, longitude, message)</code>, +qui va contenir le texte du message affiché quand on clique sur le marqueur. +</div> +<div> +<b> +Écrivez le code python permettant d'afficher au moins 3 marqueurs dans +3 pays différents, avec comme message le nom du pays. +</b> +</div> +<div> +<i>Vous pouvez vous aider des coordonnées du dernier clic qui sont affichées +sous la carte. +</i> +</div> + +<h2>Carte OpenStreetMap</h2> + +<div id = "map" style = "width: 900px; height: 580px"></div> + +<button onclick="clear_map();">Tout effacer sur la carte</button> +Coordonnées du dernier clic : +<span id="lastclick"></span> + +<h2>Code Python</h2> + +<pre id="code" class="breditor"></pre> +<div id="feedback"></div> + +</body> +</html> diff --git a/geo/prog/point.html b/geo/prog/point.html @@ -0,0 +1,286 @@ +<head> + +<meta charset="utf-8"/> + +<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"/> + +<style> +h1,h2 { + font-family: Sans; +} + +.stderr { + background-color: #fee; + color: #900; +} + +.stderr, .stdout { + /* display: contents; */ /* uncomment to make print( end='') work */ + margin: 0px; + padding: 0px 0.3em; +} + +.console { + max-height: 20em; + overflow: auto; + border: medium solid black; +} + +.console:empty { + display: none; +} + +#feedback { + border: solid #aaa; + background-color: #eee; +} + +#feedback:empty { + display: none; +} + +</style> + +<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script> +<script src="https://unpkg.com/brython@3.9.3/brython.js"></script> +<script src="https://unpkg.com/brython@3.9.3/brython_stdlib.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.min.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/mode-python.min.js"></script> + +<script type="text/javascript"> + +code = "# Écrivez votre code python ici :\nprint(\"Bonjour !\")"; + +score = 0; + +API = window.API || window.parent.API; + +function loadSCO() { + if (API) { + API.LMSInitialize(""); + + suspend_data = API.LMSGetValue("cmi.suspend_data"); + + if (suspend_data) { + code = suspend_data; + } + } +} + +function sendSCO() { + if (API) { + API.LMSSetValue("cmi.core.score.raw", score); + API.LMSSetValue("cmi.suspend_data", code); + API.LMSSetValue("cmi.core.score.lesson_status", "completed"); + + API.LMSCommit(""); + } +} + +function nextSCO() { + if (API) { + API.LMSSetValue("nav.event","continue"); // Probably Moodle specific + API.LMSFinish(""); + } +} + +// Leaflet stuff + +cognac = [45.69, -0.32]; + +markers = []; +click_latlng = {"lat":45.69, "lng":-0.32}; +click_func = function() {}; + +function clear_map() { + while (markers.length > 0) { + markers.pop().remove(); + } +} + +function on_map_click(e) { + document.getElementById("lastclick").innerHTML = e.latlng.lat+", "+e.latlng.lng; + click_latlng = e.latlng; + click_func(); +} + +window.onload = function() { + loadSCO(); + document.getElementById("code").textContent = code; + + map = L.map('map').setView([0,0], 1); + L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map); + map.on("click", on_map_click); + + brython(); +} +</script> + +<script type="text/python"> +# Requires Brython and Ace editor + +from browser import document, window, html +from sys import stderr, stdout, settrace +from traceback import print_exc, extract_stack, extract_tb + +def make_max_line_tracer(maxlines): + lines = 0 + def tracer(frame, event, arg): + nonlocal lines + if event == 'line': + lines += 1 + if lines >= maxlines: + raise TimeoutError + return tracer + return tracer + +def exec_code(editor, id): + effacer() + + console = document[id + "_console"] + console.clear() + stderr.write = lambda data : console_target(data, console, True) + stdout.write = lambda data : console_target(data, console) + + code = editor.getValue() + try: + compiled = compile(code, "<" + id + ">", "exec") + except SyntaxError: + print_exc(limit=0) + return + + settrace(make_max_line_tracer(10000)) # increase to allow longer execution + try: + exec(code) + except TimeoutError: + settrace(None) + print("L'exécution prend trop de temps, abandon.", file=stderr) + except Exception as e: + settrace(None) + tb_len = len(extract_tb(e.__traceback__)) - len(extract_stack()) + print_exc(limit=-tb_len) + finally: + settrace(None) + + window.code = code + window.score = check() + window.sendSCO() + +def console_target(data, elt, err=False): + elt <= html.PRE(data, Class="stderr" if err else "stdout") + elt.scrollTop = elt.scrollHeight + +breditors = document.select(".breditor") + +for ed_elt in breditors: + editor = window.ace.edit(ed_elt.id) + editor.session.setMode("ace/mode/python") + #editor.setOption('fontSize', '14px') + editor.setOption('maxLines', 15) + + console = html.DIV(Class="console", id=ed_elt.id + "_console") + + ed_elt.insertAdjacentElement('afterend', console) + + exec_button = html.BUTTON("Exécuter →") + exec_button.bind("click", lambda ev : exec_code(editor, ed_elt.id)) + ed_elt.insertAdjacentElement('afterend', exec_button) + +def feedback(msg): + document["feedback"].clear() + document["feedback"] <= msg + +markers = window.markers +L = window.L +map = window.map + +def marqueur(lat, lon, message=None): + mark=L.marker((lat, lon)).addTo(map) + markers.append(mark) + + if message: + mark.bindPopup(message) + +def cercle(lat, lon, rad, col='red', message=None): + mark=L.circle((lat, lon), + {"color": col, + "fillColor": col, + "fillOpacity": 0.5, + "radius": rad} + ).addTo(map) + markers.append(mark) + + if message: + mark.bindPopup(message) + + +def dernier_clic(): + return window.click_latlng["lat"], window.click_latlng["lng"] + +def au_clic(func): + window.click_func = func + +def effacer(): + window.clear_map() + +def check(): + score = 0 + + if len(markers) == 0: + feedback("Aucun marqueur placé") + elif len(markers) > 1: + feedback("Trop de marqueurs placés") + else: + latlng = markers[0].getLatLng() + coords = [latlng["lat"], latlng["lng"]] + + if coords == window.cognac: + score = 100 + feedback("Le marqueur semble bien placé, bravo ! ") + document["feedback"] <= html.BUTTON("Passer à la suite", onclick="nextSCO();") + elif coords[0] == window.cognac[0]: + score = 75 + feedback("Bonne latitude, mais mauvaise longitude") + elif coords[1] == window.cognac[1]: + score = 75 + feedback("Bonne longitude, mais mauvaise latitude") + else: + score = 30 + feedback("Le marqueur est aux mauvaises coordonnées") + return score + +</script> + +</head> + +<body> + +<h1>Placer un point sur une carte en Python</h1> + +On veut placer un marqueur à des coordonnées géographiques +précises sur une carte numérique. +<br/> +On a besion de la fonction <code>marqueur(latitude,longitude)</code>, +qui place un point aux coordonnées qu'on lui donne en paramètres +(c'est à dire entre les parenthèses). +<br/> +<b> +Modifiez le code python sous la carte pour afficher un marqueur aux +coordonnées 45.69, -0.32. +</b> + +<h2>Carte OpenStreetMap</h2> + +<div id = "map" style = "width: 900px; height: 580px"></div> + +<button onclick="clear_map();">Tout effacer sur la carte</button> +Coordonnées du dernier clic : +<span id="lastclick"></span> + +<h2>Code Python</h2> + +<pre id="code" class="breditor"></pre> +<div id="feedback"></div> + +</body> +</html> diff --git a/geo/prog/random.html b/geo/prog/random.html @@ -0,0 +1,259 @@ +<head> + +<meta charset="utf-8"/> + +<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"/> + +<style> +h1,h2 { + font-family: Sans; +} + +.stderr { + background-color: #fee; + color: #900; +} + +.stderr, .stdout { + /* display: contents; */ /* uncomment to make print( end='') work */ + margin: 0px; + padding: 0px 0.3em; +} + +.console { + max-height: 20em; + overflow: auto; + border: medium solid black; +} + +.console:empty { + display: none; +} + +#feedback { + border: solid #aaa; + background-color: #eee; +} + +#feedback:empty { + display: none; +} + +</style> + +<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script> +<script src="https://unpkg.com/brython@3.9.3/brython.js"></script> +<script src="https://unpkg.com/brython@3.9.3/brython_stdlib.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.min.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/mode-python.min.js"></script> + +<script type="text/javascript"> + +code = "# Écrivez votre code python ici :\nprint(\"Bonjour !\")"; + +score = 0; + +API = window.API || window.parent.API; + +function loadSCO() { + if (API) { + API.LMSInitialize(""); + + suspend_data = API.LMSGetValue("cmi.suspend_data"); + + if (suspend_data) { + code = suspend_data; + } + } +} + +function sendSCO() { + if (API) { + API.LMSSetValue("cmi.core.score.raw", score); + API.LMSSetValue("cmi.suspend_data", code); + API.LMSSetValue("cmi.core.score.lesson_status", "completed"); + + API.LMSCommit(""); + } +} + +function nextSCO() { + if (API) { + API.LMSSetValue("nav.event","continue"); // Probably Moodle specific + API.LMSFinish(""); + } +} + +// Leaflet stuff + +cognac = [45.69, -0.32]; + +markers = []; +click_latlng = {"lat":45.69, "lng":-0.32}; +click_func = function() {}; + +function clear_map() { + while (markers.length > 0) { + markers.pop().remove(); + } +} + +function on_map_click(e) { + document.getElementById("lastclick").innerHTML = e.latlng.lat+", "+e.latlng.lng; + click_latlng = e.latlng; + click_func(); +} + +window.onload = function() { + loadSCO(); + document.getElementById("code").textContent = code; + + map = L.map('map').setView(cognac, 11); + L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map); + map.on("click", on_map_click); + + brython(); +} +</script> + +<script type="text/python"> +# Requires Brython and Ace editor + +from browser import document, window, html +from sys import stderr, stdout, settrace +from traceback import print_exc, extract_stack, extract_tb + +def make_max_line_tracer(maxlines): + lines = 0 + def tracer(frame, event, arg): + nonlocal lines + if event == 'line': + lines += 1 + if lines >= maxlines: + raise TimeoutError + return tracer + return tracer + +def exec_code(editor, id): + effacer() + + console = document[id + "_console"] + console.clear() + stderr.write = lambda data : console_target(data, console, True) + stdout.write = lambda data : console_target(data, console) + + code = editor.getValue() + try: + compiled = compile(code, "<" + id + ">", "exec") + except SyntaxError: + print_exc(limit=0) + return + + settrace(make_max_line_tracer(10000)) # increase to allow longer execution + try: + exec(code) + except TimeoutError: + settrace(None) + print("L'exécution prend trop de temps, abandon.", file=stderr) + except Exception as e: + settrace(None) + tb_len = len(extract_tb(e.__traceback__)) - len(extract_stack()) + print_exc(limit=-tb_len) + finally: + settrace(None) + + window.code = code + window.score = check() + window.sendSCO() + +def console_target(data, elt, err=False): + elt <= html.PRE(data, Class="stderr" if err else "stdout") + elt.scrollTop = elt.scrollHeight + +breditors = document.select(".breditor") + +for ed_elt in breditors: + editor = window.ace.edit(ed_elt.id) + editor.session.setMode("ace/mode/python") + #editor.setOption('fontSize', '14px') + editor.setOption('maxLines', 15) + + console = html.DIV(Class="console", id=ed_elt.id + "_console") + + ed_elt.insertAdjacentElement('afterend', console) + + exec_button = html.BUTTON("Exécuter →") + exec_button.bind("click", lambda ev : exec_code(editor, ed_elt.id)) + ed_elt.insertAdjacentElement('afterend', exec_button) + +def feedback(msg): + document["feedback"].clear() + document["feedback"] <= msg + +markers = window.markers +L = window.L +map = window.map + +def marqueur(lat, lon, message=None): + mark=L.marker((lat, lon)).addTo(map) + markers.append(mark) + + if message: + mark.bindPopup(message) + +def cercle(lat, lon, rad, col='red', message=None): + mark=L.circle((lat, lon), + {"color": col, + "fillColor": col, + "fillOpacity": 0.5, + "radius": rad} + ).addTo(map) + markers.append(mark) + + if message: + mark.bindPopup(message) + + +def dernier_clic(): + return window.click_latlng["lat"], window.click_latlng["lng"] + +def au_clic(func): + window.click_func = func + +def effacer(): + window.clear_map() + +def check(): + score = 100 + + feedback("Bravo ? ") + document["feedback"] <= html.BUTTON("Terminer", onclick="nextSCO();") + + return score + +</script> + +</head> + +<body> + +<h1>Fini !</h1> +<b> +L'activité est terminée, vous pouvez coder ce que vous voulez ici. +</b> + +<h2>Carte OpenStreetMap</h2> + +<div id = "map" style = "width: 900px; height: 580px"></div> + +<button onclick="clear_map();">Tout effacer sur la carte</button> +Coordonnées du dernier clic : +<span id="lastclick"></span> + +<h2>Code Python</h2> + +<pre id="code" class="breditor"></pre> +<div id="feedback"></div> + +</body> +</html> diff --git a/geo/prog/souris.html b/geo/prog/souris.html @@ -0,0 +1,296 @@ +<head> + +<meta charset="utf-8"/> + +<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"/> + +<style> +h1,h2 { + font-family: Sans; +} + +.stderr { + background-color: #fee; + color: #900; +} + +.stderr, .stdout { + /* display: contents; */ /* uncomment to make print( end='') work */ + margin: 0px; + padding: 0px 0.3em; +} + +.console { + max-height: 20em; + overflow: auto; + border: medium solid black; +} + +.console:empty { + display: none; +} + +#feedback { + border: solid #aaa; + background-color: #eee; +} + +#feedback:empty { + display: none; +} + +</style> + +<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script> +<script src="https://unpkg.com/brython@3.9.3/brython.js"></script> +<script src="https://unpkg.com/brython@3.9.3/brython_stdlib.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.min.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/mode-python.min.js"></script> + +<script type="text/javascript"> + +code = "# Écrivez votre code python ici :\nprint(\"Bonjour !\")"; + +score = 0; + +API = window.API || window.parent.API; + +function loadSCO() { + if (API) { + API.LMSInitialize(""); + + suspend_data = API.LMSGetValue("cmi.suspend_data"); + + if (suspend_data) { + code = suspend_data; + } + } +} + +function sendSCO() { + if (API) { + API.LMSSetValue("cmi.core.score.raw", score); + API.LMSSetValue("cmi.suspend_data", code); + API.LMSSetValue("cmi.core.score.lesson_status", "completed"); + + API.LMSCommit(""); + } +} + +function nextSCO() { + if (API) { + API.LMSSetValue("nav.event","continue"); // Probably Moodle specific + API.LMSFinish(""); + } +} + +// Leaflet stuff + +cognac = [45.69, -0.32]; + +markers = []; +click_latlng = {"lat":45.69, "lng":-0.32}; +click_func = function() {}; + +function clear_map() { + while (markers.length > 0) { + markers.pop().remove(); + } +} + +function on_map_click(e) { + //document.getElementById("lastclick").innerHTML = e.latlng.lat+", "+e.latlng.lng; + click_latlng = e.latlng; + click_func(); +} + +window.onload = function() { + loadSCO(); + document.getElementById("code").textContent = code; + + map = L.map('map').setView(cognac, 11); + L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map); + map.on("click", on_map_click); + + brython(); +} +</script> + +<script type="text/python"> +# Requires Brython and Ace editor + +from browser import document, window, html +from sys import stderr, stdout, settrace +from traceback import print_exc, extract_stack, extract_tb + +def make_max_line_tracer(maxlines): + lines = 0 + def tracer(frame, event, arg): + nonlocal lines + if event == 'line': + lines += 1 + if lines >= maxlines: + raise TimeoutError + return tracer + return tracer + +def exec_code(editor, id): + effacer() + + console = document[id + "_console"] + console.clear() + stderr.write = lambda data : console_target(data, console, True) + stdout.write = lambda data : console_target(data, console) + + code = editor.getValue() + try: + compiled = compile(code, "<" + id + ">", "exec") + except SyntaxError: + print_exc(limit=0) + return + + settrace(make_max_line_tracer(10000)) # increase to allow longer execution + try: + exec(code) + except TimeoutError: + settrace(None) + print("L'exécution prend trop de temps, abandon.", file=stderr) + except Exception as e: + settrace(None) + tb_len = len(extract_tb(e.__traceback__)) - len(extract_stack()) + print_exc(limit=-tb_len) + finally: + settrace(None) + + window.code = code + window.score = check() + window.sendSCO() + +def console_target(data, elt, err=False): + elt <= html.PRE(data, Class="stderr" if err else "stdout") + elt.scrollTop = elt.scrollHeight + +breditors = document.select(".breditor") + +for ed_elt in breditors: + editor = window.ace.edit(ed_elt.id) + editor.session.setMode("ace/mode/python") + #editor.setOption('fontSize', '14px') + editor.setOption('maxLines', 15) + + console = html.DIV(Class="console", id=ed_elt.id + "_console") + + ed_elt.insertAdjacentElement('afterend', console) + + exec_button = html.BUTTON("Exécuter →") + exec_button.bind("click", lambda ev : exec_code(editor, ed_elt.id)) + ed_elt.insertAdjacentElement('afterend', exec_button) + +def feedback(msg): + document["feedback"].clear() + document["feedback"] <= msg + +markers = window.markers +L = window.L +map = window.map + +def marqueur(lat, lon, message=None): + mark=L.marker((lat, lon)).addTo(map) + markers.append(mark) + + if message: + mark.bindPopup(message) + +def cercle(lat, lon, rad, col='red', message=None): + mark=L.circle((lat, lon), + {"color": col, + "fillColor": col, + "fillOpacity": 0.5, + "radius": rad} + ).addTo(map) + markers.append(mark) + + if message: + mark.bindPopup(message) + + +def dernier_clic(): + return window.click_latlng["lat"], window.click_latlng["lng"] + +def au_clic(func): + window.click_func = func + +def effacer(): + window.clear_map() + +def check(): + score = 0 + + if len(markers) == 0: + feedback("Aucun marqueur placé") + else: + clatlng = window.click_latlng + latlng = markers[0].getLatLng() + if latlng["lat"] != clatlng["lat"]: + score = 30 + feedback("Les coordonnées du marqueur ne sont pas les bonnes") + else: + score = 100 + feedback("Le marqueur est bien placé, bravo ! ") + document["feedback"] <= html.BUTTON("Passer à la suite", onclick="nextSCO();") + + return score + +</script> + +</head> + +<body> + +<h1>Les coordonnées du clic</h1> + +<div> +L'affichage des coordonnées du clic précédent est maintenant désactivé, +mais j'ai laissé une fonction pour retrouver les coordonnées. +C'est la fonction <code>dernier_clic()</code>, qui ne prend pas de +paramètre, mais renvoie 2 valeurs : la latitude et la longitude du +dernier clic fait sur la carte. +<br/> +On peut donc récupérer ces coordonées en créant 2 variables qu'on pourra +réutiliser plus tard : +</div> +<pre><code>lat, lon = dernier_clic() +print(lat) +print(lon) +</code></pre> +<div> +<b> +Écrivez le code python qui place un marqueur à la position du dernier clic. +</b> +</div> +<div> +<i>Rappel : <code>marqueur(latitude, longitude)</code> +</i> +</div> +<div> +<i>Optionnel : utilisez la forme +<code>marqueur(latitude, longitude, message)</code> +pour mettre les coordonnées du clic dans le message du marqueur. +(<code>str()</code> permet de transformer quelque chose en texte) +</i> +</div> + +<h2>Carte OpenStreetMap</h2> + +<div id = "map" style = "width: 900px; height: 580px"></div> + +<button onclick="clear_map();">Tout effacer sur la carte</button> +<span id="lastclick"></span> + +<h2>Code Python</h2> + +<pre id="code" class="breditor"></pre> +<div id="feedback"></div> + +</body> +</html> diff --git a/geo/prog/suivi.html b/geo/prog/suivi.html @@ -0,0 +1,311 @@ +<head> + +<meta charset="utf-8"/> + +<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"/> + +<style> +h1,h2 { + font-family: Sans; +} + +.stderr { + background-color: #fee; + color: #900; +} + +.stderr, .stdout { + /* display: contents; */ /* uncomment to make print( end='') work */ + margin: 0px; + padding: 0px 0.3em; +} + +.console { + max-height: 20em; + overflow: auto; + border: medium solid black; +} + +.console:empty { + display: none; +} + +#feedback { + border: solid #aaa; + background-color: #eee; +} + +#feedback:empty { + display: none; +} + +</style> + +<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script> +<script src="https://unpkg.com/brython@3.9.3/brython.js"></script> +<script src="https://unpkg.com/brython@3.9.3/brython_stdlib.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/ace.min.js"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.12/mode-python.min.js"></script> + +<script type="text/javascript"> + +code = "# Écrivez votre code python ici :\nprint(\"Bonjour !\")"; + +score = 0; + +API = window.API || window.parent.API; + +function loadSCO() { + if (API) { + API.LMSInitialize(""); + + suspend_data = API.LMSGetValue("cmi.suspend_data"); + + if (suspend_data) { + code = suspend_data; + } + } +} + +function sendSCO() { + if (API) { + API.LMSSetValue("cmi.core.score.raw", score); + API.LMSSetValue("cmi.suspend_data", code); + API.LMSSetValue("cmi.core.score.lesson_status", "completed"); + + API.LMSCommit(""); + } +} + +function nextSCO() { + if (API) { + API.LMSSetValue("nav.event","continue"); // Probably Moodle specific + API.LMSFinish(""); + } +} + +// Leaflet stuff + +cognac = [45.69, -0.32]; + +markers = []; +click_latlng = {"lat":45.69, "lng":-0.32}; +click_func = function() {}; + +function clear_map() { + while (markers.length > 0) { + markers.pop().remove(); + } +} + +function on_map_click(e) { + //document.getElementById("lastclick").innerHTML = e.latlng.lat+", "+e.latlng.lng; + click_latlng = e.latlng; + click_func(); + check(); +} + +window.onload = function() { + loadSCO(); + document.getElementById("code").textContent = code; + + map = L.map('map').setView(cognac, 11); + L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map); + map.on("click", on_map_click); + + brython(); +} +</script> + +<script type="text/python"> +# Requires Brython and Ace editor + +from browser import document, window, html +from sys import stderr, stdout, settrace +from traceback import print_exc, extract_stack, extract_tb + +def make_max_line_tracer(maxlines): + lines = 0 + def tracer(frame, event, arg): + nonlocal lines + if event == 'line': + lines += 1 + if lines >= maxlines: + raise TimeoutError + return tracer + return tracer + +def exec_code(editor, id): + effacer() + + console = document[id + "_console"] + console.clear() + stderr.write = lambda data : console_target(data, console, True) + stdout.write = lambda data : console_target(data, console) + + code = editor.getValue() + try: + compiled = compile(code, "<" + id + ">", "exec") + except SyntaxError: + print_exc(limit=0) + return + + settrace(make_max_line_tracer(10000)) # increase to allow longer execution + try: + exec(code) + except TimeoutError: + settrace(None) + print("L'exécution prend trop de temps, abandon.", file=stderr) + except Exception as e: + settrace(None) + tb_len = len(extract_tb(e.__traceback__)) - len(extract_stack()) + print_exc(limit=-tb_len) + finally: + settrace(None) + + window.code = code + window.score = score + window.sendSCO() + +def console_target(data, elt, err=False): + elt <= html.PRE(data, Class="stderr" if err else "stdout") + elt.scrollTop = elt.scrollHeight + +breditors = document.select(".breditor") + +for ed_elt in breditors: + editor = window.ace.edit(ed_elt.id) + editor.session.setMode("ace/mode/python") + #editor.setOption('fontSize', '14px') + editor.setOption('maxLines', 15) + + console = html.DIV(Class="console", id=ed_elt.id + "_console") + + ed_elt.insertAdjacentElement('afterend', console) + + exec_button = html.BUTTON("Exécuter →") + exec_button.bind("click", lambda ev : exec_code(editor, ed_elt.id)) + ed_elt.insertAdjacentElement('afterend', exec_button) + +def feedback(msg): + document["feedback"].clear() + document["feedback"] <= msg + +markers = window.markers +L = window.L +map = window.map + +def marqueur(lat, lon, message=None): + mark=L.marker((lat, lon)).addTo(map) + markers.append(mark) + + if message: + mark.bindPopup(message) + +def cercle(lat, lon, rad, col='red', message=None): + mark=L.circle((lat, lon), + {"color": col, + "fillColor": col, + "fillOpacity": 0.5, + "radius": rad} + ).addTo(map) + markers.append(mark) + + if message: + mark.bindPopup(message) + + +def dernier_clic(): + return window.click_latlng["lat"], window.click_latlng["lng"] + +def au_clic(func): + window.click_func = func + +def effacer(): + window.clear_map() + +score = 0 + +def check(): + global score + score = 0 + + if len(markers) == 0: + feedback("Aucun marqueur placé") + elif len(markers) >1: + score = 10 + feedback("trop de marqueurs") + + else: + clatlng = window.click_latlng + latlng = markers[0].getLatLng() + if latlng["lat"] != clatlng["lat"]: + score = 30 + feedback("Les coordonnées du marqueur ne sont pas les bonnes") + else: + score = 100 + feedback("Le marqueur est bien placé, bravo ! ") + document["feedback"] <= html.BUTTON("Passer à la suite", onclick="nextSCO();") + + return score + +window.check = check + +</script> + +</head> + +<body> + +<h1>Suivi de la souris</h1> + +<div> +On veut maintenant que le code permette de réagir et de déplacer un marqueur +dès qu'on clique quelque part avec la souris.<br/> +Pour ça il faudra : +<ol> + <li>Créer une fonction qui contient le code pour afficher un marqueur + à la position du dernier clic. On crée une fonction de la manière + suivante : +<pre><code>def nom_de_fontion(): + # contenu de la fonction : + truc() + machin() +</code></pre> + </li> + <li>Demander à ce que la fonction soit appelée à chaque fois qu'on en utilisant + <code>au_clic(nom_de_fonction)</code> + </li> + <li>Ne pas oublier d'effacer le marqueur précédent au bon moment en + utilisant la fonction <code>effacer()</code> + (qui efface tous les éléments de la carte) + </li> +</ol> +<div> +<b> +Écrivez le code python qui fait qu'un marqueur se déplace au clic de la souris. +</b> +</div> +<div> +<i>Rappel : <code>marqueur(latitude, longitude)</code> +</i> +</div> +<div> +<i>Rappel : <code>lat, lon = dernier_clic()</code> +</i> +</div> + +<h2>Carte OpenStreetMap</h2> + +<div id = "map" style = "width: 900px; height: 580px"></div> + +<button onclick="clear_map();">Tout effacer sur la carte</button> +<span id="lastclick"></span> + +<h2>Code Python</h2> + +<pre id="code" class="breditor"></pre> +<div id="feedback"></div> + +</body> +</html>