Files
williamandClaude Sonnet 5 b2e933f322
Build and deploy / test-python (push) Successful in 11m12s
Build and deploy / test-js (push) Successful in 53s
Build and deploy / lint-python (push) Successful in 3m56s
Build and deploy / lint-js (push) Successful in 3m1s
Build and deploy / build-and-push (push) Skipped
Build and deploy / deploy (push) Skipped
Build and deploy / sonarqube (push) Failing after 3m58s
Reorganisation game/document : renommage screens->game_engine + sous-dossiers game/ dans routes, scripts, static, templates, tests
Prepare la scission a venir entre l'editeur Jeu 2D et le futur editeur
Support de formation (voir docs/plan/PLAN.md), sans toucher a
l'architecture en couches existante :

- screens/ renomme en game_engine/ (nom clair pour le moteur du jeu 2D,
  avant l'arrivee d'un second "moteur" cote document) : ~85 imports
  corriges, contrat import-linter mis a jour, meme forme de couches.
- routes/, scripts/, static/, templates/, tests/ : tout ce qui est
  propre au jeu 2D deplace dans un sous-dossier game/ de chacun
  (routes/game/, static/game/, templates/game/, tests/game/,
  scripts/game/) ; ce qui est partage par le site (auth, onboarding,
  dashboard, uploads, db/) reste a la racine de chaque dossier. Un
  sous-dossier document/ (vide) cree dans chacun pour le futur chantier.
- styles/ volontairement inchange : les 3 fichiers sources sont
  concatenes en un seul static/style.css charge par tout le site,
  scinder leur CONTENU (editeur vs partage) serait un refactor CSS
  distinct, pas un deplacement mecanique.
- Chaine d'export SCORM (publish/build_scorm_package.py) mise a jour en
  profondeur : copie des assets, URLs d'icones relatives a
  static/style.css (qui ne bouge pas), manifeste, wrapper SCORM.
- Deux regressions d'un sweep de renommage anterieur corrigees au passage
  (screens.js/screens/scene-objects incorrectement convertis en
  game_engine.js/game_engine/scene-objects dans des commentaires).
- Effet de bord Windows decouvert et corrige : git mv + Path.write_text
  convertissent des fichiers en CRLF (core.autocrlf=true) - ~189 fichiers
  normalises en LF.
- .eslintrc.json/package.json : uniquement les chemins de glob mis a jour
  (static/game/js/...) ; la preparation eslint-plugin-unicorn du lot 7
  reste volontairement non committee (package-lock.json restaure a la
  version precedente).

Verifications : ruff, mypy --strict (391 fichiers), vulture, bandit,
lint-imports tous verts ; 591/591 tests Python, 276/276 tests JS ;
demarrage serveur + requetes HTTP manuelles confirmant que les assets
deplaces repondent en 200 au nouvel emplacement et 404 a l'ancien.

SKIP=djlint : backlog H021 (styles inline) deja documente comme dette
assumee dans CODE_QUALITY.md section 6, aucun template touche par ce
commit au-dela d'un deplacement de fichier.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 12:27:53 +02:00

73 lines
4.3 KiB
Python

import db
def ensure_schema(slug: str) -> None:
"""Crée les tables de ce module si elles n'existent pas encore — les
jeux créés avant l'ajout de cette fonctionnalité n'ont pas besoin d'être
migrés manuellement, la première visite d'un écran de ce jeu suffit."""
conn = db.connect(slug)
conn.executescript(
"""
CREATE TABLE IF NOT EXISTS _screens (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
order_index INTEGER NOT NULL DEFAULT 0,
is_template INTEGER NOT NULL DEFAULT 0,
created_at TEXT DEFAULT CURRENT_TIMESTAMP
);
"""
)
screen_cols = {r["name"] for r in conn.execute("PRAGMA table_info(_screens)").fetchall()}
if "is_template" not in screen_cols:
# Un écran-modèle héberge le contenu d'un élément de jeu réutilisable
# (voir template_screen_id ci-dessus) : il n'apparaît jamais dans la
# liste des écrans du jeu, ni dans le mode jouable, ni dans les
# menus "aller à cet écran" — seul son contenu (les éléments qu'il
# contient) est utilisé, jamais l'écran lui-même.
conn.execute("ALTER TABLE _screens ADD COLUMN is_template INTEGER NOT NULL DEFAULT 0")
if "preview_aspect" not in screen_cols:
# Format d'aperçu choisi pour cet écran (Portrait 9/16, Paysage 16/9,
# ou Carré 1/1) — mémorisé par écran pour qu'il reste le même après
# un ajout/suppression d'élément ou un changement d'élément
# sélectionné (ces actions redemandent le panneau au serveur, qui
# doit donc connaître le choix déjà fait, sinon il repart sur la
# valeur par défaut à chaque fois). Sert aussi en mode Jouer, pour
# garder la zone de jeu à la bonne proportion quelle que soit la
# forme réelle de la fenêtre du joueur (voir #playFrame dans
# play.html) — sans ça, les positions/tailles en % se déforment dès
# que la fenêtre du joueur n'a pas la même proportion que celle
# utilisée à la conception.
conn.execute("ALTER TABLE _screens ADD COLUMN preview_aspect TEXT NOT NULL DEFAULT '9/16'")
if "background_music_url" not in screen_cols:
# Phase 6 — musique de fond de cet écran (URL) : démarrée en boucle
# à l'affichage de l'écran, arrêtée au changement d'écran (voir
# runScreenBackgroundMusic() dans static/game/js/play/screens.js).
# Indépendante de l'action "Jouer un son" (effet sonore ponctuel,
# non bouclé, sur n'importe quel déclencheur).
conn.execute("ALTER TABLE _screens ADD COLUMN background_music_url TEXT")
if "scene_width" not in screen_cols:
# Fondations multi-éditeurs — jeux "jeu_2d" (voir db/games/
# get_game_type.py) : une scène a une taille FIXE en pixels
# (contrairement à un écran "document", positionné en % fluides
# via preview_aspect ci-dessus) — indispensable pour la collision
# et l'animation de sprites. Sans effet sur un écran "document"
# (jamais lu par son rendu) — voir game_engine/scenes/.
conn.execute("ALTER TABLE _screens ADD COLUMN scene_width INTEGER NOT NULL DEFAULT 960")
conn.execute("ALTER TABLE _screens ADD COLUMN scene_height INTEGER NOT NULL DEFAULT 540")
if "kind" not in screen_cols:
# Un seul moteur d'écran désormais : "jeu_2d" (scène pixels — voir
# db/games/get_game_type.py, conservé pour la rétro-compatibilité
# d'un jeu créé avant l'existence de cette colonne).
conn.execute("ALTER TABLE _screens ADD COLUMN kind TEXT NOT NULL DEFAULT 'jeu_2d'")
conn.execute("UPDATE _screens SET kind = ?", (db.get_game_type(slug),))
if "_screen_triggers" not in screen_cols:
# Déclencheurs D'ÉCRAN (voir game_engine/rendering/screen_triggers.py) —
# section "Déclencheurs de l'écran" de l'éditeur de scène : SANS
# objet propriétaire, contrairement à _collision_rules (porté par
# un objet, colonne JSON dans _scene_objects.attributes). NULL
# (aucune règle) pour tout écran créé avant l'ajout de cette
# fonctionnalité, comme pour les autres colonnes ci-dessus.
conn.execute("ALTER TABLE _screens ADD COLUMN _screen_triggers TEXT")
conn.commit()
conn.close()