spb/uqo-imm1003
Public
JavaScript 68%
CSS 32%
1# _Site_web — Notes de cours interactives IMM1003 et IMM1033 (v2)23Générateur de sites statiques à partir des sources LaTeX des manuels (`<cours>/<code>_Notes_de_cours/sources/`)4et du rapport `Rapport_Immobilier_Quebec/`. Deux sites publics servis par le cluster MacLustr via `mld` + ngrok :56| Site | Domaine | App mld | Port |7|---|---|---|---|8| IMM1003 — Éléments d’évaluation immobilière | https://www.uqo-imm1003.app | `uqo-imm1003` | 8160 |9| IMM1033 — Méthodes du coût | https://www.uqo-imm1033.app | `uqo-imm1033` | 8161 |1011## Ce que contient chaque site1213- **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é.14- **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.15- **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).16- **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.17- **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.18- **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.1920**Non publiés** : solutionnaires, questionnaires d’examen, grilles de correction.2122## Arborescence2324```25_Site_web/26├── build/27│ ├── build.py ← orchestrateur : python3 build/build.py [imm1003] [imm1033]28│ ├── latex2html.py ← convertisseur LaTeX → HTML (dialecte uqo-notes.sty + article du rapport)29│ ├── videos.py ← séances vidéo : nettoyage whisper, cues VTT/SRT, paragraphes, chapitres, storyboard (ffmpeg + Pillow), cache/video-frames/30│ ├── rapport.py ← rapport : découpage en sections, tableaux \input, valeurs clés, figures PDF→SVG, extraction HPI (xlsx) et FRED (json)31│ ├── tikz.py ← tikzpicture → SVG (pdflatex standalone + pdftocairo), cache/tikz/32│ ├── render_math.mjs ← KaTeX en lot (node)33│ ├── bib.py ← references.bib → auteur-année34│ ├── brand.py ← logo UQO, favicons, apple-touch-icon, image OG (Pillow + Fira Sans de TeX Live)35│ ├── templates.py ← gabarits HTML (accueil, séance, carte, rapport, jeux, entraînement, progression…)36│ ├── courses.py ← métadonnées : parties et couleurs, calendrier, évaluations, TP publiés, widgets, séquences37│ └── test_convert.py ← test de conversion complet38├── assets/css/site.css ← feuille de style v2 (Fraunces / Source Serif 4 / Fira Sans, couleur par partie, mobile)39├── assets/js/app.js ← application cliente : recherche, quiz, fiches, widgets SVG, entraînement, jeux, progression, notes, TTS, explorateurs HPI/FRED40├── assets/brand/ ← logo UQO source (Wikimedia + sources LaTeX)41├── data/ ← quiz-<code>.json, outils-<code>.js, entrainement-<code>.js42├── videos/<code>/<nn>/ ← séance vidéo : video.mp4 + audio.m4a (gitignorés), transcript.json (whisper), meta.json (chapitres, résumé…), chat.txt, scenes.txt43├── server/server.mjs ← serveur statique Node zéro dépendance44├── cache/ ← tikz/ et rapport-fig/ (SVG rendus)45├── dist/<code>/ ← sites générés (ignorés par git)46└── stage/uqo-<code>/ ← dossiers d'app pour `mld stage`47```4849## Construire et déployer5051```bash52cd _Site_web && npm install # KaTeX (une fois)53python3 build/build.py # ≈ 1 s par cours avec les caches54node server/server.mjs 8160 dist/imm1003 # test local55for c in imm1003 imm1033; do56 rm -rf stage/uqo-$c/dist && cp -R dist/$c stage/uqo-$c/dist57 ~/Desktop/cluster-skill/mld stage stage/uqo-$c uqo-$c && ~/Desktop/cluster-skill/mld deploy uqo-$c58done59```6061Pré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.62Manifestes mld : `M1M32:~/dispatch/apps/uqo-imm1003.json`, `uqo-imm1033.json`. Emplacement courant : `mld status`.6364## Ajouter une séance vidéo (enregistrement Zoom)6566```bash67V=videos/imm1003/02 && mkdir -p $V # ou videos/imm1033/<nn> ; même recette pour les deux cours68ffmpeg -i ~/Desktop/seanceN/video*.mp4 -c copy -movflags +faststart $V/video.mp4 # remux pour la lecture progressive69cp ~/Desktop/seanceN/audio*.m4a $V/audio.m4a ; cp ~/Desktop/seanceN/chat.txt $V/ # chat optionnel70~/.venvs/whisper/bin/mlx_whisper $V/audio.m4a --model mlx-community/whisper-large-v3-turbo --language fr \71 --output-dir /tmp/tr --output-name s --output-format json --word-timestamps True --condition-on-previous-text False72cp /tmp/tr/s.json $V/transcript.json73ffmpeg -i $V/video.mp4 -vf "scale=432:-2,select='gt(scene,0.12)',showinfo" -vsync vfr -f null - 2>&1 \74 | grep -o "pts_time:[0-9.]*" | sed 's/pts_time://' > $V/scenes.txt # changements de diapositive75# puis rédiger $V/meta.json (date_text, start_t, chapters[{t,title,desc,link,kind}], summary, keypoints, questions, related)76python3 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 ;77 # commit/push stage/uqo-<code> (médias gitignorés) ; mld stage stage/uqo-<code> uqo-<code> ; mld deploy uqo-<code> --node <nœud courant>78```7980Le 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.8182## Ajouter du contenu interactif8384- **Widget dans une séance** : ajouter `("s-<ch>-<sec>", "<nom>")` dans `courses.py → widgets` et enregistrer `<nom>` via `Widgets.register(...)` dans `app.js` (le widget est inséré à la fin de la première sous-section).85- **Problème d’entraînement** : ajouter un objet `{id, title, ch, url, gen(R)}` dans `data/entrainement-<code>.js`.86- **Séquence (jeu de remise en ordre)** : ajouter un triplet dans `courses.py → sequences`.87- **Question de quiz** : `data/quiz-<code>.json` (`q`, `c` [choix], `a` index, `e` explication, `url`).88