Issue #3616062: Place a hall by arranging a generated layout in a vector editor, keep the result as its map background, and let the picker zoom out to all of it

Places a hall from a vector editor, and makes the artwork an output of that trip rather than an input to it.

The trip

  1. Generate the places as today (rows x places per row, per section).
  2. Download the layout from the venue's new Layout tab. Every place is a use marker: drawn where it already sits, or parked on a grid below the room when it has no coordinates yet, one line per row under its section name.
  3. Arrange it in a vector editor; draw the room around the markers or trace a floor plan under them.
  4. Upload it back. x, y and angle are read off the markers, and the rest of the document becomes the venue's map_background.

For a plain rectangular room the grid from step 2 is already the finished map. Downloading again draws the hall as it now stands over the current artwork, so adding a row is download, drag, upload; applying the same file twice writes nothing.

The parts

  • MapLayoutBuilder — one direct select on yoyaku_place whatever the hall's size, the artwork inlined verbatim with its viewBox (the box only ever grows downwards, and only to hold parked places, so no coordinate ever moves), the chair glyphs defined only when the artwork does not define them.
  • MapLayoutReader — position and angle from the accumulated transform chain, not from an element's own x; markers found anywhere in the document, so taking a layer apart loses nothing; changed places only, saved in chunks that drop the static cache; the document minus every marker stored as the artwork; place_sprite and accessible_place_sprite named from the glyphs when the venue names none, which is what makes the first upload enough on its own.
  • MapDocument — the one place an SVG is parsed, with the network off and a doctype stripped rather than refused, since Illustrator writes one. MapBackgroundSvg still runs first, before any parser sees the bytes.
  • VenueLayoutForm — the whole trip on one screen, reporting before it writes.

What it refuses, and what it only states

Refused whole: two markers claiming one place (a copy, not a move), no marker at all, no marker naming a place of this venue, or a script or handler in the file.

Stated and not acted on: a marker naming no place here, a marker whose center cannot be read (converted to a path), a place outside the box, and a place with no marker, which keeps the coordinates it has — which is what makes a large hall arrangeable one section at a time.

Boundary

The layout carries x, y and angle, plus the grade when an upload is expressly told to read it. Not the accessible flag, not labels, and it never creates a place. position and gap_before stay derived, by drush yoyaku:venue-positions --fix.

Grades are a second, separate decision, off by default, because a layout is not where a grade is authored: a file carries the grades of the day it was downloaded, so applying them as a side effect of moving a hall would undo whatever had been regraded since. A marker naming no grade says nothing rather than clearing one, and a grade the venue does not have is reported rather than guessed at. Each marker also names its grade in data-yyk-grade and carries a class that colors it by grade, on by default; the color is never read back.

No new field, no schema change, no update hook, no JavaScript.

Tests

Five kernel classes: the round trip on a hall that has never been placed (asserted at the grid's own figures, and idempotent on a second pass), the transform chain (nested translate/scale/rotate/matrix, a circle instead of a use, a path reported as unreadable, resolution by natural key), the refusals, the artwork derivation and sprite bootstrap, and a query budget proving the statement count does not grow with the hall. Green on SQLite and on MySQL. One functional class covers the tab, the download headers and report-then-write.

Edited by Frank Mably

Merge request reports

Loading
Loading