remove xml/svg based seating

This commit is contained in:
David Rodenkirchen 2024-09-04 23:54:28 +02:00
parent c090717486
commit e1f08f4c23
6 changed files with 7 additions and 1333 deletions

View File

@ -20,7 +20,10 @@
password="" password=""
[seating] [seating]
base_svg_path="" # SeatID -> Category
A01 = "NORMAL"
A02 = "NORMAL"
C01 = "LUXUS"
[tickets] [tickets]
[tickets."NORMAL"] [tickets."NORMAL"]

View File

@ -1,256 +0,0 @@
<mxfile host="drawio-plugin" modified="2024-08-20T12:29:20.095Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36" etag="_qBa9-8UH2I_if-_58Cs" version="22.1.22" type="embed">
<diagram id="23iRSUPoRavnBvh4doch" name="Page-1">
<mxGraphModel dx="1746" dy="706" grid="1" gridSize="20" guides="0" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" background="#0A0A0A" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="126" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;rounded=0;strokeColor=#FFFFFF;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="20" y="800" as="sourcePoint" />
<mxPoint x="800" y="800" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="4" value="&lt;font style=&quot;font-size: 28px;&quot;&gt;&lt;b&gt;Bürgerhaus Bottenhorn&lt;/b&gt;&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#FFFFFF;" parent="1" vertex="1">
<mxGeometry x="820" width="340" height="100" as="geometry" />
</mxCell>
<mxCell id="9" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;rounded=0;strokeColor=#FFFFFF;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="20" y="20" as="sourcePoint" />
<mxPoint x="20" y="800" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="12" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;rounded=0;strokeColor=#FFFFFF;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="800" y="800" as="sourcePoint" />
<mxPoint x="800" y="20" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="13" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;rounded=0;strokeColor=#FFFFFF;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="20" y="20" as="sourcePoint" />
<mxPoint x="800" y="20" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="14" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#FFFFFF;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="240" y="800" as="sourcePoint" />
<mxPoint x="240" y="560" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="15" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#FFFFFF;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="160" y="560" as="sourcePoint" />
<mxPoint x="20" y="560" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="16" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#FFFFFF;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="20" y="520" as="sourcePoint" />
<mxPoint x="260" y="520" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="18" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#FFFFFF;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="480" y="720" as="sourcePoint" />
<mxPoint x="480" y="520" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="19" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#FFFFFF;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="480" y="720" as="sourcePoint" />
<mxPoint x="720" y="720" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="20" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#FFFFFF;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="720" y="720" as="sourcePoint" />
<mxPoint x="720" y="520" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="21" value="&lt;font color=&quot;#ffffff&quot; style=&quot;font-size: 15px;&quot;&gt;&lt;b&gt;Schlarfsaal&lt;/b&gt;&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#000000;" parent="1" vertex="1">
<mxGeometry x="40" y="600" width="180" height="140" as="geometry" />
</mxCell>
<mxCell id="24" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#FFFFFF;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="340" y="520" as="sourcePoint" />
<mxPoint x="800" y="520" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="25" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#FFFFFF;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="260" y="540" as="sourcePoint" />
<mxPoint x="260" y="500" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="27" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#FFFFFF;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="340" y="540" as="sourcePoint" />
<mxPoint x="340" y="500" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="28" value="&lt;font style=&quot;font-size: 15px;&quot;&gt;&lt;b&gt;Einlass&lt;br&gt;und&lt;br&gt;Orga&lt;br&gt;&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=default;strokeColor=#FFFFFF;" parent="1" vertex="1">
<mxGeometry x="360" y="520" width="120" height="180" as="geometry" />
</mxCell>
<mxCell id="30" value="&lt;font style=&quot;font-size: 15px;&quot;&gt;&lt;b&gt;Toiletten&lt;/b&gt;&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#FFFFFF;labelBackgroundColor=none;" parent="1" vertex="1">
<mxGeometry x="80" y="520" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="31" value="" style="endArrow=classic;html=1;rounded=0;strokeColor=#FFFFFF;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="80" y="540" as="sourcePoint" />
<mxPoint x="40" y="540" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="32" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#FFFFFF;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="240" y="560" as="sourcePoint" />
<mxPoint x="200" y="560" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="33" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#FFFFFF;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="160" y="580" as="sourcePoint" />
<mxPoint x="160" y="540" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="34" value="" style="endArrow=none;html=1;rounded=0;strokeColor=#FFFFFF;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="200" y="580" as="sourcePoint" />
<mxPoint x="200" y="540" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="35" value="" style="endArrow=none;dashed=1;html=1;rounded=0;strokeColor=#FFFFFF;" parent="1" edge="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="680" y="520" as="sourcePoint" />
<mxPoint x="680" y="20" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="36" value="&lt;font style=&quot;font-size: 15px;&quot;&gt;&lt;b&gt;Bühne&lt;/b&gt;&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontColor=#FFFFFF;" parent="1" vertex="1">
<mxGeometry x="700" y="260" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="47" value="B01" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="60" y="280" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="49" value="B11" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="120" y="220" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="50" value="B03" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="180" y="280" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="51" value="B10" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="60" y="220" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="52" value="B12" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="180" y="220" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="53" value="B02" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="120" y="280" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="88" value="C01" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="60" y="120" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="89" value="C11" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="120" y="60" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="90" value="C03" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="180" y="120" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="127" value="C10" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="60" y="60" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="92" value="C12" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="180" y="60" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="93" value="C02" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="120" y="120" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="98" value="E13" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="540" y="60" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="99" value="E10" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="360" y="60" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="100" value="E12" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="480" y="60" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="101" value="E11" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="420" y="60" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="104" value="E01" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="360" y="120" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="105" value="E02" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="420" y="120" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="106" value="E03" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="480" y="120" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="107" value="E04" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="540" y="120" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="108" value="D13" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="540" y="220" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="109" value="D10" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="360" y="220" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="110" value="D12" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="480" y="220" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="111" value="D11" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="420" y="220" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="112" value="D01" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="360" y="280" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="113" value="D02" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="420" y="280" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="114" value="D03" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="480" y="280" width="60" height="40" as="geometry" />
</mxCell>
<mxCell id="115" value="D04" style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="540" y="280" width="60" height="40" as="geometry" />
</mxCell>
<object label="A01" category="LUXUS" id="116">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="60" y="440" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="A11" category="LUXUS" id="117">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="120" y="380" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="A03" category="LUXUS" id="118">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="180" y="440" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="A10" category="LUXUS" id="119">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="60" y="380" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="A12" category="LUXUS" id="120">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="180" y="380" width="60" height="40" as="geometry" />
</mxCell>
</object>
<object label="A02" category="LUXUS" id="121">
<mxCell style="rounded=0;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="120" y="440" width="60" height="40" as="geometry" />
</mxCell>
</object>
<mxCell id="128" value="&lt;font style=&quot;font-size: 15px;&quot;&gt;&lt;b&gt;Getränke&lt;/b&gt;&lt;/font&gt;" style="rounded=0;whiteSpace=wrap;html=1;fillColor=default;" parent="1" vertex="1">
<mxGeometry x="500" y="500" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="125" value="Neben-Ausgang" style="rounded=0;whiteSpace=wrap;html=1;fillColor=default;" parent="1" vertex="1">
<mxGeometry x="660" y="760" width="100" height="60" as="geometry" />
</mxCell>
<mxCell id="5" value="Eingang" style="rounded=0;whiteSpace=wrap;html=1;fillColor=default;" parent="1" vertex="1">
<mxGeometry x="320" y="760" width="80" height="60" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 89 KiB

