phase 8
This commit is contained in:
@@ -21,6 +21,7 @@ from .curriculum import QUESTIONS
|
||||
from .program_content import (
|
||||
build_program_tree,
|
||||
decode_asset_token,
|
||||
format_adaptive_kit_context,
|
||||
get_content_status,
|
||||
get_lesson,
|
||||
list_lessons_for_grade,
|
||||
@@ -102,6 +103,18 @@ def build_student_program_response(student: models.Student, assignment: models.S
|
||||
)
|
||||
|
||||
|
||||
def format_student_adaptive_profile_context(profile: models.StudentAdaptiveProfile | None) -> str:
|
||||
if not profile:
|
||||
return ""
|
||||
return (
|
||||
"Profil adaptatif recommandé pour cet élève:\n"
|
||||
f"- Parcours: {profile.profile_title}\n"
|
||||
f"- Source: {profile.source}\n"
|
||||
f"- Notes professeur: {profile.notes or 'aucune'}\n"
|
||||
"Règle: utilise ce parcours comme aide prioritaire si l'élève hésite ou se trompe sur cette leçon.\n"
|
||||
)
|
||||
|
||||
|
||||
def clamp_lesson_position(lesson: dict, asset_index: int, section_index: int) -> tuple[int, int]:
|
||||
assets = lesson.get("assets") or []
|
||||
if not assets:
|
||||
@@ -427,6 +440,55 @@ def update_student_program_start(
|
||||
return build_student_program_response(student, assignment)
|
||||
|
||||
|
||||
@app.get("/admin/students/{student_id}/adaptive-profile", response_model=schemas.StudentAdaptiveProfileRead | None)
|
||||
def get_student_adaptive_profile(
|
||||
student_id: int,
|
||||
lesson_id: str,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: models.User = Depends(require_roles("teacher", "maintenance")),
|
||||
):
|
||||
student = db.query(models.Student).filter_by(id=student_id).first()
|
||||
if not student:
|
||||
raise HTTPException(status_code=404, detail="Élève introuvable")
|
||||
return (
|
||||
db.query(models.StudentAdaptiveProfile)
|
||||
.filter_by(student_id=student_id, lesson_id=lesson_id)
|
||||
.first()
|
||||
)
|
||||
|
||||
|
||||
@app.put("/admin/students/{student_id}/adaptive-profile", response_model=schemas.StudentAdaptiveProfileRead)
|
||||
def upsert_student_adaptive_profile(
|
||||
student_id: int,
|
||||
payload: schemas.StudentAdaptiveProfileRequest,
|
||||
db: Session = Depends(get_db),
|
||||
current_user: models.User = Depends(require_roles("teacher", "maintenance")),
|
||||
):
|
||||
student = db.query(models.Student).filter_by(id=student_id).first()
|
||||
if not student:
|
||||
raise HTTPException(status_code=404, detail="Élève introuvable")
|
||||
lesson = get_lesson(payload.lesson_id)
|
||||
if not lesson:
|
||||
raise HTTPException(status_code=404, detail="Leçon introuvable")
|
||||
|
||||
row = (
|
||||
db.query(models.StudentAdaptiveProfile)
|
||||
.filter_by(student_id=student_id, lesson_id=payload.lesson_id)
|
||||
.first()
|
||||
)
|
||||
if not row:
|
||||
row = models.StudentAdaptiveProfile(student_id=student_id, lesson_id=payload.lesson_id)
|
||||
row.diagnostic_id = payload.diagnostic_id
|
||||
row.profile_id = payload.profile_id
|
||||
row.profile_title = payload.profile_title
|
||||
row.notes = payload.notes
|
||||
row.source = payload.source
|
||||
db.add(row)
|
||||
db.commit()
|
||||
db.refresh(row)
|
||||
return row
|
||||
|
||||
|
||||
@app.get("/students/{student_id}/card-progress", response_model=list[schemas.LessonCardProgressRead])
|
||||
def list_card_progress(
|
||||
student_id: int,
|
||||
@@ -544,6 +606,17 @@ def start_session(
|
||||
)
|
||||
if first_section and first_section.get("context"):
|
||||
lesson_context += f"\nTexte pédagogique de la card courante:\n{first_section['context'].strip()}"
|
||||
adaptive_context = format_adaptive_kit_context(assigned_lesson)
|
||||
if adaptive_context:
|
||||
lesson_context += f"\n\n{adaptive_context}"
|
||||
adaptive_profile = (
|
||||
db.query(models.StudentAdaptiveProfile)
|
||||
.filter_by(student_id=student.id, lesson_id=assigned_lesson["id"])
|
||||
.first()
|
||||
)
|
||||
profile_context = format_student_adaptive_profile_context(adaptive_profile)
|
||||
if profile_context:
|
||||
lesson_context += f"\n\n{profile_context}"
|
||||
lesson_reply = build_lesson_reply(
|
||||
db,
|
||||
student.id,
|
||||
@@ -581,6 +654,7 @@ def chat(
|
||||
|
||||
lesson_context = ""
|
||||
if payload.lesson_title or payload.section_title or payload.asset_title:
|
||||
current_lesson = get_lesson(payload.lesson_id) if payload.lesson_id else None
|
||||
lesson_context = (
|
||||
f"Leçon courante: {payload.lesson_title or 'non précisée'}\n"
|
||||
f"Fiche courante: {payload.asset_title or 'non précisée'}\n"
|
||||
@@ -591,6 +665,18 @@ def chat(
|
||||
)
|
||||
if payload.section_context:
|
||||
lesson_context += f"\nTexte pédagogique de la card courante:\n{payload.section_context.strip()}"
|
||||
adaptive_context = format_adaptive_kit_context(current_lesson)
|
||||
if adaptive_context:
|
||||
lesson_context += f"\n\n{adaptive_context}"
|
||||
if current_lesson:
|
||||
adaptive_profile = (
|
||||
db.query(models.StudentAdaptiveProfile)
|
||||
.filter_by(student_id=student.id, lesson_id=current_lesson["id"])
|
||||
.first()
|
||||
)
|
||||
profile_context = format_student_adaptive_profile_context(adaptive_profile)
|
||||
if profile_context:
|
||||
lesson_context += f"\n\n{profile_context}"
|
||||
|
||||
if lesson_context:
|
||||
lesson_reply = build_lesson_reply(db, payload.student_id, payload.message, lesson_context)
|
||||
|
||||
@@ -121,6 +121,25 @@ class LessonCardProgress(Base):
|
||||
student = relationship("Student")
|
||||
|
||||
|
||||
class StudentAdaptiveProfile(Base):
|
||||
__tablename__ = "student_adaptive_profiles"
|
||||
__table_args__ = (
|
||||
UniqueConstraint("student_id", "lesson_id", name="uq_student_adaptive_lesson"),
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
student_id: Mapped[int] = mapped_column(ForeignKey("students.id"), index=True)
|
||||
lesson_id: Mapped[str] = mapped_column(String(500), index=True)
|
||||
diagnostic_id: Mapped[str | None] = mapped_column(String(500), nullable=True)
|
||||
profile_id: Mapped[str] = mapped_column(String(500))
|
||||
profile_title: Mapped[str] = mapped_column(String(255))
|
||||
notes: Mapped[str] = mapped_column(Text, default="")
|
||||
source: Mapped[str] = mapped_column(String(50), default="teacher")
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
|
||||
student = relationship("Student")
|
||||
|
||||
|
||||
class AssessmentAttempt(Base):
|
||||
__tablename__ = "assessment_attempts"
|
||||
|
||||
|
||||
@@ -250,6 +250,7 @@ def list_lessons() -> list[dict]:
|
||||
"cycle": cycle,
|
||||
"asset_count": len(assets),
|
||||
"assets": assets,
|
||||
"adaptive_kit": collect_adaptive_kit(lesson_dir),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -297,6 +298,7 @@ def save_review_state(state: dict) -> None:
|
||||
|
||||
def collect_lesson_status(lesson: dict) -> dict:
|
||||
lesson_dir = CONTENT_ROOT / lesson["id"]
|
||||
kit_dir = lesson_dir / "kit_adaptatif"
|
||||
return {
|
||||
"micro_fiches": len([path for path in lesson_dir.glob("*.md") if path.name.startswith(tuple("0123456789"))]),
|
||||
"lesson_svg": len(lesson.get("assets") or []),
|
||||
@@ -304,6 +306,9 @@ def collect_lesson_status(lesson: dict) -> dict:
|
||||
"contexts": len(list((lesson_dir / "card_contexts").rglob("Fiche*Card*.md"))),
|
||||
"text_exercises": len(list((lesson_dir / "exercices").rglob("exercices.md"))),
|
||||
"exercise_svg": len(list((lesson_dir / "exercices_svg").glob("*.svg"))),
|
||||
"adaptive_tests": len([path for path in (kit_dir / "test_diagnostic").glob("*.md") if path.name != "README.md"]) if kit_dir.exists() else 0,
|
||||
"adaptive_profiles": len([path for path in (kit_dir / "parcours_profils").glob("*.md") if path.name != "README.md"]) if kit_dir.exists() else 0,
|
||||
"adaptive_svg": len(list((kit_dir / "svg").glob("*.svg"))) if kit_dir.exists() else 0,
|
||||
"validations": sorted(path.stem for path in lesson_dir.glob("VALIDATION_PHASE_*.md")),
|
||||
}
|
||||
|
||||
@@ -318,6 +323,69 @@ def append_tree_child(parent: dict, key: str, label: str, node_type: str, path:
|
||||
return child
|
||||
|
||||
|
||||
def read_review_text(path: Path, max_chars: int = 6000) -> str:
|
||||
text = path.read_text(encoding="utf-8", errors="ignore").strip()
|
||||
return text[:max_chars]
|
||||
|
||||
|
||||
def collect_adaptive_kit(lesson_dir: Path) -> dict | None:
|
||||
kit_dir = lesson_dir / "kit_adaptatif"
|
||||
if not kit_dir.exists():
|
||||
return None
|
||||
|
||||
def markdown_items(folder: str) -> list[dict]:
|
||||
base = kit_dir / folder
|
||||
if not base.exists():
|
||||
return []
|
||||
return [
|
||||
{
|
||||
"id": path.relative_to(CONTENT_ROOT).as_posix(),
|
||||
"title": title_from_slug(path.stem),
|
||||
"content": read_review_text(path),
|
||||
}
|
||||
for path in sorted(base.glob("*.md"))
|
||||
if path.name != "README.md"
|
||||
]
|
||||
|
||||
supports = []
|
||||
svg_dir = kit_dir / "svg"
|
||||
if svg_dir.exists():
|
||||
for path in sorted(svg_dir.glob("*.svg")):
|
||||
relative = path.relative_to(CONTENT_ROOT).as_posix()
|
||||
supports.append(
|
||||
{
|
||||
"id": relative,
|
||||
"title": title_from_slug(path.stem),
|
||||
"url": build_asset_url(relative),
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
"id": kit_dir.relative_to(CONTENT_ROOT).as_posix(),
|
||||
"title": "Kit adaptatif",
|
||||
"diagnostics": markdown_items("test_diagnostic"),
|
||||
"profiles": markdown_items("parcours_profils"),
|
||||
"supports": supports,
|
||||
}
|
||||
|
||||
|
||||
def format_adaptive_kit_context(lesson: dict | None) -> str:
|
||||
kit = (lesson or {}).get("adaptive_kit")
|
||||
if not kit:
|
||||
return ""
|
||||
|
||||
diagnostics = ", ".join(item["title"] for item in kit.get("diagnostics") or [])
|
||||
profiles = ", ".join(item["title"] for item in kit.get("profiles") or [])
|
||||
return (
|
||||
"Kit adaptatif disponible pour cette leçon.\n"
|
||||
f"Tests diagnostics: {diagnostics or 'aucun'}.\n"
|
||||
f"Parcours de reprise: {profiles or 'aucun'}.\n"
|
||||
"Règle adaptative: si l'élève se trompe nettement, semble bloqué, inverse les notions ou demande de l'aide, "
|
||||
"ne change pas de card tout de suite. Propose une micro-question de diagnostic liée à la difficulté observée, "
|
||||
"puis oriente vers le parcours le plus probable en une phrase courte.\n"
|
||||
)
|
||||
|
||||
|
||||
def build_program_tree() -> dict:
|
||||
reviews = load_review_state()
|
||||
root = {
|
||||
@@ -365,6 +433,37 @@ def build_program_tree() -> dict:
|
||||
)
|
||||
section_node["url"] = section.get("url")
|
||||
section_node["review"] = reviews.get(section_key, {})
|
||||
lesson_dir = CONTENT_ROOT / lesson["id"]
|
||||
kit_dir = lesson_dir / "kit_adaptatif"
|
||||
if kit_dir.exists():
|
||||
kit_key = f"{lesson['id']}/kit_adaptatif"
|
||||
kit_node = append_tree_child(lesson_node, kit_key, "Kit adaptatif", "kit", kit_key)
|
||||
kit_node["review"] = reviews.get(kit_key, {})
|
||||
|
||||
tests_node = append_tree_child(kit_node, f"{kit_key}/test_diagnostic", "Tests diagnostics", "group", f"{kit_key}/test_diagnostic")
|
||||
for test_path in sorted((kit_dir / "test_diagnostic").glob("*.md")):
|
||||
if test_path.name == "README.md":
|
||||
continue
|
||||
relative = test_path.relative_to(CONTENT_ROOT).as_posix()
|
||||
test_node = append_tree_child(tests_node, relative, title_from_slug(test_path.stem), "diagnostic", relative)
|
||||
test_node["content"] = read_review_text(test_path)
|
||||
test_node["review"] = reviews.get(relative, {})
|
||||
|
||||
profiles_node = append_tree_child(kit_node, f"{kit_key}/parcours_profils", "Parcours profils", "group", f"{kit_key}/parcours_profils")
|
||||
for profile_path in sorted((kit_dir / "parcours_profils").glob("*.md")):
|
||||
if profile_path.name == "README.md":
|
||||
continue
|
||||
relative = profile_path.relative_to(CONTENT_ROOT).as_posix()
|
||||
profile_node = append_tree_child(profiles_node, relative, title_from_slug(profile_path.stem), "parcours", relative)
|
||||
profile_node["content"] = read_review_text(profile_path)
|
||||
profile_node["review"] = reviews.get(relative, {})
|
||||
|
||||
svg_node = append_tree_child(kit_node, f"{kit_key}/svg", "Supports visuels", "group", f"{kit_key}/svg")
|
||||
for svg_path in sorted((kit_dir / "svg").glob("*.svg")):
|
||||
relative = svg_path.relative_to(CONTENT_ROOT).as_posix()
|
||||
support_node = append_tree_child(svg_node, relative, title_from_slug(svg_path.stem), "support", relative)
|
||||
support_node["url"] = build_asset_url(relative)
|
||||
support_node["review"] = reviews.get(relative, {})
|
||||
return root
|
||||
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ class StudentAccountResponse(BaseModel):
|
||||
class ChatRequest(BaseModel):
|
||||
student_id: int
|
||||
message: str
|
||||
lesson_id: str | None = None
|
||||
lesson_title: str | None = None
|
||||
asset_title: str | None = None
|
||||
section_title: str | None = None
|
||||
@@ -124,6 +125,7 @@ class ProgramLesson(BaseModel):
|
||||
cycle: str
|
||||
asset_count: int
|
||||
assets: List[ProgramAsset] = []
|
||||
adaptive_kit: dict[str, Any] | None = None
|
||||
|
||||
|
||||
class ProgramLessonListResponse(BaseModel):
|
||||
@@ -152,6 +154,30 @@ class StudentProgramStartRequest(BaseModel):
|
||||
section_index: int = Field(..., ge=0)
|
||||
|
||||
|
||||
class StudentAdaptiveProfileRequest(BaseModel):
|
||||
lesson_id: str = Field(..., min_length=1)
|
||||
diagnostic_id: str | None = None
|
||||
profile_id: str = Field(..., min_length=1)
|
||||
profile_title: str = Field(..., min_length=1)
|
||||
notes: str = ""
|
||||
source: str = "teacher"
|
||||
|
||||
|
||||
class StudentAdaptiveProfileRead(BaseModel):
|
||||
id: int
|
||||
student_id: int
|
||||
lesson_id: str
|
||||
diagnostic_id: str | None = None
|
||||
profile_id: str
|
||||
profile_title: str
|
||||
notes: str
|
||||
source: str
|
||||
updated_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class LessonCardState(BaseModel):
|
||||
lesson_id: str
|
||||
asset_path: str
|
||||
|
||||
@@ -129,3 +129,17 @@ Organisation :
|
||||
- `exercices_svg/08_fraction_d_une_quantite.svg`
|
||||
|
||||
Statut : SVG exercices initiaux prets pour relecture Phase 6B.
|
||||
|
||||
## Kit adaptatif genere
|
||||
|
||||
Phase 7A : un kit adaptatif de sous-theme est genere dans `kit_adaptatif/`.
|
||||
|
||||
Organisation :
|
||||
|
||||
- `kit_adaptatif/00_principe_adaptatif.md` : profils observables et erreurs a reperer.
|
||||
- `kit_adaptatif/routage.md` : choix du parcours apres diagnostic.
|
||||
- `kit_adaptatif/test_diagnostic/` : 4 tests courts.
|
||||
- `kit_adaptatif/parcours_profils/` : 5 parcours de reprise.
|
||||
- `kit_adaptatif/svg/` : 2 supports visuels XML valides.
|
||||
|
||||
Statut : kit adaptatif initial pret pour relecture Phase 7B.
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# Principe adaptatif - fractions CM1
|
||||
|
||||
## Compétence cible
|
||||
|
||||
Comprendre une fraction simple comme un nombre qui exprime des parts égales d'une unité, puis utiliser cette compréhension pour lire, représenter, comparer et calculer avec des fractions simples.
|
||||
|
||||
## Faiblesses à détecter
|
||||
|
||||
- l'élève inverse numérateur et dénominateur ;
|
||||
- l'élève oublie que les parts doivent être égales ;
|
||||
- l'élève lit une fraction chiffre par chiffre sans utiliser les mots `demi`, `tiers`, `quart`, `cinquième` ;
|
||||
- l'élève ne sait pas relier fraction et dessin ;
|
||||
- l'élève place une fraction sur une demi-droite comme un entier isolé ;
|
||||
- l'élève compare seulement les nombres du haut ou seulement les nombres du bas ;
|
||||
- l'élève ne distingue pas fraction inférieure, égale ou supérieure à `1` ;
|
||||
- l'élève réussit un exercice visuel mais se bloque dès que la consigne devient verbale.
|
||||
|
||||
## Profils pédagogiques observables
|
||||
|
||||
### 1. Visuel et partage
|
||||
|
||||
L'élève comprend mieux avec une unité dessinée, des parts colorées, des bandes ou des disques fractionnés.
|
||||
|
||||
### 2. Verbal et vocabulaire
|
||||
|
||||
L'élève a besoin de dire les fractions, d'entendre les mots et de stabiliser le vocabulaire : numérateur, dénominateur, unité, parts égales.
|
||||
|
||||
### 3. Manipulation et concret
|
||||
|
||||
L'élève progresse avec des situations de partage : gâteau, bande, tablette, collection d'objets, recette.
|
||||
|
||||
### 4. Repères et demi-droite
|
||||
|
||||
L'élève doit travailler le passage de la fraction dessinée à la fraction placée sur une ligne graduée.
|
||||
|
||||
### 5. Progressif et charge réduite
|
||||
|
||||
L'élève sait parfois faire, mais se trompe quand il y a trop d'informations à traiter en même temps.
|
||||
|
||||
## Règle générale
|
||||
|
||||
Le diagnostic ne doit pas coller une étiquette à l'élève. Il sert seulement à choisir la meilleure première aide.
|
||||
|
||||
Professeur TOP doit pouvoir combiner deux profils si les réponses le justifient, par exemple `visuel et partage` puis `verbal et vocabulaire`.
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# Kit adaptatif - 01B fractions
|
||||
|
||||
## Rôle du dossier
|
||||
|
||||
Ce kit transforme le sous-thème `01B_fractions` en parcours adaptatif pour Professeur TOP.
|
||||
|
||||
Il sert à choisir rapidement une entrée de travail adaptée à l'élève après quelques réponses courtes :
|
||||
|
||||
- lecture et écriture des fractions simples ;
|
||||
- représentation d'un partage ;
|
||||
- placement sur demi-droite graduée ;
|
||||
- comparaison et encadrement ;
|
||||
- petites opérations sur fractions de même dénominateur ;
|
||||
- fraction d'une quantité.
|
||||
|
||||
## Structure
|
||||
|
||||
- `00_principe_adaptatif.md` : logique générale, erreurs à repérer et profils observables.
|
||||
- `routage.md` : règles d'orientation après diagnostic.
|
||||
- `test_diagnostic/` : tests courts à utiliser avant de choisir un parcours.
|
||||
- `parcours_profils/` : exercices et reprises classés par profil pédagogique.
|
||||
- `svg/` : supports visuels du diagnostic et des parcours.
|
||||
|
||||
## Statut
|
||||
|
||||
Phase `7A` : kit adaptatif généré pour revue.
|
||||
|
||||
Les contenus restent éditoriaux : ils devront être validés dans l'interface avant assimilation complète au programme actif.
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# Parcours 01 - Visuel et partage
|
||||
|
||||
## Pour quel élève ?
|
||||
|
||||
L'élève se trompe sur les parts égales, le sens du numérateur ou la comparaison de fractions représentées.
|
||||
|
||||
## Reprise courte
|
||||
|
||||
Une fraction parle toujours d'une unité. On partage cette unité en parts égales. Le dénominateur dit combien il y a de parts égales. Le numérateur dit combien de parts on prend.
|
||||
|
||||
## Exercices
|
||||
|
||||
1. Dessine une bande en `5` parts égales et colorie `2` parts. Écris la fraction.
|
||||
2. Parmi deux dessins, choisis celui qui représente vraiment `3/4`.
|
||||
3. Colorie `4/6` d'une bande déjà partagée.
|
||||
4. Explique pourquoi un dessin avec des parts inégales ne convient pas.
|
||||
|
||||
## Réponses attendues
|
||||
|
||||
- `2/5`
|
||||
- dessin avec quatre parts égales dont trois coloriées ;
|
||||
- quatre parts coloriées sur six ;
|
||||
- les parts doivent avoir la même taille pour compter correctement.
|
||||
|
||||
## Retour programme
|
||||
|
||||
Reprendre la fiche `02_representer_fraction_partage`.
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
# Parcours 02 - Verbal et vocabulaire
|
||||
|
||||
## Pour quel élève ?
|
||||
|
||||
L'élève inverse numérateur et dénominateur, lit mal les fractions ou manque de mots pour expliquer.
|
||||
|
||||
## Reprise courte
|
||||
|
||||
Dans `3/4`, je lis d'abord le nombre du haut : `3`. Il dit combien de parts sont prises. Puis je lis le nombre du bas : `4`. Il dit en combien de parts égales l'unité est partagée.
|
||||
|
||||
## Exercices
|
||||
|
||||
1. Lis `1/2`, `2/3`, `3/4`, `5/8`.
|
||||
2. Dans `6/10`, entoure le numérateur.
|
||||
3. Dans `6/10`, souligne le dénominateur.
|
||||
4. Écris en fraction : `sept dixièmes`.
|
||||
5. Complète : le dénominateur indique `...`.
|
||||
|
||||
## Réponses attendues
|
||||
|
||||
- `un demi`, `deux tiers`, `trois quarts`, `cinq huitièmes` ;
|
||||
- numérateur `6` ;
|
||||
- dénominateur `10` ;
|
||||
- `7/10` ;
|
||||
- le nombre de parts égales dans l'unité.
|
||||
|
||||
## Retour programme
|
||||
|
||||
Reprendre la fiche `01_lire_ecrire_fraction_simple`.
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# Parcours 03 - Manipulation et concret
|
||||
|
||||
## Pour quel élève ?
|
||||
|
||||
L'élève comprend mieux quand la fraction est reliée à une situation réelle.
|
||||
|
||||
## Reprise courte
|
||||
|
||||
Une fraction peut dire une part de gâteau, une longueur de ruban, une partie d'une tablette ou une part d'une collection.
|
||||
|
||||
## Exercices
|
||||
|
||||
1. Une tablette a `8` carrés. On mange `3` carrés. Quelle fraction de la tablette est mangée ?
|
||||
2. Une bande mesure une unité. Elle est partagée en `6` morceaux égaux. On garde `5` morceaux. Quelle fraction est gardée ?
|
||||
3. Il y a `12` jetons. On prend le quart. Combien de jetons prend-on ?
|
||||
4. Explique `2/3` avec une situation de partage.
|
||||
|
||||
## Réponses attendues
|
||||
|
||||
- `3/8`
|
||||
- `5/6`
|
||||
- `3` jetons
|
||||
- situation où une unité ou une collection est partagée en trois parts égales et deux parts sont prises.
|
||||
|
||||
## Retour programme
|
||||
|
||||
Reprendre les fiches `02_representer_fraction_partage` et `08_fraction_d_une_quantite`.
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# Parcours 04 - Repères et demi-droite
|
||||
|
||||
## Pour quel élève ?
|
||||
|
||||
L'élève a besoin de relier fractions, graduations et position entre deux entiers.
|
||||
|
||||
## Reprise courte
|
||||
|
||||
Sur une demi-droite, le dénominateur dit en combien d'intervalles égaux on partage l'unité. Le numérateur dit combien d'intervalles on avance depuis `0`.
|
||||
|
||||
## Exercices
|
||||
|
||||
1. Partage l'intervalle de `0` à `1` en `4` parties égales.
|
||||
2. Place `1/4`, `2/4`, `3/4`.
|
||||
3. Place `5/4` et explique pourquoi il est après `1`.
|
||||
4. Encadre `9/4` entre deux entiers.
|
||||
|
||||
## Réponses attendues
|
||||
|
||||
- quatre intervalles égaux entre `0` et `1` ;
|
||||
- fractions placées dans l'ordre ;
|
||||
- `5/4` est une unité complète plus `1/4` ;
|
||||
- `9/4` est entre `2` et `3`.
|
||||
|
||||
## Retour programme
|
||||
|
||||
Reprendre les fiches `03_fraction_sur_demi_droite_graduee`, `04_fraction_superieure_a_un` et `06_encadrer_fraction_entre_entiers`.
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
# Parcours 05 - Progressif et charge réduite
|
||||
|
||||
## Pour quel élève ?
|
||||
|
||||
L'élève comprend une notion isolée mais se trompe quand la page contient trop d'informations.
|
||||
|
||||
## Reprise courte
|
||||
|
||||
On traite une seule idée à la fois : lire, puis représenter, puis comparer.
|
||||
|
||||
## Exercices
|
||||
|
||||
### Étape 1 - Lire
|
||||
|
||||
Lis seulement `3/4`.
|
||||
|
||||
Réponse : `trois quarts`.
|
||||
|
||||
### Étape 2 - Nommer
|
||||
|
||||
Dans `3/4`, indique seulement le dénominateur.
|
||||
|
||||
Réponse : `4`.
|
||||
|
||||
### Étape 3 - Dessiner
|
||||
|
||||
Dessine une bande en `4` parts égales.
|
||||
|
||||
Réponse : quatre parts de même taille.
|
||||
|
||||
### Étape 4 - Colorier
|
||||
|
||||
Colorie `3` parts.
|
||||
|
||||
Réponse : trois parts coloriées sur quatre.
|
||||
|
||||
### Étape 5 - Résumer
|
||||
|
||||
Écris la phrase : `3/4 signifie 3 parts prises sur 4 parts égales`.
|
||||
|
||||
## Retour programme
|
||||
|
||||
Reprendre la fiche correspondant à l'étape qui a bloqué.
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# Parcours par profils observables
|
||||
|
||||
Chaque dossier propose une reprise ciblée après diagnostic.
|
||||
|
||||
Les parcours peuvent être combinés. Par exemple, un élève peut commencer par `01_visuel_partage`, puis passer à `02_verbal_vocabulaire` pour stabiliser les mots.
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
# Routage adaptatif - fractions CM1
|
||||
|
||||
## Entrées observables
|
||||
|
||||
| Observation | Orientation principale | Orientation secondaire |
|
||||
| --- | --- | --- |
|
||||
| Inverse haut et bas dans `3/4` | `02_verbal_vocabulaire` | `01_visuel_partage` |
|
||||
| Colorie des parts inégales | `01_visuel_partage` | `03_manipulation_concret` |
|
||||
| Lit `5/8` comme `cinq barre huit` | `02_verbal_vocabulaire` | `05_progressif_charge_reduite` |
|
||||
| Place `3/4` après `3` sur la demi-droite | `04_reperes_demi_droite` | `01_visuel_partage` |
|
||||
| Compare `2/5` et `4/5` en regardant le dénominateur | `01_visuel_partage` | `02_verbal_vocabulaire` |
|
||||
| Se perd dans les énoncés longs | `05_progressif_charge_reduite` | profil dominant repéré |
|
||||
| Comprend avec objets mais pas avec symboles | `03_manipulation_concret` | `02_verbal_vocabulaire` |
|
||||
|
||||
## Décision rapide
|
||||
|
||||
1. Faire passer les quatre tests courts.
|
||||
2. Noter les erreurs, mais aussi les hésitations et reformulations spontanées.
|
||||
3. Choisir un parcours principal.
|
||||
4. Ajouter un parcours secondaire si deux difficultés sont nettes.
|
||||
5. Revenir ensuite à la fiche ou card du programme correspondant à la difficulté.
|
||||
|
||||
## Retour au programme
|
||||
|
||||
- Erreur sur lecture/écriture : reprendre `01_lire_ecrire_fraction_simple`.
|
||||
- Erreur sur dessin : reprendre `02_representer_fraction_partage`.
|
||||
- Erreur sur ligne graduée : reprendre `03_fraction_sur_demi_droite_graduee`.
|
||||
- Erreur sur `> 1` : reprendre `04_fraction_superieure_a_un`.
|
||||
- Erreur de comparaison : reprendre `05_comparer_fractions_simples`.
|
||||
- Erreur d'encadrement : reprendre `06_encadrer_fraction_entre_entiers`.
|
||||
- Erreur d'addition/soustraction : reprendre `07_additionner_soustraire_fractions_simples`.
|
||||
- Erreur sur collection : reprendre `08_fraction_d_une_quantite`.
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
# SVG du kit adaptatif fractions
|
||||
|
||||
Ces visuels servent de supports simples pour les tests et les parcours.
|
||||
|
||||
Ils sont volontairement moins denses que les fiches de leçon : chaque SVG porte une seule décision pédagogique.
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="760" viewBox="0 0 1200 760">
|
||||
<rect width="1200" height="760" fill="#f7fafc"/>
|
||||
<rect x="60" y="50" width="1080" height="660" rx="28" fill="#ffffff" stroke="#d7e3df" stroke-width="6"/>
|
||||
<text x="100" y="120" font-family="Inter, Arial, sans-serif" font-size="44" font-weight="700" fill="#0f3d5e">Aide fractions</text>
|
||||
<text x="100" y="170" font-family="Inter, Arial, sans-serif" font-size="24" fill="#415466">Une unité, des parts égales, des parts prises.</text>
|
||||
|
||||
<rect x="120" y="230" width="420" height="160" rx="20" fill="#eef6ff" stroke="#bfd7f2"/>
|
||||
<text x="150" y="280" font-family="Inter, Arial, sans-serif" font-size="30" font-weight="700" fill="#0f3d5e">3/4</text>
|
||||
<text x="230" y="270" font-family="Inter, Arial, sans-serif" font-size="24" fill="#415466">3 parts prises</text>
|
||||
<text x="230" y="325" font-family="Inter, Arial, sans-serif" font-size="24" fill="#415466">4 parts égales</text>
|
||||
<line x1="150" y1="296" x2="205" y2="296" stroke="#1f2937" stroke-width="4"/>
|
||||
|
||||
<rect x="660" y="230" width="360" height="160" rx="20" fill="#fff7ed" stroke="#fed7aa"/>
|
||||
<rect x="720" y="292" width="240" height="58" fill="#ffffff" stroke="#1f2937" stroke-width="3"/>
|
||||
<line x1="780" y1="292" x2="780" y2="350" stroke="#1f2937" stroke-width="2"/>
|
||||
<line x1="840" y1="292" x2="840" y2="350" stroke="#1f2937" stroke-width="2"/>
|
||||
<line x1="900" y1="292" x2="900" y2="350" stroke="#1f2937" stroke-width="2"/>
|
||||
<rect x="720" y="292" width="180" height="58" fill="#f97316" opacity="0.45"/>
|
||||
<text x="716" y="380" font-family="Inter, Arial, sans-serif" font-size="22" fill="#415466">3 parts sur 4</text>
|
||||
|
||||
<rect x="120" y="460" width="900" height="120" rx="20" fill="#f0fdf4" stroke="#bbf7d0"/>
|
||||
<line x1="200" y1="530" x2="900" y2="530" stroke="#1f2937" stroke-width="4"/>
|
||||
<line x1="200" y1="515" x2="200" y2="545" stroke="#1f2937" stroke-width="3"/>
|
||||
<line x1="900" y1="515" x2="900" y2="545" stroke="#1f2937" stroke-width="3"/>
|
||||
<line x1="375" y1="520" x2="375" y2="540" stroke="#64748b" stroke-width="2"/>
|
||||
<line x1="550" y1="520" x2="550" y2="540" stroke="#64748b" stroke-width="2"/>
|
||||
<line x1="725" y1="520" x2="725" y2="540" stroke="#64748b" stroke-width="2"/>
|
||||
<circle cx="725" cy="530" r="10" fill="#16a34a"/>
|
||||
<text x="190" y="570" font-family="Inter, Arial, sans-serif" font-size="20" fill="#1f2937">0</text>
|
||||
<text x="893" y="570" font-family="Inter, Arial, sans-serif" font-size="20" fill="#1f2937">1</text>
|
||||
<text x="700" y="500" font-family="Inter, Arial, sans-serif" font-size="24" font-weight="700" fill="#166534">3/4</text>
|
||||
</svg>
|
||||
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
@@ -0,0 +1,36 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="760" viewBox="0 0 1200 760">
|
||||
<rect width="1200" height="760" fill="#f7fafc"/>
|
||||
<rect x="60" y="50" width="1080" height="660" rx="28" fill="#ffffff" stroke="#d7e3df" stroke-width="6"/>
|
||||
<text x="100" y="120" font-family="Inter, Arial, sans-serif" font-size="44" font-weight="700" fill="#0f3d5e">Diagnostic fractions</text>
|
||||
<text x="100" y="170" font-family="Inter, Arial, sans-serif" font-size="24" fill="#415466">Lis, dessine, place, puis compare.</text>
|
||||
|
||||
<rect x="100" y="220" width="230" height="160" rx="18" fill="#eef6ff" stroke="#bfd7f2"/>
|
||||
<text x="130" y="270" font-family="Inter, Arial, sans-serif" font-size="28" font-weight="700" fill="#0f3d5e">1. Lire</text>
|
||||
<text x="175" y="340" font-family="Inter, Arial, sans-serif" font-size="54" font-weight="700" fill="#1f2937">3/4</text>
|
||||
|
||||
<rect x="365" y="220" width="230" height="160" rx="18" fill="#fff7ed" stroke="#fed7aa"/>
|
||||
<text x="395" y="270" font-family="Inter, Arial, sans-serif" font-size="28" font-weight="700" fill="#9a3412">2. Partager</text>
|
||||
<rect x="410" y="310" width="140" height="44" fill="#ffffff" stroke="#1f2937" stroke-width="3"/>
|
||||
<line x1="445" y1="310" x2="445" y2="354" stroke="#1f2937" stroke-width="2"/>
|
||||
<line x1="480" y1="310" x2="480" y2="354" stroke="#1f2937" stroke-width="2"/>
|
||||
<line x1="515" y1="310" x2="515" y2="354" stroke="#1f2937" stroke-width="2"/>
|
||||
<rect x="410" y="310" width="105" height="44" fill="#f97316" opacity="0.45"/>
|
||||
|
||||
<rect x="630" y="220" width="230" height="160" rx="18" fill="#f0fdf4" stroke="#bbf7d0"/>
|
||||
<text x="660" y="270" font-family="Inter, Arial, sans-serif" font-size="28" font-weight="700" fill="#166534">3. Placer</text>
|
||||
<line x1="680" y1="335" x2="815" y2="335" stroke="#1f2937" stroke-width="4"/>
|
||||
<line x1="680" y1="325" x2="680" y2="345" stroke="#1f2937" stroke-width="3"/>
|
||||
<line x1="815" y1="325" x2="815" y2="345" stroke="#1f2937" stroke-width="3"/>
|
||||
<circle cx="781" cy="335" r="9" fill="#16a34a"/>
|
||||
<text x="670" y="370" font-family="Inter, Arial, sans-serif" font-size="18" fill="#1f2937">0</text>
|
||||
<text x="808" y="370" font-family="Inter, Arial, sans-serif" font-size="18" fill="#1f2937">1</text>
|
||||
|
||||
<rect x="895" y="220" width="205" height="160" rx="18" fill="#fef2f2" stroke="#fecaca"/>
|
||||
<text x="925" y="270" font-family="Inter, Arial, sans-serif" font-size="28" font-weight="700" fill="#991b1b">4. Comparer</text>
|
||||
<text x="940" y="340" font-family="Inter, Arial, sans-serif" font-size="42" font-weight="700" fill="#1f2937">2/5 ? 4/5</text>
|
||||
|
||||
<rect x="120" y="460" width="960" height="140" rx="20" fill="#f8fafc" stroke="#dbe3ef"/>
|
||||
<text x="160" y="520" font-family="Inter, Arial, sans-serif" font-size="28" font-weight="700" fill="#0f3d5e">Observer surtout les erreurs, les hésitations et les mots utilisés.</text>
|
||||
<text x="160" y="565" font-family="Inter, Arial, sans-serif" font-size="24" fill="#415466">Le diagnostic choisit une aide. Il ne note pas l'élève.</text>
|
||||
</svg>
|
||||
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
@@ -0,0 +1,26 @@
|
||||
# Test 01 - Lecture et vocabulaire
|
||||
|
||||
## Objectif
|
||||
|
||||
Repérer si l'élève sait lire une fraction et identifier numérateur et dénominateur.
|
||||
|
||||
## Questions
|
||||
|
||||
1. Lis `3/4`.
|
||||
2. Dans `3/4`, quel nombre indique le nombre de parts prises ?
|
||||
3. Dans `3/4`, quel nombre indique le nombre de parts égales dans l'unité ?
|
||||
4. Écris en fraction : `deux cinquièmes`.
|
||||
|
||||
## Réponses attendues
|
||||
|
||||
1. `trois quarts`.
|
||||
2. `3`, le numérateur.
|
||||
3. `4`, le dénominateur.
|
||||
4. `2/5`.
|
||||
|
||||
## Indices d'orientation
|
||||
|
||||
- Inversion haut/bas : parcours `02_verbal_vocabulaire`.
|
||||
- Lecture chiffre par chiffre : parcours `02_verbal_vocabulaire`.
|
||||
- Réussite orale mais erreur écrite : parcours `05_progressif_charge_reduite`.
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# Test 02 - Partage de l'unité
|
||||
|
||||
## Objectif
|
||||
|
||||
Vérifier que l'élève relie une fraction à des parts égales d'une unité.
|
||||
|
||||
## Questions
|
||||
|
||||
1. Dessine une bande partagée en `4` parts égales.
|
||||
2. Colorie `3` parts.
|
||||
3. Écris la fraction coloriée.
|
||||
4. Explique pourquoi les parts doivent être égales.
|
||||
|
||||
## Réponses attendues
|
||||
|
||||
- Bande partagée en quatre parts de même taille.
|
||||
- Trois parts coloriées.
|
||||
- Fraction `3/4`.
|
||||
- Réponse attendue : sinon la fraction ne décrit pas correctement le partage de l'unité.
|
||||
|
||||
## Indices d'orientation
|
||||
|
||||
- Parts inégales : parcours `01_visuel_partage`.
|
||||
- Bon dessin mais explication faible : parcours `02_verbal_vocabulaire`.
|
||||
- Besoin d'une situation concrète : parcours `03_manipulation_concret`.
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# Test 03 - Demi-droite graduée
|
||||
|
||||
## Objectif
|
||||
|
||||
Voir si l'élève comprend qu'une fraction peut être placée entre deux nombres entiers.
|
||||
|
||||
## Questions
|
||||
|
||||
1. On partage le segment entre `0` et `1` en `4` parts égales.
|
||||
2. Place `1/4`, `2/4` et `3/4`.
|
||||
3. Quelle fraction est la plus proche de `1` ?
|
||||
4. `5/4` est-il avant ou après `1` ?
|
||||
|
||||
## Réponses attendues
|
||||
|
||||
- `1/4`, `2/4`, `3/4` placés dans l'ordre entre `0` et `1`.
|
||||
- `3/4` est la plus proche de `1`.
|
||||
- `5/4` est après `1`.
|
||||
|
||||
## Indices d'orientation
|
||||
|
||||
- Place `3/4` après `3` : parcours `04_reperes_demi_droite`.
|
||||
- Confond `4` graduations et `4` intervalles : parcours `04_reperes_demi_droite`.
|
||||
- Comprend avec bande mais pas avec ligne : combiner `01_visuel_partage` puis `04_reperes_demi_droite`.
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# Test 04 - Comparer et expliquer
|
||||
|
||||
## Objectif
|
||||
|
||||
Repérer si l'élève compare les fractions avec le bon critère.
|
||||
|
||||
## Questions
|
||||
|
||||
1. Compare `2/5` et `4/5`.
|
||||
2. Compare `1/2` et `1/4`.
|
||||
3. Complète : `7/4` est entre `...` et `...`.
|
||||
4. Explique avec tes mots pourquoi `4/5` est plus grand que `2/5`.
|
||||
|
||||
## Réponses attendues
|
||||
|
||||
- `4/5 > 2/5`.
|
||||
- `1/2 > 1/4`.
|
||||
- `7/4` est entre `1` et `2`.
|
||||
- Pour le même dénominateur, plus le numérateur est grand, plus on prend de parts.
|
||||
|
||||
## Indices d'orientation
|
||||
|
||||
- Compare seulement les dénominateurs : parcours `01_visuel_partage`.
|
||||
- Ne sait pas encadrer `7/4` : reprendre `04_reperes_demi_droite`.
|
||||
- Bonne comparaison mais justification fragile : parcours `02_verbal_vocabulaire`.
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
# Tests diagnostics - fractions CM1
|
||||
|
||||
Ces tests sont courts et doivent être utilisés avant de choisir un parcours adaptatif.
|
||||
|
||||
Ils ne servent pas à noter l'élève. Ils servent à comprendre quelle aide sera la plus efficace.
|
||||
|
||||
Ordre conseillé :
|
||||
|
||||
1. `01_lecture_vocabulaire.md`
|
||||
2. `02_partage_unite.md`
|
||||
3. `03_demi_droite.md`
|
||||
4. `04_comparer_expliquer.md`
|
||||
|
||||
Reference in New Issue
Block a user