[ADD] application: clock, translation, formatting, displayed name
The screens need one clock, one translation mechanism and one way to
format and name, or each component grows its own. horloge.js is the only
code that reads time and arms timers, injected so tests drive it.
traduction.js keys texts by domain, in two families of tables, raises on a
missing key and never shows a raw key; libelles/ splits the label table by
domain. format.js formats numbers and dates in French, and personnes.js
composes the displayed name the frozen labels use. Nothing persists
between sessions.
Checked: 1773 node and 43 browser tests.
--- FR ---
[ADD] application : horloge, traduction, mise en forme, nom affiché
Les écrans exigent une horloge, un mécanisme de traduction et une façon de
mettre en forme et de nommer, sans quoi chaque composant ferait les siens.
horloge.js est le seul code qui lit l'heure et arme des minuteries, injecté
pour que les épreuves le pilotent. traduction.js range les textes par
domaine, en deux familles de tables, lève sur une clé absente et ne montre
jamais une clé brute ; libelles/ découpe la table des libellés par domaine.
format.js met en forme nombres et dates en français, et personnes.js
compose le nom affiché qu'emploient les libellés figés. Rien ne persiste
d'une séance à l'autre.
Vérifié : 1773 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:39 -04:00
|
|
|
// © 2026 TechnoLibre (http://www.technolibre.ca)
|
|
|
|
|
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
|
|
|
|
|
|
[ADD] interface: diagnostic — what a configuration makes unavoidable
Before generating, the operator must know what no plan can avoid: the
encounters a table size forces, the conflicts when every table holds
colleagues, the anchors that impose a return. The engine's diagnosis is
turned into sentences with their figures and their remedies, shown in its
section and, compact, beside the plan, whose banner states the floors
when every table is in conflict (§ 7.5).
Checked: 2425 node and 413 browser tests.
--- FR ---
[ADD] interface : diagnostic — ce qu'une configuration rend inévitable
Avant de générer, l'opérateur doit savoir ce qu'aucun plan n'évite : les
rencontres qu'une taille de table impose, les conflits quand chaque table
réunit des collègues, les ancrages qui imposent un retour. Le diagnostic du
moteur devient des phrases, avec leurs chiffres et leurs remèdes, montrées
dans sa section et, en compact, à côté du plan, dont le bandeau énonce les
planchers quand toutes les tables sont en conflit (§ 7.5).
Vérifié : 2425 node et 413 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:41:51 -04:00
|
|
|
// Les libellés du diagnostic d'une configuration (§ 5.6, § 14.6). Chaque clé
|
|
|
|
|
// commence par « diagnostic. ». Un énoncé (phrases.js) a son texte sous sa
|
|
|
|
|
// clé, son remède sous diagnostic.remede.<nom>. Chaque chiffre nomme son
|
|
|
|
|
// unité : une collision se compte en occurrences, une paire distincte à
|
|
|
|
|
// part (§ 5.4). L'appartenance d'un groupe est une donnée : l'écran la pose
|
|
|
|
|
// dans son propre nœud, avant le texte, qu'aucune entrée de cette table ne
|
|
|
|
|
// lui fait porter.
|
|
|
|
|
import { compte, enumeration } from '../../application/libelles/aides.js';
|
|
|
|
|
|
|
|
|
|
// « sur le tour » ou « sur les R tours ».
|
|
|
|
|
const surLesTours = (tours) => (tours === 1 ? 'sur le tour' : `sur les ${tours} tours`);
|
|
|
|
|
|
|
|
|
|
export const TABLE = new Map([
|
|
|
|
|
// --- Le cadre de l'écran ---------------------------------------------------
|
|
|
|
|
['diagnostic.enonces', 'Ce que la configuration impose'],
|
|
|
|
|
['diagnostic.nonCalcule', 'La configuration ne se normalise pas : le diagnostic ne se calcule pas.'],
|
[IMP] plan and diagnostic: grouped toolbar, card panels, bounded tooltip
The plan's chrome mixed view controls with panels of the same weight.
The toolbar groups round, zoom and views; side panels, the reserve and
the work lists become cards. A seat tooltip, like a refusal on a seat,
stays inside the plan frame and flips side rather than cover the next
panel. The diagnostic groups its statements into one card per colliding
membership, in the same order. The drawing keeps its colours and shapes.
Checked: node 231, browser 137, 6 mutations caught.
--- FR ---
[IMP] plan et diagnostic : barre groupée, panneaux en cartes, infobulle
L'habillage du plan mêlait commandes de vue et panneaux de même poids.
La barre groupe tour, zoom et vues ; panneaux, réserve et listes de
travail deviennent des cartes. L'infobulle d'un siège, comme un refus
sur une place, reste dans le cadre du plan et change de côté plutôt que
de couvrir le panneau voisin. Le diagnostic groupe ses énoncés en une
carte par appartenance en collision, sans changer l'ordre. Le dessin
garde couleurs et formes. Vérifié : node 231, navigateur 137.
Assisted-by: Claude Opus 5.5
2026-10-11 00:58:07 -04:00
|
|
|
// Les intitulés des cartes que ne nomme pas une appartenance
|
|
|
|
|
// (cartesDiagnostic) : la séparation vidée de son sens, puis le reste.
|
|
|
|
|
['diagnostic.carte.separation', 'Séparation des appartenances'],
|
|
|
|
|
['diagnostic.carte.ensemble', "Tout l'événement"],
|
[ADD] interface: diagnostic — what a configuration makes unavoidable
Before generating, the operator must know what no plan can avoid: the
encounters a table size forces, the conflicts when every table holds
colleagues, the anchors that impose a return. The engine's diagnosis is
turned into sentences with their figures and their remedies, shown in its
section and, compact, beside the plan, whose banner states the floors
when every table is in conflict (§ 7.5).
Checked: 2425 node and 413 browser tests.
--- FR ---
[ADD] interface : diagnostic — ce qu'une configuration rend inévitable
Avant de générer, l'opérateur doit savoir ce qu'aucun plan n'évite : les
rencontres qu'une taille de table impose, les conflits quand chaque table
réunit des collègues, les ancrages qui imposent un retour. Le diagnostic du
moteur devient des phrases, avec leurs chiffres et leurs remèdes, montrées
dans sa section et, en compact, à côté du plan, dont le bandeau énonce les
planchers quand toutes les tables sont en conflit (§ 7.5).
Vérifié : 2425 node et 413 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:41:51 -04:00
|
|
|
|
|
|
|
|
// --- La séparation vidée de son sens (§ 7.5, § 15.4) -----------------------
|
|
|
|
|
[
|
|
|
|
|
'diagnostic.uneSeuleAppartenance',
|
|
|
|
|
'une seule appartenance, portée par chaque personne, sous séparation active : la séparation est vide de sens',
|
|
|
|
|
],
|
|
|
|
|
['diagnostic.collisionPartout', 'tout placement porte une collision à chaque table, à chaque tour'],
|
|
|
|
|
|
|
|
|
|
// --- Les collisions et l'excédent (§ 5.4, § 5.6) ---------------------------
|
|
|
|
|
[
|
|
|
|
|
'diagnostic.collisions',
|
|
|
|
|
({ effectif, plancherCumulees, plancherPairesDistinctes, tours }) =>
|
|
|
|
|
`${compte(effectif, 'personne', 'personnes')} : au moins ` +
|
|
|
|
|
`${compte(plancherCumulees, 'collision cumulée', 'collisions cumulées')} ${surLesTours(tours)}, ` +
|
|
|
|
|
`${plancherCumulees === 1 ? 'portée' : 'portées'} par au moins ` +
|
|
|
|
|
compte(plancherPairesDistinctes, 'paire distincte', 'paires distinctes'),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'diagnostic.excedent',
|
|
|
|
|
({ plancherExcedent }) =>
|
|
|
|
|
`excédent d'au moins ${compte(plancherExcedent, 'collision', 'collisions')} : des retrouvailles sont forcées`,
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
// --- La redondance et les animateurs (§ 5.6) -------------------------------
|
|
|
|
|
[
|
|
|
|
|
'diagnostic.redondance',
|
|
|
|
|
({ redondanceMinimale }) =>
|
|
|
|
|
`au moins ${compte(redondanceMinimale, 'appartenance recroisée', 'appartenances recroisées')} par personne`,
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'diagnostic.animateurs',
|
|
|
|
|
({ redondanceImposeeParAnimateurs }) =>
|
|
|
|
|
'tous les animateurs partagent une appartenance : chaque mobile accumule au moins ' +
|
|
|
|
|
`${compte(redondanceImposeeParAnimateurs, 'redondance', 'redondances')} qu'aucune recherche ne réduit`,
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
// --- L'ancrage par table (§ 5.6, § 5.9) ------------------------------------
|
|
|
|
|
['diagnostic.ancrage.gelee', ({ numero, capacite }) => `la table ${numero} ne tourne plus : ses ${capacite} places sont ancrées`],
|
|
|
|
|
[
|
|
|
|
|
'diagnostic.ancrage.moitie',
|
|
|
|
|
({ numero, ancres, capacite }) =>
|
|
|
|
|
`la table ${numero} a ${compte(ancres, 'place ancrée', 'places ancrées')} sur ${capacite} : ` +
|
|
|
|
|
"elle réduit d'autant le brassage de tout l'événement",
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
// --- L'écart d'itinéraire, le manque de places (§ 5.6, § 12.10.4) ----------
|
|
|
|
|
[
|
|
|
|
|
'diagnostic.ecartItineraire',
|
|
|
|
|
({ plancher, mobilesAuMoins }) =>
|
|
|
|
|
`écart d'itinéraire maximal : plancher ${plancher}, au moins ` +
|
|
|
|
|
(mobilesAuMoins === 1 ? '1 mobile finit sous son plafond a priori' : `${mobilesAuMoins} mobiles finissent sous leur plafond a priori`),
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'diagnostic.placesManquantes',
|
|
|
|
|
({ placesManquantes }) =>
|
|
|
|
|
placesManquantes === 1 ? '1 place manque à chaque tour' : `${placesManquantes} places manquent à chaque tour`,
|
|
|
|
|
],
|
|
|
|
|
|
[ADD] screens: tags on the card, table goals, priority editor, import
The operator now reaches tags, goals and priorities from the screens.
A person's card adds and removes tags, the participant list carries a
tag legend; each table takes an evening goal or one per round with its
rule; the generation settings hold a keyboard-operable priority editor
(move, join, split, restore, weights), the two optional criteria and the
goal mode; the proposals table and its ranking sentence follow the
order; the import screen reads a participants or a goals file. Removing
a tag or a goal returns focus to a neighbouring control.
Checked: node 4590, navigateur 942, node-long 124; captures republished.
--- FR ---
[ADD] écrans : étiquettes, objectifs des tables, priorités, import
L'opérateur atteint étiquettes, objectifs et priorités depuis les écrans.
La fiche ajoute et retire les étiquettes, la liste porte leur légende ;
chaque table reçoit un objectif de soirée ou par tour avec sa règle ; les
réglages de génération portent un éditeur des priorités utilisable au
clavier (monter, joindre, séparer, rétablir, poids), les deux critères
facultatifs et le mode des objectifs ; le tableau des propositions et sa
phrase suivent l'ordre ; l'import lit un fichier de personnes ou
d'objectifs. Retirer une étiquette ou un objectif rend le focus à côté.
Vérifié : node 4590, navigateur 942, longues 124 ; captures republiées.
Assisted-by: Claude Opus 5.5
2026-10-11 17:53:27 -04:00
|
|
|
// --- Les objectifs hors d'atteinte (§ 5.6, A10) -----------------------------
|
|
|
|
|
// Un plancher par valeur que le mode des objectifs compare : le texte dit
|
|
|
|
|
// ce qu'aucun placement n'évite.
|
|
|
|
|
[
|
|
|
|
|
'diagnostic.objectifs.toursHorsObjectif',
|
|
|
|
|
({ plancher }) =>
|
|
|
|
|
`au moins ${compte(plancher, 'tour hors objectif', 'tours hors objectif')} : ` +
|
|
|
|
|
"les tables qui portent un objectif n'ont pas assez de places libres pour chaque tour possible",
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'diagnostic.objectifs.jamaisServies',
|
|
|
|
|
({ plancher }) =>
|
|
|
|
|
`au moins ${compte(plancher, 'personne jamais servie', 'personnes jamais servies')} par une table à objectif, ` +
|
|
|
|
|
'quel que soit le placement',
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'diagnostic.objectifs.horsObjectifMax',
|
|
|
|
|
({ plancher }) =>
|
|
|
|
|
`au moins une personne passe au moins ${compte(plancher, 'tour', 'tours')} hors objectif, quel que soit le placement`,
|
|
|
|
|
],
|
|
|
|
|
|
[ADD] interface: diagnostic — what a configuration makes unavoidable
Before generating, the operator must know what no plan can avoid: the
encounters a table size forces, the conflicts when every table holds
colleagues, the anchors that impose a return. The engine's diagnosis is
turned into sentences with their figures and their remedies, shown in its
section and, compact, beside the plan, whose banner states the floors
when every table is in conflict (§ 7.5).
Checked: 2425 node and 413 browser tests.
--- FR ---
[ADD] interface : diagnostic — ce qu'une configuration rend inévitable
Avant de générer, l'opérateur doit savoir ce qu'aucun plan n'évite : les
rencontres qu'une taille de table impose, les conflits quand chaque table
réunit des collègues, les ancrages qui imposent un retour. Le diagnostic du
moteur devient des phrases, avec leurs chiffres et leurs remèdes, montrées
dans sa section et, en compact, à côté du plan, dont le bandeau énonce les
planchers quand toutes les tables sont en conflit (§ 7.5).
Vérifié : 2425 node et 413 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:41:51 -04:00
|
|
|
// --- Le plafond a priori et les imposés (§ 5.4, § 5.5) ---------------------
|
|
|
|
|
[
|
|
|
|
|
'diagnostic.plafond',
|
|
|
|
|
({ valeur, ancres, mobiles }) =>
|
|
|
|
|
`plafond a priori ${compte(valeur, 'rencontre', 'rencontres')} pour ` +
|
|
|
|
|
enumeration([
|
|
|
|
|
...(ancres > 0 ? [compte(ancres, 'ancré', 'ancrés')] : []),
|
|
|
|
|
...(mobiles > 0 ? [compte(mobiles, 'mobile', 'mobiles')] : []),
|
|
|
|
|
]),
|
|
|
|
|
],
|
|
|
|
|
['diagnostic.plafondInconnu', (_, texte) => `plafond a priori : ${texte('format.vide')}`],
|
|
|
|
|
[
|
|
|
|
|
'diagnostic.imposes',
|
|
|
|
|
({ retoursImposes, ancragesImposantRetours }) =>
|
|
|
|
|
`${compte(retoursImposes, 'retour imposé', 'retours imposés')} par ${compte(ancragesImposantRetours, 'ancrage', 'ancrages')}`,
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
// --- Les remèdes -----------------------------------------------------------
|
|
|
|
|
['diagnostic.remede.separation', 'désactiver la séparation des appartenances'],
|
|
|
|
|
[
|
|
|
|
|
'diagnostic.remede.tables',
|
|
|
|
|
({ tablesManquantes }) =>
|
|
|
|
|
tablesManquantes === 1
|
|
|
|
|
? '1 table de plus, de la plus grande capacité présente, la rend évitable'
|
|
|
|
|
: `${tablesManquantes} tables de plus, de la plus grande capacité présente, la rendent évitable`,
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'diagnostic.remede.redistribuer',
|
|
|
|
|
"les réservations assoient des membres ensemble : répartir autrement l'appartenance la rend évitable",
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'diagnostic.remede.tours',
|
|
|
|
|
({ toursSansRedondance, tours }) =>
|
|
|
|
|
`avec ${compte(toursSansRedondance, 'tour', 'tours')} au lieu de ${tours}, aucune ne le serait`,
|
|
|
|
|
],
|
|
|
|
|
['diagnostic.remede.appartenances', "aucun nombre de tours plus petit ne l'annule : elle tient aux appartenances déclarées"],
|
|
|
|
|
['diagnostic.remede.animateurs', 'laisser les animateurs sans appartenance déclarée, ou leur en donner des distinctes'],
|
|
|
|
|
[
|
|
|
|
|
'diagnostic.remede.ancrage',
|
|
|
|
|
'retirer des réservations de portée « tous les tours » à cette table, ou lui ajouter des places, la remet en rotation',
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'diagnostic.remede.ecartItineraire',
|
|
|
|
|
"aucune relance ne le réduit : il tient aux tables pleines dont les capacités ou les ancrages diffèrent",
|
|
|
|
|
],
|
|
|
|
|
['diagnostic.remede.places', "ajouter des tables ou des places, ou exclure des personnes : d'ici là, la génération est refusée"],
|
|
|
|
|
['diagnostic.remede.plafond', 'seules les capacités et les réservations le changent : aucune relance ne le dépasse'],
|
[ADD] screens: tags on the card, table goals, priority editor, import
The operator now reaches tags, goals and priorities from the screens.
A person's card adds and removes tags, the participant list carries a
tag legend; each table takes an evening goal or one per round with its
rule; the generation settings hold a keyboard-operable priority editor
(move, join, split, restore, weights), the two optional criteria and the
goal mode; the proposals table and its ranking sentence follow the
order; the import screen reads a participants or a goals file. Removing
a tag or a goal returns focus to a neighbouring control.
Checked: node 4590, navigateur 942, node-long 124; captures republished.
--- FR ---
[ADD] écrans : étiquettes, objectifs des tables, priorités, import
L'opérateur atteint étiquettes, objectifs et priorités depuis les écrans.
La fiche ajoute et retire les étiquettes, la liste porte leur légende ;
chaque table reçoit un objectif de soirée ou par tour avec sa règle ; les
réglages de génération portent un éditeur des priorités utilisable au
clavier (monter, joindre, séparer, rétablir, poids), les deux critères
facultatifs et le mode des objectifs ; le tableau des propositions et sa
phrase suivent l'ordre ; l'import lit un fichier de personnes ou
d'objectifs. Retirer une étiquette ou un objectif rend le focus à côté.
Vérifié : node 4590, navigateur 942, longues 124 ; captures republiées.
Assisted-by: Claude Opus 5.5
2026-10-11 17:53:27 -04:00
|
|
|
[
|
|
|
|
|
'diagnostic.remede.objectifs',
|
|
|
|
|
"ajouter des places aux tables qui portent un objectif, ou donner un objectif à d'autres tables, abaisse ce plancher",
|
|
|
|
|
],
|
[ADD] interface: diagnostic — what a configuration makes unavoidable
Before generating, the operator must know what no plan can avoid: the
encounters a table size forces, the conflicts when every table holds
colleagues, the anchors that impose a return. The engine's diagnosis is
turned into sentences with their figures and their remedies, shown in its
section and, compact, beside the plan, whose banner states the floors
when every table is in conflict (§ 7.5).
Checked: 2425 node and 413 browser tests.
--- FR ---
[ADD] interface : diagnostic — ce qu'une configuration rend inévitable
Avant de générer, l'opérateur doit savoir ce qu'aucun plan n'évite : les
rencontres qu'une taille de table impose, les conflits quand chaque table
réunit des collègues, les ancrages qui imposent un retour. Le diagnostic du
moteur devient des phrases, avec leurs chiffres et leurs remèdes, montrées
dans sa section et, en compact, à côté du plan, dont le bandeau énonce les
planchers quand toutes les tables sont en conflit (§ 7.5).
Vérifié : 2425 node et 413 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:41:51 -04:00
|
|
|
['diagnostic.remede.imposes', 'les réservations les imposent : ils ne comptent pas parmi les retours que choisit le moteur'],
|
|
|
|
|
]);
|