[ADD] csv: apply an import three ways, re-export refusals, export list
An import applies its preview by adding, updating or replacing.
Updating designates one participant by name, first name and, when
given, affiliation; an empty field keeps the stored value, and a row
that designates several is refused. Replacing first counts what it
destroys, reservations and filled titles included. A blocked plan
refuses; a retained one warns of drift. Refused rows come back as a CSV
of the original columns plus line and reason, which reimports as is;
the list exports in the exact form the import reads.
Checked: 59 tests, the round trip field by field and the refusal loop.
--- FR ---
[ADD] csv : import de trois façons, refus réexportés, liste exportée
Un import applique son aperçu en ajoutant, mettant à jour ou
remplaçant. La mise à jour désigne un participant par nom, prénom et,
s'il est donné, appartenance ; un champ vide garde la valeur, et une
ligne qui en désigne plusieurs est refusée. Remplacer compte d'abord ce
qu'il détruit, réservations et titres pourvus compris. Un plan bloqué
refuse ; un plan retenu avertit de la dérive. Les lignes refusées
reviennent en CSV des colonnes d'origine, plus ligne et motif, qui se
réimporte tel quel ; la liste s'exporte dans la forme que l'import lit.
Vérifié : 59 épreuves, l'aller-retour champ par champ et la boucle.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 14:47:25 -04:00
|
|
|
// © 2026 TechnoLibre (http://www.technolibre.ca)
|
|
|
|
|
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
|
|
|
|
|
|
|
|
|
|
// L'export de la liste des participants (§ 10.2, § 10.3), dans la forme exacte
|
|
|
|
|
// que l'import lit : UTF-8 avec marque d'ordre d'octets, « ; », CRLF, les
|
|
|
|
|
// champs de l'import pour en-têtes. Exporter puis réimporter rend les mêmes
|
|
|
|
|
// participants, champ par champ : le fichier sert de sauvegarde, et de gabarit
|
|
|
|
|
// que personne n'a besoin de documenter.
|
|
|
|
|
//
|
|
|
|
|
// L'écriture d'un CSV est unique : le CSV des lignes refusées d'un import passe
|
|
|
|
|
// par ecrireCsv, avec son propre séparateur. Une valeur s'écrit telle quelle,
|
|
|
|
|
// même quand elle commence par « = », « + », « - » ou « @ », qu'un tableur
|
|
|
|
|
// lirait comme une formule : la neutraliser romprait l'aller-retour. Une
|
|
|
|
|
// valeur se relit sans ses blancs de bord, que l'aperçu retire de chaque
|
|
|
|
|
// champ ; une valeur importée n'en porte pas.
|
|
|
|
|
|
|
|
|
|
import { CHAMPS } from './colonnes.js';
|
|
|
|
|
|
|
|
|
|
/** Séparateur de l'export : celui qu'un tableur francophone rouvre sans manipulation (§ 10.3). */
|
|
|
|
|
export const SEPARATEUR = ';';
|
|
|
|
|
|
[ADD] tags and goals: engine measures, CSV column, commands, bridge
Tags on people and goals on tables now reach every layer below the
screens. The engine measures rounds served, never-served people and
facilitators met, with a floor per goal mode at the diagnostic; the CSV
reads and writes an etiquettes column through the shared split and
spelling reconciliation; commands set tags, goals, their rule and the
two optional criteria, each refusal with cause and remedy; facilitators
and the stored priority order reach the engine through one bridge.
Without goals or the facilitator case, plans equal the reference prints.
Checked: node 4373, navigateur 885, node-long 113.
--- FR ---
[ADD] étiquettes et objectifs : mesures, colonne CSV, commandes, pont
Les étiquettes des personnes et les objectifs des tables atteignent toutes
les couches sous les écrans. Le moteur mesure les tours servis, les
personnes jamais servies et les animateurs rencontrés, avec un plancher
par mode au diagnostic ; le CSV lit et écrit une colonne d'étiquettes par
la découpe et la réconciliation communes ; des commandes posent étiquettes,
objectifs, règle et les deux critères facultatifs, chaque refus avec cause
et remède ; animateurs et ordre écrit passent au moteur par un seul pont.
Sans objectif ni case des animateurs, les plans égalent les empreintes.
Vérifié : node 4373, navigateur 885, node-long 113.
Assisted-by: Claude Opus 5.5
2026-10-11 15:03:13 -04:00
|
|
|
/**
|
|
|
|
|
* Jointure des étiquettes d'une cellule (§ 10.2) : une virgule, séparateur
|
|
|
|
|
* que la découpe de la saisie lit (SEPARATEURS_ETIQUETTES), suivie d'une
|
|
|
|
|
* espace, que la mise en forme retire. Une étiquette ne porte aucun
|
|
|
|
|
* séparateur : la cellule se relit en les mêmes étiquettes.
|
|
|
|
|
*/
|
|
|
|
|
export const JOINTURE_ETIQUETTES = ', ';
|
|
|
|
|
|
[ADD] csv: apply an import three ways, re-export refusals, export list
An import applies its preview by adding, updating or replacing.
Updating designates one participant by name, first name and, when
given, affiliation; an empty field keeps the stored value, and a row
that designates several is refused. Replacing first counts what it
destroys, reservations and filled titles included. A blocked plan
refuses; a retained one warns of drift. Refused rows come back as a CSV
of the original columns plus line and reason, which reimports as is;
the list exports in the exact form the import reads.
Checked: 59 tests, the round trip field by field and the refusal loop.
--- FR ---
[ADD] csv : import de trois façons, refus réexportés, liste exportée
Un import applique son aperçu en ajoutant, mettant à jour ou
remplaçant. La mise à jour désigne un participant par nom, prénom et,
s'il est donné, appartenance ; un champ vide garde la valeur, et une
ligne qui en désigne plusieurs est refusée. Remplacer compte d'abord ce
qu'il détruit, réservations et titres pourvus compris. Un plan bloqué
refuse ; un plan retenu avertit de la dérive. Les lignes refusées
reviennent en CSV des colonnes d'origine, plus ligne et motif, qui se
réimporte tel quel ; la liste s'exporte dans la forme que l'import lit.
Vérifié : 59 épreuves, l'aller-retour champ par champ et la boucle.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 14:47:25 -04:00
|
|
|
const MARQUE_ORDRE_OCTETS = '\u{FEFF}';
|
|
|
|
|
const FIN_DE_LIGNE = '\r\n';
|
|
|
|
|
const GUILLEMET = '"';
|
|
|
|
|
|
|
|
|
|
// Les deux valeurs écrites d'« exclu », que la liste fermée de l'aperçu
|
|
|
|
|
// relit : oui pour vrai, non pour faux.
|
|
|
|
|
const OUI = 'oui';
|
|
|
|
|
const NON = 'non';
|
|
|
|
|
|
|
|
|
|
// Propriété du participant que porte chaque champ de CHAMPS.
|
|
|
|
|
const PROPRIETE_DU_CHAMP = new Map([
|
|
|
|
|
['nom', 'nom'],
|
|
|
|
|
['prenom', 'prenom'],
|
|
|
|
|
['appartenance', 'appartenance'],
|
|
|
|
|
['courriel', 'courriel'],
|
|
|
|
|
['titre_pressenti', 'titrePressenti'],
|
|
|
|
|
['exclu', 'exclu'],
|
|
|
|
|
['notes', 'notes'],
|
[ADD] tags and goals: engine measures, CSV column, commands, bridge
Tags on people and goals on tables now reach every layer below the
screens. The engine measures rounds served, never-served people and
facilitators met, with a floor per goal mode at the diagnostic; the CSV
reads and writes an etiquettes column through the shared split and
spelling reconciliation; commands set tags, goals, their rule and the
two optional criteria, each refusal with cause and remedy; facilitators
and the stored priority order reach the engine through one bridge.
Without goals or the facilitator case, plans equal the reference prints.
Checked: node 4373, navigateur 885, node-long 113.
--- FR ---
[ADD] étiquettes et objectifs : mesures, colonne CSV, commandes, pont
Les étiquettes des personnes et les objectifs des tables atteignent toutes
les couches sous les écrans. Le moteur mesure les tours servis, les
personnes jamais servies et les animateurs rencontrés, avec un plancher
par mode au diagnostic ; le CSV lit et écrit une colonne d'étiquettes par
la découpe et la réconciliation communes ; des commandes posent étiquettes,
objectifs, règle et les deux critères facultatifs, chaque refus avec cause
et remède ; animateurs et ordre écrit passent au moteur par un seul pont.
Sans objectif ni case des animateurs, les plans égalent les empreintes.
Vérifié : node 4373, navigateur 885, node-long 113.
Assisted-by: Claude Opus 5.5
2026-10-11 15:03:13 -04:00
|
|
|
['etiquettes', 'etiquettes'],
|
[ADD] csv: apply an import three ways, re-export refusals, export list
An import applies its preview by adding, updating or replacing.
Updating designates one participant by name, first name and, when
given, affiliation; an empty field keeps the stored value, and a row
that designates several is refused. Replacing first counts what it
destroys, reservations and filled titles included. A blocked plan
refuses; a retained one warns of drift. Refused rows come back as a CSV
of the original columns plus line and reason, which reimports as is;
the list exports in the exact form the import reads.
Checked: 59 tests, the round trip field by field and the refusal loop.
--- FR ---
[ADD] csv : import de trois façons, refus réexportés, liste exportée
Un import applique son aperçu en ajoutant, mettant à jour ou
remplaçant. La mise à jour désigne un participant par nom, prénom et,
s'il est donné, appartenance ; un champ vide garde la valeur, et une
ligne qui en désigne plusieurs est refusée. Remplacer compte d'abord ce
qu'il détruit, réservations et titres pourvus compris. Un plan bloqué
refuse ; un plan retenu avertit de la dérive. Les lignes refusées
reviennent en CSV des colonnes d'origine, plus ligne et motif, qui se
réimporte tel quel ; la liste s'exporte dans la forme que l'import lit.
Vérifié : 59 épreuves, l'aller-retour champ par champ et la boucle.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 14:47:25 -04:00
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
// Un champ s'écrit cité (RFC 4180) quand il porte le séparateur, un retour
|
|
|
|
|
// chariot ou un saut de ligne, que la découpe lirait sinon comme des
|
|
|
|
|
// frontières, ou un guillemet, qui en tête ouvrirait un champ cité.
|
|
|
|
|
const SIGNES_A_CITER = /["\r\n]/;
|
|
|
|
|
const aCiter = (champ, separateur) => champ.includes(separateur) || SIGNES_A_CITER.test(champ);
|
|
|
|
|
|
|
|
|
|
// Champ cité : entre guillemets, chaque guillemet doublé.
|
|
|
|
|
const citer = (champ) => GUILLEMET + champ.replaceAll(GUILLEMET, GUILLEMET + GUILLEMET) + GUILLEMET;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Octets d'un CSV : la marque d'ordre d'octets UTF-8, puis chaque
|
|
|
|
|
* enregistrement, ses champs joints par le séparateur, terminé par CRLF,
|
|
|
|
|
* dernier compris. Un champ qui porte le séparateur, un guillemet, un retour
|
|
|
|
|
* chariot ou un saut de ligne s'écrit entre guillemets, les siens doublés ;
|
|
|
|
|
* tout autre champ s'écrit tel quel, blancs compris. decouper relit chaque
|
|
|
|
|
* enregistrement tel qu'il est donné, sous le même séparateur.
|
|
|
|
|
*
|
|
|
|
|
* @param {string[][]} enregistrements
|
|
|
|
|
* @param {string} separateur un caractère
|
|
|
|
|
* @returns {Uint8Array} UTF-8 avec marque
|
|
|
|
|
*/
|
|
|
|
|
export function ecrireCsv(enregistrements, separateur) {
|
|
|
|
|
const lignes = enregistrements.map(
|
|
|
|
|
(enregistrement) =>
|
|
|
|
|
enregistrement.map((champ) => (aCiter(champ, separateur) ? citer(champ) : champ)).join(separateur) + FIN_DE_LIGNE,
|
|
|
|
|
);
|
|
|
|
|
return new TextEncoder().encode(MARQUE_ORDRE_OCTETS + lignes.join(''));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Cellule d'un champ de CHAMPS pour le participant de rang donné, à partir
|
[ADD] tags and goals: engine measures, CSV column, commands, bridge
Tags on people and goals on tables now reach every layer below the
screens. The engine measures rounds served, never-served people and
facilitators met, with a floor per goal mode at the diagnostic; the CSV
reads and writes an etiquettes column through the shared split and
spelling reconciliation; commands set tags, goals, their rule and the
two optional criteria, each refusal with cause and remedy; facilitators
and the stored priority order reach the engine through one bridge.
Without goals or the facilitator case, plans equal the reference prints.
Checked: node 4373, navigateur 885, node-long 113.
--- FR ---
[ADD] étiquettes et objectifs : mesures, colonne CSV, commandes, pont
Les étiquettes des personnes et les objectifs des tables atteignent toutes
les couches sous les écrans. Le moteur mesure les tours servis, les
personnes jamais servies et les animateurs rencontrés, avec un plancher
par mode au diagnostic ; le CSV lit et écrit une colonne d'étiquettes par
la découpe et la réconciliation communes ; des commandes posent étiquettes,
objectifs, règle et les deux critères facultatifs, chaque refus avec cause
et remède ; animateurs et ordre écrit passent au moteur par un seul pont.
Sans objectif ni case des animateurs, les plans égalent les empreintes.
Vérifié : node 4373, navigateur 885, node-long 113.
Assisted-by: Claude Opus 5.5
2026-10-11 15:03:13 -04:00
|
|
|
// de 0 : exclu en oui ou non, les étiquettes jointes par JOINTURE_ETIQUETTES
|
|
|
|
|
// dans l'ordre de leur liste, vide quand la clé manque, un texte tel quel,
|
|
|
|
|
// null vide. Lèvent TypeError un exclu qui n'est pas un booléen, des
|
|
|
|
|
// étiquettes présentes qui ne sont pas une liste de textes, un nom qui n'est
|
|
|
|
|
// pas une chaîne, un autre texte ni chaîne ni null. Écrit sans bruit « non »
|
|
|
|
|
// ou vide, un exclu de travers réinviterait au réimport une personne qui
|
|
|
|
|
// s'est désistée ; un texte d'un autre genre lèverait plus loin, dans
|
|
|
|
|
// l'écriture, sans nommer ni la personne ni le champ.
|
[ADD] csv: apply an import three ways, re-export refusals, export list
An import applies its preview by adding, updating or replacing.
Updating designates one participant by name, first name and, when
given, affiliation; an empty field keeps the stored value, and a row
that designates several is refused. Replacing first counts what it
destroys, reservations and filled titles included. A blocked plan
refuses; a retained one warns of drift. Refused rows come back as a CSV
of the original columns plus line and reason, which reimports as is;
the list exports in the exact form the import reads.
Checked: 59 tests, the round trip field by field and the refusal loop.
--- FR ---
[ADD] csv : import de trois façons, refus réexportés, liste exportée
Un import applique son aperçu en ajoutant, mettant à jour ou
remplaçant. La mise à jour désigne un participant par nom, prénom et,
s'il est donné, appartenance ; un champ vide garde la valeur, et une
ligne qui en désigne plusieurs est refusée. Remplacer compte d'abord ce
qu'il détruit, réservations et titres pourvus compris. Un plan bloqué
refuse ; un plan retenu avertit de la dérive. Les lignes refusées
reviennent en CSV des colonnes d'origine, plus ligne et motif, qui se
réimporte tel quel ; la liste s'exporte dans la forme que l'import lit.
Vérifié : 59 épreuves, l'aller-retour champ par champ et la boucle.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 14:47:25 -04:00
|
|
|
function cellule(participant, champ, rang) {
|
|
|
|
|
const valeur = participant[PROPRIETE_DU_CHAMP.get(champ)];
|
|
|
|
|
const refuser = (attendu) => {
|
|
|
|
|
const recu = JSON.stringify(valeur) ?? String(valeur);
|
|
|
|
|
throw new TypeError(`participant ${rang + 1} de la liste, ${champ} : ${attendu} attendu, reçu ${recu}`);
|
|
|
|
|
};
|
|
|
|
|
if (champ === 'exclu') {
|
|
|
|
|
if (typeof valeur !== 'boolean') refuser('booléen');
|
|
|
|
|
return valeur ? OUI : NON;
|
|
|
|
|
}
|
[ADD] tags and goals: engine measures, CSV column, commands, bridge
Tags on people and goals on tables now reach every layer below the
screens. The engine measures rounds served, never-served people and
facilitators met, with a floor per goal mode at the diagnostic; the CSV
reads and writes an etiquettes column through the shared split and
spelling reconciliation; commands set tags, goals, their rule and the
two optional criteria, each refusal with cause and remedy; facilitators
and the stored priority order reach the engine through one bridge.
Without goals or the facilitator case, plans equal the reference prints.
Checked: node 4373, navigateur 885, node-long 113.
--- FR ---
[ADD] étiquettes et objectifs : mesures, colonne CSV, commandes, pont
Les étiquettes des personnes et les objectifs des tables atteignent toutes
les couches sous les écrans. Le moteur mesure les tours servis, les
personnes jamais servies et les animateurs rencontrés, avec un plancher
par mode au diagnostic ; le CSV lit et écrit une colonne d'étiquettes par
la découpe et la réconciliation communes ; des commandes posent étiquettes,
objectifs, règle et les deux critères facultatifs, chaque refus avec cause
et remède ; animateurs et ordre écrit passent au moteur par un seul pont.
Sans objectif ni case des animateurs, les plans égalent les empreintes.
Vérifié : node 4373, navigateur 885, node-long 113.
Assisted-by: Claude Opus 5.5
2026-10-11 15:03:13 -04:00
|
|
|
if (champ === 'etiquettes') {
|
|
|
|
|
if (!Object.hasOwn(participant, 'etiquettes')) return '';
|
|
|
|
|
if (!Array.isArray(valeur) || !valeur.every((motCle) => typeof motCle === 'string')) refuser('liste de textes');
|
|
|
|
|
return valeur.join(JOINTURE_ETIQUETTES);
|
|
|
|
|
}
|
[ADD] csv: apply an import three ways, re-export refusals, export list
An import applies its preview by adding, updating or replacing.
Updating designates one participant by name, first name and, when
given, affiliation; an empty field keeps the stored value, and a row
that designates several is refused. Replacing first counts what it
destroys, reservations and filled titles included. A blocked plan
refuses; a retained one warns of drift. Refused rows come back as a CSV
of the original columns plus line and reason, which reimports as is;
the list exports in the exact form the import reads.
Checked: 59 tests, the round trip field by field and the refusal loop.
--- FR ---
[ADD] csv : import de trois façons, refus réexportés, liste exportée
Un import applique son aperçu en ajoutant, mettant à jour ou
remplaçant. La mise à jour désigne un participant par nom, prénom et,
s'il est donné, appartenance ; un champ vide garde la valeur, et une
ligne qui en désigne plusieurs est refusée. Remplacer compte d'abord ce
qu'il détruit, réservations et titres pourvus compris. Un plan bloqué
refuse ; un plan retenu avertit de la dérive. Les lignes refusées
reviennent en CSV des colonnes d'origine, plus ligne et motif, qui se
réimporte tel quel ; la liste s'exporte dans la forme que l'import lit.
Vérifié : 59 épreuves, l'aller-retour champ par champ et la boucle.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 14:47:25 -04:00
|
|
|
if (valeur === null && champ !== 'nom') return '';
|
|
|
|
|
if (typeof valeur !== 'string') refuser(champ === 'nom' ? 'texte' : 'texte ou null');
|
|
|
|
|
return valeur;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* La liste des participants en CSV, dans la forme exacte que l'import lit
|
|
|
|
|
* (§ 10.2) : UTF-8 avec marque, « ; », CRLF ; l'en-tête
|
[ADD] tags and goals: engine measures, CSV column, commands, bridge
Tags on people and goals on tables now reach every layer below the
screens. The engine measures rounds served, never-served people and
facilitators met, with a floor per goal mode at the diagnostic; the CSV
reads and writes an etiquettes column through the shared split and
spelling reconciliation; commands set tags, goals, their rule and the
two optional criteria, each refusal with cause and remedy; facilitators
and the stored priority order reach the engine through one bridge.
Without goals or the facilitator case, plans equal the reference prints.
Checked: node 4373, navigateur 885, node-long 113.
--- FR ---
[ADD] étiquettes et objectifs : mesures, colonne CSV, commandes, pont
Les étiquettes des personnes et les objectifs des tables atteignent toutes
les couches sous les écrans. Le moteur mesure les tours servis, les
personnes jamais servies et les animateurs rencontrés, avec un plancher
par mode au diagnostic ; le CSV lit et écrit une colonne d'étiquettes par
la découpe et la réconciliation communes ; des commandes posent étiquettes,
objectifs, règle et les deux critères facultatifs, chaque refus avec cause
et remède ; animateurs et ordre écrit passent au moteur par un seul pont.
Sans objectif ni case des animateurs, les plans égalent les empreintes.
Vérifié : node 4373, navigateur 885, node-long 113.
Assisted-by: Claude Opus 5.5
2026-10-11 15:03:13 -04:00
|
|
|
* nom;prenom;appartenance;courriel;titre_pressenti;exclu;notes;etiquettes,
|
|
|
|
|
* les champs de CHAMPS dans leur ordre ; puis un participant par ligne, dans
|
|
|
|
|
* l'ordre de la liste reçue, que la charge range par identifiant. exclu
|
|
|
|
|
* s'écrit oui ou non, un champ null vide, la colonne etiquettes toujours,
|
|
|
|
|
* ses étiquettes jointes par « , », vide sans étiquette ; un champ qui porte
|
|
|
|
|
* « ; », un guillemet ou une fin de ligne entre guillemets. L'identifiant ne s'écrit pas : le réimport en
|
[ADD] csv: apply an import three ways, re-export refusals, export list
An import applies its preview by adding, updating or replacing.
Updating designates one participant by name, first name and, when
given, affiliation; an empty field keeps the stored value, and a row
that designates several is refused. Replacing first counts what it
destroys, reservations and filled titles included. A blocked plan
refuses; a retained one warns of drift. Refused rows come back as a CSV
of the original columns plus line and reason, which reimports as is;
the list exports in the exact form the import reads.
Checked: 59 tests, the round trip field by field and the refusal loop.
--- FR ---
[ADD] csv : import de trois façons, refus réexportés, liste exportée
Un import applique son aperçu en ajoutant, mettant à jour ou
remplaçant. La mise à jour désigne un participant par nom, prénom et,
s'il est donné, appartenance ; un champ vide garde la valeur, et une
ligne qui en désigne plusieurs est refusée. Remplacer compte d'abord ce
qu'il détruit, réservations et titres pourvus compris. Un plan bloqué
refuse ; un plan retenu avertit de la dérive. Les lignes refusées
reviennent en CSV des colonnes d'origine, plus ligne et motif, qui se
réimporte tel quel ; la liste s'exporte dans la forme que l'import lit.
Vérifié : 59 épreuves, l'aller-retour champ par champ et la boucle.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 14:47:25 -04:00
|
|
|
* attribue de neufs. La liste reçue n'est pas modifiée.
|
|
|
|
|
*
|
|
|
|
|
* @param {import('../stockage/types.js').Participant[]} participants
|
|
|
|
|
* @returns {Uint8Array}
|
[ADD] tags and goals: engine measures, CSV column, commands, bridge
Tags on people and goals on tables now reach every layer below the
screens. The engine measures rounds served, never-served people and
facilitators met, with a floor per goal mode at the diagnostic; the CSV
reads and writes an etiquettes column through the shared split and
spelling reconciliation; commands set tags, goals, their rule and the
two optional criteria, each refusal with cause and remedy; facilitators
and the stored priority order reach the engine through one bridge.
Without goals or the facilitator case, plans equal the reference prints.
Checked: node 4373, navigateur 885, node-long 113.
--- FR ---
[ADD] étiquettes et objectifs : mesures, colonne CSV, commandes, pont
Les étiquettes des personnes et les objectifs des tables atteignent toutes
les couches sous les écrans. Le moteur mesure les tours servis, les
personnes jamais servies et les animateurs rencontrés, avec un plancher
par mode au diagnostic ; le CSV lit et écrit une colonne d'étiquettes par
la découpe et la réconciliation communes ; des commandes posent étiquettes,
objectifs, règle et les deux critères facultatifs, chaque refus avec cause
et remède ; animateurs et ordre écrit passent au moteur par un seul pont.
Sans objectif ni case des animateurs, les plans égalent les empreintes.
Vérifié : node 4373, navigateur 885, node-long 113.
Assisted-by: Claude Opus 5.5
2026-10-11 15:03:13 -04:00
|
|
|
* @throws {TypeError} pour un exclu qui n'est pas un booléen, des étiquettes
|
|
|
|
|
* présentes qui ne sont pas une liste de textes, un nom qui n'est pas une
|
|
|
|
|
* chaîne, un autre texte ni chaîne ni null
|
[ADD] csv: apply an import three ways, re-export refusals, export list
An import applies its preview by adding, updating or replacing.
Updating designates one participant by name, first name and, when
given, affiliation; an empty field keeps the stored value, and a row
that designates several is refused. Replacing first counts what it
destroys, reservations and filled titles included. A blocked plan
refuses; a retained one warns of drift. Refused rows come back as a CSV
of the original columns plus line and reason, which reimports as is;
the list exports in the exact form the import reads.
Checked: 59 tests, the round trip field by field and the refusal loop.
--- FR ---
[ADD] csv : import de trois façons, refus réexportés, liste exportée
Un import applique son aperçu en ajoutant, mettant à jour ou
remplaçant. La mise à jour désigne un participant par nom, prénom et,
s'il est donné, appartenance ; un champ vide garde la valeur, et une
ligne qui en désigne plusieurs est refusée. Remplacer compte d'abord ce
qu'il détruit, réservations et titres pourvus compris. Un plan bloqué
refuse ; un plan retenu avertit de la dérive. Les lignes refusées
reviennent en CSV des colonnes d'origine, plus ligne et motif, qui se
réimporte tel quel ; la liste s'exporte dans la forme que l'import lit.
Vérifié : 59 épreuves, l'aller-retour champ par champ et la boucle.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 14:47:25 -04:00
|
|
|
*/
|
|
|
|
|
export function exporterParticipants(participants) {
|
|
|
|
|
const lignes = participants.map((participant, rang) => CHAMPS.map((champ) => cellule(participant, champ, rang)));
|
|
|
|
|
return ecrireCsv([[...CHAMPS], ...lignes], SEPARATEUR);
|
|
|
|
|
}
|