Tamagotchi web multiusers — FastAPI + PostgreSQL, stats vitales, aptitudes, évolution par lignées
  • Python 68.6%
  • JavaScript 27.5%
  • CSS 2.8%
  • Jinja 0.3%
  • Dockerfile 0.3%
  • Other 0.4%
Find a file
Nesquiik f061442503
All checks were successful
CI/CD / test (push) Successful in 1m30s
CI/CD / deploy (push) Successful in 57s
Village : porte dédiée, murs intérieurs, icônes menu rapide + boutique
- "Maison" : la porte (petite zone dédiée, pas tout le bâtiment) devient
  la seule cible pour entrer — le bâtiment reste solide/décoratif partout
  ailleurs. "Sortie" à l'intérieur était déjà une petite zone équivalente.
- Murs intérieurs : bordure de 4 TileSprites (texture tuilable générée,
  ajoutée au pipeline generate_terrain.py) tout autour de la pièce, avec
  collision — la pièce ne "flottait" plus dans le vide.
- Icônes Soigner/Gronder/Féliciter pour le menu rapide (mode object).
- decorationIcons.js : mapping nom→icône extrait de VillageIndoorScene.js
  vers un module partagé, réutilisé dans ShopView.jsx (catalogue, mes
  habits, mon inventaire affichent maintenant l'icône si connue).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0116RfuTFidH9dsCUWNt5Lqn
2026-09-06 16:36:12 +02:00
.forgejo/workflows CI : corrige l'accès aux services (postgres/redis) par nom, pas localhost 2026-09-05 15:52:24 +02:00
alembic Village : persistance backend position/état + prépa multi-village (tranche 6/7) 2026-09-06 13:46:44 +02:00
ansible Ansible : ajoute les clés VAPID pour les notifications push en prod 2026-09-06 09:15:44 +02:00
app Village : persistance backend position/état + prépa multi-village (tranche 6/7) 2026-09-06 13:46:44 +02:00
deploy Affiche la version (hash commit) et l'environnement en pied de page 2026-09-05 15:43:59 +02:00
docs Village : sprites de marche animés, portée réduite à la vue de face (tranche 7/7) 2026-09-06 14:03:09 +02:00
frontend Village : porte dédiée, murs intérieurs, icônes menu rapide + boutique 2026-09-06 16:36:12 +02:00
scripts Village : porte dédiée, murs intérieurs, icônes menu rapide + boutique 2026-09-06 16:36:12 +02:00
tests Village : persistance backend position/état + prépa multi-village (tranche 6/7) 2026-09-06 13:46:44 +02:00
.dockerignore Déploiement prod : Dockerfiles, docker-compose.prod.yml, Ansible, CI/CD 2026-09-05 12:45:54 +02:00
.env.example Notifications push : VAPID, service worker, job Celery étendu 2026-09-06 07:26:18 +02:00
.env.prod.example Notifications push : VAPID, service worker, job Celery étendu 2026-09-06 07:26:18 +02:00
.gitignore Ignore .claude/settings.local.json (permissions locales) 2026-09-05 19:02:06 +02:00
alembic.ini Phase 0: scaffolding FastAPI + PostgreSQL + Alembic 2026-08-31 20:19:50 +02:00
docker-compose.prod.yml Affiche la version (hash commit) et l'environnement en pied de page 2026-09-05 15:43:59 +02:00
docker-compose.yml Évolution auto, social minimal, DELETE, rate limiting, notifications (fondation) 2026-09-05 09:13:00 +02:00
Dockerfile Affiche la version (hash commit) et l'environnement en pied de page 2026-09-05 15:43:59 +02:00
pytest.ini Phase 0: scaffolding FastAPI + PostgreSQL + Alembic 2026-08-31 20:19:50 +02:00
README.md Classements par mini-jeu + écran de fin de partie avec rejouer 2026-09-05 16:33:00 +02:00
requirements.txt Notifications push : VAPID, service worker, job Celery étendu 2026-09-06 07:26:18 +02:00

Tamagotchi

Recréation du gadget Tamagotchi en application web multiusers : stats vitales, aptitudes, système d'évolution par lignées, économie interne et personnalisation. Architecture pensée pour accueillir une dimension sociale en v2 (temps réel, amis, visites).

Documentation

Rangée dans docs/ : reference/ (vision produit, architecture, style guide — la référence stable), process/ (roadmap, état du projet, journal du pipeline d'assets), features/ (specs des fonctionnalités implémentées), v2/ (idées et brouillons pas encore implémentés — un fichier migre vers features/ une fois développé).

Stack

  • Backend : FastAPI (async), SQLAlchemy 2.0 + Alembic, PostgreSQL
  • Auth : JWT, hashing argon2, rate limiting (slowapi + Redis) sur /auth/login et /auth/register
  • Notifications : Celery + Redis, tâche périodique de détection des tamagotchis en état critique (fondation backend — pas de vraies notifications navigateur pour l'instant)
  • Frontend : React (Vite), servi via Docker (Node.js pas nécessaire sur l'hôte)

Démarrage local

# Base de données + Redis + frontend (Node tourne uniquement en conteneur)
docker compose up -d

# Environnement Python (backend)
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
cp .env.example .env

# Migrations
.venv/bin/alembic upgrade head

# Seed de données de dev (user + tamagotchi de test)
.venv/bin/python -m scripts.seed

# Lancer l'API (port 8000 pris par un autre projet sur cette machine → 8010)
.venv/bin/uvicorn app.main:app --reload --port 8010

# Tests (unitaires + API, la base de test "tamagotchi_test" est créée automatiquement)
.venv/bin/pytest

# Optionnel : worker + beat Celery (notifications périodiques, pas requis pour l'API elle-même)
.venv/bin/celery -A app.tasks.celery_app worker --beat --loglevel=info

L'API est servie sur http://localhost:8010 (GET /health pour vérifier), le frontend sur http://localhost:5173 (voir frontend/README.md).

Tester l'API manuellement

Le plus simple : ouvrir http://localhost:8010/docs (Swagger UI généré automatiquement par FastAPI). Cliquer sur "Authorize" (cadenas en haut à droite), renseigner username = ton email et password = ton mot de passe (les champs client_id/client_secret/scope restent vides), valider. Swagger attache ensuite automatiquement le token à toutes les routes protégées testées via "Try it out".

/auth/login suit volontairement le format standard OAuth2 password flow (username/password en application/x-www-form-urlencoded, username porte l'email) pour être compatible nativement avec le bouton "Authorize" de Swagger — /auth/register reste en JSON classique.

Auth access + refresh : /auth/login renvoie un access token JWT (20 min) et pose un cookie httpOnly refresh_token (14 jours, sameSite=strict, secure uniquement en HTTPS). POST /auth/refresh régénère un access token à partir du cookie, POST /auth/logout l'invalide. Le frontend gère ça tout seul (401 → refresh silencieux → retry) ; via Swagger, l'access token de 20 min expire plus vite qu'avant (24h en PoC) — il suffit de re-cliquer "Authorize" après expiration, ou d'appeler /auth/refresh (le cookie posé par le navigateur suffit, pas besoin de renseigner de champ).

Sinon en ligne de commande :

BASE=http://localhost:8010

# Inscription
curl -X POST $BASE/auth/register -H "Content-Type: application/json" \
  -d '{"email":"moi@example.com","password":"password123"}'

# Connexion — récupère le token (form-urlencoded, champ "username" = email)
TOKEN=$(curl -s -X POST $BASE/auth/login -H "Content-Type: application/x-www-form-urlencoded" \
  -d "username=moi@example.com&password=password123" | python3 -c "import json,sys;print(json.load(sys.stdin)['access_token'])")

# Créer son tamagotchi (un seul par compte en PoC)
curl -X POST $BASE/tamagotchis -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"name":"Fifi"}'

# Consulter l'état (id renvoyé par la création, ex: 1)
curl $BASE/tamagotchis/1 -H "Authorization: Bearer $TOKEN"

# Actions disponibles : feed, play, clean, sleep, wake, heal, scold, praise, pet
curl -X POST $BASE/tamagotchis/1/actions/feed -H "Authorization: Bearer $TOKEN"

Pour observer la maladie/mort sans attendre des heures réelles, on peut avancer last_tick_at artificiellement en base :

docker compose exec postgres psql -U tamagotchi -d tamagotchi \
  -c "UPDATE tamagotchis SET last_tick_at = now() - interval '100 hours' WHERE id = 1;"

Un GET /tamagotchis/1 déclenchera alors la décroissance complète, puis (aléatoirement, avec plusieurs essais) le passage en malade.

Pour tester l'évolution (6 lignées : Force, Intelligence, Charisme, Créativité, Discipline, Chance), booster les aptitudes en base puis appeler /evolve autant de fois que de stades à franchir (œuf → bébé → enfant → ado → adulte) :

docker compose exec postgres psql -U tamagotchi -d tamagotchi \
  -c "UPDATE aptitudes SET force = 80, intelligence = 30, charisme = 10, discipline = 70 WHERE tamagotchi_id = 1;"

curl -X POST $BASE/tamagotchis/1/evolve -H "Authorization: Bearer $TOKEN"  # -> baby
curl -X POST $BASE/tamagotchis/1/evolve -H "Authorization: Bearer $TOKEN"  # -> child, lineage="force", variant selon discipline (et poids à l'âge adulte)

Pour observer le cimetière et l'héritage : forcer la mort (comme ci-dessus), puis consulter l'historique et recréer un œuf — il hérite de 10 % des aptitudes du précédent :

curl $BASE/users/me/cemetery -H "Authorization: Bearer $TOKEN"

curl -X POST $BASE/tamagotchis -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"name":"Successeur"}'

Avancement du PoC

Voir tamagotchi_poc_roadmap.md pour le détail des phases.

  • Phase 0 — Setup & scaffolding
  • Phase 1 — Modèles de données (subset PoC)
  • Phase 2 — Auth simplifiée
  • Phase 3 — Service de tick
  • Phase 4 — Endpoint tamagotchi + actions
  • Phase 5 — Service d'évolution (réduit)
  • Phase 6 — Frontend minimal (React)
  • Phase 7 — Test end-to-end & bilan

Bilan Phase 7

Parcours complet testé sans bug bloquant, dans le navigateur (Chrome piloté) : inscription → connexion → création de l'œuf → actions répétées (feed/clean/praise/scold/pet) reflétées en direct → aptitudes boostées en base (à défaut de mini-jeux) → évolution œuf → bébé → enfant (lignée "intelligence", variante "distrait" cohérente avec la discipline basse) → maladie déclenchée en avançant last_tick_at → guérison via "heal".

Frictions relevées

  • Mot de passe sans contrainte de longueur côté backend (seul le frontend imposait 8 caractères) — trouvé en testant l'inscription en direct, corrigé dans cette phase (Field(min_length=8) sur UserCreate).
  • Déconnexion au rechargement de pagecomblé : POST /auth/refresh + cookie httpOnly/sameSite=strict, l'access token reste en mémoire JS (jamais localStorage) mais se régénère silencieusement au chargement de la page via le cookie.
  • Messages d'erreur bruts et en anglais renvoyés tels quels par l'API et affichés dans l'UI (ex. "Tamagotchi is not sick") — pas de traduction ni de formatage convivial.
  • Pas de mini-jeux jouablescomblé : 5/5 mini-jeux jouables (voir docs/features/tamagotchi_minigames.md).
  • Pas de bouton de rafraîchissement manuel dans le dashboard — l'état ne se resynchronise qu'au montage du composant ou après une action.
  • Pas de tests automatisés sur les routes APIcomblé : tests/conftest.py fournit une base Postgres de test dédiée (tamagotchi_test, créée automatiquement), isolation par transaction/savepoint annulée après chaque test, 18 tests couvrant auth/tamagotchis/actions/evolve en plus des 21 tests unitaires sur les services purs.
  • /auth/login suit le format OAuth2 form (username/password) pour être compatible avec le bouton "Authorize" de Swagger, alors que /auth/register reste en JSON — incohérence mineure mais assumée et documentée plus haut.

Priorités proposées pour la suite

Par ordre de valeur/effort estimé, à trancher ensemble avant de reprendre docs/reference/tamagotchi_architecture.md :

  1. Tests API automatisés — fait.
  2. Refresh token + stockage httpOnly — fait.
  3. Mini-jeux jouables — 5/5 faits (Punching bag, Memory, Dialogue, Pari, Mosaïque).
  4. Lignées manquantes — fait.
  5. Boutique/économie (monnaie, habits, déco) — fait.
  6. Cimetière/héritage — fait.
  7. Poids/obésité — fait.
  8. Formes différenciées par stade — fait.
  9. Évolution automatique — fait (seuils d'âge depuis born_at, rattrape plusieurs stades d'un coup si besoin).
  10. Social minimal (FRIENDSHIPS) — fait.
  11. Rate limiting auth — fait.
  12. Notifications (fondation) — fait (détection + endpoint, pas de push navigateur).
  13. Piste plus lointaine : village explorable façon Stardew Valley — a du sens une fois la boucle cœur solide, pas avant.

Vers la v1 — cimetière, héritage, poids, formes différenciées

  • CimetièreCEMETERY (nom, lignée finale, durée de vie, cause de mort), consultable via GET /users/me/cemetery. Table indépendante du cycle de vie du tamagotchi (pas de FK vers tamagotchis), conforme à l'architecture.
  • Héritage — un compte peut désormais créer un nouvel œuf dès que son tamagotchi précédent est mort (avant : bloqué à vie après un seul). Le nouvel œuf hérite de 10 % des aptitudes finales du précédent (heritage_service.compute_inherited_aptitudes, fonction pure).
  • Poids — augmente légèrement à chaque feed (0.05), décroît passivement avec le temps via le tick (métabolisme, plancher à 0.5). Statuts maigre / normal / obese selon des seuils.
  • Formes différenciées par stade — chaque lignée a désormais un pool de variantes distinct à l'enfance, l'adolescence et l'âge adulte (au lieu d'une seule forme réutilisée). Le poids influence la forme uniquement à l'âge adulte : au-delà du seuil d'obésité, une variante dédiée prend le dessus sur la discipline (ex. force → "colosse"), fidèle à l'obésité de l'original.

Validé par 59 tests automatisés (12 nouveaux : héritage, formes par stade, poids, cimetière) + parcours complet dans un vrai navigateur (mort → cimetière visible sur l'écran de création → nouvel œuf avec aptitudes héritées affichées).

Vers la v1 (suite) — évolution auto, social minimal, rate limiting, notifications

  • Évolution automatiqueevolution_service.check_auto_evolution fait avancer le stade dès que l'âge (born_at) dépasse le seuil du stade suivant, appelé à chaque tick (consultation ou action). Rattrape plusieurs stades d'un coup si le compte n'a pas été consulté depuis longtemps. Le bouton "evolve →" manuel reste disponible en plus (pratique pour les tests).
  • DELETE /tamagotchis/{id} — endpoint manquant de l'architecture, ajouté.
  • Social minimal — table FRIENDSHIPS + GET /friendships, POST /friendships/request (par email), POST /friendships/{id}/accept. Volontairement minimal (pas de messagerie, pas de visites) : sert de fondation pour la v2 sociale sans remodeler le schéma plus tard.
  • Rate limitingslowapi + Redis, 5 tentatives/minute sur /auth/login et /auth/register (par IP).
  • Notifications (fondation backend) — Celery + Redis, tâche périodique (check_critical_tamagotchis, toutes les 30 min) qui détecte les tamagotchis en état critique (faim/bonheur/propreté sous le seuil, ou malades) et crée une entrée dans NOTIFICATIONS, consultable via GET /users/me/notifications + POST /users/me/notifications/{id}/read. Pas de vraies notifications navigateur (push) pour l'instant — décision explicite pour rester sur une fondation backend simple.

Validé par 104 tests automatisés (22 nouveaux) + vérifications manuelles (rate limit, delete, friendships, scan de notifications sur la vraie base).

Vers la v1 (suite) — boutique & économie

  • BoutiqueITEMS (catalogue), INVENTORY_ITEMS (possession compte : décoration, consommables), TAMA_ITEMS (possession tamagotchi : habits, perdus à la mort). GET /shop/items, POST /shop/items/{id}/buy, GET/POST /tamagotchis/{id}/items(/equip|/unequip|/consume), GET /users/me/inventory. Catalogue de démarrage seedé (scripts/seed_shop.py), détail complet dans docs/features/tamagotchi_shop_economy.md.
  • Habits achetés puis équipés/déséquipés séparément ; bonus = mutation directe de la vraie stat/aptitude (choix explicite). Décoration : bonus unique à l'achat, objet conservé en collection. Rare/Légendaire laissés de côté (pas de quête pour les distribuer).
  • Frontend ShopView.jsx, bouton "🛒 Boutique" sur le dashboard, testé de bout en bout en navigateur (achat des 3 catégories, équiper/déséquiper, consommer, mise à jour pièces/stats).

Validé par 127 tests automatisés (22 nouveaux) + parcours complet dans un vrai navigateur.