[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
// © 2026 TechnoLibre (http://www.technolibre.ca)
|
|
|
|
|
|
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
|
|
|
|
|
|
|
|
|
|
|
|
// Le modèle du tableau des propositions (§ 5.4, § 5.5, § 5.7, § 9, § 12.1,
|
|
|
|
|
|
// § 12.6, § 12.9), pur : SectionPropositions.svelte et
|
|
|
|
|
|
// TableauPropositions.svelte le câblent.
|
|
|
|
|
|
//
|
[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
|
|
|
|
// Le tableau lit la table d'évaluation d'evaluer (evaluation.js), la seule
|
|
|
|
|
|
// mesure : chaque cellule porte la valeur que la table rend, telle quelle, et
|
|
|
|
|
|
// sa clé de mise en forme ; aucune arithmétique ne s'y fait, aucun plafond
|
|
|
|
|
|
// ne s'y recompose. Des rencontres, il ne porte que le minimum, sur les trois
|
|
|
|
|
|
// populations du § 5.4 — tous, mobiles, ancrés —, en tête des colonnes de
|
|
|
|
|
|
// mesure ; la moyenne n'y entre pas. Le plafond réalisé, individuel, se lit
|
|
|
|
|
|
// par le manque, dont les cellules sont celles de troisChiffres. Les imposés
|
|
|
|
|
|
// se disent à part, sur chaque ligne, jamais ajoutés aux choisis.
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
//
|
|
|
|
|
|
// Chaque minimum affiché désigne la personne la plus mal servie (§ 12.1) :
|
|
|
|
|
|
// le moins de rencontres, d'appartenances vues, de diversité. La redondance
|
|
|
|
|
|
// r(p) va dans l'autre sens — plus elle est grande, pire est le sort —, et
|
|
|
|
|
|
// son minimum désignerait la personne la mieux servie : elle se lit par sa
|
|
|
|
|
|
// somme Σ r(p), la grandeur que la recherche et le classement lisent.
|
|
|
|
|
|
//
|
[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 des tables et les animateurs (A9, A11) forment un sixième
|
|
|
|
|
|
// groupe de colonnes, présentes chacune quand son critère compte — coché et
|
|
|
|
|
|
// avec un objet, tel que l'état des critères de la table le dit — : le
|
|
|
|
|
|
// tableau ne recalcule ni « sans objet » ni le mode, qu'il lit dans les
|
|
|
|
|
|
// valeurs que le critère des objectifs classe.
|
|
|
|
|
|
//
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
// Une cellule vaut { colonne, valeur, cle, decimales } : cle null, la valeur
|
|
|
|
|
|
// est un nombre que format.nombre écrit avec decimales chiffres après la
|
|
|
|
|
|
// virgule ; sinon le texte est t(cle) — « — » pour une population vide,
|
|
|
|
|
|
// « inconnu » pour une grandeur que l'a priori inconnu ne permet pas, le
|
|
|
|
|
|
// certificat en mots.
|
|
|
|
|
|
import { evaluer } from '../../application/evaluation.js';
|
|
|
|
|
|
import { nomAffiche } from '../../application/personnes.js';
|
|
|
|
|
|
|
|
|
|
|
|
const VIDE = 'format.vide';
|
|
|
|
|
|
const INCONNU = 'propositions.valeur.inconnu';
|
|
|
|
|
|
|
|
|
|
|
|
// Chaque colonne de mesure et la lecture de sa valeur dans une ligne
|
|
|
|
|
|
// comparable de la table d'évaluation, dans l'ordre d'affichage. La Map ne
|
|
|
|
|
|
// sert qu'à retrouver la lecture d'une colonne ; COLONNES fixe l'ordre.
|
|
|
|
|
|
const LECTURES = new Map([
|
|
|
|
|
|
['rencontresTous', (l) => l.mesures.aggRencontres.tous.min],
|
|
|
|
|
|
['rencontresMobiles', (l) => l.mesures.aggRencontres.mobiles.min],
|
|
|
|
|
|
['rencontresAncres', (l) => l.mesures.aggRencontres.ancres.min],
|
|
|
|
|
|
['collisionsCumulees', (l) => l.mesures.collisionsCumulees],
|
|
|
|
|
|
['pairesDistinctes', (l) => l.mesures.pairesDistinctes],
|
|
|
|
|
|
['excedentCollisions', (l) => l.mesures.excedentCollisions],
|
|
|
|
|
|
['rencontresRepetees', (l) => l.mesures.rencontresRepetees.choisies],
|
|
|
|
|
|
['maxRencontresPaire', (l) => l.mesures.maxRencontresPaire],
|
|
|
|
|
|
['retoursChoisis', (l) => l.mesures.totalRetoursChoisis],
|
|
|
|
|
|
['appartenancesVues', (l) => l.mesures.aggAppartenancesVues.tous.min],
|
|
|
|
|
|
['totalRedondance', (l) => l.mesures.totalRedondance],
|
|
|
|
|
|
['diversite', (l) => l.mesures.aggDiversite.tous.min],
|
|
|
|
|
|
['manqueMax', (l) => l.troisChiffres.manqueMax.tous],
|
|
|
|
|
|
['effectifManque', (l) => l.troisChiffres.effectifManque.tous],
|
|
|
|
|
|
['ecartItineraireMax', (l) => l.troisChiffres.ecartItineraireMax?.tous ?? null],
|
|
|
|
|
|
['ecartAuPlafondAPriori', (l) => l.ecartAuPlafondAPrioriMax],
|
[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
|
|
|
|
['jamaisServies', (l) => l.mesures.objectifs?.jamaisServies ?? null],
|
|
|
|
|
|
['horsObjectifMax', (l) => l.mesures.objectifs?.horsObjectifMax ?? null],
|
|
|
|
|
|
['toursHorsObjectif', (l) => l.mesures.objectifs?.horsObjectif ?? null],
|
|
|
|
|
|
['toursSelonObjectif', (l) => l.mesures.objectifs?.agregat.tous.min ?? null],
|
|
|
|
|
|
['animateursRencontres', (l) => l.mesures.animateurs?.agregat.tous.min ?? null],
|
|
|
|
|
|
['animateursNonRencontres', (l) => l.mesures.animateurs?.nonRencontres ?? null],
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
['certificat', (l) => l.minimumAtteint],
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
[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 colonnes que le tableau ne porte que sous une condition : [critère,
|
|
|
|
|
|
// valeur], la colonne présente quand le critère compte et, valeur non
|
|
|
|
|
|
// null, quand il classe cette valeur — les personnes jamais servies sous
|
|
|
|
|
|
// « chacun au moins une fois », le plus de tours hors objectif d'une
|
|
|
|
|
|
// personne sous le troisième mode. Toute autre colonne est toujours là. La
|
|
|
|
|
|
// Map ne sert qu'à retrouver la condition d'une colonne.
|
|
|
|
|
|
const SOUS_CONDITION = new Map([
|
|
|
|
|
|
['jamaisServies', ['toursHorsObjectif', 'jamaisServies']],
|
|
|
|
|
|
['horsObjectifMax', ['toursHorsObjectif', 'horsObjectifMax']],
|
|
|
|
|
|
['toursHorsObjectif', ['toursHorsObjectif', 'toursHorsObjectif']],
|
|
|
|
|
|
['toursSelonObjectif', ['toursHorsObjectif', null]],
|
|
|
|
|
|
['animateursRencontres', ['animateursNonRencontres', null]],
|
|
|
|
|
|
['animateursNonRencontres', ['animateursNonRencontres', 'animateursNonRencontres']],
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
// Les colonnes dont la valeur n'existe pas quand le plafond a priori est
|
|
|
|
|
|
// inconnu : elles s'écrivent « inconnu », jamais « — » (§ 12.6).
|
|
|
|
|
|
const SELON_A_PRIORI = new Set(['ecartItineraireMax', 'ecartAuPlafondAPriori']);
|
|
|
|
|
|
|
|
|
|
|
|
// Le taux de diversité, un rapport, se lit au centième ; les autres colonnes
|
|
|
|
|
|
// sont des comptes.
|
|
|
|
|
|
const DECIMALES = new Map([['diversite', 2]]);
|
|
|
|
|
|
|
[IMP] proposals, generation, badges, preview: cards and grouped headers
The proposal table had a dozen measure columns with no grouping. Five
group headers now gather neighbouring measures without changing any
column text; numbers align right in tabular figures, and the kept
placement row wears the Retenu tint and a « retenue » pill. Generation
settings and progress, badges and the paper choice become cards, each
paper a distinct choice; the preview toolbar groups its commands. The
printed paper is unchanged. Checked: node 172, browser 162.
--- FR ---
[IMP] propositions, génération, badges, aperçu : cartes, intitulés
Le tableau des propositions alignait une douzaine de mesures sans
groupe. Cinq intitulés de groupe réunissent les mesures voisines sans
changer le texte d'aucune colonne ; les nombres s'alignent à droite en
chiffres tabulaires, la ligne du retenu porte la teinte Retenu et une
pastille « retenue ». Réglages et avancement, badges et papier
deviennent des cartes, chaque papier un choix distinct ; la barre de
l'aperçu groupe ses commandes. Le papier imprimé ne change pas.
Vérifié : node 172, navigateur 162.
Assisted-by: Claude Opus 5.5
2026-10-11 00:58:07 -04:00
|
|
|
|
// Les colonnes dont les cellules sont du texte : toutes les autres portent
|
|
|
|
|
|
// un nombre, qui s'aligne à droite en chiffres tabulaires.
|
|
|
|
|
|
const TEXTUELLES = new Set(['proposition', 'certificat', 'imposes', 'commandes']);
|
|
|
|
|
|
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
/** Les colonnes du tableau, dans l'ordre d'affichage : le rang et
|
|
|
|
|
|
* l'identifiant, puis les mesures — les trois minimums des rencontres en
|
[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
|
|
|
|
* tête, celles des objectifs et des animateurs en dernier —, le certificat,
|
|
|
|
|
|
* les imposés et les commandes ; toutes celles qu'un tableau peut porter,
|
|
|
|
|
|
* tableau() rendant celles que porte le sien. Chacune porte son nom,
|
[IMP] proposals, generation, badges, preview: cards and grouped headers
The proposal table had a dozen measure columns with no grouping. Five
group headers now gather neighbouring measures without changing any
column text; numbers align right in tabular figures, and the kept
placement row wears the Retenu tint and a « retenue » pill. Generation
settings and progress, badges and the paper choice become cards, each
paper a distinct choice; the preview toolbar groups its commands. The
printed paper is unchanged. Checked: node 172, browser 162.
--- FR ---
[IMP] propositions, génération, badges, aperçu : cartes, intitulés
Le tableau des propositions alignait une douzaine de mesures sans
groupe. Cinq intitulés de groupe réunissent les mesures voisines sans
changer le texte d'aucune colonne ; les nombres s'alignent à droite en
chiffres tabulaires, la ligne du retenu porte la teinte Retenu et une
pastille « retenue ». Réglages et avancement, badges et papier
deviennent des cartes, chaque papier un choix distinct ; la barre de
l'aperçu groupe ses commandes. Le papier imprimé ne change pas.
Vérifié : node 172, navigateur 162.
Assisted-by: Claude Opus 5.5
2026-10-11 00:58:07 -04:00
|
|
|
|
* la clé de son en-tête, qui nomme son unité, celle de son explication,
|
[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
|
|
|
|
* le texte de l'infobulle de son en-tête et de la valeur appliquée qui la
|
|
|
|
|
|
* désigne, et nombre, vrai quand ses cellules portent un nombre. */
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
export const COLONNES = Object.freeze(
|
|
|
|
|
|
['rang', 'proposition', ...LECTURES.keys(), 'imposes', 'commandes'].map((nom) =>
|
[IMP] proposals, generation, badges, preview: cards and grouped headers
The proposal table had a dozen measure columns with no grouping. Five
group headers now gather neighbouring measures without changing any
column text; numbers align right in tabular figures, and the kept
placement row wears the Retenu tint and a « retenue » pill. Generation
settings and progress, badges and the paper choice become cards, each
paper a distinct choice; the preview toolbar groups its commands. The
printed paper is unchanged. Checked: node 172, browser 162.
--- FR ---
[IMP] propositions, génération, badges, aperçu : cartes, intitulés
Le tableau des propositions alignait une douzaine de mesures sans
groupe. Cinq intitulés de groupe réunissent les mesures voisines sans
changer le texte d'aucune colonne ; les nombres s'alignent à droite en
chiffres tabulaires, la ligne du retenu porte la teinte Retenu et une
pastille « retenue ». Réglages et avancement, badges et papier
deviennent des cartes, chaque papier un choix distinct ; la barre de
l'aperçu groupe ses commandes. Le papier imprimé ne change pas.
Vérifié : node 172, navigateur 162.
Assisted-by: Claude Opus 5.5
2026-10-11 00:58:07 -04:00
|
|
|
|
Object.freeze({ nom, cle: `propositions.colonne.${nom}`, explication: `propositions.explication.${nom}`, nombre: !TEXTUELLES.has(nom) }),
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
),
|
|
|
|
|
|
);
|
|
|
|
|
|
|
[IMP] proposals, generation, badges, preview: cards and grouped headers
The proposal table had a dozen measure columns with no grouping. Five
group headers now gather neighbouring measures without changing any
column text; numbers align right in tabular figures, and the kept
placement row wears the Retenu tint and a « retenue » pill. Generation
settings and progress, badges and the paper choice become cards, each
paper a distinct choice; the preview toolbar groups its commands. The
printed paper is unchanged. Checked: node 172, browser 162.
--- FR ---
[IMP] propositions, génération, badges, aperçu : cartes, intitulés
Le tableau des propositions alignait une douzaine de mesures sans
groupe. Cinq intitulés de groupe réunissent les mesures voisines sans
changer le texte d'aucune colonne ; les nombres s'alignent à droite en
chiffres tabulaires, la ligne du retenu porte la teinte Retenu et une
pastille « retenue ». Réglages et avancement, badges et papier
deviennent des cartes, chaque papier un choix distinct ; la barre de
l'aperçu groupe ses commandes. Le papier imprimé ne change pas.
Vérifié : node 172, navigateur 162.
Assisted-by: Claude Opus 5.5
2026-10-11 00:58:07 -04:00
|
|
|
|
// Les groupes d'en-têtes : chacun nomme des colonnes de mesure voisines dans
|
|
|
|
|
|
// COLONNES, sous la clé propositions.groupe.<nom>.
|
|
|
|
|
|
const GROUPES = [
|
|
|
|
|
|
['rencontres', ['rencontresTous', 'rencontresMobiles', 'rencontresAncres']],
|
|
|
|
|
|
['collisions', ['collisionsCumulees', 'pairesDistinctes', 'excedentCollisions']],
|
|
|
|
|
|
['repetitions', ['rencontresRepetees', 'maxRencontresPaire', 'retoursChoisis']],
|
|
|
|
|
|
['diversite', ['appartenancesVues', 'totalRedondance', 'diversite']],
|
|
|
|
|
|
['manque', ['manqueMax', 'effectifManque', 'ecartItineraireMax', 'ecartAuPlafondAPriori']],
|
[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
|
|
|
|
['objectifs', ['jamaisServies', 'horsObjectifMax', 'toursHorsObjectif', 'toursSelonObjectif', 'animateursRencontres', 'animateursNonRencontres']],
|
[IMP] proposals, generation, badges, preview: cards and grouped headers
The proposal table had a dozen measure columns with no grouping. Five
group headers now gather neighbouring measures without changing any
column text; numbers align right in tabular figures, and the kept
placement row wears the Retenu tint and a « retenue » pill. Generation
settings and progress, badges and the paper choice become cards, each
paper a distinct choice; the preview toolbar groups its commands. The
printed paper is unchanged. Checked: node 172, browser 162.
--- FR ---
[IMP] propositions, génération, badges, aperçu : cartes, intitulés
Le tableau des propositions alignait une douzaine de mesures sans
groupe. Cinq intitulés de groupe réunissent les mesures voisines sans
changer le texte d'aucune colonne ; les nombres s'alignent à droite en
chiffres tabulaires, la ligne du retenu porte la teinte Retenu et une
pastille « retenue ». Réglages et avancement, badges et papier
deviennent des cartes, chaque papier un choix distinct ; la barre de
l'aperçu groupe ses commandes. Le papier imprimé ne change pas.
Vérifié : node 172, navigateur 162.
Assisted-by: Claude Opus 5.5
2026-10-11 00:58:07 -04:00
|
|
|
|
];
|
|
|
|
|
|
|
[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 segments de la rangée des groupes sur les colonnes noms, une suite de
|
|
|
|
|
|
// COLONNES : un groupe couvre celles de ses colonnes que noms porte d'un seul
|
|
|
|
|
|
// segment, une colonne hors groupe forme le sien, sans clé ; un groupe dont
|
|
|
|
|
|
// noms ne porte aucune colonne n'a pas de segment. Un groupe dont les
|
|
|
|
|
|
// colonnes ne se suivent pas dans noms lève : au chargement du module pour
|
|
|
|
|
|
// COLONNES entier.
|
|
|
|
|
|
function segmenter(noms) {
|
[IMP] proposals, generation, badges, preview: cards and grouped headers
The proposal table had a dozen measure columns with no grouping. Five
group headers now gather neighbouring measures without changing any
column text; numbers align right in tabular figures, and the kept
placement row wears the Retenu tint and a « retenue » pill. Generation
settings and progress, badges and the paper choice become cards, each
paper a distinct choice; the preview toolbar groups its commands. The
printed paper is unchanged. Checked: node 172, browser 162.
--- FR ---
[IMP] propositions, génération, badges, aperçu : cartes, intitulés
Le tableau des propositions alignait une douzaine de mesures sans
groupe. Cinq intitulés de groupe réunissent les mesures voisines sans
changer le texte d'aucune colonne ; les nombres s'alignent à droite en
chiffres tabulaires, la ligne du retenu porte la teinte Retenu et une
pastille « retenue ». Réglages et avancement, badges et papier
deviennent des cartes, chaque papier un choix distinct ; la barre de
l'aperçu groupe ses commandes. Le papier imprimé ne change pas.
Vérifié : node 172, navigateur 162.
Assisted-by: Claude Opus 5.5
2026-10-11 00:58:07 -04:00
|
|
|
|
const segments = [];
|
|
|
|
|
|
for (let rang = 0; rang < noms.length; ) {
|
[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
|
|
|
|
const groupe = GROUPES.find(([, colonnes]) => colonnes.includes(noms[rang]));
|
[IMP] proposals, generation, badges, preview: cards and grouped headers
The proposal table had a dozen measure columns with no grouping. Five
group headers now gather neighbouring measures without changing any
column text; numbers align right in tabular figures, and the kept
placement row wears the Retenu tint and a « retenue » pill. Generation
settings and progress, badges and the paper choice become cards, each
paper a distinct choice; the preview toolbar groups its commands. The
printed paper is unchanged. Checked: node 172, browser 162.
--- FR ---
[IMP] propositions, génération, badges, aperçu : cartes, intitulés
Le tableau des propositions alignait une douzaine de mesures sans
groupe. Cinq intitulés de groupe réunissent les mesures voisines sans
changer le texte d'aucune colonne ; les nombres s'alignent à droite en
chiffres tabulaires, la ligne du retenu porte la teinte Retenu et une
pastille « retenue ». Réglages et avancement, badges et papier
deviennent des cartes, chaque papier un choix distinct ; la barre de
l'aperçu groupe ses commandes. Le papier imprimé ne change pas.
Vérifié : node 172, navigateur 162.
Assisted-by: Claude Opus 5.5
2026-10-11 00:58:07 -04:00
|
|
|
|
if (groupe === undefined) {
|
|
|
|
|
|
segments.push({ cle: null, colonnes: [noms[rang]] });
|
|
|
|
|
|
rang += 1;
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
const [nom, colonnes] = groupe;
|
[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
|
|
|
|
const portees = colonnes.filter((colonne) => noms.includes(colonne));
|
|
|
|
|
|
portees.forEach((colonne, decalage) => {
|
[IMP] proposals, generation, badges, preview: cards and grouped headers
The proposal table had a dozen measure columns with no grouping. Five
group headers now gather neighbouring measures without changing any
column text; numbers align right in tabular figures, and the kept
placement row wears the Retenu tint and a « retenue » pill. Generation
settings and progress, badges and the paper choice become cards, each
paper a distinct choice; the preview toolbar groups its commands. The
printed paper is unchanged. Checked: node 172, browser 162.
--- FR ---
[IMP] propositions, génération, badges, aperçu : cartes, intitulés
Le tableau des propositions alignait une douzaine de mesures sans
groupe. Cinq intitulés de groupe réunissent les mesures voisines sans
changer le texte d'aucune colonne ; les nombres s'alignent à droite en
chiffres tabulaires, la ligne du retenu porte la teinte Retenu et une
pastille « retenue ». Réglages et avancement, badges et papier
deviennent des cartes, chaque papier un choix distinct ; la barre de
l'aperçu groupe ses commandes. Le papier imprimé ne change pas.
Vérifié : node 172, navigateur 162.
Assisted-by: Claude Opus 5.5
2026-10-11 00:58:07 -04:00
|
|
|
|
if (noms[rang + decalage] !== colonne) throw new Error(`groupe ${nom} : colonnes non voisines`);
|
|
|
|
|
|
});
|
[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
|
|
|
|
segments.push({ cle: `propositions.groupe.${nom}`, colonnes: portees });
|
|
|
|
|
|
rang += portees.length;
|
[IMP] proposals, generation, badges, preview: cards and grouped headers
The proposal table had a dozen measure columns with no grouping. Five
group headers now gather neighbouring measures without changing any
column text; numbers align right in tabular figures, and the kept
placement row wears the Retenu tint and a « retenue » pill. Generation
settings and progress, badges and the paper choice become cards, each
paper a distinct choice; the preview toolbar groups its commands. The
printed paper is unchanged. Checked: node 172, browser 162.
--- FR ---
[IMP] propositions, génération, badges, aperçu : cartes, intitulés
Le tableau des propositions alignait une douzaine de mesures sans
groupe. Cinq intitulés de groupe réunissent les mesures voisines sans
changer le texte d'aucune colonne ; les nombres s'alignent à droite en
chiffres tabulaires, la ligne du retenu porte la teinte Retenu et une
pastille « retenue ». Réglages et avancement, badges et papier
deviennent des cartes, chaque papier un choix distinct ; la barre de
l'aperçu groupe ses commandes. Le papier imprimé ne change pas.
Vérifié : node 172, navigateur 162.
Assisted-by: Claude Opus 5.5
2026-10-11 00:58:07 -04:00
|
|
|
|
}
|
[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
|
|
|
|
return Object.freeze(
|
|
|
|
|
|
segments.map(({ cle, colonnes }) => Object.freeze({ cle, etendue: colonnes.length, colonnes: Object.freeze([...colonnes]) })),
|
|
|
|
|
|
);
|
[IMP] proposals, generation, badges, preview: cards and grouped headers
The proposal table had a dozen measure columns with no grouping. Five
group headers now gather neighbouring measures without changing any
column text; numbers align right in tabular figures, and the kept
placement row wears the Retenu tint and a « retenue » pill. Generation
settings and progress, badges and the paper choice become cards, each
paper a distinct choice; the preview toolbar groups its commands. The
printed paper is unchanged. Checked: node 172, browser 162.
--- FR ---
[IMP] propositions, génération, badges, aperçu : cartes, intitulés
Le tableau des propositions alignait une douzaine de mesures sans
groupe. Cinq intitulés de groupe réunissent les mesures voisines sans
changer le texte d'aucune colonne ; les nombres s'alignent à droite en
chiffres tabulaires, la ligne du retenu porte la teinte Retenu et une
pastille « retenue ». Réglages et avancement, badges et papier
deviennent des cartes, chaque papier un choix distinct ; la barre de
l'aperçu groupe ses commandes. Le papier imprimé ne change pas.
Vérifié : node 172, navigateur 162.
Assisted-by: Claude Opus 5.5
2026-10-11 00:58:07 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
[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
|
|
|
|
/** La rangée des groupes d'en-têtes de COLONNES entier, au-dessus de celle
|
|
|
|
|
|
* des colonnes : { cle, etendue, colonnes } par segment, dans l'ordre de
|
|
|
|
|
|
* COLONNES — cle, la clé du libellé du groupe, null pour une colonne hors
|
|
|
|
|
|
* groupe ; etendue, le nombre de colonnes couvertes ; colonnes, leurs noms.
|
|
|
|
|
|
* Les segments couvrent chaque colonne une fois. tableau() rend ceux des
|
|
|
|
|
|
* colonnes que porte le sien. */
|
|
|
|
|
|
export const GROUPES_COLONNES = segmenter(COLONNES.map(({ nom }) => nom));
|
|
|
|
|
|
|
|
|
|
|
|
// Les colonnes que porte le tableau d'une table d'évaluation, dans l'ordre de
|
|
|
|
|
|
// COLONNES : chacune hors de SOUS_CONDITION, et celles dont la condition
|
|
|
|
|
|
// tient sur l'état des critères de la table, {nom, coche, sansObjet,
|
|
|
|
|
|
// valeurs}. Un critère compte quand il est coché et a un objet.
|
|
|
|
|
|
function colonnesPortees(criteres) {
|
|
|
|
|
|
const comptent = new Map(criteres.filter(({ coche, sansObjet }) => coche && !sansObjet).map(({ nom, valeurs }) => [nom, valeurs]));
|
|
|
|
|
|
return COLONNES.filter(({ nom }) => {
|
|
|
|
|
|
const condition = SOUS_CONDITION.get(nom);
|
|
|
|
|
|
if (condition === undefined) return true;
|
|
|
|
|
|
const [critere, valeur] = condition;
|
|
|
|
|
|
const valeurs = comptent.get(critere);
|
|
|
|
|
|
return valeurs !== undefined && (valeur === null || valeurs.includes(valeur));
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
[IMP] proposals, generation, badges, preview: cards and grouped headers
The proposal table had a dozen measure columns with no grouping. Five
group headers now gather neighbouring measures without changing any
column text; numbers align right in tabular figures, and the kept
placement row wears the Retenu tint and a « retenue » pill. Generation
settings and progress, badges and the paper choice become cards, each
paper a distinct choice; the preview toolbar groups its commands. The
printed paper is unchanged. Checked: node 172, browser 162.
--- FR ---
[IMP] propositions, génération, badges, aperçu : cartes, intitulés
Le tableau des propositions alignait une douzaine de mesures sans
groupe. Cinq intitulés de groupe réunissent les mesures voisines sans
changer le texte d'aucune colonne ; les nombres s'alignent à droite en
chiffres tabulaires, la ligne du retenu porte la teinte Retenu et une
pastille « retenue ». Réglages et avancement, badges et papier
deviennent des cartes, chaque papier un choix distinct ; la barre de
l'aperçu groupe ses commandes. Le papier imprimé ne change pas.
Vérifié : node 172, navigateur 162.
Assisted-by: Claude Opus 5.5
2026-10-11 00:58:07 -04:00
|
|
|
|
|
[ADD] propositions: explanation tooltips on criteria and column headers
The propositions table names its measures with the glossary's terms, which
an organiser cannot be expected to know. Each ranking criterion of the
order sentence and each column header now shows a short explanation on
hover or keyboard focus: what the number counts and whether lower or
higher is better, written from the spec and the engine. The tooltip is a
reusable primitive, read through aria-describedby, kept in the window,
never over its word, closed by Escape; the rendering guards measure it.
Checked: 2882 node, 592 browser tests, from the index alone.
--- FR ---
[ADD] propositions : infobulles d'explication des critères et colonnes
Le tableau des propositions nomme ses mesures par les termes du glossaire,
qu'un organisateur n'a pas à connaître. Chaque critère de la phrase de
l'ordre et chaque en-tête de colonne montre une courte explication au
survol ou au focus : ce que compte le nombre, et s'il vaut mieux bas ou
haut, écrite d'après le spec et le moteur. L'infobulle est une primitive
réutilisable, lue par aria-describedby, gardée dans la fenêtre, jamais sur
son mot, fermée par Échap ; les gardes du rendu la mesurent.
Vérifié : 2882 node, 592 navigateur, depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-08 04:56:52 -04:00
|
|
|
|
/**
|
|
|
|
|
|
* La clé de l'explication d'une colonne : le texte de l'infobulle de son
|
[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
|
|
|
|
* en-tête, et celui du nom qui la désigne dans la phrase de l'ordre
|
|
|
|
|
|
* (colonneDeValeur) — une valeur appliquée et sa colonne partagent la même.
|
[ADD] propositions: explanation tooltips on criteria and column headers
The propositions table names its measures with the glossary's terms, which
an organiser cannot be expected to know. Each ranking criterion of the
order sentence and each column header now shows a short explanation on
hover or keyboard focus: what the number counts and whether lower or
higher is better, written from the spec and the engine. The tooltip is a
reusable primitive, read through aria-describedby, kept in the window,
never over its word, closed by Escape; the rendering guards measure it.
Checked: 2882 node, 592 browser tests, from the index alone.
--- FR ---
[ADD] propositions : infobulles d'explication des critères et colonnes
Le tableau des propositions nomme ses mesures par les termes du glossaire,
qu'un organisateur n'a pas à connaître. Chaque critère de la phrase de
l'ordre et chaque en-tête de colonne montre une courte explication au
survol ou au focus : ce que compte le nombre, et s'il vaut mieux bas ou
haut, écrite d'après le spec et le moteur. L'infobulle est une primitive
réutilisable, lue par aria-describedby, gardée dans la fenêtre, jamais sur
son mot, fermée par Échap ; les gardes du rendu la mesurent.
Vérifié : 2882 node, 592 navigateur, depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-08 04:56:52 -04:00
|
|
|
|
* Lève TypeError pour un nom qui n'est pas une colonne de COLONNES.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string} nom le nom d'une colonne
|
|
|
|
|
|
* @returns {string}
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function explicationDeColonne(nom) {
|
|
|
|
|
|
const colonne = COLONNES.find((candidate) => candidate.nom === nom);
|
|
|
|
|
|
if (colonne === undefined) throw new TypeError(`colonne inconnue : ${nom}`);
|
|
|
|
|
|
return colonne.explication;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
// Une cellule de nombre : null s'écrit « — ».
|
|
|
|
|
|
const nombre = (colonne, valeur) => ({
|
|
|
|
|
|
colonne,
|
|
|
|
|
|
valeur,
|
|
|
|
|
|
cle: valeur === null ? VIDE : null,
|
|
|
|
|
|
decimales: DECIMALES.get(colonne) ?? 0,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// Le certificat en mots (§ 5.5) : « minimum atteint » quand minimumAtteint
|
|
|
|
|
|
// est vrai ; « atteignabilité inconnue » quand il est faux, ou null faute de
|
|
|
|
|
|
// plafond a priori ; « — » sur une population vide.
|
|
|
|
|
|
function certificat(ligne) {
|
|
|
|
|
|
const valeur = ligne.minimumAtteint;
|
|
|
|
|
|
let cle = 'propositions.certificat.inconnue';
|
|
|
|
|
|
if (valeur === true) cle = 'propositions.certificat.atteint';
|
|
|
|
|
|
else if (ligne.mesures.rencontres.length === 0) cle = VIDE;
|
|
|
|
|
|
return { colonne: 'certificat', valeur, cle, decimales: 0 };
|
|
|
|
|
|
}
|
|
|
|
|
|
|
[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 cellules de mesure d'une ligne comparable, une par colonne de mesure
|
|
|
|
|
|
// portée, dans l'ordre de LECTURES. L'a priori est inconnu quand
|
|
|
|
|
|
// troisChiffres ne porte pas d'écart d'itinéraire du tout.
|
|
|
|
|
|
function cellules(ligne, portees) {
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
const inconnu = ligne.troisChiffres.ecartItineraireMax === null;
|
[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
|
|
|
|
return [...LECTURES].filter(([colonne]) => portees.has(colonne)).map(([colonne, lire]) => {
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
if (colonne === 'certificat') return certificat(ligne);
|
|
|
|
|
|
if (inconnu && SELON_A_PRIORI.has(colonne)) return { colonne, valeur: null, cle: INCONNU, decimales: 0 };
|
|
|
|
|
|
return nombre(colonne, lire(ligne));
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Ce que les réservations imposent, énoncé à part (§ 5.4) : les retours et
|
|
|
|
|
|
// les ancrages qui les imposent, les mêmes pour toute ligne ; les rencontres
|
|
|
|
|
|
// répétées imposées, propres au plan.
|
|
|
|
|
|
const imposes = (ligne, { retours, ancrages }) => [
|
|
|
|
|
|
{ cle: 'propositions.imposes.retours', details: { retours, ancrages } },
|
|
|
|
|
|
{ cle: 'propositions.imposes.repetees', details: { repetees: ligne.mesures.rencontresRepetees.imposees } },
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
// Un code et ses détails : une raison de dérive, une faute, une violation.
|
|
|
|
|
|
const codeDe = (raison) => ({ cle: raison.code, details: raison });
|
|
|
|
|
|
|
|
|
|
|
|
// Une raison de dérive : son code, ses détails, et la personne qu'elle nomme,
|
|
|
|
|
|
// null quand elle n'en nomme aucune.
|
|
|
|
|
|
const raisonDe = (raison) => ({ ...codeDe(raison), participant: raison.participant ?? null });
|
|
|
|
|
|
|
|
|
|
|
|
// La ligne d'un placement mesuré, ou celle d'un placement hors classement.
|
[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
|
|
|
|
// portees : les noms des colonnes que porte le tableau ; rang : la place
|
|
|
|
|
|
// dans le classement, à partir de 1 ; null hors classement et pour le
|
|
|
|
|
|
// retenu.
|
|
|
|
|
|
function ligneDe(ligne, table, idRetenu, portees, rang = null) {
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
const retenue = ligne.id === idRetenu;
|
|
|
|
|
|
if (ligne.statut !== 'comparable') {
|
|
|
|
|
|
return {
|
|
|
|
|
|
id: ligne.id,
|
|
|
|
|
|
rang: null,
|
|
|
|
|
|
retenue,
|
|
|
|
|
|
comparable: false,
|
|
|
|
|
|
statut: `propositions.statut.${ligne.statut}`,
|
|
|
|
|
|
raisons: ligne.raisons.map(raisonDe),
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
return {
|
|
|
|
|
|
id: ligne.id,
|
|
|
|
|
|
rang,
|
|
|
|
|
|
retenue,
|
|
|
|
|
|
comparable: true,
|
[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
|
|
|
|
cellules: cellules(ligne, portees),
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
imposes: imposes(ligne, table.imposes),
|
|
|
|
|
|
violations: ligne.violations.map(codeDe),
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
[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
|
|
|
|
// La colonne que désigne chaque valeur qui classe (§ 5.7, A11) : celle qui
|
|
|
|
|
|
// la porte ; l'identifiant croissant, le dernier départage, désigne la
|
|
|
|
|
|
// colonne des propositions. La Map ne sert qu'à retrouver la colonne d'une
|
|
|
|
|
|
// valeur ; la phrase suit l'ordre que le classement rend.
|
|
|
|
|
|
const COLONNE_DE_VALEUR = new Map([
|
[ADD] propositions: a ranking criterion highlights its table column
The order sentence names the ranking criteria, but nothing tied a name to
the column holding its value. Each criterion name, and « l'identifiant
croissant », now highlights its column when hovered or focused: the header
and every cell get heavier side borders and the header an underline, so
text contrast is unchanged and the cue is not colour alone. The mapping
from criterion to column lives in the propositions model, and a criterion
without a column fails there. The sentence still reads word for word.
Checked: 2780 node, 554 browser tests, from the index alone.
--- FR ---
[ADD] propositions : un critère du classement surligne sa colonne
La phrase de l'ordre nomme les critères, mais rien ne reliait un nom à la
colonne qui porte sa valeur. Chaque nom de critère, et « l'identifiant
croissant », surligne maintenant sa colonne au survol ou au focus : l'en-
tête et chaque cellule prennent des bords latéraux plus épais et l'en-tête
un soulignement ; le contraste du texte ne change pas, le signe ne tient
pas qu'à la couleur. Le lien critère-colonne vit dans le modèle, et un
critère sans colonne y lève. La phrase se lit mot pour mot comme avant.
Vérifié : 2780 node, 554 navigateur, depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-08 03:39:25 -04:00
|
|
|
|
['ecartAuPlafondAPrioriMax', 'ecartAuPlafondAPriori'],
|
|
|
|
|
|
['excedentCollisions', 'excedentCollisions'],
|
|
|
|
|
|
['collisionsCumulees', 'collisionsCumulees'],
|
[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
|
|
|
|
['jamaisServies', 'jamaisServies'],
|
|
|
|
|
|
['horsObjectifMax', 'horsObjectifMax'],
|
|
|
|
|
|
['toursHorsObjectif', 'toursHorsObjectif'],
|
|
|
|
|
|
['rencontresRepeteesChoisies', 'rencontresRepetees'],
|
|
|
|
|
|
['retoursChoisis', 'retoursChoisis'],
|
|
|
|
|
|
['animateursNonRencontres', 'animateursNonRencontres'],
|
[ADD] propositions: a ranking criterion highlights its table column
The order sentence names the ranking criteria, but nothing tied a name to
the column holding its value. Each criterion name, and « l'identifiant
croissant », now highlights its column when hovered or focused: the header
and every cell get heavier side borders and the header an underline, so
text contrast is unchanged and the cue is not colour alone. The mapping
from criterion to column lives in the propositions model, and a criterion
without a column fails there. The sentence still reads word for word.
Checked: 2780 node, 554 browser tests, from the index alone.
--- FR ---
[ADD] propositions : un critère du classement surligne sa colonne
La phrase de l'ordre nomme les critères, mais rien ne reliait un nom à la
colonne qui porte sa valeur. Chaque nom de critère, et « l'identifiant
croissant », surligne maintenant sa colonne au survol ou au focus : l'en-
tête et chaque cellule prennent des bords latéraux plus épais et l'en-tête
un soulignement ; le contraste du texte ne change pas, le signe ne tient
pas qu'à la couleur. Le lien critère-colonne vit dans le modèle, et un
critère sans colonne y lève. La phrase se lit mot pour mot comme avant.
Vérifié : 2780 node, 554 navigateur, depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-08 03:39:25 -04:00
|
|
|
|
['redondance', 'totalRedondance'],
|
|
|
|
|
|
['identifiant', 'proposition'],
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
[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
|
|
|
|
* La colonne du tableau que désigne une valeur qui classe (valeursQuiClassent,
|
|
|
|
|
|
* criteres.js), ou 'identifiant', le dernier départage, qui désigne la
|
|
|
|
|
|
* colonne des propositions. Lève TypeError pour un nom que la table ne
|
|
|
|
|
|
* connaît pas : une valeur ajoutée au classement doit dire laquelle elle
|
|
|
|
|
|
* compare.
|
[ADD] propositions: a ranking criterion highlights its table column
The order sentence names the ranking criteria, but nothing tied a name to
the column holding its value. Each criterion name, and « l'identifiant
croissant », now highlights its column when hovered or focused: the header
and every cell get heavier side borders and the header an underline, so
text contrast is unchanged and the cue is not colour alone. The mapping
from criterion to column lives in the propositions model, and a criterion
without a column fails there. The sentence still reads word for word.
Checked: 2780 node, 554 browser tests, from the index alone.
--- FR ---
[ADD] propositions : un critère du classement surligne sa colonne
La phrase de l'ordre nomme les critères, mais rien ne reliait un nom à la
colonne qui porte sa valeur. Chaque nom de critère, et « l'identifiant
croissant », surligne maintenant sa colonne au survol ou au focus : l'en-
tête et chaque cellule prennent des bords latéraux plus épais et l'en-tête
un soulignement ; le contraste du texte ne change pas, le signe ne tient
pas qu'à la couleur. Le lien critère-colonne vit dans le modèle, et un
critère sans colonne y lève. La phrase se lit mot pour mot comme avant.
Vérifié : 2780 node, 554 navigateur, depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-08 03:39:25 -04:00
|
|
|
|
*
|
[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
|
|
|
|
* @param {string} valeur une valeur qui classe, ou 'identifiant'
|
|
|
|
|
|
* @returns {string} le nom d'une colonne de COLONNES
|
[ADD] propositions: a ranking criterion highlights its table column
The order sentence names the ranking criteria, but nothing tied a name to
the column holding its value. Each criterion name, and « l'identifiant
croissant », now highlights its column when hovered or focused: the header
and every cell get heavier side borders and the header an underline, so
text contrast is unchanged and the cue is not colour alone. The mapping
from criterion to column lives in the propositions model, and a criterion
without a column fails there. The sentence still reads word for word.
Checked: 2780 node, 554 browser tests, from the index alone.
--- FR ---
[ADD] propositions : un critère du classement surligne sa colonne
La phrase de l'ordre nomme les critères, mais rien ne reliait un nom à la
colonne qui porte sa valeur. Chaque nom de critère, et « l'identifiant
croissant », surligne maintenant sa colonne au survol ou au focus : l'en-
tête et chaque cellule prennent des bords latéraux plus épais et l'en-tête
un soulignement ; le contraste du texte ne change pas, le signe ne tient
pas qu'à la couleur. Le lien critère-colonne vit dans le modèle, et un
critère sans colonne y lève. La phrase se lit mot pour mot comme avant.
Vérifié : 2780 node, 554 navigateur, depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-08 03:39:25 -04:00
|
|
|
|
*/
|
[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
|
|
|
|
export function colonneDeValeur(valeur) {
|
|
|
|
|
|
const colonne = COLONNE_DE_VALEUR.get(valeur);
|
|
|
|
|
|
if (colonne === undefined) throw new TypeError(`valeur sans colonne : ${valeur}`);
|
[ADD] propositions: a ranking criterion highlights its table column
The order sentence names the ranking criteria, but nothing tied a name to
the column holding its value. Each criterion name, and « l'identifiant
croissant », now highlights its column when hovered or focused: the header
and every cell get heavier side borders and the header an underline, so
text contrast is unchanged and the cue is not colour alone. The mapping
from criterion to column lives in the propositions model, and a criterion
without a column fails there. The sentence still reads word for word.
Checked: 2780 node, 554 browser tests, from the index alone.
--- FR ---
[ADD] propositions : un critère du classement surligne sa colonne
La phrase de l'ordre nomme les critères, mais rien ne reliait un nom à la
colonne qui porte sa valeur. Chaque nom de critère, et « l'identifiant
croissant », surligne maintenant sa colonne au survol ou au focus : l'en-
tête et chaque cellule prennent des bords latéraux plus épais et l'en-tête
un soulignement ; le contraste du texte ne change pas, le signe ne tient
pas qu'à la couleur. Le lien critère-colonne vit dans le modèle, et un
critère sans colonne y lève. La phrase se lit mot pour mot comme avant.
Vérifié : 2780 node, 554 navigateur, depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-08 03:39:25 -04:00
|
|
|
|
return colonne;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Un morceau de phrase : un texte de liaison, ou un nom qui désigne une
|
[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
|
|
|
|
// colonne — celui d'une valeur appliquée, sous la clé
|
|
|
|
|
|
// moteur.valeur.<valeur>, avec le critère qui la classe.
|
|
|
|
|
|
const liaison = (cle, details = {}) => ({ cle, details, critere: null, valeur: null, colonne: null });
|
|
|
|
|
|
const designant = (critere, valeur, cle = `moteur.valeur.${valeur}`) => ({ cle, details: {}, critere, valeur, colonne: colonneDeValeur(valeur) });
|
|
|
|
|
|
|
|
|
|
|
|
// Des listes de morceaux mises bout à bout, le morceau separateur entre deux.
|
|
|
|
|
|
const joindre = (listes, separateur) => listes.flatMap((morceaux, rang) => (rang === 0 ? morceaux : [separateur(), ...morceaux]));
|
|
|
|
|
|
|
|
|
|
|
|
// Les noms d'un critère appliqué, {nom, valeurs, poids} : chaque valeur
|
|
|
|
|
|
// qu'il classe, dans l'ordre, séparées par « puis » comme deux paliers.
|
|
|
|
|
|
const nomsDuCritere = ({ nom, valeurs }) =>
|
|
|
|
|
|
joindre(
|
|
|
|
|
|
valeurs.map((valeur) => [designant(nom, valeur)]),
|
|
|
|
|
|
() => liaison('propositions.ordre.separateur'),
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// Un palier appliqué en morceaux : les noms de son critère, seul ; pour un
|
|
|
|
|
|
// palier partagé, « ensemble, » puis chaque critère suivi de son poids,
|
|
|
|
|
|
// séparés par une virgule.
|
|
|
|
|
|
function palierEnMorceaux({ criteres }) {
|
|
|
|
|
|
if (criteres.length === 1) return nomsDuCritere(criteres[0]);
|
|
|
|
|
|
return [
|
|
|
|
|
|
liaison('propositions.ordre.ensemble'),
|
|
|
|
|
|
...joindre(
|
|
|
|
|
|
criteres.map((critere) => [...nomsDuCritere(critere), liaison('propositions.ordre.poids', { poids: critere.poids })]),
|
|
|
|
|
|
() => liaison('propositions.ordre.virgule'),
|
|
|
|
|
|
),
|
[ADD] propositions: a ranking criterion highlights its table column
The order sentence names the ranking criteria, but nothing tied a name to
the column holding its value. Each criterion name, and « l'identifiant
croissant », now highlights its column when hovered or focused: the header
and every cell get heavier side borders and the header an underline, so
text contrast is unchanged and the cue is not colour alone. The mapping
from criterion to column lives in the propositions model, and a criterion
without a column fails there. The sentence still reads word for word.
Checked: 2780 node, 554 browser tests, from the index alone.
--- FR ---
[ADD] propositions : un critère du classement surligne sa colonne
La phrase de l'ordre nomme les critères, mais rien ne reliait un nom à la
colonne qui porte sa valeur. Chaque nom de critère, et « l'identifiant
croissant », surligne maintenant sa colonne au survol ou au focus : l'en-
tête et chaque cellule prennent des bords latéraux plus épais et l'en-tête
un soulignement ; le contraste du texte ne change pas, le signe ne tient
pas qu'à la couleur. Le lien critère-colonne vit dans le modèle, et un
critère sans colonne y lève. La phrase se lit mot pour mot comme avant.
Vérifié : 2780 node, 554 navigateur, depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-08 03:39:25 -04:00
|
|
|
|
];
|
[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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// La phrase des critères appliqués, morceau par morceau (A11) : le début,
|
|
|
|
|
|
// chaque palier appliqué dans l'ordre, puis l'identifiant croissant, séparés
|
|
|
|
|
|
// par « puis », et la fin. Chaque nom est celui de la valeur que le palier
|
|
|
|
|
|
// applique — « retours » pour les rencontres répétées sous « nouvelle
|
|
|
|
|
|
// table » seule. Sous l'ordre par défaut et les quatre cases cochées, sans
|
|
|
|
|
|
// objectif ni case des animateurs, chaque palier porte un critère qui
|
|
|
|
|
|
// classe une valeur du nom de son critère, et les morceaux traduits bout à
|
|
|
|
|
|
// bout composent le texte de propositions.ordre.criteres, celui de l'ordre
|
|
|
|
|
|
// fixe de référence.
|
|
|
|
|
|
function phraseDesCriteres(criteresAppliques) {
|
|
|
|
|
|
const paliers = [...criteresAppliques.map(palierEnMorceaux), [designant('identifiant', 'identifiant', 'propositions.ordre.identifiant')]];
|
[ADD] propositions: a ranking criterion highlights its table column
The order sentence names the ranking criteria, but nothing tied a name to
the column holding its value. Each criterion name, and « l'identifiant
croissant », now highlights its column when hovered or focused: the header
and every cell get heavier side borders and the header an underline, so
text contrast is unchanged and the cue is not colour alone. The mapping
from criterion to column lives in the propositions model, and a criterion
without a column fails there. The sentence still reads word for word.
Checked: 2780 node, 554 browser tests, from the index alone.
--- FR ---
[ADD] propositions : un critère du classement surligne sa colonne
La phrase de l'ordre nomme les critères, mais rien ne reliait un nom à la
colonne qui porte sa valeur. Chaque nom de critère, et « l'identifiant
croissant », surligne maintenant sa colonne au survol ou au focus : l'en-
tête et chaque cellule prennent des bords latéraux plus épais et l'en-tête
un soulignement ; le contraste du texte ne change pas, le signe ne tient
pas qu'à la couleur. Le lien critère-colonne vit dans le modèle, et un
critère sans colonne y lève. La phrase se lit mot pour mot comme avant.
Vérifié : 2780 node, 554 navigateur, depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-08 03:39:25 -04:00
|
|
|
|
return [
|
|
|
|
|
|
liaison('propositions.ordre.debut'),
|
[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
|
|
|
|
...joindre(paliers, () => liaison('propositions.ordre.separateur')),
|
[ADD] propositions: a ranking criterion highlights its table column
The order sentence names the ranking criteria, but nothing tied a name to
the column holding its value. Each criterion name, and « l'identifiant
croissant », now highlights its column when hovered or focused: the header
and every cell get heavier side borders and the header an underline, so
text contrast is unchanged and the cue is not colour alone. The mapping
from criterion to column lives in the propositions model, and a criterion
without a column fails there. The sentence still reads word for word.
Checked: 2780 node, 554 browser tests, from the index alone.
--- FR ---
[ADD] propositions : un critère du classement surligne sa colonne
La phrase de l'ordre nomme les critères, mais rien ne reliait un nom à la
colonne qui porte sa valeur. Chaque nom de critère, et « l'identifiant
croissant », surligne maintenant sa colonne au survol ou au focus : l'en-
tête et chaque cellule prennent des bords latéraux plus épais et l'en-tête
un soulignement ; le contraste du texte ne change pas, le signe ne tient
pas qu'à la couleur. Le lien critère-colonne vit dans le modèle, et un
critère sans colonne y lève. La phrase se lit mot pour mot comme avant.
Vérifié : 2780 node, 554 navigateur, depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-08 03:39:25 -04:00
|
|
|
|
liaison('propositions.ordre.fin'),
|
|
|
|
|
|
];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
[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
|
|
|
|
// Le palier qui prend la place du palier sauté : ses critères {nom, poids,
|
|
|
|
|
|
// valeurs}, ceux du palier appliqué au rang rangSaute ; null quand aucun
|
|
|
|
|
|
// palier ne suit le palier sauté.
|
[ADD] priorities: search and ranking follow tiers, goals CSV, commands
The operator's priority order now drives both the search and the
ranking: each tier compiles into one score component, weights sum inside
a shared tier, and the three goal modes compare their own values. With
no stored order, no goals and the facilitator case off, plans and
rankings equal the reference fingerprints under every mode; incremental
and complete scores agree on 1 500 random configurations; a move costs
1 to 2 % more. Table goals import and export through their own CSV, and
commands set or restore the order and choose the goal mode.
Checked: node 4501, navigateur 885, node-long 124.
--- FR ---
[ADD] priorités : recherche et classement par paliers, CSV, commandes
L'ordre des priorités de l'opérateur mène désormais la recherche et le
classement : chaque palier devient une composante du score, les poids
s'additionnent dans un palier partagé, et les trois modes des objectifs
comparent leurs propres valeurs. Sans ordre écrit, sans objectif et sans
case des animateurs, plans et classements égalent les empreintes sous
chaque mode ; score incrémental et complet concordent sur 1 500
configurations tirées ; un mouvement coûte 1 à 2 % de plus. Les objectifs
des tables s'importent et s'exportent par leur CSV ; des commandes posent
ou rétablissent l'ordre et choisissent le mode des objectifs.
Vérifié : node 4501, navigateur 885, node-long 124.
Assisted-by: Claude Opus 5.5
2026-10-11 16:19:38 -04:00
|
|
|
|
function palierAppliqueASaPlace({ criteresAppliques, rangSaute }) {
|
|
|
|
|
|
const palier = criteresAppliques[rangSaute];
|
[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
|
|
|
|
return palier === undefined ? null : palier.criteres.map(({ nom, poids, valeurs }) => ({ nom, poids, valeurs: [...valeurs] }));
|
[ADD] priorities: search and ranking follow tiers, goals CSV, commands
The operator's priority order now drives both the search and the
ranking: each tier compiles into one score component, weights sum inside
a shared tier, and the three goal modes compare their own values. With
no stored order, no goals and the facilitator case off, plans and
rankings equal the reference fingerprints under every mode; incremental
and complete scores agree on 1 500 random configurations; a move costs
1 to 2 % more. Table goals import and export through their own CSV, and
commands set or restore the order and choose the goal mode.
Checked: node 4501, navigateur 885, node-long 124.
--- FR ---
[ADD] priorités : recherche et classement par paliers, CSV, commandes
L'ordre des priorités de l'opérateur mène désormais la recherche et le
classement : chaque palier devient une composante du score, les poids
s'additionnent dans un palier partagé, et les trois modes des objectifs
comparent leurs propres valeurs. Sans ordre écrit, sans objectif et sans
case des animateurs, plans et classements égalent les empreintes sous
chaque mode ; score incrémental et complet concordent sur 1 500
configurations tirées ; un mouvement coûte 1 à 2 % de plus. Les objectifs
des tables s'importent et s'exportent par leur CSV ; des commandes posent
ou rétablissent l'ordre et choisissent le mode des objectifs.
Vérifié : node 4501, navigateur 885, node-long 124.
Assisted-by: Claude Opus 5.5
2026-10-11 16:19:38 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Les phrases de l'ordre (§ 5.7), chacune une liste de morceaux : quand le
|
|
|
|
|
|
// plafond a priori manque, le critère sauté et le palier appliqué à sa
|
[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
|
|
|
|
// place, s'il en est un ; puis les paliers appliqués.
|
[ADD] priorities: search and ranking follow tiers, goals CSV, commands
The operator's priority order now drives both the search and the
ranking: each tier compiles into one score component, weights sum inside
a shared tier, and the three goal modes compare their own values. With
no stored order, no goals and the facilitator case off, plans and
rankings equal the reference fingerprints under every mode; incremental
and complete scores agree on 1 500 random configurations; a move costs
1 to 2 % more. Table goals import and export through their own CSV, and
commands set or restore the order and choose the goal mode.
Checked: node 4501, navigateur 885, node-long 124.
--- FR ---
[ADD] priorités : recherche et classement par paliers, CSV, commandes
L'ordre des priorités de l'opérateur mène désormais la recherche et le
classement : chaque palier devient une composante du score, les poids
s'additionnent dans un palier partagé, et les trois modes des objectifs
comparent leurs propres valeurs. Sans ordre écrit, sans objectif et sans
case des animateurs, plans et classements égalent les empreintes sous
chaque mode ; score incrémental et complet concordent sur 1 500
configurations tirées ; un mouvement coûte 1 à 2 % de plus. Les objectifs
des tables s'importent et s'exportent par leur CSV ; des commandes posent
ou rétablissent l'ordre et choisissent le mode des objectifs.
Vérifié : node 4501, navigateur 885, node-long 124.
Assisted-by: Claude Opus 5.5
2026-10-11 16:19:38 -04:00
|
|
|
|
function ordre(classement) {
|
|
|
|
|
|
const { criteresAppliques, critereSaute } = classement;
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
const phrases = [];
|
|
|
|
|
|
if (critereSaute !== null) {
|
[ADD] priorities: search and ranking follow tiers, goals CSV, commands
The operator's priority order now drives both the search and the
ranking: each tier compiles into one score component, weights sum inside
a shared tier, and the three goal modes compare their own values. With
no stored order, no goals and the facilitator case off, plans and
rankings equal the reference fingerprints under every mode; incremental
and complete scores agree on 1 500 random configurations; a move costs
1 to 2 % more. Table goals import and export through their own CSV, and
commands set or restore the order and choose the goal mode.
Checked: node 4501, navigateur 885, node-long 124.
--- FR ---
[ADD] priorités : recherche et classement par paliers, CSV, commandes
L'ordre des priorités de l'opérateur mène désormais la recherche et le
classement : chaque palier devient une composante du score, les poids
s'additionnent dans un palier partagé, et les trois modes des objectifs
comparent leurs propres valeurs. Sans ordre écrit, sans objectif et sans
case des animateurs, plans et classements égalent les empreintes sous
chaque mode ; score incrémental et complet concordent sur 1 500
configurations tirées ; un mouvement coûte 1 à 2 % de plus. Les objectifs
des tables s'importent et s'exportent par leur CSV ; des commandes posent
ou rétablissent l'ordre et choisissent le mode des objectifs.
Vérifié : node 4501, navigateur 885, node-long 124.
Assisted-by: Claude Opus 5.5
2026-10-11 16:19:38 -04:00
|
|
|
|
phrases.push([liaison('propositions.ordre.saute', { saute: critereSaute, applique: palierAppliqueASaPlace(classement) })]);
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
}
|
[ADD] propositions: a ranking criterion highlights its table column
The order sentence names the ranking criteria, but nothing tied a name to
the column holding its value. Each criterion name, and « l'identifiant
croissant », now highlights its column when hovered or focused: the header
and every cell get heavier side borders and the header an underline, so
text contrast is unchanged and the cue is not colour alone. The mapping
from criterion to column lives in the propositions model, and a criterion
without a column fails there. The sentence still reads word for word.
Checked: 2780 node, 554 browser tests, from the index alone.
--- FR ---
[ADD] propositions : un critère du classement surligne sa colonne
La phrase de l'ordre nomme les critères, mais rien ne reliait un nom à la
colonne qui porte sa valeur. Chaque nom de critère, et « l'identifiant
croissant », surligne maintenant sa colonne au survol ou au focus : l'en-
tête et chaque cellule prennent des bords latéraux plus épais et l'en-tête
un soulignement ; le contraste du texte ne change pas, le signe ne tient
pas qu'à la couleur. Le lien critère-colonne vit dans le modèle, et un
critère sans colonne y lève. La phrase se lit mot pour mot comme avant.
Vérifié : 2780 node, 554 navigateur, depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-08 03:39:25 -04:00
|
|
|
|
phrases.push(phraseDesCriteres(criteresAppliques));
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
return phrases;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
[FIX] interface: ghost labels, keyboard, valid HTML, closed data-* list
The drag ghost names what releasing at the point changes, floor included.
Escape on a seat returns to its table, a refused Tab stays put, the legend
toggle exposes aria-expanded, and the header markup is valid HTML. Every
data-* attribute the interface sets belongs to one closed list that a guard
reads. The tree guards follow helpers a test imports, and the reporter says
the whole series stays watched under coverage on a small machine.
Checked: every new test red first; 3001 node, 635 browser and 63 long tests
green from the index alone.
--- FR ---
[FIX] interface : fantôme nommé, clavier, HTML valide, data-* fermés
Le fantôme du glisser nomme ce que relâcher au point modifie, sol compris.
Échap sur un siège remonte à sa table, un Tab refusé reste en place, la
bascule de la légende expose aria-expanded, et la tête est du HTML valide.
Chaque attribut data-* que l'interface pose appartient à une liste fermée
qu'une garde lit. Les gardes de l'arbre suivent les aides qu'une épreuve
importe, et le rapporteur dit la série entière surveillée sous couverture.
Vérifié : chaque épreuve rouge d'abord ; 3001 node, 635 navigateur et 63
longues vertes depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-09 04:01:57 -04:00
|
|
|
|
* Le tableau d'une table d'évaluation (evaluer, evaluation.js).
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
*
|
|
|
|
|
|
* @param {import('../../application/evaluation.js').TableEvaluation} tableEvaluation
|
|
|
|
|
|
* @param {{ajuste?: boolean}} [options] ajuste : le retenu ne porte plus le
|
|
|
|
|
|
* placement de sa proposition d'origine (retenuAjuste) ; il choisit le
|
|
|
|
|
|
* libellé de la ligne du retenu
|
[ADD] propositions: a ranking criterion highlights its table column
The order sentence names the ranking criteria, but nothing tied a name to
the column holding its value. Each criterion name, and « l'identifiant
croissant », now highlights its column when hovered or focused: the header
and every cell get heavier side borders and the header an underline, so
text contrast is unchanged and the cue is not colour alone. The mapping
from criterion to column lives in the propositions model, and a criterion
without a column fails there. The sentence still reads word for word.
Checked: 2780 node, 554 browser tests, from the index alone.
--- FR ---
[ADD] propositions : un critère du classement surligne sa colonne
La phrase de l'ordre nomme les critères, mais rien ne reliait un nom à la
colonne qui porte sa valeur. Chaque nom de critère, et « l'identifiant
croissant », surligne maintenant sa colonne au survol ou au focus : l'en-
tête et chaque cellule prennent des bords latéraux plus épais et l'en-tête
un soulignement ; le contraste du texte ne change pas, le signe ne tient
pas qu'à la couleur. Le lien critère-colonne vit dans le modèle, et un
critère sans colonne y lève. La phrase se lit mot pour mot comme avant.
Vérifié : 2780 node, 554 navigateur, depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-08 03:39:25 -04:00
|
|
|
|
* @returns {{ordre: Array<Array<{cle: string, details: Object, critere: string|null,
|
[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
|
|
|
|
* valeur: string|null, colonne: string|null}>>, colonnes: typeof COLONNES,
|
|
|
|
|
|
* groupes: typeof GROUPES_COLONNES, etendueRaisons: number, lignes: Object[],
|
|
|
|
|
|
* horsClassement: Object[], retenu: Object|null}}
|
[ADD] propositions: a ranking criterion highlights its table column
The order sentence names the ranking criteria, but nothing tied a name to
the column holding its value. Each criterion name, and « l'identifiant
croissant », now highlights its column when hovered or focused: the header
and every cell get heavier side borders and the header an underline, so
text contrast is unchanged and the cue is not colour alone. The mapping
from criterion to column lives in the propositions model, and a criterion
without a column fails there. The sentence still reads word for word.
Checked: 2780 node, 554 browser tests, from the index alone.
--- FR ---
[ADD] propositions : un critère du classement surligne sa colonne
La phrase de l'ordre nomme les critères, mais rien ne reliait un nom à la
colonne qui porte sa valeur. Chaque nom de critère, et « l'identifiant
croissant », surligne maintenant sa colonne au survol ou au focus : l'en-
tête et chaque cellule prennent des bords latéraux plus épais et l'en-tête
un soulignement ; le contraste du texte ne change pas, le signe ne tient
pas qu'à la couleur. Le lien critère-colonne vit dans le modèle, et un
critère sans colonne y lève. La phrase se lit mot pour mot comme avant.
Vérifié : 2780 node, 554 navigateur, depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-08 03:39:25 -04:00
|
|
|
|
* ordre : les phrases de l'ordre, chacune une liste de morceaux que t
|
[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
|
|
|
|
* traduit et que l'affichage met bout à bout ; un morceau qui nomme une
|
|
|
|
|
|
* valeur appliquée, ou l'identifiant croissant, porte le critère qui la
|
|
|
|
|
|
* classe, la valeur et la colonne qu'elle désigne — 'identifiant' pour
|
|
|
|
|
|
* le dernier départage —, null pour un texte de liaison ; colonnes : celles
|
|
|
|
|
|
* de COLONNES que le tableau porte, les colonnes des objectifs et des
|
|
|
|
|
|
* animateurs selon l'état des critères de la table ; groupes : les
|
|
|
|
|
|
* segments de la rangée des groupes sur ces colonnes ; lignes : les
|
|
|
|
|
|
* comparables dans l'ordre du classement, chacune { id, rang, retenue, comparable: true,
|
[ADD] propositions: a ranking criterion highlights its table column
The order sentence names the ranking criteria, but nothing tied a name to
the column holding its value. Each criterion name, and « l'identifiant
croissant », now highlights its column when hovered or focused: the header
and every cell get heavier side borders and the header an underline, so
text contrast is unchanged and the cue is not colour alone. The mapping
from criterion to column lives in the propositions model, and a criterion
without a column fails there. The sentence still reads word for word.
Checked: 2780 node, 554 browser tests, from the index alone.
--- FR ---
[ADD] propositions : un critère du classement surligne sa colonne
La phrase de l'ordre nomme les critères, mais rien ne reliait un nom à la
colonne qui porte sa valeur. Chaque nom de critère, et « l'identifiant
croissant », surligne maintenant sa colonne au survol ou au focus : l'en-
tête et chaque cellule prennent des bords latéraux plus épais et l'en-tête
un soulignement ; le contraste du texte ne change pas, le signe ne tient
pas qu'à la couleur. Le lien critère-colonne vit dans le modèle, et un
critère sans colonne y lève. La phrase se lit mot pour mot comme avant.
Vérifié : 2780 node, 554 navigateur, depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-08 03:39:25 -04:00
|
|
|
|
* cellules, imposes, violations } ;
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
* horsClassement : les autres par identifiant, { id, rang: null, retenue,
|
|
|
|
|
|
* comparable: false, statut, raisons } — statut la clé de « non comparable »,
|
|
|
|
|
|
* raisons leurs codes, chacune { cle, details, participant }, participant
|
|
|
|
|
|
* l'identifiant de la personne en cause ou null ; etendueRaisons : le nombre
|
|
|
|
|
|
* de colonnes que couvre la cellule des raisons ; retenu : la ligne du
|
|
|
|
|
|
* retenu sous l'une ou l'autre forme, plus libelle { cle, details } — « tel
|
|
|
|
|
|
* que » ou « ajusté » —, null sans retenu. retenue marque la proposition
|
|
|
|
|
|
* d'origine du retenu.
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function tableau(tableEvaluation, { ajuste = false } = {}) {
|
|
|
|
|
|
const idRetenu = tableEvaluation.retenu?.id ?? null;
|
[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
|
|
|
|
const colonnes = colonnesPortees(tableEvaluation.criteres);
|
|
|
|
|
|
const portees = new Set(colonnes.map(({ nom }) => nom));
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
// Les comparables ouvrent la liste, dans l'ordre du classement : leur
|
|
|
|
|
|
// place y est leur rang.
|
[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
|
|
|
|
const toutes = tableEvaluation.propositions.map((ligne, place) => ligneDe(ligne, tableEvaluation, idRetenu, portees, place + 1));
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
return {
|
|
|
|
|
|
ordre: ordre(tableEvaluation.classement),
|
[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
|
|
|
|
colonnes,
|
|
|
|
|
|
groupes: segmenter(colonnes.map(({ nom }) => nom)),
|
|
|
|
|
|
// La cellule des raisons d'une ligne hors classement couvre les colonnes
|
|
|
|
|
|
// de mesure portées et celle des imposés.
|
|
|
|
|
|
etendueRaisons: [...LECTURES.keys()].filter((nom) => portees.has(nom)).length + 1,
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
lignes: toutes.filter(({ comparable }) => comparable),
|
|
|
|
|
|
horsClassement: toutes.filter(({ comparable }) => !comparable),
|
[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
|
|
|
|
retenu: tableEvaluation.retenu === null ? null : ligneDuRetenu(tableEvaluation, idRetenu, portees, ajuste),
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// La ligne du retenu, et son libellé : « tel que » la proposition d'origine,
|
|
|
|
|
|
// ou « ajusté » depuis elle.
|
[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
|
|
|
|
function ligneDuRetenu(tableEvaluation, idRetenu, portees, ajuste) {
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
const cle = ajuste ? 'propositions.retenu.ajuste' : 'propositions.retenu.origine';
|
[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
|
|
|
|
return { ...ligneDe(tableEvaluation.retenu, tableEvaluation, idRetenu, portees), libelle: { cle, details: { proposition: idRetenu } } };
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
[FIX] interface: ghost labels, keyboard, valid HTML, closed data-* list
The drag ghost names what releasing at the point changes, floor included.
Escape on a seat returns to its table, a refused Tab stays put, the legend
toggle exposes aria-expanded, and the header markup is valid HTML. Every
data-* attribute the interface sets belongs to one closed list that a guard
reads. The tree guards follow helpers a test imports, and the reporter says
the whole series stays watched under coverage on a small machine.
Checked: every new test red first; 3001 node, 635 browser and 63 long tests
green from the index alone.
--- FR ---
[FIX] interface : fantôme nommé, clavier, HTML valide, data-* fermés
Le fantôme du glisser nomme ce que relâcher au point modifie, sol compris.
Échap sur un siège remonte à sa table, un Tab refusé reste en place, la
bascule de la légende expose aria-expanded, et la tête est du HTML valide.
Chaque attribut data-* que l'interface pose appartient à une liste fermée
qu'une garde lit. Les gardes de l'arbre suivent les aides qu'une épreuve
importe, et le rapporteur dit la série entière surveillée sous couverture.
Vérifié : chaque épreuve rouge d'abord ; 3001 node, 635 navigateur et 63
longues vertes depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-09 04:01:57 -04:00
|
|
|
|
/**
|
|
|
|
|
|
* La colonne que la phrase de l'ordre surligne (§ 5.7), de deux états
|
|
|
|
|
|
* tenus à part : celle du nom survolé, sinon celle du nom qui a le focus,
|
|
|
|
|
|
* sinon null. Quitter l'un rend l'autre : un survol qui passe ne retire pas
|
|
|
|
|
|
* le surlignage du focus.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {string|null} survolee la colonne du nom sous le pointeur
|
|
|
|
|
|
* @param {string|null} focalisee la colonne du nom qui a le focus
|
|
|
|
|
|
* @returns {string|null}
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function surlignee(survolee, focalisee) {
|
|
|
|
|
|
return survolee ?? focalisee;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
/**
|
|
|
|
|
|
* Le texte d'une cellule : t(cle) quand elle porte une clé, sinon son nombre
|
|
|
|
|
|
* mis en forme.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {{valeur: number|boolean|null, cle: string|null, decimales: number}} cellule
|
|
|
|
|
|
* @param {{t: Function, format: {nombre: Function}}} outils
|
|
|
|
|
|
* @returns {string}
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function texteCellule({ valeur, cle, decimales }, { t, format }) {
|
|
|
|
|
|
return cle === null ? format.nombre(valeur, { decimales }) : t(cle);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Égalité en profondeur de deux valeurs du fichier d'état : nombres,
|
|
|
|
|
|
// chaînes, booléens, null, listes et objets simples.
|
|
|
|
|
|
function egaux(a, b) {
|
|
|
|
|
|
if (a === b) return true;
|
|
|
|
|
|
if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) return false;
|
|
|
|
|
|
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
|
|
|
|
const clesA = Object.keys(a);
|
|
|
|
|
|
if (clesA.length !== Object.keys(b).length) return false;
|
|
|
|
|
|
return clesA.every((cle) => Object.hasOwn(b, cle) && egaux(a[cle], b[cle]));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Ce que le retenu copie de sa proposition d'origine, et que retenirProposition
|
|
|
|
|
|
// remplacerait.
|
|
|
|
|
|
const CHAMPS_DU_PLACEMENT = ['siegesAttribues', 'tables', 'capacites', 'tours', 'participants', 'placement'];
|
|
|
|
|
|
|
[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
|
|
|
|
/** Vrai quand un retenu existe et ne porte plus le placement de sa
|
|
|
|
|
|
* proposition d'origine : tables, capacités, tours, participants ou
|
|
|
|
|
|
* placement diffèrent, en profondeur, de ceux de la proposition
|
|
|
|
|
|
* retenu.proposition, ou celle-ci n'est plus dans la liste. */
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
export function retenuAjuste(charge) {
|
|
|
|
|
|
const { retenu } = charge;
|
|
|
|
|
|
if (retenu === null) return false;
|
|
|
|
|
|
const origine = charge.propositions.find(({ id }) => id === retenu.proposition);
|
|
|
|
|
|
if (origine === undefined) return true;
|
|
|
|
|
|
return !CHAMPS_DU_PLACEMENT.every((champ) => egaux(retenu[champ], origine[champ]));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* La fenêtre à confirmer avant de retenir la proposition id (§ 2.1) : retenir
|
|
|
|
|
|
* remplace le retenu, et détruit ses ajustements quand il en porte. Elle
|
|
|
|
|
|
* s'ouvre quand la séance accepterait le geste — etat.refus null — et que le
|
|
|
|
|
|
* retenu est ajusté, y compris pour re-retenir sa proposition d'origine ; un
|
|
|
|
|
|
* geste que la séance refuserait s'exécute sans fenêtre, et son refus
|
|
|
|
|
|
* s'affiche.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {{refus: Object|null, charge: Object|null}} etat l'état observable de la séance
|
|
|
|
|
|
* @param {number} id la proposition à retenir
|
|
|
|
|
|
* @returns {null|{id: number, titre: {cle: string, details: Object},
|
|
|
|
|
|
* elements: Array<{cle: string, details: Object}>}} null sans fenêtre ;
|
|
|
|
|
|
* sinon la proposition demandée, le titre, puis les éléments qui nomment le
|
|
|
|
|
|
* retenu ajusté et la proposition qui le remplace
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function demandeConfirmation({ refus, charge }, id) {
|
|
|
|
|
|
if (refus !== null || charge === null || !retenuAjuste(charge)) return null;
|
|
|
|
|
|
return {
|
|
|
|
|
|
id,
|
|
|
|
|
|
titre: { cle: 'propositions.confirmation.titre', details: { proposition: id } },
|
|
|
|
|
|
elements: [
|
|
|
|
|
|
{ cle: 'propositions.confirmation.retenuAjuste', details: { proposition: charge.retenu.proposition } },
|
|
|
|
|
|
{ cle: 'propositions.confirmation.remplacant', details: { proposition: id } },
|
|
|
|
|
|
],
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
[IMP] proposal evaluation: cached per frozen charge, validated once
The Génération and Propositions tabs re-evaluated every proposal on each
visit, about 1 ms per proposal, with no bound on how many accumulate.
The evaluation table is now kept per frozen event charge, which every
write replaces, and both tabs share it. Each placement is validated once
instead of three times; the public derive and planDepuisFichier still
validate, and a guard keeps the unchecked variants to evaluer alone.
At 200 proposals: Génération 214 to 17 ms on revisit, Propositions 310
to 118 ms. Checked: results deep-equal; node 4019, browser 873.
--- FR ---
[IMP] évaluation des propositions : gardée par charge, validée une fois
Les onglets Génération et Propositions réévaluaient toutes les
propositions à chaque visite, environ 1 ms chacune, sans borne sur leur
nombre. La table d'évaluation se garde par charge figée, qu'une écriture
remplace, et les deux onglets la partagent. Chaque placement se valide
une fois au lieu de trois ; derive et planDepuisFichier publics valident
toujours, une garde réserve les variantes sans contrôle à evaluer.
À 200 propositions : Génération 214 → 17 ms au retour, Propositions
310 → 118 ms. Vérifié : résultats identiques ; node 4019, nav. 873.
Assisted-by: Claude Opus 5.5
2026-10-11 03:43:47 -04:00
|
|
|
|
// La table d'évaluation de chaque charge figée en profondeur, sous l'identité
|
|
|
|
|
|
// de la charge. La charge de l'état observable de la séance est une copie
|
|
|
|
|
|
// figée en profondeur (seance.js, figer), remplacée par une copie neuve à
|
|
|
|
|
|
// chaque changement de l'événement ouvert et gardée telle quelle sinon : son
|
|
|
|
|
|
// identité suffit à dire que son contenu n'a pas changé, et Génération et
|
|
|
|
|
|
// Propositions relisent la même table. Une charge qui n'est pas figée
|
|
|
|
|
|
// partout se mesure à chaque appel, son contenu pouvant changer sous la
|
|
|
|
|
|
// même identité. Le § 13.3 compte sur la réactivité de Svelte plutôt que sur
|
|
|
|
|
|
// une mémoïsation posée à la main ; ce cache en est l'exception voulue, posé
|
|
|
|
|
|
// dans le modèle pur et tenu par l'immuabilité de son entrée.
|
|
|
|
|
|
const evaluees = new WeakMap();
|
|
|
|
|
|
|
[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
|
|
|
|
/** Vrai quand chaque objet atteint depuis valeur est figé. Un objet figé ne
|
|
|
|
|
|
* redevient jamais modifiable : vrai une fois, vrai pour toujours. */
|
|
|
|
|
|
export function figeePartout(valeur) {
|
[IMP] proposal evaluation: cached per frozen charge, validated once
The Génération and Propositions tabs re-evaluated every proposal on each
visit, about 1 ms per proposal, with no bound on how many accumulate.
The evaluation table is now kept per frozen event charge, which every
write replaces, and both tabs share it. Each placement is validated once
instead of three times; the public derive and planDepuisFichier still
validate, and a guard keeps the unchecked variants to evaluer alone.
At 200 proposals: Génération 214 to 17 ms on revisit, Propositions 310
to 118 ms. Checked: results deep-equal; node 4019, browser 873.
--- FR ---
[IMP] évaluation des propositions : gardée par charge, validée une fois
Les onglets Génération et Propositions réévaluaient toutes les
propositions à chaque visite, environ 1 ms chacune, sans borne sur leur
nombre. La table d'évaluation se garde par charge figée, qu'une écriture
remplace, et les deux onglets la partagent. Chaque placement se valide
une fois au lieu de trois ; derive et planDepuisFichier publics valident
toujours, une garde réserve les variantes sans contrôle à evaluer.
À 200 propositions : Génération 214 → 17 ms au retour, Propositions
310 → 118 ms. Vérifié : résultats identiques ; node 4019, nav. 873.
Assisted-by: Claude Opus 5.5
2026-10-11 03:43:47 -04:00
|
|
|
|
if (valeur === null || typeof valeur !== 'object') return true;
|
|
|
|
|
|
if (!Object.isFrozen(valeur)) return false;
|
|
|
|
|
|
for (const cle of Object.keys(valeur)) if (!figeePartout(valeur[cle])) return false;
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Fige une valeur neuve et tout ce qu'elle atteint.
|
|
|
|
|
|
function figer(valeur) {
|
|
|
|
|
|
if (valeur === null || typeof valeur !== 'object' || Object.isFrozen(valeur)) return valeur;
|
|
|
|
|
|
for (const cle of Object.keys(valeur)) figer(valeur[cle]);
|
|
|
|
|
|
return Object.freeze(valeur);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// La table d'une charge, mesurée à neuf.
|
|
|
|
|
|
function evaluationNeuve(charge) {
|
|
|
|
|
|
if (charge.propositions.length === 0 && charge.retenu === null) return { table: null, refus: null };
|
|
|
|
|
|
try {
|
|
|
|
|
|
return { table: evaluer(charge), refus: null };
|
|
|
|
|
|
} catch (erreur) {
|
|
|
|
|
|
if (typeof erreur?.code !== 'string') throw erreur;
|
|
|
|
|
|
return { table: null, refus: { code: erreur.code, details: erreur.details ?? {} } };
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
/**
|
|
|
|
|
|
* La table d'évaluation d'une charge, ou ce qui l'empêche : null sans
|
|
|
|
|
|
* proposition ni retenu, rien n'étant à mesurer ; le refus de normaliser —
|
|
|
|
|
|
* une erreur qui porte un code — quand la configuration ne se tient pas.
|
[IMP] proposal evaluation: cached per frozen charge, validated once
The Génération and Propositions tabs re-evaluated every proposal on each
visit, about 1 ms per proposal, with no bound on how many accumulate.
The evaluation table is now kept per frozen event charge, which every
write replaces, and both tabs share it. Each placement is validated once
instead of three times; the public derive and planDepuisFichier still
validate, and a guard keeps the unchecked variants to evaluer alone.
At 200 proposals: Génération 214 to 17 ms on revisit, Propositions 310
to 118 ms. Checked: results deep-equal; node 4019, browser 873.
--- FR ---
[IMP] évaluation des propositions : gardée par charge, validée une fois
Les onglets Génération et Propositions réévaluaient toutes les
propositions à chaque visite, environ 1 ms chacune, sans borne sur leur
nombre. La table d'évaluation se garde par charge figée, qu'une écriture
remplace, et les deux onglets la partagent. Chaque placement se valide
une fois au lieu de trois ; derive et planDepuisFichier publics valident
toujours, une garde réserve les variantes sans contrôle à evaluer.
À 200 propositions : Génération 214 → 17 ms au retour, Propositions
310 → 118 ms. Vérifié : résultats identiques ; node 4019, nav. 873.
Assisted-by: Claude Opus 5.5
2026-10-11 03:43:47 -04:00
|
|
|
|
* Toute autre erreur remonte, et rien n'est retenu. Le résultat est figé en
|
|
|
|
|
|
* profondeur ; pour une charge figée partout, c'est le même objet à chaque
|
|
|
|
|
|
* appel, mesuré au premier.
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
*
|
|
|
|
|
|
* @param {Object} charge
|
|
|
|
|
|
* @returns {{table: Object|null, refus: null|{code: string, details: Object}}}
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function evaluation(charge) {
|
[IMP] proposal evaluation: cached per frozen charge, validated once
The Génération and Propositions tabs re-evaluated every proposal on each
visit, about 1 ms per proposal, with no bound on how many accumulate.
The evaluation table is now kept per frozen event charge, which every
write replaces, and both tabs share it. Each placement is validated once
instead of three times; the public derive and planDepuisFichier still
validate, and a guard keeps the unchecked variants to evaluer alone.
At 200 proposals: Génération 214 to 17 ms on revisit, Propositions 310
to 118 ms. Checked: results deep-equal; node 4019, browser 873.
--- FR ---
[IMP] évaluation des propositions : gardée par charge, validée une fois
Les onglets Génération et Propositions réévaluaient toutes les
propositions à chaque visite, environ 1 ms chacune, sans borne sur leur
nombre. La table d'évaluation se garde par charge figée, qu'une écriture
remplace, et les deux onglets la partagent. Chaque placement se valide
une fois au lieu de trois ; derive et planDepuisFichier publics valident
toujours, une garde réserve les variantes sans contrôle à evaluer.
À 200 propositions : Génération 214 → 17 ms au retour, Propositions
310 → 118 ms. Vérifié : résultats identiques ; node 4019, nav. 873.
Assisted-by: Claude Opus 5.5
2026-10-11 03:43:47 -04:00
|
|
|
|
const connue = evaluees.get(charge);
|
|
|
|
|
|
if (connue !== undefined) return connue;
|
|
|
|
|
|
const evaluee = figer(evaluationNeuve(charge));
|
|
|
|
|
|
if (figeePartout(charge)) evaluees.set(charge, evaluee);
|
|
|
|
|
|
return evaluee;
|
[ADD] interface: propositions — ranked table, retain, clear
The operator chooses among the generated plans. The ranked table orders
propositions by the criteria of § 5.4 and shows, for encounters, the
minimum only — the mean is the same for every proposition at full tables
— with redundancy read through its sum. A proposition is retained or the
list cleared through named commands; clearing spares the retained one,
and a proposition that broke is shown apart, not ranked.
Checked: 2400 node and 406 browser tests.
--- FR ---
[ADD] interface : propositions — tableau classé, retenir, effacer
L'opérateur choisit parmi les plans générés. Le tableau classé ordonne les
propositions selon les critères du § 5.4 et ne montre, pour les
rencontres, que le minimum — la moyenne est la même pour toute
proposition à tables pleines —, la redondance se lisant par sa somme. Une
proposition se retient, ou la liste s'efface, par des commandes nommées ;
effacer épargne la retenue, et une proposition abîmée se montre à part,
hors classement.
Vérifié : 2400 node et 406 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 09:10:39 -04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Le nom affiché de la personne id de la charge, exclue comprise ; null
|
|
|
|
|
|
* pour une personne que la charge n'a plus, et pour id null. */
|
|
|
|
|
|
export function nomDe(charge, id) {
|
|
|
|
|
|
const personne = charge.participants.find((candidate) => candidate.id === id);
|
|
|
|
|
|
return personne === undefined ? null : nomAffiche(personne);
|
|
|
|
|
|
}
|
[ADD] proposals: pages of 100 in the single ranking order
Past a few hundred proposals the table rebuilt every row on each visit:
at 500, 15 000 nodes and about 290 ms on a second visit. The table now
shows the global ranking 100 at a time, each row keeping its rank, with
the retained row on top of every page. The page is navigation state,
never written: it resets on each event opening and after a generation,
is clamped when proposals go, and follows a proposal shown on the plan.
At 500: second visit 288 -> 55 ms, first 686 -> 449 ms, 3 100 nodes.
Checked: node 4039, navigateur 884, node-long 105, all green.
--- FR ---
[ADD] propositions : pages de 100 dans l'ordre du classement unique
Au-delà de quelques centaines de propositions, le tableau refaisait toutes
ses lignes à chaque visite : à 500, 15 000 nœuds et environ 290 ms au
retour. Il montre désormais le classement global 100 par 100, chaque
ligne gardant son rang, le retenu en tête de chaque page. La page est un
état de navigation, jamais écrit : elle repart à chaque ouverture et après
une génération, se borne quand des propositions partent, et suit la
proposition montrée au plan. À 500 : retour 288 -> 55 ms, 1re 686 -> 449.
Vérifié : node 4039, navigateur 884, node-long 105, toutes vertes.
Assisted-by: Claude Opus 5.5
2026-10-11 04:49:54 -04:00
|
|
|
|
|
|
|
|
|
|
/** Le nombre de propositions qu'une page du tableau montre (§ 5.7) : le
|
|
|
|
|
|
* classement entier se découpe en pages de TAILLE_PAGE lignes, la ligne du
|
|
|
|
|
|
* retenu en plus, hors du compte. */
|
|
|
|
|
|
export const TAILLE_PAGE = 100;
|
|
|
|
|
|
|
|
|
|
|
|
/** Le nombre de pages d'un tableau de total propositions : une au moins,
|
|
|
|
|
|
* la page d'un tableau vide comprise. */
|
|
|
|
|
|
export function nombreDePages(total) {
|
|
|
|
|
|
return Math.max(1, Math.ceil(total / TAILLE_PAGE));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// La page bornée aux pages existantes : la première en deçà, la dernière
|
|
|
|
|
|
// au-delà.
|
|
|
|
|
|
const bornee = (page, pages) => Math.min(Math.max(1, page), pages);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* La page d'un tableau (tableau()) : le classement unique découpé, jamais
|
|
|
|
|
|
* retrié. Les propositions se comptent dans l'ordre où le tableau les
|
|
|
|
|
|
* montre — les classées dans l'ordre du classement, puis celles hors
|
|
|
|
|
|
* classement —, et la page p porte celles de rang (p − 1) × TAILLE_PAGE + 1
|
|
|
|
|
|
* à p × TAILLE_PAGE. Chaque ligne garde le rang global que tableau() lui a
|
|
|
|
|
|
* donné. La page demandée se borne aux pages existantes.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {{lignes: Object[], horsClassement: Object[]}} vue
|
|
|
|
|
|
* @param {number} page entière, à partir de 1
|
|
|
|
|
|
* @returns {{lignes: Object[], horsClassement: Object[], page: number,
|
|
|
|
|
|
* pages: number, premier: number, dernier: number, total: number,
|
|
|
|
|
|
* paginee: boolean}} lignes et horsClassement : celles de la page, dans
|
|
|
|
|
|
* l'ordre de la vue ; page : la page bornée ; pages : leur nombre ;
|
|
|
|
|
|
* premier et dernier : les places, à partir de 1, de la première et de la
|
|
|
|
|
|
* dernière proposition de la page, 0 et 0 sans proposition ; total : le
|
|
|
|
|
|
* nombre de propositions de la vue ; paginee : vrai au-delà d'une page,
|
|
|
|
|
|
* seul cas où des commandes de page existent
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function pagine(vue, page) {
|
|
|
|
|
|
const classees = vue.lignes.length;
|
|
|
|
|
|
const total = classees + vue.horsClassement.length;
|
|
|
|
|
|
const pages = nombreDePages(total);
|
|
|
|
|
|
const montree = bornee(page, pages);
|
|
|
|
|
|
const debut = (montree - 1) * TAILLE_PAGE;
|
|
|
|
|
|
const fin = Math.min(debut + TAILLE_PAGE, total);
|
|
|
|
|
|
return {
|
|
|
|
|
|
lignes: vue.lignes.slice(debut, fin),
|
|
|
|
|
|
horsClassement: vue.horsClassement.slice(Math.max(0, debut - classees), Math.max(0, fin - classees)),
|
|
|
|
|
|
page: montree,
|
|
|
|
|
|
pages,
|
|
|
|
|
|
premier: total === 0 ? 0 : debut + 1,
|
|
|
|
|
|
dernier: fin,
|
|
|
|
|
|
total,
|
|
|
|
|
|
paginee: total > TAILLE_PAGE,
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* La page du tableau qui porte la proposition id, classée ou hors
|
|
|
|
|
|
* classement ; null quand la vue ne la porte pas.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {{lignes: Object[], horsClassement: Object[]}} vue
|
|
|
|
|
|
* @param {number|null} id
|
|
|
|
|
|
* @returns {number|null}
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function pageDe(vue, id) {
|
|
|
|
|
|
const place = [...vue.lignes, ...vue.horsClassement].findIndex((ligne) => ligne.id === id);
|
|
|
|
|
|
return place === -1 ? null : Math.floor(place / TAILLE_PAGE) + 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Ce qui distingue une proposition d'une autre : son identifiant, et ce qui
|
|
|
|
|
|
// la régénère. Un retour arrière rend des identifiants que la génération
|
|
|
|
|
|
// suivante réattribue, sous d'autres graines : l'identifiant seul ne dirait
|
|
|
|
|
|
// pas qu'elle est nouvelle.
|
|
|
|
|
|
const cleDe = ({ id, graine, arret, historique }) => `${id}/${graine}/${arret}/${historique}`;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @typedef {Readonly<{cles: ReadonlyArray<string>, visee: number, page: number,
|
|
|
|
|
|
* pages: number}>} SuiviDePage
|
|
|
|
|
|
* la page du tableau que l'état de navigation retient pour l'événement
|
|
|
|
|
|
* ouvert : les clés des propositions vues (cleDe), le numéro de la
|
|
|
|
|
|
* dernière visée prise en compte (EtatUi.visee), la page, et le nombre de
|
|
|
|
|
|
* pages
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
// Vrai quand deux listes de clés portent les mêmes clés, dans le même ordre.
|
|
|
|
|
|
const memesCles = (a, b) => a.length === b.length && a.every((cle, place) => cle === b[place]);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* La page à montrer, du suivi que l'état de navigation retient et de ce que
|
|
|
|
|
|
* l'écran montre maintenant (§ 8.4 : un état d'interface, que rien
|
|
|
|
|
|
* n'écrit) :
|
|
|
|
|
|
*
|
|
|
|
|
|
* - la première, sans suivi retenu — l'état de navigation le remet à null à
|
|
|
|
|
|
* chaque ouverture d'un événement —, ou quand une proposition est
|
|
|
|
|
|
* nouvelle : une génération montre son classement depuis le meilleur ;
|
|
|
|
|
|
* - sinon la page retenue, bornée à la dernière qui existe encore ;
|
|
|
|
|
|
* - à chaque visée nouvelle — un numéro de visée autre que celui du suivi :
|
|
|
|
|
|
* « Voir sur le plan », un remède qui montre une proposition, même celle
|
|
|
|
|
|
* que le plan montrait déjà —, la page qui porte la proposition visée, si
|
|
|
|
|
|
* la vue la porte. Une visée retirée (vise null) n'amène rien.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Rien de changé, le suivi retenu revient lui-même : l'état de navigation,
|
|
|
|
|
|
* qui ne publie qu'un état différent, ne republie pas.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {SuiviDePage|null} retenue
|
|
|
|
|
|
* @param {{vue: {lignes: Object[], horsClassement: Object[]},
|
|
|
|
|
|
* propositions: Object[], vise: number|null, visee: number}} observee le
|
|
|
|
|
|
* tableau, les propositions de la charge, la proposition que l'état de
|
|
|
|
|
|
* navigation demande au plan, et le numéro de cette visée
|
|
|
|
|
|
* @returns {SuiviDePage} le suivi à retenir, celui de la page montrée
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function suivrePage(retenue, { vue, propositions, vise, visee }) {
|
|
|
|
|
|
const cles = propositions.map(cleDe);
|
|
|
|
|
|
const pages = nombreDePages(vue.lignes.length + vue.horsClassement.length);
|
|
|
|
|
|
const connues = new Set(retenue?.cles ?? []);
|
|
|
|
|
|
const neuve = retenue === null || cles.some((cle) => !connues.has(cle));
|
|
|
|
|
|
let page = neuve ? 1 : retenue.page;
|
|
|
|
|
|
const visant = vise !== null && (retenue === null || visee !== retenue.visee) ? pageDe(vue, vise) : null;
|
|
|
|
|
|
if (visant !== null) page = visant;
|
|
|
|
|
|
page = bornee(page, pages);
|
|
|
|
|
|
if (retenue !== null && retenue.visee === visee && retenue.page === page && retenue.pages === pages && memesCles(retenue.cles, cles)) {
|
|
|
|
|
|
return retenue;
|
|
|
|
|
|
}
|
|
|
|
|
|
return Object.freeze({ cles: Object.freeze(cles), visee, page, pages });
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Le suivi à la page demandée, bornée aux pages existantes.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {SuiviDePage} suivi
|
|
|
|
|
|
* @param {number} page
|
|
|
|
|
|
* @returns {SuiviDePage}
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function changerDePage(suivi, page) {
|
|
|
|
|
|
return Object.freeze({ ...suivi, page: bornee(page, suivi.pages) });
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Le texte de l'étendue d'une page (pagine) : « Propositions 101 à 200 sur
|
|
|
|
|
|
* 237 », au singulier pour une page d'une seule proposition. Ses nombres se
|
|
|
|
|
|
* mettent en forme par format.nombre ; le compte de la page accorde le nom.
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param {{premier: number, dernier: number, total: number}} page
|
|
|
|
|
|
* @param {{t: Function, format: {nombre: Function}}} outils la traduction
|
|
|
|
|
|
* et la mise en forme du contexte
|
|
|
|
|
|
* @returns {string}
|
|
|
|
|
|
*/
|
|
|
|
|
|
export function texteEtendue({ premier, dernier, total }, { t, format }) {
|
|
|
|
|
|
return t('propositions.pages.etendue', {
|
|
|
|
|
|
premier: format.nombre(premier),
|
|
|
|
|
|
dernier: format.nombre(dernier),
|
|
|
|
|
|
total: format.nombre(total),
|
|
|
|
|
|
nombre: dernier - premier + 1,
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|