gestion_table_tournante_libre/test/fixtures/badges/cas.js

150 lines
5.5 KiB
JavaScript
Raw Normal View History

// © 2026 TechnoLibre (http://www.technolibre.ca)
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
// Les petites charges des épreuves de la planche (§ 11.4 à § 11.8) : une
// soirée construite par ses personnes, ses tables et un plan écrit tour par
// tour, sous la forme positionnelle du fichier d'état (§ 8.9). Le plan d'un
// tour se donne comme le fichier l'écrit — une liste par table, dans l'ordre
// de charge.tables, et la réserve — ; sans attribution des sièges, chaque
// liste se trie par identifiant, comme le veut le format. Chaque appel rend
// une charge neuve, que l'épreuve modifie à son gré. Les noms sont inventés,
// hors du réservoir des démonstrations ; la version vient du module engendré.
import { creerCharge } from '../../../src/stockage/document.js';
import { VERSION } from '../../../src/version.genere.js';
/** L'horodatage du retenu des soirées construites, et celui d'une retouche. */
export const H_RETENU = '2031-05-17T20:15:07-04:00';
export const H_RETOUCHE = '2031-05-17T21:42:30-04:00';
/** L'horodatage des propositions construites. */
export const H_PROPOSITION = '2031-05-17T19:05:00-04:00';
/**
* Une personne de la charge : identifiant, prénom (null admis), nom ;
* appartenance, courriel, titre pressenti et notes à null, non exclue,
* sauf ce que champs remplace.
*
* @param {number} id
* @param {string|null} prenom
* @param {string} nom
* @param {Object} [champs]
* @returns {import('../../../src/stockage/types.js').Participant}
*/
export function personne(id, prenom, nom, champs = {}) {
return {
id,
nom,
prenom,
appartenance: null,
courriel: null,
titrePressenti: null,
notes: null,
exclu: false,
...champs,
};
}
/**
* Une table : son identifiant, son numéro affiché, ses sièges (null : le
* défaut de la soirée), ronde, posée en rangée par identifiant.
*
* @param {number} id
* @param {number} numero
* @param {number|null} [sieges]
*/
export function table(id, numero, sieges = null) {
return { id, numero, sieges, forme: 'ronde', position: { x: 300 * (id - 1), y: 0 } };
}
// La capacité courante d'une table de la charge.
const capaciteDe = (charge, { sieges }) => sieges ?? charge.evenement.siegesParDefaut;
/**
* La forme positionnelle d'un plan sur les tables de la charge : tables et
* capacités de charge.tables, dans leur ordre ; un tour par élément de plan,
* { sieges: (number|null)[][], reserve?: number[] } ; les participants, ceux
* que le premier tour écrit, triés. Sans attribution, chaque liste se trie
* par identifiant ; avec, elle garde l'ordre des sièges et ses null.
*
* @param {Object} charge
* @param {Array<{sieges: Array<Array<number|null>>, reserve?: number[]}>} plan
* @param {{siegesAttribues?: boolean}} [options]
*/
export function placementDe(charge, plan, { siegesAttribues = false } = {}) {
const placement = plan.map(({ sieges, reserve = [] }) => ({
sieges: sieges.map((liste) => (siegesAttribues ? [...liste] : [...liste].sort((a, b) => a - b))),
reserve: [...reserve].sort((a, b) => a - b),
}));
const premier = placement[0];
const participants = [...premier.sieges.flat(), ...premier.reserve].filter((id) => id !== null).sort((a, b) => a - b);
return {
siegesAttribues,
tables: charge.tables.map(({ id }) => id),
capacites: charge.tables.map((enregistrement) => capaciteDe(charge, enregistrement)),
tours: plan.length,
participants,
placement,
};
}
/**
* Une proposition de la charge, d'identifiant id, sur ce plan ; datée de
* horodatage, sans le champ quand il vaut null — un fichier écrit avant le
* champ.
*/
export function proposition(charge, id, plan, { siegesAttribues = false, horodatage = H_PROPOSITION } = {}) {
const p = {
id,
graine: id,
arret: 40,
historique: 500,
produitVersion: VERSION.affichee,
...placementDe(charge, plan, { siegesAttribues }),
};
return horodatage === null ? p : { ...p, horodatage };
}
/**
* Une soirée construite. personnes et tables sont les listes de la charge
* (personne, table) ; plan, le plan du retenu, null pour une soirée sans
* retenu ; propositions, des paires [id, plan] ; le retenu vient de la
* proposition 1, daté de horodatage (null : sans le champ). Les
* compteurs passent au-delà de chaque identifiant posé.
*
* @returns {import('../../../src/stockage/types.js').Charge}
*/
export function soiree({
personnes,
tables,
plan = null,
siegesParDefaut = 8,
siegesAttribues = false,
etat = 'retenu',
horodatage = H_RETENU,
nom = 'Soirée des Lucioles',
date = '2031-05-17',
reservations = [],
titres = [],
propositions = [],
}) {
const tours = plan?.length ?? propositions[0]?.[1].length ?? 1;
const charge = creerCharge({ id: 'evt-lucioles', nom, date, siegesParDefaut, tours });
charge.evenement.etat = etat;
charge.reglages.attribuerSieges = siegesAttribues;
charge.participants = personnes;
charge.tables = tables;
charge.reservations = reservations;
charge.titres = titres;
charge.propositions = propositions.map(([id, leur]) => proposition(charge, id, leur, { siegesAttribues }));
const ids = [1, ...propositions.map(([id]) => id)];
charge.prochainsIds = {
participant: Math.max(0, ...personnes.map(({ id }) => id)) + 1,
table: Math.max(0, ...tables.map(({ id }) => id)) + 1,
proposition: Math.max(...ids) + 1,
};
if (plan !== null) {
const retenu = { proposition: 1, ...placementDe(charge, plan, { siegesAttribues }) };
charge.retenu = horodatage === null ? retenu : { ...retenu, horodatage };
}
return charge;
}