Paillasse/portail/public/js/contenus-lot-12.js
Adam Belkacemi 30e14b1c54 ajoute le portail Laravel : connexion prof/élève, session unique, gestion de classe, salle d'attente
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-08 02:01:58 +02:00

282 lines
64 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Cours complets · lot 12 : modélisation des données, virtualisation et cloud, logique et arithmétique, big data, compétences professionnelles
(function () {
var reg = function (c) {
(window.CONTENUS_PRO = window.CONTENUS_PRO || []).unshift(c.cours);
(window.CONTENUS_PLUS = window.CONTENUS_PLUS || {})[c.cours.id] = c.plus;
(window.CONTENUS_EXEMPLES = window.CONTENUS_EXEMPLES || {})[c.cours.id] = c.exemples;
(window.CONTENUS_SCHEMAS = window.CONTENUS_SCHEMAS || {})[c.cours.id] = { termes: c.termes, figs: [] };
};
reg({
cours: { id: 'modelisation', match: /Modélisation : MCD|Merise|UML|MCD et MLD|Normalisation|1FN|Réplication|Entrepôt de données|modèle en étoile|Bases de données avancées|Génie logiciel|patrons de conception|urbanisation/i,
titre: 'Modéliser les données et le logiciel : Merise, UML, normalisation, réplication et entrepôts', duree: '',
niveau: 'NSI Terminale · BTS SIO SLAM · BUT Informatique · MIAGE · école d’ingénieurs',
prerequis: ['SQL'],
competences: ['BTS SIO SLAM · Bloc 2 · Concevoir une base de données', 'BUT Info · Concevoir', 'MIAGE · Urbaniser le système d’information'],
intro: 'Une base de données mal conçue se paie pendant des années : informations en double qui se contredisent, requêtes impossibles, mises à jour qui corrompent les données. La modélisation précède le code : elle traduit les règles de gestion en un schéma clair, partagé avec le métier. Ce module couvre Merise (MCD, MLD), les diagrammes UML essentiels, la normalisation, puis l’exploitation à grande échelle : réplication et entrepôts de données.',
cm: [
{ t: 'Des règles de gestion au MCD', d: '', html: 'On part des <b>règles de gestion</b> exprimées par le métier : « un élève appartient à une seule classe pour une année », « un devoir peut être donné à plusieurs classes », « un rendu concerne un élève et un devoir ». Le <b>modèle conceptuel des données</b> (MCD, méthode Merise) les représente par des <b>entités</b> (Élève, Classe, Devoir) avec leurs <b>attributs</b> et un <b>identifiant</b>, et des <b>associations</b> (Appartenir, Rendre) avec leurs <b>cardinalités</b> minimales et maximales : 0,n, 1,1, 1,n. Le MCD est indépendant de tout logiciel.' },
{ t: 'Du MCD au MLD et au SQL', d: '', html: 'Le <b>modèle logique</b> (MLD) traduit le MCD en tables par des règles simples. Chaque entité devient une table, son identifiant une clé primaire. Une association de type <b>1,n – 0,1 / 1,1</b> devient une <b>clé étrangère</b> du côté de la cardinalité maximale 1. Une association <b>n,n</b> devient une <b>table de liaison</b> dont la clé primaire combine les deux clés étrangères, et qui porte les attributs de l’association (la note d’un rendu). Le <b>modèle physique</b> ajoute les types, les index et les contraintes, et s’écrit en SQL.', exemple: 'ELEVE (id_eleve, nom, prenom, #id_classe)\nCLASSE (id_classe, libelle, annee)\nDEVOIR (id_devoir, titre, date_limite)\nRENDU (#id_eleve, #id_devoir, date_depot, note)\n\nCREATE TABLE rendu (\n id_eleve INT REFERENCES eleve(id_eleve),\n id_devoir INT REFERENCES devoir(id_devoir),\n date_depot TIMESTAMP NOT NULL,\n note NUMERIC(4,2) CHECK (note BETWEEN 0 AND 20),\n PRIMARY KEY (id_eleve, id_devoir)\n);' },
{ t: 'UML pour le logiciel', d: '', html: '<b>UML</b> propose des diagrammes complémentaires. Le <b>diagramme de cas d’utilisation</b> montre les acteurs (élève, professeur, CPE) et ce qu’ils font avec le système. Le <b>diagramme de classes</b> décrit les classes, leurs attributs, méthodes et relations (association, composition, héritage) : il sert à la fois de modèle de données et de structure du code orienté objet. Le <b>diagramme de séquence</b> montre l’enchaînement des messages pour un scénario (« l’élève lève la main »). Le <b>diagramme d’activité</b> décrit un processus. En pratique, on dessine ce qui aide à se comprendre, pas tous les diagrammes possibles.' },
{ t: 'La normalisation', d: '', html: 'Les <b>formes normales</b> éliminent les redondances et les anomalies de mise à jour. <b>1FN</b> : chaque attribut est atomique, pas de liste dans une cellule (pas de colonne « matières : maths, réseaux »). <b>2FN</b> : en 1FN, et chaque attribut non clé dépend de toute la clé primaire, pas d’une partie (dans RENDU(id_eleve, id_devoir, nom_eleve, note), nom_eleve ne dépend que de id_eleve). <b>3FN</b> : en 2FN, et aucun attribut non clé ne dépend d’un autre attribut non clé (le nom du professeur principal ne doit pas être stocké dans ELEVE, mais dans CLASSE). On peut <b>dénormaliser</b> volontairement pour la performance, en le documentant.' },
{ t: 'Réplication et haute disponibilité', d: '', html: 'La <b>réplication</b> copie les modifications d’un serveur <b>primaire</b> vers un ou plusieurs <b>réplicas</b>. Elle sert à la haute disponibilité (un réplica devient primaire si celui-ci tombe), à la répartition de la lecture et aux sauvegardes sans charger le primaire. Elle peut être <b>asynchrone</b> (rapide, mais quelques transactions peuvent être perdues lors d’une bascule) ou <b>synchrone</b> (aucune perte, plus lente). PostgreSQL utilise la réplication en flux des journaux (WAL) ; MariaDB les journaux binaires. La réplication ne remplace pas la sauvegarde : une suppression est répliquée instantanément.' },
{ t: 'Entrepôts de données', d: '', html: 'Une base <b>transactionnelle</b> (OLTP) est optimisée pour de nombreuses petites écritures. Pour l’analyse (OLAP), on construit un <b>entrepôt de données</b> alimenté par des traitements <b>ETL</b> ou ELT (extraire, transformer, charger). Le <b>modèle en étoile</b> place au centre une table de <b>faits</b> (les mesures : notes, absences, heures de lab) entourée de tables de <b>dimensions</b> (temps, élève, classe, matière, établissement). Les requêtes analytiques deviennent simples et rapides ; les bases en colonnes (ClickHouse, DuckDB) et les tableaux de bord (Metabase, Superset) s’appuient sur ce modèle.' }
],
synthese: ['Règles de gestion → MCD : entités, associations, cardinalités', 'MLD : 1,n → clé étrangère ; n,n → table de liaison', 'UML : cas d’utilisation, classes, séquence, activité', '1FN atomique, 2FN toute la clé, 3FN pas de dépendance transitive', 'Réplication primaire/réplicas, synchrone ou asynchrone ; pas une sauvegarde', 'Entrepôt : ETL, faits et dimensions, modèle en étoile'],
qcm: [
['Une association n,n devient en MLD :', ['une colonne', 'une table de liaison', 'un index', 'rien'], 1, 'Clé composée des deux clés étrangères.'],
['Une colonne « matières : maths, réseaux » viole :', ['1FN', '2FN', '3FN', 'aucune'], 0, 'Attribut non atomique.'],
['Quel diagramme UML montre les acteurs et leurs usages ?', ['Classes', 'Cas d’utilisation', 'Séquence', 'Déploiement'], 1, 'Vue fonctionnelle.'],
['Risque de la réplication asynchrone ?', ['Lenteur', 'Perte des dernières transactions à la bascule', 'Aucune', 'Corruption systématique'], 1, 'Les réplicas ont un léger retard.'],
['Dans un modèle en étoile, les notes sont :', ['une dimension', 'des faits', 'un index', 'une vue'], 1, 'Mesures au centre.'],
['La réplication remplace-t-elle la sauvegarde ?', ['Oui', 'Non, une suppression est répliquée', 'Seulement en synchrone', 'Oui si chiffrée'], 1, 'Il faut des sauvegardes historisées.']
],
td: [
{ n: 'Application', c: 'À partir des règles de gestion des labs (un lab a plusieurs étapes ; un élève réalise plusieurs labs ; pour chaque étape réalisée, on garde le nombre d’indices et la date), établir le MCD puis le MLD.', r: 'LAB (id_lab, titre) · ETAPE (id_etape, rang, consigne, #id_lab) · ELEVE (id_eleve, nom) · REALISER (#id_eleve, #id_etape, date, nb_indices).' },
{ n: 'Application', c: 'Normaliser la table INSCRIPTION(id_eleve, nom_eleve, id_classe, libelle_classe, nom_prof_principal).', r: 'ELEVE(id_eleve, nom, #id_classe) · CLASSE(id_classe, libelle, #id_prof_principal) · PROF(id_prof, nom).' },
{ n: 'Approfondissement', c: 'Concevoir le modèle en étoile d’un entrepôt de suivi pédagogique académique.', r: 'Faits : activité (heures de lab, nb de labs réussis, note moyenne) · dimensions : temps (jour, semaine, trimestre), élève (pseudonymisé), classe, filière, établissement, compétence.' }
],
tp: { type: 'IDE SQL', url: 'apercu-ide.html', desc: 'Du modèle à la base.', etapes: ['MCD à partir de règles de gestion', 'Passage au MLD', 'Création en SQL avec contraintes', 'Normalisation d’une table fournie', 'Requêtes d’analyse sur un modèle en étoile'] },
plusLoin: [['Documentation PostgreSQL · réplication', 'https://www.postgresql.org/docs/current/high-availability.html'], ['UML (OMG)', 'https://www.omg.org/spec/UML/'], ['DuckDB', 'https://duckdb.org/docs/']] },
plus: { cas: { titre: '', texte: '' },
resolu: { enonce: 'Dans l’application de vie scolaire, le nom du professeur principal d’une classe n’est pas le même selon les élèves.', etapes: [
['Constater', 'SELECT DISTINCT id_classe, prof_principal FROM eleve WHERE id_classe = 12;\n12 | M. Belkacemi\n12 | Mme Roche\n→ La même classe a deux professeurs principaux.'],
['Identifier la cause', '→ Le professeur principal est stocké dans chaque ligne de la table ELEVE : lors du changement en cours d’année, seuls les nouveaux élèves ont reçu la nouvelle valeur. Anomalie de mise à jour due à une table en 2FN mais pas en 3FN.'],
['Corriger le schéma', 'ALTER TABLE classe ADD id_prof_principal INT REFERENCES prof(id_prof);\nUPDATE classe SET id_prof_principal = … ;\nALTER TABLE eleve DROP COLUMN prof_principal;\n→ L’information n’existe plus qu’à un seul endroit.'],
['Adapter les requêtes', 'SELECT e.nom, p.nom FROM eleve e JOIN classe c USING (id_classe) JOIN prof p ON p.id_prof = c.id_prof_principal;\n→ Jointure au lieu de la colonne dupliquée.'],
['Prévenir', '→ Revue de modèle avant toute nouvelle fonctionnalité, migrations versionnées et tests.']
] },
erreurs: ['Stocker une liste dans une colonne', 'Dupliquer une information qui dépend d’une autre table', 'Oublier la table de liaison d’une association n,n', 'Identifiants métier modifiables comme clé primaire', 'Confondre réplication et sauvegarde', 'Analyser directement sur la base de production'],
memo: [['Règle', 'Traduction'], ['Entité', 'table, identifiant → clé primaire'], ['Association 1,n', 'clé étrangère côté 1'], ['Association n,n', 'table de liaison'], ['1FN', 'valeurs atomiques'], ['2FN', 'dépendance de toute la clé'], ['3FN', 'pas de dépendance transitive'], ['Cas d’utilisation', 'acteurs et usages'], ['Diagramme de classes', 'structure et relations'], ['Faits / dimensions', 'mesures / axes d’analyse']],
examen: { titre: 'Sujet type · 20 points', q: ['Établir un MCD à partir de règles de gestion. (6 pts)', 'Le traduire en MLD et en SQL. (5 pts)', 'Normaliser une table fournie. (4 pts)', 'Dessiner un diagramme de cas d’utilisation. (3 pts)', 'Comparer réplication et sauvegarde. (2 pts)'], r: ['entités, associations, cardinalités', 'règles de passage', '1FN à 3FN', 'acteurs', 'voir cours'] },
prof: { deroule: [['Ouverture', 'Une table pleine d’incohérences'], ['Cours', 'MCD et MLD'], ['Pratique', 'Modéliser les labs'], ['Cours', 'Normalisation et UML'], ['Cours', 'Réplication et entrepôts'], ['Clôture', 'Quiz flash']], diff: 'Élèves en difficulté : MCD à compléter. Élèves avancés : patrons de conception, modèle en flocon.', eval: 'Dossier de modélisation, sujet type.' } },
exemples: [
['Contrainte de clé étrangère', 'Insertion invalide.', "INSERT INTO rendu VALUES (9999, 3, now(), 12);", 'ERROR: insert or update on table "rendu" violates foreign key constraint "rendu_id_eleve_fkey"', 'L’élève 9999 n’existe pas : la base protège l’intégrité.'],
['Détecter une redondance', 'Audit d’un schéma.', 'SELECT id_classe, COUNT(DISTINCT prof_principal) FROM eleve GROUP BY id_classe HAVING COUNT(DISTINCT prof_principal) > 1;', '12 | 2', 'Signe d’une table non normalisée.'],
['État de la réplication', 'Contrôle du primaire.', 'SELECT client_addr, state, replay_lag FROM pg_stat_replication;', '10.62.40.32 | streaming | 00:00:00.12', 'Le réplica suit avec 120 ms de retard.'],
['Requête analytique', 'Entrepôt.', 'SELECT t.trimestre, c.filiere, AVG(f.note) FROM faits f JOIN dim_temps t USING (id_temps) JOIN dim_classe c USING (id_classe) GROUP BY 1, 2;', 'T1 | SIO | 11.8\nT1 | CIEL | 12.3', 'Le modèle en étoile rend la requête directe.'],
['Analyse avec DuckDB', 'Fichier d’export.', "duckdb -c \"SELECT filiere, COUNT(*) FROM 'activite.parquet' GROUP BY 1\"", '┌─────────┬──────────────┐\n│ filiere │ count_star() │\n│ SIO │ 18234 │', 'Analyse directe d’un fichier Parquet sans serveur.'],
['Clé composée', 'Doublon de rendu.', "INSERT INTO rendu VALUES (1204, 3, now(), 14);", 'ERROR: duplicate key value violates unique constraint "rendu_pkey"', 'Un élève ne peut rendre qu’une fois le même devoir.']
],
termes: ['règle de gestion', 'MCD', 'MLD', 'Merise', 'entité', 'association', 'cardinalité', 'identifiant', 'table de liaison', 'UML', 'cas d’utilisation', 'diagramme de classes', 'diagramme de séquence', 'normalisation', '1FN', '2FN', '3FN', 'réplication', 'WAL', 'entrepôt de données', 'ETL', 'modèle en étoile', 'faits', 'dimensions']
});
reg({
cours: { id: 'virtucloud', match: /Virtualisation : hyperviseurs|KVM|Proxmox|Infrastructure en code|Terraform|OpenTofu|Cloud : IaaS|OpenStack|Systèmes distribués|tolérance aux pannes|Automatisation et infrastructure|Administrateur systèmes, réseaux et cloud|Concevoir une solution d’évolution/i,
titre: 'Virtualisation, cloud et infrastructure en code : KVM, Proxmox, IaaS, Terraform', duree: '',
niveau: 'BTS SIO SISR · BUT R&T DevCloud · AIS · Bachelor · Master cloud',
prerequis: ['Linux : processus, stockage', 'Réseau : VLAN, routage'],
competences: ['BTS SIO SISR · Bloc 2 · Virtualiser une infrastructure', 'AIS · Administrer une infrastructure virtualisée', 'Master · Concevoir des systèmes distribués'],
intro: 'Les machines virtuelles qui font tourner les labs de Syllabus, les serveurs de l’établissement et les offres des hébergeurs reposent sur la virtualisation. Le cloud la rend disponible à la demande, et l’infrastructure en code la décrit dans des fichiers versionnés. Ce module explique le fonctionnement des hyperviseurs, l’exploitation de KVM et Proxmox, les modèles de cloud, et Terraform/OpenTofu, avec les principes de conception des systèmes distribués tolérants aux pannes.',
cm: [
{ t: 'Hyperviseurs', d: '', html: 'Un <b>hyperviseur</b> partage une machine physique entre plusieurs machines virtuelles isolées. Le <b>type 1</b> (natif) s’exécute directement sur le matériel : KVM intégré au noyau Linux, VMware ESXi, Hyper-V, Xen. Le <b>type 2</b> s’exécute comme une application sur un système hôte : VirtualBox, VMware Workstation, adapté au poste de travail. Les processeurs modernes offrent des instructions de virtualisation (Intel VT-x, AMD-V) qui rendent l’exécution quasi native. Les périphériques <b>virtio</b> (disque, réseau) sont paravirtualisés : le système invité sait qu’il est virtualisé et communique efficacement avec l’hyperviseur.' },
{ t: 'KVM, libvirt et Proxmox', d: '', html: '<b>KVM</b> transforme le noyau Linux en hyperviseur ; <b>QEMU</b> émule le matériel ; <b>libvirt</b> fournit une interface commune (<code>virsh</code>). <b>Proxmox VE</b>, distribution Debian, ajoute une interface web, la gestion de clusters, la migration à chaud, les sauvegardes et les conteneurs LXC : il est très répandu dans les établissements et les PME. Les notions à maîtriser : formats de disque (qcow2 avec instantanés, raw plus rapide), réseau en pont (bridge Linux) avec VLAN, <b>instantanés</b> (utiles avant une mise à jour, pas une sauvegarde), <b>modèles</b> (templates) et <b>cloud-init</b> pour créer des VM configurées automatiquement.' },
{ t: 'Les modèles de cloud', d: '', html: 'Le cloud fournit des ressources à la demande, facturées à l’usage. <b>IaaS</b> : machines virtuelles, réseaux, stockage ; le client gère le système et au-dessus. <b>PaaS</b> : plateforme d’exécution (bases de données gérées, hébergement d’applications) ; le client gère son code et ses données. <b>SaaS</b> : logiciel prêt à l’emploi (messagerie, ENT). Le <b>modèle de responsabilité partagée</b> fixe qui sécurise quoi. <b>OpenStack</b> est la plateforme libre de cloud IaaS utilisée par plusieurs hébergeurs européens. Pour les données publiques et sensibles, la doctrine française « cloud au centre » et la qualification <b>SecNumCloud</b> de l’ANSSI orientent vers des offres hébergées et opérées dans l’Union européenne, protégées des lois extraterritoriales.' },
{ t: 'Infrastructure en code', d: '', html: '<b>Terraform</b> et son fork libre <b>OpenTofu</b> décrivent l’infrastructure (VM, réseaux, enregistrements DNS, bases) dans des fichiers déclaratifs (HCL). Le cycle : <code>init</code> (télécharger les fournisseurs), <code>plan</code> (calculer les différences entre le code et la réalité), <code>apply</code> (appliquer). L’<b>état</b> (state) mémorise ce qui a été créé ; il contient souvent des secrets et doit être stocké de façon partagée, verrouillée et protégée. On combine Terraform pour créer les ressources et Ansible pour configurer les systèmes.', exemple: 'resource "proxmox_vm_qemu" "lab" {\n count = 30\n name = "lab-eleve-${count.index + 1}"\n target_node = "pve1"\n clone = "debian12-template"\n cores = 2\n memory = 2048\n network { model = "virtio" bridge = "vmbr0" tag = 120 }\n}\n\n$ tofu plan\nPlan: 30 to add, 0 to change, 0 to destroy.' },
{ t: 'Concevoir des systèmes distribués', d: '', html: 'Dès qu’un service repose sur plusieurs machines, des pannes partielles surviennent : un nœud lent, un réseau qui se coupe entre deux sites. Le <b>théorème CAP</b> rappelle qu’en cas de partition réseau, il faut choisir entre cohérence et disponibilité. Les principes de conception : éliminer les points uniques de défaillance, rendre les services <b>sans état</b> pour pouvoir les multiplier, placer l’état dans des systèmes répliqués (base, stockage objet), utiliser un <b>consensus</b> (Raft, utilisé par etcd) pour les décisions critiques, prévoir des délais d’expiration et des nouvelles tentatives avec temporisation croissante, et tester les pannes volontairement.' },
{ t: 'Dimensionner et exploiter', d: '', html: 'On dimensionne un hôte de virtualisation à partir des besoins : processeurs (un léger <b>surengagement</b> est acceptable), mémoire (à éviter de surengager), stockage (IOPS plus que capacité), réseau. On surveille la charge de l’hôte, le temps d’attente processeur des VM (steal time), la latence disque. Un cluster de trois nœuds avec stockage partagé ou répliqué (Ceph) permet la haute disponibilité : une VM redémarre sur un autre nœud si le sien tombe. Les sauvegardes des VM (Proxmox Backup Server) s’ajoutent aux sauvegardes applicatives.' }
],
synthese: ['Type 1 (KVM, ESXi) et type 2 (VirtualBox) ; VT-x/AMD-V ; virtio', 'KVM + QEMU + libvirt ; Proxmox : cluster, migration, sauvegardes, LXC', 'Instantanés ≠ sauvegardes ; templates et cloud-init', 'IaaS, PaaS, SaaS ; responsabilité partagée ; SecNumCloud', 'Terraform/OpenTofu : init, plan, apply, état protégé', 'Distribué : pas de point unique, sans état, consensus, CAP', 'Dimensionner mémoire et IOPS ; haute disponibilité en cluster'],
qcm: [
['KVM est un hyperviseur de type :', ['1', '2', '3', 'aucun'], 0, 'Intégré au noyau.'],
['Un instantané de VM est-il une sauvegarde ?', ['Oui', 'Non, il dépend du disque d’origine', 'Seulement en qcow2', 'Oui s’il est récent'], 1, 'Il disparaît avec le stockage.'],
['Dans un IaaS, qui met à jour le système de la VM ?', ['Le fournisseur', 'Le client', 'Personne', 'L’ANSSI'], 1, 'Responsabilité partagée.'],
['Que fait terraform plan ?', ['Crée tout', 'Montre les changements à appliquer', 'Supprime l’état', 'Installe Terraform'], 1, 'Aucune modification.'],
['Pourquoi protéger le fichier d’état Terraform ?', ['Il est gros', 'Il peut contenir des secrets et doit rester cohérent', 'Obligation', 'Il est lent'], 1, 'Stockage distant verrouillé.'],
['Que dit le théorème CAP ?', ['Tout est possible', 'En cas de partition, choisir entre cohérence et disponibilité', 'Le cloud est sûr', 'Les VM sont isolées'], 1, 'Brewer.']
],
td: [
{ n: 'Application', c: 'Dimensionner un hôte Proxmox pour 30 VM de labs (2 vCPU, 2 Go, 20 Go chacune), avec une marge de 30 %.', r: 'Mémoire : 60 Go + 30 % ≈ 80 Go (+ hôte) → 96 Go · CPU : 60 vCPU, surengagement 3:1 → 20 cœurs · disque : 600 Go en qcow2 léger sur SSD.' },
{ n: 'Application', c: 'Écrire un fichier OpenTofu qui crée 30 VM de lab à partir d’un modèle, dans le VLAN 120.', r: 'Voir l’exemple du cours : resource avec count = 30, clone du template, réseau tag 120 ; tofu plan puis apply.' },
{ n: 'Approfondissement', c: 'Concevoir l’architecture d’un service de labs tolérant à la panne d’un serveur.', r: 'Cluster de trois nœuds, stockage Ceph répliqué ×3, orchestrateur de VM avec haute disponibilité, application web sans état derrière deux répartiteurs avec IP virtuelle, base PostgreSQL répliquée, sauvegardes externes.' }
],
tp: { type: 'Lab VM', url: 'apercu-labs.html', desc: 'Virtualisation imbriquée sous KVM.', etapes: ['Créer une VM avec virsh', 'Configurer un pont réseau et un VLAN', 'Prendre et restaurer un instantané', 'Créer une VM par cloud-init', 'Décrire l’infrastructure avec OpenTofu', 'Mesurer la charge de l’hôte'] },
plusLoin: [['Proxmox VE · documentation', 'https://pve.proxmox.com/pve-docs/'], ['OpenTofu', 'https://opentofu.org/docs/'], ['ANSSI · SecNumCloud', 'https://cyber.gouv.fr/secnumcloud-pour-les-fournisseurs-de-services-cloud'], ['libvirt', 'https://libvirt.org/docs.html']] },
plus: { cas: { titre: '', texte: '' },
resolu: { enonce: 'Les VM des labs deviennent très lentes l’après-midi, alors que l’hôte Proxmox affiche un processeur à 45 %.', etapes: [
['Mesurer côté VM', 'vmstat 1 dans une VM : st (steal) = 2, wa = 61\n→ Peu d’attente processeur mais beaucoup d’attente d’entrées-sorties.'],
['Mesurer côté hôte', 'iostat -x 1 sur l’hôte : sda %util 100, await 180 ms\n→ Le disque de l’hôte est saturé.'],
['Identifier', '→ Toutes les VM sont sur un disque mécanique, et la sauvegarde planifiée à 14 h lit l’intégralité des disques pendant les cours.'],
['Corriger', '→ Sauvegarde déplacée à 2 h, VM de labs migrées à chaud vers le stockage SSD, limite de bande passante disque pour la sauvegarde.'],
['Vérifier', 'await : 3 ms · wa dans les VM : 1 %\n→ Règle de dimensionnement documentée : les VM interactives sur SSD, sauvegardes hors des heures de cours.']
] },
erreurs: ['Prendre les instantanés pour des sauvegardes', 'Surengager la mémoire', 'Dimensionner le disque en capacité sans regarder les IOPS', 'Fichier d’état Terraform sur un poste et dans Git', 'Point unique de défaillance', 'Modifier à la main une ressource gérée par Terraform'],
memo: [['Commande', 'Usage'], ['virsh list --all', 'VM et état'], ['virsh snapshot-create-as vm nom', 'instantané'], ['qm list · qm migrate', 'Proxmox : VM, migration'], ['pvesh get /cluster/resources', 'ressources du cluster'], ['tofu init · plan · apply', 'infrastructure en code'], ['tofu state list', 'ressources gérées'], ['iostat -x 1', 'charge disque'], ['vmstat 1 (colonne st)', 'temps volé à la VM']],
examen: { titre: 'Sujet type · 20 points', q: ['Comparer hyperviseurs de type 1 et 2. (3 pts)', 'Dimensionner un hôte pour un besoin donné. (5 pts)', 'Comparer IaaS, PaaS, SaaS et la responsabilité partagée. (4 pts)', 'Écrire une configuration Terraform simple. (5 pts)', 'Expliquer le théorème CAP. (3 pts)'], r: ['natif / hébergé', 'CPU, mémoire, IOPS', 'voir cours', 'resource, plan, apply', 'cohérence / disponibilité'] },
prof: { deroule: [['Ouverture', 'Créer 30 VM à la main ou en une commande'], ['Cours', 'Hyperviseurs'], ['Pratique', 'KVM et instantanés'], ['Cours', 'Cloud et IaC'], ['Pratique', 'OpenTofu'], ['Clôture', 'Quiz flash']], diff: 'Élèves en difficulté : interface Proxmox. Élèves avancés : Ceph, consensus.', eval: 'Lab validé, sujet type.' } },
exemples: [
['Lister les VM', 'Inventaire.', 'virsh list --all', ' Id Name State\n 3 lab-eleve-1 running\n - debian12-tpl shut off', 'Une VM de lab en cours et le modèle arrêté.'],
['Vérifier la virtualisation matérielle', 'Nouvel hôte.', 'grep -cE "vmx|svm" /proc/cpuinfo', '24', 'Les instructions de virtualisation sont présentes sur les 24 processeurs logiques.'],
['Planifier une infrastructure', 'Avant application.', 'tofu plan | tail -1', 'Plan: 30 to add, 0 to change, 0 to destroy.', 'Aucune ressource existante n’est modifiée.'],
['Détecter une dérive', 'Une VM modifiée à la main.', 'tofu plan | grep "~"', ' ~ memory = 4096 -> 2048', 'La mémoire a été changée hors du code ; apply la ramènerait à 2 Go.'],
['Temps volé', 'VM lente.', 'vmstat 1 3 | tail -1', ' r b … us sy id wa st\n 2 0 … 20 5 40 0 35', '35 % de steal : l’hôte surengage le processeur.'],
['Migration à chaud', 'Maintenance d’un nœud.', 'qm migrate 104 pve2 --online', 'migration finished successfully (duration 00:00:21)', 'La VM a changé d’hôte sans interruption.']
],
termes: ['hyperviseur', 'type 1', 'type 2', 'KVM', 'QEMU', 'libvirt', 'virsh', 'Proxmox', 'virtio', 'qcow2', 'instantané', 'template', 'cloud-init', 'LXC', 'IaaS', 'PaaS', 'SaaS', 'responsabilité partagée', 'OpenStack', 'SecNumCloud', 'Terraform', 'OpenTofu', 'state', 'CAP', 'consensus', 'Raft', 'Ceph']
});
reg({
cours: { id: 'logique', match: /Algèbre de Boole|Karnaugh|Portes logiques|circuits combinatoires|additionneur|Arithmétique : division euclidienne|PGCD|Bézout|congruences|Fonctions : dérivées|exponentielle|logarithme|RSA, logique|Numération, codage, logique combinatoire|Numération, modulo/i,
titre: 'Logique et arithmétique pour l’informatique : Boole, circuits, modulo et RSA', duree: '',
niveau: 'NSI · STI2D SIN · BTS SIO (maths) · BTS CIEL · BUT · classes préparatoires',
prerequis: ['Binaire'],
competences: ['NSI · Architectures matérielles : portes logiques', 'BTS SIO · Mathématiques pour l’informatique', 'STI2D SIN · Logique combinatoire'],
intro: 'Un processeur n’est qu’un immense assemblage de portes logiques ; une connexion HTTPS repose sur de l’arithmétique modulaire ; une boucle qui double à chaque tour suit une exponentielle. Ce module rassemble les bases mathématiques directement utilisées en informatique : algèbre de Boole et simplification, circuits combinatoires jusqu’à l’additionneur, arithmétique des entiers jusqu’au chiffrement RSA, et le comportement des fonctions exponentielle et logarithme.',
cm: [
{ t: 'Algèbre de Boole', d: '', html: 'Une variable booléenne vaut 0 ou 1. Trois opérations de base : <b>ET</b> (produit, a·b), <b>OU</b> (somme, a + b) et <b>NON</b> (complément, ā). Les lois usuelles permettent de simplifier : commutativité, associativité, distributivité, a + ā = 1, a·ā = 0, a + a·b = a (absorption), et les <b>lois de De Morgan</b> : NON(a ET b) = ā OU b̄, NON(a OU b) = ā ET b̄. Une fonction se décrit par sa <b>table de vérité</b> ; on en tire une expression en somme de produits (une ligne à 1 = un produit).' },
{ t: 'Tableaux de Karnaugh', d: '', html: 'Le <b>tableau de Karnaugh</b> présente la table de vérité de façon que deux cases voisines ne diffèrent que d’une variable (ordre de Gray : 00, 01, 11, 10). On regroupe les 1 en rectangles de 1, 2, 4 ou 8 cases, les plus grands possible, éventuellement en passant par les bords. Chaque groupe donne un produit où ne restent que les variables qui ne changent pas. La somme des groupes est l’expression simplifiée, qui demande moins de portes. Les cas indifférents (« X ») peuvent être inclus dans un groupe s’ils l’agrandissent.' },
{ t: 'Portes et circuits combinatoires', d: '', html: 'Chaque opération correspond à une <b>porte logique</b> : ET, OU, NON, et leurs combinaisons NON-ET (NAND), NON-OU (NOR), OU exclusif (XOR, vrai si les entrées diffèrent). La porte NAND seule suffit à construire toutes les autres : elle est dite universelle. Un <b>circuit combinatoire</b> a des sorties qui ne dépendent que des entrées : multiplexeur, décodeur, comparateur. Le <b>demi-additionneur</b> additionne deux bits : somme = a XOR b, retenue = a ET b. L’<b>additionneur complet</b> prend aussi une retenue entrante ; en chaînant n additionneurs complets, on additionne deux nombres de n bits : c’est le cœur de l’UAL.', exemple: 'Additionneur complet :\nS = a XOR b XOR r_entrée\nr_s = (a ET b) OU (r_entrée ET (a XOR b))' },
{ t: 'Division euclidienne et congruences', d: '', html: 'Pour deux entiers a et b > 0, il existe un unique couple (q, r) tel que a = b·q + r avec 0 ≤ r < b : c’est la <b>division euclidienne</b> ; en programmation, <code>a // b</code> et <code>a % b</code>. On dit que a est <b>congru</b> à r modulo b. L’arithmétique <b>modulaire</b> est partout : heures sur 24, jours de la semaine, numéros de clé de contrôle (RIB, INE, numéro de sécurité sociale), répartition de charge par hachage, et cryptographie. On peut additionner et multiplier les congruences, ce qui permet de calculer de grandes puissances modulaires sans manipuler d’énormes nombres (exponentiation rapide).' },
{ t: 'PGCD, Bézout et RSA', d: '', html: 'L’<b>algorithme d’Euclide</b> calcule le PGCD par divisions successives : PGCD(a, b) = PGCD(b, a mod b), jusqu’à un reste nul. Le <b>théorème de Bézout</b> affirme qu’il existe des entiers u et v tels que a·u + b·v = PGCD(a, b) ; l’algorithme d’Euclide étendu les calcule, ce qui permet de trouver l’<b>inverse modulaire</b> d’un nombre premier avec le module.<br><br><b>RSA</b> repose sur ces outils : on choisit deux grands nombres premiers p et q, n = p·q, φ = (p − 1)(q − 1), un exposant e premier avec φ, et d l’inverse de e modulo φ. La clé publique est (n, e), la clé privée d. Chiffrer : c = m<sup>e</sup> mod n ; déchiffrer : m = c<sup>d</sup> mod n. La sécurité repose sur la difficulté de factoriser n quand p et q ont des centaines de chiffres.', exemple: 'p = 61, q = 53, n = 3233, φ = 3120\ne = 17 (premier avec 3120), d = 2753 (17 × 2753 = 46801 ≡ 1 mod 3120)\nm = 65 → c = 65¹⁷ mod 3233 = 2790 → 2790²⁷⁵³ mod 3233 = 65' },
{ t: 'Exponentielle et logarithme', d: '', html: 'La fonction <b>exponentielle</b> modélise les croissances proportionnelles à la valeur atteinte : un nombre d’utilisateurs qui augmente de 5 % par mois, un algorithme en O(2ⁿ). Le <b>logarithme</b> est sa réciproque : log₂(n) est le nombre de fois qu’on peut diviser n par deux, d’où la complexité de la recherche dichotomique, la profondeur d’un arbre équilibré, ou le nombre de bits nécessaires pour coder n valeurs. Propriétés utiles : log(a·b) = log a + log b, log(aⁿ) = n·log a. La <b>dérivée</b> mesure une vitesse de variation : elle sert à la descente de gradient des réseaux de neurones et à l’étude des variations d’une fonction de coût.' }
],
synthese: ['Boole : ET, OU, NON ; De Morgan ; table de vérité', 'Karnaugh : ordre de Gray, groupes de 2ⁿ cases', 'Portes ET, OU, NON, NAND, NOR, XOR ; NAND universelle', 'Demi-additionneur et additionneur complet : base de l’UAL', 'Division euclidienne, congruences, exponentiation rapide', 'Euclide, Bézout, inverse modulaire, RSA', 'Exponentielle pour les croissances, logarithme pour les divisions par deux'],
qcm: [
['NON(a ET b) est égal à :', ['ā ET b̄', 'ā OU b̄', 'a OU b', 'a XOR b'], 1, 'De Morgan.'],
['Somme du demi-additionneur ?', ['a ET b', 'a OU b', 'a XOR b', 'NON a'], 2, 'Retenue = a ET b.'],
['Quelle porte est universelle ?', ['XOR', 'NAND', 'OU', 'NON'], 1, 'Tout se construit avec des NAND.'],
['17 mod 5 ?', ['3', '2', '1', '0'], 1, '17 = 5 × 3 + 2.'],
['PGCD(84, 36) ?', ['6', '12', '18', '4'], 1, '84 = 2×36 + 12, 36 = 3×12.'],
['Sur quoi repose la sécurité de RSA ?', ['La vitesse', 'La difficulté de factoriser n', 'Le secret de l’algorithme', 'Le hachage'], 1, 'Grands nombres premiers.'],
['log₂(1024) ?', ['8', '10', '12', '512'], 1, '2¹⁰ = 1024.']
],
td: [
{ n: 'Application', c: 'Simplifier par Karnaugh la fonction à 3 variables valant 1 pour les combinaisons abc = 001, 011, 101, 111.', r: 'Les quatre 1 forment un groupe où c = 1 : F = c.' },
{ n: 'Application', c: 'Construire la table de vérité de l’additionneur complet et vérifier les expressions de S et de la retenue.', r: '8 lignes ; S vaut 1 quand le nombre d’entrées à 1 est impair ; la retenue vaut 1 quand au moins deux entrées valent 1.' },
{ n: 'Application', c: 'Calculer avec l’algorithme d’Euclide étendu l’inverse de 17 modulo 3120.', r: '3120 = 17 × 183 + 9 ; 17 = 9 + 8 ; 9 = 8 + 1 → en remontant : 1 = 2 × 3120 − 367 × 17 → inverse ≡ −367 ≡ 2753.' },
{ n: 'Approfondissement', c: 'Écrire en Python l’exponentiation modulaire rapide et la comparer à pow(m, e, n).', r: 'def expmod(m, e, n):\n r = 1\n while e:\n if e & 1: r = r * m % n\n m = m * m % n\n e >>= 1\n return r' }
],
tp: { type: 'IDE Python', url: 'apercu-ide.html', desc: 'Logique et arithmétique en code.', etapes: ['Générer une table de vérité', 'Simuler un additionneur 4 bits', 'Algorithme d’Euclide étendu', 'RSA avec de petits nombres', 'Exponentiation rapide et mesure'] },
plusLoin: [['Logisim Evolution (simulateur de circuits)', 'https://github.com/logisim-evolution/logisim-evolution'], ['Eduscol · NSI', 'https://eduscol.education.fr/'], ['Nand to Tetris', 'https://www.nand2tetris.org/']] },
plus: { cas: { titre: '', texte: '' },
resolu: { enonce: 'Un script de contrôle des numéros INE saisis dans l’application rejette des numéros valides.', etapes: [
['Comprendre la règle', '→ Les identifiants comportent une clé de contrôle calculée par une opération modulo sur la partie numérique ; le script doit recalculer la clé et la comparer.'],
['Tester', 'controle("070123456AB") → False alors que le numéro figure dans l’annuaire officiel.'],
['Lire le code', 'cle = int(partie) % 23\n→ Le script utilise un modulo différent de celui de la spécification, et convertit la lettre de clé avec un décalage erroné.'],
['Corriger', '→ Réécriture selon la documentation de la règle de calcul, avec des tests sur une liste de numéros valides et invalides fournie.'],
['Retenir', '→ Toute règle de contrôle par modulo se vérifie avec un jeu de tests issus de cas réels, avant la mise en production.']
] },
erreurs: ['Oublier une ligne de la table de vérité', 'Groupes de Karnaugh de 3 ou 6 cases', 'Confondre OU et OU exclusif', 'Calculer mᵉ puis mod n sur de grands nombres', 'Croire que RSA est sûr avec de petits nombres', 'Confondre log₂ et log₁₀'],
memo: [['Formule', 'Usage'], ['NON(a·b) = ā + b̄', 'De Morgan'], ['a + a·b = a', 'absorption'], ['S = a ⊕ b ⊕ r', 'somme d’un additionneur'], ['a = bq + r, 0 ≤ r < b', 'division euclidienne'], ['PGCD(a, b) = PGCD(b, a mod b)', 'Euclide'], ['au + bv = PGCD(a, b)', 'Bézout'], ['c = mᵉ mod n · m = cᵈ mod n', 'RSA'], ['pow(m, e, n)', 'exponentiation modulaire en Python'], ['log(ab) = log a + log b', 'logarithme']],
examen: { titre: 'Sujet type · 20 points', q: ['Simplifier une fonction par Karnaugh. (5 pts)', 'Dessiner un additionneur complet. (4 pts)', 'Calculer un PGCD et un inverse modulaire. (5 pts)', 'Dérouler RSA sur de petits nombres. (4 pts)', 'Utiliser un logarithme pour une complexité. (2 pts)'], r: ['groupes', 'XOR, ET, OU', 'Euclide étendu', 'n, φ, e, d', 'log₂ n'] },
prof: { deroule: [['Ouverture', 'Construire un additionneur dans Logisim'], ['Cours', 'Boole et Karnaugh'], ['Pratique', 'Circuits'], ['Cours', 'Modulo, Euclide, RSA'], ['Pratique', 'RSA en Python'], ['Clôture', 'Quiz flash']], diff: 'Élèves en difficulté : tables guidées. Élèves avancés : exponentiation rapide, test de primalité.', eval: 'Sujet type.' } },
exemples: [
['Table de vérité', 'XOR.', 'python3 -c "print([(a, b, a ^ b) for a in (0, 1) for b in (0, 1)])"', '[(0, 0, 0), (0, 1, 1), (1, 0, 1), (1, 1, 0)]', 'Vrai si les entrées diffèrent.'],
['Addition binaire', 'Vérifier un additionneur.', 'python3 -c "print(bin(0b1011 + 0b0110))"', '0b10001', '11 + 6 = 17 : la dernière retenue produit un cinquième bit.'],
['PGCD', 'Euclide.', 'python3 -c "import math; print(math.gcd(84, 36))"', '12', 'Comme le calcul à la main.'],
['Inverse modulaire', 'Clé privée RSA.', 'python3 -c "print(pow(17, -1, 3120))"', '2753', 'Python 3.8+ calcule directement l’inverse.'],
['Chiffrer et déchiffrer', 'RSA jouet.', 'python3 -c "c = pow(65, 17, 3233); print(c, pow(c, 2753, 3233))"', '2790 65', 'Le message revient intact.'],
['Nombre de bits', 'Coder 1 500 identifiants.', 'python3 -c "import math; print(math.ceil(math.log2(1500)))"', '11', '11 bits suffisent (2¹¹ = 2048).']
],
termes: ['algèbre de Boole', 'ET', 'OU', 'NON', 'XOR', 'NAND', 'NOR', 'De Morgan', 'table de vérité', 'Karnaugh', 'code de Gray', 'porte logique', 'circuit combinatoire', 'demi-additionneur', 'additionneur complet', 'division euclidienne', 'modulo', 'congruence', 'PGCD', 'Euclide', 'Bézout', 'inverse modulaire', 'RSA', 'logarithme', 'exponentielle']
});
reg({
cours: { id: 'bigdata', match: /Kafka|Spark|Traitement distribué|Flux temps réel|big data|Ingénierie des données/i,
titre: 'Ingénierie des données à grande échelle : pipelines, Kafka et Spark', duree: '',
niveau: 'BUT SD / Informatique · école d’ingénieurs · Master data',
prerequis: ['Analyse de données avec pandas', 'SQL', 'Docker'],
competences: ['BUT SD · Traiter des données massives', 'Master · Concevoir un pipeline de données'],
intro: 'Quand les données dépassent la mémoire d’une machine ou arrivent en continu, pandas et une base unique ne suffisent plus. Le data engineer conçoit des pipelines qui collectent, transportent, transforment et stockent ces données de façon fiable. Ce module présente l’architecture d’un pipeline, le transport d’événements avec Apache Kafka, le traitement distribué avec Apache Spark, et les formats et pratiques qui rendent l’ensemble exploitable.',
cm: [
{ t: 'Architecture d’un pipeline', d: '', html: 'Un pipeline suit des étapes : <b>ingestion</b> (bases, fichiers, API, capteurs, journaux), <b>stockage brut</b> (lac de données, souvent en stockage objet S3), <b>transformation</b> (nettoyage, jointures, agrégats), <b>stockage préparé</b> (entrepôt ou couche « gold »), puis <b>exposition</b> (tableaux de bord, modèles, API). Le traitement par <b>lots</b> (batch) s’exécute périodiquement ; le traitement en <b>flux</b> (streaming) traite chaque événement à son arrivée. Un <b>orchestrateur</b> (Airflow, Dagster) planifie les tâches et leurs dépendances, et rejoue celles qui échouent.' },
{ t: 'Formats et stockage', d: '', html: 'Le CSV ne porte pas de types et se lit lentement. Les formats en <b>colonnes</b> comme <b>Parquet</b> sont typés, compressés, et permettent de ne lire que les colonnes utiles. Les formats de tables comme <b>Delta Lake</b> ou <b>Apache Iceberg</b> ajoutent sur Parquet des transactions, l’historique des versions et l’évolution du schéma. On <b>partitionne</b> les données (par date, par établissement) pour ne lire que les partitions nécessaires.' },
{ t: 'Kafka : le journal d’événements', d: '', html: '<b>Apache Kafka</b> est un <b>journal distribué</b> : des <b>producteurs</b> écrivent des messages dans des <b>topics</b>, découpés en <b>partitions</b> répliquées sur plusieurs <b>brokers</b> ; des <b>consommateurs</b> les lisent à leur rythme en suivant leur position (<b>offset</b>). Les messages sont conservés pendant une durée configurée, ce qui permet de relire l’historique. L’ordre est garanti à l’intérieur d’une partition ; la clé du message détermine sa partition. Les consommateurs d’un même <b>groupe</b> se répartissent les partitions pour monter en charge. Kafka découple les systèmes : la source d’événements (connexions, mains levées, mesures de capteurs) n’a pas à connaître ses consommateurs.' },
{ t: 'Spark : le calcul distribué', d: '', html: '<b>Apache Spark</b> répartit un calcul sur un cluster. Un <b>pilote</b> (driver) découpe le travail en tâches exécutées par des <b>exécuteurs</b>. Le <b>DataFrame</b> de Spark ressemble à celui de pandas, mais ses opérations sont <b>paresseuses</b> : elles construisent un plan, optimisé puis exécuté seulement lors d’une action (count, write). Les transformations qui regroupent ou joignent des données provoquent un <b>shuffle</b>, échange réseau coûteux entre machines. Spark SQL permet d’écrire les traitements en SQL, et Structured Streaming applique le même modèle aux flux, par exemple depuis Kafka.', exemple: 'from pyspark.sql import SparkSession, functions as F\nspark = SparkSession.builder.appName("activite").getOrCreate()\ndf = spark.read.parquet("s3a://lac/activite/annee=2026/")\n(df.filter(F.col("type") == "lab")\n .groupBy("etablissement", "semaine")\n .agg(F.countDistinct("eleve").alias("eleves"), F.avg("duree").alias("duree_moy"))\n .write.mode("overwrite").partitionBy("semaine").parquet("s3a://gold/activite_hebdo/"))' },
{ t: 'Fiabilité et qualité', d: '', html: 'Un pipeline de production doit être <b>idempotent</b> : rejouer un traitement ne doit pas dupliquer les données (écriture par partition en remplacement, clés uniques). Il faut gérer les <b>données tardives</b> en streaming (fenêtres et filigranes), les <b>garanties de livraison</b> (au moins une fois, exactement une fois), et contrôler la <b>qualité</b> à chaque étape : schéma attendu, valeurs manquantes, volumes anormaux (Great Expectations, tests dbt). La <b>traçabilité</b> (lignage) indique d’où vient chaque donnée, utile pour le RGPD et pour corriger une erreur à la source.' },
{ t: 'Données personnelles et sobriété', d: '', html: 'Les données d’élèves restent des données personnelles même dans un lac de données : on pseudonymise au plus tôt, on applique des durées de conservation, on limite les accès par rôle et on journalise. Les traitements massifs ont aussi un coût énergétique : on ne garde que les données utiles, on choisit des formats compressés, on dimensionne les clusters à la demande et on préfère souvent une seule machine bien dimensionnée (DuckDB, Polars) à un cluster quand le volume le permet.' }
],
synthese: ['Ingestion → brut → transformation → préparé → exposition ; lots ou flux ; orchestrateur', 'Parquet, Delta/Iceberg, partitionnement', 'Kafka : topics, partitions, offsets, groupes, rétention', 'Spark : driver, exécuteurs, évaluation paresseuse, shuffle, Spark SQL, Structured Streaming', 'Idempotence, données tardives, garanties de livraison, qualité, lignage', 'Pseudonymiser, conserver le nécessaire, dimensionner sobrement'],
qcm: [
['Où l’ordre des messages est-il garanti dans Kafka ?', ['Dans tout le topic', 'Dans une partition', 'Nulle part', 'Par broker'], 1, 'La clé choisit la partition.'],
['Qu’est-ce qu’un offset ?', ['Une clé', 'La position d’un consommateur dans une partition', 'Un serveur', 'Un format'], 1, 'Permet de reprendre.'],
['Quand Spark exécute-t-il réellement les transformations ?', ['Immédiatement', 'Lors d’une action', 'Jamais', 'Au démarrage'], 1, 'Évaluation paresseuse.'],
['Qu’est-ce qu’un shuffle ?', ['Un tri local', 'Un échange de données entre machines pour regrouper ou joindre', 'Une erreur', 'Un format'], 1, 'Opération coûteuse.'],
['Pourquoi un pipeline doit-il être idempotent ?', ['Vitesse', 'Le rejouer ne doit pas dupliquer les données', 'Obligation', 'Sécurité'], 1, 'Reprises sans risque.'],
['Pourquoi préférer Parquet au CSV ?', ['Lisible', 'Typé, compressé, lecture par colonnes', 'Obligatoire', 'Plus petit en mémoire'], 1, 'Format colonne.']
],
td: [
{ n: 'Application', c: 'Concevoir le pipeline qui alimente chaque nuit le tableau de bord académique des labs à partir des bases de 40 établissements.', r: 'Extraction incrémentale (depuis la dernière date) → Parquet partitionné par jour et établissement dans le lac → pseudonymisation → agrégats Spark ou DuckDB → tables gold → tableau de bord ; orchestration Airflow avec reprise et contrôles de volume.' },
{ n: 'Application', c: 'Choisir le nombre de partitions et la clé d’un topic Kafka « mains-levees » consommé par 4 instances, l’ordre devant être respecté par salle.', r: 'Clé = identifiant de la salle (ordre par salle) · au moins 4 partitions, idéalement 8 à 12 pour la croissance · réplication 3.' },
{ n: 'Approfondissement', c: 'Un traitement Spark de 10 Go met 40 minutes. Proposer des pistes d’optimisation.', r: 'Lire seulement les colonnes et partitions utiles · filtrer avant de joindre · diffuser la petite table (broadcast join) · réduire les shuffles · vérifier le déséquilibre des clés · ou utiliser DuckDB sur une seule machine.' }
],
tp: { type: 'Lab VM', url: 'apercu-labs.html', desc: 'Kafka et Spark en conteneurs.', etapes: ['Démarrer Kafka avec Compose', 'Produire et consommer des événements', 'Lire un flux avec Structured Streaming', 'Agréger par fenêtre', 'Écrire en Parquet partitionné', 'Comparer avec DuckDB'] },
plusLoin: [['Apache Kafka · documentation', 'https://kafka.apache.org/documentation/'], ['Apache Spark · documentation', 'https://spark.apache.org/docs/latest/'], ['DataCamp · Big Data with PySpark', 'https://www.datacamp.com/tracks/big-data-with-pyspark'], ['Data Engineering Zoomcamp', 'https://github.com/DataTalksClub/data-engineering-zoomcamp']] },
plus: { cas: { titre: '', texte: '' },
resolu: { enonce: 'Le tableau de bord affiche deux fois plus d’heures de labs que la réalité pour la semaine dernière.', etapes: [
['Comparer avec la source', 'SELECT SUM(duree) FROM activite WHERE semaine = 39 (base source) → 1 840 h ; tableau de bord → 3 680 h\n→ Exactement le double.'],
['Lire l’historique de l’orchestrateur', '→ La tâche du lundi a échoué à mi-parcours puis a été relancée ; elle écrivait en mode ajout (append).'],
['Identifier', '→ La première exécution partielle et la seconde complète ont toutes deux été écrites : traitement non idempotent.'],
['Corriger', '.write.mode("overwrite").option("partitionOverwriteMode", "dynamic").partitionBy("semaine")\n→ Chaque exécution remplace la partition qu’elle traite ; on recalcule la semaine 39.'],
['Prévenir', '→ Contrôle automatique : le total d’heures doit correspondre à la source à 1 % près, sinon la publication est bloquée et une alerte est envoyée.']
] },
erreurs: ['Écrire en mode ajout un traitement rejouable', 'Stocker en CSV non typé', 'Clé Kafka mal choisie qui casse l’ordre ou déséquilibre les partitions', 'Collecter un gros DataFrame sur le pilote', 'Pas de contrôle de qualité', 'Données personnelles non pseudonymisées dans le lac'],
memo: [['Commande / API', 'Usage'], ['kafka-topics.sh --create --partitions 8 --replication-factor 3', 'créer un topic'], ['kafka-console-producer.sh / consumer.sh', 'tester'], ['kafka-consumer-groups.sh --describe --group g', 'retard des consommateurs'], ['spark.read.parquet(...)', 'lire'], ['df.explain()', 'plan d’exécution'], ['.write.partitionBy(...).mode("overwrite")', 'écrire de façon idempotente'], ['F.window("ts", "5 minutes")', 'fenêtres en streaming'], ['duckdb', 'analyse locale de Parquet']],
examen: { titre: 'Sujet type · 20 points', q: ['Décrire l’architecture d’un pipeline. (4 pts)', 'Expliquer topics, partitions, offsets et groupes Kafka. (5 pts)', 'Écrire un traitement Spark. (5 pts)', 'Expliquer l’idempotence et la corriger dans un cas. (4 pts)', 'Mesures RGPD d’un lac de données. (2 pts)'], r: ['étapes', 'voir cours', 'read, groupBy, write', 'overwrite par partition', 'pseudonymisation, conservation'] },
prof: { deroule: [['Ouverture', 'Un fichier qui ne tient pas en mémoire'], ['Cours', 'Pipelines et formats'], ['Pratique', 'Kafka'], ['Cours', 'Spark'], ['Pratique', 'Streaming'], ['Clôture', 'Quiz flash']], diff: 'Élèves en difficulté : notebooks guidés. Élèves avancés : Iceberg, exactly-once.', eval: 'Pipeline fonctionnel, sujet type.' } },
exemples: [
['Créer un topic', 'Mise en place.', 'kafka-topics.sh --bootstrap-server kafka:9092 --create --topic mains-levees --partitions 8 --replication-factor 3', 'Created topic mains-levees.', 'Huit partitions répliquées trois fois.'],
['Retard des consommateurs', 'Le tableau de bord n’est plus à jour.', 'kafka-consumer-groups.sh --bootstrap-server kafka:9092 --describe --group tableau', 'TOPIC PARTITION CURRENT-OFFSET LOG-END-OFFSET LAG\nmains-levees 0 18233 18233 0\nmains-levees 3 9120 52218 43098', 'La partition 3 accumule du retard : consommateur bloqué ou clé déséquilibrée.'],
['Plan Spark', 'Comprendre la lenteur.', 'df.groupBy("etablissement").count().explain()', '== Physical Plan ==\nHashAggregate(keys=[etablissement]…)\n+- Exchange hashpartitioning(etablissement, 200)\n +- HashAggregate(…)\n +- FileScan parquet […] PushedFilters: [], ReadSchema: struct<etablissement:string>', 'Exchange = shuffle ; seule la colonne utile est lue.'],
['Volume réel', 'Faut-il un cluster ?', 'du -sh /lac/activite/annee=2026/', '6.2G', '6 Go de Parquet tiennent sur une seule machine avec DuckDB ou Polars.'],
['Analyse locale', 'Même calcul sans cluster.', "duckdb -c \"SELECT etablissement, COUNT(DISTINCT eleve) FROM '/lac/activite/annee=2026/*/*.parquet' GROUP BY 1 ORDER BY 2 DESC LIMIT 3\"", '0750012A | 1840\n0930045K | 1612\n…', 'Résultat en quelques secondes.'],
['Consommer un flux', 'Test.', 'kafka-console-consumer.sh --bootstrap-server kafka:9092 --topic mains-levees --from-beginning --max-messages 2', '{"salle":"B204","eleve":"a3f9c1","etape":4,"ts":"2026-10-01T10:14:02"}\n{"salle":"B204","eleve":"7b20e1","etape":2,"ts":"2026-10-01T10:14:09"}', 'Événements pseudonymisés, ordonnés par salle.']
],
termes: ['pipeline', 'ingestion', 'lac de données', 'batch', 'streaming', 'orchestrateur', 'Airflow', 'Parquet', 'Delta Lake', 'Iceberg', 'partitionnement', 'Kafka', 'topic', 'partition', 'broker', 'producteur', 'consommateur', 'offset', 'groupe', 'Spark', 'driver', 'exécuteur', 'évaluation paresseuse', 'shuffle', 'idempotent', 'lignage']
});
reg({
cours: { id: 'pro', match: /Rédiger une documentation|compte rendu|Veille technologique|Relation client|support utilisateur|Anglais technique|CEJM et anglais|Assister les utilisateurs|Comptabilité et gestion d’entreprise/i,
titre: 'Compétences professionnelles : documentation, compte rendu, veille, support et anglais technique', duree: '',
niveau: 'Bac pro CIEL · BTS SIO / CIEL · BUT · Titres pro TSSR / AIS',
prerequis: ['Aucun'],
competences: ['BTS SIO · Bloc 1 · Organiser son développement professionnel, répondre aux demandes', 'TSSR · Assister les utilisateurs', 'Tous référentiels · Communiquer'],
intro: 'Un technicien est jugé autant sur ce qu’il sait faire que sur la façon dont il l’explique, le documente et le partage. Une procédure claire évite d’être appelé pendant ses congés, un compte rendu précis désamorce une crise, une veille régulière évite d’être surpris par une faille, et une bonne relation avec les utilisateurs rend tout le reste plus simple. Ce module présente ces compétences, évaluées dans toutes les épreuves professionnelles, et l’anglais technique indispensable pour lire la documentation.',
cm: [
{ t: 'La documentation technique', d: '', html: 'On distingue plusieurs documents. La <b>documentation d’architecture</b> décrit l’ensemble : schéma réseau, plan d’adressage, flux, dépendances. La <b>procédure</b> décrit une tâche pas à pas, pour qu’un collègue puisse l’exécuter sans aide : prérequis, étapes numérotées avec les commandes exactes, résultat attendu à chaque étape, vérification, retour arrière. Le <b>guide utilisateur</b> explique un usage avec des mots simples et des captures. Une bonne documentation est datée, versionnée (Git, wiki), relue, et tenue à jour à chaque changement : une documentation fausse est pire qu’une absence de documentation.' },
{ t: 'Le compte rendu d’incident ou d’intervention', d: '', html: 'Un compte rendu répond aux questions essentielles : <b>quoi</b> (symptôme constaté, impact), <b>quand</b> (heures de début, de détection, de résolution), <b>qui</b> (personnes concernées, intervenants), <b>cause</b> (racine, démontrée par les éléments recueillis), <b>actions</b> (ce qui a été fait, dans l’ordre), <b>résultat</b> et <b>actions préventives</b> avec un responsable et une échéance. On écrit des faits vérifiables, sans chercher de coupable : l’objectif est que l’incident ne se reproduise pas. La démarche « post-mortem sans blâme » des équipes d’exploitation formalise cette approche.' },
{ t: 'La veille technologique', d: '', html: 'La veille consiste à suivre de façon organisée les évolutions de son domaine : vulnérabilités (avis du CERT-FR), nouvelles versions et fins de support des logiciels utilisés, évolutions réglementaires (CNIL, ANSSI), nouvelles technologies. On choisit des <b>sources fiables</b> (sites officiels, documentations, publications d’éditeurs, revues spécialisées), on les agrège (flux RSS, lettres d’information), on <b>trie et vérifie</b> (croiser les sources, dater l’information), puis on <b>synthétise</b> et on <b>diffuse</b> ce qui est utile à l’équipe. Au BTS SIO, la veille fait partie du portfolio présenté à l’épreuve E5.' },
{ t: 'Le support utilisateur', d: '', html: 'Le support suit un circuit : <b>réception</b> de la demande (de préférence par un outil de tickets, pas par un couloir), <b>qualification</b> (incident ou demande, priorité selon l’impact et l’urgence), <b>diagnostic</b>, <b>résolution</b> ou <b>escalade</b> vers un niveau supérieur, <b>clôture</b> après validation par l’utilisateur, et capitalisation dans une base de connaissances. Côté relation : écouter jusqu’au bout, reformuler, poser des questions fermées pour préciser (« le message apparaît-il au démarrage ou à l’ouverture de l’ENT ? »), expliquer sans jargon, annoncer un délai réaliste et le tenir, et rester courtois même face à un utilisateur agacé, dont la frustration vise rarement la personne qui répond.' },
{ t: 'Communiquer à l’oral', d: '', html: 'Présenter une solution à un responsable ou un jury suppose d’adapter le niveau de détail à l’auditoire : le proviseur veut connaître l’impact, le coût et le risque ; le collègue technique veut les choix et la configuration. Une structure simple fonctionne : contexte et besoin, solution retenue et alternatives écartées, mise en œuvre, résultats mesurés, limites et suites. On s’appuie sur une démonstration ou un schéma plutôt que sur des diapositives chargées de texte.' },
{ t: 'L’anglais technique', d: '', html: 'Documentations, messages d’erreur, forums, normes et RFC sont presque toujours en anglais. Il faut lire couramment ce vocabulaire et savoir rédiger un message clair, par exemple un rapport de bogue sur un projet libre ou une demande au support d’un éditeur : contexte (versions, système), étapes pour reproduire, résultat attendu, résultat obtenu, journaux pertinents. Quelques faux amis fréquents : <i>eventually</i> (finalement), <i>actually</i> (en fait), <i>library</i> (bibliothèque), <i>to deprecate</i> (déconseiller, avant suppression), <i>legacy</i> (hérité, ancien).', table: [['Anglais', 'Français'], ['deprecated', 'déconseillé, voué à disparaître'], ['workaround', 'contournement'], ['root cause', 'cause racine'], ['rollback', 'retour arrière'], ['throughput', 'débit'], ['outage', 'panne, indisponibilité'], ['to troubleshoot', 'diagnostiquer, dépanner'], ['release notes', 'notes de version'], ['breaking change', 'changement incompatible']] }
],
synthese: ['Architecture, procédure, guide utilisateur ; datés, versionnés, à jour', 'Compte rendu : quoi, quand, qui, cause, actions, résultat, prévention ; sans blâme', 'Veille : sources fiables, tri, synthèse, diffusion', 'Support : réception, qualification, diagnostic, résolution ou escalade, clôture, capitalisation', 'Oral : adapter au public, structure claire, démonstration', 'Anglais : lire la documentation, rédiger un rapport de bogue, faux amis'],
qcm: [
['Qu’est-ce qu’une bonne procédure doit permettre ?', ['Impressionner', 'Qu’un collègue exécute la tâche sans aide', 'Remplacer la formation', 'Être courte à tout prix'], 1, 'Étapes, résultat attendu, retour arrière.'],
['Objectif d’un post-mortem sans blâme ?', ['Trouver un coupable', 'Éviter que l’incident se reproduise', 'Sanctionner', 'Rassurer'], 1, 'Faits et actions préventives.'],
['Que signifie « deprecated » ?', ['Supprimé', 'Déconseillé, voué à disparaître', 'Nouveau', 'Rapide'], 1, 'Il fonctionne encore.'],
['Première étape du support ?', ['Résoudre', 'Recevoir et qualifier la demande', 'Escalader', 'Clôturer'], 1, 'Priorité selon impact et urgence.'],
['Source fiable pour les vulnérabilités en France ?', ['Un forum', 'Le CERT-FR', 'Un réseau social', 'Une vidéo'], 1, 'Avis officiels.'],
['Que contient un rapport de bogue utile ?', ['Une plainte', 'Versions, étapes pour reproduire, attendu, obtenu, journaux', 'Une capture seule', 'Un titre'], 1, 'Reproductible.']
],
td: [
{ n: 'Application', c: 'Rédiger la procédure « ajouter une salle de TP au réseau » à partir des cours VLAN et DHCP.', r: 'Prérequis (plan d’adressage, accès aux switchs) · 1. créer le VLAN · 2. l’autoriser sur les trunks · 3. créer la passerelle · 4. créer l’étendue DHCP · 5. affecter les ports · 6. tester depuis un poste · retour arrière.' },
{ n: 'Application', c: 'Transformer les notes brutes d’une intervention (fournies) en compte rendu structuré.', r: 'Titre, date · symptôme et impact · chronologie horodatée · cause racine démontrée · actions · résultat · prévention avec responsable et échéance.' },
{ n: 'Application', c: 'Rédiger en anglais un rapport de bogue pour un projet libre dont le paquet échoue à démarrer après mise à jour.', r: 'Title · Environment (Debian 12, version x.y) · Steps to reproduce · Expected behavior · Actual behavior (with log excerpt) · Workaround if any.' },
{ n: 'Approfondissement', c: 'Mettre en place une veille sur les logiciels de l’établissement : sources, outil, rythme, diffusion.', r: 'CERT-FR, notes de version des éditeurs, flux RSS dans un agrégateur · lecture hebdomadaire · synthèse mensuelle et alerte immédiate pour les failles critiques · archivage dans le wiki.' }
],
tp: { type: 'Atelier', url: 'apercu-aide.html', desc: 'Mise en situation de support et de documentation.', etapes: ['Jeu de rôle : appel d’un utilisateur', 'Créer et qualifier un ticket', 'Rédiger la fiche de base de connaissances', 'Rédiger un compte rendu d’incident', 'Présenter oralement la solution en 3 minutes'] },
plusLoin: [['CERT-FR · avis et alertes', 'https://www.cert.ssi.gouv.fr/'], ['Google SRE Book · Postmortem Culture', 'https://sre.google/sre-book/postmortem-culture/'], ['Documentation GLPI · assistance', 'https://glpi-project.org/fr/documentation/'], ['Write the Docs', 'https://www.writethedocs.org/guide/']] },
plus: { cas: { titre: '', texte: '' },
resolu: { enonce: 'Une enseignante appelle, très agacée : « Rien ne marche, je dois faire cours dans dix minutes. »', etapes: [
['Accueillir', '→ « Je comprends, on va regarder ça tout de suite. » Laisser expliquer sans interrompre.'],
['Qualifier', '→ Questions fermées : quel appareil ? quelle salle ? quel message ? Résultat : le vidéoprojecteur de la salle C112 n’affiche rien. Impact élevé, urgence immédiate : priorité haute.'],
['Diagnostiquer et contourner', '→ À distance, guider : source HDMI sélectionnée, câble branché. Sans succès : prêt immédiat d’un vidéoprojecteur mobile pour que le cours ait lieu.'],
['Résoudre', '→ Après le cours : lampe du vidéoprojecteur en fin de vie (compteur dépassé), remplacement.'],
['Clôturer et capitaliser', '→ Ticket clôturé après validation de l’enseignante ; fiche de base de connaissances « vidéoprojecteur sans image » ; ajout du suivi des heures de lampe dans l’inventaire GLPI pour anticiper.']
] },
erreurs: ['Procédure sans résultat attendu ni retour arrière', 'Compte rendu qui cherche un coupable', 'Documentation jamais mise à jour', 'Veille sans sources fiables ni synthèse', 'Jargon avec un utilisateur', 'Promettre un délai intenable', 'Traiter une demande sans ticket'],
memo: [['Document', 'Contenu clé'], ['Procédure', 'prérequis, étapes, résultat attendu, vérification, retour arrière'], ['Compte rendu', 'quoi, quand, qui, cause, actions, résultat, prévention'], ['Fiche de veille', 'source, date, résumé, impact pour nous, action'], ['Ticket', 'demandeur, catégorie, priorité, description, résolution'], ['Rapport de bogue (EN)', 'environment, steps, expected, actual, logs'], ['Priorité', 'impact × urgence'], ['Escalade', 'quand la résolution dépasse son niveau ou son délai']],
examen: { titre: 'Sujet type · 20 points', q: ['Rédiger une procédure pour une tâche donnée. (6 pts)', 'Rédiger un compte rendu à partir de notes. (5 pts)', 'Qualifier trois demandes de support. (3 pts)', 'Présenter une démarche de veille. (3 pts)', 'Traduire et expliquer un extrait de documentation en anglais. (3 pts)'], r: ['étapes vérifiables', 'structure du cours', 'impact et urgence', 'sources, tri, diffusion', 'vocabulaire'] },
prof: { deroule: [['Ouverture', 'Exécuter une procédure mal écrite'], ['Cours', 'Documentation et compte rendu'], ['Atelier', 'Rédaction'], ['Cours', 'Support et veille'], ['Jeu de rôle', 'Appel d’utilisateur'], ['Clôture', 'Oral de 3 minutes']], diff: 'Tous niveaux : modèles fournis. Élèves avancés : post-mortem complet, oral en anglais.', eval: 'Documents rédigés, oral, sujet type.' } },
exemples: [
['Versionner une procédure', 'Mise à jour du wiki.', 'git log --oneline -3 docs/procedures/ajout-salle.md', 'a91c2e3 Ajout de l’étape DHCP snooping\n4f0b7d1 Correction du VLAN natif\n1c22e90 Création de la procédure', 'L’historique montre qui a modifié quoi et quand.'],
['Lire des notes de version', 'Veille.', 'curl -s https://www.postgresql.org/support/versioning/ | grep -o "16[^<]*November 2028"', '16 … November 2028', 'Fin de support connue : la migration se planifie.'],
['Suivre les avis CERT-FR', 'Veille automatisée.', 'curl -s https://www.cert.ssi.gouv.fr/avis/feed/ | grep -oE "<title>[^<]+" | head -3', '<title>CERT-FR – Avis\n<title>Multiples vulnérabilités dans …\n<title>Vulnérabilité dans …', 'Flux à intégrer dans un agrégateur.'],
['Chronologie d’un incident', 'Rédaction du compte rendu.', 'journalctl -u nginx --since "08:00" --until "09:00" | grep -E "start|stop|error" | head -3', '08:12:03 nginx[612]: [emerg] …\n08:12:03 systemd: nginx.service: Failed\n08:41:55 systemd: Started nginx.service', 'Les horodatages des journaux fournissent la chronologie factuelle.'],
['Statistiques du support', 'Bilan mensuel.', 'Requête GLPI : tickets par catégorie, septembre', 'Mot de passe oublié 142 · Vidéoprojecteur 37 · Accès ENT 29', 'Les mots de passe oubliés dominent : mettre en place la réinitialisation en libre-service.'],
['Rapport de bogue', 'Projet libre.', 'Title: Service fails to start after upgrade to 2.4.0 on Debian 12', 'Steps to reproduce · Expected · Actual · Logs', 'Un titre précis et des étapes reproductibles augmentent fortement les chances de réponse.']
],
termes: ['documentation', 'procédure', 'retour arrière', 'compte rendu', 'cause racine', 'post-mortem', 'veille', 'CERT-FR', 'flux RSS', 'support', 'ticket', 'qualification', 'priorité', 'escalade', 'base de connaissances', 'deprecated', 'workaround', 'rollback', 'outage', 'release notes', 'breaking change']
});
})();