View File

@ -71,13 +71,8 @@ class ConfigurationService:
def get_seating_configuration(self) -> SeatingConfiguration: def get_seating_configuration(self) -> SeatingConfiguration:
try: try:
seating_config = self._config["seating"]
base_svg_file_path = from_root(seating_config["base_svg_path"])
if not base_svg_file_path.exists():
logger.fatal(f"Specified seating plan SVG file was not found at {base_svg_file_path}! Exiting...")
sys.exit(1)
return SeatingConfiguration( return SeatingConfiguration(
base_svg_path=base_svg_file_path seats=self._config["seating"]
) )
except KeyError: except KeyError:
logger.fatal("Error loading seating configuration, exiting...") logger.fatal("Error loading seating configuration, exiting...")

View File

@ -1,11 +1,6 @@
import logging import logging
import re
from io import StringIO
from pathlib import Path
from typing import Optional from typing import Optional
from xml.etree import ElementTree
from from_root import from_root
from src.ez_lan_manager.services.DatabaseService import DatabaseService from src.ez_lan_manager.services.DatabaseService import DatabaseService
from src.ez_lan_manager.services.TicketingService import TicketingService from src.ez_lan_manager.services.TicketingService import TicketingService
@ -32,9 +27,6 @@ class SeatingService:
self._lan_info = lan_info self._lan_info = lan_info
self._db_service = db_service self._db_service = db_service
self._ticketing_service = ticketing_service self._ticketing_service = ticketing_service
self._seating_plan = StringIO()
ElementTree.parse(self._seating_configuration.base_svg_path).write(self._seating_plan, encoding="unicode")
async def get_seating(self) -> list[Seat]: async def get_seating(self) -> list[Seat]:
return await self._db_service.get_seating_info() return await self._db_service.get_seating_info()
@ -67,92 +59,5 @@ class SeatingService:
raise SeatAlreadyTakenError raise SeatAlreadyTakenError
await self._db_service.seat_user(seat_id, user_id) await self._db_service.seat_user(seat_id, user_id)
await self.update_svg_with_seating_status()
async def generate_new_seating_table(self, seating_plan_fp: Path, no_confirm: bool = False) -> None: # ToDo: Make function that creates database table `seats` from config
if not no_confirm:
confirm = input("WARNING: THIS ACTION WILL DELETE ALL SEATING DATA! TYPE 'AGREE' TO CONTINUE: ")
if confirm != "AGREE":
logging.info("Seating table generation aborted...")
return
et = ElementTree.parse(seating_plan_fp)
seat_ids = []
for child in et.getroot().findall(".//mxCell"):
possible_seat_identifier = child.get("value")
try:
if re.match(r"^\w\d{1,3}$", possible_seat_identifier):
seat_ids.append((possible_seat_identifier, self._lan_info.ticket_info.default_category))
except TypeError:
continue
for child in et.getroot().findall(".//object"):
possible_seat_identifier = child.get("label")
try:
if re.match(r"^\w\d{1,3}$", possible_seat_identifier):
category = child.get("category")
seat_ids.append((possible_seat_identifier, category))
except TypeError:
continue
await self._db_service.generate_fresh_seats_table(sorted(seat_ids, key=lambda sd: sd[0]))
await self.update_svg_with_seating_status()
async def update_svg_with_seating_status(self) -> None:
et = ElementTree.parse(self._seating_configuration.base_svg_path)
root = et.getroot()
namespace = {'svg': root.tag.split('}')[0].strip('{')} if '}' in root.tag else {}
rect_g_pairs = []
last_rect = None
for elem in root.iter():
if elem.tag == f"{{{namespace.get('svg')}}}rect":
last_rect = elem
elif elem.tag == f"{{{namespace.get('svg')}}}g":
if last_rect is not None:
rect_g_pairs.append((last_rect, elem))
last_rect = None
all_seats = await self.get_seating()
for rect, g in rect_g_pairs:
seat_id = self.get_seat_id_from_element(g, namespace)
if not seat_id:
continue
seat = await self.get_seat(seat_id, cached_data=all_seats)
if not seat.is_blocked and seat.user is None:
rect.set("fill", "rgb(102, 255, 51)")
elif not seat.is_blocked and seat.user is not None:
rect.set("fill", "rgb(204, 0, 0)")
else:
rect.set("fill", "rgb(190,190,190)")
# @ToDo: Set URL's properly
rect.set('onclick', f"window.open('https://httpbin.org/get?seat_id={seat_id}', '_blank')")
g.set('onclick', f"window.open('https://httpbin.org/get?seat_id={seat_id}', '_blank')")
# Debug output
et.write(from_root("debug_seating_plan.svg"))
self._seating_plan = StringIO()
et.write(self._seating_plan, encoding='unicode')
@staticmethod
def get_seat_id_from_element(element: ElementTree.Element, namespace: dict) -> Optional[str]:
seat_id = None
for child in element.iter():
if child.tag == f"{{{namespace.get('svg')}}}text":
# Extract identifier from <text> element
seat_id = child.text.strip() if child.text else None
elif child.tag.endswith('div') and child.text:
# Extract identifier from <foreignObject>/<div>
seat_id = child.text.strip()
if seat_id: # Break if we've already found the identifier
break
try:
if re.match(r"^\w\d{1,3}$", seat_id):
return seat_id
except TypeError:
pass
return

View File

@ -41,4 +41,4 @@ class LanInfo:
@dataclass(frozen=True) @dataclass(frozen=True)
class SeatingConfiguration: class SeatingConfiguration:
base_svg_path: Path seats: dict[str, str]