From a1f749de40f2e0e92ecc263cc0215031ab007219 Mon Sep 17 00:00:00 2001 From: Denis Defolie Date: Sun, 11 Oct 2026 16:15:19 +0200 Subject: [PATCH] Add project skeleton: Godot setup, tooling, and smoke test Pins Godot 4.6.3-stable and GUT 9.6.0 (9.6.1+ reference AccessibilityServer, unavailable in 4.6.3) via tools/setup.sh. Wires make check (gdlint + gdformat config for 4-space indent, headless GUT run, and a JSON well-formedness check ahead of real schema validation). Seven autoload stubs match the architecture in the cahier des charges; real logic lands with the following steps. Co-Authored-By: Claude Sonnet 5 --- .editorconfig | 16 +++++++++ .gitattributes | 30 ++++++++++++++++ .gitignore | 26 ++++++++++++++ .godot-version | 1 + Makefile | 35 ++++++++++++++++++ README-EN.md | 44 +++++++++++++++++++++++ README.md | 44 +++++++++++++++++++++++ assets/CREDITS.md | 9 +++++ assets/animations/.gitkeep | 0 assets/audio/.gitkeep | 0 assets/characters/.gitkeep | 0 assets/environments/.gitkeep | 0 assets/fonts/.gitkeep | 0 assets/interface/.gitkeep | 0 autoload/audio_manager.gd | 3 ++ autoload/audio_manager.gd.uid | 1 + autoload/exercise_engine.gd | 3 ++ autoload/exercise_engine.gd.uid | 1 + autoload/game_manager.gd | 3 ++ autoload/game_manager.gd.uid | 1 + autoload/profile_manager.gd | 3 ++ autoload/profile_manager.gd.uid | 1 + autoload/progress_manager.gd | 3 ++ autoload/progress_manager.gd.uid | 1 + autoload/save_manager.gd | 4 +++ autoload/save_manager.gd.uid | 1 + autoload/settings_manager.gd | 3 ++ autoload/settings_manager.gd.uid | 1 + data/curriculum/.gitkeep | 0 data/dictations/.gitkeep | 0 data/exercises/ce1/.gitkeep | 0 data/exercises/ce2/.gitkeep | 0 data/localization/.gitkeep | 0 data/rules/.gitkeep | 0 data/schemas/.gitkeep | 0 docs/review/.gitkeep | 0 docs/testing/.gitkeep | 0 gdformatrc | 5 +++ gdlintrc | 47 ++++++++++++++++++++++++ icon.svg | 4 +++ icon.svg.import | 43 ++++++++++++++++++++++ project.godot | 26 ++++++++++++++ scenes/boot/boot.tscn | 3 ++ scripts/data/validate_data_cli.gd | 46 ++++++++++++++++++++++++ scripts/data/validate_data_cli.gd.uid | 1 + tests/test_bootstrap.gd | 14 ++++++++ tests/test_bootstrap.gd.uid | 1 + tools/setup.sh | 51 +++++++++++++++++++++++++++ 48 files changed, 475 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .godot-version create mode 100644 Makefile create mode 100644 README-EN.md create mode 100644 README.md create mode 100644 assets/CREDITS.md create mode 100644 assets/animations/.gitkeep create mode 100644 assets/audio/.gitkeep create mode 100644 assets/characters/.gitkeep create mode 100644 assets/environments/.gitkeep create mode 100644 assets/fonts/.gitkeep create mode 100644 assets/interface/.gitkeep create mode 100644 autoload/audio_manager.gd create mode 100644 autoload/audio_manager.gd.uid create mode 100644 autoload/exercise_engine.gd create mode 100644 autoload/exercise_engine.gd.uid create mode 100644 autoload/game_manager.gd create mode 100644 autoload/game_manager.gd.uid create mode 100644 autoload/profile_manager.gd create mode 100644 autoload/profile_manager.gd.uid create mode 100644 autoload/progress_manager.gd create mode 100644 autoload/progress_manager.gd.uid create mode 100644 autoload/save_manager.gd create mode 100644 autoload/save_manager.gd.uid create mode 100644 autoload/settings_manager.gd create mode 100644 autoload/settings_manager.gd.uid create mode 100644 data/curriculum/.gitkeep create mode 100644 data/dictations/.gitkeep create mode 100644 data/exercises/ce1/.gitkeep create mode 100644 data/exercises/ce2/.gitkeep create mode 100644 data/localization/.gitkeep create mode 100644 data/rules/.gitkeep create mode 100644 data/schemas/.gitkeep create mode 100644 docs/review/.gitkeep create mode 100644 docs/testing/.gitkeep create mode 100644 gdformatrc create mode 100644 gdlintrc create mode 100644 icon.svg create mode 100644 icon.svg.import create mode 100644 project.godot create mode 100644 scenes/boot/boot.tscn create mode 100644 scripts/data/validate_data_cli.gd create mode 100644 scripts/data/validate_data_cli.gd.uid create mode 100644 tests/test_bootstrap.gd create mode 100644 tests/test_bootstrap.gd.uid create mode 100755 tools/setup.sh diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..db901b1 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,16 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 4 + +[*.{gd,py,json,md,cfg,yml,yaml,sh}] +indent_style = space +indent_size = 4 + +[Makefile] +indent_style = tab diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..750d847 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,30 @@ +# Texte : fins de ligne normalisees en LF +* text=auto eol=lf + +*.gd text eol=lf +*.gdshader text eol=lf +*.tscn text eol=lf +*.tres text eol=lf +*.cfg text eol=lf +*.json text eol=lf +*.md text eol=lf +*.cs text eol=lf +*.py text eol=lf +*.sh text eol=lf +Makefile text eol=lf + +# Assets : binaires, jamais de conversion de fin de ligne +*.png binary +*.jpg binary +*.jpeg binary +*.webp binary +*.ogg binary +*.wav binary +*.mp3 binary +*.ttf binary +*.otf binary +*.woff binary +*.woff2 binary +*.zip binary +*.ico binary +*.svg binary diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dd36eaa --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# Runtime et artefacts Godot +.godot/ +build/ + +# Outillage telecharge par `make setup` (Godot, GUT), non versionne +.godot-bin/ +addons/gut/ +.venv/ + +# Python +__pycache__/ +*.pyc + +# Secrets et identifiants (export, env, mots de passe, cles) +.env +*.env +*.keystore +*.jks +*.p12 +*.mobileprovision +secrets.* +export_credentials.cfg + +# Fichiers d'edition courants +*.swp +.DS_Store diff --git a/.godot-version b/.godot-version new file mode 100644 index 0000000..6abea06 --- /dev/null +++ b/.godot-version @@ -0,0 +1 @@ +4.6.3-stable diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fd1fa9d --- /dev/null +++ b/Makefile @@ -0,0 +1,35 @@ +GODOT_BIN := .godot-bin/godot +VENV := .venv +GDLINT := $(VENV)/bin/gdlint +GDFORMAT := $(VENV)/bin/gdformat +GD_SOURCES := autoload scripts tests + +.PHONY: setup run lint format validate-data test check export-linux export-windows + +setup: + tools/setup.sh + +run: + $(GODOT_BIN) --path . + +lint: + $(GDLINT) $(GD_SOURCES) + +format: + $(GDFORMAT) $(GD_SOURCES) + +validate-data: + $(GODOT_BIN) --headless --path . -s res://scripts/data/validate_data_cli.gd + +test: + $(GODOT_BIN) --headless --path . -s res://addons/gut/gut_cmdln.gd -gdir=res://tests -gexit + +check: lint validate-data test + +export-linux: + @echo "Export Linux : pas encore configure (voir Ordre de construction, etape 6)." + @exit 1 + +export-windows: + @echo "Export Windows : pas encore configure (voir Ordre de construction, etape 6)." + @exit 1 diff --git a/README-EN.md b/README-EN.md new file mode 100644 index 0000000..0daf8f1 --- /dev/null +++ b/README-EN.md @@ -0,0 +1,44 @@ +# Les Aventuriers des mots (The Word Adventurers) + +An educational French-language game for 7-9 year olds (French grades CE1-CE2): an offline 2D adventure with an explorable map, a guide character, and grammar, spelling, and dictation exercises. + +Open source project, in development. Current status: technical skeleton (see `docs/specs/decisions.md` for scoping decisions and `docs/specs/cahier-des-charges.md` for the full specification, both in French — this is a French-curriculum product). + +## Tech stack + +- Godot 4.6 (typed GDScript) +- Exercises and pedagogical content as JSON data, validated on load +- Headless tests (GUT), GDScript lint/format (gdtoolkit) + +## Getting started + +```sh +make setup # installs Godot (pinned), GUT and gdtoolkit locally, nothing is committed +make run # runs the game +``` + +## Commands + +| Command | Effect | +|---|---| +| `make setup` | installs tooling (lint, tests, export templates) | +| `make run` | runs the game | +| `make lint` / `make format` | GDScript static analysis and formatting | +| `make validate-data` | validates the JSON files in `data/` | +| `make test` | headless tests | +| `make check` | lint + validate-data + test, must pass before every commit | +| `make export-linux` / `make export-windows` | exports into `build/` (from the export step onward) | + +## Structure + +- `autoload/`: global modules (game lifecycle, profiles, progress, exercises, saves, audio, settings) +- `scenes/`: self-contained Godot scenes communicating via signals +- `scripts/`: pure logic (correction, pedagogy) and data loading +- `data/`: pedagogical content as JSON, validated against schemas +- `assets/`: graphics and audio (placeholder at this stage, see `assets/CREDITS.md`) +- `tests/`: headless tests (GUT) +- `docs/specs/`: specification and scoping decisions (French) + +## License + +Code and content under the [GNU Affero General Public License v3](LICENSE). diff --git a/README.md b/README.md new file mode 100644 index 0000000..f0b6792 --- /dev/null +++ b/README.md @@ -0,0 +1,44 @@ +# Les Aventuriers des mots + +Jeu éducatif de français pour les CE1-CE2 (7-9 ans) : une aventure 2D hors ligne, avec une carte à explorer, un personnage guide, et des exercices de grammaire, d'orthographe et de dictées. + +Projet open source, en développement. Statut actuel : squelette technique (voir `docs/specs/decisions.md` pour les décisions de cadrage et `docs/specs/cahier-des-charges.md` pour la spécification complète). + +## Pile technique + +- Godot 4.6 (GDScript typé) +- Exercices et contenu pédagogique en données JSON, validées au chargement +- Tests headless (GUT), lint/format GDScript (gdtoolkit) + +## Démarrer + +```sh +make setup # installe Godot (pinné), GUT et gdtoolkit en local, rien n'est commité +make run # lance le jeu +``` + +## Commandes + +| Commande | Effet | +|---|---| +| `make setup` | installe l'outillage (lint, tests, modèles d'export) | +| `make run` | lance le jeu | +| `make lint` / `make format` | analyse statique et formatage GDScript | +| `make validate-data` | valide les JSON de `data/` | +| `make test` | tests headless | +| `make check` | lint + validate-data + test, à passer avant chaque commit | +| `make export-linux` / `make export-windows` | exports dans `build/` (à partir de l'étape export) | + +## Structure + +- `autoload/` : modules globaux (gestion du jeu, profils, progression, exercices, sauvegardes, audio, réglages) +- `scenes/` : scènes Godot, autonomes et communiquant par signaux +- `scripts/` : logique pure (correction, pédagogie) et chargement des données +- `data/` : contenu pédagogique en JSON, validé contre des schémas +- `assets/` : graphismes et audio (provisoires à ce stade, voir `assets/CREDITS.md`) +- `tests/` : tests headless (GUT) +- `docs/specs/` : cahier des charges et décisions de cadrage + +## Licence + +Code et contenu sous [GNU Affero General Public License v3](LICENSE). diff --git a/assets/CREDITS.md b/assets/CREDITS.md new file mode 100644 index 0000000..3f58ce8 --- /dev/null +++ b/assets/CREDITS.md @@ -0,0 +1,9 @@ +# Sources des assets provisoires + +Tous les graphismes et sons actuels sont provisoires, crees pour ce projet, sans asset tiers. + +| Fichier | Origine | Licence | +|---|---|---| +| `icon.svg` | Forme geometrique simple, creee pour ce projet | AGPL-3.0 (code et assets du depot) | + +Les voix de dictee provisoires (a venir) seront generees par synthese vocale hors ligne et listees ici au fur et a mesure, avec la mention `review_status: draft` correspondante dans les donnees. diff --git a/assets/animations/.gitkeep b/assets/animations/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/assets/audio/.gitkeep b/assets/audio/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/assets/characters/.gitkeep b/assets/characters/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/assets/environments/.gitkeep b/assets/environments/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/assets/fonts/.gitkeep b/assets/fonts/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/assets/interface/.gitkeep b/assets/interface/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/autoload/audio_manager.gd b/autoload/audio_manager.gd new file mode 100644 index 0000000..524aaa4 --- /dev/null +++ b/autoload/audio_manager.gd @@ -0,0 +1,3 @@ +extends Node +## Lecture des voix, dictees, musiques et effets sonores, y compris l'audio provisoire des dictees. +## Logique detaillee a partir de l'etape "Scenes" (voir Ordre de construction). diff --git a/autoload/audio_manager.gd.uid b/autoload/audio_manager.gd.uid new file mode 100644 index 0000000..90d787b --- /dev/null +++ b/autoload/audio_manager.gd.uid @@ -0,0 +1 @@ +uid://542icpqhkik3 diff --git a/autoload/exercise_engine.gd b/autoload/exercise_engine.gd new file mode 100644 index 0000000..87f35b2 --- /dev/null +++ b/autoload/exercise_engine.gd @@ -0,0 +1,3 @@ +extends Node +## Chargement et deroulement des exercices a partir des donnees JSON validees. +## Logique detaillee a partir de l'etape "Donnees" (voir Ordre de construction). diff --git a/autoload/exercise_engine.gd.uid b/autoload/exercise_engine.gd.uid new file mode 100644 index 0000000..3f3ef6b --- /dev/null +++ b/autoload/exercise_engine.gd.uid @@ -0,0 +1 @@ +uid://dvni3nligy7lx diff --git a/autoload/game_manager.gd b/autoload/game_manager.gd new file mode 100644 index 0000000..6d44d82 --- /dev/null +++ b/autoload/game_manager.gd @@ -0,0 +1,3 @@ +extends Node +## Cycle de vie de l'application, navigation entre scenes et etat general du jeu. +## Logique detaillee a partir de l'etape "Scenes" (voir Ordre de construction). diff --git a/autoload/game_manager.gd.uid b/autoload/game_manager.gd.uid new file mode 100644 index 0000000..d5fd26a --- /dev/null +++ b/autoload/game_manager.gd.uid @@ -0,0 +1 @@ +uid://cw6hsqn7d08bu diff --git a/autoload/profile_manager.gd b/autoload/profile_manager.gd new file mode 100644 index 0000000..47d55d4 --- /dev/null +++ b/autoload/profile_manager.gd @@ -0,0 +1,3 @@ +extends Node +## Creation, selection et suppression des profils enfants. +## Logique detaillee a partir de l'etape "Profils et sauvegardes". diff --git a/autoload/profile_manager.gd.uid b/autoload/profile_manager.gd.uid new file mode 100644 index 0000000..724b8ce --- /dev/null +++ b/autoload/profile_manager.gd.uid @@ -0,0 +1 @@ +uid://dl471qrur3sxh diff --git a/autoload/progress_manager.gd b/autoload/progress_manager.gd new file mode 100644 index 0000000..0c9463f --- /dev/null +++ b/autoload/progress_manager.gd @@ -0,0 +1,3 @@ +extends Node +## Competences, missions debloquees et planification des revisions par profil. +## Logique detaillee a partir de l'etape "Logique pure" (voir docs/specs/decisions.md, point 5). diff --git a/autoload/progress_manager.gd.uid b/autoload/progress_manager.gd.uid new file mode 100644 index 0000000..6688040 --- /dev/null +++ b/autoload/progress_manager.gd.uid @@ -0,0 +1 @@ +uid://ei0m2liq1j86 diff --git a/autoload/save_manager.gd b/autoload/save_manager.gd new file mode 100644 index 0000000..c3c3626 --- /dev/null +++ b/autoload/save_manager.gd @@ -0,0 +1,4 @@ +extends Node +## Serialisation des sauvegardes par profil dans user:// (ecriture atomique, +## copie de secours, migration). +## Logique detaillee a partir de l'etape "Profils et sauvegardes". diff --git a/autoload/save_manager.gd.uid b/autoload/save_manager.gd.uid new file mode 100644 index 0000000..e346f1f --- /dev/null +++ b/autoload/save_manager.gd.uid @@ -0,0 +1 @@ +uid://ce07tiyi8ad46 diff --git a/autoload/settings_manager.gd b/autoload/settings_manager.gd new file mode 100644 index 0000000..4182563 --- /dev/null +++ b/autoload/settings_manager.gd @@ -0,0 +1,3 @@ +extends Node +## Volume, taille du texte et autres preferences de l'enfant ou de l'adulte. +## Logique detaillee a partir de l'etape "Scenes" (voir Ordre de construction). diff --git a/autoload/settings_manager.gd.uid b/autoload/settings_manager.gd.uid new file mode 100644 index 0000000..aadb5f7 --- /dev/null +++ b/autoload/settings_manager.gd.uid @@ -0,0 +1 @@ +uid://cdsn8dm6pbh6w diff --git a/data/curriculum/.gitkeep b/data/curriculum/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/data/dictations/.gitkeep b/data/dictations/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/data/exercises/ce1/.gitkeep b/data/exercises/ce1/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/data/exercises/ce2/.gitkeep b/data/exercises/ce2/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/data/localization/.gitkeep b/data/localization/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/data/rules/.gitkeep b/data/rules/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/data/schemas/.gitkeep b/data/schemas/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docs/review/.gitkeep b/docs/review/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docs/testing/.gitkeep b/docs/testing/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/gdformatrc b/gdformatrc new file mode 100644 index 0000000..1ad1e50 --- /dev/null +++ b/gdformatrc @@ -0,0 +1,5 @@ +excluded_directories: !!set + .git: null +line_length: 100 +safety_checks: null +use_spaces: 4 diff --git a/gdlintrc b/gdlintrc new file mode 100644 index 0000000..eb2e165 --- /dev/null +++ b/gdlintrc @@ -0,0 +1,47 @@ +class-definitions-order: +- tools +- classnames +- extends +- docstrings +- signals +- enums +- consts +- staticvars +- exports +- pubvars +- prvvars +- onreadypubvars +- onreadyprvvars +- others +class-load-variable-name: (([A-Z][a-z0-9]*)+|_?[a-z][a-z0-9]*(_[a-z0-9]+)*) +class-name: ([A-Z][a-z0-9]*)+ +class-variable-name: _?[a-z][a-z0-9]*(_[a-z0-9]+)* +comparison-with-itself: null +constant-name: _?[A-Z][A-Z0-9]*(_[A-Z0-9]+)* +disable: [] +duplicated-load: null +enum-element-name: '[A-Z][A-Z0-9]*(_[A-Z0-9]+)*' +enum-name: ([A-Z][a-z0-9]*)+ +excluded_directories: !!set + .git: null +expression-not-assigned: null +function-argument-name: _?[a-z][a-z0-9]*(_[a-z0-9]+)* +function-arguments-number: 10 +function-name: (_on_([A-Z][a-z0-9]*)+(_[a-z0-9]+)*|_?[a-z][a-z0-9]*(_[a-z0-9]+)*) +function-preload-variable-name: ([A-Z][a-z0-9]*)+ +function-variable-name: '[a-z][a-z0-9]*(_[a-z0-9]+)*' +load-constant-name: (([A-Z][a-z0-9]*)+|_?[A-Z][A-Z0-9]*(_[A-Z0-9]+)*) +loop-variable-name: _?[a-z][a-z0-9]*(_[a-z0-9]+)* +max-file-lines: 1000 +max-line-length: 100 +max-public-methods: 20 +max-returns: 6 +mixed-tabs-and-spaces: null +no-elif-return: null +no-else-return: null +signal-name: '[a-z][a-z0-9]*(_[a-z0-9]+)*' +sub-class-name: _?([A-Z][a-z0-9]*)+ +tab-characters: 1 +trailing-whitespace: null +unnecessary-pass: null +unused-argument: null diff --git a/icon.svg b/icon.svg new file mode 100644 index 0000000..5d058b5 --- /dev/null +++ b/icon.svg @@ -0,0 +1,4 @@ + + + M + diff --git a/icon.svg.import b/icon.svg.import new file mode 100644 index 0000000..344e77f --- /dev/null +++ b/icon.svg.import @@ -0,0 +1,43 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://blboaodg2nrl7" +path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.svg" +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..f9cc2e0 --- /dev/null +++ b/project.godot @@ -0,0 +1,26 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="Les Aventuriers des mots" +run/main_scene="res://scenes/boot/boot.tscn" +config/features=PackedStringArray("4.6", "Forward Plus") +config/icon="res://icon.svg" + +[autoload] + +GameManager="*res://autoload/game_manager.gd" +ProfileManager="*res://autoload/profile_manager.gd" +ProgressManager="*res://autoload/progress_manager.gd" +ExerciseEngine="*res://autoload/exercise_engine.gd" +SaveManager="*res://autoload/save_manager.gd" +AudioManager="*res://autoload/audio_manager.gd" +SettingsManager="*res://autoload/settings_manager.gd" diff --git a/scenes/boot/boot.tscn b/scenes/boot/boot.tscn new file mode 100644 index 0000000..93dc0aa --- /dev/null +++ b/scenes/boot/boot.tscn @@ -0,0 +1,3 @@ +[gd_scene load_steps=1 format=3] + +[node name="Boot" type="Node"] diff --git a/scripts/data/validate_data_cli.gd b/scripts/data/validate_data_cli.gd new file mode 100644 index 0000000..cabbad9 --- /dev/null +++ b/scripts/data/validate_data_cli.gd @@ -0,0 +1,46 @@ +extends SceneTree +## Outil headless invoque par `make validate-data`. +## A ce stade, verifie seulement que les fichiers data/**/*.json sont du JSON bien forme. +## La validation contre les schemas (rule, exercise, dictation, curriculum, save) sera +## ajoutee a l'etape "Donnees" (voir Ordre de construction, docs/specs/decisions.md point 2). + + +func _init() -> void: + var json_paths: Array[String] = _find_json_files("res://data") + var failures: Array[String] = [] + for path in json_paths: + var file := FileAccess.open(path, FileAccess.READ) + if file == null: + failures.append("%s : lecture impossible" % path) + continue + var text := file.get_as_text() + if text.strip_edges().is_empty(): + continue + if JSON.parse_string(text) == null: + failures.append("%s : JSON invalide" % path) + + if failures.is_empty(): + print("validate-data : %d fichier(s) JSON valide(s)" % json_paths.size()) + quit(0) + else: + for failure in failures: + printerr(failure) + quit(1) + + +func _find_json_files(root_path: String) -> Array[String]: + var result: Array[String] = [] + var dir := DirAccess.open(root_path) + if dir == null: + return result + dir.list_dir_begin() + var entry := dir.get_next() + while entry != "": + if entry != "." and entry != "..": + var full_path := root_path.path_join(entry) + if dir.current_is_dir(): + result.append_array(_find_json_files(full_path)) + elif entry.ends_with(".json"): + result.append(full_path) + entry = dir.get_next() + return result diff --git a/scripts/data/validate_data_cli.gd.uid b/scripts/data/validate_data_cli.gd.uid new file mode 100644 index 0000000..d2d7c52 --- /dev/null +++ b/scripts/data/validate_data_cli.gd.uid @@ -0,0 +1 @@ +uid://01g5hgfcb5tq diff --git a/tests/test_bootstrap.gd b/tests/test_bootstrap.gd new file mode 100644 index 0000000..85c8ce1 --- /dev/null +++ b/tests/test_bootstrap.gd @@ -0,0 +1,14 @@ +extends GutTest +## Verifie que le squelette du projet charge correctement les sept autoloads. +## Les tests de logique pedagogique (correction, progression, sauvegardes) +## arrivent avec les etapes correspondantes. + + +func test_autoloads_are_registered() -> void: + assert_not_null(GameManager, "GameManager doit etre charge") + assert_not_null(ProfileManager, "ProfileManager doit etre charge") + assert_not_null(ProgressManager, "ProgressManager doit etre charge") + assert_not_null(ExerciseEngine, "ExerciseEngine doit etre charge") + assert_not_null(SaveManager, "SaveManager doit etre charge") + assert_not_null(AudioManager, "AudioManager doit etre charge") + assert_not_null(SettingsManager, "SettingsManager doit etre charge") diff --git a/tests/test_bootstrap.gd.uid b/tests/test_bootstrap.gd.uid new file mode 100644 index 0000000..505b0db --- /dev/null +++ b/tests/test_bootstrap.gd.uid @@ -0,0 +1 @@ +uid://bgko12vcwsipr diff --git a/tools/setup.sh b/tools/setup.sh new file mode 100755 index 0000000..f87f37c --- /dev/null +++ b/tools/setup.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash +# Installe l'outillage de developpement : binaire Godot pinne, addon GUT, +# environnement Python pour gdtoolkit. Rien de ceci n'est commite (voir .gitignore) : +# ce script est la seule source de verite pour reconstruire l'outillage. +set -euo pipefail + +cd "$(dirname "$0")/.." + +GODOT_VERSION="$(cat .godot-version)" +GODOT_BIN_DIR=".godot-bin" +GODOT_BIN="${GODOT_BIN_DIR}/godot" +GUT_VERSION="v9.6.0" # v9.6.1+ reference AccessibilityServer, absent de Godot 4.6.3 +GDTOOLKIT_VERSION="4.5.0" + +mkdir -p "${GODOT_BIN_DIR}" + +if [ ! -x "${GODOT_BIN}" ]; then + echo "Telechargement de Godot ${GODOT_VERSION}..." + TMP_ZIP="$(mktemp)" + curl -sL -o "${TMP_ZIP}" \ + "https://github.com/godotengine/godot/releases/download/${GODOT_VERSION}/Godot_v${GODOT_VERSION}_linux.x86_64.zip" + unzip -o -j "${TMP_ZIP}" -d "${GODOT_BIN_DIR}" + mv "${GODOT_BIN_DIR}/Godot_v${GODOT_VERSION}_linux.x86_64" "${GODOT_BIN}" + chmod +x "${GODOT_BIN}" + rm -f "${TMP_ZIP}" +else + echo "Godot deja present dans ${GODOT_BIN}." +fi + +if [ ! -d "addons/gut" ]; then + echo "Telechargement de GUT ${GUT_VERSION}..." + TMP_TAR="$(mktemp)" + TMP_DIR="$(mktemp -d)" + curl -sL -o "${TMP_TAR}" \ + "https://github.com/bitwes/Gut/archive/refs/tags/${GUT_VERSION}.tar.gz" + tar xzf "${TMP_TAR}" -C "${TMP_DIR}" + mkdir -p addons + cp -r "${TMP_DIR}"/Gut-*/addons/gut addons/gut + rm -rf "${TMP_TAR}" "${TMP_DIR}" +else + echo "GUT deja present dans addons/gut." +fi + +if [ ! -d ".venv" ]; then + echo "Creation de l'environnement Python pour gdtoolkit..." + python3 -m venv .venv +fi +./.venv/bin/pip install --quiet --upgrade pip +./.venv/bin/pip install --quiet "gdtoolkit==${GDTOOLKIT_VERSION}" + +echo "Setup termine : Godot ${GODOT_VERSION}, GUT ${GUT_VERSION}, gdtoolkit ${GDTOOLKIT_VERSION}."