Bloc 98 — 🐛 Progression : une ligue disponible parce qu'elle a ses valeurs, pas parce qu'elle est dans une liste - #124
Merged
Conversation
Numéroté 98 : le 97 est pris par le correctif CI mergé juste avant.
A. Les valeurs d'Argent saisies et enregistrées en admin n'étaient jamais
regardées par le référentiel public. Trois choses les ignoraient, et
toutes nommaient une ligue en dur :
- `levelUpTroopsAt` s'ouvrait sur `if (league === "silver") return null`
- `confirmedLevelUpLeagues`, une liste statique de 5 noms
- le message public listait ces 5 noms dans son texte traduit
La disponibilité vient maintenant des données : `hasLevelUpTroopsFormula`
répond oui quand coefficient ET ratio sont présents et > 0, pour
n'importe quelle ligue. Une ligue renseignée s'affiche, une ligue vidée
redevient non confirmée, sans aucun nom de ligue dans la logique — un
test le vérifie sur le source lui-même (hors commentaires).
Le message nomme désormais les ligues réellement disponibles, assemblées
par `Intl.ListFormat` pour que le « A, B et C » reste correct dans les
5 langues. Formulation retouchée en conséquence dans les 5 fichiers de
messages, avec une branche ICU pour le cas où aucune ligue n'en a.
A-bis (trouvé en route, non signalé au brief). La route PUT refusait tout
payload contenant un zéro, donc le référentiel Progression était
insauvegardable tant qu'une ligue restait vierge — sur une installation
neuve, c'est Argent, et la toute première sauvegarde revenait en 400.
Or c'est précisément {0, 0} qui marque une ligue non confirmée. La règle
devient : une paire est soit renseignée (les deux > 0), soit vierge (les
deux à 0) ; à moitié remplie, négative ou NaN, elle reste refusée.
B. Le « (Formule de troupes non confirmée) » de l'éditeur admin suit
maintenant ce qui est réellement stocké : il disparaît dès que la ligue
a ses deux valeurs, et apparaît sur n'importe quelle autre ligue laissée
vide — il n'était pas propre à Argent.
C. Les ligues sont listées dans l'ordre de progression du jeu (Bronze →
Légende, l'ordre de la constante `leagues`), côté admin comme public.
Le public l'était déjà ; l'admin affichait Argent en dernier, après
Légende, parce que sa ligne était écrite à la main à la suite des cinq
« confirmées ».
Tests : 21 unitaires (prédicat, validation de sauvegarde, ordre, absence
de nom de ligue dans le source, note admin conditionnelle) et 1 e2e qui
refait le parcours signalé — constat de l'indisponibilité, saisie côté
admin, puis table d'Argent affichée en public avec la valeur calculée
depuis les données enregistrées, et retour à l'état vierge.
Contre-vérifié en cassant le correctif : le littéral silver remis en
place rougit 3 unitaires et l'e2e ; la note admin rendue inconditionnelle
en rougit 4.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HJgsDSfsCbbn8cochFGwe2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A — 🚨 Le bug
Ton diagnostic était le bon, et c'était encore plus littéral que « vraisemblablement codé en dur » : trois choses ignoraient les données, et toutes nommaient une ligue en dur.
src/lib/level-up.tslevelUpTroopsAts'ouvrait surif (league === "silver") return null;src/lib/level-up.tsconfirmedLevelUpLeagues, une liste statique de 5 nomsmessages/*.jsonD'où le symptôme exact que tu décris : la saisie partait bien en base, et rien ne la lisait.
Le correctif. La disponibilité est maintenant une question posée aux données :
hasLevelUpTroopsFormula(league, parameters)répond oui quand coefficient et ratio sont présents et > 0 — pour n'importe quelle ligue. Une ligue renseignée s'affiche ; une ligue vidée redevient non confirmée toute seule. Aucun nom de ligue ne subsiste dans la logique, et un test le vérifie sur le source lui-même (src/lib/level-up.tsetsrc/components/level-up-reference.tsx, hors commentaires) — c'est ce qui empêche la rechute.Le message nomme désormais les ligues qui en ont vraiment une, assemblées par
Intl.ListFormatpour que le « A, B et C » reste correct dans les 5 langues sans séparateur écrit à la main. La formulation change donc un peu — c'était inévitable, l'ancienne contenait la liste :A-bis —⚠️ Un second bug trouvé en route, pas dans le brief
src/app/api/admin/guides/references/level-up/route.tsrefusait tout payload contenant un zéro :Or
{0, 0}est exactement ce qui marque une ligue non confirmée. Conséquence : le référentiel Progression était insauvegardable tant qu'une ligue restait vierge — sur une installation neuve c'est Argent, donc la toute première sauvegarde tentée par un admin revenait en 400. Tu n'y es plus exposé (tes 6 ligues sont remplies), mais la règle « 0/0 = pas encore confirmé » ne tenait pas debout tant que l'API interdisait de stocker ce 0.La règle devient : une paire est soit renseignée (les deux > 0), soit vierge (les deux à 0). À moitié remplie, négative ou NaN, elle reste refusée.
B — Le texte « (Formule de troupes non confirmée) » en admin
Il suit maintenant ce qui est réellement stocké : il disparaît dès qu'une ligue a ses deux valeurs, et il apparaît sur n'importe quelle ligue laissée vide — il n'avait rien de spécifique à Argent.
C — Ordre des ligues
Bronze, Argent, Or, Platine, Diamant, Légende, admin et public. Le public l'était déjà (il boucle sur
leagues) ; l'admin affichait Argent en dernier, après Légende, parce que sa ligne était écrite à la main à la suite des cinq « confirmées ». Une seule boucle sur la liste partagée règle l'ordre et le bug en même temps.Tests
21 tests unitaires : le prédicat dans les deux sens (une ligue remplie devient disponible, une ligue vidée redevient indisponible — écrits sur une ligue passée en paramètre, jamais sur « silver »), les formes refusées (à moitié remplie, négative, NaN), la validation de sauvegarde, l'ordre de progression, la note admin conditionnelle, et le garde-fou qui interdit un nom de ligue dans le source.
1 test e2e qui refait ton parcours dans l'ordre où tu l'as vécu : constat de l'indisponibilité d'Argent en public → saisie et enregistrement côté admin → table d'Argent affichée en public, avec la valeur calculée depuis les données enregistrées (niveau 2 = 30 × 1,24² = 46, pas juste « une table est là ») → retour à l'état vierge, dont le succès prouve au passage le correctif A-bis.
Contre-vérifié en cassant le correctif : le littéral
silverremis danslevelUpTroopsAtrougit 3 unitaires et l'e2e ; la note admin rendue inconditionnelle en rougit 4.Validation
pnpm lint+ typecheck + prettier : proprespnpm test: 1296 tests verts (+21)pnpm build: succèspnpm test:e2e: 87/87 verts (5,2 min), sur une base e2e recréée à neufCe qu'il te reste à faire
Rien côté données : tes valeurs d'Argent sont déjà en base, elles s'afficheront dès le déploiement. Si tu veux les revérifier, l'éditeur admin les montre maintenant à leur place dans l'ordre, sans la mention « non confirmée ».
🤖 Generated with Claude Code
https://claude.ai/code/session_01HJgsDSfsCbbn8cochFGwe2
Generated by Claude Code