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
155 lines
7.4 KiB
JavaScript
155 lines
7.4 KiB
JavaScript
// © 2026 TechnoLibre (http://www.technolibre.ca)
|
|
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
|
|
|
|
// 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.'],
|
|
// 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"],
|
|
|
|
// --- 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`,
|
|
],
|
|
|
|
// --- 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`,
|
|
],
|
|
|
|
// --- 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'],
|
|
[
|
|
'diagnostic.remede.objectifs',
|
|
"ajouter des places aux tables qui portent un objectif, ou donner un objectif à d'autres tables, abaisse ce plancher",
|
|
],
|
|
['diagnostic.remede.imposes', 'les réservations les imposent : ils ne comptent pas parmi les retours que choisit le moteur'],
|
|
]);
|