Portail d'enseignement

E Suong
E Suong

Explorer les ressources

Accueil

Documentation technique

Défi caisses

Fiche de référence du code : fonctionnement, formats et limites. La disponibilité publique dépend de la version publiée.

Sommaire de la fiche

Fiche comparée aux sources, à l’interface et au catalogue le 26 octobre 2026. Voir l’audit commun des neuf activités (../JEUX.md#validation-documentaire). Les comptes de tests et recettes navigateur datés plus bas sont des vérifications historiques, pas un état de validation global actuel.

Défi et accès

Rubrique publique jeux-empilement-caisses, /rubriques/jeux-empilement-caisses, dans Défis algorithmiques. Bloc À venir retiré. Énoncé fourni par le propriétaire : programmer un escalier de N marches avec une pince. N=4 par défaut, réglable de 1 à 8 ; objectif exact : piles 1,2,…,N depuis la première colonne, deux colonnes supplémentaires vides et pince vide. Fantôme de l’objectif masqué par défaut, affichable par la case à cocher. Numéros de colonnes non dessinés. Pince initialement vide au-dessus du convoyeur d’entrée à gauche, hauteur maximale N+2. Chaque exécution repart de cet état, et ne reprend pas les essais manuels.

Interface

src/components/CratePlayground.svelte : éditeur LN avec coloration et mise en majuscules des mots-clés au lancement (helpers LN), ligne de commande active surlignée, console AFFICHER et saisie ENTRER intégrée. Commandes immédiates au clic pour expérimenter à la main. Exécuter, Pause/Reprendre, Pas à pas, Arrêter, Réinitialiser le plateau ; vitesse ×0,25 à ×3. Pas à pas = un appel de commande ou de capteur, pas chaque instruction LN. N fourni comme valeur initiale du contexte ; une affectation de N dans le programme ne change pas l’objectif de l’interface.

SVG 2D : deux convoyeurs avec rouleaux animés, arrivée et évacuation horizontales des caisses, rail et pince, caisses avec texture de planches, descente/dépôt ou prise/remontée, déplacements horizontaux continus. Une commande est validée dans le modèle affiché seulement au dernier frame. Pause fige l’animation. Pas à pas termine une commande puis attend. Arrêter invalide la session, termine le Worker, annule RAF et promesses de pause/saisie, puis réaffiche le dernier état entièrement validé ; une commande inachevée est annulée, y compris l’aller-retour entier de jeter. Réinitialiser conserve le code. Saisie et commandes manuelles ne permettent pas de modifier une scène pendant une exécution.

Code sauvegardé sous localStorage empilement-caisses-ln-v1, indépendant de ln-code-v1. Ni programme ni scène envoyés au serveur. Pas de solution complète chargée par défaut ; un exemple de commandes et de syntaxe est visible à la demande. La scène, N et la vitesse ne sont pas persistants.

Moteur réutilisable

src/lib/challenges/crane.mjs est indépendant du DOM : initialCrane({columns,maxHeight,column,stacks,held,supply}), challengeCrane(N), craneAction(state,name), staircaseComplete, createCraneExtension(config,emit), craneGeometry, restCraneFrame, craneFrame(command,t), craneDuration(command), crateBelow(state). Dimensions génériques de 1 à 16 colonnes/niveaux ; piles personnalisées et caisse portée possibles pour d’autres défis. Identifiants de caisses entiers positifs uniques. État : columns, maxHeight, column, stacks (tableaux du bas vers le haut), held (id ou null), supply (id de la caisse en attente sur le convoyeur), nextId, removed (nombre de caisses évacuées), commands. Transitions immuables. Les colonnes de construction sont indexées 0 à columns−1 ; entrée à −1, sortie à columns. Ces deux postes supplémentaires ne font pas partie des piles ni de l’objectif.

droite()/gauche() : déplacement d’un poste avec la charge, entre le convoyeur gauche et le convoyeur droit inclus. lever() : prend la caisse supérieure d’une pile ou la caisse attendant à l’entrée, uniquement si la pince est vide. Après prise à l’entrée, une nouvelle caisse arrive par le convoyeur (nouvel identifiant unique). poser() : dépose la caisse portée sur une pile ou l’évacue si la pince est au-dessus du convoyeur de sortie. Une pince vide provoque une erreur ; aucune création spontanée dans ses crochets. Impossible de déposer sur l’entrée ou de reprendre une caisse évacuée. Erreurs explicites aux bords, en pile pleine, prise à vide/pince pleine et arguments non vides.

La construction doit donc faire des allers-retours vers l’entrée. La pince commence au poste −1 : lever(), droite(), poser() dépose la première caisse sur la première colonne. Les anciens programmes qui utilisaient poser() à vide doivent être adaptés ; le code enregistré de l’utilisateur est conservé sans transformation.

Adaptateur LN : six fonctions sans argument en minuscules + valeur N, disponibles sans import. Moteur syntaxique/runtime existant, sans eval ni traduction du code utilisateur. startProgram(source,hooks,{kind:‘crates’,steps}) utilise le Worker LN ; contexte hôte autorisé explicitement. createExtension et allowedImports sont des options hôtes, pas des objets LN. Stylo reste inchangé dans la page ordinaire ; imports interdits dans ce défi pour éviter les homonymes droite/gauche. Commande graphique {kind:‘crates’,name,line,before,after,value}, acquittée après animation, sans file non bornée.

Limites : dix secondes de calcul LN hors attente de rendu/saisie, 1 000 appels par exécution, caisse_dessous compris, autres budgets LN inchangés. Le temps d’animation peut dépasser dix secondes. La durée d’une commande est de 700 ms horizontalement ou 1 200 ms verticalement sur les piles, 1 800 ms pour une prise ou un dépôt sur convoyeur à vitesse ×1. craneFrame est une interpolation pure testable ; le renderer emploie requestAnimationFrame. L’arrêt remet une animation partielle au dernier état validé pour éviter les caisses dupliquées ou flottantes. Identifiant de session refuse toute mise à jour périmée après arrêt/reprise.

Réutilisation et validation

Pour un futur défi : conserver le modèle indépendant, fournir initialCrane avec une configuration validée, ajouter un objectif et un contexte hôte explicitement autorisé, puis réutiliser le rendu/acquittement. Ne pas exposer de chargement arbitraire de modules ni d’objets JavaScript au LN. Garder des tests de conservation des identifiants et de limites.

tests/crane.test.mjs : approvisionnement/transport/conservation/évacuation, erreurs et configuration, objectif exact, frames de déplacement/descente/prise, véritable LN (boucles imbriquées et fonctions), N=1 à 8, imports isolés, arité/ligne d’erreur, attente du rendu exclue du budget, arrêt et limite de commandes. Les suites LN/stylo/coloration sont à relancer après toute évolution du contrat hôte. Contrôles navigateur requis : animation visible, pause/pas à pas, arrêt pendant commande, relance, erreurs, saisie ENTRER et sauvegarde. Tactile non vérifié sur appareil.

Validation de la version convoyeurs : tests de la prise et du renouvellement, de l’évacuation unique, de la conservation des ids, des limites et erreurs, de l’objectif hors tapis, des frames d’arrivée/départ, du programme LN avec allers-retours pour N=1 à 8, de l’attente et de l’arrêt. Les pauses et arrêts annulent aussi les caisses en transit des convoyeurs : la scène revient au dernier état validé.

Vérification après modification : 143 tests réussis et compilation Astro réussie. Dans le navigateur : prise sur l’entrée, transport et pose sur la première pile, évacuation par un programme LN, pause puis arrêt d’une prise (retour au dernier état), objectif masqué au chargement et affichage par la case à cocher. Rendu visuel des convoyeurs et absence des numéros vérifiés.

Présentation du plateau : chaque colonne repose sur un bloc gris de 44 × 16 unités, avec 8 unités entre blocs. Les convoyeurs sont écartés de 40 unités supplémentaires de chaque côté (32 unités libres entre tapis et bloc). La projection columnX interpole les positions de la pince sur ces intervalles plus larges ; les commandes gardent les mêmes postes logiques. Les caisses reposent sur le sommet des blocs, sans numéros de colonnes.

Capteur et évacuation automatique

caisse_dessous() : booléen LN, vrai sur une pile non vide ou l’entrée alimentée, faux sur une colonne vide ou la sortie. Ignore la caisse portée ; accessible à la main aussi. crateBelow(state) est pur. Chaque appel est compté dans les 1 000 appels autorisés et émet un rendu acquitté de 300 ms avec value booléenne ; pause, source active et pas à pas incluent les capteurs.

jeter() : requiert une caisse portée, retire la caisse portée et incrémente removed une seule fois (aucun historique des ids évacués n’est stocké) et revient à la même colonne, pince vide. Les piles et l’approvisionnement ne changent pas. Une seule commande atomique : déplacement vers la sortie, descente, dépôt/évacuation, remontée puis retour. craneDuration donne 700 ms par poste à l’aller et au retour, plus 1 800 ms pour le dépôt. Si déjà à la sortie, seul le dépôt est animé. craneFrame compose le rendu poser et deux déplacements ; aucun changement de modèle avant la fin. Arrêter pendant jeter annule tout l’aller-retour, y compris un dépôt déjà montré, et restaure la caisse portée au poste initial. Les deux fonctions sont sans argument, disponibles seulement dans le contexte du défi, sans import.

Tests supplémentaires dans tests/crane-extra.test.mjs : capteur avec/sans charge à chaque poste, absence de mutation, jeter depuis tous les postes, animation aller/dépôt/retour et cas déjà à la sortie, véritable boucle LN de vidage, arité, ligne d’erreur, limite des capteurs et arrêt.

Validation des nouvelles fonctions : 148 tests réussis, compilation réussie. Navigateur : capteur manuel VRAI à l’entrée ; programme LN affichant VRAI puis FAUX sur une colonne vide ; jeter animé suivi du retour pince vide à la première colonne ; pas à pas sur le capteur ; pause pendant la descente à la sortie puis arrêt restituant la caisse portée au poste de départ.

← Retour à la documentation