fix: #3622101 The seated example seeds its hall in code, so it ships no artwork, no outlines and no configurations, and draws blank on a fresh install
The hall the seated example ships is now a venue package it imports, so it arrives drawn, outlined and configured. It was 175 lines of entity creation that could express none of those things.
What a fresh install got before. A venue with no map background and no area carrying an outline, and 128 places with no coordinates at all. The place map drew over nothing, every seat was at the origin, and a pooled area had no shape to click. The hall looked right only on a site where somebody had done the layout trip by hand, and that work lived in no repository: a file in one site's public files directory and a column on one site's sections.
What it ships now. examples/grand-hall/, a version 5 package: the Grand Hall, four tiers of four rows of eight on arcs centred in the stage so every seat carries the rotation that turns it to face the stage, each area with the outline it is clicked by when it is sold by quantity, two end seats of every front row accessible, and two ways of opening the hall — complete, which deviates nowhere, and reduced, which closes the gallery and sells the balcony by quantity at twenty places. The install imports it through VenueImporter and keeps in code only what is not the venue's: the concert, its slot and its two tariffs.
The hall is drawn rather than exported from anywhere, and it is drawn for legibility: a closed area reads at a glance on 128 places across four areas where it is invisible on the 1422 of the Auditorium. That is the argument for this being the hall the demo recipe and the Tugboat preview use, and it is why the small hall is the one that has to demonstrate the deviations model. The Auditorium stays where it is, in yoyaku_placement_io, as the example of a real hall at real scale.
English throughout, as the Auditorium package is since #3622067: Stalls, Dress circle, Balcony, Upper gallery, Optima and Category 1 to 3, and the artwork's own labels with them. Nothing in the package is French, and its keys are identifiers rather than labels.
Its teardown had to grow with it. The importer answers with the venue, so the install reads back what came in under it — the grades, areas, places and configurations, their per-area settings, and the managed file the artwork became — and records the lot for uninstall, in an order that deletes a row before whatever it points at.
PlacementExampleTest extends rather than a class of its own, and it went from 59 assertions to 831: the configuration and setting counts, the artwork being there and defining the sprites the places are drawn as, every area carrying an outline, and every seat sitting at a distinct point inside the artwork's own viewBox with more than one facing between them. That last one replaced an assertion phpstan called out as always true, since a place's angle is not nullable: it could not have failed, and a hall of 128 places stacked at the origin would have passed it.
Verified locally: PlacementExampleTest green at 831 assertions; phpcs over the module at the job's own extensions, no violations; phpstan level 5 from the module directory, [OK] No errors; scripts/check-translations.php says every string the module ships is translated, the new description included; cspell clean over the package, the install hook and the test.
One consequence worth stating: the example now depends on yoyaku_placement_io, because that is what reads a package. Installing the example therefore enables the import and export module too.
AI-Generated: Yes (Claude Code was used to draw the hall, to write the package, the install and the assertions, and this description. I looked at the rendered layout on screen through several passes, and ran the tests and every linter myself before posting.)