Skip to content
Extraits de code Groupes Projets

Comparer les révisions

Les modifications sont affichées comme si la révision source était fusionnée avec la révision cible. En savoir plus sur la comparaison des révisions.

Source

Sélectionner le projet cible
No results found

Cible

Sélectionner le projet cible
  • fossardchristophe/nsilo
  • kuniansamuel/nsi
  • Lycee-Cezanne-NSI/nsi-projet-site
  • nsiforges76/swc-pnav
  • nsi-p-corneille/pyodide-mkdocs-theme-review
  • fjunier/snt
  • avenel_sylvain/test-forge-sa
  • jcottin/eval-nsi
  • deleuphilippe/test-phi
  • chardine_marc_aurelien/nsi-premiere-chardine
  • maybeflush/site-de-maybeflush
  • nsicurie/exercices-experts
  • amislanghe/nsi-terminale
  • pdupuits/1-nsi-lakanal
  • profjahier/pyxel
  • max_cholley/enessite
  • moyivan/pyodide-mkdocs-theme-review
  • profpabloneruda/pablo-neruda-nsi
  • doduyrat/cpge-mpi
  • mbloch/python-pyodide-mkdocs
  • le-coin-de-rapha-l/essai-de-raphael
  • aimeeric/pyodide-mkdocs-theme-review
  • agostinoluca/pyodide-mkdocs-theme-review
  • vroullier/2024-intro-forge
  • mkdocs-david/site-web-version-pyodide-mkdocs-theme
  • nsicurie/nsi
  • cournill/nsi-lycee-prevert-pont-audemer
  • docs/modeles/pyodide-mkdocs-theme-review
  • rthibaudeau/site
  • azzizaxavier/pyodide-mkdocs-theme-review
  • dominguezanne/site-modele-forge
  • fjunier/qcm-nsi-snt-maths
  • nativelfabrice/info-cpge
  • mezeray-nsi/site-web-formation-nsi
  • bergson-paris/pyodide-mkdocs-theme-review
  • cyril.thuillier-hamel/term-nsi-honfleur
  • jdleroy/mon-essai-de-site-web
  • delphine-nunez/terminales-maths
  • dkany/site-daphne-kany
  • nsi-cornat/essai-fork
  • janson-paris/sbt-nsi-1-ere
  • nsi-guehenno/cours-nsi
  • thirionlaurent/nsi-lycee-jean-hyppolite-jonzac
  • nsinormandie/exemplej1
  • jmdemouy/cours
  • ydyd/cours-nsi
  • profjahier_test_01/site-test-01
  • initpoo/decouverte-de-la-programmation-orientee-objet
  • devedeud/essai-forge-dd
  • stvalnsi/mon-projet
  • llaadu/lla_ex
  • spy/snt-nsi
  • mcoilhac/site-demo
  • glc-nsi/cours-avec-exercices-python
  • Lycee-Cezanne-NSI/nsi-projet
  • laura-fleron/ros-docu
  • initpoo/pyodide-mkdocs-theme-review
  • charpentierronan/pyodide-mkdocs-theme-review
  • mezeray-nsi/formation-nsi-copie-du-site
  • nsi-fresnel/nsi_fresnel
  • nsinormandie/2024-intro-forge
  • test01072024/test-01072020-d-apres-pyodide-mkdocs-theme
  • madeceric/site-avec-pyodide-mkdocs-theme
  • sekowskijean-jacques/python-cours-et-exercices
  • profjahier/nsi-terminale
  • profjahier/nsi-premiere
  • BenDup/traitement-d-image-python
  • essais/term-nsi-honfleur
  • mcoilhac/sio-2-maths-approfondies
  • lefebvre05/cours-de-nsi-rey
  • tfontanet/terminale
  • ybousba/snt-en-egypte
  • olaf_le_viking/nsi-anguier
  • nieduziakamaury/ansi
  • lycee_pgdg_paris/pyodide-mkdocs-theme-review
  • profpabloneruda/tnsi-lycee-pablo-neruda
  • delphine-nunez/2-gt-maths-snt
  • mcoilhac/sio-1-maths-approfondies
  • lp-ameublement-revel/ERA-TMA-TFBMA
