{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"color:white;border-collapse:separate;border:solid 2px;border-radius:14px;border-color:#1a237e;background-color:#283593;width:100%;padding:6px 0;\">\n",
    "    <div style=\"display:flex;\">\n",
    "        <div style=\"display:inline;width:20%;text-align:left;padding-left:10px;\"><b>Classe Seconde</b></div>\n",
    "        <div style=\"display:inline;width:60%;text-align:center;\"></div>\n",
    "        <div style=\"display:inline;width:20%;text-align:right;padding-right:10px;\"><b>SNT</b></div>\n",
    "    </div>\n",
    "    <h1 style=\"color:white;text-align:center;font-size:1.7em;margin:0.4em 0;\">🕵️ Escape Game — Cyber-enquête à La Flèche</h1>\n",
    "    <div style=\"text-align:center;font-style:italic;\">Sciences Numériques et Technologie · 6 énigmes · ~1h30</div>\n",
    "</div>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 🎬 Le mystère\n",
    "\n",
    "Une cyber-enquête frappe La Flèche. Un message chiffré a été retrouvé sur le smartphone d'un témoin.\n",
    "\n",
    "**Ta mission :** résoudre **6 énigmes** couvrant tout le programme SNT pour reconstituer un **code secret à 6 chiffres** et identifier le suspect.\n",
    "\n",
    "🔗 Si tu bloques, retrouve les cours sur [mathamine.fr/snt](https://mathamine.fr/snt/).\n",
    "\n",
    "## 📋 Consignes\n",
    "\n",
    "**1. Exécute la cellule \"Initialisation\" — elle génère TES données personnelles.**\n",
    "\n",
    "**2. Pour chaque énigme : complète le code, puis appelle `verif_En(...)` pour valider.**\n",
    "\n",
    "**3. Note le chiffre indiqué par chaque énigme validée.**\n",
    "\n",
    "**4. À la fin, colle les 6 chiffres pour former ton code secret.**\n",
    "\n",
    "---\n",
    "\n",
    "### Sommaire\n",
    "1. [⚙️ Initialisation](#INIT)\n",
    "2. [🌐 Énigme 1 — Internet : reconstituer une IP](#E1)\n",
    "3. [🔍 Énigme 2 — Web : balises HTML](#E2)\n",
    "4. [📊 Énigme 3 — Données : filtrer un fichier](#E3)\n",
    "5. [🗺️ Énigme 4 — Cartographie : GPS et distance](#E4)\n",
    "6. [📷 Énigme 5 — Photo numérique : pixels RVB](#E5)\n",
    "7. [🌍 Énigme 6 — Réseaux sociaux : graphe](#E6)\n",
    "8. [🔐 Code final](#FINAL)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id=\"INIT\"></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"color:white;border-collapse:separate;border:solid 2px;border-radius:14px;border-color:#4a148c;background-color:#6a1b9a;width:100%;padding:4px 0;\">\n",
    "<h2 style=\"color:white;text-align:center;\">⚙️ Initialisation</h2>\n",
    "</div>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? info Comment ça marche ?\n",
    "\n",
    "Cette cellule génère tes données à partir de ton identifiant Capytale.\n",
    "Tes données sont **toujours les mêmes** si tu reviens sur cette activité.\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "from _init import *\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id=\"OUTILS\"></a>\n",
    "<div style=\"color:white;border-collapse:separate;border:solid 2px;border-radius:14px;border-color:#e65100;background-color:#ef6c00;width:100%;padding:4px 0;\">\n",
    "<h2 style=\"color:white;text-align:center;\">🧰 Boîte à outils Python — à consulter en cas de besoin</h2>\n",
    "</div>\n",
    "\n",
    "??? info <a id=\"outils-tuples\"></a>📦 Tuples : (a, b)\n",
    "\n",
    "Un **tuple** est une paire (ou triplet, etc.) de valeurs : `t = (3, 5)`.\n",
    "\n",
    "```python\n",
    "p = (1, 192)\n",
    "p[0]    # → 1   (1er élément)\n",
    "p[1]    # → 192 (2e élément)\n",
    "```\n",
    "\n",
    "**Déballer** dans une boucle : `for seq, val in liste_de_couples:` donne directement chaque élément.\n",
    "\n",
    "???\n",
    "\n",
    "??? info <a id=\"outils-sorted\"></a>📊 sorted() et tri par clé (lambda)\n",
    "\n",
    "```python\n",
    "liste = [(3, 'C'), (1, 'A'), (2, 'B')]\n",
    "sorted(liste)                         # tri sur le 1er élément par défaut\n",
    "sorted(liste, key=lambda p: p[0])     # idem, explicitement par p[0]\n",
    "sorted(liste, key=lambda p: p[1])     # tri sur le 2e élément\n",
    "```\n",
    "\n",
    "**`lambda p: p[0]`** veut dire : « la clé de tri = le premier élément du tuple ».\n",
    "\n",
    "???\n",
    "\n",
    "??? info <a id=\"outils-listcomp\"></a>📜 Listes en compréhension\n",
    "\n",
    "Condensé d'une boucle qui construit une liste :\n",
    "\n",
    "```python\n",
    "[expression for élément in liste]\n",
    "```\n",
    "\n",
    "Exemples :\n",
    "```python\n",
    "nombres = [1, 2, 3, 4]\n",
    "[n*10 for n in nombres]              # → [10, 20, 30, 40]\n",
    "[val for (seq, val) in [(1,'A'),(2,'B')]]   # → ['A', 'B']\n",
    "```\n",
    "\n",
    "???\n",
    "\n",
    "??? info <a id=\"outils-find\"></a>🔍 str.find() et tranches\n",
    "\n",
    "```python\n",
    "texte = \"Bonjour <span>monde</span> !\"\n",
    "i = texte.find(\"<span>\")           # position du début\n",
    "j = texte.find(\"</span>\", i)       # cherche après position i\n",
    "texte[i + len(\"<span>\") : j]       # → \"monde\"\n",
    "```\n",
    "\n",
    "Tranche : `texte[debut:fin]` extrait les caractères entre les positions `debut` (inclus) et `fin` (exclu).\n",
    "\n",
    "???\n",
    "\n",
    "??? info <a id=\"outils-for-dict\"></a>🔁 Boucle for + condition\n",
    "\n",
    "```python\n",
    "nb = 0\n",
    "for r in table:\n",
    "    if r[\"classe\"] == \"2A\" and r[\"age\"] >= 15:\n",
    "        nb = nb + 1\n",
    "```\n",
    "\n",
    "`and` = ET logique (les deux conditions doivent être vraies).\n",
    "\n",
    "???\n",
    "\n",
    "??? info <a id=\"outils-math\"></a>📐 math.cos() et radians\n",
    "\n",
    "Le module `math` fournit cos, sin, sqrt, etc. **En Python, les angles sont en radians**.\n",
    "\n",
    "```python\n",
    "import math\n",
    "math.cos(math.radians(60))    # cos(60°) = 0.5\n",
    "math.sqrt(9)                  # → 3.0\n",
    "math.radians(180)             # → 3.1415... (π)\n",
    "```\n",
    "\n",
    "???\n",
    "\n",
    "??? info <a id=\"outils-dict-items\"></a>📖 Dictionnaires : .items()\n",
    "\n",
    "```python\n",
    "graphe = {\"Alice\": [\"Bob\", \"Clara\"], \"Bob\": [\"Alice\"]}\n",
    "\n",
    "# Parcourir clés et valeurs ensemble :\n",
    "for nom, amis in graphe.items():\n",
    "    print(nom, \"a\", len(amis), \"amis\")\n",
    "```\n",
    "\n",
    "`len(liste)` compte les éléments d'une liste.\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id=\"E1\"></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"color:white;border-collapse:separate;border:solid 2px;border-radius:14px;border-color:#1b5e20;background-color:#2e7d32;width:100%;padding:4px 0;\">\n",
    "<h2 style=\"color:white;text-align:center;\">🌐 Énigme 1 — Internet : Reconstituer une adresse IP</h2>\n",
    "</div>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? question Contexte\n",
    "\n",
    "Le pirate s'est connecté à un serveur depuis une machine X. Les 4 paquets contenant l'adresse IPv4 ont été interceptés **dans le désordre**.\n",
    "\n",
    "Chaque paquet contient :\n",
    "- son **n° de séquence** (1, 2, 3 ou 4) — qui indique sa position dans l'adresse\n",
    "- la **valeur de l'octet** correspondant (entre 0 et 255)\n",
    "\n",
    "Reconstitue l'adresse IPv4 au format `a.b.c.d` en remettant les paquets dans l'ordre.\n",
    "\n",
    "Appelle `verif_E1(\"a.b.c.d\")` pour vérifier.\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? danger Rappel — Adresse IPv4\n",
    "\n",
    "Une adresse IPv4 est composée de **4 octets** (0–255) séparés par des points.\n",
    "\n",
    "Exemple : `192.168.1.42`\n",
    "\n",
    "L'octet n°1 est le plus à gauche. 🔗 Voir [SNT Internet sur mathamine.fr](https://mathamine.fr/snt/cours_th1_internet.html).\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? hint 💡 Indice rapide\n",
    "\n",
    "`sorted(liste, key=lambda p: p[0])` trie selon le 1<sup>er</sup> élément du tuple. La syntaxe `[val for seq, val in liste]` ne garde que `val`.\n",
    "\n",
    "???\n",
    "\n",
    "??? note 📚 Méthode + cours\n",
    "\n",
    "Un tuple `(seq, val)` se \"déballe\" en deux variables. Sur chaque couple :<br>\n",
    "- `p[0]` = `seq` (n° de séquence)<br>\n",
    "- `p[1]` = `val` (la valeur)<br><br>\n",
    "**Tri par clé** : `sorted(liste, key=lambda p: p[0])` trie en utilisant le 1<sup>er</sup> élément comme critère.<br>\n",
    "**Liste en compréhension** : `[val for seq, val in liste]` parcourt et garde seulement les `val`.\n",
    "\n",
    "🔗 **Concept SNT** : [Adresse IPv4](https://mathamine.fr/snt/cours_th1_internet.html)  \n",
    "🐍 **Syntaxe Python** : [🧰 Boîte à outils : tuples, sorted, lambda, listes en compréhension](#OUTILS) (en haut du notebook)\n",
    "\n",
    "???\n",
    "\n",
    "??? tip 🎯 Étapes guidées (en dernier recours !)\n",
    "\n",
    "1. Premier `...` : on veut trier par n° de séquence → tape <code>p[0]</code>.<br>\n",
    "2. Deuxième `...` : on veut juste la valeur → tape <code>val</code>.<br>\n",
    "3. La ligne finale `\".\".join(...)` recolle les 4 octets avec des points pour faire l'IP.\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "# ── Énigme 1 : reconstitue l'adresse IP ──────────────────────────────────────\n",
    "print(\"Paquets reçus (dans le désordre) :\")\n",
    "for seq, val in E1_paquets:\n",
    "    print(f\"  seq={seq}  →  octet = {val}\")\n",
    "print()\n",
    "\n",
    "# 🔧 À COMPLÉTER : tri des paquets par seq puis extraction des valeurs\n",
    "# Astuce : la fonction sorted() trie selon une clé\n",
    "\n",
    "octets_ordonnes = sorted(E1_paquets, key=lambda p: ...)   # trie selon le n° de séquence\n",
    "valeurs = [...  for seq, val in octets_ordonnes]          # garde seulement les valeurs\n",
    "\n",
    "ip = \".\".join(str(v) for v in valeurs)\n",
    "print(f\"IP reconstituée : {ip}\")\n",
    "\n",
    "verif_E1(ip)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? success Note ton chiffre 1\n",
    "\n",
    "**Chiffre 1 = ____**\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id=\"E2\"></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"color:white;border-collapse:separate;border:solid 2px;border-radius:14px;border-color:#1b5e20;background-color:#2e7d32;width:100%;padding:4px 0;\">\n",
    "<h2 style=\"color:white;text-align:center;\">🔍 Énigme 2 — Web : Code source HTML</h2>\n",
    "</div>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? question Contexte\n",
    "\n",
    "Le pirate a laissé sa signature dans le code source HTML d'une page web. Cette signature est cachée dans une **balise `<span>` de classe `secret`**.\n",
    "\n",
    "Ouvre le code HTML stocké dans la variable `E2_html`, repère la balise et extrais le mot.\n",
    "\n",
    "Appelle `verif_E2(\"MOT\")` pour vérifier (en majuscules).\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? danger Rappel — Balises HTML\n",
    "\n",
    "Une page web est structurée par des **balises** : `<tag>contenu</tag>`.\n",
    "\n",
    "```html\n",
    "<p>texte normal</p>\n",
    "<span class=\"secret\">mot caché</span>\n",
    "```\n",
    "\n",
    "🔧 **En Python**, tu peux chercher une sous-chaîne avec `find()` :\n",
    "```python\n",
    "i = texte.find(\"AVANT\")     # position du début\n",
    "j = texte.find(\"APRÈS\", i)  # position de la fin\n",
    "mot = texte[i+len(\"AVANT\") : j]\n",
    "```\n",
    "\n",
    "🔗 Voir [SNT Web sur mathamine.fr](https://mathamine.fr/snt/cours_th2_web.html).\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? hint 💡 Indice rapide\n",
    "\n",
    "`str.find(\"AVANT\")` donne la position du début. Puis `str.find(\"APRÈS\", i)` cherche APRÈS la position `i`. Le mot est entre les deux.\n",
    "\n",
    "???\n",
    "\n",
    "??? note 📚 Méthode + cours\n",
    "\n",
    "**`find()`** retourne la position (un entier) où commence le texte cherché :<br><br>\n",
    "```python\n",
    "texte = \"Hello <span>monde</span> !\"\n",
    "i = texte.find(\"<span>\")        # position du < dans <span>\n",
    "j = texte.find(\"</span>\", i)    # position du < dans </span> APRÈS i\n",
    "mot = texte[i + len(\"<span>\") : j]   # tranche entre les deux\n",
    "print(mot)  # → \"monde\"\n",
    "```\n",
    "\n",
    "🔗 **Concept SNT** : [Balises HTML](https://mathamine.fr/snt/cours_th2_web.html)  \n",
    "🐍 **Syntaxe Python** : [🧰 Boîte à outils : str.find() et tranches](#OUTILS) (en haut du notebook)\n",
    "\n",
    "???\n",
    "\n",
    "??? tip 🎯 Étapes guidées (en dernier recours !)\n",
    "\n",
    "1. Premier `...` : on cherche le début → tape <code>debut_balise</code>.<br>\n",
    "2. Deuxième `...` : on cherche la fin → tape <code>fin_balise</code>.<br>\n",
    "3. Troisième `...` (la borne droite de la tranche) : tape <code>j</code> (la position de </span>).\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "# ── Énigme 2 : trouve le mot caché dans le HTML ──────────────────────────────\n",
    "print(\"Aperçu du HTML reçu :\")\n",
    "print(E2_html[:300] + \"  ...\")\n",
    "print()\n",
    "\n",
    "# 🔧 À COMPLÉTER : récupère le mot situé entre <span class=\"secret\"> et </span>\n",
    "debut_balise = '<span class=\"secret\">'\n",
    "fin_balise   = '</span>'\n",
    "\n",
    "i = E2_html.find(...)                     # position du début de la balise ouvrante\n",
    "j = E2_html.find(..., i)                  # position de la balise fermante\n",
    "mot = E2_html[i + len(debut_balise) : ...]\n",
    "\n",
    "print(f\"Mot trouvé : {mot}\")\n",
    "\n",
    "verif_E2(mot)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? success Note ton chiffre 2\n",
    "\n",
    "**Chiffre 2 = ____**\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id=\"TOPO3\"></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"color:white;border-collapse:separate;border:solid 2px;border-radius:14px;border-color:#e65100;background-color:#ef6c00;width:100%;padding:4px 0;\">\n",
    "<h2 style=\"color:white;text-align:center;\">📚 Mini-topo — Parcourir une table (liste de dictionnaires)</h2>\n",
    "</div>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? info Tables en Python : ce dont tu as besoin pour l'énigme 3\n",
    "\n",
    "### Une ligne = un dictionnaire\n",
    "```python\n",
    "ligne = {\"prenom\": \"Alice\", \"classe\": \"2A\", \"age\": 15, \"score\": 17}\n",
    "ligne[\"classe\"]     # → \"2A\"   accès à une colonne\n",
    "ligne[\"age\"]        # → 15\n",
    "```\n",
    "\n",
    "### Une table = une liste de dictionnaires\n",
    "```python\n",
    "table = [\n",
    "    {\"prenom\": \"Alice\", \"classe\": \"2A\", \"age\": 15, \"score\": 17},\n",
    "    {\"prenom\": \"Bob\",   \"classe\": \"2B\", \"age\": 14, \"score\": 12},\n",
    "]\n",
    "```\n",
    "\n",
    "### Filtrer = boucle for + condition if\n",
    "```python\n",
    "nb = 0\n",
    "for ligne in table:\n",
    "    if ligne[\"classe\"] == \"2A\" and ligne[\"age\"] >= 15:\n",
    "        nb = nb + 1\n",
    "print(nb)\n",
    "```\n",
    "\n",
    "🔗 [SNT Données structurées sur mathamine.fr](https://mathamine.fr/snt/cours_th4_donnees.html).\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "# ── Mini-exercices de préparation ────────────────────────────────────────────\n",
    "\n",
    "# ① Accéder à un champ\n",
    "eleve = {\"prenom\": \"Léa\", \"classe\": \"2C\", \"age\": 16, \"score\": 14}\n",
    "print(eleve[\"prenom\"])      # attendu : Léa\n",
    "print(eleve[...])           # affiche la classe de Léa\n",
    "\n",
    "# ② Compter dans une boucle\n",
    "table_demo = [\n",
    "    {\"prenom\": \"A\", \"classe\": \"2A\"},\n",
    "    {\"prenom\": \"B\", \"classe\": \"2B\"},\n",
    "    {\"prenom\": \"C\", \"classe\": \"2A\"},\n",
    "]\n",
    "n = 0\n",
    "for r in table_demo:\n",
    "    if r[...] == \"2A\":\n",
    "        n = n + 1\n",
    "print(n)                    # attendu : 2\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id=\"E3\"></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"color:white;border-collapse:separate;border:solid 2px;border-radius:14px;border-color:#1b5e20;background-color:#2e7d32;width:100%;padding:4px 0;\">\n",
    "<h2 style=\"color:white;text-align:center;\">📊 Énigme 3 — Données structurées : filtrer la table</h2>\n",
    "</div>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? question Contexte\n",
    "\n",
    "Une table d'élèves `E3_table` a été récupérée sur un serveur. Chaque ligne contient :\n",
    "`id`, `prenom`, `classe`, `age`, `score`.\n",
    "\n",
    "Le suspect appartient à un groupe précis. **Combien d'élèves** de la classe `E3_classe`\n",
    "ont au moins `E3_age_min` ans ?\n",
    "\n",
    "Appelle `verif_E3(nombre)` pour vérifier.\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? danger Indice\n",
    "\n",
    "Utilise une boucle `for` avec un compteur, et une condition combinée avec `and`.\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? hint 💡 Indice rapide\n",
    "\n",
    "Une condition combinée avec `and` : `r[\"classe\"] == E3_classe and r[\"age\"] >= E3_age_min`\n",
    "\n",
    "???\n",
    "\n",
    "??? note 📚 Méthode + cours\n",
    "\n",
    "**Filtrer une table** : on parcourt chaque ligne avec une boucle `for`, on teste avec un `if`, et on compte si la condition est vraie.<br><br>\n",
    "```python\n",
    "nb = 0\n",
    "for r in table:\n",
    "    if r[\"colonne1\"] == valeur1 and r[\"colonne2\"] >= valeur2:\n",
    "        nb = nb + 1\n",
    "```<br>\n",
    "Le `and` combine deux conditions : les **deux** doivent être vraies.\n",
    "\n",
    "🔗 **Concept SNT** : [Données structurées](https://mathamine.fr/snt/cours_th7_donnees.html)  \n",
    "🐍 **Syntaxe Python** : [🧰 Boîte à outils : boucle for + condition if](#OUTILS) (en haut du notebook)\n",
    "\n",
    "???\n",
    "\n",
    "??? tip 🎯 Étapes guidées (en dernier recours !)\n",
    "\n",
    "1. Premier `...` : la classe cible → tape <code>E3_classe</code>.<br>\n",
    "2. Deuxième `...` : l'âge minimum → tape <code>E3_age_min</code>.<br>\n",
    "3. La boucle parcourt la table et incrémente <code>nb</code> chaque fois que la condition est vraie.\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "# ── Énigme 3 : filtre la table ────────────────────────────────────────────────\n",
    "print(f\"Classe cible : {E3_classe}   |   Âge minimum : {E3_age_min}\")\n",
    "print(f\"Table de {len(E3_table)} élèves :\")\n",
    "for r in E3_table:\n",
    "    print(f\"  id={r['id']:2d}  {r['prenom']:10s}  classe={r['classe']}  age={r['age']}  score={r['score']}\")\n",
    "print()\n",
    "\n",
    "# 🔧 À COMPLÉTER\n",
    "nb = 0\n",
    "for r in E3_table:\n",
    "    if r[\"classe\"] == ... and r[\"age\"] >= ...:\n",
    "        nb = nb + 1\n",
    "\n",
    "print(f\"Nombre d'élèves correspondants : {nb}\")\n",
    "\n",
    "verif_E3(nb)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? success Note ton chiffre 3\n",
    "\n",
    "**Chiffre 3 = ____**\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id=\"E4\"></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"color:white;border-collapse:separate;border:solid 2px;border-radius:14px;border-color:#1b5e20;background-color:#2e7d32;width:100%;padding:4px 0;\">\n",
    "<h2 style=\"color:white;text-align:center;\">🗺️ Énigme 4 — Cartographie : coordonnées GPS et distance</h2>\n",
    "</div>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? question Contexte\n",
    "\n",
    "Deux lieux suspects ont été repérés près de La Flèche. Leurs coordonnées GPS sont en **DMS** (degrés, minutes, secondes).\n",
    "\n",
    "Convertis-les en degrés décimaux puis calcule la **distance approximative en mètres** entre les deux points.\n",
    "\n",
    "Appelle `verif_E4(distance_metres)` pour vérifier (tolérance ±10 %).\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? danger Rappel — Conversion DMS → décimal\n",
    "\n",
    "$$\\text{décimal} = \\text{deg} + \\dfrac{\\text{min}}{60} + \\dfrac{\\text{sec}}{3600}$$\n",
    "\n",
    "Les longitudes **ouest** sont **négatives** (La Flèche est à l'ouest du méridien de Greenwich).\n",
    "\n",
    "### Distance entre deux points proches (échelle locale)\n",
    "\n",
    "Pour deux points proches en France :\n",
    "- 1° de **latitude** ≈ 111 km\n",
    "- 1° de **longitude** à 47°N ≈ 111 × cos(47°) ≈ 75,7 km\n",
    "\n",
    "$$d \\approx \\sqrt{(\\Delta_{lat} \\cdot 111)^2 + (\\Delta_{lon} \\cdot 75{,}7)^2} \\quad \\text{(en km)}$$\n",
    "\n",
    "🔗 [SNT Cartographie sur mathamine.fr](https://mathamine.fr/snt/cours_th5_carto.html).\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? hint 💡 Indice rapide\n",
    "\n",
    "À 47°N : 1° de longitude ≈ **111 km × cos(47°)**. Distance ≈ √(Δlat² + Δlon²) en km.\n",
    "\n",
    "???\n",
    "\n",
    "??? note 📚 Méthode + cours\n",
    "\n",
    "**Distance plane** (valide à petite échelle) :<br><br>\n",
    "$$d \\approx \\sqrt{(\\Delta_{lat} \\cdot 111)^2 + (\\Delta_{lon} \\cdot 111 \\cdot \\cos(\\theta))^2}$$<br><br>\n",
    "où $\\theta$ est la latitude moyenne en radians. À La Flèche (≈47°N), on a $\\cos(47°) ≈ 0.68$.<br><br>\n",
    "**Important** : en Python, `math.cos()` prend des **radians**, donc utilise `math.radians(47.7)` pour convertir.\n",
    "\n",
    "🔗 **Concept SNT** : [Localisation / GPS](https://mathamine.fr/snt/cours_th4_localisation.html)  \n",
    "🐍 **Syntaxe Python** : [🧰 Boîte à outils : math.cos() et math.radians()](#OUTILS) (en haut du notebook)\n",
    "\n",
    "???\n",
    "\n",
    "??? tip 🎯 Étapes guidées (en dernier recours !)\n",
    "\n",
    "1. Premier `...` (facteur longitude) : tape <code>111</code> (km/°).<br>\n",
    "2. Le deuxième `...` (radicande) : <code>dlat_km**2</code>.<br>\n",
    "3. Le troisième `...` : <code>dlon_km**2</code>.<br>\n",
    "4. Pour les mètres : <code>distance_km * 1000</code>.\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "# ── Énigme 4 : GPS et distance ───────────────────────────────────────────────\n",
    "import math\n",
    "\n",
    "# Chaque tuple = (lat_deg, lat_min, lat_sec, lon_deg, lon_min, lon_sec)\n",
    "print(f\"Point A (DMS) : {E4_A_DMS}\")\n",
    "print(f\"Point B (DMS) : {E4_B_DMS}\")\n",
    "print()\n",
    "\n",
    "def dms_to_dd(deg, mn, sec):\n",
    "    return deg + mn / 60 + sec / 3600\n",
    "\n",
    "# Convertir en degrés décimaux\n",
    "lat_A = dms_to_dd(E4_A_DMS[0], E4_A_DMS[1], E4_A_DMS[2])\n",
    "lat_B = dms_to_dd(E4_B_DMS[0], E4_B_DMS[1], E4_B_DMS[2])\n",
    "lon_A = -dms_to_dd(E4_A_DMS[3], E4_A_DMS[4], E4_A_DMS[5])  # ouest négatif\n",
    "lon_B = -dms_to_dd(E4_B_DMS[3], E4_B_DMS[4], E4_B_DMS[5])\n",
    "\n",
    "print(f\"A : lat={lat_A:.6f}, lon={lon_A:.6f}\")\n",
    "print(f\"B : lat={lat_B:.6f}, lon={lon_B:.6f}\")\n",
    "\n",
    "# 🔧 À COMPLÉTER : calcule la distance en km puis en mètres\n",
    "dlat_km = (lat_B - lat_A) * 111\n",
    "dlon_km = (lon_B - lon_A) * ... * math.cos(math.radians(47.7))\n",
    "\n",
    "distance_km = math.sqrt(... + ...)\n",
    "distance_m  = ...\n",
    "\n",
    "print(f\"Distance ≈ {distance_m:.0f} m\")\n",
    "\n",
    "verif_E4(distance_m)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? success Note ton chiffre 4\n",
    "\n",
    "**Chiffre 4 = ____**\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id=\"E5\"></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"color:white;border-collapse:separate;border:solid 2px;border-radius:14px;border-color:#1b5e20;background-color:#2e7d32;width:100%;padding:4px 0;\">\n",
    "<h2 style=\"color:white;text-align:center;\">📷 Énigme 5 — Photo numérique : pixels RVB</h2>\n",
    "</div>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? question Contexte\n",
    "\n",
    "Quatre pixels ont été extraits d'une photo numérique. Chaque pixel a 3 composantes : **R** (rouge), **V** (vert), **B** (bleu), chacune entre 0 et 255.\n",
    "\n",
    "Calcule **la somme des composantes Rouges** des 4 pixels, puis **divise par 50** (division entière).\n",
    "\n",
    "Appelle `verif_E5(code)` avec ce résultat.\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? danger Rappel — Codage RVB\n",
    "\n",
    "Chaque pixel d'une image couleur est codé par 3 entiers (0–255) :\n",
    "- **R** = niveau de rouge\n",
    "- **V** = niveau de vert\n",
    "- **B** = niveau de bleu\n",
    "\n",
    "Un pixel `(255, 0, 0)` est rouge pur. `(255, 255, 255)` est blanc, `(0, 0, 0)` est noir.\n",
    "\n",
    "En Python : `pixel[0]` = R, `pixel[1]` = V, `pixel[2]` = B.\n",
    "\n",
    "La **division entière** en Python : `15 // 4 = 3`.\n",
    "\n",
    "🔗 [SNT Photographie numérique sur mathamine.fr](https://mathamine.fr/snt/cours_th6_photo.html).\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? hint 💡 Indice rapide\n",
    "\n",
    "`pix[0]` accède au **R** (rouge) d'un pixel `(R, V, B)`. Division entière : `//`.\n",
    "\n",
    "???\n",
    "\n",
    "??? note 📚 Méthode + cours\n",
    "\n",
    "Un pixel est un **tuple** `(R, V, B)`. Pour accéder à un élément :<br>\n",
    "- `pix[0]` → R (rouge)<br>\n",
    "- `pix[1]` → V (vert)<br>\n",
    "- `pix[2]` → B (bleu)<br><br>\n",
    "**Division entière** : `//` donne le quotient sans virgule.<br>\n",
    "Exemple : `347 // 50 = 6`.\n",
    "\n",
    "🔗 **Concept SNT** : [Photographie numérique](https://mathamine.fr/snt/cours_th_photo.html)  \n",
    "🐍 **Syntaxe Python** : [🧰 Boîte à outils : indices de tuple pix[0], division entière //](#OUTILS) (en haut du notebook)\n",
    "\n",
    "???\n",
    "\n",
    "??? tip 🎯 Étapes guidées (en dernier recours !)\n",
    "\n",
    "1. Premier `...` : on veut le rouge → tape <code>0</code> (pour <code>pix[0]</code>).<br>\n",
    "2. Deuxième `...` : le diviseur → tape <code>50</code>.<br>\n",
    "3. La boucle parcourt les 4 pixels et accumule la somme des R.\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "# ── Énigme 5 : décoder les pixels ────────────────────────────────────────────\n",
    "print(\"Pixels reçus :\")\n",
    "for i, pix in enumerate(E5_pixels, start=1):\n",
    "    print(f\"  Pixel {i} : R={pix[0]:3d}  V={pix[1]:3d}  B={pix[2]:3d}\")\n",
    "print()\n",
    "\n",
    "# 🔧 À COMPLÉTER : calcule la somme des R, puis divise par 50\n",
    "somme_R = 0\n",
    "for pix in E5_pixels:\n",
    "    somme_R = somme_R + pix[...]   # composante rouge\n",
    "\n",
    "code = somme_R // ...               # division entière par 50\n",
    "\n",
    "print(f\"Somme des R = {somme_R}, code = {code}\")\n",
    "\n",
    "verif_E5(code)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? success Note ton chiffre 5\n",
    "\n",
    "**Chiffre 5 = ____**\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id=\"TOPO6\"></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"color:white;border-collapse:separate;border:solid 2px;border-radius:14px;border-color:#e65100;background-color:#ef6c00;width:100%;padding:4px 0;\">\n",
    "<h2 style=\"color:white;text-align:center;\">📚 Mini-topo — Graphes en Python (dictionnaire d'amis)</h2>\n",
    "</div>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? info Représenter un graphe\n",
    "\n",
    "Un **graphe** modélise des relations (amitiés, contacts...). Chaque sommet est une personne et chaque arête une relation.\n",
    "\n",
    "En Python, on utilise un **dictionnaire** : à chaque personne, on associe la liste de ses amis.\n",
    "\n",
    "```python\n",
    "graphe = {\n",
    "    \"Aïcha\":  [\"Boris\", \"Clara\"],\n",
    "    \"Boris\":  [\"Aïcha\", \"Dimitri\"],\n",
    "    \"Clara\":  [\"Aïcha\"],\n",
    "    \"Dimitri\":[\"Boris\"],\n",
    "}\n",
    "\n",
    "# Nombre d'amis (degré) d'une personne :\n",
    "len(graphe[\"Aïcha\"])    # → 2\n",
    "\n",
    "# Parcourir tout le monde :\n",
    "for nom, amis in graphe.items():\n",
    "    print(nom, \"→\", len(amis), \"amis\")\n",
    "```\n",
    "\n",
    "🔗 [SNT Réseaux sociaux sur mathamine.fr](https://mathamine.fr/snt/cours_th3_reseaux.html).\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id=\"E6\"></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"color:white;border-collapse:separate;border:solid 2px;border-radius:14px;border-color:#1b5e20;background-color:#2e7d32;width:100%;padding:4px 0;\">\n",
    "<h2 style=\"color:white;text-align:center;\">🌍 Énigme 6 — Réseaux sociaux : trouver l'influenceur</h2>\n",
    "</div>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? question Contexte\n",
    "\n",
    "Un graphe de relations a été extrait du compte du suspect : `E6_graphe`. La clé est le nom d'une personne, la valeur est la liste de ses amis.\n",
    "\n",
    "**Question :** Qui est l'**influenceur** — la personne avec le **plus d'amis** ?\n",
    "Donne aussi son **degré** (nombre d'amis).\n",
    "\n",
    "Appelle `verif_E6(nom, degre)` pour vérifier.\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? danger Indice\n",
    "\n",
    "Parcours le dictionnaire avec `.items()`. Pour chaque personne, calcule `len(amis)`.\n",
    "Garde la meilleure au fil de la boucle (variable `meilleur_nom`, `meilleur_degre`).\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? hint 💡 Indice rapide\n",
    "\n",
    "`len(amis)` compte le nombre d'amis. Mets à jour `meilleur_nom` et `meilleur_degre` si on trouve mieux.\n",
    "\n",
    "???\n",
    "\n",
    "??? note 📚 Méthode + cours\n",
    "\n",
    "**Parcourir un dictionnaire** : `for nom, amis in graphe.items()` donne `nom` (clé) et `amis` (valeur = liste).<br><br>\n",
    "**Algorithme du maximum** : on garde au fil de la boucle la meilleure valeur trouvée jusqu'ici.<br><br>\n",
    "```python\n",
    "meilleur = -1\n",
    "for x in liste:\n",
    "    if x > meilleur:\n",
    "        meilleur = x\n",
    "```\n",
    "\n",
    "🔗 **Concept SNT** : [Réseaux sociaux](https://mathamine.fr/snt/cours_th3_reseaux_sociaux.html)  \n",
    "🐍 **Syntaxe Python** : [🧰 Boîte à outils : dict.items() et len()](#OUTILS) (en haut du notebook)\n",
    "\n",
    "???\n",
    "\n",
    "??? tip 🎯 Étapes guidées (en dernier recours !)\n",
    "\n",
    "1. Premier `...` : le nombre d'amis → tape <code>len(amis)</code>.<br>\n",
    "2. Deuxième `...` : la nouvelle valeur de <code>meilleur_degre</code> → tape <code>degre</code>.<br>\n",
    "3. Troisième `...` : la nouvelle valeur de <code>meilleur_nom</code> → tape <code>nom</code>.<br>\n",
    "4. À la fin, <code>meilleur_nom</code> contient l'influenceur et <code>meilleur_degre</code> son nombre d'amis.\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "# ── Énigme 6 : trouver l'influenceur ──────────────────────────────────────────\n",
    "print(\"Graphe d'amitiés :\")\n",
    "for nom, amis in E6_graphe.items():\n",
    "    print(f\"  {nom:10s} → {len(amis)} amis : {', '.join(amis)}\")\n",
    "print()\n",
    "\n",
    "# 🔧 À COMPLÉTER : trouve la personne avec le plus d'amis\n",
    "meilleur_nom    = None\n",
    "meilleur_degre  = -1\n",
    "\n",
    "for nom, amis in E6_graphe.items():\n",
    "    degre = ...                          # nombre d'amis\n",
    "    if degre > meilleur_degre:\n",
    "        meilleur_degre = ...\n",
    "        meilleur_nom   = ...\n",
    "\n",
    "print(f\"Influenceur : {meilleur_nom}  ({meilleur_degre} amis)\")\n",
    "\n",
    "verif_E6(meilleur_nom, meilleur_degre)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? success Note ton chiffre 6\n",
    "\n",
    "**Chiffre 6 = ____**\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a id=\"FINAL\"></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div style=\"color:white;border-collapse:separate;border:solid 2px;border-radius:14px;border-color:#b71c1c;background-color:#c62828;width:100%;padding:4px 0;\">\n",
    "<h2 style=\"color:white;text-align:center;\">🔐 Code final — Cyber-enquête résolue</h2>\n",
    "</div>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "??? question Combine tes 6 chiffres\n",
    "\n",
    "Colle les 6 chiffres notés (énigmes 1 à 6) pour former un code **à 6 chiffres**.\n",
    "\n",
    "Exemple : si tu as trouvé 3, 7, 2, 5, 8, 1 → code = `372581`.\n",
    "\n",
    "Appelle `verif_final(\"code\")` pour révéler le verdict.\n",
    "\n",
    "???\n"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {},
   "execution_count": null,
   "outputs": [],
   "source": [
    "# ── Code final ────────────────────────────────────────────────────────────────\n",
    "# Remplace les ... par les 6 chiffres notés au fil des énigmes\n",
    "chiffre_1 = ...\n",
    "chiffre_2 = ...\n",
    "chiffre_3 = ...\n",
    "chiffre_4 = ...\n",
    "chiffre_5 = ...\n",
    "chiffre_6 = ...\n",
    "\n",
    "code = f\"{chiffre_1}{chiffre_2}{chiffre_3}{chiffre_4}{chiffre_5}{chiffre_6}\"\n",
    "print(f\"Code proposé : {code}\")\n",
    "\n",
    "verif_final(code)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "<div style=\"text-align:center;color:#666;font-size:0.9em;margin-top:1em;\">\n",
    "🌐 Tous les cours SNT Seconde sur <a href=\"https://mathamine.fr/snt/\">mathamine.fr/snt</a>\n",
    "</div>\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}