gestion_table_tournante_libre/test/fixtures/banc/pessimiste.js
Mathieu Benoit d8a6fb8202 [ADD] bench: a priori ceiling cost on the largest and worst events
Spec 17 point 4 asks whether the a priori ceiling is cheap enough to compute
on every check. The bench times plafondsAPriori and diagnostiquer on the
large demonstration, its variant without exceptions, and a pessimistic
event of 260 people, 33 tables of 8 and 10 rounds with every signature
distinct: about 0.075 ms, 0.04 ms and 11.5 ms. A long test guards each at
four times its reference, so losing the memoisation turns it red.
Checked: red first under that mutant; 3208 node and 71 long tests green.

--- FR ---

[ADD] banc : coût du plafond a priori, grand événement et pire cas

Le spec 17, point 4, demande si le plafond a priori se calcule assez vite
pour chaque contrôle. Le banc mesure plafondsAPriori et diagnostiquer sur
la grande démonstration, sa variante sans exception, et un événement
pessimiste de 260 personnes, 33 tables de 8 et 10 tours aux signatures
toutes distinctes : environ 0,075 ms, 0,04 ms et 11,5 ms. Une épreuve
longue garde chacun à quatre fois sa référence : perdre la mémoïsation la
rend rouge.
Vérifié : rouge d'abord sous ce mutant ; 3208 node et 71 longues vertes.

Assisted-by: Claude Opus 5.5
2026-10-09 04:53:10 -04:00

78 lines
3.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// © 2026 TechnoLibre (http://www.technolibre.ca)
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
// La configuration pessimiste du coût du plafond a priori (§ 17, point 4) :
// la salle de la variante sans exception, 33 tables de 8, et 260 personnes
// qui portent chacune deux tours fixés, sur 10 tours. Le plafond a priori se
// mémoïse par signature — statut, ancrage, multiensemble des tables fixées
// (src/moteur/plafond.js) — : ici chaque personne a la sienne, et la
// programmation dynamique se refait 260 fois, chacune sur 8 tours libres.
// C'est le cas que la mémoïsation ne rattrape pas, là où les démonstrations
// livrées n'ont que quelques signatures.
//
// La personne de rang i, de 0 à 259, est fixée à la table a = i mod 33 au
// tour 1 + (i mod 10), et à la table b = (a + d) mod 33 au tour
// 1 + ((i + 5) mod 10), où d = 1 + ⌊i / 33⌋ va de 1 à 8. La paire {a, b}
// détermine (a, d) tant que d ≤ 16 : les 260 paires sont distinctes, et les
// 260 signatures aussi. Les deux tours d'une personne diffèrent de 5. Aucune
// table ne reçoit plus de 8 personnes fixées au même tour : le moteur la
// normalise sans SURRESERVATION. Personne n'a d'appartenance, et les quatre
// contraintes sont actives, comme dans les démonstrations.
//
// Les noms sont forgés : le produit de 20 prénoms et de 13 noms, hors des
// réservoirs de src/demo/noms.js.
/** Les nombres de la configuration, que ses épreuves affirment. */
export const FORME_PESSIMISTE = Object.freeze({ personnes: 260, tables: 33, capacite: 8, tours: 10 });
const PRENOMS = [
'Iris', 'Théo', 'Ondine', 'Basile', 'Capucine', 'Aurèle', 'Mélisande', 'Firmin', 'Clélia', 'Anselme',
'Bérénice', 'Cyprien', 'Daphné', 'Eudes', 'Flavie', 'Gaspard', 'Hortense', 'Ignace', 'Jacinthe', 'Lisandre',
];
const NOMS = [
'Ombrelle', 'Pervenche', 'Lacasse', 'Grisaille', 'Tourmaline', 'Arrosoir', 'Cerfeuil',
'Bruyère', 'Galet', 'Mistral', 'Sarriette', 'Quenouille', 'Vermeil',
];
/**
* La configuration pessimiste, sous la forme que le moteur reçoit
* (src/moteur/types.js › Configuration) : un objet neuf à chaque appel.
* Participants d'identifiants 1 à 260 ; tables d'identifiants et de numéros
* 1 à 33 ; réservations de portée « tour », deux par personne, dans l'ordre
* des personnes, la plus petite des deux tours d'abord.
*
* @returns {import('../../../src/moteur/types.js').Configuration}
*/
export function configurationPessimiste() {
const { personnes, tables, capacite, tours } = FORME_PESSIMISTE;
const participants = [];
const reservations = [];
for (let i = 0; i < personnes; i += 1) {
const id = i + 1;
participants.push({
id,
nom: NOMS[i % NOMS.length],
prenom: PRENOMS[Math.floor(i / NOMS.length)],
appartenance: null,
});
const a = i % tables;
const b = (a + 1 + Math.floor(i / tables)) % tables;
const fixations = [
{ table: a + 1, tour: 1 + (i % tours) },
{ table: b + 1, tour: 1 + ((i + 5) % tours) },
].sort((x, y) => x.tour - y.tour);
for (const { table, tour } of fixations) reservations.push({ participant: id, table, portee: 'tour', tour });
}
return {
participants,
tables: Array.from({ length: tables }, (_, t) => ({ id: t + 1, numero: t + 1, capacite })),
tours,
reservations,
contraintes: {
separerAppartenances: true,
nouveauxVoisins: true,
nouvelleTable: true,
varierAppartenances: true,
},
};
}