diff --git a/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/01_lire_ecrire_fraction_simple.svg b/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/01_lire_ecrire_fraction_simple.svg
index f397873..51da493 100644
--- a/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/01_lire_ecrire_fraction_simple.svg
+++ b/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/01_lire_ecrire_fraction_simple.svg
@@ -27,6 +27,6 @@
-L'unité est coupée en 4 parts égales.
+L'unité est coupée en 4 partségales.
À retenirLe dénominateur indique le partage. Le numérateur indique les parts prises.
diff --git a/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/03_fraction_sur_demi_droite_graduee.svg b/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/03_fraction_sur_demi_droite_graduee.svg
index 42b0f85..5f52fb0 100644
--- a/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/03_fraction_sur_demi_droite_graduee.svg
+++ b/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/03_fraction_sur_demi_droite_graduee.svg
@@ -8,7 +8,7 @@
Exemple : placer
- 5
+ 5
4
@@ -22,13 +22,13 @@
- 5
+ 5
4
-Dénominateur 4 :chaque unité a 4 parts.
+Dénominateur 4 :chaque unité a 4 parts.
- 5
+ 5
4
diff --git a/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/04_fraction_superieure_a_un.svg b/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/04_fraction_superieure_a_un.svg
index 55dd84c..ae3d376 100644
--- a/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/04_fraction_superieure_a_un.svg
+++ b/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/04_fraction_superieure_a_un.svg
@@ -30,34 +30,34 @@
Je décompose
- 7
+ 7
4
=
- 4
+ 4
4
+
- 3
+ 3
4
- 7
+ 7
4
= 1 +
- 3
+ 3
4
-La première unité est complète.Il reste encore trois quarts.
+Unité complète.Reste trois quarts.
À retenirUne fraction peut être plus grande que 1 : il faut alors utiliser plusieurs unités.
diff --git a/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/05_comparer_fractions_simples.svg b/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/05_comparer_fractions_simples.svg
index a35a81e..8f996cf 100644
--- a/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/05_comparer_fractions_simples.svg
+++ b/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/05_comparer_fractions_simples.svg
@@ -7,13 +7,13 @@
Même dénominateur
- 3
+ 3
5
<
- 4
+ 4
5
@@ -37,13 +37,13 @@
Même numérateur
- 1
+ 1
2
>
- 1
+ 1
4
diff --git a/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/06_encadrer_fraction_entre_entiers.svg b/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/06_encadrer_fraction_entre_entiers.svg
index 2fc02f4..3cb23b2 100644
--- a/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/06_encadrer_fraction_entre_entiers.svg
+++ b/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/06_encadrer_fraction_entre_entiers.svg
@@ -22,14 +22,14 @@
- 6
+ 6
3
= 2
- 9
+ 9
3
@@ -37,7 +37,7 @@
2 <
- 7
+ 7
3
diff --git a/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/07_additionner_soustraire_fractions_simples.svg b/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/07_additionner_soustraire_fractions_simples.svg
index 987f25e..a157a16 100644
--- a/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/07_additionner_soustraire_fractions_simples.svg
+++ b/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/07_additionner_soustraire_fractions_simples.svg
@@ -7,19 +7,19 @@
Exemple
- 2
+ 2
7
+
- 3
+ 3
7
=
- 5
+ 5
7
@@ -38,19 +38,19 @@
La règleJe garde le dénominateur.J'ajoute ou je retireseulement les numérateurs.
- 6
+ 6
8
-
- 2
+ 2
8
=
- 4
+ 4
8
diff --git a/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/08_fraction_d_une_quantite.svg b/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/08_fraction_d_une_quantite.svg
index 26ed570..d88e133 100644
--- a/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/08_fraction_d_une_quantite.svg
+++ b/backend/contenus_pedagogiques/cycle_3/mathematiques/cm1/01_nombres_calcul_resolution/01B_fractions/svg/08_fraction_d_une_quantite.svg
@@ -20,7 +20,7 @@
-20 partagé en 4 parts : chaque part vaut 5.Je prends 3 parts : 15.
+20 partagé en 4 parts : chaque part vaut 5.Je prends 3 parts : 15.
La méthode20 à 4 = 55 x 3 = 15Le dénominateur partage.Le numérateur dit combien prendre.
À retenir
Pour trouver
diff --git a/backend/tools/validate_svg_quality.py b/backend/tools/validate_svg_quality.py
index e3432de..60c76ec 100644
--- a/backend/tools/validate_svg_quality.py
+++ b/backend/tools/validate_svg_quality.py
@@ -179,6 +179,14 @@ def shape_box(node: ET.Element, ox: float, oy: float) -> Box | None:
return None
+def panel_box_from_rect(node: ET.Element, ox: float, oy: float) -> Box | None:
+ if local_name(node.tag) != "rect" or not class_names(node).intersection({"panel", "soft", "card", "white"}):
+ return None
+ x = ox + parse_number(node.attrib.get("x"))
+ y = oy + parse_number(node.attrib.get("y"))
+ return Box("panel", "panel", x, y, x + parse_number(node.attrib.get("width")), y + parse_number(node.attrib.get("height")))
+
+
def collect_layout_boxes(
node: ET.Element,
styles: dict[str, dict[str, str]],
@@ -228,6 +236,45 @@ def validate_layout_collisions(path: Path, root: ET.Element, styles: dict[str, d
return issues
+def validate_panel_containment(
+ path: Path,
+ node: ET.Element,
+ styles: dict[str, dict[str, str]],
+ ox: float = 0.0,
+ oy: float = 0.0,
+) -> list[Issue]:
+ issues: list[Issue] = []
+ tx, ty = parse_translate(node.attrib.get("transform"))
+ ox += tx
+ oy += ty
+
+ if local_name(node.tag) == "g":
+ panel = next((panel_box_from_rect(child, ox, oy) for child in node if panel_box_from_rect(child, ox, oy)), None)
+ if panel:
+ safe = Box("panel", panel.label, panel.x1, panel.y1, panel.x2, panel.y2)
+ for box in collect_layout_boxes(node, styles, ox - tx, oy - ty):
+ if box.kind == "shape" and box.label == "line":
+ continue
+ tolerance = 0.0 if box.kind == "fraction" else 70.0
+ if (
+ box.x1 < safe.x1 - tolerance
+ or box.y1 < safe.y1 - tolerance
+ or box.x2 > safe.x2 + tolerance
+ or box.y2 > safe.y2 + tolerance
+ ):
+ issues.append(
+ Issue(
+ "error",
+ path,
+ f"Element hors panneau: {box.kind} {box.label!r} depasse la zone utile du panneau.",
+ )
+ )
+
+ for child in node:
+ issues.extend(validate_panel_containment(path, child, styles, ox, oy))
+ return issues
+
+
def validate_fraction_group(path: Path, group: ET.Element, styles: dict[str, dict[str, str]]) -> list[Issue]:
issues: list[Issue] = []
texts = [node for node in group if local_name(node.tag) == "text"]
@@ -257,7 +304,9 @@ def validate_fraction_group(path: Path, group: ET.Element, styles: dict[str, dic
num_size = font_size(numerator, styles)
den_size = font_size(denominator, styles)
- min_top_gap = max(8.0, num_size * 0.30)
+ # La baseline du numérateur est volontairement plus proche du trait que celle
+ # du dénominateur : c'est ce qui équilibre l'espace visible autour de la barre.
+ min_top_gap = max(8.0, num_size * 0.24)
min_bottom_gap = max(8.0, den_size * 0.30)
if bar_y - num_y < min_top_gap:
@@ -314,6 +363,7 @@ def validate_svg(path: Path) -> list[Issue]:
styles = parse_styles(root)
issues.extend(validate_layout_collisions(path, root, styles))
+ issues.extend(validate_panel_containment(path, root, styles))
for node in root.iter():
if local_name(node.tag) == "text":