_Site_web — Notes de cours interactives IMM1003 et IMM1033 (v2)
Générateur de sites statiques à partir des sources LaTeX des manuels (<cours>/<code>_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-<code>.js), jeux (association, vrai/faux, remise en ordre —courses.py → sequences), calculateurs (data/outils-<code>.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/<nn>/) : 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-<code>.json, outils-<code>.js, entrainement-<code>.js
├── videos/<code>/<nn>/ ← 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/<code>/ ← sites générés (ignorés par git)
└── stage/uqo-<code>/ ← dossiers d'app pour `mld stage`Construire et déployer
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
donePré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)
V=videos/imm1003/02 && mkdir -p $V # ou videos/imm1033/<nn> ; 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/<code> stage/uqo-<code>/dist ; cp server/server.mjs stage/uqo-<code>/ ; python3 stage/make_app_repos.py ;
# commit/push stage/uqo-<code> (médias gitignorés) ; mld stage stage/uqo-<code> uqo-<code> ; mld deploy uqo-<code> --node <nœud courant>Le build lie (hard link) le MP4 dans dist/<code>/videos/<nn>/, 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-<code>) : 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-<ch>-<sec>", "<nom>")danscourses.py → widgetset enregistrer<nom>viaWidgets.register(...)dansapp.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)}dansdata/entrainement-<code>.js. - Séquence (jeu de remise en ordre) : ajouter un triplet dans
courses.py → sequences. - Question de quiz :
data/quiz-<code>.json(q,c[choix],aindex,eexplication,url).