79 résultats
Afficher les modifications
Affichage de
avec 263 ajouts et 746 suppressions
---
author: Mireille Coilhac
title: Crédits
author: Votre nom
title: 👏 Crédits
---
Le site est hébergé par la forge des communs numériques éducatifs <a href="https://docs.forge.apps.education.fr/" target="_blank">
<span aria-label="Avatar" aria-hidden="true" data-type="round" data-color="3" class="_avatar_k41ul_17 mx_BaseAvatar" style="--cpd-avatar-size: 16px;"><img loading="lazy" alt="" src="https://matrix.agent.education.tchap.gouv.fr/_matrix/media/v3/thumbnail/matrix.agent.education.tchap.gouv.fr/de0e2fe63b40dd452178360baa3ff29ba16d8b98?width=16&amp;height=16&amp;method=crop" crossorigin="anonymous" referrerpolicy="no-referrer" class="_image_k41ul_49" data-type="round" width="16px" height="16px"></span><span class="mx_Pill_text">Centre de documentation</span></a>
![AEIF](../assets/images/logo_aeif_300.png){width=7%}
Le modèle du site a été créé par l' [Association des enseignantes et enseignants d'informatique de France](https://aeif.fr/index.php/category/non-classe/){target="_blank"}.
Le site est construit avec [`mkdocs`](https://www.mkdocs.org/) et en particulier [`mkdocs-material`](https://squidfunk.github.io/mkdocs-material/), et surtout [Pyodide-Mkdocs-Theme](https://frederic-zinelli.gitlab.io/pyodide-mkdocs-theme/) pour la partie Python.
😀 Un grand merci à Frédéric Zinelli, et Vincent-Xavier Jumel qui ont réalisé la partie technique de ce site. Merci également à Charles Poulmaire pour ses relectures attentives et ses conseils judicieux.
Le site est construit avec [`mkdocs`](https://www.mkdocs.org/){target="_blank"} et en particulier [`mkdocs-material`](https://squidfunk.github.io/mkdocs-material/){target="_blank"}, et surtout [Pyodide-Mkdocs-Theme](https://frederic-zinelli.gitlab.io/pyodide-mkdocs-theme/){target="_blank"} pour la partie Python nécessaire pour les QCM.
😀 Un grand merci à Frédéric Zinelli, et Vincent-Xavier Jumel qui ont réalisé la partie technique de ce site.
Merci également à Charles Poulmaire pour ses relectures attentives et ses conseils judicieux.
# --- PYODIDE:env --- #
# --------- PYODIDE:env --------- #
from js import document
if "restart" in globals():
restart()
# --- PYODIDE:code --- #
def m_a_j(cible):
done()
document.getElementById(cible).innerHTML = Screen().html
_cible = 'cible_3'
# --------- PYODIDE:code --------- #
from turtle import *
setup(640, 480) # pour définir la taille de la fenêtre
speed(10)
def arbre(l=100, n=5):
......@@ -18,6 +25,12 @@ def arbre(l=100, n=5):
back(l)
arbre(200, 5)
# --- PYODIDE:post --- #
done()
document.getElementById("cible_3").innerHTML = svg()
# --------- PYODIDE:post --------- #
if Screen().html is None:
forward(0)
m_a_j(_cible)
# --------- PYODIDE:post_term --------- #
if "m_a_j" in globals():
m_a_j(_cible)
# --- PYODIDE:env --- #
import matplotlib.pyplot as plt # Indispensable (provoque la déclaration de PyodidePlot)
fig = PyodidePlot('cible_double')
fig.target()
# --- PYODIDE:code --- #
# L'import suivant a été fait dans du code caché :
# import matplotlib.pyplot as plt
xs1 = [-3 + k * 0.1 for k in range(61)]
ys1 = [x**2 for x in xs1]
xs2 = [-2 + k * 0.1 for k in range(41)]
ys2 = [x**3 for x in xs2]
plt.plot(xs1, ys1, "r-", xs2, ys2, "b+")
plt.grid() # Optionnel : pour voir le quadrillage
plt.axhline() # Optionnel : pour voir l'axe des abscisses
plt.axvline() # Optionnel : pour voir l'axe des ordonnées
plt.title("La fonction carré et la fonction cube")
plt.show()
......@@ -3,31 +3,30 @@ author: Mireille Coilhac
title: Images en Python
---
😊
## I. Utiliser la bibliothèque matplotlib
## I. Utiliser la bibliothèque matplotlib par Nicolas Revéret
### La fonction carré
{{ IDE('fct_carre') }}
???+ question "La courbe 1 s'affiche dans une admonition sous l'éditeur"
{{ figure() }}
### Les courbes de la fonction carré et de la fonction cube séparées
{{ IDE('exo_figure_1')}}
??? tip "Votre figure"
<div id="cible_1" class="center" style="display: flex;justify-content: center;align-content:center;flex-direction: column;margin:auto;min-height:5em;text-align:center">
Votre tracé sera ici
</div>
{{ IDE('fct_carre_cube') }}
{{ figure('cible_1') }}
{{ figure('cible_2') }}
### Les courbes de la fonction carré et de la fonction cube superposées
???+ question "La courbe 2 s'affiche dans une admonition sous l'éditeur"
{{ IDE('carre_cube_superposees') }}
{{ IDE('exo_figure_2')}}
{{ figure('cible_double') }}
??? tip "Votre figure"
<div id="cible_2" class="center" style="display: flex;justify-content: center;align-content:center;flex-direction: column;margin:auto;min-height:5em;text-align:center">
Votre tracé sera ici
</div>
## II. Utiliser la tortue par Romain Janvier
......@@ -36,10 +35,8 @@ title: Images en Python
???+ question "Utilisation de la tortue"
{{ IDE('arbre_tortue') }}
<div id="cible_3" class="admonition center" style="display: flex;justify-content: center;align-content:center;flex-direction: column;margin:auto;min-height:5em;text-align:center">
Le tracé sera affiché ici
</div>
{{ figure('cible_3') }}
# --- PYODIDE:env --- #
# Import de matplotlib (installation lors du 1er lancement)
import matplotlib
# Précision du backend à utiliser
matplotlib.use("module://matplotlib_pyodide.html5_canvas_backend")
# Insertion de la courbe dans une div spécifié(id="cible_2")
from js import document
document.pyodideMplTarget = document.getElementById("cible_2")
# On vide la div
document.getElementById("cible_2").textContent = ""
# --- PYODIDE:code --- #
import matplotlib.pyplot as plt
fig, ax = plt.subplots() # Syntaxe obligatoire pour ne pas mélanger plusieurs graphiques
xs = [-2 + k * 0.1 for k in range(41)]
ys = [x**3 for x in xs]
ax.plot(xs, ys, "r-") # Syntaxe obligatoire pour ne pas mélanger plusieurs graphiques
plt.grid() # Optionnel : pour voir le quadrillage
plt.axhline() # Optionnel : pour voir l'axe des abscisses
plt.axvline() # Optionnel : pour voir l'axe des ordonnées
plt.title("La fonction cube")
plt.show()
\ No newline at end of file
# --- PYODIDE:env --- #
# Un import de matplotlib en tout premier est indispensable, pour que la classe
# PyodidePlot devienne disponible dans l'environnement:
import matplotlib.pyplot as plt
PyodidePlot().target() # Cible la figure dans laquelle tracer la figure dans la page
# --- PYODIDE:code --- #
# L'import suivant a été fait dans du code caché :
# import matplotlib.pyplot as plt
xs = [-3 + k * 0.1 for k in range(61)]
ys = [x**2 for x in xs]
plt.plot(xs, ys, "r-")
plt.grid() # Optionnel : pour voir le quadrillage
plt.axhline() # Optionnel : pour voir l'axe des abscisses
plt.axvline() # Optionnel : pour voir l'axe des ordonnées
plt.title("La fonction carré")
plt.show()
# --- PYODIDE:env --- #
# Import de matplotlib (installation lors du 1er lancement)
import matplotlib
# Précision du backend à utiliser
matplotlib.use("module://matplotlib_pyodide.html5_canvas_backend")
# Insertion de la courbe dans une div spécifié(id="cible_1")
from js import document
document.pyodideMplTarget = document.getElementById("cible_1")
# On vide la div
document.getElementById("cible_1").textContent = ""
import matplotlib.pyplot as plt
fig1 = PyodidePlot('cible_1')
fig2 = PyodidePlot('cible_2')
# --- PYODIDE:code --- #
# L'import suivant a été fait dans du code caché :
# import matplotlib.pyplot as plt
import matplotlib.pyplot as plt
fig, ax = plt.subplots() # Syntaxe obligatoire pour ne pas mélanger plusieurs graphiques
fig1.target() # Pour tracer la fonction ci-dessous
xs = [-3 + k * 0.1 for k in range(61)]
ys = [x**2 for x in xs]
ax.plot(xs, ys, "r-") # Syntaxe obligatoire pour ne pas mélanger plusieurs graphiques
plt.plot(xs, ys, "r-")
plt.grid() # Optionnel : pour voir le quadrillage
plt.axhline() # Optionnel : pour voir l'axe des abscisses
plt.axvline() # Optionnel : pour voir l'axe des ordonnées
plt.title("La fonction carré")
plt.show()
fig2.target() # Pour tracer la fonction ci-dessous
xs = [-2 + k * 0.1 for k in range(41)]
ys = [x**3 for x in xs]
plt.plot(xs, ys, "r-")
plt.grid() # Optionnel : pour voir le quadrillage
plt.axhline() # Optionnel : pour voir l'axe des abscisses
plt.axvline() # Optionnel : pour voir l'axe des ordonnées
plt.title("La fonction cube")
plt.show()
# Mon site
---
author: Votre nom
title: 🏡 Accueil
---
Vous trouverez ...
À vous de personnaliser cet accueil
## titre 1
!!! info "Adapter ce site modèle"
leçons
Le tutoriel est ici : [Tutoriel de site avec python](https://docs.forge.apps.education.fr/modeles/tutoriels/pyodide-mkdocs-theme-review/){:target="_blank" }
Si vous voulez conserver certaines pages de ce modèles sans qu'elles ne soient visibles dans le menu, il suffit de les enlever du fichier .pages
Vous les retrouverez facilement en utilisant la barre de recherche en haut à droite
## titre 2
autres leçons
Si vous voulez supprimer le lien vers le dépôt de votre site en haut à droite : ![lien_depot](assets/images/aller_depot.png){ width=5%}
👉 les explications sont ici : [Tutoriel : votre propre contenu](https://docs.forge.apps.education.fr/modeles/tutoriels/pyodide-mkdocs-theme-review/08_tuto_fork/1_fork_projet/#iii-votre-propre-contenu){:target="_blank" }
😊 Bienvenue !
_Dernière MAJ le 11/03/2025_
......@@ -6,71 +6,7 @@ tags:
- Difficulté **
---
Pour créer **très facilement de façon automatique** ce fichier, suivre ce lien : [Création de QCM : générer le fichier .json automatiquement](https://frederic-zinelli.gitlab.io/pyodide-mkdocs-theme/redactors/qcm_builder/){ .md-button target="_blank" rel="noopener" }.
{{ multi_qcm('qcm_exemple.json') }}
## Multi QCM original ancien Pyodide
{{multi_qcm(
["Quelle est la réponse à la question universelle ? Cocher deux réponses.",
["$6\\times 7$", "$\\int_0^{42} 1 dx$", "Je ne sais pas", " `#!py sum([i for i in range(10)])`", "La réponse D"], [1, 2]],
["1 + 1 = ? Cocher deux réponses.",
["Je ne sais pas", "2", "L'âge du capitaine", "10 en binaire"], [2, 4]]
)}}
## QCM de la documentation de Frédéric Zinelli
{{ multi_qcm(
[
"""
On a saisi le code suivant :
```python title=''
n = 8
while n > 1:
n = n/2
```
Que vaut `n` après l'exécution du code ?
""",
[
"2.0",
"4.0",
"1.0",
"0.5",
],
[3]
],
[
"Quelle est la machine qui va exécuter un programme JavaScript inclus dans une page HTML ?",
[
"La machine de l’utilisateur sur laquelle s’exécute le navigateur web.",
"La machine de l’utilisateur ou du serveur, selon celle qui est la plus disponible.",
"La machine de l’utilisateur ou du serveur, suivant la confidentialité des données manipulées.",
"Le serveur web sur lequel est stockée la page HTML."
],
[1],
],
[
"""
Quelle expression permet d'accéder au numéro de Tournesol :
```python title=''
repertoire = [{'nom': 'Dupont', 'tel': 5234}, {'nom': 'Tournesol', 'tel': 5248}, {'nom': 'Dupond', 'tel': 5237}]
```
""",
[
"`#!py repertoire[1]['tel']`",
"`#!py repertoire['tel'][1]`",
"`#!py repertoire['Tournesol']`",
"`#!py repertoire['Tournesol']['tel']`",
],
[1],
{'multi':True}
],
multi = False,
qcm_title = "Un QCM avec mélange automatique des questions (bouton en bas pour recommencer)",
DEBUG = False,
shuffle = True,
) }}
{
"questions": [
[
"```python title=\"\"\nn = 8\nwhile n > 1:\n n = n/2\n```\n\nQue vaut `n` après l'exécution du code ?",
[
"0.5",
"1.0",
"2.0",
"4.0"
],
[2]
],
[
"`meubles = ['Table', 'Commode', 'Armoire', 'Placard', 'Buffet']`\n\nCocher toutes les bonnes réponses.",
[
"`meubles[-1]` vaut `'Buffet'`",
"`meubles[1]` vaut `'Table'`",
"`meubles[1]` vaut `'Commode'`"
],
[1,3],
{"multi":true}
]
],
"description": "QCM Exemple",
"shuffle": true
}
\ No newline at end of file
......@@ -48,9 +48,10 @@
margin: 0 auto;
}
/*
Largeur de la page
*/
.md-grid {
max-width: 90%;
}
}
\ No newline at end of file
import js
import inspect
from math import cos, sin, pi, sqrt, atan2
import time
class Turtle:
""" TODO : les indicateurs de position ne fonctionnent pas car on ne renvoie rien.
Par exemple, self.state fixe l'appel à self._xcor qui renvoie une donnée.
"""
def __init__(self, x = 0, y = 0, angle = 0):
self.x, self.y = x, y
self.angle = angle
self.init_angle = angle
self.pen_color = 'black'
self.fill_color = 'black'
self._pen_down = True
self.width = 3
self.canvas = js.document.querySelector('canvas')
self.ctx = js.document.querySelector('canvas').getContext("2d")
self.canvas_pt = js.document.getElementById('pointer')
self.ctx_pt = js.document.getElementById('pointer').getContext("2d")
self.__set_default()
self.state = list() # queue
self.on_draw = 0
self.stamp_number = 0
self.fill = False
self._speed = 5
self._hide = False
def __set_default(self):
self.ctx.lineJoin = "miter"
self.ctx.lineCap = "round"
self.ctx.strokeStyle = self.pen_color
self.ctx.lineWidth = self.width
self.style = self.triangle
def _basic_pointer_draw(function):
def wrapper(self):
self.ctx_pt.clearRect(0, 0, self.canvas_pt.width, self.canvas_pt.height)
self.ctx_pt.beginPath()
function(self)
self.ctx_pt.fill()
self.ctx_pt.stroke()
return wrapper
def speed(self, number):
assert 0 <= number <= 10
self._speed = number
def rad2deg(self, angle):
return angle / pi *180
def deg2rad(self, angle):
return angle / 180 * pi
def hideturtle(self):
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}""", "hide" : True})
def ht(self):
self.hideturtle()
def _hideturtle(self, params):
self._hide = params['hide']
def showturtle(self):
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}""", "hide" : False})
def st(self):
self.hideturtle()
def _showturtle(self, params):
self._hide = params['hide']
def goto(self, x, y):
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}""", "x" : x, "y" : y})
def _goto(self, params):
x, y = params["x"], params["y"]
if self._pen_down :
self.ctx.beginPath()
self.ctx.moveTo(self.x, self.y)
self.ctx.lineTo(x, y)
self.ctx.stroke()
self.x, self.y = x, y
if (not self._hide): self.style()
def _get_parameters(self, x, y):
if y is not None :
x2, y2 = x, y
elif isinstance(x, Turtle):
x2, y2 = Turtle.x, Turtle.y
else :
x2, y2 = x
return x2, y2
def towards(self, x, y = None):
""" Fonction à revoir ?"""
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}""", "x" : x, "y" : y})
def _towards(self, params):
x2, y2 = self._get_parameters(params["x"], params["y"])
return (self.rad2deg(atan2(self.y-y2, self.x-x2)) + 180) % 360
def distance(self, x, y = None):
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}""", "x" : x, "y" : y})
def _distance(self, x, y = None):
x2, y2 = self._get_parameters(params["x"], params["y"])
return sqrt((self.x-x2)**2 + (self.y-y2)**2)
def pencolor(self, r = None, g = None, b = None):
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}""", "r" : r, "g" : g, "b" : b})
def _pencolor(self, params):
r, g, b = params["r"], params["g"], params["b"]
if isinstance(r, str) :
color = r
elif isinstance(r, tuple) :
rr, g, b = r
color = self.rgb2hex(rr, g, b)
elif g is not None and b is not None :
color = self.rgb2hex(r, g, b)
elif r is None:
return self.pen_color
self.pen_color = color
self.ctx.strokeStyle = color
self.ctx_pt.strokeStyle = color
def fillcolor(self, r = None, g = None, b = None):
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}""", "r" : r, "g" : g, "b" : b})
def _fillcolor(self, params):
r, g, b = params["r"], params["g"], params["b"]
if isinstance(r, str) :
color = r
elif isinstance(r, tuple) :
rr, g, b = r
color = self.rgb2hex(rr, g, b)
elif g is not None and b is not None :
color = self.rgb2hex(r, g, b)
elif r is None:
return self.fill_color
self.fill_color = color
self.ctx.fillStyle = color
self.ctx_pt.fillStyle = color
def color(self, r1 = None, g1 = None, b1 = None, r2 = None, g2 = None, b2 = None):
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}""", \
"r1" : r1, "g1" : g1, "b1" : b1, "r2" : r2, "g2" : g2, "b2" : b2 })
def _color(self, params):
r1, g1, b1 = params["r1"], params["g1"], params["b1"]
r2, g2, b2 = params["r2"], params["g2"], params["b2"]
if r1 is None and r2 is None:
return self.pen_color, self.fill_color
elif isinstance(r1, str) and isinstance(g1, str):
new_pen_params = {"r" : r1, "g":None, "b": None}
new_fill_params = {"r" : g1, "g":None, "b": None}
self._pencolor(new_pen_params)
self._fillcolor(new_fill_params)
elif isinstance(r1, tuple) and isinstance(g1, tuple):
new_pen_params = {"r" : r1, "g":None, "b": None}
new_fill_params = {"r" : g1, "g":None, "b": None}
self._pencolor(new_pen_params)
self._fillcolor(new_fill_params)
elif isinstance(r1, str) and g1 is None:
new_params = {"r" : r1, "g":None, "b": None}
self._pencolor(new_params)
self._fillcolor(new_params)
elif isinstance(r1, tuple) and g1 is None:
new_params = {"r" : r1, "g":None, "b": None}
self._pencolor(new_params)
self._fillcolor(new_params)
elif r1 is not None and g1 is not None and b1 is not None and r2 is None:
new_params = {"r" : r1, "g":g1, "b": b1}
self._pencolor(new_params)
self._fillcolor(new_params)
#def _determine_colors(self, r, g, b):
def rgb2hex(self, r, g, b):
for i in [r, g, b]:
assert 0 <= i <= 255, "Wrong color code"
return '#%02x%02x%02x' % (r, g, b)
def pensize(self, width = None):
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}""", "width" : width })
def width(self, width = None):
self.pensize(width)
def _pensize(self, params):
width = params["width"]
if (width is None): return self.ctx.lineWidth
self.ctx.lineWidth = width
def pendown(self):
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}"""})
def pd(self):
self.pendown()
def down(self):
self.pendown()
def _pendown(self, params):
self._pen_down = True
def penup(self):
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}"""})
def up(self):
self.penup()
def pu(self):
self.penup()
def _penup(self, params):
self._pen_down = False
def shape(self, style = None):
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}""", "sh" : style})
def _shape(self, params):
style = params["sh"]
dico_style = {'arrow' : self.arrow, 'turtle' : self.turtle, \
'circle' : self.cercle, 'square' : self.square, \
'triangle' : self.triangle, 'classic': self.arrow}
self.style = dico_style[style]
def forward(self, L):
if self._speed == 0 :
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}""", "L" : L })
else :
for _ in range(0, L, self._speed):
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}""", "L" : self._speed})
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}""", "L" : L % self._speed})
def fd(self, L):
self.forward(L)
def _forward(self, params):
L = params["L"]
if self.fill : self.fill_coordinates.append((self.x, self.y))
self.ctx.beginPath()
if (not self._hide): self.style()
self.ctx.moveTo(self.x, self.y)
self.ctx.lineTo(self.x + L * cos(self.deg2rad(self.angle)), \
self.y + L * sin(self.deg2rad(self.angle)))
if self._pen_down: self.ctx.stroke()
self.x += L * cos(self.deg2rad(self.angle))
self.y += L * sin(self.deg2rad(self.angle))
def backward(self, L):
if self._speed == 0 :
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}""", "L" : -L })
else :
for _ in range(0, L, self._speed):
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}""", "L" : -self._speed})
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}""", "L" : -L % self._speed})
def back(self, L):
self.backward(L)
def bk(self, L):
self.backward(L)
def _backward(self, params):
L = params["L"]
if self.fill : self.fill_coordinates.append((self.x, self.y))
self.ctx.beginPath()
if (not self._hide): self.style()
self.ctx.moveTo(self.x, self.y)
self.ctx.lineTo(self.x + L * cos(self.deg2rad(self.angle)), \
self.y + L * sin(self.deg2rad(self.angle)))
if self._pen_down: self.ctx.stroke()
self.x += L * cos(self.deg2rad(self.angle))
self.y += L * sin(self.deg2rad(self.angle))
def xcor(self):
""" non fonctionnel """
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}"""})
def _xcor(self, params):
return self.x
def ycor(self):
""" non fonctionnel """
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}"""})
def _ycor(self):
return self.y
def heading(self):
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}"""})
def _heading(self):
return self.angle
def setheading(self, angle):
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}""", "a" : angle})
def seth(self, angle):
self.setheading(angle)
def _setheading(self, params):
angle = params["a"]
self.angle = angle
def setx(self, x):
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}""", "x" : x})
def _setx(self, params):
x = params["x"]
self.x = x
def sety(self, y):
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}""", "y" : y})
def _setx(self, params):
y = params["y"]
self.y = y
def home(self):
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}"""})
def _home(self, params):
self.x, self.y, self.angle = 0, 0, self.init_angle
def begin_fill(self):
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}"""})
def _begin_fill(self, *args):
self.fill_coordinates = []
self.fill = True
def end_fill(self):
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}"""})
def _end_fill(self, *args):
self.ctx.fillStyle = self.fill_color
for ptX, ptY in self.fill_coordinates:
self.ctx.lineTo(ptX, ptY)
self.ctx.fill("evenodd")
self.fill = False
def filling(self):
return self.fill
@_basic_pointer_draw
def triangle(self):
x, y = self.x, self.y
x1, y1 = self.rotation(-15, -10)
x2, y2 = self.rotation(-15, 10)
self.ctx_pt.moveTo(x, y)
self.ctx_pt.lineTo(x+x1, y+y1)
self.ctx_pt.lineTo(x+x2, y+y2)
@_basic_pointer_draw
def arrow(self):
x, y = self.x, self.y
x1, y1 = self.rotation(-15, -8)
x2, y2 = self.rotation(-15, 8)
x3, y3 = self.rotation(-10, 0)
self.ctx_pt.moveTo(x, y)
self.ctx_pt.lineTo(x+x1, y+y1)
self.ctx_pt.lineTo(x+x3, y+y3)
self.ctx_pt.lineTo(x+x2, y+y2)
@_basic_pointer_draw
def turtle(self):
x, y = self.x, self.y
quarter_turtle = [(-5,2), (-6,4), (-5,5), (-4,3)]
half_head = [(5,1), (7,2)]
half_turtle = quarter_turtle + [(-1,4)] \
+ [self._x_symmetry(p, q, -1) for (p,q) in quarter_turtle[::-1]] \
+ half_head
full_turtle = [(-6,0)] + half_turtle + [(9,0)] \
+ [self._y_symmetry(p, q, 0) for (p,q) in half_turtle[::-1]]
rotated_full_turtle = [self.rotation(p, q) for (p, q) in full_turtle]
rotated_full_turtle = [self._stretch(p, q) for (p, q) in rotated_full_turtle]
self.ctx_pt.moveTo(x + rotated_full_turtle[0][0], y + rotated_full_turtle[0][1])
for (p,q) in rotated_full_turtle:
self.ctx_pt.lineTo(x + p, y + q)
def _stretch(self, x, y, stretch_factor=2):
return (x*stretch_factor, y*stretch_factor)
@_basic_pointer_draw
def cercle(self):
rad = 15
x, y = self.x, self.y
self.ctx_pt.arc(x, y, rad, 0, 2*pi)
@_basic_pointer_draw
def square(self):
side = 15
x, y = self.x, self.y
x0, y0 = self.rotation(-side/2, -side/2)
x1, y1 = self.rotation(-side/2, side/2)
x2, y2 = self.rotation(side/2, -side/2)
x3, y3 = self.rotation(side/2, side/2)
self.ctx_pt.moveTo(x+x0, y+y0)
self.ctx_pt.lineTo(x+x1, y+y1)
self.ctx_pt.lineTo(x+x3, y+y3)
self.ctx_pt.lineTo(x+x2, y+y2)
def _x_symmetry(self, x, y, x_axis):
return (2*x_axis-x, y)
def _y_symmetry(self, x, y, y_axis):
return (x, 2*y_axis-y)
def rotation(self, x, y):
inv_rot_mat = [[cos(self.deg2rad(self.angle)), -sin(self.deg2rad(self.angle))], \
[sin(self.deg2rad(self.angle)), cos(self.deg2rad(self.angle))]]
new_x = inv_rot_mat[0][0]*x + inv_rot_mat[0][1]*y
new_y = inv_rot_mat[1][0]*x + inv_rot_mat[1][1]*y
return new_x, new_y
def circle(self, radius, extent = None, steps = None):
#coords = self._get_circle_coordinates(radius)
#n = 12
#for i in range(n):
# self.state.append({"code": f"""self._{inspect.currentframe().f_code.co_name}""", \
# "x" : coords[i][0], "y" : coords[i][1]})
self.state.append({"code": f"""self._{inspect.currentframe().f_code.co_name}""", \
"r": radius, "e":extent , "s":steps})
def _circle(self, params):
#self._goto(params)
radius, extent, steps = params["r"], params["e"], params["s"]
n = 12
eps = 1
if radius < 0 : radius, eps = -radius, -1
center = [self.x+radius*cos(self.deg2rad(self.angle - 90)), \
self.y+radius*sin(self.deg2rad(self.angle - 90))]
if extent is None and steps is None:
angle = [eps*i*360/n-90 for i in range(n)]
coords = [(radius*cos(self.deg2rad(angle[i])), radius*sin(self.deg2rad(angle[i]))) for i in range(n)]
self.ctx.clearRect(0, 0, self.canvas_pt.width, self.canvas_pt.height)
self.ctx.beginPath()
self.ctx.moveTo(center[0]+coords[0][0], center[1]+coords[0][1])
for i in range(1, n):
self.ctx.lineTo(center[0]+coords[i][0], center[1]+coords[i][1])
self.ctx.closePath()
self.ctx.stroke()
#elif steps is None:
#else:
#def _get_circle_coordinates(self, radius):
# n = 12
# eps = 1
# if radius < 0 : radius, eps = -radius, -1
# center = [self.x+radius*cos(self.deg2rad(self.angle - 90)), \
# self.y+radius*sin(self.deg2rad(self.angle - 90))]
#angle = [eps*i*360/n-90 for i in range(n)]
#coords = [(center[0] +radius*cos(self.deg2rad(angle[i])), center[1] +radius*sin(self.deg2rad(angle[i]))) for i in range(n)]
#return coords
def right(self, angle):
if self._speed == 0 :
self.state.append({"code": f"""self._{inspect.currentframe().f_code.co_name}""", "a": angle})
else :
for _ in range(angle//self._speed):
self.state.append({"code": f"""self._{inspect.currentframe().f_code.co_name}""", "a": self._speed})
self.state.append({"code": f"""self._{inspect.currentframe().f_code.co_name}""", "a": angle % (self._speed)})
def rt(self, angle):
self.right(angle)
def left(self, angle):
if self._speed == 0 :
self.state.append({"code": f"""self._{inspect.currentframe().f_code.co_name}""", "a": angle})
else :
for _ in range(angle//self._speed):
self.state.append({"code": f"""self._{inspect.currentframe().f_code.co_name}""", "a": self._speed})
self.state.append({"code": f"""self._{inspect.currentframe().f_code.co_name}""", "a": angle % (self._speed)})
def lt(self, angle):
self.left(angle)
def _right(self, params):
angle = params["a"]
self.angle += angle
if (not self._hide): self.style()
def _left(self, params):
angle = params["a"]
self.angle -= angle
if (not self._hide): self.style()
#def stamp(self):
# self.stamp_number += 1
# self.ctx.triangle()
# return self.stamp_number
def dot(self, size = None, color = None):
if isinstance(size, str) : size, color = None, size
self.state.append({"code": f"""self._{inspect.currentframe().f_code.co_name}""", "size": size, "color": color})
def _dot(self, params):
# dot is not always on top of the line
color = params["color"]
size = params["size"]/2 if params["size"] is not None else max(self.ctx.lineWidth+4, self.ctx.lineWidth*2)
assert size >= 1, f"""bad screen distance {size}"""
self.ctx.beginPath()
self.ctx.arc(self.x, self.y, size, 0, 2*pi)
self.ctx.fillStyle = color if color is not None else self.color
self.ctx.fill()
def position(self):
self.state.append({"code" : f"""self._{inspect.currentframe().f_code.co_name}"""})
def _position(self, *args):
return (self.x, self.y)
def pos(self):
self.position()
def tick(self):
# Clear canvas
if len(self.state) > 0 :
# Draw current state
commands = self.state.pop(0)
command = commands.pop("code")
params = commands
eval(command)(params)
else :
js.clearInterval(self.on_draw)
def mainloop(self):
self.ctx.clearRect(0, 0, self.canvas.width, self.canvas.height)
self.ctx_pt.clearRect(0, 0, self.canvas_pt.width, self.canvas_pt.height)
self._animate()
def _mainloop_noclear(self):
self._animate()
def _animate(self):
self.on_draw = js.window.setInterval(lambda x=2 : self.tick(), 10)
_direct_access_turtle = Turtle()
def _deco_direct_access(function):
def wrapper(*args):
global _direct_access_turtle
function(*args)
_direct_access_turtle._mainloop_noclear()
return wrapper
method_list = [func for func in dir(Turtle) if callable(getattr(Turtle, func)) and not func.startswith("_")]
for nom in method_list:
exec(f"""@_deco_direct_access\ndef {nom}(*args):\n\t_direct_access_turtle.{nom}(*args)""")
#!/bin/zsh
cd docs/scripts/
for rep in `ls -d */`
do
cd $rep
echo $rep
for i in `ls -1 corr_*`
do
echo $i ${i:-2}
echo ${i:5:-3}_corr.py
mv $i ${i:5:-3}_corr.py;
done
for i in `ls -1 test_*`
do
echo $i ${i:-2}
echo ${i:5:-3}_test.py
mv $i ${i:5:-3}_test.py;
done
cd ..
done
cd ..
logo_forge.png

24,9 ko

from pyodide_mkdocs_theme.pyodide_macros import PyodideMacrosPlugin, TestsToken
def define_env(env:PyodideMacrosPlugin):
custom = {
"tests": TestsToken("\n# Tests"),
}
\ No newline at end of file
......@@ -4,9 +4,9 @@ site_description: Un modèle avec pyodide-mkdocs-theme
# À modifier, avec votre nom et la licence choisie
copyright: |
M. Coilhac
<a rel="license" href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.fr"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" /></a><br/>
Nom d'auteur
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a>.
<br><a href="https://aeif.fr">Design by AEIF</a>
# À modifier, avec votre mail
#extra:
......@@ -20,11 +20,15 @@ copyright: |
# Éventuellement à modifier avec votre thème de couleurs
theme:
favicon: assets/favicon.ico
favicon: assets/images/favicon.png
icon:
logo: material/stairs-up
#custom_dir: my_theme_customizations/
name: pyodide-mkdocs-theme
# La palette de couleur est maintenant intégrée par défaut au thème.
# Si vous souhaitez en changer, vous pouvez redéclarer la section entière
# et vos réglages prendront le pas sur les valeurs par défaut.
# Mêmes choses pour la langue et la suppression des google-fonts (non RGPD).
#font: false # RGPD ; pas de fonte Google
#language: fr # français
#palette: # Palettes de couleurs jour/nuit
......@@ -51,6 +55,8 @@ theme:
- content.code.annotate # Pour les annotations de code deroulantes avec +
- content.code.copy # Ajout après MAJ pour pouvoir copier du code
custom_dir: overrides
site_url: !ENV [CI_PAGES_URL, "http://127.0.0.1:8000/"]
......@@ -60,9 +66,7 @@ edit_uri: !ENV [EDIT_VARIABLE]
docs_dir: docs
nav:
- "🏡 Accueil": index.md
- ... | regex=^(?:(?!_REM.md).)*$
#nav: inutile on utilise les fichiers .pages plus pratiques
markdown_extensions:
- md_in_html
......@@ -77,18 +81,22 @@ markdown_extensions:
- pymdownx.mark # Passage ==surligné==.
- pymdownx.tilde # Passage ~~barré~~ ou en ~indice~.
- pymdownx.highlight: # Coloration syntaxique du code
auto_title: true
anchor_linenums: true
line_spans: __span
pygments_lang_class: true
- pymdownx.inlinehilite # pour `#!python <python en ligne>`
- pymdownx.snippets # Inclusion de fichiers externe.
- pymdownx.tasklist: # Cases à cocher - [ ] et - [x]
custom_checkbox: false # avec cases d'origine
clickable_checkbox: true # et cliquables.
- pymdownx.tabbed: # Volets glissants. === "Mon volet"
alternate_style: true
alternate_style: true
- pymdownx.keys: # Touches du clavier. ++ctrl+d++
separator: "\uff0b"
- pymdownx.emoji: # Émojis :boom:
emoji_index: !!python/name:materialx.emoji.twemoji
emoji_generator: !!python/name:materialx.emoji.to_svg
- pymdownx.emoji: # Émojis :boom:
emoji_index: !!python/name:material.extensions.emoji.twemoji
emoji_generator: !!python/name:material.extensions.emoji.to_svg
- pymdownx.superfences:
custom_fences:
- name: mermaid
......@@ -103,11 +111,11 @@ markdown_extensions:
plugins:
- awesome-pages:
- awesome-pages: # Pour les fichiers .pages
collapse_single_pages: true
- material/search
- material/tags:
- search
- tags:
tags_file: tags.md
- pyodide_macros:
# Vous pouvez ajouter ici tout réglage que vous auriez ajouté concernant les macros:
......@@ -115,7 +123,8 @@ plugins:
build:
python_libs:
- turtle
tab_to_spaces: 4
- sqlite-console
# En remplacement de mkdocs-exclude. Tous les fichiers correspondant aux patterns indiqués seront
......@@ -125,12 +134,10 @@ exclude_docs: |
**/*_REM.md
**/*.py
#extra_javascript:
#- xtra/javascripts/mathjax-config.js Supprimé pour MAJ pyodide
#extra_javascript: Supprimé pour MAJ pyodide pris en compte par le thème lui même
#- xtra/mathjax.js # MathJax
#- https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js
extra_css:
#- xtra/stylesheets/qcm.css ## Supprimé pour MAJ pyodide
- xtra/stylesheets/ajustements.css # ajustements
function mathJaxUpdate(){
jsLogger('[MathJax] - Page formatting')
if(!window.MathJax.startup.output){
console.error("Cannot update MathJax (CDN failed to load?)")
return
}
window.MathJax.startup.output.clearCache()
window.MathJax.typesetClear()
window.MathJax.texReset()
window.MathJax.typesetPromise()
}
const mathJaxIsReady = subscribeWhenReady('mathJax', mathJaxUpdate, {maxTries:100})
window.MathJax = {
startup: {
ready: () => {
jsLogger("[MathJax] - Setting up");
MathJax.startup.defaultReady();
jsLogger("[MathJax] - Ready");
mathJaxIsReady()
mathJaxUpdate()
},
},
loader: {
load: ['[tex]/cancel', 'output/svg', '[tex]/color', '[tex]/mhchem']
},
tex: {
packages: {'[+]': ['cancel', 'color', 'mhchem']},
inlineMath: [["\\(", "\\)"]],
displayMath: [["\\[", "\\]"]],
processEscapes: true,
processEnvironments: true,
},
options: {
ignoreHtmlClass: ".*|",
processHtmlClass: "arithmatex",
},
}
......@@ -3,6 +3,7 @@
#
# A revised version of CPython's turtle module written for Brython
#
# Adaptation to pyodide-mkdocs-theme by Romain Janvier
# Note: This version is not intended to be used in interactive mode,
# nor use help() to look up methods/functions definitions. The docstrings
......@@ -22,6 +23,8 @@
# as rotating it from 350 to 10 degrees. For this reason, we did not use the
# Vec2D class from the CPython module and handle the rotations quite differently.
# TODO: quand la tortue est invisible puis visible, on ne met pas à jour
# sa position avec les déplacements "invisibles"
import math
import sys
......@@ -182,6 +185,7 @@ class Screen(metaclass=Singleton):
"square": (create_square, 20),
"circle": (create_circle, 10),
}
self.html = None
self._animate = True
self._old_svg_scene = None
self.reset()
......@@ -210,13 +214,13 @@ class Screen(metaclass=Singleton):
raise RuntimeError(
"No turtle scene ended! " "You should call 'done' first."
)
html = self.svg()
# html = self.svg()
if isinstance(file, str):
with open(file, "w") as f:
f.write(html)
f.write(self.html)
else:
# file should be a file descriptor
file.write(html)
file.write(self.html)
def animation_frame_id(self, index):
return "af_{}_{}".format(self.svg_id, index)
......@@ -466,6 +470,7 @@ class Screen(metaclass=Singleton):
self.background_color = "white"
self._scene_finished = False
self._set_geometry()
self.html = None
def restart(self):
_CFG.update(_default_cfg())
......@@ -1229,6 +1234,9 @@ class Turtle(TPen, TNavigator):
self._creatingPoly = False
self._fillitem = self._fillpath = None
self._init(shape, visible)
def _init(self, shape=_CFG["shape"], visible=_CFG["visible"]):
self.name = shape
self.svg, rotation = self.screen.create_svg_turtle(self, name=shape)
self.svg.setAttribute("opacity", 0)
......@@ -1246,14 +1254,17 @@ class Turtle(TPen, TNavigator):
) # this will update the display to include the correction
self.speed(speed)
def reset(self):
"""Delete the turtle's drawings and restore its default values."""
# TODO: review this and most likely revise docstring.
TNavigator.reset(self)
TPen._reset(self)
self._old_heading = self.heading() + self.rotation_correction
self.home()
self.color(_CFG["pencolor"], _CFG["fillcolor"])
self.screen.reset()
self._init()
def clear(self):
sys.stderr.write("Warning: Turtle.clear() is not implemented.\n")
......@@ -1590,7 +1601,19 @@ Pen = Turtle
def done():
Screen().show_scene()
ancien = Screen().html
s = Screen().show_scene()
Screen().html = Screen().svg() # On mémorise le svg produit
if ancien is None or len(ancien) < len(Screen().html): # L'aninmation a changé
# Lorsqu'on réduit, on peut diminuer la taille
# On suppose juste que rajouter quelque chose compense cette
# différence
#print("on réduit")
#if ancien is None:
# print("C'est None")
#else:
# print(len(ancien), len(Screen().html))
s.reduire_animation()
show_scene = done
......
......@@ -93,6 +93,12 @@ class Element:
content += self._value
return f"{open_tag}{content}{close_tag}"
def reduire_animation(self):
if "dur" in self._attributes: # On réduit le temps de l'animation
self._attributes["dur"] = " 1ms"
for elem in self._children:
elem.reduire_animation()
def _tag_func(tag):
def func(*args, **kwargs):
......