# _Site_web — Notes de cours interactives IMM1003 et IMM1033 (v2) Générateur de sites statiques à partir des sources LaTeX des manuels (`/_Notes_de_cours/sources/`) et du rapport `Rapport_Immobilier_Quebec/`. Deux sites publics servis par le cluster MacLustr via `mld` + ngrok : | Site | Domaine | App mld | Port | |---|---|---|---| | IMM1003 — Éléments d’évaluation immobilière | https://www.uqo-imm1003.app | `uqo-imm1003` | 8160 | | IMM1033 — Méthodes du coût | https://www.uqo-imm1033.app | `uqo-imm1033` | 8161 | ## Ce que contient chaque site - **Séances 1 à 14** : notes intégrales (boîtes pédagogiques, notes marginales Tufte, KaTeX, TikZ→SVG), stepper de sections, sommaire avec sections lues, objectifs cochables, mode révision, **explorateurs interactifs** insérés dans les séances (9 par cours, `courses.py → widgets`), **surlignage + notes personnelles** (export Markdown), **lecture audio** (synthèse vocale), quiz intégré. - **Réviser** : aide-mémoire, glossaire (infobulles dans le texte), toutes les définitions, fiches recto-verso, **carte du cours** (SVG radial, objectifs par séance), banque d’exercices. - **S’exercer** : quiz + examen blanc, **entraînement** (problèmes à données aléatoires, `data/entrainement-.js`), **jeux** (association, vrai/faux, remise en ordre — `courses.py → sequences`), calculateurs (`data/outils-.js`), **tableau de bord de progression** (export/import JSON). - **Ressources** : diapositives, téléchargements, **rapport « Le marché de l’habitation au Québec »** (21 sections, 67 figures SVG, 28 tableaux, métriques clés, **explorateurs HPI ACI et FRED** avec données `data/hpi.json`, `data/fred.json`), bibliographie fusionnée, recherche plein texte. - **Séances vidéo** (`/videos/`, `/videos//`) : enregistrements Zoom avec chapitres cliquables, ligne du temps, transcription synchronisée et cherchable (clic = aller dans la vidéo), sous-titres WebVTT, storyboard des changements d’écran, résumé + « à retenir » + questions posées, clavardage, téléchargements (MP4, M4A, VTT, SRT, TXT), reprise de lecture, vitesse, mode audio seulement, lien horodaté `?t=`. Bouton « Enregistrement de la séance » sur la page de séance correspondante ; chapitres indexés dans la recherche. - **Identité UQO** : logo officiel (barre, héros, pied de page), favicons/icônes tactiles générés (`build/brand.py`), image de partage Open Graph 1200×630 par cours (`/assets/og.png`), thème clair par défaut + thème sombre. **Non publiés** : solutionnaires, questionnaires d’examen, grilles de correction. ## Arborescence ``` _Site_web/ ├── build/ │ ├── build.py ← orchestrateur : python3 build/build.py [imm1003] [imm1033] │ ├── latex2html.py ← convertisseur LaTeX → HTML (dialecte uqo-notes.sty + article du rapport) │ ├── videos.py ← séances vidéo : nettoyage whisper, cues VTT/SRT, paragraphes, chapitres, storyboard (ffmpeg + Pillow), cache/video-frames/ │ ├── rapport.py ← rapport : découpage en sections, tableaux \input, valeurs clés, figures PDF→SVG, extraction HPI (xlsx) et FRED (json) │ ├── tikz.py ← tikzpicture → SVG (pdflatex standalone + pdftocairo), cache/tikz/ │ ├── render_math.mjs ← KaTeX en lot (node) │ ├── bib.py ← references.bib → auteur-année │ ├── brand.py ← logo UQO, favicons, apple-touch-icon, image OG (Pillow + Fira Sans de TeX Live) │ ├── templates.py ← gabarits HTML (accueil, séance, carte, rapport, jeux, entraînement, progression…) │ ├── courses.py ← métadonnées : parties et couleurs, calendrier, évaluations, TP publiés, widgets, séquences │ └── test_convert.py ← test de conversion complet ├── assets/css/site.css ← feuille de style v2 (Fraunces / Source Serif 4 / Fira Sans, couleur par partie, mobile) ├── assets/js/app.js ← application cliente : recherche, quiz, fiches, widgets SVG, entraînement, jeux, progression, notes, TTS, explorateurs HPI/FRED ├── assets/brand/ ← logo UQO source (Wikimedia + sources LaTeX) ├── data/ ← quiz-.json, outils-.js, entrainement-.js ├── videos/// ← séance vidéo : video.mp4 + audio.m4a (gitignorés), transcript.json (whisper), meta.json (chapitres, résumé…), chat.txt, scenes.txt ├── server/server.mjs ← serveur statique Node zéro dépendance ├── cache/ ← tikz/ et rapport-fig/ (SVG rendus) ├── dist// ← sites générés (ignorés par git) └── stage/uqo-/ ← dossiers d'app pour `mld stage` ``` ## Construire et déployer ```bash cd _Site_web && npm install # KaTeX (une fois) python3 build/build.py # ≈ 1 s par cours avec les caches node server/server.mjs 8160 dist/imm1003 # test local for c in imm1003 imm1033; do rm -rf stage/uqo-$c/dist && cp -R dist/$c stage/uqo-$c/dist ~/Desktop/cluster-skill/mld stage stage/uqo-$c uqo-$c && ~/Desktop/cluster-skill/mld deploy uqo-$c done ``` Prérequis : Python ≥ 3.12 (+ Pillow, openpyxl), Node ≥ 20, TeX Live (pdflatex, FiraSans, fontawesome5, pgfplots), poppler (`pdftocairo`, `pdfinfo`), ffmpeg/ffprobe (séances vidéo), venv `~/.venvs/whisper` (mlx-whisper) pour transcrire. Manifestes mld : `M1M32:~/dispatch/apps/uqo-imm1003.json`, `uqo-imm1033.json`. Emplacement courant : `mld status`. ## Ajouter une séance vidéo (enregistrement Zoom) ```bash V=videos/imm1003/02 && mkdir -p $V # ou videos/imm1033/ ; même recette pour les deux cours ffmpeg -i ~/Desktop/seanceN/video*.mp4 -c copy -movflags +faststart $V/video.mp4 # remux pour la lecture progressive cp ~/Desktop/seanceN/audio*.m4a $V/audio.m4a ; cp ~/Desktop/seanceN/chat.txt $V/ # chat optionnel ~/.venvs/whisper/bin/mlx_whisper $V/audio.m4a --model mlx-community/whisper-large-v3-turbo --language fr \ --output-dir /tmp/tr --output-name s --output-format json --word-timestamps True --condition-on-previous-text False cp /tmp/tr/s.json $V/transcript.json ffmpeg -i $V/video.mp4 -vf "scale=432:-2,select='gt(scene,0.12)',showinfo" -vsync vfr -f null - 2>&1 \ | grep -o "pts_time:[0-9.]*" | sed 's/pts_time://' > $V/scenes.txt # changements de diapositive # puis rédiger $V/meta.json (date_text, start_t, chapters[{t,title,desc,link,kind}], summary, keypoints, questions, related) python3 build/build.py imm1003 # puis : cp -R dist/ stage/uqo-/dist ; cp server/server.mjs stage/uqo-/ ; python3 stage/make_app_repos.py ; # commit/push stage/uqo- (médias gitignorés) ; mld stage stage/uqo- uqo- ; mld deploy uqo- --node ``` Le build lie (hard link) le MP4 dans `dist//videos//`, génère `captions.vtt`, `chapters.vtt`, `transcript.{json,srt,txt}`, `poster.webp`, `sb/*.webp` et la page. Les médias ne sont pas versionnés (ni dans UQO_COURS ni dans `stage/uqo-`) : ils voyagent par `mld stage` (rsync). Le serveur sert les plages HTTP (`Range`) pour la lecture progressive. ## Ajouter du contenu interactif - **Widget dans une séance** : ajouter `("s--", "")` dans `courses.py → widgets` et enregistrer `` via `Widgets.register(...)` dans `app.js` (le widget est inséré à la fin de la première sous-section). - **Problème d’entraînement** : ajouter un objet `{id, title, ch, url, gen(R)}` dans `data/entrainement-.js`. - **Séquence (jeu de remise en ordre)** : ajouter un triplet dans `courses.py → sequences`. - **Question de quiz** : `data/quiz-.json` (`q`, `c` [choix], `a` index, `e` explication, `url`).