Note de mise à jour du 19.04.2026


Dice Lab — Dev Log

Version du 19 avril 2026

🔧 Corrections

Audio

  • Volume par défaut passé à 1.0 (100%) dans l'état JS (vol=1) et dans le slider HTML (value="1")
  • Cohérence mute/unmute vérifiée : gain.gain.value = muted ? 0 : vol reste intact
  • Sons légèrement adoucis (amplitudes réduites, attaques plus douces)

Système de tooltips — refactorisation complète

  • Problème : les tooltips étaient des <span> positionnés en absolute à l'intérieur de cartes avec overflow:hidden, ce qui les faisait se faire rogner
  • Solution : déplacement vers une couche fixe dédiée au niveau du <body> (#tip-layer + .tip-bubble)
  • Le module TIP gère désormais le positionnement dynamique via getBoundingClientRect() à chaque hover et resize
  • Support du focus clavier (focusin / focusout) ajouté pour l'accessibilité
  • Les tooltips s'affichent toujours au-dessus de tout (z-index: 9999), y compris le canvas et les cartes
  • Les éléments .tip sont maintenant des <button tabindex="0"> au lieu de <span> pour la navigation clavier
  • Repositionnement automatique si la bulle sortirait de l'écran (bord gauche, bord droit, sous l'élément si pas assez de place au-dessus)

Score — mise en cohérence totale

  • Problème : la formule affichée dans la tooltip (floor(...)) ne correspondait pas au calcul JS qui utilisait Math.round
  • Décision : uniformisation sur Math.round
  • Formule désormais identique partout : round((moy + méd) / 2 − 0.2 × σ)
  • Tooltip mise à jour en conséquence
  • Commentaire dans le code aligné

Gestion des erreurs

  • Les messages d'erreur distinguent maintenant explicitement la source :
    • "Formule A invalide : ..." → champ A mis en rouge
    • "Formule B invalide : ..." → champ B mis en rouge
  • Si A est valide mais B invalide en mode comparaison : les résultats de A s'affichent normalement, les anciennes stats/comparaisons de B sont effacées proprement
  • Si A est invalide : les résultats sont masqués entièrement, pas de vieux affichage fantôme
  • Ajout d'une fonction clearCmp() pour réinitialiser proprement les barres de comparaison

Division par zéro

  • Avant : les paires (va, vb=0) étaient silencieusement ignorées, tronquant la masse de probabilité sans avertissement
  • Après : détection explicite dans divDist()
    • Si des cas de division par zéro existent, un flag divZeroWarning est levé
    • Un bandeau d'avertissement jaune s'affiche dans l'UI avec un message explicatif
    • Si le dénominateur est toujours zéro (masse résultante < 1%), une exception est levée avec message clair
    • La masse de probabilité restante est préservée et signalée, jamais ignorée silencieusement

✨ Nouvelles fonctionnalités parseur / moteur

Dés spéciaux

  • d% : alias syntaxique pour 1d100 (centile), géré au niveau du lexer
  • dF / dFate : dé Fate/Fudge avec distribution {-1: 1/3, 0: 1/3, +1: 1/3}, exact

Dés explosifs

  • ! : explosion infinie — série géométrique tronquée à 8 niveaux (précision < 1e-9 au-delà), normalisée
  • !! : explosion une fois — calcul exact combinatoire
  • Pour NdX! avec N > 1 ou combiné à d'autres modificateurs : fallback Monte Carlo

Rerolls

  • r : relance infinie tant que la condition est vraie (protection anti-boucle à 200 itérations/dé)
  • ro : relance une seule fois si la condition est vraie
  • Comparateurs supportés : <, <=, >, >=, =, !=
  • Pour un dé simple sans autre modificateur : calcul exact par série géométrique (r) ou calcul direct (ro)
  • Sinon : fallback Monte Carlo avec indication dans l'UI
  • Détection des rerolls impossibles (tous les résultats satisfont la condition) → exception explicite

Lexer enrichi

  • Détection de ro avant r pour éviter les ambiguïtés de tokenisation
  • Détection de !! avant ! pour la même raison
  • Gestion des comparateurs <=, >=, != comme tokens dédiés
  • Alias % reconnu en standalone

🎨 Améliorations UX / UI

Section aide syntaxique

  • Ajout d'un panneau rétractable "Syntaxes supportées" entre le titre et les champs de saisie
  • Contenu : tableau 2 colonnes des syntaxes utiles avec exemples concrets
  • Fermé par défaut, state toggle géré proprement avec animation de la flèche

Légendes du graphe

  • Les légendes "A" et "B" affichent maintenant la formule tronquée (28 caractères max)
  • L'attribut title contient la formule complète (tooltip navigateur natif au survol)
  • Mise à jour à chaque analyse via updateLegends(fa, fb)

Résultats les plus probables — mode comparaison

  • Avant : une seule liste, dominée par les tops de A, avec le pourcentage de B affiché à côté
  • Après : deux colonnes distinctes, une pour A et une pour B, chacune avec ses 7 résultats les plus probables et leurs probabilités respectives
  • Labels "A" et "B" colorés distinctement au-dessus de chaque colonne

Note de simulation

  • Formulation plus prudente : "Estimation par simulation (200 000 tirages) — valeurs approchées" au lieu d'une précision chiffrée fixe
  • Nombre de tirages affiché avec séparateur de milliers localisé (toLocaleString('fr-FR'))
  • La note n'apparaît que si au moins une des deux distributions est estimée

États UI propres

  • Réinitialisation systématique des barres de comparaison (width: 0) lors de toute désactivation du mode B
  • Suppression des valeurs B dans les stats au bon moment (changement de mode, erreur B, désactivation)
  • Le bandeau d'avertissement division par zéro est effacé à chaque nouvelle analyse

🏗️ Refactoring interne

  • Extraction de clearCmp() pour centraliser la réinitialisation de la section comparaison
  • evalDice() centralisé : point d'entrée unique pour tous les types de dés avec leur modificateurs
  • modMC() simplifié pour déléguer à mcFull()
  • mcFull() unifié : gère keep/drop, explosion et reroll en une seule simulation cohérente
  • parseFull() renommé (était PARSE.parse) pour clarté
  • cmpMatch() extrait comme utilitaire pur pour la logique de comparateurs
  • Constante MC_N = 200000 centralisée

Version du 18 avril 2026 — Initial release

  • Interface sombre minimaliste, fichier HTML autonome sans dépendances
  • Parseur : XdY, kh/kl/dh/dl, floor/ceil/round/abs, +-*/, parenthèses, négation unaire
  • Moteur de distribution exact (convolution) avec fallback Monte Carlo (160 000 tirages) pour les combinaisons volumineuses
  • Score synthétique : floor((moy + méd) / 2 − 0.2 × σ)
  • Statistiques : min, max, moyenne, médiane, mode, écart-type
  • Graphe interactif avec hover, animation d'apparition, double distribution A/B
  • Mode comparaison : probabilités A > B, B > A, égalité avec barres animées
  • Résultats les plus probables (top 7)
  • Sound design procédural (Web Audio API, sans assets)
  • Contrôle volume + mute
  • Arrondi final configurable (none / floor / ceil)
  • Tooltips d'aide discrètes sur les termes clés

Files

20260419225830 Dice Lab.html Play in browser
Apr 19, 2026