diff --git a/doc/captures/01b-passer-en-ecriture.png b/doc/captures/01b-passer-en-ecriture.png index d619c41..6d9a889 100644 Binary files a/doc/captures/01b-passer-en-ecriture.png and b/doc/captures/01b-passer-en-ecriture.png differ diff --git a/doc/captures/02-import-apercu.png b/doc/captures/02-import-apercu.png index 497f6b4..03f22ad 100644 Binary files a/doc/captures/02-import-apercu.png and b/doc/captures/02-import-apercu.png differ diff --git a/doc/captures/02b-import-cp1252.png b/doc/captures/02b-import-cp1252.png index 04a2b53..79b6c35 100644 Binary files a/doc/captures/02b-import-cp1252.png and b/doc/captures/02b-import-cp1252.png differ diff --git a/doc/captures/03-import-rapport.png b/doc/captures/03-import-rapport.png index e1f9237..557bd0d 100644 Binary files a/doc/captures/03-import-rapport.png and b/doc/captures/03-import-rapport.png differ diff --git a/doc/captures/04-grille-participants.png b/doc/captures/04-grille-participants.png index fc754ee..f3dea54 100644 Binary files a/doc/captures/04-grille-participants.png and b/doc/captures/04-grille-participants.png differ diff --git a/doc/captures/05-tables-etat.png b/doc/captures/05-tables-etat.png index b4ff9ed..c9b4363 100644 Binary files a/doc/captures/05-tables-etat.png and b/doc/captures/05-tables-etat.png differ diff --git a/doc/captures/06-defaut-consequence.png b/doc/captures/06-defaut-consequence.png index feb8185..0960859 100644 Binary files a/doc/captures/06-defaut-consequence.png and b/doc/captures/06-defaut-consequence.png differ diff --git a/doc/captures/07-plan-tables.png b/doc/captures/07-plan-tables.png index f899442..37b217f 100644 Binary files a/doc/captures/07-plan-tables.png and b/doc/captures/07-plan-tables.png differ diff --git a/doc/captures/07a-cibles-sieges.png b/doc/captures/07a-cibles-sieges.png index e2025f6..f4485af 100644 Binary files a/doc/captures/07a-cibles-sieges.png and b/doc/captures/07a-cibles-sieges.png differ diff --git a/doc/captures/07a-cibles-tables.png b/doc/captures/07a-cibles-tables.png index 57839da..82b383d 100644 Binary files a/doc/captures/07a-cibles-tables.png and b/doc/captures/07a-cibles-tables.png differ diff --git a/doc/captures/07b-nombre-de-tours.png b/doc/captures/07b-nombre-de-tours.png index c39a813..8b95b7f 100644 Binary files a/doc/captures/07b-nombre-de-tours.png and b/doc/captures/07b-nombre-de-tours.png differ diff --git a/doc/captures/08-animateurs-designes.png b/doc/captures/08-animateurs-designes.png index 08d102f..91820ab 100644 Binary files a/doc/captures/08-animateurs-designes.png and b/doc/captures/08-animateurs-designes.png differ diff --git a/doc/captures/09-refus-sur-place.png b/doc/captures/09-refus-sur-place.png index 3833717..169ba2c 100644 Binary files a/doc/captures/09-refus-sur-place.png and b/doc/captures/09-refus-sur-place.png differ diff --git a/doc/captures/10-diagnostic.png b/doc/captures/10-diagnostic.png index 8a411aa..16e1d56 100644 Binary files a/doc/captures/10-diagnostic.png and b/doc/captures/10-diagnostic.png differ diff --git a/doc/captures/11-propositions.png b/doc/captures/11-propositions.png index 00c930e..6e32271 100644 Binary files a/doc/captures/11-propositions.png and b/doc/captures/11-propositions.png differ diff --git a/doc/captures/19-ajustement.png b/doc/captures/19-ajustement.png index a76c33d..25dacc1 100644 Binary files a/doc/captures/19-ajustement.png and b/doc/captures/19-ajustement.png differ diff --git a/doc/captures/20-mode-lecture.png b/doc/captures/20-mode-lecture.png index 1d870dc..a59d6a7 100644 Binary files a/doc/captures/20-mode-lecture.png and b/doc/captures/20-mode-lecture.png differ diff --git a/doc/captures/manifeste.json b/doc/captures/manifeste.json index 01eacab..df1aa61 100644 --- a/doc/captures/manifeste.json +++ b/doc/captures/manifeste.json @@ -1,22 +1,22 @@ {"captures":[ {"cadre":{"hauteur":700,"largeur":1366},"empreinte":"3d457536d0600103ea1141c08871a4aebb7c5ef455311fe8201a817f38d7bca0","etape":"1","etat":null,"facteurEchelle":1,"fichier":"01-premier-ecran","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"22433fa483e23340e474b89d0dcf084f9ab6b6d254f3867fe5006846ee1fb0a1"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Clair","Sombre","À propos","Liste des événements","version","construction de documentation","Le dossier de l'exécutable n'est pas connu : les événements se rangent dans les Documents.","Dossier de travail","C:\\Users\\Exemple\\Documents\\Gestion table tournante Libre","Ouvrir dans l’explorateur","Créer un événement","Nom de l’événement","Date, facultative (AAAA-MM-JJ)","Créer l’événement","Importer un événement depuis un fichier…","Démonstrations","Chacune se charge comme un nouvel événement, numéroté et ouvert en lecture ; aucun autre événement n’est touché.","Grande démonstration","Grande démonstration sans exception","Petite démonstration","Petite démonstration, conflit inévitable"],"theme":"clair","versionReelle":"2026.10.05.01"}, -{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"0023540aac46fdec821d303affd3f2c56887ddaece22471a203ad0abec7f14b1","etape":"1b","etat":"ab468ad775d39cda60057d23f67ba34d787dda85b66c87b5500b41bff1b2b630","facteurEchelle":1,"fichier":"01b-passer-en-ecriture","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"4d431e8aff586a750d02909023fe62e9ade39429937d58a054b26c5ebc14d826"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-lecture","ratio":5.29,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5},{"jeton":"--couleur-refus","ratio":8.76,"role":"texte","seuil":4.5}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-lecture","ratio":7.34,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5},{"jeton":"--couleur-refus","ratio":9.24,"role":"texte","seuil":4.5}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Lecture","Liste des événements","Clair","Sombre","À propos","Modifier","Lecture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Tables et tours","Places par défaut","Nombre de tours","Tables","Ajouter une table ronde","L'événement est ouvert en lecture : « Modifier » permet de le changer.","Modifier","Ajouter une table carrée","Aucune table : ajoutez-en une, ronde ou carrée."],"theme":"clair","versionReelle":"2026.10.05.01"}, -{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"3ad6f4328868a85de8f0c0aae7164d41cf786b90882aaaf6a2eb244eea48f4ec","etape":"2","etat":"4acf3230b0733a35d33c6baf84b7d4f312e98a5b799147dcea6b3bb5d4f082d5","facteurEchelle":1,"fichier":"02-import-apercu","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"67c04c11a309a028bc0718b7d0c34ca5b71845e96f646740be57593ff63275f3"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":4.78,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":9.1,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Import","Choisissez un fichier CSV ou déposez-le sur la fenêtre ; une plage collée dans la grille des participants arrive ici. Rien ne s'importe avant l'aperçu.","Choisir un fichier CSV…","Aperçu","Mode de l'import","Ajouter","Mettre à jour","Remplacer","Fichier","participants_cas_limites.csv","Encodage","UTF-8 avec marque","Séparateur","point-virgule","Colonnes","En-tête","Devient","Nom","nom","Prénom","prénom","Organisation","appartenance","Courriel","courriel","Rôle","titre pressenti","Exclu","exclu","Notes","notes","Téléphone","non reconnue : ignorée","13","lignes valides","Ligne","nom","prénom","appartenance","courriel","titre pressenti","exclu","notes","2","Lanterneau","Basile","Chœur de l’Anse","basile.lanterneau@exemple.test","animation","3","Pommerel","Capucine","Société des Hérons","capucine.pommerel@exemple.test","4","Marbrelle","Gaspard","Cercle des Saules","animation","5","Sablonnet","Ysaline","Chœur de l’Anse","6","Givrecœur","Anselme","anselme.givrecoeur@exemple.test","7","Tourterel","Héloïse","Cercle des Saules","oui","S’est désistée la veille","8","Fenouillet","Côme","Société des Hérons","végétarien; sans noix, ni arachides","9","Coudraie","Apolline","Chœur de l’Anse","Arrive après le premier tour repart avant le dessert","10","Lanterneau","Basile","Chœur de l’Anse","11","Brunœil","Cercle des Saules","brunoeil@exemple.test","12","Ormelin","Faustine","Société des Hérons","14","Ardoisier","Edgar","Société des Hérons","15","Cressonnier","Bertille","Cercle des Saules","Lignes refusées","Ligne","Motif","13","Le nom manque.","Orthographes fondues en une appartenance","affichée :","Société des Hérons","Société des Hérons","3","lignes","Societe des herons","1","ligne","Doublons signalés, jamais fusionnés","lignes","2","10","Importer","Enregistrer les lignes refusées","Fermer l'aperçu"],"theme":"clair","versionReelle":"2026.10.05.01"}, -{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"a9c6a351e2789fd1c5a5fcc3fc9b7fa2f4317d74f5a03628fc4ae9f743f66350","etape":"2","etat":"4acf3230b0733a35d33c6baf84b7d4f312e98a5b799147dcea6b3bb5d4f082d5","facteurEchelle":1,"fichier":"02b-import-cp1252","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"1bf8d5408e9410f02765011540c1824e5b0137e3c8a29a0ba740e98e000fb186"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":4.78,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":9.1,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Import","Choisissez un fichier CSV ou déposez-le sur la fenêtre ; une plage collée dans la grille des participants arrive ici. Rien ne s'importe avant l'aperçu.","Choisir un fichier CSV…","Aperçu","Mode de l'import","Ajouter","Mettre à jour","Remplacer","Fichier","participants_cas_limites_cp1252.csv","Encodage","windows-1252","Séparateur","virgule","Colonnes","En-tête","Devient","Nom","nom","Prénom","prénom","Organisation","appartenance","Courriel","courriel","Rôle","titre pressenti","Exclu","exclu","Notes","notes","Téléphone","non reconnue : ignorée","13","lignes valides","Ligne","nom","prénom","appartenance","courriel","titre pressenti","exclu","notes","2","Lanterneau","Basile","Chœur de l’Anse","basile.lanterneau@exemple.test","animation","3","Pommerel","Capucine","Société des Hérons","capucine.pommerel@exemple.test","4","Marbrelle","Gaspard","Cercle des Saules","animation","5","Sablonnet","Ysaline","Chœur de l’Anse","6","Givrecœur","Anselme","anselme.givrecoeur@exemple.test","7","Tourterel","Héloïse","Cercle des Saules","oui","S’est désistée la veille","8","Fenouillet","Côme","Société des Hérons","végétarien; sans noix, ni arachides","9","Coudraie","Apolline","Chœur de l’Anse","Arrive après le premier tour repart avant le dessert","10","Lanterneau","Basile","Chœur de l’Anse","11","Brunœil","Cercle des Saules","brunoeil@exemple.test","12","Ormelin","Faustine","Société des Hérons","14","Ardoisier","Edgar","Société des Hérons","15","Cressonnier","Bertille","Cercle des Saules","Lignes refusées","Ligne","Motif","13","Le nom manque.","Orthographes fondues en une appartenance","affichée :","Société des Hérons","Société des Hérons","3","lignes","Societe des herons","1","ligne","Doublons signalés, jamais fusionnés","lignes","2","10","Importer","Enregistrer les lignes refusées","Fermer l'aperçu"],"theme":"clair","versionReelle":"2026.10.05.01"}, -{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"8f44e483f92bcc714de0a16d062d218393b778797bb5e9a50497d0e3a24b9170","etape":"2","etat":"b3119a32dda90f0c824bb31f31cb2f5a58af891b3338215d7efabf785b0a5d48","facteurEchelle":1,"fichier":"03-import-rapport","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"5bf126478eaa23cec5b164a9e2d43477995fa2f04384e717ce642e917cf37952"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":4.78,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":9.1,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Il manque 4 places à chaque tour pour asseoir toutes les personnes : ajouter des tables ou des sièges, ou exclure des personnes, rend la génération possible.","Ouvrir les tables","Import","Choisissez un fichier CSV ou déposez-le sur la fenêtre ; une plage collée dans la grille des participants arrive ici. Rien ne s'importe avant l'aperçu.","Choisir un fichier CSV…","Rapport d'import","13","personnes ajoutées","0","personne mise à jour","0","personne inchangée","0","personne retirée","0","réservation retirée","Fichier","participants_cas_limites.csv","Encodage","UTF-8 avec marque","Séparateur","point-virgule","Colonnes","En-tête","Devient","Nom","nom","Prénom","prénom","Organisation","appartenance","Courriel","courriel","Rôle","titre pressenti","Exclu","exclu","Notes","notes","Téléphone","non reconnue : ignorée","13","lignes valides","Ligne","nom","prénom","appartenance","courriel","titre pressenti","exclu","notes","2","Lanterneau","Basile","Chœur de l’Anse","basile.lanterneau@exemple.test","animation","3","Pommerel","Capucine","Société des Hérons","capucine.pommerel@exemple.test","4","Marbrelle","Gaspard","Cercle des Saules","animation","5","Sablonnet","Ysaline","Chœur de l’Anse","6","Givrecœur","Anselme","anselme.givrecoeur@exemple.test","7","Tourterel","Héloïse","Cercle des Saules","oui","S’est désistée la veille","8","Fenouillet","Côme","Société des Hérons","végétarien; sans noix, ni arachides","9","Coudraie","Apolline","Chœur de l’Anse","Arrive après le premier tour repart avant le dessert","10","Lanterneau","Basile","Chœur de l’Anse","11","Brunœil","Cercle des Saules","brunoeil@exemple.test","12","Ormelin","Faustine","Société des Hérons","14","Ardoisier","Edgar","Société des Hérons","15","Cressonnier","Bertille","Cercle des Saules","Lignes refusées","Ligne","Motif","13","Le nom manque.","Orthographes fondues en une appartenance","affichée :","Société des Hérons","Société des Hérons","3","lignes","Societe des herons","1","ligne","Doublons signalés, jamais fusionnés","lignes","2","10","Enregistrer les lignes refusées","Fermer le rapport"],"theme":"clair","versionReelle":"2026.10.05.01"}, -{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"57beb21ea94036118cb17e1dcd3815d26c5b4398c1f6b0a5b75f52830b9d26a0","etape":"3","etat":"a220b2f80cc83728c43e0bcca0bb785ce7e7b4fa5c3fea5289d095d09a911535","facteurEchelle":1,"fichier":"04-grille-participants","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"e877a0c8abfae2558ec08a72b8eb5bb27ba50c7121724e9a9ba7fff5c88cf6ab"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":4.78,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":9.1,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Il manque 4 places à chaque tour pour asseoir toutes les personnes : ajouter des tables ou des sièges, ou exclure des personnes, rend la génération possible.","Ouvrir les tables","Participants","Ajouter une personne","Nom","Prénom","Appartenance","Courriel","Titre pressenti","Notes","Ajouter","Filtrer","Grouper par","Aucun groupement","Nom","Prénom","Appartenance","Courriel","Titre pressenti","Exclusion","Notes","Statut","13 participants","Exporter la liste","Nom","(décroissant)","Prénom","Appartenance","Courriel","Titre pressenti","Exclusion","Notes","Actions","Tourterel","Héloïse","Cercle des Saules","exclue","S’est désistée la veille","Fiche","Voir sur le plan","Réintégrer","Supprimer","Sablonnet","Ysaline","Chœur de l’Anse","présente","Fiche","Voir sur le plan","Exclure","Supprimer","Pommerel","Capucine","Société des Hérons","capucine.pommerel@exemple.test","présente","Fiche","Voir sur le plan","Exclure","Supprimer","Ormelin","Faustine","Société des Hérons","présente","Fiche","Voir sur le plan","Exclure","Supprimer","Marbrelle","Gaspard","Cercle des Saules","ondine@exemple.test","animation","présente","Fiche","Voir sur le plan","Exclure","Supprimer","Lanterneau","Basile","Chœur de l’Anse","basile.lanterneau@exemple.test","animation","présente","Fiche","Voir sur le plan","Exclure","Supprimer","Lanterneau","Basile","Chœur de l’Anse","présente","Fiche","Voir sur le plan","Exclure","Supprimer","Givrecœur","Anselme","anselme.givrecoeur@exemple.test","présente","Fiche","Voir sur le plan","Exclure","Supprimer","Fenouillet","Côme","Société des Hérons","présente","végétarien; sans noix, ni arachides","Fiche","Voir sur le plan","Exclure","Supprimer","Cressonnier","Bertille","Cercle des Saules","présente","Fiche","Voir sur le plan","Exclure","Supprimer","Coudraie","Apolline","Chœur de l’Anse","présente","Arrive après le premier tour repart avant le dessert","Fiche","Voir sur le plan","Exclure","Supprimer","Brunœil","Cercle des Saules","brunoeil@exemple.test","présente","Fiche","Voir sur le plan","Exclure","Supprimer","Ardoisier","Edgar","Société des Hérons","présente","Fiche","Voir sur le plan","Exclure","Supprimer"],"theme":"clair","versionReelle":"2026.10.05.01"}, -{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"082a133e76c809940ead417be7cdf66077972ad229b85bac12e80f4b007f3307","etape":"4","etat":"421c6294b4348fa49aa0105ea643fd11c80806a9fbb1e079435adac079e6b260","facteurEchelle":1,"fichier":"05-tables-etat","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"6eb751e9553f8dcf77d07c918f43c5da865b15f2a7f516bb9eb8b87cd8a87a1f"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":4.78,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":9.1,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Tables et tours","Places par défaut","Nombre de tours","Tables","Ajouter une table ronde","Ajouter une table carrée","Table","1","Ronde","Suit le défaut","Places","Supprimer","Table","2","Ronde","Surchargée","Places","Réaligner","Supprimer"],"theme":"clair","versionReelle":"2026.10.05.01"}, -{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"6a48fe8ea1922ed946072eefdd7ca53833d7fe4bd2420543e9ebd3c40612e179","etape":"4","etat":"421c6294b4348fa49aa0105ea643fd11c80806a9fbb1e079435adac079e6b260","facteurEchelle":1,"fichier":"06-defaut-consequence","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"742079465f67a44ae4bcc8028b79b4a1e9bab8c4656d9b633b4d8d6c8455f9a6"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":4.78,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":9.1,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Tables et tours","Places par défaut","1 table suit le défaut et passe de 8 à 10 places ; 1 table surchargée (8) ne change pas.","Total : 16 → 18 sièges pour 12 participants.","Appliquer","Appliquer et réaligner la surchargée","Garder le défaut actuel","Nombre de tours","Tables","Ajouter une table ronde","Ajouter une table carrée","Table","1","Ronde","Suit le défaut","Places","Supprimer","Table","2","Ronde","Surchargée","Places","Réaligner","Supprimer"],"theme":"clair","versionReelle":"2026.10.05.01"}, -{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"e650f15bb5c51bec4160ff76219fe77902bf42d1e9ab47d46b9f81e4c5055844","etape":"4","etat":"7d42132a2caa999f9d046f580b1093732ebb44984b8fdec5b27da7e42801678e","facteurEchelle":1,"fichier":"07-plan-tables","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"ba04243df820caa656e7884ce0e9db02912b6d6203cd0efe889ff5dbe0052354"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":4.78,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":15.1,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":7.58,"role":"marque","seuil":3}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":9.1,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":8.89,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":14.62,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":11.32,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":5.59,"role":"marque","seuil":3}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Plan","Réservations","Tour affiché","1","2","3","Zoom +","Zoom −","Ajuster","Listes de noms","Légende","Plein écran","1. (libre)","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","9. (libre)","10. (libre)","1. (libre)","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1","m","disposition relative — l'encombrement dans la salle n'est pas vérifié","Diagnostic","Chœur de l’Anse","4 personnes : au moins 6 collisions cumulées sur les 3 tours, portées par au moins 2 paires distinctes","Société des Hérons","4 personnes : au moins 6 collisions cumulées sur les 3 tours, portées par au moins 2 paires distinctes","Cercle des Saules","3 personnes : au moins 3 collisions cumulées sur les 3 tours, portées par au moins 1 paire distincte","au moins 8 appartenances recroisées par personne","plafond a priori 11 rencontres pour 12 mobiles","Listes de travail","Titres de place non pourvus","Aucun.","Titres pressentis sans réservation","Basile Lanterneau","— titre pressenti","animation","Gaspard Marbrelle","— titre pressenti","animation","Réserve","Personnes en attente au tour 1","Basile Lanterneau","Capucine Pommerel","Gaspard Marbrelle","Ysaline Sablonnet","Anselme Givrecœur","Côme Fenouillet","Apolline Coudraie","Basile Lanterneau","Brunœil","Faustine Ormelin","Edgar Ardoisier","Bertille Cressonnier"],"theme":"clair","versionReelle":"2026.10.05.01"}, -{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"6aa6e1f767f7608b2d6382064b2f3c6e8b22a59ee1b2155ec262d1c47999bf2e","etape":"4","etat":"4d37d30748068354162752743c26aa7e0ab00d6e9b2aa1996b6f9fb410848280","facteurEchelle":1,"fichier":"07a-cibles-sieges","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"964fd3e038e1c2e09181edca01bbb597a3643b4e5176ca44b9ab8e38808f9c08"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-lecture","ratio":5.29,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-pleine","ratio":15.38,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":15.1,"role":"marque","seuil":3},{"jeton":"--couleur-marque","ratio":3.63,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":7.58,"role":"marque","seuil":3}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-lecture","ratio":7.34,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-pleine","ratio":14.94,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":8.89,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":14.62,"role":"marque","seuil":3},{"jeton":"--couleur-marque","ratio":3.5,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":11.32,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":5.59,"role":"marque","seuil":3}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Lecture","Liste des événements","Clair","Sombre","À propos","Modifier","Lecture","Défaire","Grande démonstration 1","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Plan","Réservations","Tour affiché","1","2","3","4","Zoom +","Zoom −","Ajuster","Listes de noms","Légende","Plein écran","1. (réservée, tous les tours)","Manon Urvançon","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Guillaume Luski…","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Fatima Korvouze","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Antoine Bralmault","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Manon Tolveron","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Philippe Voskeval","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Félix Voskande","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Michel Korveron","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Gabriel Ivreval","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Marc Vandergro…","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Étienne Tolvançon","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Sophie Pruvotte","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Fatima Abrevan…","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Marie Urvard","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Catherine Hulver…","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Camille Neskard","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Youssef Neskière","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Guillaume Dulvi…","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Philippe Ivroubre","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Claire Jusvivet","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Youssef Jusvard","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Louise Neskichon","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Hugo Bralmouze","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Gabriel Abrevault","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Louis Selvivet","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Jean Fralvumet","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Marie Bralmesson","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Thomas Selvignac","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Émilie Abrevière","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Geneviève Dulv…","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","1. (réservée, tous les tours)","François Obrouze","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","1. (réservée, tous les tours)","François Ivrivet","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","1. (réservée, tous les tours)","Samuel Bralmeux","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","1","m","disposition relative — l'encombrement dans la salle n'est pas vérifié","Diagnostic","écart d'itinéraire maximal : plancher 1, au moins 24 mobiles finissent sous leur plafond a priori","plafond a priori 24 rencontres pour 4 ancrés","plafond a priori 28 rencontres pour 29 ancrés et 227 mobiles","99 retours imposés par 33 ancrages","Listes de travail","Titres de place non pourvus","Aucun.","Titres pressentis sans réservation","Aucun.","Réserve","Personnes en attente au tour 1","Isabelle Mirvault","Félix Abrevande","Hugo Fralvançon","Manon Fralveux","Catherine Luskotte","Zoé WAMMERWOLM-MAWWEMMEL","Catherine Urvesson","Karim Hulvivet","Caroline Selveron","Catherine Korvault","Caroline Fralvotte","Geneviève Jusvesson","Paul Abrevumet","Léa Fralvault","Fatima Obrivet","Zoé Dulveval","Paul Korveux","Julie Luskière","Émilie Clovande","Paul Hulvande","Hugo Fralvesson","Isabelle Urvière","Thomas Rozvotte","Isabelle Bralmumet","Catherine Dulvouze","Marc Voskichon","Simon Mirvivet","Louise Clovault","Lucie Voskeux","Amina Eskignac","Luc Selvoubre","Étienne Fralvichon","Philippe Voskivet","Louise Quilmançon","Sophie Luskande","Pierre Abreveron","Philippe Neskeux","Amina Neskançon","Léa Tolvande","Antoine Quilmeron","Guillaume Clovumet","Michel Eskeux","Louise Hulvault","Samuel Eskumet","Claire Fralvivet","Léa Mirveux","Karim Gorzesson","Sylvie Quilmande","François Gorzichon","Amina Pruvesson","Lucie Quilmière","Fatima Korvesson","Nicolas Selvesson","Louise Neskesson","Lucie Tolvesson","Olivier Quilmesson","Guillaume Luskivet","Gabriel Neskault","Antoine Urvumet","Olivier Jusvançon","Simon Dulvançon","Chloé Gorzard","Gabriel Pruveux","Manon Clovière","Karim Tolveval","Hugo Bérêçàuvïlle-Dœûmôntëÿ","Claire Gorzeron","Hélène Luskumet","Louis Fralvande","Émilie Selvault","Léa Neskumet","Isabelle Korvichon","Michel Obrande","Isabelle Luskeval","Fatima Tolvoubre","Zoé Gorzière","Sylvie Korvignac","Antoine Obreval","Camille Tolvumet","Marie Dulvesson","Guillaume Tolvignac","Gabriel Mirvotte","Paul Neskignac","Raphaël Ivrotte","Marc Luskouze","Sylvie Jusvotte","Véronique Bralmoubre","Pierre Selvard","Marie Hulveux","Karim Fralveval","Philippe Gorzignac","Étienne Selvouze","Louis Hulvichon","Sylvie Urvoubre","Pierre Pruveval","Guillaume Hulvotte","Geneviève Abrevignac","Amina Bralmignac","Olivier Bralmançon","Marc Luskoubre","Geneviève Abrevoubre","Raphaël Korvoubre","Pierre Mirvard","Camille Jusvumet","Samuel Cloveval","Antoine Selvière","Véronique Jusvouze","Paul Neskivet","Samuel Dulvande","Lucie Selveval","Olivier Tolvichon","Fatima Hulvard","Alexandre Ivreux","Félix Korveval","Karim Urvichon","Émilie Dulvichon","Luc Tolvouze","Amina Quilmault","François Ivrouze","Hélène Gorzumet","Sophie Ivrault","Louise Bralmière","Nicolas Korvande","Geneviève Ivrumet","Geneviève Obresson","Guillaume Obrançon","Fatima Urvignac","Claire Bralmotte","Félix Hulvignac","François Clovotte","Philippe Dulvoubre","Samuel Rozveron","Pierre Hulvoubre","Émilie Urvouze","Félix Korvançon","Émilie Neskande","Chantal Mirvumet","Alexandre Korvotte","Zoé Eskeval","Nathalie Voskoubre","Sophie Pruvière","Paul Obrichon","Nathalie Eskière","Caroline Ivreron","Véronique Neskoubre","Anne Urvivet","Olivier Hulvançon","Karim Clovançon","Zoé Quilmotte","Félix Eskouze","Amina Rozvichon","Simon Fralvière","Pierre Hulvière","Raphaël Jusvault","Pierre Fralvoubre","Hélène Selveux","Caroline Rozvançon","Olivier Korvière","Nicolas Ivrichon","Félix Korvumet","Guillaume Selvumet","Michel Urvotte","Émilie Eskault","Hélène Bralmeval","Guillaume Hulvesson","Caroline Jusvoubre","Félix Luskeux","Antoine Pruvouze","Julie Quilmignac","Hugo Voskumet","Manon Quilmumet","Marc Voskouze","Samuel Abrevard","Manon Clovesson","Simon Hulvumet","Lucie Voskeron","Jean Neskeron","Manon Pruvivet","Sophie Clovard","Étienne Gorzeval","Gabriel Luskault","Émilie Korvard","Thomas Quilmichon","Alexandre Eskançon","Émilie Luskançon","Marc Dulvault","Hélène Rozveval","Julie Pruvançon","Louis Mirveron","François Eskard","Louis Ivrançon","Karim Clovivet","Léa Rozvande","Amina Hulvouze","Étienne Eskesson","Philippe Abreveval","Émilie Quilmeux","Simon Voskotte","Chantal Obrignac","Guillaume Eskotte","Léa Obrard","Guillaume Gorzivet","Geneviève Mirvançon","Julie Selvotte","Amina Mirvesson","Isabelle Luskignac","Chloé Obrumet","Anne Abrevesson","Fatima Rozvumet","Guillaume Mirvoubre","Véronique Rozvoubre","Claire Gorzotte","Antoine Ivrière","Isabelle Selvichon","Isabelle Urvault","Julie Voskesson","Chantal Abrevotte","Amina Neskotte","Étienne Voskançon","Zoé Fralveron","Marc Rozvouze","Sylvie Abreveux","Karim Pruvignac","Zoé Mirveval","Philippe Fralvignac","Gabriel Gorzeux","Jean Urveval"],"theme":"clair","versionReelle":"2026.10.05.01"}, -{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"5e94a05db66d052a94435895fb62675b9438247e0ce319cfdb38a743cdb3e547","etape":"4","etat":"4d37d30748068354162752743c26aa7e0ab00d6e9b2aa1996b6f9fb410848280","facteurEchelle":1,"fichier":"07a-cibles-tables","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"7ee04170e649d97b27eb4136d30cfb240a5e734a1b4f22eceabc6dc9f17e1961"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-lecture","ratio":5.29,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":15.1,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":8.13,"role":"marque","seuil":3}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-lecture","ratio":7.34,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":8.89,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":14.62,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":11.32,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":5.59,"role":"marque","seuil":3}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Lecture","Liste des événements","Clair","Sombre","À propos","Modifier","Lecture","Défaire","Grande démonstration 1","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Plan","Réservations","Tour affiché","1","2","3","4","Zoom +","Zoom −","Ajuster","Listes de noms","Légende","Plein écran","5","m","disposition relative — l'encombrement dans la salle n'est pas vérifié","Diagnostic","écart d'itinéraire maximal : plancher 1, au moins 24 mobiles finissent sous leur plafond a priori","plafond a priori 24 rencontres pour 4 ancrés","plafond a priori 28 rencontres pour 29 ancrés et 227 mobiles","99 retours imposés par 33 ancrages","Listes de travail","Titres de place non pourvus","Aucun.","Titres pressentis sans réservation","Aucun.","Réserve","Personnes en attente au tour 1","Isabelle Mirvault","Félix Abrevande","Hugo Fralvançon","Manon Fralveux","Catherine Luskotte","Zoé WAMMERWOLM-MAWWEMMEL","Catherine Urvesson","Karim Hulvivet","Caroline Selveron","Catherine Korvault","Caroline Fralvotte","Geneviève Jusvesson","Paul Abrevumet","Léa Fralvault","Fatima Obrivet","Zoé Dulveval","Paul Korveux","Julie Luskière","Émilie Clovande","Paul Hulvande","Hugo Fralvesson","Isabelle Urvière","Thomas Rozvotte","Isabelle Bralmumet","Catherine Dulvouze","Marc Voskichon","Simon Mirvivet","Louise Clovault","Lucie Voskeux","Amina Eskignac","Luc Selvoubre","Étienne Fralvichon","Philippe Voskivet","Louise Quilmançon","Sophie Luskande","Pierre Abreveron","Philippe Neskeux","Amina Neskançon","Léa Tolvande","Antoine Quilmeron","Guillaume Clovumet","Michel Eskeux","Louise Hulvault","Samuel Eskumet","Claire Fralvivet","Léa Mirveux","Karim Gorzesson","Sylvie Quilmande","François Gorzichon","Amina Pruvesson","Lucie Quilmière","Fatima Korvesson","Nicolas Selvesson","Louise Neskesson","Lucie Tolvesson","Olivier Quilmesson","Guillaume Luskivet","Gabriel Neskault","Antoine Urvumet","Olivier Jusvançon","Simon Dulvançon","Chloé Gorzard","Gabriel Pruveux","Manon Clovière","Karim Tolveval","Hugo Bérêçàuvïlle-Dœûmôntëÿ","Claire Gorzeron","Hélène Luskumet","Louis Fralvande","Émilie Selvault","Léa Neskumet","Isabelle Korvichon","Michel Obrande","Isabelle Luskeval","Fatima Tolvoubre","Zoé Gorzière","Sylvie Korvignac","Antoine Obreval","Camille Tolvumet","Marie Dulvesson","Guillaume Tolvignac","Gabriel Mirvotte","Paul Neskignac","Raphaël Ivrotte","Marc Luskouze","Sylvie Jusvotte","Véronique Bralmoubre","Pierre Selvard","Marie Hulveux","Karim Fralveval","Philippe Gorzignac","Étienne Selvouze","Louis Hulvichon","Sylvie Urvoubre","Pierre Pruveval","Guillaume Hulvotte","Geneviève Abrevignac","Amina Bralmignac","Olivier Bralmançon","Marc Luskoubre","Geneviève Abrevoubre","Raphaël Korvoubre","Pierre Mirvard","Camille Jusvumet","Samuel Cloveval","Antoine Selvière","Véronique Jusvouze","Paul Neskivet","Samuel Dulvande","Lucie Selveval","Olivier Tolvichon","Fatima Hulvard","Alexandre Ivreux","Félix Korveval","Karim Urvichon","Émilie Dulvichon","Luc Tolvouze","Amina Quilmault","François Ivrouze","Hélène Gorzumet","Sophie Ivrault","Louise Bralmière","Nicolas Korvande","Geneviève Ivrumet","Geneviève Obresson","Guillaume Obrançon","Fatima Urvignac","Claire Bralmotte","Félix Hulvignac","François Clovotte","Philippe Dulvoubre","Samuel Rozveron","Pierre Hulvoubre","Émilie Urvouze","Félix Korvançon","Émilie Neskande","Chantal Mirvumet","Alexandre Korvotte","Zoé Eskeval","Nathalie Voskoubre","Sophie Pruvière","Paul Obrichon","Nathalie Eskière","Caroline Ivreron","Véronique Neskoubre","Anne Urvivet","Olivier Hulvançon","Karim Clovançon","Zoé Quilmotte","Félix Eskouze","Amina Rozvichon","Simon Fralvière","Pierre Hulvière","Raphaël Jusvault","Pierre Fralvoubre","Hélène Selveux","Caroline Rozvançon","Olivier Korvière","Nicolas Ivrichon","Félix Korvumet","Guillaume Selvumet","Michel Urvotte","Émilie Eskault","Hélène Bralmeval","Guillaume Hulvesson","Caroline Jusvoubre","Félix Luskeux","Antoine Pruvouze","Julie Quilmignac","Hugo Voskumet","Manon Quilmumet","Marc Voskouze","Samuel Abrevard","Manon Clovesson","Simon Hulvumet","Lucie Voskeron","Jean Neskeron","Manon Pruvivet","Sophie Clovard","Étienne Gorzeval","Gabriel Luskault","Émilie Korvard","Thomas Quilmichon","Alexandre Eskançon","Émilie Luskançon","Marc Dulvault","Hélène Rozveval","Julie Pruvançon","Louis Mirveron","François Eskard","Louis Ivrançon","Karim Clovivet","Léa Rozvande","Amina Hulvouze","Étienne Eskesson","Philippe Abreveval","Émilie Quilmeux","Simon Voskotte","Chantal Obrignac","Guillaume Eskotte","Léa Obrard","Guillaume Gorzivet","Geneviève Mirvançon","Julie Selvotte","Amina Mirvesson","Isabelle Luskignac","Chloé Obrumet","Anne Abrevesson","Fatima Rozvumet","Guillaume Mirvoubre","Véronique Rozvoubre","Claire Gorzotte","Antoine Ivrière","Isabelle Selvichon","Isabelle Urvault","Julie Voskesson","Chantal Abrevotte","Amina Neskotte","Étienne Voskançon","Zoé Fralveron","Marc Rozvouze","Sylvie Abreveux","Karim Pruvignac","Zoé Mirveval","Philippe Fralvignac","Gabriel Gorzeux","Jean Urveval"],"theme":"clair","versionReelle":"2026.10.05.01"}, -{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"03fa9a9b0f1b629d6d43dd536ae6da66ddfb105dd8bd6a68f65807235644183d","etape":"5","etat":"7e19a3b61721017693ee5895e1b4a82e2f1656e35e71989ac4d29ea9cfc59fe8","facteurEchelle":1,"fichier":"07b-nombre-de-tours","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"d49f53ecabd801b0b4681d5c4ccbd277c71ebe2b15c46e6d77e08a741faf4a90"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5}],"sombre":[{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Tables et tours","Places par défaut","Nombre de tours","Passer de 3 à 2 tours ? Ce changement emporte :","Basile Lanterneau : réservation à la table 1 au tour 3, détruite","Annuler","Confirmer","Tables","Ajouter une table ronde","Ajouter une table carrée","Table","1","Ronde","Suit le défaut","Places","Supprimer","Table","2","Ronde","Surchargée","Places","Réaligner","Supprimer"],"theme":"clair","versionReelle":"2026.10.05.01"}, -{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"683bc10e0c646219a177996b828093c6033d6ae959c82e6528967f61151b8227","etape":"6","etat":"0ad50f28307185683e15e5660c2da2f3398d783d68988d637c519ef3ba0658a5","facteurEchelle":1,"fichier":"08-animateurs-designes","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"86e95804c0abe8acbe9b34fa0a43642ad26b39e7a56a6e335603c167988a49c2"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":4.78,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-pleine","ratio":15.38,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":15.1,"role":"marque","seuil":3},{"jeton":"--couleur-hachure","ratio":16.48,"role":"marque","seuil":3},{"jeton":"--couleur-marque","ratio":3.63,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-selection","ratio":4.66,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":7.58,"role":"marque","seuil":3}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":9.1,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-pleine","ratio":14.94,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":8.89,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":14.62,"role":"marque","seuil":3},{"jeton":"--couleur-hachure","ratio":15.21,"role":"marque","seuil":3},{"jeton":"--couleur-marque","ratio":3.5,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":11.32,"role":"marque","seuil":3},{"jeton":"--couleur-selection","ratio":4.18,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":5.59,"role":"marque","seuil":3}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Plan","Réservations","Tour affiché","1","2","3","Zoom +","Zoom −","Ajuster","Listes de noms","Légende","Plein écran","1. (réservée, tous les tours)","Basile Lanterneau","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","9. (libre)","10. (libre)","1. (libre)","— titre","animation","non pourvu","2. (réservée, tour 1)","Capucine Pommerel","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1","m","disposition relative — l'encombrement dans la salle n'est pas vérifié","Diagnostic","Chœur de l’Anse","4 personnes : au moins 6 collisions cumulées sur les 3 tours, portées par au moins 2 paires distinctes","Société des Hérons","4 personnes : au moins 6 collisions cumulées sur les 3 tours, portées par au moins 2 paires distinctes","Cercle des Saules","3 personnes : au moins 3 collisions cumulées sur les 3 tours, portées par au moins 1 paire distincte","au moins 8 appartenances recroisées par personne","plafond a priori 11 rencontres pour 1 ancré et 11 mobiles","2 retours imposés par 1 ancrage","Listes de travail","Titres de place non pourvus","table 2 : titre","animation","non pourvu","Titres pressentis sans réservation","Gaspard Marbrelle","— titre pressenti","animation","Réserve","Personnes en attente au tour 1","Gaspard Marbrelle","Ysaline Sablonnet","Anselme Givrecœur","Côme Fenouillet","Apolline Coudraie","Basile Lanterneau","Brunœil","Faustine Ormelin","Edgar Ardoisier","Bertille Cressonnier","Table 2, siège 1","1. (libre)","— titre","animation","non pourvu","Choisissez d'abord une personne : dans la réserve, dans la liste des pressentis, ou par « Déplacer » dans son menu.","Portée","Tour 1","Tous les tours","Libellé du titre","Assigner","Réserver","Désigner","Retirer le titre"],"theme":"clair","versionReelle":"2026.10.05.01"}, -{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"a0193f21920d9a2d6740a92d8fe78cb2d5d8d551be7c3cbc4f8c31aabe511add","etape":"7","etat":"0ad50f28307185683e15e5660c2da2f3398d783d68988d637c519ef3ba0658a5","facteurEchelle":1,"fichier":"09-refus-sur-place","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"4eb952f4bba4537ca9c306f59c39eab22b4ee1d9c7cd2e2a7f40735a888eb6c1"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":4.78,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-pleine","ratio":15.38,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":15.1,"role":"marque","seuil":3},{"jeton":"--couleur-hachure","ratio":16.48,"role":"marque","seuil":3},{"jeton":"--couleur-marque","ratio":3.63,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-refus","ratio":8.76,"role":"texte","seuil":4.5},{"jeton":"--couleur-selection","ratio":4.66,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":7.58,"role":"marque","seuil":3},{"jeton":"rgb(0, 0, 0)","ratio":18.26,"role":"texte","seuil":4.5}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":9.1,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-pleine","ratio":14.94,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":8.89,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":14.62,"role":"marque","seuil":3},{"jeton":"--couleur-hachure","ratio":15.21,"role":"marque","seuil":3},{"jeton":"--couleur-marque","ratio":3.5,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5},{"jeton":"--couleur-papier","ratio":5.33,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":11.32,"role":"marque","seuil":3},{"jeton":"--couleur-refus","ratio":9.24,"role":"texte","seuil":4.5},{"jeton":"--couleur-selection","ratio":4.18,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":5.59,"role":"marque","seuil":3}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Plan","Réservations","Tour affiché","1","2","3","Zoom +","Zoom −","Ajuster","Listes de noms","Légende","Plein écran","1. (réservée, tous les tours)","Basile Lanterneau","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","9. (libre)","10. (libre)","1. (libre)","— titre","animation","non pourvu","2. (réservée, tour 1)","Capucine Pommerel","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","Table 1, siège 1","Le siège 1 est réservé à une autre personne à tous les tours : déplacer sa réservation libère la place.","Choisir une place","Fermer","1","m","disposition relative — l'encombrement dans la salle n'est pas vérifié","Diagnostic","Chœur de l’Anse","4 personnes : au moins 6 collisions cumulées sur les 3 tours, portées par au moins 2 paires distinctes","Société des Hérons","4 personnes : au moins 6 collisions cumulées sur les 3 tours, portées par au moins 2 paires distinctes","Cercle des Saules","3 personnes : au moins 3 collisions cumulées sur les 3 tours, portées par au moins 1 paire distincte","au moins 8 appartenances recroisées par personne","plafond a priori 11 rencontres pour 1 ancré et 11 mobiles","2 retours imposés par 1 ancrage","Listes de travail","Titres de place non pourvus","table 2 : titre","animation","non pourvu","Titres pressentis sans réservation","Gaspard Marbrelle","— titre pressenti","animation","Réserve","Personnes en attente au tour 1","Gaspard Marbrelle","Ysaline Sablonnet","Anselme Givrecœur","Côme Fenouillet","Apolline Coudraie","Basile Lanterneau","Brunœil","Faustine Ormelin","Edgar Ardoisier","Bertille Cressonnier","Table 1, siège 1","1. (réservée, tous les tours)","Basile Lanterneau","—","animation","Personne choisie :","Gaspard Marbrelle","Assigner","Retirer la réservation","Retirer le titre","Oublier le choix","Menu de","Basile Lanterneau","Déplacer","Échanger","Retirer du tour","Déplacer sa réservation","Exclure","Mettre en évidence","Ouvrir la fiche"],"theme":"clair","versionReelle":"2026.10.05.01"}, -{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"7ecb8436808e6bb30b06224c9fcd64bd94b58a6b7142d1e5d4252e6ff4a76bc0","etape":"8","etat":"4d37d30748068354162752743c26aa7e0ab00d6e9b2aa1996b6f9fb410848280","facteurEchelle":1,"fichier":"10-diagnostic","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"fa29e3517f71a8001d18734854f1f03fe908fe060727aa995b2f7d38ec39766e"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-lecture","ratio":5.29,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5},{"jeton":"--couleur-page-texte-secondaire","ratio":7.05,"role":"texte","seuil":4.5}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-lecture","ratio":7.34,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5},{"jeton":"--couleur-page-texte-secondaire","ratio":7.98,"role":"texte","seuil":4.5}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Lecture","Liste des événements","Clair","Sombre","À propos","Modifier","Lecture","Défaire","Grande démonstration 1","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Diagnostic","écart d'itinéraire maximal : plancher 1, au moins 24 mobiles finissent sous leur plafond a priori","aucune relance ne le réduit : il tient aux tables pleines dont les capacités ou les ancrages diffèrent","plafond a priori 24 rencontres pour 4 ancrés","seules les capacités et les réservations le changent : aucune relance ne le dépasse","plafond a priori 28 rencontres pour 29 ancrés et 227 mobiles","seules les capacités et les réservations le changent : aucune relance ne le dépasse","99 retours imposés par 33 ancrages","les réservations les imposent : ils ne comptent pas parmi les retours que choisit le moteur"],"theme":"clair","versionReelle":"2026.10.05.01"}, -{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"5469971810061d85c542f58b14f231f6238d16087cee4311155e9f6c3c140a4b","etape":"9","etat":"78c47299a88ae35b3dc4c09bededdd6e0e9dc695a35d313d74f46c9cbede5573","facteurEchelle":1,"fichier":"11-propositions","graine":4242,"image":{"hauteur":700,"largeur":1366,"sha256":"fa6d9de0b2e35b38cf40e343b99000f03e4cbf20081a93d21b67e2358152ce9d"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":4.78,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":9.1,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Propositions","Ordre du classement, chaque critère au plus faible d'abord :","écart au plafond a priori",", puis","excédent de collisions",", puis","collisions cumulées",", puis","rencontres répétées",", puis","redondance d'appartenance",", puis","l'identifiant croissant",".","Propositions classées","Rang","Proposition","Personnes distinctes rencontrées, minimum : tous","Personnes distinctes rencontrées, minimum : mobiles","Personnes distinctes rencontrées, minimum : ancrés","Collisions cumulées (paire et tour)","Paires distinctes de même appartenance","Excédent de collisions (retrouvailles au-delà de la première)","Rencontres répétées choisies (paires)","Rencontres d'une même paire, au plus","Retours choisis à une table déjà occupée","Appartenances rencontrées A(p), minimum","Redondance d'appartenance, somme Σ r(p)","Taux de diversité d(p), minimum","Plus grand manque (personnes)","Personnes à qui il en manque","Écart d'itinéraire maximal (personnes)","Écart au plafond a priori maximal (personnes)","Certificat","Imposé par les réservations","Commandes","Placement retenu","3","Tel que la proposition n° 3.","11","11","11","26","15","11","30","3","11","3","85","0,27","0","0","0","0","minimum atteint","2 retours imposés par 1 ancrage.","Aucune rencontre répétée imposée.","Voir sur le plan","1","3","retenue","11","11","11","26","15","11","30","3","11","3","85","0,27","0","0","0","0","minimum atteint","2 retours imposés par 1 ancrage.","Aucune rencontre répétée imposée.","Voir sur le plan","Retenir","2","1","11","11","11","27","15","12","19","3","16","3","85","0,27","0","0","0","0","minimum atteint","2 retours imposés par 1 ancrage.","Aucune rencontre répétée imposée.","Voir sur le plan","Retenir","3","2","11","11","11","33","15","18","54","3","16","3","85","0,27","0","0","0","0","minimum atteint","2 retours imposés par 1 ancrage.","Aucune rencontre répétée imposée.","Voir sur le plan","Retenir","4","5","10","10","10","20","15","5","22","3","12","3","83","0,27","1","1","1","1","atteignabilité inconnue","2 retours imposés par 1 ancrage.","Aucune rencontre répétée imposée.","Voir sur le plan","Retenir","5","4","10","10","11","31","14","17","46","3","17","3","82","0,30","1","4","0","1","atteignabilité inconnue","2 retours imposés par 1 ancrage.","Aucune rencontre répétée imposée.","Voir sur le plan","Retenir","Le numéro de la proposition, donné à sa génération ; un numéro effacé ne revient jamais. Il sert de dernier départage : deux propositions égales sur tous les critères se rangent par numéro croissant.","Cible de la somme de redondance","La liste des événements montre, pour le placement retenu, la différence sans signe entre cette cible et la somme Σ r(p) de la colonne « Redondance d'appartenance ». Un nombre entier, 0 ou plus.","Effacer les propositions"],"theme":"clair","versionReelle":"2026.10.05.01"}, -{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"56511b4b7b473f6c7532a44d940149ad7ace45451fb5c1fb8276813790bad305","etape":"11","etat":"78c47299a88ae35b3dc4c09bededdd6e0e9dc695a35d313d74f46c9cbede5573","facteurEchelle":1,"fichier":"19-ajustement","graine":4242,"image":{"hauteur":700,"largeur":1366,"sha256":"c51555af8cfa902df73c13e69111b42371d9e665175ccb4d69a5a434c5f85187"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":13.44,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":4.78,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-pleine","ratio":15.38,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-conflit-appartenance","ratio":8.92,"role":"marque","seuil":3},{"jeton":"--couleur-contour-fort","ratio":12.54,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":15.1,"role":"marque","seuil":3},{"jeton":"--couleur-fantome","ratio":4.34,"role":"marque","seuil":3},{"jeton":"--couleur-hachure","ratio":16.48,"role":"marque","seuil":3},{"jeton":"--couleur-marque","ratio":3.63,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5},{"jeton":"--couleur-pastille-fond","ratio":13.44,"role":"marque","seuil":3},{"jeton":"--couleur-poignee","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":7.58,"role":"marque","seuil":3}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":9.1,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-pleine","ratio":14.94,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":8.89,"role":"marque","seuil":3},{"jeton":"--couleur-conflit-appartenance","ratio":6.81,"role":"marque","seuil":3},{"jeton":"--couleur-contour-fort","ratio":11.62,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":14.62,"role":"marque","seuil":3},{"jeton":"--couleur-fantome","ratio":4.1,"role":"marque","seuil":3},{"jeton":"--couleur-hachure","ratio":15.21,"role":"marque","seuil":3},{"jeton":"--couleur-marque","ratio":3.5,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":11.39,"role":"texte","seuil":4.5},{"jeton":"--couleur-pastille-fond","ratio":11.62,"role":"marque","seuil":3},{"jeton":"--couleur-pastille-texte","ratio":14.51,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":11.32,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":5.59,"role":"marque","seuil":3}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Plan","Placement retenu","Tour affiché","1","2","3","Zoom +","Zoom −","Ajuster","Listes de noms","Légende","Plein écran","9","1. (réservée, tous les tours)","Basile Lanterneau","—","animation","2.","Gaspard Marbrelle","3.","Ysaline Sablonnet","4.","Anselme Givrecœur","5.","Côme Fenouillet","6.","Apolline Coudraie","7.","Brunœil","8.","Faustine Ormelin","9.","Edgar Ardoisier","10.","Bertille Cressonnier","1.","Basile Lanterneau","— titre","animation","non pourvu","2. (réservée, tour 1)","Capucine Pommerel","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","Gaspard Marbrelle","déplace dans le placement retenu","1","m","disposition relative — l'encombrement dans la salle n'est pas vérifié","Diagnostic","Chœur de l’Anse","4 personnes : au moins 6 collisions cumulées sur les 3 tours, portées par au moins 2 paires distinctes","Société des Hérons","4 personnes : au moins 6 collisions cumulées sur les 3 tours, portées par au moins 2 paires distinctes","Cercle des Saules","3 personnes : au moins 3 collisions cumulées sur les 3 tours, portées par au moins 1 paire distincte","au moins 8 appartenances recroisées par personne","plafond a priori 11 rencontres pour 1 ancré et 11 mobiles","2 retours imposés par 1 ancrage","Listes de travail","Titres de place non pourvus","table 2 : titre","animation","non pourvu","Titres pressentis sans réservation","Gaspard Marbrelle","— titre pressenti","animation","Réserve","Personnes en attente au tour 1","Personne en attente à ce tour."],"theme":"clair","versionReelle":"2026.10.05.01"}, -{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"169488d265a583d3459bec989f0f4ab8a0526431e546cf5a130374df469e22ae","etape":"11","etat":"20666d70d9b2503335efc1f2cece5453a199ab77f4864835baf4bccf5aff17d5","facteurEchelle":1,"fichier":"20-mode-lecture","graine":4242,"image":{"hauteur":700,"largeur":1366,"sha256":"ca2ab13caba0f64fc26749675dd5a5a1b2319240ea259ac5cf08f519ffd0eb05"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":13.44,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-lecture","ratio":5.29,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-pleine","ratio":15.38,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-conflit-appartenance","ratio":8.92,"role":"marque","seuil":3},{"jeton":"--couleur-contour-fort","ratio":12.54,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":15.1,"role":"marque","seuil":3},{"jeton":"--couleur-hachure","ratio":16.48,"role":"marque","seuil":3},{"jeton":"--couleur-marque","ratio":3.63,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5},{"jeton":"--couleur-pastille-fond","ratio":13.44,"role":"marque","seuil":3},{"jeton":"--couleur-poignee","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-selection","ratio":4.66,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":7.58,"role":"marque","seuil":3}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-lecture","ratio":7.34,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-pleine","ratio":14.94,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":8.89,"role":"marque","seuil":3},{"jeton":"--couleur-conflit-appartenance","ratio":6.81,"role":"marque","seuil":3},{"jeton":"--couleur-contour-fort","ratio":11.62,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":14.62,"role":"marque","seuil":3},{"jeton":"--couleur-hachure","ratio":15.21,"role":"marque","seuil":3},{"jeton":"--couleur-marque","ratio":3.5,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5},{"jeton":"--couleur-pastille-fond","ratio":11.62,"role":"marque","seuil":3},{"jeton":"--couleur-pastille-texte","ratio":14.51,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":11.32,"role":"marque","seuil":3},{"jeton":"--couleur-selection","ratio":4.18,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":5.59,"role":"marque","seuil":3}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Lecture","Liste des événements","Clair","Sombre","À propos","Modifier","Lecture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Plan","Placement retenu","Tour affiché","1","2","3","Zoom +","Zoom −","Ajuster","Listes de noms","Légende","Plein écran","7","1. (réservée, tous les tours)","Basile Lanterneau","—","animation","2.","Ysaline Sablonnet","3.","Anselme Givrecœur","4.","Côme Fenouillet","5.","Apolline Coudraie","6.","Brunœil","7.","Faustine Ormelin","8.","Edgar Ardoisier","9.","Bertille Cressonnier","10. (libre)","1.","Gaspard Marbrelle","— titre","animation","non pourvu","2. (réservée, tour 1)","Capucine Pommerel","3.","Basile Lanterneau","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","Table 2, siège 4","L'événement est ouvert en lecture : « Modifier » permet de le changer.","Modifier","Fermer","1","m","disposition relative — l'encombrement dans la salle n'est pas vérifié","Diagnostic","Chœur de l’Anse","4 personnes : au moins 6 collisions cumulées sur les 3 tours, portées par au moins 2 paires distinctes","Société des Hérons","4 personnes : au moins 6 collisions cumulées sur les 3 tours, portées par au moins 2 paires distinctes","Cercle des Saules","3 personnes : au moins 3 collisions cumulées sur les 3 tours, portées par au moins 1 paire distincte","au moins 8 appartenances recroisées par personne","plafond a priori 11 rencontres pour 1 ancré et 11 mobiles","2 retours imposés par 1 ancrage","Listes de travail","Titres de place non pourvus","table 2 : titre","animation","non pourvu","Titres pressentis sans réservation","Gaspard Marbrelle","— titre pressenti","animation","Réserve","Personnes en attente au tour 1","Personne en attente à ce tour.","Table 2, siège 4","4. (libre)","Choisissez d'abord une personne : dans la réserve, dans la liste des pressentis, ou par « Déplacer » dans son menu.","Portée","Tour 1","Tous les tours","Libellé du titre","Assigner","Réserver","Donner un titre","Désigner"],"theme":"clair","versionReelle":"2026.10.05.01"} +{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"b8ca0bddb4eb46edfa81963063a9ae2077255a9de62282943ba898a7c365f4e5","etape":"1b","etat":"ab468ad775d39cda60057d23f67ba34d787dda85b66c87b5500b41bff1b2b630","facteurEchelle":1,"fichier":"01b-passer-en-ecriture","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"1c00c0fd453c094550f099ab5e15b1b398f4b5a980ea1a7e9257f5dfeec1f957"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-lecture","ratio":5.29,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5},{"jeton":"--couleur-refus","ratio":8.76,"role":"texte","seuil":4.5}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-lecture","ratio":7.34,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5},{"jeton":"--couleur-refus","ratio":9.24,"role":"texte","seuil":4.5}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Lecture","Liste des événements","Clair","Sombre","À propos","Modifier","Lecture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Badges","Tables et tours","Places par défaut","Nombre de tours","Tables","Ajouter une table ronde","L'événement est ouvert en lecture : « Modifier » permet de le changer.","Modifier","Ajouter une table carrée","Aucune table : ajoutez-en une, ronde ou carrée."],"theme":"clair","versionReelle":"2026.10.05.01"}, +{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"55041fe791e916e74668aa5fee83f90dcd191c6b359e31040353ce5a762cc12e","etape":"2","etat":"4acf3230b0733a35d33c6baf84b7d4f312e98a5b799147dcea6b3bb5d4f082d5","facteurEchelle":1,"fichier":"02-import-apercu","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"8c981b345ac07a5a82bd6af6aa64d38318878ef8bb2295e068af132afc4977fa"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":4.78,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":9.1,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Badges","Import","Choisissez un fichier CSV ou déposez-le sur la fenêtre ; une plage collée dans la grille des participants arrive ici. Rien ne s'importe avant l'aperçu.","Choisir un fichier CSV…","Aperçu","Mode de l'import","Ajouter","Mettre à jour","Remplacer","Fichier","participants_cas_limites.csv","Encodage","UTF-8 avec marque","Séparateur","point-virgule","Colonnes","En-tête","Devient","Nom","nom","Prénom","prénom","Organisation","appartenance","Courriel","courriel","Rôle","titre pressenti","Exclu","exclu","Notes","notes","Téléphone","non reconnue : ignorée","13","lignes valides","Ligne","nom","prénom","appartenance","courriel","titre pressenti","exclu","notes","2","Lanterneau","Basile","Chœur de l’Anse","basile.lanterneau@exemple.test","animation","3","Pommerel","Capucine","Société des Hérons","capucine.pommerel@exemple.test","4","Marbrelle","Gaspard","Cercle des Saules","animation","5","Sablonnet","Ysaline","Chœur de l’Anse","6","Givrecœur","Anselme","anselme.givrecoeur@exemple.test","7","Tourterel","Héloïse","Cercle des Saules","oui","S’est désistée la veille","8","Fenouillet","Côme","Société des Hérons","végétarien; sans noix, ni arachides","9","Coudraie","Apolline","Chœur de l’Anse","Arrive après le premier tour repart avant le dessert","10","Lanterneau","Basile","Chœur de l’Anse","11","Brunœil","Cercle des Saules","brunoeil@exemple.test","12","Ormelin","Faustine","Société des Hérons","14","Ardoisier","Edgar","Société des Hérons","15","Cressonnier","Bertille","Cercle des Saules","Lignes refusées","Ligne","Motif","13","Le nom manque.","Orthographes fondues en une appartenance","affichée :","Société des Hérons","Société des Hérons","3","lignes","Societe des herons","1","ligne","Doublons signalés, jamais fusionnés","lignes","2","10","Importer","Enregistrer les lignes refusées","Fermer l'aperçu"],"theme":"clair","versionReelle":"2026.10.05.01"}, +{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"6ef3c1483e674815becf6b24cd0afc8097c7f8111329606ea362c5c0847b1d5a","etape":"2","etat":"4acf3230b0733a35d33c6baf84b7d4f312e98a5b799147dcea6b3bb5d4f082d5","facteurEchelle":1,"fichier":"02b-import-cp1252","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"d73a4263188368d36785354a91af2462c4fa72b7d73f4cd17d9405b2791dc44f"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":4.78,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":9.1,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Badges","Import","Choisissez un fichier CSV ou déposez-le sur la fenêtre ; une plage collée dans la grille des participants arrive ici. Rien ne s'importe avant l'aperçu.","Choisir un fichier CSV…","Aperçu","Mode de l'import","Ajouter","Mettre à jour","Remplacer","Fichier","participants_cas_limites_cp1252.csv","Encodage","windows-1252","Séparateur","virgule","Colonnes","En-tête","Devient","Nom","nom","Prénom","prénom","Organisation","appartenance","Courriel","courriel","Rôle","titre pressenti","Exclu","exclu","Notes","notes","Téléphone","non reconnue : ignorée","13","lignes valides","Ligne","nom","prénom","appartenance","courriel","titre pressenti","exclu","notes","2","Lanterneau","Basile","Chœur de l’Anse","basile.lanterneau@exemple.test","animation","3","Pommerel","Capucine","Société des Hérons","capucine.pommerel@exemple.test","4","Marbrelle","Gaspard","Cercle des Saules","animation","5","Sablonnet","Ysaline","Chœur de l’Anse","6","Givrecœur","Anselme","anselme.givrecoeur@exemple.test","7","Tourterel","Héloïse","Cercle des Saules","oui","S’est désistée la veille","8","Fenouillet","Côme","Société des Hérons","végétarien; sans noix, ni arachides","9","Coudraie","Apolline","Chœur de l’Anse","Arrive après le premier tour repart avant le dessert","10","Lanterneau","Basile","Chœur de l’Anse","11","Brunœil","Cercle des Saules","brunoeil@exemple.test","12","Ormelin","Faustine","Société des Hérons","14","Ardoisier","Edgar","Société des Hérons","15","Cressonnier","Bertille","Cercle des Saules","Lignes refusées","Ligne","Motif","13","Le nom manque.","Orthographes fondues en une appartenance","affichée :","Société des Hérons","Société des Hérons","3","lignes","Societe des herons","1","ligne","Doublons signalés, jamais fusionnés","lignes","2","10","Importer","Enregistrer les lignes refusées","Fermer l'aperçu"],"theme":"clair","versionReelle":"2026.10.05.01"}, +{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"c3dab545f5c9609ed05ad07c5ae5c10d16e73c27e23136307b49fe67feddfe26","etape":"2","etat":"b3119a32dda90f0c824bb31f31cb2f5a58af891b3338215d7efabf785b0a5d48","facteurEchelle":1,"fichier":"03-import-rapport","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"334e5a1667b71f856917b4b049c9451d552541afcfa4cdac83619c3c3cf8982e"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":4.78,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":9.1,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Badges","Il manque 4 places à chaque tour pour asseoir toutes les personnes : ajouter des tables ou des sièges, ou exclure des personnes, rend la génération possible.","Ouvrir les tables","Import","Choisissez un fichier CSV ou déposez-le sur la fenêtre ; une plage collée dans la grille des participants arrive ici. Rien ne s'importe avant l'aperçu.","Choisir un fichier CSV…","Rapport d'import","13","personnes ajoutées","0","personne mise à jour","0","personne inchangée","0","personne retirée","0","réservation retirée","Fichier","participants_cas_limites.csv","Encodage","UTF-8 avec marque","Séparateur","point-virgule","Colonnes","En-tête","Devient","Nom","nom","Prénom","prénom","Organisation","appartenance","Courriel","courriel","Rôle","titre pressenti","Exclu","exclu","Notes","notes","Téléphone","non reconnue : ignorée","13","lignes valides","Ligne","nom","prénom","appartenance","courriel","titre pressenti","exclu","notes","2","Lanterneau","Basile","Chœur de l’Anse","basile.lanterneau@exemple.test","animation","3","Pommerel","Capucine","Société des Hérons","capucine.pommerel@exemple.test","4","Marbrelle","Gaspard","Cercle des Saules","animation","5","Sablonnet","Ysaline","Chœur de l’Anse","6","Givrecœur","Anselme","anselme.givrecoeur@exemple.test","7","Tourterel","Héloïse","Cercle des Saules","oui","S’est désistée la veille","8","Fenouillet","Côme","Société des Hérons","végétarien; sans noix, ni arachides","9","Coudraie","Apolline","Chœur de l’Anse","Arrive après le premier tour repart avant le dessert","10","Lanterneau","Basile","Chœur de l’Anse","11","Brunœil","Cercle des Saules","brunoeil@exemple.test","12","Ormelin","Faustine","Société des Hérons","14","Ardoisier","Edgar","Société des Hérons","15","Cressonnier","Bertille","Cercle des Saules","Lignes refusées","Ligne","Motif","13","Le nom manque.","Orthographes fondues en une appartenance","affichée :","Société des Hérons","Société des Hérons","3","lignes","Societe des herons","1","ligne","Doublons signalés, jamais fusionnés","lignes","2","10","Enregistrer les lignes refusées","Fermer le rapport"],"theme":"clair","versionReelle":"2026.10.05.01"}, +{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"48fe54c0925eb4eef9a3663f6f9e9165368bdf602b8bd2763e723f7b13431542","etape":"3","etat":"a220b2f80cc83728c43e0bcca0bb785ce7e7b4fa5c3fea5289d095d09a911535","facteurEchelle":1,"fichier":"04-grille-participants","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"0b28aedb367eee7fe1c0b372c721b0829e0fb637c48cc3867526ad63f85971f1"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":4.78,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":9.1,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Badges","Il manque 4 places à chaque tour pour asseoir toutes les personnes : ajouter des tables ou des sièges, ou exclure des personnes, rend la génération possible.","Ouvrir les tables","Participants","Ajouter une personne","Nom","Prénom","Appartenance","Courriel","Titre pressenti","Notes","Ajouter","Filtrer","Grouper par","Aucun groupement","Nom","Prénom","Appartenance","Courriel","Titre pressenti","Exclusion","Notes","Statut","13 participants","Exporter la liste","Nom","(décroissant)","Prénom","Appartenance","Courriel","Titre pressenti","Exclusion","Notes","Actions","Tourterel","Héloïse","Cercle des Saules","exclue","S’est désistée la veille","Fiche","Voir sur le plan","Réintégrer","Supprimer","Sablonnet","Ysaline","Chœur de l’Anse","présente","Fiche","Voir sur le plan","Exclure","Supprimer","Pommerel","Capucine","Société des Hérons","capucine.pommerel@exemple.test","présente","Fiche","Voir sur le plan","Exclure","Supprimer","Ormelin","Faustine","Société des Hérons","présente","Fiche","Voir sur le plan","Exclure","Supprimer","Marbrelle","Gaspard","Cercle des Saules","ondine@exemple.test","animation","présente","Fiche","Voir sur le plan","Exclure","Supprimer","Lanterneau","Basile","Chœur de l’Anse","basile.lanterneau@exemple.test","animation","présente","Fiche","Voir sur le plan","Exclure","Supprimer","Lanterneau","Basile","Chœur de l’Anse","présente","Fiche","Voir sur le plan","Exclure","Supprimer","Givrecœur","Anselme","anselme.givrecoeur@exemple.test","présente","Fiche","Voir sur le plan","Exclure","Supprimer","Fenouillet","Côme","Société des Hérons","présente","végétarien; sans noix, ni arachides","Fiche","Voir sur le plan","Exclure","Supprimer","Cressonnier","Bertille","Cercle des Saules","présente","Fiche","Voir sur le plan","Exclure","Supprimer","Coudraie","Apolline","Chœur de l’Anse","présente","Arrive après le premier tour repart avant le dessert","Fiche","Voir sur le plan","Exclure","Supprimer","Brunœil","Cercle des Saules","brunoeil@exemple.test","présente","Fiche","Voir sur le plan","Exclure","Supprimer","Ardoisier","Edgar","Société des Hérons","présente","Fiche","Voir sur le plan","Exclure","Supprimer"],"theme":"clair","versionReelle":"2026.10.05.01"}, +{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"8e193ed22bba110595f389085df0391dbe20cc0b7aed3652923ac555f9b84fea","etape":"4","etat":"421c6294b4348fa49aa0105ea643fd11c80806a9fbb1e079435adac079e6b260","facteurEchelle":1,"fichier":"05-tables-etat","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"7490454761fee42ddec2e4d63face5bd94fad070e430b8a7bef788bc89c4cd68"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":4.78,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":9.1,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Badges","Tables et tours","Places par défaut","Nombre de tours","Tables","Ajouter une table ronde","Ajouter une table carrée","Table","1","Ronde","Suit le défaut","Places","Supprimer","Table","2","Ronde","Surchargée","Places","Réaligner","Supprimer"],"theme":"clair","versionReelle":"2026.10.05.01"}, +{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"54822aa5fac5895107c96ffdcb7d92e9a5a7b4bb54391201cedd0dbdb6a31599","etape":"4","etat":"421c6294b4348fa49aa0105ea643fd11c80806a9fbb1e079435adac079e6b260","facteurEchelle":1,"fichier":"06-defaut-consequence","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"dcfa033363d8c7ef4bd2b5aa1d9fbd642947c5b2acb81ec9853d22926db8c879"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":4.78,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":9.1,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Badges","Tables et tours","Places par défaut","1 table suit le défaut et passe de 8 à 10 places ; 1 table surchargée (8) ne change pas.","Total : 16 → 18 sièges pour 12 participants.","Appliquer","Appliquer et réaligner la surchargée","Garder le défaut actuel","Nombre de tours","Tables","Ajouter une table ronde","Ajouter une table carrée","Table","1","Ronde","Suit le défaut","Places","Supprimer","Table","2","Ronde","Surchargée","Places","Réaligner","Supprimer"],"theme":"clair","versionReelle":"2026.10.05.01"}, +{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"80ea70bf8cae4e6c108a13f0aba8a36400863a7d9987d16f0f82cbdb35a9364f","etape":"4","etat":"7d42132a2caa999f9d046f580b1093732ebb44984b8fdec5b27da7e42801678e","facteurEchelle":1,"fichier":"07-plan-tables","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"78e03d995139b2ac16e77168b76dc378bd328f32853440623c4911ba74cb1997"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":4.78,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":15.1,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":7.58,"role":"marque","seuil":3}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":9.1,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":8.89,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":14.62,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":11.32,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":5.59,"role":"marque","seuil":3}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Badges","Plan","Réservations","Tour affiché","1","2","3","Zoom +","Zoom −","Ajuster","Listes de noms","Légende","Plein écran","1. (libre)","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","9. (libre)","10. (libre)","1. (libre)","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1","m","disposition relative — l'encombrement dans la salle n'est pas vérifié","Diagnostic","Chœur de l’Anse","4 personnes : au moins 6 collisions cumulées sur les 3 tours, portées par au moins 2 paires distinctes","Société des Hérons","4 personnes : au moins 6 collisions cumulées sur les 3 tours, portées par au moins 2 paires distinctes","Cercle des Saules","3 personnes : au moins 3 collisions cumulées sur les 3 tours, portées par au moins 1 paire distincte","au moins 8 appartenances recroisées par personne","plafond a priori 11 rencontres pour 12 mobiles","Listes de travail","Titres de place non pourvus","Aucun.","Titres pressentis sans réservation","Basile Lanterneau","— titre pressenti","animation","Gaspard Marbrelle","— titre pressenti","animation","Réserve","Personnes en attente au tour 1","Basile Lanterneau","Capucine Pommerel","Gaspard Marbrelle","Ysaline Sablonnet","Anselme Givrecœur","Côme Fenouillet","Apolline Coudraie","Basile Lanterneau","Brunœil","Faustine Ormelin","Edgar Ardoisier","Bertille Cressonnier"],"theme":"clair","versionReelle":"2026.10.05.01"}, +{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"399d4189696db033eed981e7e9330d44970f5efa3c378580c7ae5738a5812ba6","etape":"4","etat":"4d37d30748068354162752743c26aa7e0ab00d6e9b2aa1996b6f9fb410848280","facteurEchelle":1,"fichier":"07a-cibles-sieges","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"7c32146406b085652ace20613d69a0a81287d84aac0f73dda0f900a8685efa31"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-lecture","ratio":5.29,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-pleine","ratio":15.38,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":15.1,"role":"marque","seuil":3},{"jeton":"--couleur-marque","ratio":3.63,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":7.58,"role":"marque","seuil":3}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-lecture","ratio":7.34,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-pleine","ratio":14.94,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":8.89,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":14.62,"role":"marque","seuil":3},{"jeton":"--couleur-marque","ratio":3.5,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":11.32,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":5.59,"role":"marque","seuil":3}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Lecture","Liste des événements","Clair","Sombre","À propos","Modifier","Lecture","Défaire","Grande démonstration 1","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Badges","Plan","Réservations","Tour affiché","1","2","3","4","Zoom +","Zoom −","Ajuster","Listes de noms","Légende","Plein écran","1. (réservée, tous les tours)","Manon Urvançon","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Guillaume Luski…","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Fatima Korvouze","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Antoine Bralmault","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Manon Tolveron","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Philippe Voskeval","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Félix Voskande","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Michel Korveron","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Gabriel Ivreval","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Marc Vandergro…","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Étienne Tolvançon","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Sophie Pruvotte","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Fatima Abrevan…","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Marie Urvard","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Catherine Hulver…","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Camille Neskard","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Youssef Neskière","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Guillaume Dulvi…","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Philippe Ivroubre","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Claire Jusvivet","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Youssef Jusvard","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Louise Neskichon","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Hugo Bralmouze","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Gabriel Abrevault","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Louis Selvivet","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Jean Fralvumet","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Marie Bralmesson","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Thomas Selvignac","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Émilie Abrevière","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1. (réservée, tous les tours)","Geneviève Dulv…","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","1. (réservée, tous les tours)","François Obrouze","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","1. (réservée, tous les tours)","François Ivrivet","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","1. (réservée, tous les tours)","Samuel Bralmeux","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","1","m","disposition relative — l'encombrement dans la salle n'est pas vérifié","Diagnostic","écart d'itinéraire maximal : plancher 1, au moins 24 mobiles finissent sous leur plafond a priori","plafond a priori 24 rencontres pour 4 ancrés","plafond a priori 28 rencontres pour 29 ancrés et 227 mobiles","99 retours imposés par 33 ancrages","Listes de travail","Titres de place non pourvus","Aucun.","Titres pressentis sans réservation","Aucun.","Réserve","Personnes en attente au tour 1","Isabelle Mirvault","Félix Abrevande","Hugo Fralvançon","Manon Fralveux","Catherine Luskotte","Zoé WAMMERWOLM-MAWWEMMEL","Catherine Urvesson","Karim Hulvivet","Caroline Selveron","Catherine Korvault","Caroline Fralvotte","Geneviève Jusvesson","Paul Abrevumet","Léa Fralvault","Fatima Obrivet","Zoé Dulveval","Paul Korveux","Julie Luskière","Émilie Clovande","Paul Hulvande","Hugo Fralvesson","Isabelle Urvière","Thomas Rozvotte","Isabelle Bralmumet","Catherine Dulvouze","Marc Voskichon","Simon Mirvivet","Louise Clovault","Lucie Voskeux","Amina Eskignac","Luc Selvoubre","Étienne Fralvichon","Philippe Voskivet","Louise Quilmançon","Sophie Luskande","Pierre Abreveron","Philippe Neskeux","Amina Neskançon","Léa Tolvande","Antoine Quilmeron","Guillaume Clovumet","Michel Eskeux","Louise Hulvault","Samuel Eskumet","Claire Fralvivet","Léa Mirveux","Karim Gorzesson","Sylvie Quilmande","François Gorzichon","Amina Pruvesson","Lucie Quilmière","Fatima Korvesson","Nicolas Selvesson","Louise Neskesson","Lucie Tolvesson","Olivier Quilmesson","Guillaume Luskivet","Gabriel Neskault","Antoine Urvumet","Olivier Jusvançon","Simon Dulvançon","Chloé Gorzard","Gabriel Pruveux","Manon Clovière","Karim Tolveval","Hugo Bérêçàuvïlle-Dœûmôntëÿ","Claire Gorzeron","Hélène Luskumet","Louis Fralvande","Émilie Selvault","Léa Neskumet","Isabelle Korvichon","Michel Obrande","Isabelle Luskeval","Fatima Tolvoubre","Zoé Gorzière","Sylvie Korvignac","Antoine Obreval","Camille Tolvumet","Marie Dulvesson","Guillaume Tolvignac","Gabriel Mirvotte","Paul Neskignac","Raphaël Ivrotte","Marc Luskouze","Sylvie Jusvotte","Véronique Bralmoubre","Pierre Selvard","Marie Hulveux","Karim Fralveval","Philippe Gorzignac","Étienne Selvouze","Louis Hulvichon","Sylvie Urvoubre","Pierre Pruveval","Guillaume Hulvotte","Geneviève Abrevignac","Amina Bralmignac","Olivier Bralmançon","Marc Luskoubre","Geneviève Abrevoubre","Raphaël Korvoubre","Pierre Mirvard","Camille Jusvumet","Samuel Cloveval","Antoine Selvière","Véronique Jusvouze","Paul Neskivet","Samuel Dulvande","Lucie Selveval","Olivier Tolvichon","Fatima Hulvard","Alexandre Ivreux","Félix Korveval","Karim Urvichon","Émilie Dulvichon","Luc Tolvouze","Amina Quilmault","François Ivrouze","Hélène Gorzumet","Sophie Ivrault","Louise Bralmière","Nicolas Korvande","Geneviève Ivrumet","Geneviève Obresson","Guillaume Obrançon","Fatima Urvignac","Claire Bralmotte","Félix Hulvignac","François Clovotte","Philippe Dulvoubre","Samuel Rozveron","Pierre Hulvoubre","Émilie Urvouze","Félix Korvançon","Émilie Neskande","Chantal Mirvumet","Alexandre Korvotte","Zoé Eskeval","Nathalie Voskoubre","Sophie Pruvière","Paul Obrichon","Nathalie Eskière","Caroline Ivreron","Véronique Neskoubre","Anne Urvivet","Olivier Hulvançon","Karim Clovançon","Zoé Quilmotte","Félix Eskouze","Amina Rozvichon","Simon Fralvière","Pierre Hulvière","Raphaël Jusvault","Pierre Fralvoubre","Hélène Selveux","Caroline Rozvançon","Olivier Korvière","Nicolas Ivrichon","Félix Korvumet","Guillaume Selvumet","Michel Urvotte","Émilie Eskault","Hélène Bralmeval","Guillaume Hulvesson","Caroline Jusvoubre","Félix Luskeux","Antoine Pruvouze","Julie Quilmignac","Hugo Voskumet","Manon Quilmumet","Marc Voskouze","Samuel Abrevard","Manon Clovesson","Simon Hulvumet","Lucie Voskeron","Jean Neskeron","Manon Pruvivet","Sophie Clovard","Étienne Gorzeval","Gabriel Luskault","Émilie Korvard","Thomas Quilmichon","Alexandre Eskançon","Émilie Luskançon","Marc Dulvault","Hélène Rozveval","Julie Pruvançon","Louis Mirveron","François Eskard","Louis Ivrançon","Karim Clovivet","Léa Rozvande","Amina Hulvouze","Étienne Eskesson","Philippe Abreveval","Émilie Quilmeux","Simon Voskotte","Chantal Obrignac","Guillaume Eskotte","Léa Obrard","Guillaume Gorzivet","Geneviève Mirvançon","Julie Selvotte","Amina Mirvesson","Isabelle Luskignac","Chloé Obrumet","Anne Abrevesson","Fatima Rozvumet","Guillaume Mirvoubre","Véronique Rozvoubre","Claire Gorzotte","Antoine Ivrière","Isabelle Selvichon","Isabelle Urvault","Julie Voskesson","Chantal Abrevotte","Amina Neskotte","Étienne Voskançon","Zoé Fralveron","Marc Rozvouze","Sylvie Abreveux","Karim Pruvignac","Zoé Mirveval","Philippe Fralvignac","Gabriel Gorzeux","Jean Urveval"],"theme":"clair","versionReelle":"2026.10.05.01"}, +{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"f84ef02eb03165eb14bd0933a9dc2771e9b0ef7a7b58e52c63ddcbaf33d1e1c4","etape":"4","etat":"4d37d30748068354162752743c26aa7e0ab00d6e9b2aa1996b6f9fb410848280","facteurEchelle":1,"fichier":"07a-cibles-tables","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"fb99b8e5274401e473ed1fea7e5cb7050f1fd0c777d465c2c6c87f1804078c4b"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-lecture","ratio":5.29,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":15.1,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":8.13,"role":"marque","seuil":3}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-lecture","ratio":7.34,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":8.89,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":14.62,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":11.32,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":5.59,"role":"marque","seuil":3}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Lecture","Liste des événements","Clair","Sombre","À propos","Modifier","Lecture","Défaire","Grande démonstration 1","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Badges","Plan","Réservations","Tour affiché","1","2","3","4","Zoom +","Zoom −","Ajuster","Listes de noms","Légende","Plein écran","5","m","disposition relative — l'encombrement dans la salle n'est pas vérifié","Diagnostic","écart d'itinéraire maximal : plancher 1, au moins 24 mobiles finissent sous leur plafond a priori","plafond a priori 24 rencontres pour 4 ancrés","plafond a priori 28 rencontres pour 29 ancrés et 227 mobiles","99 retours imposés par 33 ancrages","Listes de travail","Titres de place non pourvus","Aucun.","Titres pressentis sans réservation","Aucun.","Réserve","Personnes en attente au tour 1","Isabelle Mirvault","Félix Abrevande","Hugo Fralvançon","Manon Fralveux","Catherine Luskotte","Zoé WAMMERWOLM-MAWWEMMEL","Catherine Urvesson","Karim Hulvivet","Caroline Selveron","Catherine Korvault","Caroline Fralvotte","Geneviève Jusvesson","Paul Abrevumet","Léa Fralvault","Fatima Obrivet","Zoé Dulveval","Paul Korveux","Julie Luskière","Émilie Clovande","Paul Hulvande","Hugo Fralvesson","Isabelle Urvière","Thomas Rozvotte","Isabelle Bralmumet","Catherine Dulvouze","Marc Voskichon","Simon Mirvivet","Louise Clovault","Lucie Voskeux","Amina Eskignac","Luc Selvoubre","Étienne Fralvichon","Philippe Voskivet","Louise Quilmançon","Sophie Luskande","Pierre Abreveron","Philippe Neskeux","Amina Neskançon","Léa Tolvande","Antoine Quilmeron","Guillaume Clovumet","Michel Eskeux","Louise Hulvault","Samuel Eskumet","Claire Fralvivet","Léa Mirveux","Karim Gorzesson","Sylvie Quilmande","François Gorzichon","Amina Pruvesson","Lucie Quilmière","Fatima Korvesson","Nicolas Selvesson","Louise Neskesson","Lucie Tolvesson","Olivier Quilmesson","Guillaume Luskivet","Gabriel Neskault","Antoine Urvumet","Olivier Jusvançon","Simon Dulvançon","Chloé Gorzard","Gabriel Pruveux","Manon Clovière","Karim Tolveval","Hugo Bérêçàuvïlle-Dœûmôntëÿ","Claire Gorzeron","Hélène Luskumet","Louis Fralvande","Émilie Selvault","Léa Neskumet","Isabelle Korvichon","Michel Obrande","Isabelle Luskeval","Fatima Tolvoubre","Zoé Gorzière","Sylvie Korvignac","Antoine Obreval","Camille Tolvumet","Marie Dulvesson","Guillaume Tolvignac","Gabriel Mirvotte","Paul Neskignac","Raphaël Ivrotte","Marc Luskouze","Sylvie Jusvotte","Véronique Bralmoubre","Pierre Selvard","Marie Hulveux","Karim Fralveval","Philippe Gorzignac","Étienne Selvouze","Louis Hulvichon","Sylvie Urvoubre","Pierre Pruveval","Guillaume Hulvotte","Geneviève Abrevignac","Amina Bralmignac","Olivier Bralmançon","Marc Luskoubre","Geneviève Abrevoubre","Raphaël Korvoubre","Pierre Mirvard","Camille Jusvumet","Samuel Cloveval","Antoine Selvière","Véronique Jusvouze","Paul Neskivet","Samuel Dulvande","Lucie Selveval","Olivier Tolvichon","Fatima Hulvard","Alexandre Ivreux","Félix Korveval","Karim Urvichon","Émilie Dulvichon","Luc Tolvouze","Amina Quilmault","François Ivrouze","Hélène Gorzumet","Sophie Ivrault","Louise Bralmière","Nicolas Korvande","Geneviève Ivrumet","Geneviève Obresson","Guillaume Obrançon","Fatima Urvignac","Claire Bralmotte","Félix Hulvignac","François Clovotte","Philippe Dulvoubre","Samuel Rozveron","Pierre Hulvoubre","Émilie Urvouze","Félix Korvançon","Émilie Neskande","Chantal Mirvumet","Alexandre Korvotte","Zoé Eskeval","Nathalie Voskoubre","Sophie Pruvière","Paul Obrichon","Nathalie Eskière","Caroline Ivreron","Véronique Neskoubre","Anne Urvivet","Olivier Hulvançon","Karim Clovançon","Zoé Quilmotte","Félix Eskouze","Amina Rozvichon","Simon Fralvière","Pierre Hulvière","Raphaël Jusvault","Pierre Fralvoubre","Hélène Selveux","Caroline Rozvançon","Olivier Korvière","Nicolas Ivrichon","Félix Korvumet","Guillaume Selvumet","Michel Urvotte","Émilie Eskault","Hélène Bralmeval","Guillaume Hulvesson","Caroline Jusvoubre","Félix Luskeux","Antoine Pruvouze","Julie Quilmignac","Hugo Voskumet","Manon Quilmumet","Marc Voskouze","Samuel Abrevard","Manon Clovesson","Simon Hulvumet","Lucie Voskeron","Jean Neskeron","Manon Pruvivet","Sophie Clovard","Étienne Gorzeval","Gabriel Luskault","Émilie Korvard","Thomas Quilmichon","Alexandre Eskançon","Émilie Luskançon","Marc Dulvault","Hélène Rozveval","Julie Pruvançon","Louis Mirveron","François Eskard","Louis Ivrançon","Karim Clovivet","Léa Rozvande","Amina Hulvouze","Étienne Eskesson","Philippe Abreveval","Émilie Quilmeux","Simon Voskotte","Chantal Obrignac","Guillaume Eskotte","Léa Obrard","Guillaume Gorzivet","Geneviève Mirvançon","Julie Selvotte","Amina Mirvesson","Isabelle Luskignac","Chloé Obrumet","Anne Abrevesson","Fatima Rozvumet","Guillaume Mirvoubre","Véronique Rozvoubre","Claire Gorzotte","Antoine Ivrière","Isabelle Selvichon","Isabelle Urvault","Julie Voskesson","Chantal Abrevotte","Amina Neskotte","Étienne Voskançon","Zoé Fralveron","Marc Rozvouze","Sylvie Abreveux","Karim Pruvignac","Zoé Mirveval","Philippe Fralvignac","Gabriel Gorzeux","Jean Urveval"],"theme":"clair","versionReelle":"2026.10.05.01"}, +{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"19710bbe8b9d8edf50daedd0637c01035700dbfd103936befc95fa5a5948157b","etape":"5","etat":"7e19a3b61721017693ee5895e1b4a82e2f1656e35e71989ac4d29ea9cfc59fe8","facteurEchelle":1,"fichier":"07b-nombre-de-tours","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"a13bb17c3f135482346cbee373817868a83f664977533344184aa044c7990b6f"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5}],"sombre":[{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Badges","Tables et tours","Places par défaut","Nombre de tours","Passer de 3 à 2 tours ? Ce changement emporte :","Basile Lanterneau : réservation à la table 1 au tour 3, détruite","Annuler","Confirmer","Tables","Ajouter une table ronde","Ajouter une table carrée","Table","1","Ronde","Suit le défaut","Places","Supprimer","Table","2","Ronde","Surchargée","Places","Réaligner","Supprimer"],"theme":"clair","versionReelle":"2026.10.05.01"}, +{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"e58549be9ac69cdfd1605e945ae0ae16fcdff26d031b180a1cc8cda286aaa615","etape":"6","etat":"0ad50f28307185683e15e5660c2da2f3398d783d68988d637c519ef3ba0658a5","facteurEchelle":1,"fichier":"08-animateurs-designes","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"443072cde6446f90d3d543e4ee751ace5cbaa9e496e4b52eb6a0b6a3e8fa0f0e"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":4.78,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-pleine","ratio":15.38,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":15.1,"role":"marque","seuil":3},{"jeton":"--couleur-hachure","ratio":16.48,"role":"marque","seuil":3},{"jeton":"--couleur-marque","ratio":3.63,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-selection","ratio":4.66,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":7.58,"role":"marque","seuil":3}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":9.1,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-pleine","ratio":14.94,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":8.89,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":14.62,"role":"marque","seuil":3},{"jeton":"--couleur-hachure","ratio":15.21,"role":"marque","seuil":3},{"jeton":"--couleur-marque","ratio":3.5,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":11.32,"role":"marque","seuil":3},{"jeton":"--couleur-selection","ratio":4.18,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":5.59,"role":"marque","seuil":3}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Badges","Plan","Réservations","Tour affiché","1","2","3","Zoom +","Zoom −","Ajuster","Listes de noms","Légende","Plein écran","1. (réservée, tous les tours)","Basile Lanterneau","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","9. (libre)","10. (libre)","1. (libre)","— titre","animation","non pourvu","2. (réservée, tour 1)","Capucine Pommerel","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","1","m","disposition relative — l'encombrement dans la salle n'est pas vérifié","Diagnostic","Chœur de l’Anse","4 personnes : au moins 6 collisions cumulées sur les 3 tours, portées par au moins 2 paires distinctes","Société des Hérons","4 personnes : au moins 6 collisions cumulées sur les 3 tours, portées par au moins 2 paires distinctes","Cercle des Saules","3 personnes : au moins 3 collisions cumulées sur les 3 tours, portées par au moins 1 paire distincte","au moins 8 appartenances recroisées par personne","plafond a priori 11 rencontres pour 1 ancré et 11 mobiles","2 retours imposés par 1 ancrage","Listes de travail","Titres de place non pourvus","table 2 : titre","animation","non pourvu","Titres pressentis sans réservation","Gaspard Marbrelle","— titre pressenti","animation","Réserve","Personnes en attente au tour 1","Gaspard Marbrelle","Ysaline Sablonnet","Anselme Givrecœur","Côme Fenouillet","Apolline Coudraie","Basile Lanterneau","Brunœil","Faustine Ormelin","Edgar Ardoisier","Bertille Cressonnier","Table 2, siège 1","1. (libre)","— titre","animation","non pourvu","Choisissez d'abord une personne : dans la réserve, dans la liste des pressentis, ou par « Déplacer » dans son menu.","Portée","Tour 1","Tous les tours","Libellé du titre","Assigner","Réserver","Désigner","Retirer le titre"],"theme":"clair","versionReelle":"2026.10.05.01"}, +{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"2c9afe336a74750c7349bcab924d0495733d1cca77f43967cf6e361e3b439339","etape":"7","etat":"0ad50f28307185683e15e5660c2da2f3398d783d68988d637c519ef3ba0658a5","facteurEchelle":1,"fichier":"09-refus-sur-place","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"868fac3a5dde24aa5a84890a0385e946dbb0de4af8dd42953532ab801c133add"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":4.78,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-pleine","ratio":15.38,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":15.1,"role":"marque","seuil":3},{"jeton":"--couleur-hachure","ratio":16.48,"role":"marque","seuil":3},{"jeton":"--couleur-marque","ratio":3.63,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-refus","ratio":8.76,"role":"texte","seuil":4.5},{"jeton":"--couleur-selection","ratio":4.66,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":7.58,"role":"marque","seuil":3},{"jeton":"rgb(0, 0, 0)","ratio":18.26,"role":"texte","seuil":4.5}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":9.1,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-pleine","ratio":14.94,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":8.89,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":14.62,"role":"marque","seuil":3},{"jeton":"--couleur-hachure","ratio":15.21,"role":"marque","seuil":3},{"jeton":"--couleur-marque","ratio":3.5,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5},{"jeton":"--couleur-papier","ratio":5.33,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":11.32,"role":"marque","seuil":3},{"jeton":"--couleur-refus","ratio":9.24,"role":"texte","seuil":4.5},{"jeton":"--couleur-selection","ratio":4.18,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":5.59,"role":"marque","seuil":3}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Badges","Plan","Réservations","Tour affiché","1","2","3","Zoom +","Zoom −","Ajuster","Listes de noms","Légende","Plein écran","1. (réservée, tous les tours)","Basile Lanterneau","—","animation","2. (libre)","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","9. (libre)","10. (libre)","1. (libre)","— titre","animation","non pourvu","2. (réservée, tour 1)","Capucine Pommerel","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","Table 1, siège 1","Le siège 1 est réservé à une autre personne à tous les tours : déplacer sa réservation libère la place.","Choisir une place","Fermer","1","m","disposition relative — l'encombrement dans la salle n'est pas vérifié","Diagnostic","Chœur de l’Anse","4 personnes : au moins 6 collisions cumulées sur les 3 tours, portées par au moins 2 paires distinctes","Société des Hérons","4 personnes : au moins 6 collisions cumulées sur les 3 tours, portées par au moins 2 paires distinctes","Cercle des Saules","3 personnes : au moins 3 collisions cumulées sur les 3 tours, portées par au moins 1 paire distincte","au moins 8 appartenances recroisées par personne","plafond a priori 11 rencontres pour 1 ancré et 11 mobiles","2 retours imposés par 1 ancrage","Listes de travail","Titres de place non pourvus","table 2 : titre","animation","non pourvu","Titres pressentis sans réservation","Gaspard Marbrelle","— titre pressenti","animation","Réserve","Personnes en attente au tour 1","Gaspard Marbrelle","Ysaline Sablonnet","Anselme Givrecœur","Côme Fenouillet","Apolline Coudraie","Basile Lanterneau","Brunœil","Faustine Ormelin","Edgar Ardoisier","Bertille Cressonnier","Table 1, siège 1","1. (réservée, tous les tours)","Basile Lanterneau","—","animation","Personne choisie :","Gaspard Marbrelle","Assigner","Retirer la réservation","Retirer le titre","Oublier le choix","Menu de","Basile Lanterneau","Déplacer","Échanger","Retirer du tour","Déplacer sa réservation","Exclure","Mettre en évidence","Ouvrir la fiche"],"theme":"clair","versionReelle":"2026.10.05.01"}, +{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"78463eac80ed918ee56db0c81dd2b1e83a41ecf0d05b774580ac37c439171bfe","etape":"8","etat":"4d37d30748068354162752743c26aa7e0ab00d6e9b2aa1996b6f9fb410848280","facteurEchelle":1,"fichier":"10-diagnostic","graine":null,"image":{"hauteur":700,"largeur":1366,"sha256":"74b0aca5bfb2eb45593f8c3578da9fbd98e88a5b5e15ef8b48487f551975a61f"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-lecture","ratio":5.29,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5},{"jeton":"--couleur-page-texte-secondaire","ratio":7.05,"role":"texte","seuil":4.5}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-lecture","ratio":7.34,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5},{"jeton":"--couleur-page-texte-secondaire","ratio":7.98,"role":"texte","seuil":4.5}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Lecture","Liste des événements","Clair","Sombre","À propos","Modifier","Lecture","Défaire","Grande démonstration 1","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Badges","Diagnostic","écart d'itinéraire maximal : plancher 1, au moins 24 mobiles finissent sous leur plafond a priori","aucune relance ne le réduit : il tient aux tables pleines dont les capacités ou les ancrages diffèrent","plafond a priori 24 rencontres pour 4 ancrés","seules les capacités et les réservations le changent : aucune relance ne le dépasse","plafond a priori 28 rencontres pour 29 ancrés et 227 mobiles","seules les capacités et les réservations le changent : aucune relance ne le dépasse","99 retours imposés par 33 ancrages","les réservations les imposent : ils ne comptent pas parmi les retours que choisit le moteur"],"theme":"clair","versionReelle":"2026.10.05.01"}, +{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"609cee6886e7a3e30dbf520fc2fc7e6432d889032bc2dbde76f90ad04fcfacf6","etape":"9","etat":"78c47299a88ae35b3dc4c09bededdd6e0e9dc695a35d313d74f46c9cbede5573","facteurEchelle":1,"fichier":"11-propositions","graine":4242,"image":{"hauteur":700,"largeur":1366,"sha256":"7e0d73294910ac8c344f871d1f6e217352a70978b557f80b6516c13049278af5"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":4.78,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":9.1,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Badges","Propositions","Ordre du classement, chaque critère au plus faible d'abord :","écart au plafond a priori",", puis","excédent de collisions",", puis","collisions cumulées",", puis","rencontres répétées",", puis","redondance d'appartenance",", puis","l'identifiant croissant",".","Propositions classées","Rang","Proposition","Personnes distinctes rencontrées, minimum : tous","Personnes distinctes rencontrées, minimum : mobiles","Personnes distinctes rencontrées, minimum : ancrés","Collisions cumulées (paire et tour)","Paires distinctes de même appartenance","Excédent de collisions (retrouvailles au-delà de la première)","Rencontres répétées choisies (paires)","Rencontres d'une même paire, au plus","Retours choisis à une table déjà occupée","Appartenances rencontrées A(p), minimum","Redondance d'appartenance, somme Σ r(p)","Taux de diversité d(p), minimum","Plus grand manque (personnes)","Personnes à qui il en manque","Écart d'itinéraire maximal (personnes)","Écart au plafond a priori maximal (personnes)","Certificat","Imposé par les réservations","Commandes","Placement retenu","3","Tel que la proposition n° 3.","11","11","11","26","15","11","30","3","11","3","85","0,27","0","0","0","0","minimum atteint","2 retours imposés par 1 ancrage.","Aucune rencontre répétée imposée.","Voir sur le plan","1","3","retenue","11","11","11","26","15","11","30","3","11","3","85","0,27","0","0","0","0","minimum atteint","2 retours imposés par 1 ancrage.","Aucune rencontre répétée imposée.","Voir sur le plan","Retenir","2","1","11","11","11","27","15","12","19","3","16","3","85","0,27","0","0","0","0","minimum atteint","2 retours imposés par 1 ancrage.","Aucune rencontre répétée imposée.","Voir sur le plan","Retenir","3","2","11","11","11","33","15","18","54","3","16","3","85","0,27","0","0","0","0","minimum atteint","2 retours imposés par 1 ancrage.","Aucune rencontre répétée imposée.","Voir sur le plan","Retenir","4","5","10","10","10","20","15","5","22","3","12","3","83","0,27","1","1","1","1","atteignabilité inconnue","2 retours imposés par 1 ancrage.","Aucune rencontre répétée imposée.","Voir sur le plan","Retenir","5","4","10","10","11","31","14","17","46","3","17","3","82","0,30","1","4","0","1","atteignabilité inconnue","2 retours imposés par 1 ancrage.","Aucune rencontre répétée imposée.","Voir sur le plan","Retenir","Le numéro de la proposition, donné à sa génération ; un numéro effacé ne revient jamais. Il sert de dernier départage : deux propositions égales sur tous les critères se rangent par numéro croissant.","Cible de la somme de redondance","La liste des événements montre, pour le placement retenu, la différence sans signe entre cette cible et la somme Σ r(p) de la colonne « Redondance d'appartenance ». Un nombre entier, 0 ou plus.","Effacer les propositions"],"theme":"clair","versionReelle":"2026.10.05.01"}, +{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"b0493a03b5a4aa0ffcaa1f2c87c3fa02a066f9795ac839925461f0d65daeecbd","etape":"11","etat":"78c47299a88ae35b3dc4c09bededdd6e0e9dc695a35d313d74f46c9cbede5573","facteurEchelle":1,"fichier":"19-ajustement","graine":4242,"image":{"hauteur":700,"largeur":1366,"sha256":"de987d6b42e8a6f51bc7675e9e0f2c7ec2e0902e8eb7783d37f8281e077d63ec"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":13.44,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":4.78,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-pleine","ratio":15.38,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-conflit-appartenance","ratio":8.92,"role":"marque","seuil":3},{"jeton":"--couleur-contour-fort","ratio":12.54,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":15.1,"role":"marque","seuil":3},{"jeton":"--couleur-fantome","ratio":4.34,"role":"marque","seuil":3},{"jeton":"--couleur-hachure","ratio":16.48,"role":"marque","seuil":3},{"jeton":"--couleur-marque","ratio":3.63,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5},{"jeton":"--couleur-pastille-fond","ratio":13.44,"role":"marque","seuil":3},{"jeton":"--couleur-poignee","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":7.58,"role":"marque","seuil":3}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-ecriture","ratio":9.1,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-pleine","ratio":14.94,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":8.89,"role":"marque","seuil":3},{"jeton":"--couleur-conflit-appartenance","ratio":6.81,"role":"marque","seuil":3},{"jeton":"--couleur-contour-fort","ratio":11.62,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":14.62,"role":"marque","seuil":3},{"jeton":"--couleur-fantome","ratio":4.1,"role":"marque","seuil":3},{"jeton":"--couleur-hachure","ratio":15.21,"role":"marque","seuil":3},{"jeton":"--couleur-marque","ratio":3.5,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":11.39,"role":"texte","seuil":4.5},{"jeton":"--couleur-pastille-fond","ratio":11.62,"role":"marque","seuil":3},{"jeton":"--couleur-pastille-texte","ratio":14.51,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":11.32,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":5.59,"role":"marque","seuil":3}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Écriture","Liste des événements","Clair","Sombre","À propos","Revenir en lecture","Écriture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Badges","Plan","Placement retenu","Tour affiché","1","2","3","Zoom +","Zoom −","Ajuster","Listes de noms","Légende","Plein écran","9","1. (réservée, tous les tours)","Basile Lanterneau","—","animation","2.","Gaspard Marbrelle","3.","Ysaline Sablonnet","4.","Anselme Givrecœur","5.","Côme Fenouillet","6.","Apolline Coudraie","7.","Brunœil","8.","Faustine Ormelin","9.","Edgar Ardoisier","10.","Bertille Cressonnier","1.","Basile Lanterneau","— titre","animation","non pourvu","2. (réservée, tour 1)","Capucine Pommerel","3. (libre)","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","Gaspard Marbrelle","déplace dans le placement retenu","1","m","disposition relative — l'encombrement dans la salle n'est pas vérifié","Diagnostic","Chœur de l’Anse","4 personnes : au moins 6 collisions cumulées sur les 3 tours, portées par au moins 2 paires distinctes","Société des Hérons","4 personnes : au moins 6 collisions cumulées sur les 3 tours, portées par au moins 2 paires distinctes","Cercle des Saules","3 personnes : au moins 3 collisions cumulées sur les 3 tours, portées par au moins 1 paire distincte","au moins 8 appartenances recroisées par personne","plafond a priori 11 rencontres pour 1 ancré et 11 mobiles","2 retours imposés par 1 ancrage","Listes de travail","Titres de place non pourvus","table 2 : titre","animation","non pourvu","Titres pressentis sans réservation","Gaspard Marbrelle","— titre pressenti","animation","Réserve","Personnes en attente au tour 1","Personne en attente à ce tour."],"theme":"clair","versionReelle":"2026.10.05.01"}, +{"cadre":{"hauteur":700,"largeur":1366},"empreinte":"4ccadc12b652215c6611b87fd70c9579e0cf4cfd48b5a9b98bba9f80f471cfe2","etape":"11","etat":"20666d70d9b2503335efc1f2cece5453a199ab77f4864835baf4bccf5aff17d5","facteurEchelle":1,"fichier":"20-mode-lecture","graine":4242,"image":{"hauteur":700,"largeur":1366,"sha256":"0d66820beae96b1724c177ed6a2b949173051c8dec9c564692461aac01877c1b"},"instant":"2026-10-06T19:00:00-04:00","mode":"chromium-headless-shell","pdf":null,"source":"navigateur","styles":{"clair":[{"jeton":"--couleur-bandeau-fond","ratio":14.26,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":13.44,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-lecture","ratio":5.29,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-pleine","ratio":15.38,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-conflit-appartenance","ratio":8.92,"role":"marque","seuil":3},{"jeton":"--couleur-contour-fort","ratio":12.54,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":15.1,"role":"marque","seuil":3},{"jeton":"--couleur-hachure","ratio":16.48,"role":"marque","seuil":3},{"jeton":"--couleur-marque","ratio":3.63,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":15.1,"role":"texte","seuil":4.5},{"jeton":"--couleur-pastille-fond","ratio":13.44,"role":"marque","seuil":3},{"jeton":"--couleur-poignee","ratio":7.58,"role":"marque","seuil":3},{"jeton":"--couleur-selection","ratio":4.66,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":7.58,"role":"marque","seuil":3}],"sombre":[{"jeton":"--couleur-bandeau-fond","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-bandeau-texte","ratio":12.84,"role":"texte","seuil":4.5},{"jeton":"--couleur-cadre-lecture","ratio":7.34,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-pleine","ratio":14.94,"role":"marque","seuil":3},{"jeton":"--couleur-chaise-trait","ratio":8.89,"role":"marque","seuil":3},{"jeton":"--couleur-conflit-appartenance","ratio":6.81,"role":"marque","seuil":3},{"jeton":"--couleur-contour-fort","ratio":11.62,"role":"marque","seuil":3},{"jeton":"--couleur-echelle","ratio":14.62,"role":"marque","seuil":3},{"jeton":"--couleur-hachure","ratio":15.21,"role":"marque","seuil":3},{"jeton":"--couleur-marque","ratio":3.5,"role":"marque","seuil":3},{"jeton":"--couleur-page-texte","ratio":14.62,"role":"texte","seuil":4.5},{"jeton":"--couleur-pastille-fond","ratio":11.62,"role":"marque","seuil":3},{"jeton":"--couleur-pastille-texte","ratio":14.51,"role":"texte","seuil":4.5},{"jeton":"--couleur-poignee","ratio":11.32,"role":"marque","seuil":3},{"jeton":"--couleur-selection","ratio":4.18,"role":"marque","seuil":3},{"jeton":"--couleur-table-trait","ratio":5.59,"role":"marque","seuil":3}]},"texte":["Gestion table tournante Libre","construction de documentation","documentation","Lecture","Liste des événements","Clair","Sombre","À propos","Modifier","Lecture","Défaire","Soirée d’essai","Brouillon","Proposé","Retenu","Bloqué","Imprimer…","Import","Participants","Tables et tours","Plan","Diagnostic","Génération","Propositions","Badges","Plan","Placement retenu","Tour affiché","1","2","3","Zoom +","Zoom −","Ajuster","Listes de noms","Légende","Plein écran","7","1. (réservée, tous les tours)","Basile Lanterneau","—","animation","2.","Ysaline Sablonnet","3.","Anselme Givrecœur","4.","Côme Fenouillet","5.","Apolline Coudraie","6.","Brunœil","7.","Faustine Ormelin","8.","Edgar Ardoisier","9.","Bertille Cressonnier","10. (libre)","1.","Gaspard Marbrelle","— titre","animation","non pourvu","2. (réservée, tour 1)","Capucine Pommerel","3.","Basile Lanterneau","4. (libre)","5. (libre)","6. (libre)","7. (libre)","8. (libre)","Table 2, siège 4","L'événement est ouvert en lecture : « Modifier » permet de le changer.","Modifier","Fermer","1","m","disposition relative — l'encombrement dans la salle n'est pas vérifié","Diagnostic","Chœur de l’Anse","4 personnes : au moins 6 collisions cumulées sur les 3 tours, portées par au moins 2 paires distinctes","Société des Hérons","4 personnes : au moins 6 collisions cumulées sur les 3 tours, portées par au moins 2 paires distinctes","Cercle des Saules","3 personnes : au moins 3 collisions cumulées sur les 3 tours, portées par au moins 1 paire distincte","au moins 8 appartenances recroisées par personne","plafond a priori 11 rencontres pour 1 ancré et 11 mobiles","2 retours imposés par 1 ancrage","Listes de travail","Titres de place non pourvus","table 2 : titre","animation","non pourvu","Titres pressentis sans réservation","Gaspard Marbrelle","— titre pressenti","animation","Réserve","Personnes en attente au tour 1","Personne en attente à ce tour.","Table 2, siège 4","4. (libre)","Choisissez d'abord une personne : dans la réserve, dans la liste des pressentis, ou par « Déplacer » dans son menu.","Portée","Tour 1","Tous les tours","Libellé du titre","Assigner","Réserver","Donner un titre","Désigner"],"theme":"clair","versionReelle":"2026.10.05.01"} ],"format":1,"pilote":{"cadre":{"hauteur":700,"largeur":1366},"facteurEchelle":1,"mode":"chromium-headless-shell","navigateur":"chromium","versionNavigateur":"153.0.8010.12"},"reportees":[ {"etape":"10","fichier":"12-qualite-profil","raison":"iteration5"}, {"etape":"10","fichier":"13-qualite-collisions","raison":"iteration5"}, diff --git a/src/interface/badges/Badges.navigateur.test.js b/src/interface/badges/Badges.navigateur.test.js new file mode 100644 index 0000000..f8f13ac --- /dev/null +++ b/src/interface/badges/Badges.navigateur.test.js @@ -0,0 +1,472 @@ +// © 2026 TechnoLibre (http://www.technolibre.ca) +// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) + +// La section des badges dans un vrai moteur de rendu (§ 2.1 étape 12, +// § 11.2, § 11.6, § 11.8, § 8.4, § 8.5, § 14.6, Q1, Q3) : la question du +// papier à la première production, et jamais ensuite, sur cette machine ; +// l'annonce avant de produire — planches des deux papiers, dérive nommée, +// « Produire » désactivé et expliqué tant que le refus tient ; la +// production en lecture et sur un plan bloqué sans écriture de l'état ni du +// journal ; le chemin produit, « Ouvrir le dossier », la réédition ; le +// refus d'écriture et son remède « Enregistrer sous… » ; le choix de la +// source, de l'imposition et de l'ordre, et le retrait de l'annonce quand +// un réglage ou le papier change ; le téléchargement sous web ; la langue +// témoin. +// +// App est montée par test/navigateur/ecrans.js sur le système de fichiers +// simulé ; le texte attendu vient de la même traduction que celle de +// l'application, les comptes du témoin de test/fixtures/badges/temoin.js. +// +// Le projet navigateur emploie expect, et test et describe de Vitest +// (§ 14.8). +import { afterEach, beforeEach, describe, expect, test } from 'vitest'; +import { appliquerCommande } from '../../application/commandes.js'; +import { TABLES_APPLICATION } from '../../application/libelles.js'; +import { MARQUE_TEMOIN, creerTraduction } from '../../application/traduction.js'; +import { PAPIERS } from '../../geometrie/papiers.js'; +import { SUFFIXES } from '../../stockage/noms.js'; +import { FICHIER_REGLAGES } from '../../stockage/reglages_locaux.js'; +import { fixerCadre } from '../../../test/navigateur/entrees.js'; +import { BASE, attendre, chargeBloquee, chargePrincipale, cliquer, creerContexte, fichierReglages, ouvrirEvenement } from '../../../test/navigateur/ecrans.js'; +import { FORME_TEMOIN, chargeTemoin } from '../../../test/fixtures/badges/temoin.js'; +import { clesPapier } from '../impression/modele.js'; +import { TABLES_INTERFACE } from '../libelles.js'; +import { personnesReeditables } from './modele.js'; + +const TABLES = [...TABLES_APPLICATION, ...TABLES_INTERFACE]; +const { t } = creerTraduction(TABLES); + +// Images attendues au plus pour une préparation ou une production : la +// police et pdf-lib se chargent à la première, et le témoin met en page +// 257 badges. +const IMAGES = 1800; + +let contexte = null; +beforeEach(async () => { + await fixerCadre(1366, 700); + contexte = creerContexte(); +}); +afterEach(async () => { + const erreurs = contexte.erreurs(); + await contexte.defaire(); + expect(erreurs, 'erreurs reçues par le collecteur').toEqual([]); +}); + +const dans = (m, selecteur) => m.racine.querySelector(selecteur); +const plat = (chaine) => chaine.replace(/\s+/g, ' ').trim(); +const texte = (element) => plat(element.textContent); +const section = (m) => dans(m, '[data-section="badges"]'); +const annonce = (m) => dans(m, '[data-section="badges"] [data-annonce-planche]'); +const question = (m) => dans(m, '[data-section="badges"] [data-papier="question"]'); +const produire = (m) => dans(m, '[data-section="badges"] [data-commande="produirePlanche"]'); + +// Les écritures relevées depuis le rang donné : celles qui touchent l'état, +// le journal ou la version précédente d'un événement, et toutes les autres. +const ecrituresEvenement = (m, depuis) => + m.trace.slice(depuis).filter(([, , chemin]) => [SUFFIXES.etat, SUFFIXES.journal, SUFFIXES.precedent].some((suffixe) => chemin.endsWith(suffixe))); +const planchesEcrites = (m, depuis) => m.trace.slice(depuis).filter(([primitive]) => primitive === 'ecrireOctetsAtomique'); + +// La principale, sa proposition retenue, sur un plan retenu. +function chargeRetenue() { + const principale = chargePrincipale(); + return appliquerCommande('retenirProposition', principale, { id: principale.propositions[0].id }).charge; +} + +// Ouvre l'événement de la charge sur la section des badges, le papier de +// la machine posé dans les réglages locaux ; null n'en pose aucun. +function ouvrirBadges(charge, { papier = 'A4', ecriture = false, options = {} } = {}) { + const fichiers = [...(papier === null ? [] : [fichierReglages(papier)]), ...(options.fichiers ?? [])]; + return ouvrirEvenement(contexte, charge, { ecriture, section: 'badges', options: { ...options, fichiers } }); +} + +// Choisit la valeur d'un sélecteur de la section, comme l'opérateur. +function choisirReglage(m, champ, valeur) { + const choix = dans(m, `[data-section="badges"] [data-champ="${champ}"]`); + choix.value = valeur; + choix.dispatchEvent(new Event('change', { bubbles: true })); +} + +// Relève chaque demande que la section passe à seance.produirePlanche, et +// la transmet telle quelle. +function releverDemandes(m) { + const demandes = []; + const originale = m.seance.produirePlanche; + m.seance.produirePlanche = (demande) => { + demandes.push(demande); + return originale(demande); + }; + return demandes; +} + +// Clique « Produire » et attend l'issue que condition rend. +async function cliquerProduire(m, quoi, condition) { + produire(m).click(); + return attendre(quoi, condition, IMAGES); +} + +// Le texte attendu des planches sur chaque papier, le papier choisi marqué. +const textePlanches = (planches, choisi) => + t('badges.annonce.planches', { + parPapier: Object.keys(PAPIERS).map((papier) => ({ papier, nom: clesPapier(papier).nom, planches: planches[papier], choisi: papier === choisi })), + }); + +// Le chemin attendu d'un fichier du dossier de travail des épreuves. +async function cheminDocuments(m, nom) { + const { separateur } = await m.fs.emplacements(); + const racine = m.seance.etat().racine; + return `${racine.chemin}${separateur}${nom}`; +} + +describe('la question du papier : à la première production, jamais ensuite (§ 8.5, § 11.2, Q1)', () => { + test('le témoin : « Produire » sans papier annonce 65 planches A4 et 129 Lettre et pose la question ; le choix fait, la planche se produit', async () => { + const m = await ouvrirBadges(chargeTemoin(), { papier: null }); + // Avant toute production, la section ne pose pas la question. + expect(dans(m, '[data-section="badges"] [data-papier]')).toBeNull(); + await cliquerProduire(m, 'la question du papier', () => question(m)); + const lue = texte(annonce(m)); + const { planchesA4: A4, planchesLettre } = FORME_TEMOIN; + const planches = Object.fromEntries(Object.keys(PAPIERS).map((papier, rang) => [papier, [A4, planchesLettre][rang]])); + expect(lue).toContain(plat(textePlanches(planches, null))); + expect(lue).toContain(plat(t('badges.annonce.comptes', { produits: FORME_TEMOIN.produits, participants: FORME_TEMOIN.participants, exclus: FORME_TEMOIN.exclus }))); + expect(dans(m, '[data-annonce-planche] [data-refus="PAPIER_REQUIS"]')).not.toBeNull(); + expect(planchesEcrites(m, 0)).toEqual([]); + const depuis = m.trace.length; + dans(m, '[data-papier="question"] [data-cible="A4"] [data-commande="choisirPapier"]').click(); + const chemin = await attendre('la planche produite', () => dans(m, '[data-chemin-planche]'), IMAGES); + expect(m.seance.etat().papier).toBe('A4'); + const ecrites = planchesEcrites(m, depuis); + expect(ecrites).toHaveLength(1); + expect(ecrites[0][2]).toMatch(/_A4_feuille_/); + expect(texte(chemin)).toBe(await cheminDocuments(m, ecrites[0][2])); + expect(question(m)).toBeNull(); + expect(texte(annonce(m))).toContain(plat(textePlanches(planches, 'A4'))); + }); + + test('une seconde production, puis un nouvel événement, puis App remontée sur le même système : jamais redemandée ; « Changer » la modifie', async () => { + const m = await ouvrirBadges(chargeBloquee(), { papier: null }); + await cliquerProduire(m, 'la question du papier', () => question(m)); + dans(m, '[data-papier="question"] [data-cible="A4"] [data-commande="choisirPapier"]').click(); + await attendre('la première planche', () => dans(m, '[data-chemin-planche]'), IMAGES); + // Les réglages locaux portent le papier : la seule écriture hors du PDF. + expect(JSON.parse(m.fs.contenu('documents', FICHIER_REGLAGES)).papier).toBe('A4'); + + // Une seconde production : aucune question, la planche se réécrit. + const depuis = m.trace.length; + await cliquerProduire(m, 'la seconde planche', () => planchesEcrites(m, depuis).length === 1); + expect(question(m)).toBeNull(); + expect(texte(dans(m, '[data-papier="choisi"]'))).toContain(t('impression.papier.nom.a4')); + + // Un nouvel événement, sans placement : la section montre le papier, et + // « Produire » dit le refus du placement, jamais la question. + await m.seance.fermer(); + await m.seance.creer({ nom: 'Bal des Pervenches', date: null, siegesParDefaut: 8, tours: 2 }); + m.ui.allerA('badges'); + await attendre('la section du nouvel événement', () => section(m) && dans(m, '[data-papier="choisi"]'), IMAGES); + await cliquerProduire(m, 'le refus du placement', () => dans(m, '[data-annonce-planche] [data-refus="PLANCHE_SANS_PLACEMENT"]')); + expect(question(m)).toBeNull(); + + // App remontée sur le même disque : le papier se relit, la question ne + // vient pas, la planche se produit. + const second = await contexte.monter({ systeme: { disque: m.disque } }); + await cliquer(second, `[data-evenement="${BASE}"] [data-commande="ouvrir"]`); + await cliquer(second, '[data-commande="section"][data-cible="badges"]'); + await attendre('le papier relu', () => dans(second, '[data-section="badges"] [data-papier="choisi"]'), IMAGES); + const avant = second.trace.length; + await cliquerProduire(second, 'la planche du second montage', () => dans(second, '[data-chemin-planche]')); + expect(question(second)).toBeNull(); + expect(planchesEcrites(second, avant)).toHaveLength(1); + + // « Changer » rouvre la question ; le nouveau papier s'écrit, et la + // planche suivante le porte. + dans(second, '[data-papier="choisi"] [data-commande="changerPapier"]').click(); + await attendre('la question rouverte', () => question(second), IMAGES); + const lettre = Object.keys(PAPIERS)[1]; + dans(second, `[data-papier="question"] [data-cible="${lettre}"] [data-commande="choisirPapier"]`).click(); + await attendre('le papier changé', () => second.seance.etat().papier === lettre, IMAGES); + expect(JSON.parse(second.fs.contenu('documents', FICHIER_REGLAGES)).papier).toBe(lettre); + const ensuite = second.trace.length; + await cliquerProduire(second, 'la planche sur le nouveau papier', () => planchesEcrites(second, ensuite).length === 1); + expect(planchesEcrites(second, ensuite)[0][2]).toContain(`_${lettre}_`); + }); +}); + +describe('sortir n’est pas modifier (§ 8.4, § 11.6, contrainte 24)', () => { + test('en lecture, sur une proposition : préparer et produire passent, BROUILLON annoncé ; seuls le PDF et les réglages s’écrivent', async () => { + // La principale n'a pas de retenu : l'ouverture demande au plan sa + // première proposition, la source de la planche. + const charge = chargePrincipale(); + const m = await ouvrirBadges(charge, { papier: null }); + expect(m.seance.etat().mode).toBe('lecture'); + const depuis = m.trace.length; + dans(m, '[data-section="badges"] [data-commande="preparerPlanche"]').click(); + await attendre('l’annonce', () => annonce(m), IMAGES); + const lue = texte(annonce(m)); + expect(lue).toContain(plat(t('badges.annonce.source.proposition', { id: charge.propositions[0].id }))); + expect(lue).toContain(plat(t('badges.annonce.brouillon.proposition'))); + dans(m, '[data-annonce-planche] [data-refus="PAPIER_REQUIS"] [data-commande="choisirPapier"]').click(); + await attendre('la question du papier', () => question(m), IMAGES); + dans(m, '[data-papier="question"] [data-cible="A4"] [data-commande="choisirPapier"]').click(); + await attendre('l’annonce sans refus', () => annonce(m) && dans(m, '[data-annonce-planche] [data-refus]') === null, IMAGES); + await cliquerProduire(m, 'la planche', () => dans(m, '[data-chemin-planche]')); + expect(ecrituresEvenement(m, depuis)).toEqual([]); + expect(m.trace.slice(depuis).map(([primitive, , chemin]) => [primitive, chemin.endsWith('.pdf') ? 'pdf' : chemin])).toEqual([ + ['ecrireAtomique', FICHIER_REGLAGES], + ['ecrireOctetsAtomique', 'pdf'], + ]); + }); + + test('sur un plan bloqué : la planche se produit, sans BROUILLON ; seule l’écriture du PDF', async () => { + const m = await ouvrirBadges(chargeBloquee()); + expect(m.seance.etat().charge.evenement.etat).toBe('bloque'); + const depuis = m.trace.length; + await cliquerProduire(m, 'la planche', () => dans(m, '[data-chemin-planche]')); + expect(texte(annonce(m))).not.toContain('BROUILLON'); + expect(texte(annonce(m))).toContain(plat(t('badges.annonce.source.retenu'))); + expect(m.trace.slice(depuis).map(([primitive]) => primitive)).toEqual(['ecrireOctetsAtomique']); + expect(ecrituresEvenement(m, depuis)).toEqual([]); + }); +}); + +describe('la dérive, nommée avant toute production (§ 11.8)', () => { + test('« Produire » sur un retenu en dérive : le refus nomme la personne ajoutée, rien ne s’écrit ; « Produire » reste désactivé et expliqué tant que le refus tient', async () => { + const charge = appliquerCommande('ajouterParticipant', chargeRetenue(), { champs: { nom: 'Ombrelle', prenom: 'Iris' } }).charge; + const ajoutee = charge.participants.at(-1).id; + const m = await ouvrirBadges(charge); + const depuis = m.trace.length; + await cliquerProduire(m, 'le refus de dérive', () => dans(m, '[data-annonce-planche] [data-refus="PLANCHE_DERIVE"]')); + const refus = dans(m, '[data-annonce-planche] [data-refus="PLANCHE_DERIVE"]'); + expect(texte(refus)).toContain('Iris Ombrelle'); + expect(refus.querySelector('[data-commande="ouvrirSection"]')).not.toBeNull(); + expect(planchesEcrites(m, depuis)).toEqual([]); + + const bouton = produire(m); + expect(bouton.getAttribute('aria-disabled')).toBe('true'); + const explication = m.racine.querySelector(`#${CSS.escape(bouton.getAttribute('aria-describedby'))}`); + expect(texte(explication)).toBe(plat(t('badges.produire.bloque'))); + bouton.click(); + await attendre('une image', () => true); + expect(planchesEcrites(m, depuis)).toEqual([]); + expect(dans(m, '[data-chemin-planche]')).toBeNull(); + + // La personne retirée, la dérive tombe : l'annonce d'avant se retire, + // et « Produire » produit. + await m.seance.passerEnEcriture(); + await m.seance.executer('supprimerParticipant', { id: ajoutee }); + await attendre('« Produire » rendu', () => produire(m)?.getAttribute('aria-disabled') === null && annonce(m) === null, IMAGES); + await cliquerProduire(m, 'la planche', () => dans(m, '[data-chemin-planche]')); + expect(planchesEcrites(m, depuis)).toHaveLength(1); + }); +}); + +describe('la planche produite, le dossier, la réédition (§ 11.6, § 11.8)', () => { + test('le chemin s’affiche ; « Ouvrir le dossier » appelle la façade sur le dossier de travail ; trois badges se rééditent', async () => { + const charge = chargeBloquee(); + const m = await ouvrirBadges(charge); + const depuis = m.trace.length; + await cliquerProduire(m, 'la planche', () => dans(m, '[data-chemin-planche]')); + const [[, , nom]] = planchesEcrites(m, depuis); + expect(texte(dans(m, '[data-chemin-planche]'))).toBe(await cheminDocuments(m, nom)); + expect(new TextDecoder().decode(m.fs.octets('documents', nom).slice(0, 5))).toBe('%PDF-'); + + const ouvertes = []; + const originale = m.fs.ouvrirDansExplorateur; + m.fs.ouvrirDansExplorateur = async (racine) => { + ouvertes.push(racine); + return originale(racine); + }; + dans(m, '[data-section="badges"] [data-commande="ouvrirDossier"]').click(); + await attendre('l’explorateur appelé', () => ouvertes.length === 1, IMAGES); + expect(ouvertes[0].id).toBe(m.seance.etat().racine.id); + + // Trois personnes cochées, dans le désordre de la liste. + const personnes = personnesReeditables(charge); + const choisies = [personnes[4].id, personnes[0].id, personnes[2].id]; + for (const id of choisies) { + dans(m, `[data-section="badges"] li[data-participant="${id}"] input[type="checkbox"]`).click(); + } + const reediter = await attendre('« Rééditer 3 badges »', () => dans(m, '[data-section="badges"] [data-commande="reediter"]'), IMAGES); + expect(texte(reediter)).toBe(plat(t('badges.reedition.produire', { n: 3 }))); + const avant = m.trace.length; + reediter.click(); + await attendre('la réédition', () => planchesEcrites(m, avant).length === 1, IMAGES); + const [[, , nomReedition]] = planchesEcrites(m, avant); + expect(nomReedition).toMatch(/\.badges-3_A4_feuille_/); + await attendre('son chemin', () => texte(dans(m, '[data-chemin-planche]')).endsWith(nomReedition), IMAGES); + expect(texte(annonce(m))).toContain(plat(t('badges.annonce.reedition', { n: 3 }))); + expect(ecrituresEvenement(m, depuis)).toEqual([]); + }); + + test('le filtre restreint la liste ; une personne cochée le reste sous le filtre', async () => { + const charge = chargeBloquee(); + const m = await ouvrirBadges(charge); + const [premiere, seconde] = personnesReeditables(charge); + dans(m, `li[data-participant="${premiere.id}"] input[type="checkbox"]`).click(); + const champ = dans(m, '[data-section="badges"] [data-champ="reedition"]'); + champ.value = seconde.nom; + champ.dispatchEvent(new Event('input', { bubbles: true })); + await attendre('la liste filtrée', () => dans(m, `li[data-participant="${premiere.id}"]`) === null, IMAGES); + expect(dans(m, `li[data-participant="${seconde.id}"]`)).not.toBeNull(); + expect(texte(dans(m, '[data-commande="reediter"]'))).toBe(plat(t('badges.reedition.produire', { n: 1 }))); + champ.value = 'zzzz'; + champ.dispatchEvent(new Event('input', { bubbles: true })); + await attendre('aucune personne', () => texte(section(m)).includes(plat(t('badges.reedition.aucune'))), IMAGES); + }); +}); + +describe('l’imposition et l’ordre (§ 11.6)', () => { + test('« En pile » puis « Par table du premier tour » passent à la demande : la planche porte _pile_, l’annonce nomme son fichier', async () => { + const m = await ouvrirBadges(chargeBloquee()); + const demandes = releverDemandes(m); + choisirReglage(m, 'imposition', 'pile'); + const depuis = m.trace.length; + await cliquerProduire(m, 'la planche en pile', () => planchesEcrites(m, depuis).length === 1); + const [[, , nom]] = planchesEcrites(m, depuis); + expect(nom).toMatch(/_A4_pile_/); + expect(texte(annonce(m))).toContain(plat(t('badges.annonce.fichier', { nom }))); + + choisirReglage(m, 'ordre', 'table'); + const ensuite = m.trace.length; + await cliquerProduire(m, 'la planche par table', () => planchesEcrites(m, ensuite).length === 1); + expect(demandes.map(({ imposition, ordre }) => ({ imposition, ordre }))).toEqual([ + { imposition: 'pile', ordre: 'alphabetique' }, + { imposition: 'pile', ordre: 'table' }, + ]); + }); + + test('l’annonce montrée se retire quand l’imposition change, puis quand le papier change', async () => { + const m = await ouvrirBadges(chargeBloquee()); + const preparer = () => dans(m, '[data-section="badges"] [data-commande="preparerPlanche"]').click(); + preparer(); + await attendre('l’annonce feuille par feuille', () => annonce(m), IMAGES); + expect(texte(annonce(m))).toMatch(/_A4_feuille_/); + choisirReglage(m, 'imposition', 'pile'); + await attendre('une image', () => true); + expect(annonce(m)).toBeNull(); + + preparer(); + await attendre('l’annonce en pile', () => annonce(m), IMAGES); + expect(texte(annonce(m))).toMatch(/_A4_pile_/); + // Le papier changé hors de la section : l'annonce sur A4 se retire, et + // la suivante porte le nouveau papier. + const lettre = Object.keys(PAPIERS)[1]; + await m.seance.choisirPapier(lettre); + await attendre('une image', () => true); + expect(annonce(m)).toBeNull(); + preparer(); + await attendre('l’annonce sur le nouveau papier', () => annonce(m), IMAGES); + expect(texte(annonce(m))).toContain(`_${lettre}_pile_`); + }); +}); + +describe('sous web, la planche se télécharge (§ 11.6)', () => { + test('la section dit le nom téléchargé ; ni « Ouvrir le dossier » ni écriture du PDF', async () => { + const m = await ouvrirBadges(chargeBloquee(), { options: { systeme: { nature: 'web' } } }); + const telechargees = []; + m.fs.enregistrerSous = async (nom, octets) => { + telechargees.push({ nom, debut: new TextDecoder().decode(octets.slice(0, 5)) }); + return null; + }; + const depuis = m.trace.length; + await cliquerProduire(m, 'la planche téléchargée', () => dans(m, '[data-chemin-planche]')); + expect(telechargees).toHaveLength(1); + const [{ nom, debut }] = telechargees; + expect(nom).toMatch(/_A4_feuille_.*\.pdf$/); + expect(debut).toBe('%PDF-'); + expect(texte(dans(m, '[data-chemin-planche]'))).toBe(plat(t('badges.produite.telechargee', { nom }))); + expect(dans(m, '[data-section="badges"] [data-commande="ouvrirDossier"]')).toBeNull(); + expect(planchesEcrites(m, depuis)).toEqual([]); + }); +}); + +describe('une écriture refusée, et son remède (§ 8.5, § 11.6)', () => { + test('PLANCHE_NON_ECRITE s’affiche à côté de « Produire », remède « Enregistrer sous… », dont le chemin choisi s’affiche', async () => { + const m = await ouvrirBadges(chargeBloquee()); + m.fs.pannes.ecriture('documents'); + const proposes = []; + m.fs.enregistrerSous = async (nom, octets) => { + proposes.push({ nom, debut: new TextDecoder().decode(octets.slice(0, 5)) }); + return 'D:\\ailleurs\\planche.pdf'; + }; + await cliquerProduire(m, 'le refus d’écriture', () => dans(m, '[data-section="badges"] [data-refus="PLANCHE_NON_ECRITE"]')); + const remede = dans(m, '[data-refus="PLANCHE_NON_ECRITE"] [data-commande="enregistrerSous"]'); + expect(texte(remede)).toBe(plat(t('communs.remede.enregistrerSous'))); + remede.click(); + const chemin = await attendre('le chemin choisi', () => dans(m, '[data-chemin-planche]'), IMAGES); + expect(texte(chemin)).toBe('D:\\ailleurs\\planche.pdf'); + expect(proposes).toHaveLength(1); + expect(proposes[0].nom).toMatch(/_A4_feuille_.*\.pdf$/); + expect(proposes[0].debut).toBe('%PDF-'); + // Le refus levé ; « Ouvrir le dossier » ne montre que le dossier de + // travail, pas celui choisi ailleurs. + expect(dans(m, '[data-refus="PLANCHE_NON_ECRITE"]')).toBeNull(); + expect(dans(m, '[data-section="badges"] [data-commande="ouvrirDossier"]')).toBeNull(); + }); + + test('une production refusée après une réussie ne montre plus le chemin de la précédente', async () => { + const m = await ouvrirBadges(chargeBloquee()); + await cliquerProduire(m, 'la première planche', () => dans(m, '[data-chemin-planche]')); + m.fs.pannes.ecriture('documents'); + await cliquerProduire(m, 'le refus d’écriture', () => dans(m, '[data-section="badges"] [data-refus="PLANCHE_NON_ECRITE"]')); + expect(dans(m, '[data-chemin-planche]')).toBeNull(); + }); +}); + +describe('la source de la planche (Q3)', () => { + test('le retenu et la proposition demandée au plan : le retenu par défaut ; la proposition choisie s’annonce, BROUILLON', async () => { + const charge = chargeRetenue(); + const m = await ouvrirBadges(charge); + expect(dans(m, '[data-section="badges"] [data-champ="source"]')).toBeNull(); + m.ui.montrerProposition(charge.propositions[0].id); + const choix = await attendre('le choix de la source', () => dans(m, '[data-section="badges"] [data-champ="source"]'), IMAGES); + expect([...choix.options].map((option) => option.value)).toEqual(['retenu', `proposition:${charge.propositions[0].id}`]); + expect(choix.value).toBe('retenu'); + choix.value = `proposition:${charge.propositions[0].id}`; + choix.dispatchEvent(new Event('change', { bubbles: true })); + dans(m, '[data-section="badges"] [data-commande="preparerPlanche"]').click(); + await attendre('l’annonce', () => annonce(m), IMAGES); + expect(texte(annonce(m))).toContain(plat(t('badges.annonce.source.proposition', { id: charge.propositions[0].id }))); + expect(texte(annonce(m))).toContain(plat(t('badges.annonce.brouillon.proposition'))); + }); + + test('sans retenu ni proposition demandée : le refus du placement, remède vers les propositions', async () => { + const charge = chargePrincipale(); + const m = await ouvrirBadges(charge); + m.ui.montrerProposition(null); + await cliquerProduire(m, 'le refus', () => dans(m, '[data-annonce-planche] [data-refus="PLANCHE_SANS_PLACEMENT"]')); + dans(m, '[data-refus="PLANCHE_SANS_PLACEMENT"] [data-commande="ouvrirSection"]').click(); + await attendre('les propositions', () => dans(m, '[data-section="propositions"]'), IMAGES); + }); +}); + +describe('la langue témoin (§ 14.6)', () => { + test('chaque texte de la section, annonce, refus, question et réédition compris, est marqué, hors des données', async () => { + const temoin = creerContexte({ langue: 'temoin' }); + try { + const charge = chargeBloquee(); + const m = await ouvrirEvenement(temoin, charge, { section: 'badges' }); + produire(m).click(); + await attendre('la question et l’annonce', () => question(m) && annonce(m), IMAGES); + dans(m, '[data-papier="question"] [data-cible="A4"] [data-commande="choisirPapier"]').click(); + await attendre('la planche', () => dans(m, '[data-chemin-planche]'), IMAGES); + const racine = m.seance.etat().racine.chemin; + const noms = new Set([...personnesReeditables(charge).flatMap(({ nom, appartenance }) => [nom, appartenance]), charge.evenement.nom]); + const { ouverture, fermeture } = MARQUE_TEMOIN; + const fautes = []; + const marchant = document.createTreeWalker(section(m), NodeFilter.SHOW_TEXT); + let lus = 0; + for (let noeud = marchant.nextNode(); noeud !== null; noeud = marchant.nextNode()) { + const lu = plat(noeud.textContent); + if (lu === '') continue; + lus += 1; + const marque = lu.startsWith(ouverture) && lu.endsWith(fermeture); + if (!marque && !noms.has(lu) && !lu.startsWith(racine)) fautes.push(lu); + } + expect(lus).toBeGreaterThan(10); + expect(fautes).toEqual([]); + } finally { + const erreurs = temoin.erreurs(); + await temoin.defaire(); + expect(erreurs).toEqual([]); + } + }); +}); diff --git a/src/interface/badges/Reedition.svelte b/src/interface/badges/Reedition.svelte new file mode 100644 index 0000000..132f059 --- /dev/null +++ b/src/interface/badges/Reedition.svelte @@ -0,0 +1,129 @@ + + + + +
+

{t('badges.reedition.titre')}

+

{t('badges.reedition.explication')}

+ + {#if montrees.length === 0} +

{t('badges.reedition.aucune')}

+ {:else} + + {/if} + {#if selection !== null} + executer(selection)} {gestes} /> + {/if} +
+ + diff --git a/src/interface/badges/SectionBadges.svelte b/src/interface/badges/SectionBadges.svelte new file mode 100644 index 0000000..619f35f --- /dev/null +++ b/src/interface/badges/SectionBadges.svelte @@ -0,0 +1,345 @@ + + + + +
+

{t('coquille.section.badges')}

+

{t('badges.introduction')}

+ + {#if charge !== null} +
+ {#if offertes.length > 1} + + {/if} + + +
+ + {#if $seance.papier !== null || attente !== null} + + {/if} + +
+ preparer(null)} {gestes} /> + {#if bloque} + +

{t('badges.produire.bloque')}

+ {:else} + produire(null)} {gestes} /> + {/if} +
+ {#if refusRepris !== null} + (refusRepris = null)} {gestes} /> + {/if} + + {#if montree !== null} +
+

{t('badges.annonce.titre')}

+
    + {#each phrases as phrase, rang (rang)} +
  • {t(phrase.cle, phrase.details)}
  • + {/each} +
+ {#if montree.annonce.refus !== null} + + {/if} +
+ {/if} + + {#if produite !== null} +
+ {#if produite.chemin !== null} +

+ {t('badges.produite.chemin')} + {produite.chemin} +

+ {#if explorateur.disponible && !produite.ailleurs} + facade.ouvrirExplorateur()} /> + {/if} + {:else} +

{t('badges.produite.telechargee', { nom: produite.nom })}

+ {/if} +
+ {/if} + + + {/if} +
+ + diff --git a/src/interface/badges/modele.js b/src/interface/badges/modele.js new file mode 100644 index 0000000..d846a3a --- /dev/null +++ b/src/interface/badges/modele.js @@ -0,0 +1,210 @@ +// © 2026 TechnoLibre (http://www.technolibre.ca) +// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) + +// Le modèle de la section des badges (§ 11.2, § 11.5, § 11.6, § 11.8, Q3), +// pur : SectionBadges.svelte et Reedition.svelte le câblent. +// +// Une planche se tire du placement retenu, ou d'une proposition — celle que +// la section des propositions a demandée au plan —, toujours BROUILLON (Q3). +// La section offre ces sources, le retenu d'abord ; la source qui vaut est +// celle que l'opérateur a choisie tant qu'elle reste offerte, sinon la +// première. Sans source offerte, la demande désigne le retenu, et la séance +// la refuse PLANCHE_SANS_PLACEMENT, remède vers les propositions. +// +// L'annonce que rend seance.preparerPlanche se dit en phrases : chacune une +// clé de libelles/badges.js et ses détails, données comprises — le nom du +// fichier, les noms des homonymes, les caractères absents de la police —, +// que t compose en une seule chaîne. Le refus de l'annonce ne fait pas de +// phrase : la section le pose par Refus, avec son remède. Le modèle ne rend +// que des clés, des détails et des données. +import { cleNormalisee } from '../../application/csv.js'; +import { nomAffiche } from '../../application/personnes.js'; +import { IMPOSITIONS, ORDRES, comparerPointsDeCode } from '../../application/planche.js'; +import { PAPIERS } from '../../geometrie/papiers.js'; +import { clesPapier } from '../impression/modele.js'; + +/** Les impositions que la section offre, la première par défaut (§ 11.6). */ +export const IMPOSITIONS_OFFERTES = IMPOSITIONS; + +/** Les ordres de la pile que la section offre, le premier par défaut. */ +export const ORDRES_OFFERTS = ORDRES; + +// Le refus qui ne bloque pas « Produire » : le papier se choisit sur place, +// et la production reprend. +const PAPIER_REQUIS = 'PAPIER_REQUIS'; + +/** La source que désigne une demande sans source offerte : le retenu, que + * la séance refuse alors PLANCHE_SANS_PLACEMENT. */ +const SOURCE_PAR_DEFAUT = Object.freeze({ source: 'retenu', proposition: null }); + +/** + * Les sources d'une planche que la section offre (Q3) : le retenu quand la + * charge en porte un, puis la proposition demandée au plan quand la charge + * la porte. Une liste neuve, vide sans l'un ni l'autre. + * + * @param {Object} charge la charge de l'événement ouvert + * @param {number|null} demandee la proposition demandée au plan (EtatUi.proposition) + * @returns {Array<{source: 'retenu'|'proposition', proposition: number|null}>} + */ +export function sourcesOffertes(charge, demandee) { + const offertes = []; + if (charge.retenu !== null) offertes.push({ source: 'retenu', proposition: null }); + if (demandee !== null && charge.propositions.some(({ id }) => id === demandee)) { + offertes.push({ source: 'proposition', proposition: demandee }); + } + return offertes; +} + +/** La clé d'une source, valeur de son option : 'retenu', ou + * 'proposition:'. */ +export const cleSource = ({ source, proposition }) => (source === 'retenu' ? 'retenu' : `proposition:${proposition}`); + +/** + * La source qui vaut : l'offerte de clé choisie, sinon la première + * offerte, sinon le retenu. + * + * @param {Array<{source: string, proposition: number|null}>} offertes + * @param {string|null} choisie la clé que l'opérateur a choisie + */ +export function sourceChoisie(offertes, choisie) { + return offertes.find((offerte) => cleSource(offerte) === choisie) ?? offertes[0] ?? SOURCE_PAR_DEFAUT; +} + +/** + * Le libellé d'une source, pour son option : {cle, details}. + * + * @throws {RangeError} une source hors de 'retenu' et 'proposition' + */ +export function libelleSource({ source, proposition }) { + if (source === 'retenu') return { cle: 'badges.source.retenu', details: {} }; + if (source === 'proposition') return { cle: 'badges.source.proposition', details: { id: proposition } }; + throw new RangeError(`source inconnue : ${JSON.stringify(source)}`); +} + +/** La clé du libellé d'une imposition ; RangeError hors d'IMPOSITIONS. */ +export function cleImposition(imposition) { + if (!IMPOSITIONS.includes(imposition)) throw new RangeError(`imposition inconnue : ${JSON.stringify(imposition)}`); + return `badges.imposition.${imposition}`; +} + +/** La clé du libellé d'un ordre ; RangeError hors d'ORDRES. */ +export function cleOrdre(ordre) { + if (!ORDRES.includes(ordre)) throw new RangeError(`ordre inconnu : ${JSON.stringify(ordre)}`); + return `badges.ordre.${ordre}`; +} + +/** + * Deux demandes ont-elles les mêmes réglages — source, proposition, + * imposition, ordre — ? La sélection d'une réédition n'en est pas un : + * l'annonce d'une réédition reste montrée tant que les réglages tiennent. + */ +export function memesReglages(a, b) { + return a.source === b.source && a.proposition === b.proposition && a.imposition === b.imposition && a.ordre === b.ordre; +} + +/** + * Vrai quand l'annonce porte un refus qui empêche toute production : celui + * du placement ou de la mise en page. PAPIER_REQUIS ne bloque pas : la + * production pose la question du papier, puis reprend. Faux sans annonce. + * + * @param {import('../../application/planche_seance.js').Annonce|null} annonce + */ +export function produireBloque(annonce) { + return annonce !== null && annonce.refus !== null && annonce.refus.code !== PAPIER_REQUIS; +} + +// Le point de code d'un caractère, écrit U+XXXX, quatre chiffres au moins, +// comme la feuille de contrôle l'imprime. +const pointDeCode = (caractere) => `U+${caractere.codePointAt(0).toString(16).toUpperCase().padStart(4, '0')}`; + +/** + * Les phrases de l'annonce d'une planche (§ 11.2, § 11.5, § 11.8, + * décision 12), dans cet ordre : la source ; les comptes de la soirée, ou + * celui d'une réédition ; le nombre de planches sur chaque papier de + * PAPIERS, le papier choisi marqué ; chaque groupe d'homonymes ; les + * caractères absents de la police avec leur point de code ; la mention + * BROUILLON, de la source ; le nom du fichier. Sous un refus du placement, + * seule la source se dit : comptes, planches et nom manquent à l'annonce. + * L'annonce reçue n'est pas modifiée. + * + * @param {import('../../application/planche_seance.js').Annonce} annonce + * @param {{source?: 'retenu'|'proposition', proposition?: number|null, selection?: number[]|null}} [demande] + * @returns {Array<{cle: string, details: Object}>} + */ +export function phrasesAnnonce(annonce, { source = 'retenu', proposition = null, selection = null } = {}) { + const { details } = libelleSource({ source, proposition }); + const phrases = [{ cle: `badges.annonce.source.${source}`, details }]; + if (annonce.comptes !== null) { + phrases.push( + selection === null + ? { cle: 'badges.annonce.comptes', details: { ...annonce.comptes } } + : { cle: 'badges.annonce.reedition', details: { n: annonce.comptes.produits } }, + ); + } + if (annonce.planches !== null) { + const parPapier = Object.keys(PAPIERS).map((papier) => ({ + papier, + nom: clesPapier(papier).nom, + planches: annonce.planches[papier], + choisi: papier === annonce.papier, + })); + phrases.push({ cle: 'badges.annonce.planches', details: { parPapier } }); + } + for (const { nom, ids } of annonce.homonymes) phrases.push({ cle: 'badges.annonce.homonymes', details: { nom, ids: [...ids] } }); + if (annonce.absents.length > 0) { + const caracteres = annonce.absents.map((caractere) => ({ caractere, point: pointDeCode(caractere) })); + phrases.push({ cle: 'badges.annonce.absents', details: { caracteres } }); + } + if (annonce.comptes !== null && annonce.brouillon) { + phrases.push({ cle: `badges.annonce.brouillon.${source === 'proposition' ? 'proposition' : 'retenu'}`, details: {} }); + } + if (annonce.nom !== null) phrases.push({ cle: 'badges.annonce.fichier', details: { nom: annonce.nom } }); + return phrases; +} + +// La clé de tri d'un nom affiché : sa forme normalisée (§ 10.1). +const cleDeNom = (personne) => cleNormalisee(nomAffiche(personne)); + +/** + * Les personnes dont un badge peut se rééditer (§ 11.8) : les non exclues, + * par ordre de leur nom affiché normalisé, comparé par points de code, + * départagées par identifiant. {id, nom, appartenance}, nom affiché. + * + * @param {Object} charge la charge de l'événement ouvert + * @returns {Array<{id: number, nom: string, appartenance: string|null}>} + */ +export function personnesReeditables(charge) { + return charge.participants + .filter(({ exclu }) => !exclu) + .map((personne) => ({ personne, cle: cleDeNom(personne) })) + .sort((a, b) => comparerPointsDeCode(a.cle, b.cle) || a.personne.id - b.personne.id) + .map(({ personne }) => ({ id: personne.id, nom: nomAffiche(personne), appartenance: personne.appartenance })); +} + +/** + * Les personnes dont le nom affiché ou l'appartenance contient la saisie, + * l'un et l'autre normalisés ; toutes pour une saisie vide ou de blancs. + * + * @param {Array<{id: number, nom: string, appartenance: string|null}>} personnes + * @param {string} saisie + */ +export function filtrerPersonnes(personnes, saisie) { + const cherchee = cleNormalisee(saisie); + if (cherchee === '') return personnes; + return personnes.filter( + ({ nom, appartenance }) => cleNormalisee(nom).includes(cherchee) || cleNormalisee(appartenance ?? '').includes(cherchee), + ); +} + +/** + * La sélection d'une réédition : les identifiants cochés qui restent + * rééditables, dans l'ordre de la liste ; null quand il n'en reste aucun. + * + * @param {number[]} cochees + * @param {Array<{id: number}>} personnes celles de personnesReeditables + * @returns {number[]|null} + */ +export function selectionRetenue(cochees, personnes) { + const retenues = personnes.filter(({ id }) => cochees.includes(id)).map(({ id }) => id); + return retenues.length === 0 ? null : retenues; +} diff --git a/src/interface/badges/modele.test.js b/src/interface/badges/modele.test.js new file mode 100644 index 0000000..0485cf8 --- /dev/null +++ b/src/interface/badges/modele.test.js @@ -0,0 +1,300 @@ +// © 2026 TechnoLibre (http://www.technolibre.ca) +// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) + +// Le modèle de la section des badges (§ 11.2, § 11.5, § 11.6, § 11.8, Q3), +// sans DOM : les sources offertes et celle qui vaut, les réglages d'une +// demande, les phrases de l'annonce, ce qui bloque « Produire », les +// personnes d'une réédition. Chaque clé que le modèle désigne existe, en +// français comme en langue témoin, et se compose sans lever. Une annonce se +// prend telle que la séance la rend (planche_seance.js), sur de petites +// soirées construites ; aucune production de PDF. +import assert from 'node:assert/strict'; +import { describe, test } from '../../../test/lanceur.js'; +import { personne, soiree, table } from '../../../test/fixtures/badges/cas.js'; +import { lirePolices } from '../../../test/polices.js'; +import { TABLES_APPLICATION } from '../../application/libelles.js'; +import { creerPlanches } from '../../application/planche_seance.js'; +import { MARQUE_TEMOIN, creerTraduction } from '../../application/traduction.js'; +import { PAPIERS } from '../../geometrie/papiers.js'; +import { VERSION } from '../../version.genere.js'; +import { TABLES_INTERFACE } from '../libelles.js'; +import { + IMPOSITIONS_OFFERTES, + ORDRES_OFFERTS, + cleImposition, + cleOrdre, + cleSource, + filtrerPersonnes, + libelleSource, + memesReglages, + personnesReeditables, + phrasesAnnonce, + produireBloque, + selectionRetenue, + sourceChoisie, + sourcesOffertes, +} from './modele.js'; + +const TABLES = [...TABLES_APPLICATION, ...TABLES_INTERFACE]; +const { t } = creerTraduction(TABLES); +const { t: tTemoin } = creerTraduction(TABLES, { langue: 'temoin' }); + +// Chaque phrase se compose, en français et en langue témoin, entière dans sa +// marque ; rend les textes français. +function composer(phrases) { + assert.ok(phrases.length > 0, 'aucune phrase'); + return phrases.map(({ cle, details }) => { + const francais = t(cle, details); + assert.equal(typeof francais, 'string', cle); + assert.notEqual(francais.trim(), '', cle); + assert.equal(tTemoin(cle, details), `${MARQUE_TEMOIN.ouverture}${francais}${MARQUE_TEMOIN.fermeture}`, cle); + return francais; + }); +} + +const cles = (phrases) => phrases.map(({ cle }) => cle); + +// Deux tables de quatre, deux tours : quatre personnes, dont une sans +// prénom ; la personne 5 est exclue. +const PERSONNES = () => [ + personne(1, 'Iris', 'Ombrelle', { appartenance: 'Club des Merles' }), + personne(2, 'Théo', 'Pervenche'), + personne(3, 'Ondine', 'Lacasse'), + personne(4, null, 'Grisaille'), + personne(5, 'Iris', 'Pervenche', { exclu: true }), +]; +const TABLES_SOIREE = () => [table(1, 1, 4), table(2, 2, 4)]; +const PLAN = [{ sieges: [[1, 2], [3, 4]] }, { sieges: [[1, 3], [2, 4]] }]; + +// La soirée retenue, datée, sur un plan retenu, et une proposition 2. +const retenue = (champs = {}) => + soiree({ personnes: PERSONNES(), tables: TABLES_SOIREE(), plan: PLAN, propositions: [[2, PLAN]], ...champs }); + +// Les opérations de la planche d'une séance, sur la police embarquée lue +// du disque, la provenance d'épreuve et la version engendrée. +const planches = creerPlanches({ polices: async () => lirePolices(), provenance: 'test', version: VERSION.affichee }); +const fsInutile = Object.freeze({ nature: 'epreuve' }); + +// L'annonce que la séance rendrait sur cette charge, ce papier et cette +// demande : la lecture que la séance passe, sans système de fichiers lu. +const annoncer = (charge, papier, demande = {}) => + planches.preparer({ charge, base: 'lucioles', fs: fsInutile, racine: { id: 'documents', chemin: '/d' }, papier }, demande); + +describe('les sources offertes (Q3)', () => { + test('le retenu d’abord, puis la proposition demandée au plan quand elle existe ; rien sans l’un ni l’autre', () => { + const charge = retenue(); + assert.deepEqual(sourcesOffertes(charge, null), [{ source: 'retenu', proposition: null }]); + assert.deepEqual(sourcesOffertes(charge, 2), [ + { source: 'retenu', proposition: null }, + { source: 'proposition', proposition: 2 }, + ]); + // Une proposition demandée que la charge ne porte plus n'est pas offerte. + assert.deepEqual(sourcesOffertes(charge, 9), [{ source: 'retenu', proposition: null }]); + const sansRetenu = soiree({ personnes: PERSONNES(), tables: TABLES_SOIREE(), etat: 'propose', propositions: [[2, PLAN]] }); + assert.deepEqual(sourcesOffertes(sansRetenu, 2), [{ source: 'proposition', proposition: 2 }]); + assert.deepEqual(sourcesOffertes(sansRetenu, null), []); + }); + + test('la source qui vaut : celle de la clé choisie quand elle est offerte, sinon la première, sinon le retenu', () => { + const offertes = [ + { source: 'retenu', proposition: null }, + { source: 'proposition', proposition: 2 }, + ]; + assert.equal(cleSource(offertes[0]), 'retenu'); + assert.equal(cleSource(offertes[1]), 'proposition:2'); + assert.deepEqual(sourceChoisie(offertes, null), offertes[0]); + assert.deepEqual(sourceChoisie(offertes, 'proposition:2'), offertes[1]); + assert.deepEqual(sourceChoisie(offertes, 'proposition:7'), offertes[0]); + assert.deepEqual(sourceChoisie([offertes[1]], 'retenu'), offertes[1]); + assert.deepEqual(sourceChoisie([], 'proposition:2'), { source: 'retenu', proposition: null }); + }); + + test('chaque source, imposition et ordre a son libellé ; une valeur inconnue lève', () => { + assert.deepEqual([...IMPOSITIONS_OFFERTES], ['feuille', 'pile']); + assert.deepEqual([...ORDRES_OFFERTS], ['alphabetique', 'table']); + composer([ + libelleSource({ source: 'retenu', proposition: null }), + libelleSource({ source: 'proposition', proposition: 2 }), + ...IMPOSITIONS_OFFERTES.map((imposition) => ({ cle: cleImposition(imposition), details: {} })), + ...ORDRES_OFFERTS.map((ordre) => ({ cle: cleOrdre(ordre), details: {} })), + ]); + assert.match(t(libelleSource({ source: 'proposition', proposition: 2 }).cle, { id: 2 }), /2/); + assert.throws(() => cleImposition('rame'), RangeError); + assert.throws(() => cleOrdre('hasard'), RangeError); + assert.throws(() => libelleSource({ source: 'reservations', proposition: null }), RangeError); + }); + + test('deux demandes ont les mêmes réglages quand source, proposition, imposition et ordre concordent, sélection à part', () => { + const base = { source: 'retenu', proposition: null, imposition: 'feuille', ordre: 'alphabetique', selection: null }; + assert.equal(memesReglages(base, { ...base, selection: [1, 2] }), true); + for (const [cle, valeur] of [ + ['source', 'proposition'], + ['proposition', 2], + ['imposition', 'pile'], + ['ordre', 'table'], + ]) { + assert.equal(memesReglages(base, { ...base, [cle]: valeur }), false, cle); + } + }); +}); + +describe('les phrases de l’annonce (§ 11.2, § 11.5, § 11.8)', () => { + test('un retenu, papier choisi : la source, les comptes, les planches des deux papiers, le fichier ; ni brouillon ni refus', async () => { + const charge = retenue(); + const annonce = await annoncer(charge, 'A4'); + assert.equal(annonce.refus, null); + const phrases = phrasesAnnonce(annonce, { source: 'retenu', proposition: null, selection: null }); + assert.deepEqual(cles(phrases), [ + 'badges.annonce.source.retenu', + 'badges.annonce.comptes', + 'badges.annonce.planches', + 'badges.annonce.fichier', + ]); + const [source, comptes, planchesLues, fichier] = composer(phrases); + assert.match(source, /retenu/); + assert.equal(comptes, '4 badges pour 5 participants, 1 exclu.'); + assert.deepEqual(phrases[2].details.parPapier, Object.keys(PAPIERS).map((papier) => ({ + papier, + nom: `impression.papier.nom.${papier.toLowerCase()}`, + planches: annonce.planches[papier], + choisi: papier === 'A4', + }))); + assert.equal(planchesLues, 'Planches : 1 planche en A4 (papier choisi) et 2 planches en Lettre.'); + assert.ok(fichier.endsWith(annonce.nom), fichier); + assert.equal(produireBloque(annonce), false); + }); + + test('un brouillon : un plan proposé qui garde son retenu, puis une proposition, toujours BROUILLON, que l’annonce nomme', async () => { + const proposee = retenue({ etat: 'propose' }); + const surRetenu = phrasesAnnonce(await annoncer(proposee, 'A4'), { source: 'retenu', proposition: null, selection: null }); + assert.ok(cles(surRetenu).includes('badges.annonce.brouillon.retenu')); + composer(surRetenu); + + const demande = { source: 'proposition', proposition: 2, selection: null }; + const annonce = await annoncer(retenue(), 'A4', demande); + assert.equal(annonce.brouillon, true); + const phrases = phrasesAnnonce(annonce, demande); + assert.deepEqual(cles(phrases), [ + 'badges.annonce.source.proposition', + 'badges.annonce.comptes', + 'badges.annonce.planches', + 'badges.annonce.brouillon.proposition', + 'badges.annonce.fichier', + ]); + const textes = composer(phrases); + assert.match(textes[0], /n° 2/); + assert.match(textes[3], /BROUILLON/); + }); + + test('une dérive : le refus nomme ce qui a changé ; ni comptes, ni planches, ni fichier ; « Produire » bloqué', async () => { + const charge = retenue(); + charge.participants.push(personne(6, 'Ondine', 'Pervenche')); + charge.prochainsIds.participant = 7; + const annonce = await annoncer(charge, 'A4'); + assert.equal(annonce.refus.code, 'PLANCHE_DERIVE'); + assert.ok(annonce.refus.details.raisons.length > 0); + assert.deepEqual(annonce.refus.details.remede, { geste: 'ouvrirSection', section: 'propositions' }); + const phrases = phrasesAnnonce(annonce, { source: 'retenu', proposition: null, selection: null }); + assert.deepEqual(cles(phrases), ['badges.annonce.source.retenu']); + composer(phrases); + assert.match(t(annonce.refus.code, annonce.refus.details), /Ondine Pervenche/); + assert.equal(produireBloque(annonce), true); + }); + + test('sans placement, ou sous tout refus du placement ou de la mise en page, « Produire » est bloqué ; sans papier, non', () => { + const vide = { papier: null, comptes: null, planches: null, homonymes: [], absents: [], brouillon: true, nom: null }; + assert.equal(produireBloque(null), false); + assert.equal(produireBloque({ ...vide, refus: null }), false); + assert.equal(produireBloque({ ...vide, refus: { code: 'PAPIER_REQUIS', details: {} } }), false); + for (const code of ['PLANCHE_SANS_PLACEMENT', 'RETENU_FAUTIF', 'PLANCHE_DERIVE', 'PLANCHE_TROP_DE_TOURS', 'PLANCHE_NOM_TROP_LONG']) { + assert.equal(produireBloque({ ...vide, refus: { code, details: {} } }), true, code); + } + }); + + test('un papier absent : PAPIER_REQUIS, remède « Choisir le papier », les planches des deux papiers sans papier choisi, aucun fichier', async () => { + const annonce = await annoncer(retenue(), null); + assert.equal(annonce.refus.code, 'PAPIER_REQUIS'); + assert.deepEqual(annonce.refus.details.remede, { geste: 'choisirPapier' }); + const phrases = phrasesAnnonce(annonce, { source: 'retenu', proposition: null, selection: null }); + assert.deepEqual(cles(phrases), ['badges.annonce.source.retenu', 'badges.annonce.comptes', 'badges.annonce.planches']); + assert.ok(phrases[2].details.parPapier.every(({ choisi }) => choisi === false)); + assert.equal(composer(phrases)[2], 'Planches : 1 planche en A4 et 2 planches en Lettre.'); + }); + + test('des homonymes : chaque groupe nommé, avec les identifiants que le badge imprime', async () => { + const charge = retenue(); + charge.participants[2] = personne(3, 'Iris', 'Ombrelle', { appartenance: 'Club des Merles' }); + const annonce = await annoncer(charge, 'A4'); + assert.deepEqual(annonce.homonymes, [{ nom: 'Iris Ombrelle', ids: [1, 3] }]); + const phrases = phrasesAnnonce(annonce, { source: 'retenu', proposition: null, selection: null }); + const rang = cles(phrases).indexOf('badges.annonce.homonymes'); + assert.ok(rang > 0); + assert.deepEqual(phrases[rang].details, { nom: 'Iris Ombrelle', ids: [1, 3] }); + assert.equal(composer(phrases)[rang], 'Iris Ombrelle : 2 badges que seul leur identifiant imprimé sépare, n° 1 et n° 3.'); + }); + + test('des glyphes absents : chaque caractère nommé avec son point de code, dans l’ordre de l’annonce', async () => { + const charge = retenue(); + charge.participants[1] = personne(2, 'Théo', 'Pervenche 李'); + charge.participants[3] = personne(4, null, 'Grisaille \u{1F600}'); + const annonce = await annoncer(charge, 'A4'); + // Grisaille vient avant Théo Pervenche dans la pile : son caractère est + // rencontré le premier. + assert.deepEqual(annonce.absents, ['\u{1F600}', '李']); + const phrases = phrasesAnnonce(annonce, { source: 'retenu', proposition: null, selection: null }); + const rang = cles(phrases).indexOf('badges.annonce.absents'); + assert.ok(rang > 0); + assert.deepEqual(phrases[rang].details.caracteres, [ + { caractere: '\u{1F600}', point: 'U+1F600' }, + { caractere: '李', point: 'U+674E' }, + ]); + assert.match(composer(phrases)[rang], /U\+1F600.*U\+674E/); + }); + + test('une réédition : son compte à la place de ceux de la soirée', async () => { + const demande = { source: 'retenu', proposition: null, selection: [4, 2, 3] }; + const annonce = await annoncer(retenue(), 'A4', demande); + const phrases = phrasesAnnonce(annonce, demande); + assert.deepEqual(cles(phrases).slice(0, 2), ['badges.annonce.source.retenu', 'badges.annonce.reedition']); + assert.deepEqual(phrases[1].details, { n: 3 }); + assert.match(composer(phrases)[1], /3 badges/); + assert.match(annonce.nom, /\.badges-3_/); + }); + + test('sans demande, l’annonce se lit sur le retenu, sans sélection ; l’annonce reçue ne change pas', async () => { + const annonce = await annoncer(retenue(), 'A4'); + const copie = structuredClone(annonce); + assert.deepEqual(phrasesAnnonce(annonce), phrasesAnnonce(annonce, { source: 'retenu', proposition: null, selection: null })); + assert.deepEqual(annonce, copie); + }); +}); + +describe('la réédition (§ 11.8)', () => { + test('les personnes non exclues, par ordre alphabétique de leur nom affiché, accents et casse ignorés', () => { + const charge = retenue(); + charge.participants.push(personne(6, 'éloi', 'Abeille')); + assert.deepEqual(personnesReeditables(charge), [ + { id: 6, nom: 'éloi Abeille', appartenance: null }, + { id: 4, nom: 'Grisaille', appartenance: null }, + { id: 1, nom: 'Iris Ombrelle', appartenance: 'Club des Merles' }, + { id: 3, nom: 'Ondine Lacasse', appartenance: null }, + { id: 2, nom: 'Théo Pervenche', appartenance: null }, + ]); + }); + + test('le filtre retient les noms ou appartenances qui contiennent la saisie normalisée ; une saisie vide retient tout', () => { + const personnes = personnesReeditables(retenue()); + assert.deepEqual(filtrerPersonnes(personnes, ''), personnes); + assert.deepEqual(filtrerPersonnes(personnes, ' '), personnes); + assert.deepEqual(filtrerPersonnes(personnes, 'THEO').map(({ id }) => id), [2]); + assert.deepEqual(filtrerPersonnes(personnes, 'merles').map(({ id }) => id), [1]); + assert.deepEqual(filtrerPersonnes(personnes, 'zz'), []); + }); + + test('la sélection retenue : les cochées encore rééditables, dans l’ordre de la liste, null quand aucune', () => { + const personnes = personnesReeditables(retenue()); + assert.deepEqual(selectionRetenue([2, 5, 1], personnes), [1, 2]); + assert.equal(selectionRetenue([5], personnes), null); + assert.equal(selectionRetenue([], personnes), null); + }); +}); diff --git a/src/interface/evenement/Evenement.navigateur.test.js b/src/interface/evenement/Evenement.navigateur.test.js index cd15c57..6552896 100644 --- a/src/interface/evenement/Evenement.navigateur.test.js +++ b/src/interface/evenement/Evenement.navigateur.test.js @@ -178,7 +178,7 @@ describe('aucun assistant (§ 2.1)', () => { const { charge } = m.seance.etat(); expect([charge.participants.length, charge.tables.length]).toEqual([0, 0]); const ordre = creerPcg32(20261006, FLUX.DEMO).melanger([...SECTIONS]); - expect(ordre.length).toBe(7); + expect(ordre.length).toBe(8); for (const nom of [...ordre, ...[...ordre].reverse()]) { const bouton = dans(m, `[data-commande="section"][data-cible="${nom}"]`); expect(visible(bouton), nom).toBe(true); @@ -200,7 +200,7 @@ describe('aucun assistant (§ 2.1)', () => { }); describe('la place fixe (§ 8.4, § 8.5)', () => { - test('« Modifier » aux mêmes coordonnées sur les sept sections ; plein écran, il reste visible et atteint ; « Revenir en lecture » puis « Débloquer » au même endroit', async () => { + test('« Modifier » aux mêmes coordonnées sur les huit sections ; plein écran, il reste visible et atteint ; « Revenir en lecture » puis « Débloquer » au même endroit', async () => { const m = await neuf(); const coins = []; for (const nom of SECTIONS) { @@ -209,7 +209,7 @@ describe('la place fixe (§ 8.4, § 8.5)', () => { expect(visible(fixe(m, 'modifier')), nom).toBe(true); coins.push(coin(fixe(m, 'modifier'))); } - expect(coins.length).toBe(7); + expect(coins.length).toBe(8); for (const lu of coins) expect(lu).toEqual(coins[0]); // Un refus posé à côté d'un état, au-dessus de la surface, ne déplace // pas la place fixe, et ne la couvre pas. diff --git a/src/interface/evenement/Evenement.svelte b/src/interface/evenement/Evenement.svelte index 649e031..dc64e03 100644 --- a/src/interface/evenement/Evenement.svelte +++ b/src/interface/evenement/Evenement.svelte @@ -25,6 +25,7 @@ // nombre des avertissements, et le support rompu, en tête de la zone, // garde ses issues en vue (CadreMode.svelte). import { getContext } from 'svelte'; + import SectionBadges from '../badges/SectionBadges.svelte'; import Diagnostic from '../diagnostic/Diagnostic.svelte'; import SectionGeneration from '../generation/SectionGeneration.svelte'; import SectionImport from '../import/SectionImport.svelte'; @@ -52,6 +53,7 @@ ['diagnostic', Diagnostic], ['generation', SectionGeneration], ['propositions', SectionPropositions], + ['badges', SectionBadges], ]); const Section = $derived(COMPOSANTS.get($ui.section)); @@ -115,8 +117,12 @@ gap: var(--espace-2); } + /* Le retrait latéral des boutons de section vaut --espace-2 : les huit + sections tiennent sur une ligne à côté de la place des annonces dans + une fenêtre de 1 366 px, et un avertissement ne retire donc aucune + hauteur au plan (CadreMode.svelte). */ button { - padding: var(--espace-1) var(--espace-3); + padding: var(--espace-1) var(--espace-2); border: 1px solid var(--couleur-page-filet); border-radius: var(--rayon-1); background-color: var(--couleur-page-fond); diff --git a/src/interface/evenement/sections.js b/src/interface/evenement/sections.js index d71de1e..747bfcd 100644 --- a/src/interface/evenement/sections.js +++ b/src/interface/evenement/sections.js @@ -15,11 +15,13 @@ const CLES = new Map([ ['diagnostic', 'coquille.section.diagnostic'], ['generation', 'coquille.section.generation'], ['propositions', 'coquille.section.propositions'], + ['badges', 'coquille.section.badges'], ]); -/** Les sections de l'itération, dans l'ordre du § 2.1 : import, - * participants, tables, plan, diagnostic, generation, propositions. Aucune - * n'en exige une autre. Le titre et le nom de navigation de chacune sont la +/** Les sections de l'événement, dans l'ordre du § 2.1 : import, + * participants, tables, plan, diagnostic, generation, propositions, badges + * — la planche, dernière étape (§ 2.1 étape 12). Aucune n'en exige une + * autre. Le titre et le nom de navigation de chacune sont la * clé coquille.section. de coquille.js. */ export const SECTIONS = Object.freeze([...CLES.keys()]); diff --git a/src/interface/evenement/sections.test.js b/src/interface/evenement/sections.test.js index 0543ffe..dd6a831 100644 --- a/src/interface/evenement/sections.test.js +++ b/src/interface/evenement/sections.test.js @@ -1,8 +1,9 @@ // © 2026 TechnoLibre (http://www.technolibre.ca) // License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) -// Les sections de l'événement ouvert (§ 2.1) : sept noms distincts, dans -// l'ordre du parcours de l'opérateur, chacun nommé par sa clé +// Les sections de l'événement ouvert (§ 2.1) : huit noms distincts, dans +// l'ordre du parcours de l'opérateur — les badges, dernière étape, après les +// propositions (§ 2.1 étape 12) —, chacun nommé par sa clé // coquille.section. de la table de la coquille ; la section d'ouverture // en est une. import assert from 'node:assert/strict'; @@ -11,9 +12,9 @@ import { TABLE as COQUILLE } from '../libelles/coquille.js'; import { SECTION_OUVERTURE, SECTIONS, cleDeSection } from './sections.js'; describe('sections de l’événement (§ 2.1)', () => { - test('sept noms distincts, dans l’ordre du parcours, figés', () => { - assert.deepEqual(SECTIONS, ['import', 'participants', 'tables', 'plan', 'diagnostic', 'generation', 'propositions']); - assert.equal(new Set(SECTIONS).size, 7); + test('huit noms distincts, dans l’ordre du parcours, les badges après les propositions, figés', () => { + assert.deepEqual(SECTIONS, ['import', 'participants', 'tables', 'plan', 'diagnostic', 'generation', 'propositions', 'badges']); + assert.equal(new Set(SECTIONS).size, 8); assert.ok(Object.isFrozen(SECTIONS)); }); diff --git a/src/interface/libelles.js b/src/interface/libelles.js index ef05cd1..bcb629c 100644 --- a/src/interface/libelles.js +++ b/src/interface/libelles.js @@ -11,6 +11,7 @@ // démarrage et le livrable les appellent sans connaître la traduction. import { creerTraduction } from '../application/traduction.js'; import { TABLE as ACCUEIL } from './libelles/accueil.js'; +import { TABLE as BADGES } from './libelles/badges.js'; import { TABLE as COMMUNS } from './libelles/communs.js'; import { TABLE as COQUILLE } from './libelles/coquille.js'; import { TABLE as DIAGNOSTIC } from './libelles/diagnostic.js'; @@ -28,6 +29,7 @@ import { TABLE as TABLES } from './libelles/tables.js'; /** Les tables de libelles/, dans l'ordre alphabétique de leurs fichiers. */ export const TABLES_INTERFACE = Object.freeze([ ACCUEIL, + BADGES, COMMUNS, COQUILLE, DIAGNOSTIC, diff --git a/src/interface/libelles.test.js b/src/interface/libelles.test.js index c0ac220..7dded68 100644 --- a/src/interface/libelles.test.js +++ b/src/interface/libelles.test.js @@ -65,11 +65,11 @@ async function tablesDuDossier() { } describe('libellés : les tables des écrans (§ 14.6)', () => { - test('chaque module de libelles/ exporte TABLE, une Map ; TABLES_INTERFACE les assemble, quatorze, par ordre alphabétique', async () => { + test('chaque module de libelles/ exporte TABLE, une Map ; TABLES_INTERFACE les assemble, quinze, par ordre alphabétique', async () => { const tables = await tablesDuDossier(); - assert.equal(tables.length, 14); + assert.equal(tables.length, 15); assert.deepEqual(tables.map(({ table }) => table), [ - 'accueil', 'communs', 'coquille', 'diagnostic', 'evenement', 'feuilles', 'generation', + 'accueil', 'badges', 'communs', 'coquille', 'diagnostic', 'evenement', 'feuilles', 'generation', 'import', 'impression', 'participants', 'plan', 'propositions', 'raccourcis', 'tables', ]); for (const { table, module } of tables) assert.ok(module.TABLE instanceof Map, table); diff --git a/src/interface/libelles/badges.js b/src/interface/libelles/badges.js new file mode 100644 index 0000000..6d39ee5 --- /dev/null +++ b/src/interface/libelles/badges.js @@ -0,0 +1,100 @@ +// © 2026 TechnoLibre (http://www.technolibre.ca) +// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) + +// Les libellés de la section des badges (§ 11.2, § 11.5, § 11.6, § 11.8, +// Q3) : ses réglages — source, imposition, ordre —, ses commandes, les +// phrases de l'annonce que rend phrasesAnnonce (badges/modele.js), la +// planche produite et la réédition. Chaque clé commence par « badges. ». +// Les refus de la planche sont des textes de l'application +// (application/libelles/planche.js), le nom d'un papier un libellé de +// l'aperçu (impression.papier.nom.*), que l'annonce lit par texte. Le +// chemin de la planche produite est une donnée : l'écran le pose dans son +// propre nœud, à côté de son intitulé. +import { compte, enumeration } from '../../application/libelles/aides.js'; + +export const TABLE = new Map([ + ['badges.introduction', "Un badge A6 par personne présente, imposé sur le papier de l'imprimante, précédé d'une feuille de contrôle."], + + // --- Les réglages de la planche (§ 11.6, Q3) ------------------------------ + ['badges.source.titre', 'Placement imprimé'], + ['badges.source.retenu', 'Le placement retenu'], + ['badges.source.proposition', ({ id }) => `La proposition n° ${id}`], + ['badges.imposition.titre', 'Imposition'], + ['badges.imposition.feuille', 'Feuille par feuille (ciseaux, massicot à main)'], + ['badges.imposition.pile', 'En pile (massicot qui tranche toute la rame)'], + ['badges.ordre.titre', 'Ordre des badges'], + ['badges.ordre.alphabetique', 'Alphabétique'], + ['badges.ordre.table', 'Par table du premier tour'], + + // --- Les commandes ---------------------------------------------------------- + ['badges.commande.preparer', 'Préparer'], + ['badges.commande.produire', 'Produire la planche'], + ['badges.commande.ouvrirDossier', 'Ouvrir le dossier'], + ['badges.produire.bloque', 'La planche ne se produit pas tant que le refus de l\u{2019}annonce tient.'], + + // --- L'annonce, avant de produire (§ 11.2, § 11.5, § 11.8) ------------------ + ['badges.annonce.titre', 'Avant de produire'], + ['badges.annonce.source.retenu', 'Source : le placement retenu.'], + [ + 'badges.annonce.source.proposition', + ({ id }) => `Source : la proposition n° ${id}, qui n\u{2019}est pas le placement retenu.`, + ], + [ + 'badges.annonce.comptes', + ({ produits, participants, exclus }) => + `${compte(produits, 'badge', 'badges')} pour ${compte(participants, 'participant', 'participants')}` + + `${exclus === 0 ? '' : `, ${compte(exclus, 'exclu', 'exclus')}`}.`, + ], + [ + 'badges.annonce.reedition', + ({ n }) => `Réédition : ${compte(n, 'badge', 'badges')}, que la feuille de contrôle annonce comme telle.`, + ], + // parPapier : par papier, la clé de son nom, ses planches, et s'il est + // celui de la machine. + [ + 'badges.annonce.planches', + ({ parPapier }, texte) => + `Planches : ${enumeration( + parPapier.map( + ({ nom, planches, choisi }) => `${compte(planches, 'planche', 'planches')} en ${texte(nom)}${choisi ? ' (papier choisi)' : ''}`, + ), + )}.`, + ], + [ + 'badges.annonce.homonymes', + ({ nom, ids }) => + `${nom} : ${compte(ids.length, 'badge', 'badges')} que seul leur identifiant imprimé sépare, ` + + `${enumeration(ids.map((id) => `n° ${id}`))}.`, + ], + [ + 'badges.annonce.absents', + ({ caracteres }) => + `Caractères absents de la police, imprimés sans glyphe et listés sur la feuille de contrôle : ${enumeration( + caracteres.map(({ caractere, point }) => `« ${caractere} » (${point})`), + )}.`, + ], + [ + 'badges.annonce.brouillon.retenu', + 'Chaque badge portera la mention BROUILLON : le plan n\u{2019}est ni retenu ni bloqué, ou son placement ne couvre pas tous les tours.', + ], + [ + 'badges.annonce.brouillon.proposition', + 'Chaque badge portera la mention BROUILLON : une proposition n\u{2019}est pas le placement retenu.', + ], + ['badges.annonce.fichier', ({ nom }) => `Fichier : ${nom}`], + + // --- La planche produite (§ 11.6, décision 13) ----------------------------- + ['badges.produite.chemin', 'Planche déposée :'], + ['badges.produite.telechargee', ({ nom }) => `Planche téléchargée sous le nom ${nom}.`], + + // --- La réédition (§ 11.8) -------------------------------------------------- + ['badges.reedition.titre', 'Rééditer des badges'], + [ + 'badges.reedition.explication', + "Cochez les personnes dont le badge est à refaire : la planche ne porte qu'elles, et sa feuille de contrôle l'annonce.", + ], + ['badges.reedition.filtre', 'Chercher une personne'], + ['badges.reedition.personnes', 'Personnes présentes'], + ['badges.reedition.aucune', 'Aucune personne ne répond à cette recherche.'], + ['badges.reedition.produire', ({ n }) => `Rééditer ${compte(n, 'badge', 'badges')}`], +]); diff --git a/src/interface/libelles/coquille.js b/src/interface/libelles/coquille.js index 61fb46b..3a00c8b 100644 --- a/src/interface/libelles/coquille.js +++ b/src/interface/libelles/coquille.js @@ -71,4 +71,5 @@ export const TABLE = new Map([ ['coquille.section.diagnostic', 'Diagnostic'], ['coquille.section.generation', 'Génération'], ['coquille.section.propositions', 'Propositions'], + ['coquille.section.badges', 'Badges'], ]); diff --git a/test/navigateur/designations.js b/test/navigateur/designations.js index 0c67b54..084fcde 100644 --- a/test/navigateur/designations.js +++ b/test/navigateur/designations.js @@ -19,6 +19,7 @@ // [attribut, porteur, valeurs], dans l'ordre des attributs. const ENTREES = [ ['data-affichee', 'import : la valeur affichée d’une cellule de l’aperçu', ['']], + ['data-annonce-planche', 'badges : l’annonce de la planche, avant de produire', ['']], ['data-annonces', 'événement : la zone des annonces à côté de la tête', ['']], ['data-apercu', 'import : l’aperçu d’un fichier ou d’un collage', ['']], ['data-attente-demonstration', 'accueil : le message d’une démonstration cliquée pendant un chargement', ['']], @@ -34,6 +35,7 @@ const ENTREES = [ ['data-champ', 'un champ de saisie ou un sélecteur, par son nom', null], ['data-chargement', 'accueil : le signe d’un calcul en cours', ['']], ['data-chargement-liste', 'accueil : l’annonce du calcul des colonnes de la liste', ['']], + ['data-chemin-planche', 'badges : le chemin de la planche produite, ou son nom téléchargé', ['']], ['data-choix-siege', 'plan : un siège offert par le panneau d’une table, par son rang', null], ['data-cible', 'la cible d’une commande : section, groupe, colonne, vue imprimée ou papier', null], ['data-cible-redondance', 'propositions : le champ de la cible de redondance', ['']], @@ -143,7 +145,7 @@ const ENTREES = [ ['data-reserve', 'plan : la réserve d’un tour', null], ['data-retenu', 'propositions : la ligne du retenu', null], ['data-secours', 'récupération : une source de secours', null], - ['data-section', 'une section de l’événement', ['diagnostic', 'generation', 'import', 'participants', 'plan', 'propositions', 'tables']], + ['data-section', 'une section de l’événement', ['badges', 'diagnostic', 'generation', 'import', 'participants', 'plan', 'propositions', 'tables']], ['data-separateur', 'import : le séparateur nommé', ['']], ['data-siege', 'plan : un siège, par sa table et son numéro', null], ['data-sieges-retires', 'tables : les sièges retirés', ['']], diff --git a/test/navigateur/ecrans.js b/test/navigateur/ecrans.js index cc04fea..09a5968 100644 --- a/test/navigateur/ecrans.js +++ b/test/navigateur/ecrans.js @@ -23,6 +23,7 @@ import { flushSync } from 'svelte'; import { appliquerCommande } from '../../src/application/commandes.js'; import { ErreurAnnulee } from '../../src/application/generation.js'; import { texteLivre } from '../../src/demo/livrees.js'; +import { SECTIONS } from '../../src/interface/evenement/sections.js'; import { rechercher } from '../../src/moteur/recherche.js'; import { serialiser } from '../../src/stockage/canonique.js'; import { analyser, capacite, configurationDepuisCharge } from '../../src/stockage/document.js'; @@ -39,8 +40,10 @@ export const BASE = 'soiree'; /** Le nom du CSV des cas limites que sert le dialogue d'import. */ export const NOM_CAS_LIMITES = 'participants_cas_limites.csv'; -/** Les sections d'un événement, dans l'ordre de la navigation. */ -export const SECTIONS_EVENEMENT = Object.freeze(['import', 'participants', 'tables', 'plan', 'diagnostic', 'generation', 'propositions']); +/** Les sections d'un événement, dans l'ordre de la navigation : celles + * que l'application offre, si bien qu'une section ajoutée se visite à + * chaque mode sans retouche ici. */ +export const SECTIONS_EVENEMENT = SECTIONS; // L'exécutable publié du système simulé : son dossier data/ refuse // l'écriture, et la question du dossier de travail se pose au démarrage.