Compare commits

...

9 Commits

Author SHA1 Message Date
Michael Stangl 6ee33eb085 Beispiel-/Doku-Ausgaben neu erzeugt
Regenerierte SVG-Doku-Bilder und die hochzeit-Beispielausgaben
(TischePersonen.txt / PersonenTische.csv) nach den aktuellen Aenderungen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-27 10:11:38 +02:00
Michael Stangl cded317a40 Doku: Farbprofile (--farben, cfg/farben.cfg, libs/Farben.py)
CLAUDE.md dokumentiert das neue SVG-Farbprofil-Feature: den Schalter
--farben, die Profile in cfg/farben.cfg (palette / kategorien) und das
Modul libs/Farben.py.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-27 10:11:25 +02:00
Michael Stangl c6e0b95d81 Web-GUI: fixierte Gruppen anzeigen, Strafprofil waehlen, Farben nutzen
CSVConfig.HandleGaesteliste liefert zusaetzlich FixierteGruppen (Name ->
Tisch/Anzahl), damit fest platzierte Gaeste in der Gaesteliste sichtbar
(grau hinterlegt) erscheinen. Durchgaengig "VIP" -> "fixiert" umbenannt.

Backend: Strafprofile werden gecacht geladen, neuer Endpoint /strafprofile
und Query-Parameter strafen an /berechnen, damit sich Profile (default vs.
locker) in der GUI vergleichen lassen. SVG-Ausgabe nutzt das Farbschema aus
farben.cfg (Rueckfall auf Palette).

Frontend: tische.ini und CSV werden bei Auswahl sofort geladen, Auswahl der
fixierten Gruppen und des Optimierungsprofils in der Oberflaeche.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-27 10:10:41 +02:00
Michael Stangl d19913a53d SVG-Farbprofile: --farben mit palette- und kategorien-Modus
Neues Modul libs/Farben.py mit Farbschema, das Gruppen Farben zuordnet,
gesteuert durch Profile aus cfg/farben.cfg. Zwei Modi: "palette" (Farbliste
zyklisch je Gruppe, Profil grosse_gruppen) und "kategorien" (Hochzeit:
Familie/Verein/VIP getrennt ueber Farbverlaeufe, Profil hochzeit).

Sitzplatzverteilung.alsSVG bekommt Parameter Farbschema; Farben werden nun
fest fuer die vollstaendige Gruppenliste (nach Id) vergeben statt lazy in
Zeichenreihenfolge, damit jede Gruppe variantenuebergreifend dieselbe Farbe
hat. platz.py bekommt Schalter --farben (Vorgabe grosse_gruppen).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-27 10:10:23 +02:00
Michael Stangl d4844ded67 Loesungs-Dedup: getGruppenId/getPersonenId, keine doppelten Sitzordnungen
- getGruppenId (Gruppen-Ebene, personen-unabhaengig: welche Gruppen mit
  welcher Anzahl je Tisch) und getPersonenId (Personen-Ebene: alphabetische
  Namen je Tisch) an Sitzplatzverteilung; Basis-Methoden an Loesung. Gleiche
  Gruppen-Verteilung -> gleiche getGruppenId und damit gleiche Wertigkeit,
  egal welche Personen die geteilten Plaetze einnehmen.
- Farm verwirft nach jeder Erzeugung/Mutation Loesungen mit schon gesehener
  getGruppenId, so dass dieselbe Sitzordnung nicht mehrfach gehalten und
  bewertet wird (defensiv: Klassen ohne getGruppenId bleiben unberuehrt,
  Tests unveraendert).
- Web: Varianten-Vergleich ueber getGruppenId statt der person-basierten
  _Signatur; gruppenId und personenId zusaetzlich im Ergebnis-JSON.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 18:10:23 +02:00
Michael Stangl b29b3b22d4 SVG-Raumplan: Platzzahl je Tisch, Hover-Infos und Bild vor der Liste
- Platzzahl unter der Tischnummer im SVG
- Personenkreise mit <title> (Name - Gruppe) und data-Attributen
  (gruppe/name/gid); im Web den Raumplan inline statt als <img>
  einbetten, dazu ein Kasten mit der Gruppen-Namensliste und
  Hervorhebung der Gruppe beim Hover
- Ausgabe: Raumplan vor der Tabellenliste (schneller Varianten-Vergleich)
- SVG als UTF-8 schreiben (Umlaute/Gedankenstrich sonst ungueltig)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 17:30:33 +02:00
Michael Stangl 4a059f32c5 Strafen können durch benannte Profile festgelegt werden 2026-07-15 17:05:13 +02:00
Michael Stangl db69f3498d Funktion zum relode der Tische aus der Session und der Gäste laden 2026-07-12 17:03:23 +02:00
Michael Stangl f880ae1c97 in der Roademap weitergemacht 2026-07-12 17:02:14 +02:00
27 changed files with 3199 additions and 1812 deletions
+41 -6
View File
@@ -72,8 +72,10 @@ the same layout:
The GA cycle and penalty scheme are read directly from `$PLATZ_CFG/zyklus.cfg` and The GA cycle and penalty scheme are read directly from `$PLATZ_CFG/zyklus.cfg` and
`$PLATZ_CFG/strafen.cfg` (independent of `--indir`). There is no `platz.cfg` indirection any `$PLATZ_CFG/strafen.cfg` (independent of `--indir`). There is no `platz.cfg` indirection any
more — it was removed; `zyklus.cfg`/`strafen.cfg` are loaded straight from `$PLATZ_CFG`, and more — it was removed; `zyklus.cfg`/`strafen.cfg` are loaded straight from `$PLATZ_CFG`, the
the GA profile is chosen by the `--zyklus-art <name>` switch (default `Adaptiv`). GA profile is chosen by the `--zyklus-art <name>` switch (default `Adaptiv`), the penalty
profile by the `--strafen <name>` switch (default `default`), and the SVG colour profile by
the `--farben <name>` switch (default `grosse_gruppen`).
- `cfg/zyklus.cfg` — defines the GA profiles. Two flavours: **static** profiles (`Easy`, - `cfg/zyklus.cfg` — defines the GA profiles. Two flavours: **static** profiles (`Easy`,
`Simple`) give an explicit sequence of actions (`e`=erzeugen/create, `s`=selektieren/ `Simple`) give an explicit sequence of actions (`e`=erzeugen/create, `s`=selektieren/
@@ -84,10 +86,30 @@ the GA profile is chosen by the `--zyklus-art <name>` switch (default `Adaptiv`)
with a shrinking population (`Start`, `Schrumpfung`, `MinPopulation`) and a convergence with a shrinking population (`Start`, `Schrumpfung`, `MinPopulation`) and a convergence
stop (`Geduld` generations without an improvement of at least `Schwelle`, capped by stop (`Geduld` generations without an improvement of at least `Schwelle`, capped by
`MaxGenerationen`). Static profiles run via `Farm._LaufStatisch()`. `MaxGenerationen`). Static profiles run via `Farm._LaufStatisch()`.
- `cfg/strafen.cfg` — the penalty ("Strafpunkte") table: cost of splitting a group across - `cfg/strafen.cfg` — the penalty ("Strafpunkte") profiles. Each section is one complete
tables (by group size and number of splits), cost of a lone person, per-table profile ("Vorgehen") in a single namespace, chosen by `--strafen <section>` (default
under-utilization penalties, and (optional `[Abstand]` section) a penalty for the spatial `default`); this lets several scoring strategies live in one file (the shipped file also
distance between split-off parts of a group. has a `locker` example with cheaper splits). Keys per profile: `Anzahl_Trennungen_N`
(`{groupsize:points}` for a group split across `N+1` tables, i.e. `N` splits — recursing to
smaller sizes when no exact entry), `NichtNachbar` (no group-mate at a neighbouring table),
`Allein` (a lone person), optional `TischWertigkeiten` (`{freeseats:points}` under-utilization,
with a nearest-lower-key fallback; absent = free seats not penalised, as in the `locker`
profile), and optional `AbstandFaktor` (per spatial-distance unit
between split-off parts; absent = distance not penalised). `Strafliste.laden(FileName,
Sektion='default')` parses one section; the old `[Trennung]`/`[Globals]`/`[Abstand]`
three-section layout is gone.
- `cfg/farben.cfg` — SVG colour profiles, chosen by `--farben <section>` (default
`grosse_gruppen`) / env `PLATZ_FARBENART`, parsed by `Farben.Farbschema.laden()` (in
`libs/Farben.py`) and passed into `Sitzplatzverteilung.alsSVG(..., Farbschema=...)`. Two
modes: `Modus = palette` (a `Palette` colour list cycled per group by sorted group id — the
`grosse_gruppen` profile) and `Modus = kategorien` (the `hochzeit` profile — splits groups
into **Familie** = members mostly share a surname, coloured along `FamilienVerlaeufe`
gradients blue→green / yellow→orange, one gradient bucket per surname; **Verein** = any
other named group, along `VereinVerlauf` violet→grey; **VIP** = fixed-table people with no
GA group, the start of `VIPVerlauf`, red). Gradient syntax `"start -> end"`. Anonymous bulk
bookings (all members identical, e.g. an `anzahl`-expanded "Gast Musikverein") are *not*
treated as a family. Absent/invalid config falls back to the built-in palette
(`Farbschema=None`), so the SVG always renders.
`tische.ini`/`bestellung.json`/`TischePersonen.txt`/`PersonenTische.csv` are fixed filenames `tische.ini`/`bestellung.json`/`TischePersonen.txt`/`PersonenTische.csv` are fixed filenames
resolved as `os.path.join(indir, ...)` in `platz.py`. resolved as `os.path.join(indir, ...)` in `platz.py`.
@@ -100,6 +122,19 @@ solution's ancestral branch highlighted and labelled with its id. Every solution
running number (`Farm._NeueId`, `1..N`); the ancestry is not encoded in the id but recorded running number (`Farm._NeueId`, `1..N`); the ancestry is not encoded in the id but recorded
via each node's stored predecessor (parent id) and followed back along the highlighted branch. via each node's stored predecessor (parent id) and followed back along the highlighted branch.
Pass `--seed <int>` to make a run fully reproducible: `platz.py` calls `random.seed()` with
it before any GA action, so the same seed always yields the same seating (for support
questions like "why is Aunt Erna seated there?" — rerun with the same seed to get the exact
same plan). Reproducibility needs more than seeding the RNG: `Person` defines an Id-based
`__hash__`/`__eq__` (each booking has a unique running integer Id) so that the `set()` of
people in a `Gruppe` iterates/`pop()`s in a process-stable order — otherwise the order would
hinge on object memory addresses (and, for string-keyed containers, `PYTHONHASHSEED`), leaving
the run non-reproducible even with `--seed`. Integer Ids aren't affected by `PYTHONHASHSEED`,
so no environment tweaking is required.
`Farm.TopN(n)` returns the `n` best solutions (descending), clamped to `[0, len(Pool)]` — the
list generalisation of `Farm.Bester()` (single best), for surfacing several good alternatives.
Run the test suite with `bin/run_tests.bat` / `bin/run_tests.sh` (or directly: `python -m Run the test suite with `bin/run_tests.bat` / `bin/run_tests.sh` (or directly: `python -m
unittest discover -s tests -p "test_*.py" -v`). A stray global `PYTHONPATH` entry on this unittest discover -s tests -p "test_*.py" -v`). A stray global `PYTHONPATH` entry on this
machine points at an unrelated project that also defines a `tests` package — this shadows machine points at an unrelated project that also defines a `tests` package — this shadows
+44
View File
@@ -0,0 +1,44 @@
# Farbprofile fuer die SVG-Ausgabe (Sitzplatzverteilung.alsSVG).
#
# Jede Sektion ist ein Farbprofil, waehlbar per --farben <Sektion> (libs/platz.py,
# Vorgabe: grosse_gruppen) bzw. ueber PLATZ_FARBENART (Web). So laesst sich je
# Anlass ein anderes Farbschema vorwaehlen.
#
# Modus = palette
# Eine Farbliste (Palette), die zyklisch je Gruppe (nach Gruppen-Id sortiert)
# vergeben wird. Gut fuer viele/grosse Gruppen, wo es nur auf klare
# Unterscheidbarkeit ankommt.
#
# Modus = kategorien
# Trennt die Gruppen nach Art und faerbt sie unterschiedlich ein - gedacht
# fuer Hochzeiten:
# - Familie: eine Gruppe, deren Mitglieder mehrheitlich denselben
# Nachnamen tragen. Jeder Nachname bekommt einen Farbverlauf
# (abwechselnd aus FamilienVerlaeufe), Untergruppen desselben
# Nachnamens laufen den Verlauf entlang (z.B. Blau -> Gruen).
# - Verein: jede sonstige benannte Gruppe (Freunde, Kollegen, Vereine);
# laeuft ueber VereinVerlauf (z.B. Violett -> Grau).
# - VIP: fest gesetzte Gaeste ohne GA-Gruppe (Ehrentafel, Kindertisch);
# bekommen die Startfarbe von VIPVerlauf (Rot).
#
# Farbverlauf-Syntax: "Startfarbe -> Endfarbe"; mehrere Verlaeufe kommagetrennt.
# Fuer grosse Veranstaltungen mit vielen Gruppen: reine Palette, zyklisch.
[grosse_gruppen]
Modus = palette
Palette = #e6194b, #3cb44b, #4363d8, #f58231, #911eb4, #42d4f4, #f032e6,
#bfef45, #fabed4, #469990, #dcbeff, #9a6324, #800000, #aaffc3,
#000075, #808000, #ffd8b1, #f58231, #46f0f0, #d2f53c
# Fuer Hochzeiten: nach Familie / Verein / VIP getrennt.
[hochzeit]
Modus = kategorien
# Familien: abwechselnd Blau -> Gruen und Gelb -> Orange (je Nachname ein
# Verlauf, damit sich verschiedene Familien unterscheiden).
FamilienVerlaeufe = #1f4e9c -> #2fae5f, #f2c200 -> #e8590c
# Vereine / gemischte Gruppen: Violett -> Grau.
VereinVerlauf = #7b2fbf -> #9aa0a6
# VIPs (feste Platzierung): Rot.
VIPVerlauf = #e63946 -> #8b0000
+51 -33
View File
@@ -1,38 +1,56 @@
# Strafpunkte fuer die Trennung einer Gruppe: # Strafpunkte-Profile ("Vorgehen") fuer die Bewertung einer Sitzplatzverteilung.
# Aufbau: Anzahl der Trennungen = { Gruppengroesse:Strafpunkte, .. } #
# Deutlich hoeher als frueher, damit eine Trennung teurer ist als der Gewinn, # Jede Sektion ist EIN vollstaendiges Bewertungsprofil mit allen Angaben. So
# einen Tisch dafuer teilbelegt zu lassen (sonst werden Gruppen getrennt, # lassen sich mehrere Vorgehensweisen nebeneinander pflegen und speichern. Per
# obwohl daneben leere Tische stehen). # Schalter --strafen <Sektionsname> waehlt man ein Profil; ohne Schalter wird
[Trennung] # [default] verwendet.
1={ 2:-25, 3:-22, 4:-18, 6:-14, 8:-12, 10:-10 } #
2={ 3:-40, 4:-30, 6:-22, 8:-18, 10:-14 } # Schluessel je Profil:
3={ 4:-60, 6:-40, 8:-30, 10:-20 } # Anzahl_Trennungen_N = { Gruppengroesse:Strafpunkte, .. }
# Strafpunkte fuer das Aufteilen einer Gruppe (N = Anzahl der Trennungen,
# also auf N+1 Tische verteilt), gestaffelt nach Gruppengroesse. Fehlt ein
# exakter Gruppengroessen-Eintrag, wird auf die naechstkleinere Groesse
# zurueckgegriffen. Mindestens Anzahl_Trennungen_1 sollte gesetzt sein.
# NichtNachbar = Strafe, wenn zwei Gruppenteile nicht am Nachbartisch sitzen
# Allein = Strafe, wenn eine Person ohne Gruppenmitglied am Tisch sitzt
# TischWertigkeiten = { freiePlaetze:Strafpunkte, .. } fuer freie Sitze an einem
# (teil-)belegten Tisch. Fehlt ein exakter Eintrag, gilt der
# naechstkleinere. Teilbelegte Tische sind am schlechtesten
# (dort passt keine ganze Gruppe mehr hin), daher steigt die
# Strafe mit den freien Plaetzen; ein komplett leerer Tisch
# (hoechster Schluessel) ist etwas besser, aber nicht gratis,
# damit sich das Zusammenziehen von Gruppen lohnt.
# Optional; fehlt der ganze Schluessel, werden freie Plaetze
# gar nicht bestraft -> mehr Teilbelegungen moeglich.
# AbstandFaktor = Strafpunkte je normierter Abstandseinheit (0..100) zwischen
# getrennten Teilen einer Gruppe. Der Abstand ist auf die
# maximale Ausdehnung der Tischanordnung normiert (100 =
# ein Teil ganz links/oben, der andere ganz rechts/unten).
# AbstandFaktor=-0.2 kostet den Maximalabstand also -20.
# Optional; fehlt der Schluessel, wird der Abstand nicht
# bestraft (Faktor 0).
# Wieviele Strafpunkte bekommt man # Standardprofil: Trennungen sind bewusst teuer, damit eine Gruppe lieber
# wenn zwei Gruppen nicht am Nachbartisch sitzen # zusammen an einem teilbelegten Tisch sitzt, als neben einem leeren getrennt zu
# wenn einer aus einer Gruppe allein sitzen muss # werden.
[Globals] [default]
Anzahl_Trennungen_1={ 2:-25, 3:-22, 4:-18, 6:-14, 8:-12, 10:-10 }
Anzahl_Trennungen_2={ 3:-40, 4:-30, 6:-22, 8:-18, 10:-14 }
Anzahl_Trennungen_3={ 4:-60, 6:-40, 8:-30, 10:-20 }
NichtNachbar=-3 NichtNachbar=-3
Allein=-30 Allein=-30
TischWertigkeiten={ 1:-3, 2:-3, 4:-5, 6:-6, 8:-4 } TischWertigkeiten={ 1:-3, 2:-3, 4:-5, 6:-6, 8:-4 }
AbstandFaktor=-0.2
# TischWertigkeiten sind Strafpunkte fuer freie Sitze an einem Tisch, je nach # Beispiel fuer ein alternatives Vorgehen: Trennungen sind guenstiger, der
# Anzahl freier Plaetze (fehlt ein exakter Eintrag, gilt der naechstkleinere). # Abstand wird nicht bestraft, und freie Plaetze werden gar nicht bestraft
# Ziel: teilbelegte Tische sind am schlechtesten (dort passt keine ganze # (TischWertigkeiten fehlt bewusst) — so sind mehr Teilbelegungen moeglich.
# Gruppe mehr hin und die Sitzenden haben leere Nachbarplaetze), daher steigt # Nuetzlich fuer grosse Saele, in denen sich Gruppen kaum ungeteilt platzieren
# die Strafe mit den freien Plaetzen an (1..7 frei: -3 -> -6). Ein *komplett* # lassen. Aufruf: --strafen locker
# leerer Tisch ist etwas besser als ein halbleerer (-4 bei 8 frei), weil ein [locker]
# leerer Tisch als Ganzes fuer eine Gruppe frei bleibt - er soll aber nicht Anzahl_Trennungen_1={ 2:-12, 3:-10, 4:-8, 6:-6, 8:-5, 10:-4 }
# gratis sein, damit sich das Zusammenziehen von Gruppen lohnt. Anzahl_Trennungen_2={ 3:-20, 4:-16, 6:-12, 8:-9, 10:-7 }
Anzahl_Trennungen_3={ 4:-30, 6:-22, 8:-16, 10:-12 }
# Strafpunkte fuer den Abstand zwischen getrennten Teilen einer Gruppe. NichtNachbar=-2
# Wird eine Gruppe auf mehrere Tische aufgeteilt, ist ein grosser raeumlicher Allein=-20
# Abstand zwischen den Teilen viel schlechter als ein kleiner. AbstandFaktor=0.0
# Der Abstand wird als normierter Wert 0..100 berechnet: Bezugsgroesse ist die
# maximale Ausdehnung der Tischanordnung (Breite oder Laenge). Ein Abstand von
# 100 heisst also, dass ein Gruppenteil ganz links/oben und der andere ganz
# rechts/unten sitzt.
# Faktor = Strafpunkte je normierter Abstandseinheit. Bei Faktor=-0.2 kostet
# der maximal moegliche Abstand (100) demnach -20 Punkte.
[Abstand]
Faktor=-0.2
+15 -12
View File
@@ -2,18 +2,21 @@
<svg xmlns="http://www.w3.org/2000/svg" width="251.2" height="90.4" viewBox="0 0 251.2 90.4"> <svg xmlns="http://www.w3.org/2000/svg" width="251.2" height="90.4" viewBox="0 0 251.2 90.4">
<rect width="100%" height="100%" fill="white"/> <rect width="100%" height="100%" fill="white"/>
<circle cx="45.2" cy="45.2" r="35.2" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="45.2" cy="45.2" r="35.2" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="45.2" cy="32" r="12" fill="#e6194b" stroke="black" stroke-width="1"/> <circle class="person" data-gid="1" data-gruppe="Gruppe 1" data-name="Vorname1 Nachname1" cx="45.2" cy="32" r="12" fill="#e6194b" stroke="black" stroke-width="1"><title>Vorname1 Nachname1 — Gruppe 1</title></circle>
<circle cx="45.2" cy="58.4" r="12" fill="#e6194b" stroke="black" stroke-width="1"/> <circle class="person" data-gid="1" data-gruppe="Gruppe 1" data-name="Vorname2 Nachname2" cx="45.2" cy="58.4" r="12" fill="#e6194b" stroke="black" stroke-width="1"><title>Vorname2 Nachname2 — Gruppe 1</title></circle>
<circle cx="45.2" cy="45.2" r="12" fill="white" fill-opacity="0.75"/> <ellipse cx="45.2" cy="45.2" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="45.2" y="45.2" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text> <text x="45.2" y="40.4" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text>
<text x="45.2" y="53.6" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">2 Pl.</text>
<circle cx="125.6" cy="45.2" r="35.2" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="125.6" cy="45.2" r="35.2" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="125.6" cy="32" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/> <circle class="person" data-gid="2" data-gruppe="Gruppe 2" data-name="Vorname3 Nachname3" cx="125.6" cy="32" r="12" fill="#3cb44b" stroke="black" stroke-width="1"><title>Vorname3 Nachname3 — Gruppe 2</title></circle>
<circle cx="125.6" cy="58.4" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/> <circle class="person" data-gid="2" data-gruppe="Gruppe 2" data-name="Vorname4 Nachname4" cx="125.6" cy="58.4" r="12" fill="#3cb44b" stroke="black" stroke-width="1"><title>Vorname4 Nachname4 — Gruppe 2</title></circle>
<circle cx="125.6" cy="45.2" r="12" fill="white" fill-opacity="0.75"/> <ellipse cx="125.6" cy="45.2" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="125.6" y="45.2" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text> <text x="125.6" y="40.4" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text>
<text x="125.6" y="53.6" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">2 Pl.</text>
<circle cx="206" cy="45.2" r="35.2" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="206" cy="45.2" r="35.2" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="206" cy="32" r="12" fill="#4363d8" stroke="black" stroke-width="1"/> <circle class="person" data-gid="3" data-gruppe="Gruppe 3" data-name="Vorname5 Nachname5" cx="206" cy="32" r="12" fill="#4363d8" stroke="black" stroke-width="1"><title>Vorname5 Nachname5 — Gruppe 3</title></circle>
<circle cx="206" cy="58.4" r="12" fill="#4363d8" stroke="black" stroke-width="1"/> <circle class="person" data-gid="3" data-gruppe="Gruppe 3" data-name="Vorname6 Nachname6" cx="206" cy="58.4" r="12" fill="#4363d8" stroke="black" stroke-width="1"><title>Vorname6 Nachname6 — Gruppe 3</title></circle>
<circle cx="206" cy="45.2" r="12" fill="white" fill-opacity="0.75"/> <ellipse cx="206" cy="45.2" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="206" y="45.2" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text> <text x="206" y="40.4" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text>
<text x="206" y="53.6" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">2 Pl.</text>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

+34 -28
View File
@@ -1,38 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="251.2" height="412" viewBox="0 0 251.2 412"> <svg xmlns="http://www.w3.org/2000/svg" width="251.2" height="412" viewBox="0 0 251.2 412">
<rect width="100%" height="100%" fill="white"/> <rect width="100%" height="100%" fill="white"/>
<polyline points="125.6,353.6 206,286.4" fill="none" stroke="#e6194b" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="0.5"/> <polyline points="125.6,353.6 206,286.4" fill="none" stroke="#f58231" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="0.5"/>
<polyline points="125.6,380 45.2,286.4" fill="none" stroke="#3cb44b" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="0.5"/> <polyline points="125.6,380 45.2,286.4" fill="none" stroke="#4363d8" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="0.5"/>
<polyline points="206,125.6 125.6,32" fill="none" stroke="#4363d8" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="0.5"/> <polyline points="206,125.6 125.6,32" fill="none" stroke="#e6194b" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="0.5"/>
<polyline points="125.6,58.4 45.2,125.6" fill="none" stroke="#f58231" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="0.5"/> <polyline points="125.6,58.4 45.2,125.6" fill="none" stroke="#3cb44b" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="0.5"/>
<circle cx="125.6" cy="366.8" r="35.2" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="125.6" cy="366.8" r="35.2" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="125.6" cy="353.6" r="12" fill="#e6194b" stroke="black" stroke-width="1"/> <circle class="person" data-gid="4" data-gruppe="Gruppe 4" data-name="Vorname10 Nachname10" cx="125.6" cy="353.6" r="12" fill="#f58231" stroke="black" stroke-width="1"><title>Vorname10 Nachname10 — Gruppe 4</title></circle>
<circle cx="125.6" cy="380" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/> <circle class="person" data-gid="3" data-gruppe="Gruppe 3" data-name="Vorname7 Nachname7" cx="125.6" cy="380" r="12" fill="#4363d8" stroke="black" stroke-width="1"><title>Vorname7 Nachname7 — Gruppe 3</title></circle>
<circle cx="125.6" cy="366.8" r="12" fill="white" fill-opacity="0.75"/> <ellipse cx="125.6" cy="366.8" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="125.6" y="366.8" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text> <text x="125.6" y="362" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text>
<text x="125.6" y="375.2" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">2 Pl.</text>
<circle cx="206" cy="286.4" r="35.2" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="206" cy="286.4" r="35.2" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="206" cy="273.2" r="12" fill="#e6194b" stroke="black" stroke-width="1"/> <circle class="person" data-gid="4" data-gruppe="Gruppe 4" data-name="Vorname11 Nachname11" cx="206" cy="273.2" r="12" fill="#f58231" stroke="black" stroke-width="1"><title>Vorname11 Nachname11 — Gruppe 4</title></circle>
<circle cx="206" cy="299.6" r="12" fill="#e6194b" stroke="black" stroke-width="1"/> <circle class="person" data-gid="4" data-gruppe="Gruppe 4" data-name="Vorname12 Nachname12" cx="206" cy="299.6" r="12" fill="#f58231" stroke="black" stroke-width="1"><title>Vorname12 Nachname12 — Gruppe 4</title></circle>
<circle cx="206" cy="286.4" r="12" fill="white" fill-opacity="0.75"/> <ellipse cx="206" cy="286.4" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="206" y="286.4" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text> <text x="206" y="281.6" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text>
<text x="206" y="294.8" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">2 Pl.</text>
<circle cx="206" cy="125.6" r="35.2" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="206" cy="125.6" r="35.2" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="206" cy="112.4" r="12" fill="#4363d8" stroke="black" stroke-width="1"/> <circle class="person" data-gid="1" data-gruppe="Gruppe 1" data-name="Vorname2 Nachname2" cx="206" cy="112.4" r="12" fill="#e6194b" stroke="black" stroke-width="1"><title>Vorname2 Nachname2 — Gruppe 1</title></circle>
<circle cx="206" cy="138.8" r="12" fill="#4363d8" stroke="black" stroke-width="1"/> <circle class="person" data-gid="1" data-gruppe="Gruppe 1" data-name="Vorname3 Nachname3" cx="206" cy="138.8" r="12" fill="#e6194b" stroke="black" stroke-width="1"><title>Vorname3 Nachname3 — Gruppe 1</title></circle>
<circle cx="206" cy="125.6" r="12" fill="white" fill-opacity="0.75"/> <ellipse cx="206" cy="125.6" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="206" y="125.6" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text> <text x="206" y="120.8" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text>
<text x="206" y="134" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">2 Pl.</text>
<circle cx="125.6" cy="45.2" r="35.2" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="125.6" cy="45.2" r="35.2" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="125.6" cy="32" r="12" fill="#4363d8" stroke="black" stroke-width="1"/> <circle class="person" data-gid="1" data-gruppe="Gruppe 1" data-name="Vorname1 Nachname1" cx="125.6" cy="32" r="12" fill="#e6194b" stroke="black" stroke-width="1"><title>Vorname1 Nachname1 — Gruppe 1</title></circle>
<circle cx="125.6" cy="58.4" r="12" fill="#f58231" stroke="black" stroke-width="1"/> <circle class="person" data-gid="2" data-gruppe="Gruppe 2" data-name="Vorname4 Nachname4" cx="125.6" cy="58.4" r="12" fill="#3cb44b" stroke="black" stroke-width="1"><title>Vorname4 Nachname4 — Gruppe 2</title></circle>
<circle cx="125.6" cy="45.2" r="12" fill="white" fill-opacity="0.75"/> <ellipse cx="125.6" cy="45.2" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="125.6" y="45.2" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text> <text x="125.6" y="40.4" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text>
<text x="125.6" y="53.6" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">2 Pl.</text>
<circle cx="45.2" cy="125.6" r="35.2" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="45.2" cy="125.6" r="35.2" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="45.2" cy="112.4" r="12" fill="#f58231" stroke="black" stroke-width="1"/> <circle class="person" data-gid="2" data-gruppe="Gruppe 2" data-name="Vorname5 Nachname5" cx="45.2" cy="112.4" r="12" fill="#3cb44b" stroke="black" stroke-width="1"><title>Vorname5 Nachname5 — Gruppe 2</title></circle>
<circle cx="45.2" cy="138.8" r="12" fill="#f58231" stroke="black" stroke-width="1"/> <circle class="person" data-gid="2" data-gruppe="Gruppe 2" data-name="Vorname6 Nachname6" cx="45.2" cy="138.8" r="12" fill="#3cb44b" stroke="black" stroke-width="1"><title>Vorname6 Nachname6 — Gruppe 2</title></circle>
<circle cx="45.2" cy="125.6" r="12" fill="white" fill-opacity="0.75"/> <ellipse cx="45.2" cy="125.6" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="45.2" y="125.6" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text> <text x="45.2" y="120.8" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text>
<text x="45.2" y="134" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">2 Pl.</text>
<circle cx="45.2" cy="286.4" r="35.2" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="45.2" cy="286.4" r="35.2" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="45.2" cy="273.2" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/> <circle class="person" data-gid="3" data-gruppe="Gruppe 3" data-name="Vorname8 Nachname8" cx="45.2" cy="273.2" r="12" fill="#4363d8" stroke="black" stroke-width="1"><title>Vorname8 Nachname8 — Gruppe 3</title></circle>
<circle cx="45.2" cy="299.6" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/> <circle class="person" data-gid="3" data-gruppe="Gruppe 3" data-name="Vorname9 Nachname9" cx="45.2" cy="299.6" r="12" fill="#4363d8" stroke="black" stroke-width="1"><title>Vorname9 Nachname9 — Gruppe 3</title></circle>
<circle cx="45.2" cy="286.4" r="12" fill="white" fill-opacity="0.75"/> <ellipse cx="45.2" cy="286.4" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="45.2" y="286.4" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text> <text x="45.2" y="281.6" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text>
<text x="45.2" y="294.8" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">2 Pl.</text>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

+22 -18
View File
@@ -1,26 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="331.6" height="90.4" viewBox="0 0 331.6 90.4"> <svg xmlns="http://www.w3.org/2000/svg" width="331.6" height="90.4" viewBox="0 0 331.6 90.4">
<rect width="100%" height="100%" fill="white"/> <rect width="100%" height="100%" fill="white"/>
<polyline points="45.2,45.2 125.6,45.2" fill="none" stroke="#e6194b" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="0.5"/> <polyline points="45.2,45.2 125.6,45.2" fill="none" stroke="#3cb44b" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="0.5"/>
<polyline points="206,45.2 286.4,45.2" fill="none" stroke="#3cb44b" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="0.5"/> <polyline points="206,45.2 286.4,45.2" fill="none" stroke="#e6194b" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="0.5"/>
<circle cx="45.2" cy="45.2" r="35.2" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="45.2" cy="45.2" r="35.2" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="45.2" cy="32" r="12" fill="#e6194b" stroke="black" stroke-width="1"/> <circle class="person" data-gid="2" data-gruppe="Gruppe 2" data-name="Vorname8 Nachname8" cx="45.2" cy="32" r="12" fill="#3cb44b" stroke="black" stroke-width="1"><title>Vorname8 Nachname8 — Gruppe 2</title></circle>
<circle cx="45.2" cy="58.4" r="12" fill="#e6194b" stroke="black" stroke-width="1"/> <circle class="person" data-gid="2" data-gruppe="Gruppe 2" data-name="Vorname5 Nachname5" cx="45.2" cy="58.4" r="12" fill="#3cb44b" stroke="black" stroke-width="1"><title>Vorname5 Nachname5 — Gruppe 2</title></circle>
<circle cx="45.2" cy="45.2" r="12" fill="white" fill-opacity="0.75"/> <ellipse cx="45.2" cy="45.2" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="45.2" y="45.2" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text> <text x="45.2" y="40.4" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text>
<text x="45.2" y="53.6" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">2 Pl.</text>
<circle cx="125.6" cy="45.2" r="35.2" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="125.6" cy="45.2" r="35.2" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="125.6" cy="32" r="12" fill="#e6194b" stroke="black" stroke-width="1"/> <circle class="person" data-gid="2" data-gruppe="Gruppe 2" data-name="Vorname6 Nachname6" cx="125.6" cy="32" r="12" fill="#3cb44b" stroke="black" stroke-width="1"><title>Vorname6 Nachname6 — Gruppe 2</title></circle>
<circle cx="125.6" cy="58.4" r="12" fill="#e6194b" stroke="black" stroke-width="1"/> <circle class="person" data-gid="2" data-gruppe="Gruppe 2" data-name="Vorname7 Nachname7" cx="125.6" cy="58.4" r="12" fill="#3cb44b" stroke="black" stroke-width="1"><title>Vorname7 Nachname7 — Gruppe 2</title></circle>
<circle cx="125.6" cy="45.2" r="12" fill="white" fill-opacity="0.75"/> <ellipse cx="125.6" cy="45.2" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="125.6" y="45.2" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text> <text x="125.6" y="40.4" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text>
<text x="125.6" y="53.6" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">2 Pl.</text>
<circle cx="206" cy="45.2" r="35.2" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="206" cy="45.2" r="35.2" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="206" cy="32" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/> <circle class="person" data-gid="1" data-gruppe="Gruppe 1" data-name="Vorname3 Nachname3" cx="206" cy="32" r="12" fill="#e6194b" stroke="black" stroke-width="1"><title>Vorname3 Nachname3 — Gruppe 1</title></circle>
<circle cx="206" cy="58.4" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/> <circle class="person" data-gid="1" data-gruppe="Gruppe 1" data-name="Vorname4 Nachname4" cx="206" cy="58.4" r="12" fill="#e6194b" stroke="black" stroke-width="1"><title>Vorname4 Nachname4 — Gruppe 1</title></circle>
<circle cx="206" cy="45.2" r="12" fill="white" fill-opacity="0.75"/> <ellipse cx="206" cy="45.2" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="206" y="45.2" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text> <text x="206" y="40.4" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text>
<text x="206" y="53.6" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">2 Pl.</text>
<circle cx="286.4" cy="45.2" r="35.2" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="286.4" cy="45.2" r="35.2" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="286.4" cy="32" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/> <circle class="person" data-gid="1" data-gruppe="Gruppe 1" data-name="Vorname1 Nachname1" cx="286.4" cy="32" r="12" fill="#e6194b" stroke="black" stroke-width="1"><title>Vorname1 Nachname1 — Gruppe 1</title></circle>
<circle cx="286.4" cy="58.4" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/> <circle class="person" data-gid="1" data-gruppe="Gruppe 1" data-name="Vorname2 Nachname2" cx="286.4" cy="58.4" r="12" fill="#e6194b" stroke="black" stroke-width="1"><title>Vorname2 Nachname2 — Gruppe 1</title></circle>
<circle cx="286.4" cy="45.2" r="12" fill="white" fill-opacity="0.75"/> <ellipse cx="286.4" cy="45.2" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="286.4" y="45.2" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text> <text x="286.4" y="40.4" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">0</text>
<text x="286.4" y="53.6" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">2 Pl.</text>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

+56 -21
View File
@@ -160,10 +160,17 @@ Die folgenden Grundsatzfragen sind entschieden und gelten für alle Meilensteine
- [x] Python 2 → 3 Migration (bereits erledigt) - [x] Python 2 → 3 Migration (bereits erledigt)
- [x] Unittest-Suite mit Kernszenarien (bereits erledigt) - [x] Unittest-Suite mit Kernszenarien (bereits erledigt)
- [ ] `Farm` erweitern: `TopN()` statt nur `Bester()` — Grundlage für "mehrere Varianten" - [x] `Farm` erweitern: `TopN()` statt nur `Bester()` — Grundlage für "mehrere Varianten"
später. Kleine, risikoarme Änderung am bestehenden Code. später. Umgesetzt in `libs/ga.py` (`Farm.TopN(n)`: die `n` besten Lösungen absteigend,
- [ ] Determinismus-Option: `random.seed()` als Parameter durchreichen, damit ein Ergebnis geclamped auf `[0, len(Pool)]`).
bei Bedarf reproduzierbar ist (Support-Anfragen: "warum sitzt Tante Erna da?") - [x] Determinismus-Option: `random.seed()` als Parameter durchreichen, damit ein Ergebnis
bei Bedarf reproduzierbar ist (Support-Anfragen: "warum sitzt Tante Erna da?").
Umgesetzt als `--seed <int>` in `libs/platz.py`. **Wichtig:** der RNG-Seed allein
reichte nicht — `Person` hasht im `set()` einer `Gruppe` sonst über `id()`
(Speicheradresse), wodurch `set.pop()`-Reihenfolge in `Gruppe.teilen()` pro Prozess
variierte. Behoben durch Id-basiertes `__hash__`/`__eq__` an `Person`
(`libs/Strukturdaten.py`); Integer-Ids sind zudem `PYTHONHASHSEED`-unabhängig. Auf
`work/hochzeit` verifiziert: gleicher Seed → bytegleicher Plan, anderer Seed → abweichend.
- [x] Rechtsform geklärt: Betrieb über die bestehende **MiSta GmbH** (Impressum), keine - [x] Rechtsform geklärt: Betrieb über die bestehende **MiSta GmbH** (Impressum), keine
Neugründung — Ausgründung aus der Holding erst bei Erfolg (Konzeptentscheidung Nr. 7) Neugründung — Ausgründung aus der Holding erst bei Erfolg (Konzeptentscheidung Nr. 7)
- [x] Namensfrage geklärt: **"Sitz & Platz"** für Deutschland, **Sitzwunder/SeatWonder** - [x] Namensfrage geklärt: **"Sitz & Platz"** für Deutschland, **Sitzwunder/SeatWonder**
@@ -201,11 +208,22 @@ Session-basiert, nichts wird dauerhaft gespeichert (schont Datenschutz-Aufwand i
- [x] Einfache Browser-Testoberfläche (`web/static/index.html`): Tisch-Tabelle mit - [x] Einfache Browser-Testoberfläche (`web/static/index.html`): Tisch-Tabelle mit
Presets, CSV-Textfeld/-Upload, Berechnen-Button, Kennzahlen + SVG-Anzeige — Presets, CSV-Textfeld/-Upload, Berechnen-Button, Kennzahlen + SVG-Anzeige —
Zwischenschritt, wird durch den Konva-Tisch-Editor (unten) abgelöst Zwischenschritt, wird durch den Konva-Tisch-Editor (unten) abgelöst
- [ ] **Interaktiver Tisch-Editor** (Frontend, React/Vue + SVG): - [x] **Interaktiver Tisch-Editor** (Frontend): Kreise per Drag & Drop platzieren,
Kreise per Drag & Drop platzieren, Kapazität einstellen, Nachbarschaft automatisch Kapazität einstellen (+//Direkteingabe), Tische hinzufügen/löschen, Nachbarschaft
aus räumlicher Nähe ableiten (statt manueller `Nachbarliste`-Pflege in `tische.ini`) live aus räumlicher Nähe abgeleitet (gleiche Radius-Logik wie `_NachbarnAbleiten`
im Backend, Radius per Slider). Umgesetzt als `web/static/editor.html`
**buildfrei, Inline-SVG + Vanilla-JS** statt React/Konva, weil das bestehende
Frontend keine Build-Toolchain (npm/package.json) hat; das State-Modell
(`{id, plaetze, x, y}`) ist dasselbe wie für eine spätere Konva-Portierung.
Backend um `GET /sitzung/{id}/tische` (Layout-Round-Trip) ergänzt, Session wird
per `localStorage` mit der Testoberfläche geteilt. Nebenbei behoben: fehlender
`import configparser` in `web/main.py` (der `/tische-datei`-Upload wäre sonst mit
`NameError` abgestürzt).
- Baut direkt auf `alsSVG()`-Geometrie auf (Radius-Berechnung ist bereits da) - Baut direkt auf `alsSVG()`-Geometrie auf (Radius-Berechnung ist bereits da)
- [ ] Undo/Redo, "Variante neu berechnen"-Button - [x] **Undo/Redo** im Editor: Snapshot-History (Stapel je Vor-Zustand von `state.tische`),
ein Drag zählt als ein Schritt; Tastatur `Strg+Z` / `Strg+Y` (bzw. `Strg+Shift+Z`),
`Entf` löscht den ausgewählten Tisch. "Variante neu berechnen" liegt bereits als
wiederholter `POST .../berechnen` in der Testoberfläche vor (jeder Klick = neue Variante).
- [ ] Hosting: einfacher Single-Server-Betrieb bei **Hetzner** reicht (Konzeptentscheidung - [ ] Hosting: einfacher Single-Server-Betrieb bei **Hetzner** reicht (Konzeptentscheidung
Nr. 6 — kein Kubernetes-Overkill für MVP) Nr. 6 — kein Kubernetes-Overkill für MVP)
@@ -225,15 +243,28 @@ verarbeitet werden (was bei jedem Webserver der Fall ist).
**Ziel:** Nutzer bekommt mehrere Vorschläge statt einer festen Lösung, kann vergleichen. **Ziel:** Nutzer bekommt mehrere Vorschläge statt einer festen Lösung, kann vergleichen.
- [ ] `Farm.TopN(n)` nutzen, um z.B. 35 unterschiedliche gute Lösungen zurückzugeben - [x] `Farm.TopN(n)` nutzen, um z.B. 35 unterschiedliche gute Lösungen zurückzugeben:
(ggf. mit verschiedenen Zufalls-Seeds parallel starten für Diversität) `POST /berechnen?varianten=N` (15, Default 3) nimmt `TopN` über den ganzen Endpool
- [ ] Vergleichsansicht im Frontend: Varianten nebeneinander, Kennzahlen sichtbar machen und dedupliziert über eine Sitzordnungs-Signatur (`frozenset` aus Tisch-Id ×
(Wertigkeit, Anzahl Gruppentrennungen, "Alleine sitzende Personen") Personen-Ids), damit Mutations-Verwandte mit identischer Sitzordnung nicht als
- [ ] Performance: bei sehr großen Sälen (200+ Personen) ggf. `Zyklus`-Parameter "Varianten" zählen. Liefert der Pool weniger unterschiedliche Sitzordnungen, kommen
(Anzahl Generationen/Population) an Problemgröße koppeln, damit Antwortzeit weniger zurück; ein weiterer Berechnen-Klick startet einen frischen Lauf.
im Web-Kontext (Sekunden, nicht Minuten) bleibt — Lasttest nötig Seed-parallele Läufe für noch mehr Diversität ("ggf.") waren nicht nötig
- [ ] Optional: Hintergrund-Job-Queue (z.B. Celery/RQ), falls Berechnung >5s dauert, ein Lauf liefert im Test bereits 3 paarweise verschiedene Varianten.
damit der Webserver nicht blockiert `GET /ergebnis.svg?variante=k` rendert jede Variante einzeln.
- [x] Vergleichsansicht im Frontend: Varianten-Karten nebeneinander mit Kennzahlen
(Wertigkeit, getrennte Gruppen + Teilungen gesamt, allein sitzende Personen —
letzteres via `LeuteAllein()`, zählt nur Personen aus mehrköpfigen Gruppen ohne
Gruppenmitglied am Tisch); Klick auf eine Karte schaltet Tische-/Gruppen-Tabellen
und den SVG-Raumplan auf die Variante um.
- [x] Performance: Lasttest erledigt (2026-07-12) — `work/innenhoefe` (300 Gäste,
88 Tische) rechnet mit dem **Adaptiv**-Profil (Web-Default) in ~1,71,9 s
(57 Generationen, inkl. Python-Start), Easy in ~0,3 s. Beides weit unter der
5-s-Schwelle → `Zyklus`-Parameter-Kopplung an die Problemgröße ist **nicht nötig**;
erst wieder prüfen, falls Zyklen deutlich vergrößert werden (siehe Risiko Nr. 2).
- [x] Optional: Hintergrund-Job-Queue (z.B. Celery/RQ), falls Berechnung >5s dauert —
**entfällt nach dem Lasttest** (s.o.): Adaptiv bleibt bei ~2 s, der Webserver
blockiert nicht spürbar. Entscheidung dokumentiert, bei Bedarf reaktivierbar.
**Tech-Debt / Modernisierung (Code-Review 2026-07-11):** Beim Umbau bereits erledigt sind **Tech-Debt / Modernisierung (Code-Review 2026-07-11):** Beim Umbau bereits erledigt sind
`eval()``ast.literal_eval` (bzw. ein sicherer Mini-Auswerter für die String-Ausdrücke `eval()``ast.literal_eval` (bzw. ein sicherer Mini-Auswerter für die String-Ausdrücke
@@ -331,10 +362,14 @@ parallel anlaufen — eher ~44,5 Monate bis M4-Abschluss.
nicht erst kurz vor Launch. nicht erst kurz vor Launch.
2. **GA-Performance bei großen Sälen** — erster Datenpunkt (2026-07-11): das Beispiel 2. **GA-Performance bei großen Sälen** — erster Datenpunkt (2026-07-11): das Beispiel
`work/innenhoefe` mit 300 Gästen an 88 Tischen rechnet mit dem Easy-Zyklus in ~0,4 s `work/innenhoefe` mit 300 Gästen an 88 Tischen rechnet mit dem Easy-Zyklus in ~0,4 s
durch — weit unter der 5-s-Schwelle, ab der M2 eine Job-Queue vorsieht. Offen bleibt durch — weit unter der 5-s-Schwelle, ab der M2 eine Job-Queue vorsieht. Zweiter
der Test mit größeren Zyklen (mehr Generationen für bessere Lösungsqualität bei Datenpunkt (2026-07-12, M2-Lasttest): dasselbe Beispiel mit dem **Adaptiv**-Profil
vielen Trennungen) — die Lösungsgüte bei 4er-Tischen mit großen Gruppen (Wertigkeit (Web-Default) braucht ~1,71,9 s (57 Generationen, 3 Seeds, inkl. Python-Start) —
384) legt nahe, dass hier eher mehr GA-Iterationen nötig sind als bisher. Job-Queue und Parameter-Kopplung bleiben unnötig. Weiter offen ist nur die
Lösungsgüte-Frage: bei 4er-Tischen mit großen Gruppen (Wertigkeit ~560) legen die
vielen Trennungen nahe, dass mehr GA-Iterationen (größere `Geduld`/`Start`-Werte)
bessere Pläne liefern könnten — das würde die Laufzeit dann wieder Richtung
5-s-Schwelle schieben und wäre neu zu messen.
3. **Wettbewerb ist real und etabliert** — siehe Abschnitt "Marktübersicht" oben. 3. **Wettbewerb ist real und etabliert** — siehe Abschnitt "Marktübersicht" oben.
PerfectTablePlan verfolgt seit Jahren denselben GA-Ansatz, allerdings als Desktop-Tool. PerfectTablePlan verfolgt seit Jahren denselben GA-Ansatz, allerdings als Desktop-Tool.
Differenzierung muss über Web-nativ + DSGVO-Hosting + detailliertere Regeln Differenzierung muss über Web-nativ + DSGVO-Hosting + detailliertere Regeln
+14 -3
View File
@@ -84,6 +84,11 @@ class CSVConfig:
VIPGruppe = Gruppe( 0 ) VIPGruppe = Gruppe( 0 )
VipHash = {} VipHash = {}
GruppenNamen = {} GruppenNamen = {}
# fest platzierte ("fixierte") Gruppen fuer die Anzeige: Name ->
# {'tisch': Tischnummer, 'anzahl': Personenzahl}. VIPs laufen nicht
# durch die GA-Platzierung, sollen in der Gaesteliste aber sichtbar
# (grau hinterlegt) erscheinen.
FixierteGruppen = {}
# Gruppen entstehen beim ersten Auftreten ihres Namens; # Gruppen entstehen beim ersten Auftreten ihres Namens;
# Einzelpersonen (leerer Gruppenname) bekommen eine eigene Gruppe # Einzelpersonen (leerer Gruppenname) bekommen eine eigene Gruppe
@@ -126,9 +131,13 @@ class CSVConfig:
PID = PID + 1 PID = PID + 1
P = Person( PID, Vorname, Nachname, Titel ) P = Person( PID, Vorname, Nachname, Titel )
if TischNr is not None: if TischNr is not None:
# VIP: fester Tisch, keine GA-Platzierung # fixiert: fester Tisch, keine GA-Platzierung
VipHash[ PID ] = TischNr VipHash[ PID ] = TischNr
VIPGruppe.Person_dazu( P ) VIPGruppe.Person_dazu( P )
Name = GruppenName if GruppenName else 'Fixiert Tisch %d' % TischNr
Eintrag = FixierteGruppen.setdefault(
Name, { 'tisch': TischNr, 'anzahl': 0 } )
Eintrag['anzahl'] = Eintrag['anzahl'] + 1
else: else:
PN.PersonAdd( P ) PN.PersonAdd( P )
if GruppenName == '': if GruppenName == '':
@@ -155,7 +164,7 @@ class CSVConfig:
if G.Anzahl() > 0: if G.Anzahl() > 0:
GN.Gruppe_dazu( G ) GN.Gruppe_dazu( G )
return [ PN, GN, VIPGruppe, VipHash, GruppenNamen ] return [ PN, GN, VIPGruppe, VipHash, GruppenNamen, FixierteGruppen ]
def laden(self, FileName): def laden(self, FileName):
"""lese alle Eingangsdaten aus einer CSV-Datei ein""" """lese alle Eingangsdaten aus einer CSV-Datei ein"""
@@ -179,12 +188,14 @@ Einzel;Gast;;;;
""" """
print("\n-- Parse Beispiel-CSV:") print("\n-- Parse Beispiel-CSV:")
C = CSVConfig() C = CSVConfig()
[ PN, GN, VIPGruppe, VipHash, GruppenNamen ] = C.HandleGaesteliste( Beispiel ) [ PN, GN, VIPGruppe, VipHash, GruppenNamen, FixierteGruppen ] = \
C.HandleGaesteliste( Beispiel )
print(PN) print(PN)
print(GN) print(GN)
print(VIPGruppe) print(VIPGruppe)
print(VipHash) print(VipHash)
print(GruppenNamen) print(GruppenNamen)
print(FixierteGruppen)
else: else:
pass pass
+165
View File
@@ -0,0 +1,165 @@
"""
Farbschema fuer die SVG-Ausgabe (Sitzplatzverteilung.alsSVG).
Laedt ein Farbprofil aus cfg/farben.cfg und ordnet jeder Gruppe eine Farbe zu.
Zwei Modi (siehe cfg/farben.cfg fuer Details):
- 'palette': eine Farbliste, zyklisch je Gruppe (nach Gruppen-Id sortiert)
- 'kategorien': trennt nach Art (Hochzeit) in Familie / Verein / VIP und
faerbt sie ueber je einen Farbverlauf ein.
Waehlbar per --farben <Sektion> (libs/platz.py) bzw. PLATZ_FARBENART (web).
"""
__author__ = "Michael Stangl"
__copyright__ = "Copyright (c) 2026 Michael Stangl"
__license__ = "Python"
import configparser
import os
from collections import Counter, defaultdict
def _hex_zu_rgb(h):
h = h.strip().lstrip('#')
return tuple( int(h[i:i+2], 16) for i in (0, 2, 4) )
def _rgb_zu_hex(rgb):
return '#%02x%02x%02x' % tuple( max(0, min(255, int(round(c)))) for c in rgb )
def _verlauf(start, ende, t):
"""Farbe im linearen RGB-Verlauf start->ende an Position t in [0,1]"""
a, b = _hex_zu_rgb(start), _hex_zu_rgb(ende)
return _rgb_zu_hex( tuple( a[i] + (b[i] - a[i]) * t for i in range(3) ) )
def _verlauf_liste(start, ende, n):
"""n Farben gleichmaessig ueber den Verlauf start->ende (n>=1)"""
if n <= 1:
return [ _verlauf(start, ende, 0.0) ]
return [ _verlauf(start, ende, j / (n - 1)) for j in range(n) ]
class Farbschema:
"""ordnet Gruppen Farben zu, gesteuert durch ein Profil aus farben.cfg"""
# Rueckfall-Palette, falls keine Config / kein gueltiges Profil geladen wurde
Standard = [
'#e6194b', '#3cb44b', '#4363d8', '#f58231', '#911eb4',
'#42d4f4', '#f032e6', '#bfef45', '#fabed4', '#469990',
'#dcbeff', '#9a6324', '#800000', '#aaffc3', '#000075' ]
def __init__(self):
self.Modus = 'palette'
self.Palette = list(self.Standard)
self.FamilienVerlaeufe = [ ('#1f4e9c', '#2fae5f'), ('#f2c200', '#e8590c') ]
self.VereinVerlauf = ('#7b2fbf', '#9aa0a6')
self.VIPVerlauf = ('#e63946', '#8b0000')
def laden(self, FileName, Sektion='grosse_gruppen'):
config = configparser.ConfigParser()
config.read( os.path.expanduser(FileName) )
if not config.has_section( Sektion ):
raise ValueError(
"Farbprofil '%s' nicht in %s gefunden (vorhanden: %s)"
% ( Sektion, FileName, ', '.join(config.sections()) or '-' ) )
self.Modus = config.get( Sektion, 'Modus', fallback='palette' ).strip()
if config.has_option( Sektion, 'Palette' ):
self.Palette = self._farbliste( config.get( Sektion, 'Palette' ) )
if config.has_option( Sektion, 'FamilienVerlaeufe' ):
self.FamilienVerlaeufe = self._verlaeufe(
config.get( Sektion, 'FamilienVerlaeufe' ) )
if config.has_option( Sektion, 'VereinVerlauf' ):
self.VereinVerlauf = self._verlaeufe( config.get( Sektion, 'VereinVerlauf' ) )[0]
if config.has_option( Sektion, 'VIPVerlauf' ):
self.VIPVerlauf = self._verlaeufe( config.get( Sektion, 'VIPVerlauf' ) )[0]
return self
@staticmethod
def _farbliste(text):
return [ f.strip() for f in text.replace('\n', ',').split(',') if f.strip() ]
@staticmethod
def _verlaeufe(text):
"""'A -> B, C -> D' -> [(A,B),(C,D)]; ein einzelner Wert wird zu (v,v)"""
ergebnis = []
for teil in text.replace('\n', ',').split(','):
teil = teil.strip()
if not teil:
continue
if '->' in teil:
a, b = teil.split('->', 1)
ergebnis.append( (a.strip(), b.strip()) )
else:
ergebnis.append( (teil, teil) )
return ergebnis or [ ('#888888', '#888888') ]
def farben(self, Gruppen):
"""ordnet den Gruppen Farben zu.
Rueckgabe: (GidZuFarbe {Gruppen-Id: hexfarbe}, VIPFarbe hexfarbe).
VIPFarbe gilt fuer Personen ohne GA-Gruppe (feste Platzierung)."""
GruppenListe = sorted( Gruppen, key=lambda g: g.Id )
if self.Modus == 'kategorien':
return self._kategorien( GruppenListe )
return self._palette( GruppenListe )
def _palette(self, GruppenListe):
pal = self.Palette or self.Standard
GidZuFarbe = { G.Id: pal[i % len(pal)] for i, G in enumerate(GruppenListe) }
return GidZuFarbe, '#888888'
@staticmethod
def _nachname(G):
"""dominanter Nachname der Gruppe, wenn ihn die Mehrheit traegt (bei
>= 2 Mitgliedern) - sonst None (dann gilt die Gruppe als Verein/
gemischt). Anonyme Sammelbuchungen (alle Mitglieder derselbe Name,
z.B. 13x 'Gast Musikverein') sind keine Familie, sondern gelten als
Verein - daher werden mindestens zwei VERSCHIEDENE Personen verlangt."""
personen = list( G )
if len(personen) < 2:
return None
if len({ (P._Vorname, P._Name) for P in personen }) < 2:
return None # anonymer Block (alle identisch) -> kein Familienname
namen = [ P._Name for P in personen ]
name, anzahl = Counter(namen).most_common(1)[0]
return name if anzahl * 2 > len(namen) else None
def _kategorien(self, GruppenListe):
# 1. klassifizieren: Familien (nach Nachname) vs. Vereine
familien = defaultdict(list) # Nachname -> [Gruppen]
vereine = []
for G in GruppenListe:
nn = self._nachname( G )
if nn is not None:
familien[nn].append( G )
else:
vereine.append( G )
GidZuFarbe = {}
# 2. Familien: jeder Nachname kommt (alphabetisch, abwechselnd) in einen
# Farbbereich - Blau->Gruen ODER Gelb->Orange. Innerhalb eines
# Bereichs werden ALLE zugehoerigen Familiengruppen ueber den Verlauf
# gespreizt, damit verschiedene Familien verschiedene Toene haben;
# Gruppen desselben Nachnamens bleiben benachbart (ein zusammen-
# haengendes Band). So laeuft z.B. eine mehrteilige Familie Brandt
# ueber benachbarte Gelb->Orange-Toene, waehrend Familie Peters einen
# anderen Blau->Gruen-Ton bekommt.
Nachnamen = sorted( familien )
Bereich = { nn: i % len(self.FamilienVerlaeufe)
for i, nn in enumerate(Nachnamen) }
GruppenImBereich = defaultdict(list)
for nn in Nachnamen:
for G in sorted( familien[nn], key=lambda g: g.Id ):
GruppenImBereich[ Bereich[nn] ].append( G )
for b, gruppen in GruppenImBereich.items():
start, ende = self.FamilienVerlaeufe[b]
for farbe, G in zip( _verlauf_liste(start, ende, len(gruppen)), gruppen ):
GidZuFarbe[G.Id] = farbe
# 3. Vereine: ein Verlauf (z.B. Violett -> Grau) ueber alle Vereine
vstart, vende = self.VereinVerlauf
for farbe, G in zip( _verlauf_liste(vstart, vende, len(vereine)),
sorted(vereine, key=lambda g: g.Id) ):
GidZuFarbe[G.Id] = farbe
# 4. VIP-Farbe: Startfarbe des VIP-Verlaufs (i.d.R. Rot)
return GidZuFarbe, self.VIPVerlauf[0]
+156 -35
View File
@@ -14,6 +14,8 @@ from random import *
import ast import ast
import configparser, os import configparser, os
import copy import copy
import hashlib
import html
import math import math
from collections import defaultdict from collections import defaultdict
from functools import total_ordering from functools import total_ordering
@@ -30,6 +32,16 @@ class Person:
def __repr__(self): def __repr__(self):
return ' Person %s: "%s %s %s"' % ( self.Id, self._Titel, return ' Person %s: "%s %s %s"' % ( self.Id, self._Titel,
self._Vorname, self._Name) self._Vorname, self._Name)
def __hash__(self):
# stabil ueber die (eindeutige, fortlaufende) Id hashen statt ueber
# die Objekt-Identitaet: sonst haengt die Iterations-/pop()-Reihenfolge
# der set() aus Person-Objekten (Gruppe._Personen) an der Speicher-
# adresse und variiert pro Prozesslauf - das machte selbst mit --seed
# den GA-Lauf nichtreproduzierbar. Integer-Ids sind zudem nicht von
# PYTHONHASHSEED betroffen, daher prozessstabil.
return hash( self.Id )
def __eq__(self, other):
return isinstance( other, Person ) and self.Id == other.Id
@total_ordering @total_ordering
class Gruppe: class Gruppe:
@@ -427,21 +439,45 @@ class Strafliste:
return self.gibPunkte('Trennung',Gruppengroesse-1, N_Teilungen) return self.gibPunkte('Trennung',Gruppengroesse-1, N_Teilungen)
else: else:
raise IndexError("Bezeichner gibts nicht") raise IndexError("Bezeichner gibts nicht")
def laden( self, FileName ): def laden( self, FileName, Sektion='default' ):
print("-- Strafliste laden") """laedt ein Strafpunkte-Profil aus einer Sektion der strafen.cfg.
Jede Sektion ist ein vollstaendiges Bewertungs-'Vorgehen' mit allen
Angaben in einem gemeinsamen Namensraum. Der Aufrufer waehlt das
Profil ueber 'Sektion' (Vorgabe 'default'); so lassen sich mehrere
Bewertungsstrategien in derselben Datei pflegen. Die Trennungs-
Straffen stehen unter den Schluesseln 'Anzahl_Trennungen_N'."""
print("-- Strafliste laden (Profil '%s')" % Sektion)
config = configparser.ConfigParser() config = configparser.ConfigParser()
config.read( os.path.expanduser(FileName) ) config.read( os.path.expanduser(FileName) )
if not config.has_section( Sektion ):
raise ValueError(
"Strafprofil '%s' nicht in %s gefunden (vorhanden: %s)"
% ( Sektion, FileName, ', '.join(config.sections()) or '-' ) )
# ast.literal_eval statt eval: die Werte sind reine Literale # ast.literal_eval statt eval: die Werte sind reine Literale
# (Zahlen und Dicts wie {2:-10}), also kein Code noetig. # (Zahlen und Dicts wie {2:-10}), also kein Code noetig.
self.NichtNachbar = ast.literal_eval(config.get( 'Globals', 'NichtNachbar' )) self.NichtNachbar = ast.literal_eval(config.get( Sektion, 'NichtNachbar' ))
self.Allein = ast.literal_eval(config.get( 'Globals', 'Allein' )) self.Allein = ast.literal_eval(config.get( Sektion, 'Allein' ))
self.TischWert = ast.literal_eval( config.get( 'Globals', 'TischWertigkeiten' ) ) # TischWertigkeiten ist optional; fehlt der Schluessel, werden freie
# Abschnitt [Abstand] ist optional; fehlt er, wird der Abstand # Plaetze gar nicht bestraft (leeres Dict -> gibPunkte('Tischbesetzung')
# getrennter Gruppen nicht bestraft (Faktor 0). # gibt 0), wodurch mehr Teilbelegungen moeglich sind.
if config.has_section( 'Abstand' ): if config.has_option( Sektion, 'TischWertigkeiten' ):
self.AbstandFaktor = ast.literal_eval(config.get( 'Abstand', 'Faktor' )) self.TischWert = ast.literal_eval( config.get( Sektion, 'TischWertigkeiten' ) )
for (k,v) in config.items( 'Trennung' ): else:
self.GruppenTrennen[int(k)] = ast.literal_eval(v) self.TischWert = {}
# AbstandFaktor ist optional; fehlt er, wird der Abstand getrennter
# Gruppen nicht bestraft (Faktor 0).
if config.has_option( Sektion, 'AbstandFaktor' ):
self.AbstandFaktor = ast.literal_eval(config.get( Sektion, 'AbstandFaktor' ))
# Trennungs-Straffen: Schluessel 'Anzahl_Trennungen_N' -> N Trennungen.
# frisches Dict, damit nicht der (mutable) Konstruktor-Default geteilt
# wird und Reste eines frueheren laden() bleiben.
self.GruppenTrennen = {}
for (k, v) in config.items( Sektion ):
# configparser liefert Schluessel klein geschrieben
if k.startswith( 'anzahl_trennungen_' ):
N = int( k.rsplit( '_', 1 )[-1] )
self.GruppenTrennen[N] = ast.literal_eval(v)
# Sitzplatzverteilung, bestehend aus den Einzelelementen # Sitzplatzverteilung, bestehend aus den Einzelelementen
@@ -571,7 +607,8 @@ class Sitzplatzverteilung:
'#42d4f4', '#f032e6', '#bfef45', '#fabed4', '#469990', '#42d4f4', '#f032e6', '#bfef45', '#fabed4', '#469990',
'#dcbeff', '#9a6324', '#800000', '#aaffc3', '#000075' ] '#dcbeff', '#9a6324', '#800000', '#aaffc3', '#000075' ]
def alsSVG(self, OutputSVG, PersonenRadius=12, Puffer=10, Verbindungen=True): def alsSVG(self, OutputSVG, PersonenRadius=12, Puffer=10, Verbindungen=True,
GruppenNamen=None, Farbschema=None):
"""Zeichnet die Sitzplatzverteilung als SVG: """Zeichnet die Sitzplatzverteilung als SVG:
Tische werden als weisse Kreise dargestellt, Personen als Tische werden als weisse Kreise dargestellt, Personen als
@@ -583,7 +620,24 @@ class Sitzplatzverteilung:
Ist Verbindungen=True (Vorgabe), wird jede ueber mehrere Tische Ist Verbindungen=True (Vorgabe), wird jede ueber mehrere Tische
getrennte Gruppe zusaetzlich mit einer Linie in ihrer Gruppenfarbe getrennte Gruppe zusaetzlich mit einer Linie in ihrer Gruppenfarbe
verbunden, so dass die Zusammengehoerigkeit sichtbar bleibt. verbunden, so dass die Zusammengehoerigkeit sichtbar bleibt.
Jeder Personenkreis bekommt ein <title>-Kind (nativer Browser-
Tooltip beim Hover: "Vorname Nachname — Gruppe") sowie die Attribute
class="person" und data-gruppe/data-gid, damit eine einbettende
Seite darauf ein Hover-/Kasten-Verhalten aufsetzen kann. Optional
liefert GruppenNamen ({Gid: Anzeigename}) die lesbaren Gruppennamen;
fehlt es, wird "Gruppe <Id>" verwendet.
""" """
GruppenNamen = GruppenNamen or {}
def GruppenName(G):
if G is None:
return 'fixiert'
return GruppenNamen.get( G.Id, 'Gruppe %s' % G.Id )
def PersonName(P):
Teile = [ t for t in (P._Titel, P._Vorname, P._Name) if t ]
return ' '.join( Teile )
# Tischradius je Tisch berechnen: gross genug, damit alle # Tischradius je Tisch berechnen: gross genug, damit alle
# Personenkreise (auf einem inneren Kreis gleichmaessig verteilt) # Personenkreise (auf einem inneren Kreis gleichmaessig verteilt)
# nebeneinander Platz haben, ohne sich zu beruehren. Der Faktor # nebeneinander Platz haben, ohne sich zu beruehren. Der Faktor
@@ -631,20 +685,29 @@ class Sitzplatzverteilung:
except KeyError: except KeyError:
return None return None
GidZuFarbe = {} # Feste Gruppenfarben: einmal fuer die vollstaendige Gruppenliste (nach
# Gruppen-Id) vergeben - NICHT lazy nach der Sitz-Reihenfolge. Da alle
# Varianten dieselbe Gruppenmenge mit denselben Ids teilen, hat so jede
# Gruppe in jeder Variante (und ueber Laeufe hinweg) dieselbe Farbe.
# Mit Farbschema (aus farben.cfg) kommen die Farben von dort (z.B. nach
# Familie/Verein/VIP getrennt); ohne dient die eingebaute Palette als
# Rueckfall (zyklisch je Gruppe).
if Farbschema is not None:
GidZuFarbe, VIPFarbe = Farbschema.farben( self.Gruppen )
else:
GidZuFarbe = {}
for Index, G in enumerate( sorted( self.Gruppen, key=lambda g: g.Id ) ):
GidZuFarbe[G.Id] = self.SVGGruppenFarben[
Index % len(self.SVGGruppenFarben) ]
VIPFarbe = '#888888'
def FarbeVonGruppe(G): def FarbeVonGruppe(G):
if G is None: if G is None:
return '#888888' return VIPFarbe # VIP / feste Platzierung (ohne GA-Gruppe)
if G.Id not in GidZuFarbe: return GidZuFarbe.get( G.Id, VIPFarbe )
Index = len(GidZuFarbe) % len(self.SVGGruppenFarben)
GidZuFarbe[G.Id] = self.SVGGruppenFarben[Index]
return GidZuFarbe[G.Id]
# Fuer jede Gruppe pro Tisch den Mittelpunkt (Zentroid) ihrer # Fuer jede Gruppe pro Tisch den Mittelpunkt (Zentroid) ihrer
# an diesem Tisch sitzenden Personenkreise sammeln. Die Reihenfolge # an diesem Tisch sitzenden Personenkreise sammeln (fuer die
# der Iteration (Tische, darin Personen) stimmt mit der spaeteren # Verbindungslinien getrennter Gruppen).
# Zeichenschleife ueberein, damit die per FarbeVonGruppe() lazy
# vergebenen Farben konsistent sind.
GidZuTischZentroiden = {} GidZuTischZentroiden = {}
for T in self.Tische: for T in self.Tische:
Mx, My = TischMitte(T) Mx, My = TischMitte(T)
@@ -659,7 +722,6 @@ class Sitzplatzverteilung:
G = GruppeVonPerson(P) G = GruppeVonPerson(P)
if G is None: if G is None:
continue continue
FarbeVonGruppe(G) # Farbe frueh (aber in Zeichenreihenfolge) festlegen
sx, sy, cnt = GidZuSummen.get( G.Id, (0.0, 0.0, 0) ) sx, sy, cnt = GidZuSummen.get( G.Id, (0.0, 0.0, 0) )
GidZuSummen[G.Id] = (sx + Px, sy + Py, cnt + 1) GidZuSummen[G.Id] = (sx + Px, sy + Py, cnt + 1)
for Gid, (sx, sy, cnt) in GidZuSummen.items(): for Gid, (sx, sy, cnt) in GidZuSummen.items():
@@ -723,28 +785,49 @@ class Sitzplatzverteilung:
Winkel = 2 * math.pi * i / max(n, 1) - math.pi / 2 Winkel = 2 * math.pi * i / max(n, 1) - math.pi / 2
Px = Mx + SitzRadius * math.cos(Winkel) Px = Mx + SitzRadius * math.cos(Winkel)
Py = My + SitzRadius * math.sin(Winkel) Py = My + SitzRadius * math.sin(Winkel)
Farbe = FarbeVonGruppe( GruppeVonPerson(P) ) G = GruppeVonPerson(P)
Farbe = FarbeVonGruppe( G )
GName = GruppenName( G )
PName = PersonName( P )
# data-gid: -1 fuer VIPs/ohne Gruppe (keine self.Gruppen-Id)
Gid = G.Id if G is not None else -1
Teile.append( Teile.append(
'<circle cx="%g" cy="%g" r="%g" fill="%s" ' '<circle class="person" data-gid="%s" data-gruppe="%s" '
'stroke="black" stroke-width="1"/>\n' 'data-name="%s" cx="%g" cy="%g" r="%g" fill="%s" '
% (Px, Py, PersonenRadius, Farbe) ) 'stroke="black" stroke-width="1"><title>%s%s</title>'
'</circle>\n'
% ( Gid, html.escape(GName, quote=True),
html.escape(PName, quote=True),
Px, Py, PersonenRadius, Farbe,
html.escape(PName), html.escape(GName) ) )
# Tischnummer zentriert in die Tischmitte (nach den Personen- # Tischnummer und Platzzahl zentriert in die Tischmitte (nach den
# kreisen gezeichnet, damit sie oben liegt; ein halbtransparenter # Personenkreisen gezeichnet, damit sie oben liegen; eine halb-
# weisser Kreis darunter haelt sie auch ueber Personenkreisen # transparente weisse Ellipse darunter haelt beide Zeilen auch
# lesbar, falls die Tischmitte belegt sein sollte) # ueber Personenkreisen lesbar, falls die Tischmitte belegt ist).
# Obere Zeile: Tischnummer (gross/fett), darunter die Platzzahl.
Teile.append( Teile.append(
'<circle cx="%g" cy="%g" r="%g" fill="white" ' '<ellipse cx="%g" cy="%g" rx="%g" ry="%g" fill="white" '
'fill-opacity="0.75"/>\n' % (Mx, My, PersonenRadius) ) 'fill-opacity="0.75"/>\n'
% (Mx, My, PersonenRadius, PersonenRadius * 1.3) )
Teile.append( Teile.append(
'<text x="%g" y="%g" text-anchor="middle" ' '<text x="%g" y="%g" text-anchor="middle" '
'dominant-baseline="central" font-size="%g" ' 'dominant-baseline="central" font-size="%g" '
'font-weight="bold" fill="black">%s</text>\n' 'font-weight="bold" fill="black">%s</text>\n'
% (Mx, My, PersonenRadius * 1.1, T.Nummer) ) % (Mx, My - PersonenRadius * 0.4, PersonenRadius * 1.1, T.Nummer) )
Teile.append(
'<text x="%g" y="%g" text-anchor="middle" '
'dominant-baseline="central" font-size="%g" '
'fill="#333">%d Pl.</text>\n'
% (Mx, My + PersonenRadius * 0.7, PersonenRadius * 0.62, T.Plaetze) )
Teile.append( '</svg>\n' ) Teile.append( '</svg>\n' )
fout = open( OutputSVG, 'w' ) # als UTF-8 schreiben (die SVG deklariert encoding="UTF-8"): Namen
# enthalten Umlaute und der Gedankenstrich im <title> ist non-ASCII;
# ohne dies wuerde die Windows-Standardkodierung (cp1252) die Datei
# ungueltig machen.
fout = open( OutputSVG, 'w', encoding='utf-8' )
fout.writelines( Teile ) fout.writelines( Teile )
fout.close() fout.close()
@@ -1040,6 +1123,44 @@ class Sitzplatzverteilung:
return len( self.Gid_Tid[Gruppe.Id] ) - 1 return len( self.Gid_Tid[Gruppe.Id] ) - 1
except KeyError: except KeyError:
return 0 return 0
def getGruppenId(self):
"""eindeutige Id der Loesung auf GRUPPEN-Ebene (personen-unabhaengig).
Signatur: je Tisch, welche Gruppen mit wie vielen Mitgliedern dort
sitzen. Zwei Loesungen mit identischer Gruppen-Verteilung bekommen
dieselbe Id - egal welche konkreten Personen die geteilten Plaetze
einnehmen (die Teilung einer 5er-Gruppe auf die Tische 3 und 4 ist
dieselbe Sitzordnung, gleich welche Personen wohin kommen). Da die
Bewertung (Strafliste) nur von den Gruppen-Anzahlen je Tisch, den
Nachbarschaften und der Auslastung abhaengt, haben Loesungen mit
gleicher getGruppenId auch dieselbe Wertigkeit. Diese Id dient dem
Vergleich der Loesungen (Dedup), damit dieselbe Sitzordnung nicht
mehrfach als eigene Loesung gehalten und bewertet wird."""
Teile = []
for T in sorted( self.Tische, key=lambda t: t.Id ):
Zaehler = {}
for P in T:
try:
Gid = self.Gruppen.GruppeVonPid( P.Id ).Id
except KeyError:
Gid = -1 # VIP / feste Platzierung (ohne GA-Gruppe)
Zaehler[Gid] = Zaehler.get( Gid, 0 ) + 1
Teile.append( (T.Id, tuple(sorted( Zaehler.items() ))) )
return hashlib.sha1( repr(Teile).encode('utf-8') ).hexdigest()[:16]
def getPersonenId(self):
"""eindeutige Id der Loesung auf PERSONEN-Ebene.
Signatur: je Tisch die alphabetisch sortierten Personennamen.
Identifiziert WIRKLICH identische Sitzbelegungen (dieselben Personen
an denselben Tischen) - feiner als getGruppenId, das nur die Gruppen-
Verteilung vergleicht."""
Teile = []
for T in sorted( self.Tische, key=lambda t: t.Id ):
Namen = sorted(
' '.join( s for s in (P._Titel, P._Vorname, P._Name) if s )
for P in T )
Teile.append( (T.Id, tuple(Namen)) )
return hashlib.sha1( repr(Teile).encode('utf-8') ).hexdigest()[:16]
def VIPsSetzen(self, VIPListe, VIPs, Tische ): def VIPsSetzen(self, VIPListe, VIPs, Tische ):
"""setze die VIPs auf Ihre Plaetze""" """setze die VIPs auf Ihre Plaetze"""
#print " VIPsSetzen:" #print " VIPsSetzen:"
+41 -1
View File
@@ -61,6 +61,15 @@ class Loesung:
print(" lade Loesung " + repr(self.Id)) print(" lade Loesung " + repr(self.Id))
def speichern(self): def speichern(self):
print(" speichere Loesung " + repr(self.Id)) print(" speichere Loesung " + repr(self.Id))
def getGruppenId(self):
"""Id fuer den Dedup-Vergleich (Basis: jede Loesung eigenstaendig).
Unterklassen ueberladen dies mit einer inhaltlichen Signatur, so
dass gleiche Loesungen dieselbe Id bekommen und nicht mehrfach
gehalten werden."""
return id(self)
def getPersonenId(self):
"""feinere Id fuer wirklich identische Loesungen (Basis: eigenstaendig)"""
return id(self)
def __repr__(self): def __repr__(self):
return ' L '+ repr(self.Id) return ' L '+ repr(self.Id)
def __eq__(self,other): def __eq__(self,other):
@@ -493,6 +502,9 @@ class Farm:
self.Abstammung = Abstammung() self.Abstammung = Abstammung()
self._AbsZaehler = 0 # vergibt fortlaufende Loesungs-Ids 1..N self._AbsZaehler = 0 # vergibt fortlaufende Loesungs-Ids 1..N
self._Generation = 0 self._Generation = 0
# schon gesehene Loesungs-Signaturen (getGruppenId), damit dieselbe
# Sitzordnung nicht mehrfach gehalten und bewertet wird.
self._GeseheneGruppenIds = set()
if getattr(Zyklus, 'Modus', 'statisch') == 'adaptiv': if getattr(Zyklus, 'Modus', 'statisch') == 'adaptiv':
self._LaufAdaptiv(Klasse, *Arguments, **keywords) self._LaufAdaptiv(Klasse, *Arguments, **keywords)
else: else:
@@ -580,10 +592,27 @@ class Farm:
self._AbsZaehler = self._AbsZaehler + 1 self._AbsZaehler = self._AbsZaehler + 1
return self._AbsZaehler return self._AbsZaehler
def _LoesungIstNeu(self, L):
"""Kontrolle nach jeder Erzeugung: True, wenn die Loesung eine bisher
ungesehene Sitzordnung hat (Vergleich ueber getGruppenId, also auf
Gruppen-Ebene) - und merkt sie dann vor. Duplikate (gleiche Sitz-
ordnung) werden so nicht noch einmal gehalten und bewertet.
Loesungen ohne getGruppenId gelten immer als neu (kein Dedup)."""
Hole = getattr(L, 'getGruppenId', None)
if Hole is None:
return True
Gid = Hole()
if Gid in self._GeseheneGruppenIds:
return False
self._GeseheneGruppenIds.add(Gid)
return True
def LoesungenErzeugen(self, N, Klasse, *Arguments, **keywords): def LoesungenErzeugen(self, N, Klasse, *Arguments, **keywords):
""" Erzeuge Loesungen""" """ Erzeuge Loesungen (bereits gesehene Sitzordnungen werden verworfen)"""
for i in range(N): for i in range(N):
L = Klasse( *Arguments, **keywords ) L = Klasse( *Arguments, **keywords )
if not self._LoesungIstNeu(L):
continue # gleiche Sitzordnung schon vorhanden -> nicht behalten
L._absid = self._NeueId() # Wurzel: kein Vorgaenger L._absid = self._NeueId() # Wurzel: kein Vorgaenger
self.Abstammung.erfassen( self.Abstammung.erfassen(
L._absid, None, self._Generation, getattr(L, 'value', 0), 'e' ) L._absid, None, self._Generation, getattr(L, 'value', 0), 'e' )
@@ -603,6 +632,8 @@ class Farm:
for L in chain(self.Pool): for L in chain(self.Pool):
O = deepcopy(L) O = deepcopy(L)
Kind = O.mutieren() Kind = O.mutieren()
if not self._LoesungIstNeu(Kind):
continue # gleiche Sitzordnung schon gesehen -> verwerfen
# Kind bekommt eine neue fortlaufende Nummer; der Vorgaenger # Kind bekommt eine neue fortlaufende Nummer; der Vorgaenger
# (Eltern-Id) wird separat in der Abstammung gemerkt. # (Eltern-Id) wird separat in der Abstammung gemerkt.
ElternId = getattr(L, '_absid', None) ElternId = getattr(L, '_absid', None)
@@ -659,6 +690,15 @@ class Farm:
print("+ speichern") print("+ speichern")
def Bester(self): def Bester(self):
return max(self.Pool) return max(self.Pool)
def TopN(self, N):
"""die N besten Loesungen, absteigend nach Wertigkeit sortiert.
Erweiterung von Bester() (das nur die einzelne beste liefert): gibt
eine Liste der bis zu N besten Loesungen zurueck, damit sich mehrere
gute Alternativen betrachten lassen. N wird auf [0, len(Pool)]
begrenzt; bei N >= Poolgroesse ist es der ganze Pool (sortiert)."""
N = max( 0, min( N, len(self.Pool) ) )
return sorted( self.Pool, reverse=True )[:N]
if __name__ == '__main__': if __name__ == '__main__':
+38 -2
View File
@@ -11,7 +11,9 @@ __license__ = "Python"
from ga import * from ga import *
from Strukturdaten import * from Strukturdaten import *
from Farben import Farbschema
import optparse import optparse
import random
if __name__ == '__main__': if __name__ == '__main__':
@@ -50,8 +52,30 @@ if __name__ == '__main__':
parser.add_option( "--zyklus-art", dest="zyklusart", default="Adaptiv", parser.add_option( "--zyklus-art", dest="zyklusart", default="Adaptiv",
help="Name des GA-Profils in zyklus.cfg (Vorgabe: Adaptiv). " help="Name des GA-Profils in zyklus.cfg (Vorgabe: Adaptiv). "
"Weitere mitgelieferte Profile: Easy, Simple" ) "Weitere mitgelieferte Profile: Easy, Simple" )
parser.add_option( "--strafen", dest="strafen", default="default",
help="Name des Strafpunkte-Profils (Sektion in strafen.cfg; "
"Vorgabe: default). Erlaubt mehrere Bewertungs-Vorgehen in einer "
"Datei, z.B. --strafen locker" )
parser.add_option( "--farben", dest="farben", default="grosse_gruppen",
help="Name des Farbprofils fuer die SVG-Ausgabe (Sektion in "
"farben.cfg; Vorgabe: grosse_gruppen). Fuer Hochzeiten: "
"--farben hochzeit (Familien/Vereine/VIPs getrennt)" )
parser.add_option( "--seed", dest="seed", type="int", default=None,
help="Zufalls-Startwert (int) fuer random.seed(), macht den Lauf "
"reproduzierbar. Ohne Angabe laeuft der GA nichtdeterministisch. "
"Fuer Support-Rueckfragen ('warum sitzt Tante Erna dort?') mit "
"demselben --seed exakt denselben Sitzplan erneut erzeugen" )
(options, args) = parser.parse_args() (options, args) = parser.parse_args()
# Determinismus auf Wunsch: den globalen Zufallsgenerator seeden, bevor
# irgendeine GA-Aktion laeuft. Der gesamte Algorithmus (ga.py und
# Strukturdaten.py nutzen 'from random import *') zieht aus demselben
# Modul-RNG, daher genuegt ein einziges random.seed() hier.
if options.seed is not None:
random.seed( options.seed )
print( "Determinismus: random.seed(%d) - Lauf ist reproduzierbar"
% options.seed )
if options.indir is None: if options.indir is None:
parser.error( "--indir ist erforderlich" ) parser.error( "--indir ist erforderlich" )
InDir = os.path.expandvars( os.path.expanduser( options.indir ) ) InDir = os.path.expandvars( os.path.expanduser( options.indir ) )
@@ -68,6 +92,9 @@ if __name__ == '__main__':
Zyklusconfig = os.path.join( CfgDir, 'zyklus.cfg' ) Zyklusconfig = os.path.join( CfgDir, 'zyklus.cfg' )
Zyklusart = options.zyklusart Zyklusart = options.zyklusart
Strafenconfig = os.path.join( CfgDir, 'strafen.cfg' ) Strafenconfig = os.path.join( CfgDir, 'strafen.cfg' )
Strafenart = options.strafen
Farbenconfig = os.path.join( CfgDir, 'farben.cfg' )
Farbenart = options.farben
# lade Eingabedateien # lade Eingabedateien
Tischconfig = os.path.join( InDir, 'tische.ini' ) Tischconfig = os.path.join( InDir, 'tische.ini' )
@@ -84,8 +111,16 @@ if __name__ == '__main__':
Z.laden( Zyklusconfig, Zyklusart ) Z.laden( Zyklusconfig, Zyklusart )
print(Z) print(Z)
SL = Strafliste() SL = Strafliste()
SL.laden( Strafenconfig ) try:
SL.laden( Strafenconfig, Strafenart )
except ValueError as Fehler:
parser.error( str(Fehler) )
print(SL) print(SL)
FS = Farbschema()
try:
FS.laden( Farbenconfig, Farbenart )
except ValueError as Fehler:
parser.error( str(Fehler) )
TE = Tische() TE = Tische()
TE.laden( Tischconfig ) TE.laden( Tischconfig )
print(TE) print(TE)
@@ -104,7 +139,8 @@ if __name__ == '__main__':
print(S) print(S)
S.speichern( AusgabeTP, AusgabePT ) S.speichern( AusgabeTP, AusgabePT )
if options.tosvg: if options.tosvg:
S.alsSVG( AusgabeSVG, Verbindungen=options.showconn ) S.alsSVG( AusgabeSVG, Verbindungen=options.showconn,
GruppenNamen=GruppenNamen, Farbschema=FS )
if options.showdev: if options.showdev:
F1.Entwicklung.alsSVG( AusgabeEntwicklung ) F1.Entwicklung.alsSVG( AusgabeEntwicklung )
print( "Entwicklungsverlauf geschrieben:", AusgabeEntwicklung ) print( "Entwicklungsverlauf geschrieben:", AusgabeEntwicklung )
+160 -38
View File
@@ -10,15 +10,17 @@ Endpunkte (siehe auch /docs — interaktive Swagger-UI von FastAPI):
GET /sitzung/{id} — Status der Session GET /sitzung/{id} — Status der Session
POST /sitzung/{id}/tische — Tisch-Layout als JSON (Ersatz tische.ini) POST /sitzung/{id}/tische — Tisch-Layout als JSON (Ersatz tische.ini)
POST /sitzung/{id}/personen — Gaesteliste als CSV-Upload (Ersatz bestellung.json) POST /sitzung/{id}/personen — Gaesteliste als CSV-Upload (Ersatz bestellung.json)
POST /sitzung/{id}/berechnen — startet die GA-Optimierung POST /sitzung/{id}/berechnen — startet die GA-Optimierung; liefert bis zu
GET /sitzung/{id}/ergebnis — Ergebnis als JSON (Tische -> Personen) ?varianten=N unterschiedliche Loesungen (M2)
GET /sitzung/{id}/ergebnis.svg — Ergebnis als SVG (alsSVG aus dem Kern) GET /sitzung/{id}/ergebnis — alle Varianten des letzten Laufs als JSON
GET /sitzung/{id}/ergebnis.svg — eine Variante als SVG (?variante=k, 1 = beste)
Start (lokale Testinstanz, siehe bin/run_web.bat / bin/run_web.sh): Start (lokale Testinstanz, siehe bin/run_web.bat / bin/run_web.sh):
python -m uvicorn main:app --reload --app-dir web python -m uvicorn main:app --reload --app-dir web
""" """
import ast import ast
import configparser
import math import math
import os import os
import sys import sys
@@ -35,13 +37,14 @@ CFGDIR = os.environ.get( 'PLATZ_CFG', os.path.join( BASISDIR, 'cfg' ) )
if LIBSDIR not in sys.path: if LIBSDIR not in sys.path:
sys.path.insert( 0, LIBSDIR ) sys.path.insert( 0, LIBSDIR )
from fastapi import FastAPI, File, HTTPException, UploadFile from fastapi import FastAPI, File, HTTPException, Query, UploadFile
from fastapi.responses import Response from fastapi.responses import Response
from fastapi.staticfiles import StaticFiles from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from ga import Farm, Zyklus from ga import Farm, Zyklus
from CSVConfig import CSVConfig from CSVConfig import CSVConfig
from Farben import Farbschema
from Strukturdaten import Sitzplatzverteilung, Strafliste, Tisch, Tische from Strukturdaten import Sitzplatzverteilung, Strafliste, Tisch, Tische
app = FastAPI( app = FastAPI(
@@ -54,15 +57,49 @@ app = FastAPI(
# Zyklus und Strafliste einmal beim Start laden (wie in libs/platz.py): # Zyklus und Strafliste einmal beim Start laden (wie in libs/platz.py):
# zyklus.cfg und strafen.cfg direkt aus dem cfg-Verzeichnis (PLATZ_CFG bzw. # zyklus.cfg und strafen.cfg direkt aus dem cfg-Verzeichnis (PLATZ_CFG bzw.
# Projekt-cfg). GA-Profil per Umgebungsvariable PLATZ_ZYKLUSART (Vorgabe: # Projekt-cfg). GA-Profil per Umgebungsvariable PLATZ_ZYKLUSART (Vorgabe:
# Adaptiv). # Adaptiv), Strafpunkte-Profil per PLATZ_STRAFENART (Vorgabe: default) —
# analog zum Schalter --strafen in libs/platz.py.
ZYKLUSDATEI = os.path.join( CFGDIR, 'zyklus.cfg' ) ZYKLUSDATEI = os.path.join( CFGDIR, 'zyklus.cfg' )
STRAFENDATEI = os.path.join( CFGDIR, 'strafen.cfg' ) STRAFENDATEI = os.path.join( CFGDIR, 'strafen.cfg' )
ZYKLUSART = os.environ.get( 'PLATZ_ZYKLUSART', 'Adaptiv' ) ZYKLUSART = os.environ.get( 'PLATZ_ZYKLUSART', 'Adaptiv' )
STRAFENART = os.environ.get( 'PLATZ_STRAFENART', 'default' )
FARBENDATEI = os.path.join( CFGDIR, 'farben.cfg' )
FARBENART = os.environ.get( 'PLATZ_FARBENART', 'grosse_gruppen' )
GAZyklus = Zyklus() GAZyklus = Zyklus()
GAZyklus.laden( ZYKLUSDATEI, ZYKLUSART ) GAZyklus.laden( ZYKLUSDATEI, ZYKLUSART )
Strafen = Strafliste()
Strafen.laden( STRAFENDATEI ) # Strafprofile werden bei Bedarf geladen und gecacht, damit sich in der GUI
# verschiedene Profile (z.B. 'default' vs 'locker') auswaehlen und vergleichen
# lassen. Das Default-Profil wird schon beim Start geladen (faellt frueh auf,
# falls die Datei/Sektion kaputt ist).
StrafProfile = {}
def strafprofil(Name):
"""liefert (gecacht) die Strafliste einer Sektion aus strafen.cfg;
wirft ValueError bei unbekannter Sektion"""
if Name not in StrafProfile:
SL = Strafliste()
SL.laden( STRAFENDATEI, Name )
StrafProfile[Name] = SL
return StrafProfile[Name]
def strafprofil_namen():
"""alle in strafen.cfg vorhandenen Profilnamen (fuer die GUI-Auswahl)"""
cfg = configparser.ConfigParser()
cfg.read( STRAFENDATEI )
return cfg.sections()
strafprofil( STRAFENART ) # Default vorwaermen / frueh scheitern
# Farbprofil fuer die SVG-Ausgabe; faellt bei fehlender Datei/Sektion auf die
# eingebaute Palette zurueck (Farbschema=None), damit der Server trotzdem laeuft.
try:
Farben = Farbschema().laden( FARBENDATEI, FARBENART )
except (ValueError, OSError):
Farben = None
# ---------------------------------------------------------------- Sessions # ---------------------------------------------------------------- Sessions
SESSION_TTL_SEKUNDEN = 24 * 3600 SESSION_TTL_SEKUNDEN = 24 * 3600
@@ -149,17 +186,14 @@ def _TischeBauen(S):
return TE return TE
def _ErgebnisJSON(S): def _VarianteJSON(SV, GruppenNamen, Nr):
"""baut die JSON-Darstellung des besten Ergebnisses einer Session""" """baut die JSON-Darstellung EINER Loesung (eine Variante)"""
SV = S['ergebnis']
GruppenNamen = S.get( 'gruppenNamen', {} )
def GruppeVonPerson(P): def GruppeVonPerson(P):
try: try:
G = SV.Gruppen.GruppeVonPid( P.Id ) G = SV.Gruppen.GruppeVonPid( P.Id )
return GruppenNamen.get( G.Id, 'Gruppe %s' % G.Id ) return GruppenNamen.get( G.Id, 'Gruppe %s' % G.Id )
except KeyError: except KeyError:
return 'VIP' return 'fixiert'
TischListe = [] TischListe = []
for T in SV.Tische: for T in SV.Tische:
@@ -193,14 +227,38 @@ def _ErgebnisJSON(S):
} ) } )
GruppenListe.sort( key=lambda g: g['id'] ) GruppenListe.sort( key=lambda g: g['id'] )
return { # Vergleichs-Kennzahlen (Roadmap M2: Wertigkeit, Gruppentrennungen,
# allein sitzende Personen — LeuteAllein zaehlt nur Personen aus
# mehrkoepfigen Gruppen ohne Gruppenmitglied am Tisch)
Kennzahlen = {
'wertigkeit': SV.value, 'wertigkeit': SV.value,
'variante': S['varianten'], 'getrennteGruppen': sum( 1 for G in GruppenListe if G['teilungen'] > 0 ),
'teilungenGesamt': sum( G['teilungen'] for G in GruppenListe ),
'alleinePersonen': sum( len( SV.LeuteAllein(T) ) for T in SV.Tische ),
}
return {
'nr': Nr,
'wertigkeit': SV.value,
'gruppenId': SV.getGruppenId(),
'personenId': SV.getPersonenId(),
'kennzahlen': Kennzahlen,
'tische': TischListe, 'tische': TischListe,
'gruppen': GruppenListe, 'gruppen': GruppenListe,
} }
def _ErgebnisJSON(S):
"""baut die JSON-Darstellung aller Varianten des letzten Laufs"""
GruppenNamen = S.get( 'gruppenNamen', {} )
return {
'lauf': S['laeufe'],
'strafen': S.get( 'strafen', STRAFENART ), # verwendetes Strafprofil
'varianten': [ _VarianteJSON( SV, GruppenNamen, Nr + 1 )
for Nr, SV in enumerate( S['ergebnisse'] ) ],
}
# --------------------------------------------------------------- Endpunkte # --------------------------------------------------------------- Endpunkte
@app.post( '/sitzung', status_code=201 ) @app.post( '/sitzung', status_code=201 )
def SitzungAnlegen(): def SitzungAnlegen():
@@ -212,8 +270,8 @@ def SitzungAnlegen():
'erzeugt': time.time(), 'erzeugt': time.time(),
'tische': None, 'tische': None,
'personen': None, 'personen': None,
'ergebnis': None, 'ergebnisse': [], # Varianten des letzten Laufs (beste zuerst)
'varianten': 0, 'laeufe': 0, # wie oft .../berechnen aufgerufen wurde
} }
return { 'id': SitzungsId, 'ttlStunden': SESSION_TTL_SEKUNDEN // 3600 } return { 'id': SitzungsId, 'ttlStunden': SESSION_TTL_SEKUNDEN // 3600 }
@@ -227,8 +285,9 @@ def SitzungStatus(SitzungsId: str):
'tische': len( S['tische'] ) if S['tische'] else 0, 'tische': len( S['tische'] ) if S['tische'] else 0,
'personen': S['personen']['nLeute'] if S['personen'] else 0, 'personen': S['personen']['nLeute'] if S['personen'] else 0,
'vips': S['personen']['nVips'] if S['personen'] else 0, 'vips': S['personen']['nVips'] if S['personen'] else 0,
'berechnet': S['ergebnis'] is not None, 'berechnet': len( S['ergebnisse'] ) > 0,
'varianten': S['varianten'], 'laeufe': S['laeufe'],
'varianten': len( S['ergebnisse'] ),
} }
@@ -262,8 +321,10 @@ def TischeSetzen(SitzungsId: str, Layout: TischLayout):
'y': T.y, 'y': T.y,
'nachbarn': Nachbarn[T.id], 'nachbarn': Nachbarn[T.id],
} for T in Layout.tische ] } for T in Layout.tische ]
S['ergebnis'] = None # Nachbar-Radius fuer den Rueckweg merken (GET .../tische), damit der
S['varianten'] = 0 # grafische Editor dasselbe Layout inkl. Radius wieder laden kann.
S['nachbarRadius'] = Layout.nachbarRadius
S['ergebnisse'] = []
return { return {
'tische': S['tische'], 'tische': S['tische'],
@@ -271,6 +332,19 @@ def TischeSetzen(SitzungsId: str, Layout: TischLayout):
} }
@app.get( '/sitzung/{SitzungsId}/tische' )
def TischeHolen(SitzungsId: str):
"""das gespeicherte Tisch-Layout zurueckgeben (fuer den grafischen
Editor: Layout aus einer geteilten Session wieder aufnehmen).
Die abgeleitete Nachbarliste ist pro Tisch enthalten; der zuletzt
verwendete nachbarRadius kommt separat mit (Vorgabe 1.5)."""
S = _GibSession( SitzungsId )
return {
'tische': S['tische'] or [],
'nachbarRadius': S.get( 'nachbarRadius', 1.5 ),
}
@app.post( '/sitzung/{SitzungsId}/tische-datei' ) @app.post( '/sitzung/{SitzungsId}/tische-datei' )
def TischDateiHochladen(SitzungsId: str, datei: UploadFile = File(...)): def TischDateiHochladen(SitzungsId: str, datei: UploadFile = File(...)):
"""bestehende tische.ini hochladen (gleiches Format wie fuer die CLI, """bestehende tische.ini hochladen (gleiches Format wie fuer die CLI,
@@ -330,8 +404,7 @@ def TischDateiHochladen(SitzungsId: str, datei: UploadFile = File(...)):
detail='tische.ini enthaelt doppelte Tisch-Ids' ) detail='tische.ini enthaelt doppelte Tisch-Ids' )
S['tische'] = TischListe S['tische'] = TischListe
S['ergebnis'] = None S['ergebnisse'] = []
S['varianten'] = 0
return { return {
'tische': S['tische'], 'tische': S['tische'],
'plaetzeGesamt': sum( T['plaetze'] for T in S['tische'] ), 'plaetzeGesamt': sum( T['plaetze'] for T in S['tische'] ),
@@ -350,7 +423,7 @@ def PersonenHochladen(SitzungsId: str, datei: UploadFile = File(...)):
Text = Rohdaten.decode( 'cp1252' ) # Excel/Windows-Fallback Text = Rohdaten.decode( 'cp1252' ) # Excel/Windows-Fallback
try: try:
[ PN, GN, VIPGruppe, VipHash, GruppenNamen ] = \ [ PN, GN, VIPGruppe, VipHash, GruppenNamen, FixierteGruppen ] = \
CSVConfig().HandleGaesteliste( Text ) CSVConfig().HandleGaesteliste( Text )
except ValueError as Fehler: except ValueError as Fehler:
raise HTTPException( status_code=400, detail=str(Fehler) ) raise HTTPException( status_code=400, detail=str(Fehler) )
@@ -364,23 +437,34 @@ def PersonenHochladen(SitzungsId: str, datei: UploadFile = File(...)):
'nVips': VIPGruppe.Anzahl(), 'nVips': VIPGruppe.Anzahl(),
} }
S['gruppenNamen'] = GruppenNamen S['gruppenNamen'] = GruppenNamen
S['ergebnis'] = None S['ergebnisse'] = []
S['varianten'] = 0
return { return {
'personen': GN.NLeute, 'personen': GN.NLeute,
'vips': VIPGruppe.Anzahl(), 'fixiert': VIPGruppe.Anzahl(),
'gruppen': [ { 'gruppen': [ {
'id': G.Id, 'id': G.Id,
'name': GruppenNamen.get( G.Id, 'Gruppe %s' % G.Id ), 'name': GruppenNamen.get( G.Id, 'Gruppe %s' % G.Id ),
'anzahl': G.Anzahl(), 'anzahl': G.Anzahl(),
} for G in GN ], } for G in GN ],
# fest platzierte Gruppen (fuer die grau hinterlegte Anzeige)
'fixierte': [ { 'name': Name, 'tisch': Info['tisch'], 'anzahl': Info['anzahl'] }
for Name, Info in FixierteGruppen.items() ],
} }
@app.post( '/sitzung/{SitzungsId}/berechnen' ) @app.post( '/sitzung/{SitzungsId}/berechnen' )
def Berechnen(SitzungsId: str): def Berechnen(SitzungsId: str,
"""startet die GA-Optimierung; jeder Aufruf erzeugt eine neue Variante""" varianten: int = Query( default=3, ge=1, le=5,
description='wieviele unterschiedliche Varianten der Lauf '
'zurueckgeben soll (aus Farm.TopN, dedupliziert)' ),
strafen: str = Query( default=STRAFENART,
description='Name des Strafpunkte-Profils (Sektion in strafen.cfg), '
'z.B. default oder locker - zum Vergleich waehlbar' )):
"""startet die GA-Optimierung; jeder Aufruf ist ein neuer Lauf und
liefert bis zu 'varianten' unterschiedliche gute Sitzordnungen. Das
Strafpunkte-Profil ('strafen') steuert die Bewertung waehrend der
Optimierung - so lassen sich z.B. default und locker vergleichen."""
S = _GibSession( SitzungsId ) S = _GibSession( SitzungsId )
if S['tische'] is None: if S['tische'] is None:
raise HTTPException( status_code=400, raise HTTPException( status_code=400,
@@ -412,41 +496,79 @@ def Berechnen(SitzungsId: str):
detail='Tisch %d hat %d Plaetze, aber %d VIPs sind ' detail='Tisch %d hat %d Plaetze, aber %d VIPs sind '
'dort fest gesetzt' % (Tid, T.Plaetze, AnzahlVIPs) ) 'dort fest gesetzt' % (Tid, T.Plaetze, AnzahlVIPs) )
try:
SL = strafprofil( strafen )
except ValueError as Fehler:
raise HTTPException( status_code=400, detail=str(Fehler) )
try: try:
GAFarm = Farm( GAZyklus, Sitzplatzverteilung, GAFarm = Farm( GAZyklus, Sitzplatzverteilung,
Tische=TE, Gruppen=P['GN'], Strafen=Strafen, Tische=TE, Gruppen=P['GN'], Strafen=SL,
VIPListe=P['VipHash'], VIPs=P['VIPGruppe'] ) VIPListe=P['VipHash'], VIPs=P['VIPGruppe'] )
except IndexError as Fehler: except IndexError as Fehler:
raise HTTPException( status_code=400, detail=str(Fehler) ) raise HTTPException( status_code=400, detail=str(Fehler) )
S['ergebnis'] = GAFarm.Bester() # Roadmap M2: nicht nur den Besten, sondern bis zu 'varianten'
S['varianten'] = S['varianten'] + 1 # UNTERSCHIEDLICHE gute Loesungen aus dem Endpool — Farm.TopN liefert
# absteigend sortiert. Der Vergleich der Loesungen laeuft ueber die
# getGruppenId (Gruppen-Ebene): dieselbe Sitzordnung zaehlt nicht mehrfach
# als eigene Variante. Der GA-Pool ist ohnehin schon per getGruppenId
# dedupliziert; das hier ist die zusaetzliche Absicherung fuer die Ausgabe.
# Liefert der Pool weniger unterschiedliche Sitzordnungen, kommen eben
# weniger zurueck (ein weiterer Klick auf Berechnen erzeugt einen frischen Lauf).
Ergebnisse, Gesehen = [], set()
for SV in GAFarm.TopN( len( GAFarm.Pool ) ):
Sig = SV.getGruppenId()
if Sig in Gesehen:
continue
Gesehen.add( Sig )
Ergebnisse.append( SV )
if len( Ergebnisse ) == varianten:
break
S['ergebnisse'] = Ergebnisse
S['laeufe'] = S['laeufe'] + 1
S['strafen'] = strafen # fuer die Anzeige, welches Profil den Lauf ergab
return _ErgebnisJSON( S ) return _ErgebnisJSON( S )
@app.get( '/strafprofile' )
def Strafprofile():
"""verfuegbare Strafpunkte-Profile (Sektionen in strafen.cfg) fuer die
Auswahl in der GUI; 'vorgabe' ist das voreingestellte Profil."""
return { 'profile': strafprofil_namen(), 'vorgabe': STRAFENART }
@app.get( '/sitzung/{SitzungsId}/ergebnis' ) @app.get( '/sitzung/{SitzungsId}/ergebnis' )
def Ergebnis(SitzungsId: str): def Ergebnis(SitzungsId: str):
"""das beste bisher berechnete Ergebnis als JSON""" """alle Varianten des letzten Laufs als JSON (beste zuerst)"""
S = _GibSession( SitzungsId ) S = _GibSession( SitzungsId )
if S['ergebnis'] is None: if not S['ergebnisse']:
raise HTTPException( status_code=404, raise HTTPException( status_code=404,
detail='Noch nichts berechnet (POST .../berechnen)' ) detail='Noch nichts berechnet (POST .../berechnen)' )
return _ErgebnisJSON( S ) return _ErgebnisJSON( S )
@app.get( '/sitzung/{SitzungsId}/ergebnis.svg' ) @app.get( '/sitzung/{SitzungsId}/ergebnis.svg' )
def ErgebnisSVG(SitzungsId: str): def ErgebnisSVG(SitzungsId: str,
"""das beste bisher berechnete Ergebnis als SVG (alsSVG aus dem Kern)""" variante: int = Query( default=1, ge=1,
description='Nummer der Variante (1 = beste)' )):
"""eine berechnete Variante als SVG (alsSVG aus dem Kern)"""
S = _GibSession( SitzungsId ) S = _GibSession( SitzungsId )
if S['ergebnis'] is None: if not S['ergebnisse']:
raise HTTPException( status_code=404, raise HTTPException( status_code=404,
detail='Noch nichts berechnet (POST .../berechnen)' ) detail='Noch nichts berechnet (POST .../berechnen)' )
if variante > len( S['ergebnisse'] ):
raise HTTPException( status_code=404,
detail='Variante %d gibt es nicht (letzter Lauf hat %d)'
% (variante, len( S['ergebnisse'] )) )
# alsSVG schreibt in eine Datei -> Tempdatei schreiben, lesen, loeschen # alsSVG schreibt in eine Datei -> Tempdatei schreiben, lesen, loeschen
Handle, TempPfad = tempfile.mkstemp( suffix='.svg' ) Handle, TempPfad = tempfile.mkstemp( suffix='.svg' )
os.close( Handle ) os.close( Handle )
try: try:
S['ergebnis'].alsSVG( TempPfad ) S['ergebnisse'][variante - 1].alsSVG( TempPfad,
GruppenNamen=S.get( 'gruppenNamen', {} ), Farbschema=Farben )
fsock = open( TempPfad, 'r' ) fsock = open( TempPfad, 'r' )
SVG = fsock.read() SVG = fsock.read()
fsock.close() fsock.close()
+472
View File
@@ -0,0 +1,472 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Sitz &amp; Platz — Tisch-Editor (M1)</title>
<style>
:root {
--akzent: #2f6f4f;
--akzent-hell: #e6f0ea;
--rand: #d9d4c8;
--hintergrund: #faf8f3;
}
* { box-sizing: border-box; }
body {
font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
margin: 0; background: var(--hintergrund); color: #2a2a24; line-height: 1.5;
}
header { background: var(--akzent); color: white; padding: 1rem 1.5rem; }
header h1 { margin: 0; font-size: 1.3rem; }
header p { margin: .2rem 0 0; opacity: .85; font-size: .85rem; }
header a { color: #d6eade; }
main { max-width: 68rem; margin: 0 auto; padding: 1rem 1.5rem 4rem; }
.werkzeug {
display: flex; flex-wrap: wrap; align-items: center; gap: .4rem;
background: white; border: 1px solid var(--rand); border-radius: 8px;
padding: .6rem .75rem; margin-bottom: 1rem;
}
.werkzeug .trenner { width: 1px; height: 1.6rem; background: var(--rand); margin: 0 .3rem; }
.werkzeug label { font-size: .82rem; color: #6b6557; display: inline-flex; align-items: center; gap: .3rem; }
button {
background: var(--akzent); color: white; border: 0; border-radius: 4px;
padding: .42rem .8rem; font-size: .88rem; cursor: pointer;
}
button.sekundaer { background: #8b8577; }
button.geist { background: white; color: var(--akzent); border: 1px solid var(--rand); }
button:disabled { background: #cfcabc; color: #f3f0e8; cursor: not-allowed; }
.buehne {
display: grid; grid-template-columns: 1fr 15rem; gap: 1rem; align-items: start;
}
@media (max-width: 48rem) { .buehne { grid-template-columns: 1fr; } }
#leinwand {
background: white; border: 1px solid var(--rand); border-radius: 8px;
overflow: auto; touch-action: none; min-height: 24rem;
}
#leinwand svg { display: block; }
.circle-tisch { cursor: grab; }
.circle-tisch:active { cursor: grabbing; }
aside {
background: white; border: 1px solid var(--rand); border-radius: 8px;
padding: 1rem; font-size: .9rem;
}
aside h2 { font-size: 1rem; margin: 0 0 .6rem; color: var(--akzent); }
aside .feld { margin: .5rem 0; }
aside input[type=number] { width: 4rem; }
.zahl { display: inline-block; background: #f1eee6; border-radius: 4px;
padding: .25rem .6rem; margin: .1rem .3rem .1rem 0; font-size: .85rem; }
.zahl b { color: var(--akzent); }
.status { font-size: .85rem; margin-top: .6rem; min-height: 1.2rem; }
.status.ok { color: var(--akzent); }
.status.fehler { color: #a03030; white-space: pre-wrap; }
.hinweis { font-size: .8rem; color: #6b6557; }
kbd { background: #f1eee6; border: 1px solid var(--rand); border-bottom-width: 2px;
border-radius: 3px; padding: 0 .3rem; font-size: .78rem; }
</style>
</head>
<body>
<header>
<h1>Sitz &amp; Platz <small style="font-weight:normal">— Interaktiver Tisch-Editor (Meilenstein 1)</small></h1>
<p>Tische per Drag &amp; Drop platzieren; Nachbarschaft wird aus der Nähe abgeleitet.
Sitzung: <code id="sitzungsId"></code> · weiter zu <a href="/">Gäste &amp; Berechnung</a></p>
</header>
<main>
<div class="werkzeug">
<button id="btnUndo" title="Rückgängig (Strg+Z)" disabled>↶ Rückgängig</button>
<button id="btnRedo" title="Wiederholen (Strg+Y)" disabled>↷ Wiederholen</button>
<span class="trenner"></span>
<button id="btnAdd" class="geist">+ Tisch</button>
<button id="btnReihe" class="sekundaer">Preset: 4er-Reihe</button>
<button id="btnRaster" class="sekundaer">Preset: 3×3-Raster</button>
<span class="trenner"></span>
<label>Nachbar-Radius
<input type="range" id="radius" min="0.5" max="3" step="0.1" value="1.5">
<b id="radiusWert">1,5</b>
</label>
<label>Raster
<select id="raster">
<option value="0.5" selected>0,5</option>
<option value="1">1</option>
<option value="1.5">1,5</option>
<option value="2">2</option>
</select>
</label>
<span class="trenner"></span>
<label>tische.ini <input type="file" id="iniDatei" accept=".ini,text/plain"></label>
<button id="btnIni" class="geist">laden</button>
<span class="trenner"></span>
<button id="btnSpeichern">Layout speichern</button>
</div>
<div class="buehne">
<div id="leinwand"></div>
<aside>
<h2>Ausgewählter Tisch</h2>
<div id="inspektor"><p class="hinweis">Kein Tisch ausgewählt. Auf einen Tisch
klicken, um Plätze zu ändern oder ihn zu löschen. Ziehen zum Verschieben.</p></div>
<hr style="border:0;border-top:1px solid var(--rand);margin:.8rem 0">
<div id="zahlen"></div>
<p class="hinweis" style="margin-top:.6rem">Tastatur: <kbd>Strg</kbd>+<kbd>Z</kbd> /
<kbd>Strg</kbd>+<kbd>Y</kbd> Undo/Redo · <kbd>Entf</kbd> löscht den
ausgewählten Tisch.</p>
</aside>
</div>
<div class="status" id="status"></div>
</main>
<script>
'use strict';
/* ============================================================ Zustand
state.tische ist die einzige Wahrheit; das SVG wird daraus gezeichnet
(state-getrieben, nie umgekehrt). Der Nachbar-Radius ist bewusst KEIN
Teil der Undo-History (Undo/Redo betrifft Tischgeometrie/-kapazität,
nicht diese Ableitungs-Einstellung), wird aber mitgespeichert. */
const state = { tische: [] };
let radius = 1.5;
let rasterSchritt = 0.5;
const ZIEH_TEMPO = 0.5; // Ziehgeschwindigkeit: Tisch folgt dem Zeiger halb so schnell
let selectedId = null;
let sitzung = null;
/* Undo/Redo: Schnappschuss-Stapel. Ein Schnappschuss ist ein tiefer Klon
von state.tische. Vor jeder verändernden Aktion wird der aktuelle
Zustand auf undoStack gelegt und redoStack geleert. */
const undoStack = [];
const redoStack = [];
const HIST_MAX = 200;
const klon = (t) => JSON.parse(JSON.stringify(t));
function pushHistory() {
undoStack.push(klon(state.tische));
if (undoStack.length > HIST_MAX) undoStack.shift();
redoStack.length = 0;
knoepfe();
}
function undo() {
if (!undoStack.length) return;
redoStack.push(klon(state.tische));
state.tische = undoStack.pop();
nachZustandswechsel();
}
function redo() {
if (!redoStack.length) return;
undoStack.push(klon(state.tische));
state.tische = redoStack.pop();
nachZustandswechsel();
}
function nachZustandswechsel() {
if (selectedId !== null && !tischVonId(selectedId)) selectedId = null;
knoepfe(); zeichne(); inspektor();
}
function knoepfe() {
document.getElementById('btnUndo').disabled = undoStack.length === 0;
document.getElementById('btnRedo').disabled = redoStack.length === 0;
}
/* ============================================================ Helfer */
const tischVonId = (id) => state.tische.find(t => t.id === id);
function neueId() {
return state.tische.reduce((m, t) => Math.max(m, t.id), 0) + 1;
}
function snap(v) { return Math.round( Math.round(v / rasterSchritt) * rasterSchritt * 100 ) / 100; }
function radiusPx(plaetze) {
// Kreisgroesse waechst mit der Platzzahl (analog alsSVG im Kern)
return Math.max(18, Math.min(48, 15 + plaetze * 1.5));
}
/* ============================================================ Geometrie
Grid-Koordinaten (wie tische.ini) <-> Pixel. Bei jeder Zeichnung neu
bestimmt und in Modulvariablen abgelegt, damit pointerGrid() umrechnen
kann. */
const SCALE = 72, MARGIN = 34, PAD = 1;
let viewMinX = 0, viewMinY = 0, curW = 600, curH = 400;
function grenzen() {
if (!state.tische.length) return { minX: 0, maxX: 3, minY: 0, maxY: 2 };
const xs = state.tische.map(t => t.x), ys = state.tische.map(t => t.y);
return { minX: Math.min(...xs), maxX: Math.max(...xs),
minY: Math.min(...ys), maxY: Math.max(...ys) };
}
const px = (gx, min) => MARGIN + (gx - min) * SCALE;
function pointerGrid(e) {
const svg = document.querySelector('#leinwand svg');
const r = svg.getBoundingClientRect();
const sx = curW / r.width, sy = curH / r.height;
const X = (e.clientX - r.left) * sx, Y = (e.clientY - r.top) * sy;
return { x: (X - MARGIN) / SCALE + viewMinX, y: (Y - MARGIN) / SCALE + viewMinY };
}
/* ============================================================ Zeichnen */
function nachbarPaare() {
const paare = [];
for (let i = 0; i < state.tische.length; i++)
for (let j = i + 1; j < state.tische.length; j++) {
const a = state.tische[i], b = state.tische[j];
if (Math.hypot(a.x - b.x, a.y - b.y) <= radius) paare.push([a, b]);
}
return paare;
}
function zeichne() {
const g = grenzen();
viewMinX = g.minX - PAD; viewMinY = g.minY - PAD;
curW = Math.max(480, MARGIN * 2 + (g.maxX - g.minX + 2 * PAD) * SCALE);
curH = Math.max(320, MARGIN * 2 + (g.maxY - g.minY + 2 * PAD) * SCALE);
let s = `<svg xmlns="http://www.w3.org/2000/svg" width="${curW}" height="${curH}" `
+ `viewBox="0 0 ${curW} ${curH}" font-family="sans-serif">`;
s += `<rect width="100%" height="100%" fill="white"/>`;
// feines Grid an ganzzahligen Rasterlinien
for (let gx = Math.ceil(viewMinX); px(gx, viewMinX) <= curW; gx++)
s += `<line x1="${px(gx, viewMinX)}" y1="0" x2="${px(gx, viewMinX)}" y2="${curH}" stroke="#f0ede5"/>`;
for (let gy = Math.ceil(viewMinY); px(gy, viewMinY) <= curH; gy++)
s += `<line x1="0" y1="${px(gy, viewMinY)}" x2="${curW}" y2="${px(gy, viewMinY)}" stroke="#f0ede5"/>`;
// Nachbar-Linien (aus der Naehe abgeleitet, wie im Backend)
for (const [a, b] of nachbarPaare())
s += `<line x1="${px(a.x, viewMinX)}" y1="${px(a.y, viewMinY)}" `
+ `x2="${px(b.x, viewMinX)}" y2="${px(b.y, viewMinY)}" `
+ `stroke="#bcd3c6" stroke-width="2"/>`;
// Tische als Kreise
for (const t of state.tische) {
const cx = px(t.x, viewMinX), cy = px(t.y, viewMinY), r = radiusPx(t.plaetze);
const gewaehlt = t.id === selectedId;
s += `<g class="circle-tisch" data-id="${t.id}">`;
if (gewaehlt)
s += `<circle cx="${cx}" cy="${cy}" r="${r + 5}" fill="none" `
+ `stroke="#2f6f4f" stroke-width="2" stroke-dasharray="4 3"/>`;
s += `<circle cx="${cx}" cy="${cy}" r="${r}" `
+ `fill="${gewaehlt ? '#e6f0ea' : 'white'}" stroke="#2f6f4f" stroke-width="2"/>`;
s += `<text x="${cx}" y="${cy - 1}" text-anchor="middle" font-size="15" `
+ `font-weight="bold" fill="#2f6f4f">${t.id}</text>`;
s += `<text x="${cx}" y="${cy + 13}" text-anchor="middle" font-size="10" `
+ `fill="#6b6557">${t.plaetze} Pl.</text>`;
s += `</g>`;
}
s += `</svg>`;
document.getElementById('leinwand').innerHTML = s;
// Kennzahlen
const plaetze = state.tische.reduce((m, t) => m + t.plaetze, 0);
document.getElementById('zahlen').innerHTML =
`<span class="zahl">Tische: <b>${state.tische.length}</b></span>` +
`<span class="zahl">Plätze: <b>${plaetze}</b></span>` +
`<span class="zahl">Nachbar-Paare: <b>${nachbarPaare().length}</b></span>`;
}
/* ============================================================ Inspektor */
function inspektor() {
const el = document.getElementById('inspektor');
const t = selectedId !== null ? tischVonId(selectedId) : null;
if (!t) {
el.innerHTML = '<p class="hinweis">Kein Tisch ausgewählt. Auf einen Tisch ' +
'klicken, um Plätze zu ändern oder ihn zu löschen. Ziehen zum Verschieben.</p>';
return;
}
el.innerHTML =
`<div class="feld"><b>Tisch ${t.id}</b></div>` +
`<div class="feld">Plätze: ` +
`<button class="geist" id="plMinus"></button> ` +
`<input type="number" id="plaetze" min="1" max="100" value="${t.plaetze}"> ` +
`<button class="geist" id="plPlus">+</button></div>` +
`<div class="feld hinweis">Position: x=${t.x}, y=${t.y}</div>` +
`<div class="feld"><button class="sekundaer" id="loeschen">Tisch löschen</button></div>`;
document.getElementById('plMinus').onclick = () => plaetzeSetzen(t.plaetze - 1);
document.getElementById('plPlus').onclick = () => plaetzeSetzen(t.plaetze + 1);
document.getElementById('plaetze').onchange = (e) => plaetzeSetzen(parseInt(e.target.value, 10));
document.getElementById('loeschen').onclick = tischLoeschen;
}
function plaetzeSetzen(wert) {
const t = tischVonId(selectedId);
if (!t || isNaN(wert)) return;
wert = Math.max(1, Math.min(100, wert));
if (wert === t.plaetze) return;
pushHistory(); t.plaetze = wert; zeichne(); inspektor();
}
/* ============================================================ Auswahl */
function auswaehlen(id) { selectedId = id; zeichne(); inspektor(); }
/* ============================================================ Aktionen */
function tischHinzufuegen() {
const g = grenzen();
const x = state.tische.length ? snap((g.minX + g.maxX) / 2) : 0;
const y = state.tische.length ? snap((g.minY + g.maxY) / 2) : 0;
pushHistory();
const id = neueId();
state.tische.push({ id, plaetze: 8, x, y });
auswaehlen(id);
melde('Tisch ' + id + ' hinzugefügt.', 'ok');
}
function tischLoeschen() {
if (selectedId === null) return;
pushHistory();
state.tische = state.tische.filter(t => t.id !== selectedId);
const weg = selectedId; selectedId = null;
zeichne(); inspektor();
melde('Tisch ' + weg + ' gelöscht.', 'ok');
}
function presetReihe() {
pushHistory();
state.tische = [1, 2, 3, 4].map(i => ({ id: i, plaetze: 5, x: i - 1, y: 0 }));
selectedId = null; zeichne(); inspektor();
}
function presetRaster() {
pushHistory();
state.tische = [];
let id = 1;
for (let y = 0; y < 3; y++)
for (let x = 0; x < 3; x++) state.tische.push({ id: id++, plaetze: 8, x, y });
selectedId = null; zeichne(); inspektor();
}
/* ============================================================ Drag & Drop */
let dragId = null, dragMoved = false, dragStart = null;
let ankerPtr = null, ankerPos = null; // Zeiger- und Tischposition bei Zugbeginn
document.getElementById('leinwand').addEventListener('pointerdown', (e) => {
const el = e.target.closest('[data-id]');
if (!el) { if (selectedId !== null) auswaehlen(null); return; }
const id = parseInt(el.dataset.id, 10);
auswaehlen(id);
const gpt = pointerGrid(e), t = tischVonId(id);
dragId = id; dragMoved = false; dragStart = klon(state.tische);
// Anker merken: der Tisch wandert ab hier um ZIEH_TEMPO * Zeigerweg
ankerPtr = { x: gpt.x, y: gpt.y };
ankerPos = { x: t.x, y: t.y };
e.preventDefault();
});
window.addEventListener('pointermove', (e) => {
if (dragId === null) return;
const gpt = pointerGrid(e);
// halbe Geschwindigkeit: Verschiebung des Tisches = halber Zeigerweg
const nx = snap(ankerPos.x + (gpt.x - ankerPtr.x) * ZIEH_TEMPO);
const ny = snap(ankerPos.y + (gpt.y - ankerPtr.y) * ZIEH_TEMPO);
const t = tischVonId(dragId);
if (t && (t.x !== nx || t.y !== ny)) { t.x = nx; t.y = ny; dragMoved = true; zeichne(); inspektor(); }
});
window.addEventListener('pointerup', () => {
if (dragId === null) return;
if (dragMoved) {
// den ganzen Zug als EINEN Undo-Schritt ablegen (Vor-Zustand)
undoStack.push(dragStart);
if (undoStack.length > HIST_MAX) undoStack.shift();
redoStack.length = 0; knoepfe();
}
dragId = null; dragStart = null;
});
/* ============================================================ Tastatur */
window.addEventListener('keydown', (e) => {
const tippt = /^(INPUT|TEXTAREA)$/.test(document.activeElement.tagName);
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'z' && !e.shiftKey) {
e.preventDefault(); undo();
} else if ((e.ctrlKey || e.metaKey) && (e.key.toLowerCase() === 'y' ||
(e.key.toLowerCase() === 'z' && e.shiftKey))) {
e.preventDefault(); redo();
} else if ((e.key === 'Delete' || e.key === 'Backspace') && selectedId !== null && !tippt) {
e.preventDefault(); tischLoeschen();
}
});
/* ============================================================ Backend */
function melde(text, klasse) {
const el = document.getElementById('status');
el.textContent = text; el.className = 'status ' + (klasse || '');
}
async function api(pfad, optionen) {
const antwort = await fetch(pfad, optionen);
const daten = await antwort.json().catch(() => null);
if (!antwort.ok) {
const d = daten && daten.detail
? (typeof daten.detail === 'string' ? daten.detail : JSON.stringify(daten.detail))
: antwort.statusText;
throw new Error(d);
}
return daten;
}
async function sitzungHolen() {
// Session mit der Testoberflaeche (index.html) ueber localStorage teilen
let id = localStorage.getItem('platzSitzung');
if (id) {
const ok = await fetch('/sitzung/' + id).then(r => r.ok).catch(() => false);
if (ok) return id;
}
const r = await api('/sitzung', { method: 'POST' });
localStorage.setItem('platzSitzung', r.id);
return r.id;
}
async function layoutSpeichern() {
if (!state.tische.length) { melde('Mindestens ein Tisch nötig.', 'fehler'); return; }
const tische = state.tische.map(t => ({ id: t.id, plaetze: t.plaetze, x: t.x, y: t.y }));
try {
const r = await api('/sitzung/' + sitzung + '/tische', {
method: 'POST', headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ tische, nachbarRadius: radius }),
});
melde('✓ ' + r.tische.length + ' Tische, ' + r.plaetzeGesamt +
' Plätze gespeichert. Weiter mit „Gäste & Berechnung“.', 'ok');
} catch (e) { melde('Fehler: ' + e.message, 'fehler'); }
}
async function iniLaden() {
const eingabe = document.getElementById('iniDatei');
if (!eingabe.files.length) { melde('Bitte zuerst eine tische.ini auswählen.', 'fehler'); return; }
const form = new FormData(); form.append('datei', eingabe.files[0]);
try {
const r = await api('/sitzung/' + sitzung + '/tische-datei', { method: 'POST', body: form });
pushHistory();
state.tische = r.tische.map(t => ({ id: t.id, plaetze: t.plaetze, x: t.x, y: t.y }));
selectedId = null; zeichne(); inspektor();
melde('✓ ' + r.tische.length + ' Tische aus Datei geladen.', 'ok');
} catch (e) { melde('Fehler: ' + e.message, 'fehler'); }
}
async function layoutLaden() {
// bereits in der (geteilten) Session gespeichertes Layout uebernehmen
try {
const r = await api('/sitzung/' + sitzung + '/tische');
if (r.tische && r.tische.length) {
state.tische = r.tische.map(t => ({ id: t.id, plaetze: t.plaetze, x: t.x, y: t.y }));
radius = r.nachbarRadius || 1.5;
document.getElementById('radius').value = radius;
document.getElementById('radiusWert').textContent = radius.toFixed(1).replace('.', ',');
return true;
}
} catch (e) { /* neue Session ohne Layout — Preset zeigen */ }
return false;
}
/* ============================================================ Verdrahtung */
document.getElementById('btnUndo').onclick = undo;
document.getElementById('btnRedo').onclick = redo;
document.getElementById('btnAdd').onclick = tischHinzufuegen;
document.getElementById('btnReihe').onclick = presetReihe;
document.getElementById('btnRaster').onclick = presetRaster;
document.getElementById('btnSpeichern').onclick = layoutSpeichern;
document.getElementById('btnIni').onclick = iniLaden;
document.getElementById('raster').onchange = (e) => { rasterSchritt = parseFloat(e.target.value); };
const radiusInput = document.getElementById('radius');
radiusInput.oninput = (e) => {
radius = parseFloat(e.target.value);
document.getElementById('radiusWert').textContent = radius.toFixed(1).replace('.', ',');
zeichne();
};
/* ============================================================ Start */
window.addEventListener('DOMContentLoaded', async () => {
try {
sitzung = await sitzungHolen();
document.getElementById('sitzungsId').textContent = sitzung;
} catch (e) {
document.getElementById('sitzungsId').textContent = 'Fehler: ' + e.message;
}
const geladen = sitzung ? await layoutLaden() : false;
if (!geladen) state.tische = [1, 2, 3, 4].map(i => ({ id: i, plaetze: 5, x: i - 1, y: 0 }));
knoepfe(); zeichne(); inspektor();
});
</script>
</body>
</html>
+214 -44
View File
@@ -47,18 +47,38 @@
.status { font-size: .85rem; margin-top: .5rem; min-height: 1.2rem; } .status { font-size: .85rem; margin-top: .5rem; min-height: 1.2rem; }
.status.ok { color: var(--akzent); } .status.ok { color: var(--akzent); }
.status.fehler { color: #a03030; white-space: pre-wrap; } .status.fehler { color: #a03030; white-space: pre-wrap; }
#svgBild { max-width: 100%; border: 1px solid var(--rand); border-radius: 4px; #svgPlan { margin-top: .75rem; border: 1px solid var(--rand); border-radius: 4px;
margin-top: .75rem; background: white; } background: white; overflow: auto; }
#svgPlan svg { max-width: 100%; height: auto; display: block; }
#svgPlan .person { cursor: pointer; }
#svgPlan .person.aktiv { stroke: #111; stroke-width: 3; }
#gruppeBox { position: fixed; z-index: 1000; pointer-events: none; display: none;
background: #2a2a24; color: white; border-radius: 6px;
padding: .5rem .7rem; font-size: .8rem; max-width: 18rem;
line-height: 1.35; box-shadow: 0 2px 10px rgba(0,0,0,.35); }
#gruppeBox b { display: block; margin-bottom: .3rem; color: var(--akzent-hell, #d6eade); }
.kennzahl { display: inline-block; background: #f1eee6; border-radius: 4px; .kennzahl { display: inline-block; background: #f1eee6; border-radius: 4px;
padding: .3rem .7rem; margin: .15rem .3rem .15rem 0; font-size: .9rem; } padding: .3rem .7rem; margin: .15rem .3rem .15rem 0; font-size: .9rem; }
.kennzahl b { color: var(--akzent); } .kennzahl b { color: var(--akzent); }
.hinweis { font-size: .8rem; color: #6b6557; } .hinweis { font-size: .8rem; color: #6b6557; }
#gruppenUebersicht tr.fixiert td { background: #e6e3dc; color: #555; }
.varianten { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: .6rem; }
.variante {
border: 1px solid var(--rand); border-radius: 6px; background: white;
padding: .5rem .8rem; cursor: pointer; font-size: .85rem; text-align: left;
color: #2a2a24; min-width: 11rem;
}
.variante.aktiv { border-color: var(--akzent); background: #e6f0ea;
box-shadow: 0 0 0 1px var(--akzent); }
.variante b { color: var(--akzent); font-size: 1rem; }
.variante .zeile { display: block; color: #6b6557; }
</style> </style>
</head> </head>
<body> <body>
<header> <header>
<h1>Sitz &amp; Platz <small style="font-weight:normal">— Testoberfläche (Meilenstein 1)</small></h1> <h1>Sitz &amp; Platz <small style="font-weight:normal">— Testoberfläche (Meilenstein 1)</small></h1>
<p>Session-basiert, nichts wird dauerhaft gespeichert (TTL 24 h). Sitzung: <code id="sitzungsId">wird angelegt…</code></p> <p>Session-basiert, nichts wird dauerhaft gespeichert (TTL 24 h). Sitzung: <code id="sitzungsId">wird angelegt…</code>
· <a href="/editor.html" style="color:#d6eade">grafischer Tisch-Editor</a></p>
</header> </header>
<main> <main>
@@ -78,10 +98,9 @@
<button type="button" class="sekundaer" onclick="presetReihe()">Preset: 4er-Reihe</button> <button type="button" class="sekundaer" onclick="presetReihe()">Preset: 4er-Reihe</button>
<button type="button" class="sekundaer" onclick="presetRaster()">Preset: 3×3-Raster</button> <button type="button" class="sekundaer" onclick="presetRaster()">Preset: 3×3-Raster</button>
<br> <br>
<label class="hinweis">Oder eine bestehende <code>tische.ini</code> laden <label class="hinweis">Oder eine bestehende <code>tische.ini</code> auswählen
(z.&nbsp;B. aus <code>work/hochzeit</code>):</label> (z.&nbsp;B. aus <code>work/hochzeit</code>) — wird sofort geladen:</label>
<input type="file" id="tischDatei" accept=".ini,text/plain"> <input type="file" id="tischDatei" accept=".ini,text/plain" onchange="tischDateiLaden()">
<button type="button" class="sekundaer" onclick="tischDateiLaden()">tische.ini laden</button>
<br> <br>
<button type="button" onclick="tischeSpeichern()">Tische speichern</button> <button type="button" onclick="tischeSpeichern()">Tische speichern</button>
<div class="status" id="tischStatus"></div> <div class="status" id="tischStatus"></div>
@@ -91,9 +110,10 @@
<h2>2. Gästeliste (CSV)</h2> <h2>2. Gästeliste (CSV)</h2>
<p class="hinweis">Spalten: <code>Vorname;Nachname;Titel;Gruppe;Tisch;Anzahl</code> <p class="hinweis">Spalten: <code>Vorname;Nachname;Titel;Gruppe;Tisch;Anzahl</code>
<code>Gruppe</code> hält Personen zusammen (leer = Einzelgast), <code>Gruppe</code> hält Personen zusammen (leer = Einzelgast),
<code>Tisch</code> setzt VIPs fest (z.&nbsp;B. Brautpaar an Tisch 1), <code>Tisch</code> fixiert Gäste an einem Tisch (z.&nbsp;B. Brautpaar an Tisch 1),
<code>Anzahl</code> expandiert eine Zeile in mehrere Buchungen <code>Anzahl</code> expandiert eine Zeile in mehrere Buchungen
(anonyme Sammelbuchung). Datei hochladen <em>oder</em> direkt hier bearbeiten:</p> (anonyme Sammelbuchung). Eine Datei auswählen (wird sofort übernommen)
<em>oder</em> hier direkt bearbeiten und übernehmen:</p>
<textarea id="csvText"></textarea> <textarea id="csvText"></textarea>
<br> <br>
<input type="file" id="csvDatei" accept=".csv,text/csv"> <input type="file" id="csvDatei" accept=".csv,text/csv">
@@ -104,16 +124,27 @@
</section> </section>
<section> <section>
<h2>3. Sitzordnung berechnen</h2> <h2>3. Sitzordnung berechnen &amp; Varianten vergleichen</h2>
<p class="hinweis">Jeder Klick startet den genetischen Algorithmus neu und liefert <p class="hinweis">Ein Lauf liefert bis zu drei <em>unterschiedliche</em> gute
eine neue Variante — die Wertigkeit (0 = perfekt, negativer = schlechter) Sitzordnungen zum Vergleich — die Wertigkeit (0 = perfekt, negativer = schlechter),
macht Varianten vergleichbar.</p> die Zahl getrennter Gruppen und allein sitzende Personen machen sie vergleichbar.
Variante anklicken, um Tische und Raumplan umzuschalten; jeder weitere Klick auf
„Berechnen“ startet einen frischen Lauf. Über das <em>Optimierungsprofil</em> lassen sich
Bewertungs-Vorgehen vergleichen (z.&nbsp;B. <code>default</code> vs.
<code>locker</code>): Profil wählen und neu berechnen.</p>
<label class="hinweis">Optimierungsprofil:
<select id="strafenWahl"></select></label>
<button type="button" id="berechnenKnopf" onclick="berechnen()" disabled>Sitzordnung berechnen</button> <button type="button" id="berechnenKnopf" onclick="berechnen()" disabled>Sitzordnung berechnen</button>
<div class="status" id="rechnenStatus"></div> <div class="status" id="rechnenStatus"></div>
<div class="varianten" id="variantenListe"></div>
<div id="kennzahlen"></div> <div id="kennzahlen"></div>
<p class="hinweis" style="margin-bottom:0">Im Raumplan mit der Maus über eine Person
fahren: Tooltip zeigt Name &amp; Gruppe, ein Kasten listet alle Namen dieser Gruppe,
und die Gruppe wird im Plan hervorgehoben.</p>
<div id="svgPlan"></div>
<div id="ergebnisTabellen"></div> <div id="ergebnisTabellen"></div>
<img id="svgBild" alt="" style="display:none">
</section> </section>
<div id="gruppeBox"></div>
</main> </main>
<script> <script>
@@ -139,6 +170,23 @@ function status(id, text, klasse) {
} }
/* ------------------------------------------------ 1. Tische */ /* ------------------------------------------------ 1. Tische */
let geladenerRadius = 1.5; // zuletzt aus der Session geladener Nachbar-Radius
async function tischeAusSessionLaden() {
// Sektion 1 aus dem serverseitigen Session-Layout fuellen (z.B. was der
// grafische Editor gespeichert hat) statt fest das Preset zu zeigen.
try {
const r = await api('/sitzung/' + sitzung + '/tische');
if (r.tische && r.tische.length) {
tischeLeeren();
for (const t of r.tische) tischZeile(t.plaetze, t.x, t.y, t.id);
geladenerRadius = r.nachbarRadius || 1.5;
return;
}
} catch (e) { /* frische/abgelaufene Session — Preset als Fallback */ }
presetReihe();
}
function tischZeile(plaetze, x, y, tid) { function tischZeile(plaetze, x, y, tid) {
const tbody = document.querySelector('#tischTabelle tbody'); const tbody = document.querySelector('#tischTabelle tbody');
const nr = tid ?? tbody.children.length + 1; const nr = tid ?? tbody.children.length + 1;
@@ -190,7 +238,7 @@ async function tischeSpeichern() {
const r = await api('/sitzung/' + sitzung + '/tische', { const r = await api('/sitzung/' + sitzung + '/tische', {
method: 'POST', method: 'POST',
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ tische }), body: JSON.stringify({ tische, nachbarRadius: geladenerRadius }),
}); });
const nachbarn = r.tische.map(t => 'Tisch ' + t.id + ' ↔ [' + t.nachbarn.join(', ') + ']').join(' '); const nachbarn = r.tische.map(t => 'Tisch ' + t.id + ' ↔ [' + t.nachbarn.join(', ') + ']').join(' ');
status('tischStatus', '✓ ' + r.tische.length + ' Tische, ' + r.plaetzeGesamt + status('tischStatus', '✓ ' + r.tische.length + ' Tische, ' + r.plaetzeGesamt +
@@ -216,6 +264,7 @@ async function tischDateiLaden() {
'„Tische speichern“ ist nur nach Änderungen nötig.', 'ok'); '„Tische speichern“ ist nur nach Änderungen nötig.', 'ok');
berechnenFreigeben(); berechnenFreigeben();
} catch (e) { status('tischStatus', 'Fehler: ' + e.message, 'fehler'); } } catch (e) { status('tischStatus', 'Fehler: ' + e.message, 'fehler'); }
finally { eingabe.value = ''; } // damit dieselbe Datei erneut auswählbar ist
} }
/* ------------------------------------------------ 2. Gäste */ /* ------------------------------------------------ 2. Gäste */
@@ -236,29 +285,63 @@ Gast;Kollegium;;Kollegen;;4
Karl;Einzelgast;;;; Karl;Einzelgast;;;;
`; `;
async function gaesteHochladen() { async function csvDateiGewaehlt(ev) {
const dateiInput = document.getElementById('csvDatei'); // Ausgewaehlte CSV sofort sichtbar in die Textarea laden (Single Source):
let blob; // dekodieren wie das Backend (utf-8-sig, sonst cp1252), BOM strippen.
if (dateiInput.files.length > 0) { const datei = ev.target.files[0];
blob = dateiInput.files[0]; if (!datei) return;
} else { const puffer = await datei.arrayBuffer();
blob = new Blob([document.getElementById('csvText').value], { type: 'text/csv' }); let text;
try {
text = new TextDecoder('utf-8', { fatal: true }).decode(puffer);
} catch (e) {
text = new TextDecoder('windows-1252').decode(puffer); // Excel/Windows
} }
text = text.replace(/^/, '');
document.getElementById('csvText').value = text;
ev.target.value = ''; // damit dieselbe Datei erneut auswählbar ist
// direkt uebernehmen: die ausgewaehlte Datei wird sofort geladen (die
// Textarea ist bereits befuellt und dient gaesteHochladen als Quelle)
await gaesteHochladen();
}
async function gaesteHochladen() {
// immer die (ggf. aus einer Datei befuellte) Textarea senden
const blob = new Blob([document.getElementById('csvText').value], { type: 'text/csv' });
const form = new FormData(); const form = new FormData();
form.append('datei', blob, 'gaeste.csv'); form.append('datei', blob, 'gaeste.csv');
try { try {
const r = await api('/sitzung/' + sitzung + '/personen', { method: 'POST', body: form }); const r = await api('/sitzung/' + sitzung + '/personen', { method: 'POST', body: form });
status('gaesteStatus', '✓ ' + r.personen + ' Personen in ' + r.gruppen.length + status('gaesteStatus', '✓ ' + r.personen + ' Personen in ' + r.gruppen.length +
' Gruppen, dazu ' + r.vips + ' VIPs mit festem Tisch.', 'ok'); ' Gruppen' + (r.fixiert ? ', dazu ' + r.fixiert +
' fixierte Personen an festen Tischen' : '') + '.', 'ok');
// regulaere Gruppen, danach die fest platzierten ("fixierten") Gruppen
// grau hinterlegt
const regulaer = r.gruppen.map(g =>
'<tr><td>' + g.name + '</td><td>' + g.anzahl + '</td></tr>').join('');
const fixiert = (r.fixierte || []).map(f =>
'<tr class="fixiert"><td>' + f.name +
' <span class="hinweis">(fixiert an Tisch ' + f.tisch + ')</span></td><td>' +
f.anzahl + '</td></tr>').join('');
const html = '<table><thead><tr><th>Gruppe</th><th>Personen</th></tr></thead><tbody>' + const html = '<table><thead><tr><th>Gruppe</th><th>Personen</th></tr></thead><tbody>' +
r.gruppen.map(g => '<tr><td>' + g.name + '</td><td>' + g.anzahl + '</td></tr>').join('') + regulaer + fixiert + '</tbody></table>';
'</tbody></table>';
document.getElementById('gruppenUebersicht').innerHTML = html; document.getElementById('gruppenUebersicht').innerHTML = html;
berechnenFreigeben(); berechnenFreigeben();
} catch (e) { status('gaesteStatus', 'Fehler: ' + e.message, 'fehler'); } } catch (e) { status('gaesteStatus', 'Fehler: ' + e.message, 'fehler'); }
} }
/* ------------------------------------------------ 3. Berechnen */ /* ------------------------------------------------ 3. Berechnen */
async function strafprofileLaden() {
// Auswahl der Strafprofile aus strafen.cfg fuellen (z.B. default, locker)
try {
const r = await api('/strafprofile');
const sel = document.getElementById('strafenWahl');
sel.innerHTML = r.profile.map(p =>
'<option value="' + p + '"' + (p === r.vorgabe ? ' selected' : '') +
'>' + p + '</option>').join('');
} catch (e) { /* Auswahl bleibt leer -> Backend nutzt sein Default */ }
}
async function berechnenFreigeben() { async function berechnenFreigeben() {
try { try {
const s = await api('/sitzung/' + sitzung); const s = await api('/sitzung/' + sitzung);
@@ -266,20 +349,25 @@ async function berechnenFreigeben() {
} catch (e) { /* Session ggf. abgelaufen — beim Berechnen gemeldet */ } } catch (e) { /* Session ggf. abgelaufen — beim Berechnen gemeldet */ }
} }
let letzterLauf = null; // Antwort des letzten Berechnen-Laufs (mit Varianten)
async function berechnen() { async function berechnen() {
const knopf = document.getElementById('berechnenKnopf'); const knopf = document.getElementById('berechnenKnopf');
knopf.disabled = true; knopf.disabled = true;
status('rechnenStatus', 'Der genetische Algorithmus läuft…'); status('rechnenStatus', 'Der genetische Algorithmus läuft…');
try { try {
const r = await api('/sitzung/' + sitzung + '/berechnen', { method: 'POST' }); const profil = document.getElementById('strafenWahl').value || 'default';
status('rechnenStatus', '✓ Variante ' + r.variante + ' berechnet.', 'ok'); const r = await api('/sitzung/' + sitzung + '/berechnen?varianten=3&strafen=' +
knopf.textContent = 'Neue Variante berechnen'; encodeURIComponent(profil), { method: 'POST' });
zeigeErgebnis(r); letzterLauf = r;
const svg = await fetch('/sitzung/' + sitzung + '/ergebnis.svg'); status('rechnenStatus', '✓ Lauf ' + r.lauf + ' (Optimierungsprofil „' + r.strafen + '“): ' +
const svgText = await svg.text(); r.varianten.length +
const bild = document.getElementById('svgBild'); (r.varianten.length === 1
bild.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svgText); ? ' Variante gefunden (der Lauf konvergierte auf eine Sitzordnung).'
bild.style.display = 'block'; : ' unterschiedliche Varianten zum Vergleich.'), 'ok');
knopf.textContent = 'Neuen Lauf berechnen';
zeigeVariantenListe(r);
await zeigeVariante(0);
} catch (e) { } catch (e) {
status('rechnenStatus', 'Fehler: ' + e.message, 'fehler'); status('rechnenStatus', 'Fehler: ' + e.message, 'fehler');
} finally { } finally {
@@ -287,15 +375,32 @@ async function berechnen() {
} }
} }
function zeigeErgebnis(r) { function zeigeVariantenListe(r) {
const getrennte = r.gruppen.filter(g => g.teilungen > 0).length; document.getElementById('variantenListe').innerHTML = r.varianten.map((v, i) =>
'<button type="button" class="variante" data-i="' + i + '" onclick="zeigeVariante(' + i + ')">' +
'<b>Variante ' + v.nr + '</b>' +
'<span class="zeile">Wertigkeit: ' + v.kennzahlen.wertigkeit + '</span>' +
'<span class="zeile">getrennte Gruppen: ' + v.kennzahlen.getrennteGruppen +
' (' + v.kennzahlen.teilungenGesamt + ' Teilungen)</span>' +
'<span class="zeile">allein sitzend: ' + v.kennzahlen.alleinePersonen + '</span>' +
'</button>').join('');
}
async function zeigeVariante(i) {
if (!letzterLauf || !letzterLauf.varianten[i]) return;
const v = letzterLauf.varianten[i];
document.querySelectorAll('#variantenListe .variante').forEach(el =>
el.classList.toggle('aktiv', parseInt(el.dataset.i, 10) === i));
document.getElementById('kennzahlen').innerHTML = document.getElementById('kennzahlen').innerHTML =
'<span class="kennzahl">Wertigkeit: <b>' + r.wertigkeit + '</b></span>' + '<span class="kennzahl">Variante: <b>' + v.nr + '</b> (Lauf ' + letzterLauf.lauf + ')</span>' +
'<span class="kennzahl">Variante: <b>' + r.variante + '</b></span>' + '<span class="kennzahl">Optimierungsprofil: <b>' + letzterLauf.strafen + '</b></span>' +
'<span class="kennzahl">getrennte Gruppen: <b>' + getrennte + '</b></span>'; '<span class="kennzahl">Wertigkeit: <b>' + v.kennzahlen.wertigkeit + '</b></span>' +
'<span class="kennzahl">getrennte Gruppen: <b>' + v.kennzahlen.getrennteGruppen + '</b></span>' +
'<span class="kennzahl">allein sitzend: <b>' + v.kennzahlen.alleinePersonen + '</b></span>';
let html = '<table><thead><tr><th>Tisch</th><th>Belegung</th><th>Gäste (Gruppe)</th></tr></thead><tbody>'; let html = '<table><thead><tr><th>Tisch</th><th>Belegung</th><th>Gäste (Gruppe)</th></tr></thead><tbody>';
for (const t of r.tische) { for (const t of v.tische) {
const gaeste = t.personen.map(p => const gaeste = t.personen.map(p =>
((p.titel ? p.titel + ' ' : '') + p.vorname + ' ' + p.nachname + ((p.titel ? p.titel + ' ' : '') + p.vorname + ' ' + p.nachname +
' <span class="hinweis">(' + p.gruppe + ')</span>')).join(', '); ' <span class="hinweis">(' + p.gruppe + ')</span>')).join(', ');
@@ -306,24 +411,89 @@ function zeigeErgebnis(r) {
html += '<h2 style="margin-top:1rem">Gruppen</h2>' + html += '<h2 style="margin-top:1rem">Gruppen</h2>' +
'<table><thead><tr><th>Gruppe</th><th>Personen</th><th>Teilungen</th><th>Strafpunkte</th></tr></thead><tbody>' + '<table><thead><tr><th>Gruppe</th><th>Personen</th><th>Teilungen</th><th>Strafpunkte</th></tr></thead><tbody>' +
r.gruppen.map(g => '<tr><td>' + g.name + '</td><td>' + g.anzahl + '</td><td>' + v.gruppen.map(g => '<tr><td>' + g.name + '</td><td>' + g.anzahl + '</td><td>' +
g.teilungen + '</td><td>' + g.wert + '</td></tr>').join('') + g.teilungen + '</td><td>' + g.wert + '</td></tr>').join('') +
'</tbody></table>'; '</tbody></table>';
document.getElementById('ergebnisTabellen').innerHTML = html; document.getElementById('ergebnisTabellen').innerHTML = html;
// Raumplan der gewaehlten Variante — inline einbetten (nicht als <img>),
// damit die <title>-Tooltips und das Gruppen-Hover funktionieren
try {
const antwort = await fetch('/sitzung/' + sitzung + '/ergebnis.svg?variante=' + v.nr);
const svgText = await antwort.text();
const plan = document.getElementById('svgPlan');
plan.innerHTML = svgText.replace(/<\?xml[^>]*\?>/, ''); // XML-Prolog raus
gruppeInteraktion(plan.querySelector('svg'));
} catch (e) { /* SVG optional — Tabellen stehen schon da */ }
}
function escHtml(s) {
return (s || '').replace(/[&<>"]/g, c =>
({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[c]));
}
// Hover ueber einen Personenkreis: alle Kreise derselben Gruppe hervorheben
// und einen Kasten mit der Namensliste dieser Gruppe zeigen. Die Namen kommen
// direkt aus den data-name/data-gruppe-Attributen der SVG (vom Kern erzeugt).
function gruppeInteraktion(svg) {
if (!svg) return;
const box = document.getElementById('gruppeBox');
let markiert = null;
svg.querySelectorAll('.person').forEach(kreis => {
kreis.addEventListener('mouseenter', () => {
const gruppe = kreis.dataset.gruppe || '';
const gleiche = svg.querySelectorAll(
'.person[data-gruppe="' + (window.CSS ? CSS.escape(gruppe) : gruppe) + '"]');
gleiche.forEach(k => k.classList.add('aktiv'));
markiert = gleiche;
const namen = [...gleiche].map(k => k.dataset.name || '');
box.innerHTML = '<b>' + escHtml(gruppe) + ' (' + namen.length + ')</b>' +
namen.map(escHtml).join('<br>');
box.style.display = 'block';
});
kreis.addEventListener('mouseleave', () => {
if (markiert) markiert.forEach(k => k.classList.remove('aktiv'));
markiert = null;
box.style.display = 'none';
});
});
svg.addEventListener('mousemove', e => {
box.style.left = (e.clientX + 14) + 'px';
box.style.top = (e.clientY + 14) + 'px';
});
} }
/* ------------------------------------------------ Start */ /* ------------------------------------------------ Start */
window.addEventListener('DOMContentLoaded', async () => { window.addEventListener('DOMContentLoaded', async () => {
document.getElementById('csvText').value = beispielCSV; document.getElementById('csvText').value = beispielCSV;
presetReihe(); document.getElementById('csvDatei').addEventListener('change', csvDateiGewaehlt);
strafprofileLaden();
try { try {
const r = await api('/sitzung', { method: 'POST' }); sitzung = await sitzungHolen();
sitzung = r.id;
document.getElementById('sitzungsId').textContent = sitzung; document.getElementById('sitzungsId').textContent = sitzung;
// Tische aus der (ggf. mit dem Editor geteilten) Session laden;
// Preset nur, wenn die Session noch keine Tische hat
await tischeAusSessionLaden();
berechnenFreigeben();
} catch (e) { } catch (e) {
document.getElementById('sitzungsId').textContent = 'Fehler: ' + e.message; document.getElementById('sitzungsId').textContent = 'Fehler: ' + e.message;
presetReihe();
} }
}); });
// Session mit dem grafischen Editor (editor.html) ueber localStorage teilen:
// eine bestehende, noch gueltige Sitzung wiederverwenden statt jedes Mal
// eine neue anzulegen — so wirkt ein im Editor gebautes Layout hier weiter.
async function sitzungHolen() {
let id = localStorage.getItem('platzSitzung');
if (id) {
const ok = await fetch('/sitzung/' + id).then(r => r.ok).catch(() => false);
if (ok) return id;
}
const r = await api('/sitzung', { method: 'POST' });
localStorage.setItem('platzSitzung', r.id);
return r.id;
}
</script> </script>
</body> </body>
</html> </html>
+100 -100
View File
@@ -1,120 +1,120 @@
Aksoy, Rainer, = Hof 1, Tisch 1, Nummer 8 Aksoy, Rainer, = Hof 1, Tisch 1, Nummer 13
Aksoy, Renate, = Hof 1, Tisch 1, Nummer 4 Aksoy, Renate, = Hof 1, Tisch 1, Nummer 10
Aydin, Horst, = Hof 1, Tisch 15, Nummer 5 Aydin, Horst, = Hof 1, Tisch 15, Nummer 4
Aydin, Ursula, = Hof 1, Tisch 15, Nummer 6 Aydin, Ursula, = Hof 1, Tisch 15, Nummer 5
Barth, Hannelore, = Hof 1, Tisch 9, Nummer 3 Barth, Hannelore, = Hof 1, Tisch 9, Nummer 3
Berger, Sergej, = Hof 1, Tisch 8, Nummer 8 Berger, Sergej, = Hof 1, Tisch 8, Nummer 3
Brandt, Andreas, = Hof 1, Tisch 14, Nummer 2 Brandt, Andreas, = Hof 1, Tisch 14, Nummer 2
Brandt, Anja, = Hof 1, Tisch 14, Nummer 8 Brandt, Anja, = Hof 1, Tisch 14, Nummer 6
Brandt, Anton, = Hof 1, Tisch 16, Nummer 10 Brandt, Anton, = Hof 1, Tisch 16, Nummer 9
Brandt, Ben, = Hof 1, Tisch 17, Nummer 6 Brandt, Ben, = Hof 1, Tisch 17, Nummer 2
Brandt, Daniel, = Hof 1, Tisch 11, Nummer 5 Brandt, Daniel, = Hof 1, Tisch 11, Nummer 8
Brandt, Felix, = Hof 1, Tisch 16, Nummer 12 Brandt, Felix, = Hof 1, Tisch 16, Nummer 7
Brandt, Frieda, = Hof 1, Tisch 16, Nummer 7 Brandt, Frieda, = Hof 1, Tisch 16, Nummer 10
Brandt, Greta, = Hof 1, Tisch 16, Nummer 8 Brandt, Greta, = Hof 1, Tisch 16, Nummer 12
Brandt, Helga, = Hof 1, Tisch 1, Nummer 6 Brandt, Helga, = Hof 1, Tisch 1, Nummer 5
Brandt, Julia, = Hof 1, Tisch 1, Nummer 10 Brandt, Julia, = Hof 1, Tisch 1, Nummer 2
Brandt, Kathrin, = Hof 1, Tisch 11, Nummer 2 Brandt, Kathrin, = Hof 1, Tisch 11, Nummer 9
Brandt, Lena, = Hof 1, Tisch 14, Nummer 4 Brandt, Lena, = Hof 1, Tisch 14, Nummer 3
Brandt, Milan, = Hof 1, Tisch 14, Nummer 7 Brandt, Milan, = Hof 1, Tisch 14, Nummer 5
Brandt, Paul, = Hof 1, Tisch 17, Nummer 4 Brandt, Paul, = Hof 1, Tisch 17, Nummer 3
Brandt, Sofia, = Hof 1, Tisch 14, Nummer 9 Brandt, Sofia, = Hof 1, Tisch 14, Nummer 7
Brandt, Theo, = Hof 1, Tisch 14, Nummer 3 Brandt, Theo, = Hof 1, Tisch 14, Nummer 4
Brandt, Werner, = Hof 1, Tisch 1, Nummer 5 Brandt, Werner, = Hof 1, Tisch 1, Nummer 4
Busch, Stefanie, = Hof 1, Tisch 8, Nummer 3 Busch, Stefanie, = Hof 1, Tisch 8, Nummer 7
Demir, Elif, = Hof 1, Tisch 10, Nummer 3 Demir, Elif, = Hof 1, Tisch 10, Nummer 2
Demir, Hannelore, = Hof 1, Tisch 13, Nummer 2 Demir, Hannelore, = Hof 1, Tisch 13, Nummer 4
Demir, Ingrid, = Hof 1, Tisch 13, Nummer 8 Demir, Ingrid, = Hof 1, Tisch 13, Nummer 2
Demir, Monika, = Hof 1, Tisch 13, Nummer 5 Demir, Monika, = Hof 1, Tisch 13, Nummer 3
Dietrich, Jennifer, = Hof 1, Tisch 2, Nummer 9 Dietrich, Jennifer, = Hof 1, Tisch 2, Nummer 5
Dietrich, Nicole, = Hof 1, Tisch 12, Nummer 2 Dietrich, Nicole, = Hof 1, Tisch 12, Nummer 7
Erdem, Erika, = Hof 1, Tisch 14, Nummer 5 Erdem, Erika, = Hof 1, Tisch 15, Nummer 7
Erdem, Gerhard, = Hof 1, Tisch 9, Nummer 4 Erdem, Gerhard, = Hof 1, Tisch 9, Nummer 5
Erdem, Rainer, = Hof 1, Tisch 9, Nummer 9 Erdem, Rainer, = Hof 1, Tisch 9, Nummer 6
Esposito, Christian, = Hof 1, Tisch 12, Nummer 3 Esposito, Christian, = Hof 1, Tisch 12, Nummer 4
Esposito, Gisela, = Hof 1, Tisch 9, Nummer 8 Esposito, Gisela, = Hof 1, Tisch 9, Nummer 7
Esposito, Julia, = Hof 1, Tisch 8, Nummer 9 Esposito, Julia, = Hof 1, Tisch 2, Nummer 4
Fischer, Heinz, = Hof 1, Tisch 15, Nummer 9 Fischer, Heinz, = Hof 1, Tisch 3, Nummer 3
Fischer, Helga, = Hof 1, Tisch 15, Nummer 2 Fischer, Helga, = Hof 1, Tisch 3, Nummer 2
Fischer, Nicole, = Hof 1, Tisch 12, Nummer 6 Fischer, Nicole, = Hof 1, Tisch 12, Nummer 2
Fischer, Sven, = Hof 1, Tisch 4, Nummer 3 Fischer, Sven, = Hof 1, Tisch 4, Nummer 9
Frank, Erika, = Hof 1, Tisch 9, Nummer 2 Frank, Erika, = Hof 1, Tisch 9, Nummer 4
Frank, Nadine, = Hof 1, Tisch 11, Nummer 8 Frank, Nadine, = Hof 1, Tisch 11, Nummer 2
Frank, Timo, = Hof 1, Tisch 10, Nummer 7 Frank, Timo, = Hof 1, Tisch 10, Nummer 6
Frank, Tobias, = Hof 1, Tisch 1, Nummer 7 Frank, Tobias, = Hof 1, Tisch 1, Nummer 9
Franke, Brigitte, = Hof 1, Tisch 9, Nummer 5 Franke, Brigitte, = Hof 1, Tisch 9, Nummer 8
Hansen, Olga, = Hof 1, Tisch 11, Nummer 4 Hansen, Olga, = Hof 1, Tisch 11, Nummer 5
Hansen, Wolfgang, = Hof 1, Tisch 9, Nummer 6 Hansen, Wolfgang, = Hof 1, Tisch 9, Nummer 2
Hoffmann, Lena, = Hof 1, Tisch 12, Nummer 5 Hoffmann, Lena, = Hof 1, Tisch 12, Nummer 5
Horn, Daniel, = Hof 1, Tisch 11, Nummer 3 Horn, Daniel, = Hof 1, Tisch 11, Nummer 6
Horn, Svenja, = Hof 1, Tisch 2, Nummer 8 Horn, Svenja, = Hof 1, Tisch 2, Nummer 7
Klein, Stefan, = Hof 1, Tisch 10, Nummer 8 Klein, Stefan, = Hof 1, Tisch 10, Nummer 5
Koch, Andreas, = Hof 1, Tisch 8, Nummer 5 Koch, Andreas, = Hof 1, Tisch 8, Nummer 8
Koch, Giovanna, = Hof 1, Tisch 8, Nummer 6 Koch, Giovanna, = Hof 1, Tisch 2, Nummer 3
Kovac, Giovanna, = Hof 1, Tisch 2, Nummer 3 Kovac, Giovanna, = Hof 1, Tisch 8, Nummer 4
Kraus, Dennis, = Hof 1, Tisch 12, Nummer 8 Kraus, Dennis, = Hof 1, Tisch 12, Nummer 8
Kraus, Matteo, = Hof 1, Tisch 16, Nummer 3 Kraus, Matteo, = Hof 1, Tisch 16, Nummer 8
Kraus, Melanie, = Hof 1, Tisch 12, Nummer 4 Kraus, Melanie, = Hof 1, Tisch 12, Nummer 9
Kuhn, Leni, = Hof 1, Tisch 16, Nummer 9 Kuhn, Leni, = Hof 1, Tisch 16, Nummer 2
Kuhn, Sarah, = Hof 1, Tisch 15, Nummer 3 Kuhn, Sarah, = Hof 1, Tisch 14, Nummer 9
Kuhn, Stefan, = Hof 1, Tisch 2, Nummer 5 Kuhn, Stefan, = Hof 1, Tisch 2, Nummer 9
Kuhn, Timo, = Hof 1, Tisch 15, Nummer 8 Kuhn, Timo, = Hof 1, Tisch 14, Nummer 8
Lange, Milan, = Hof 1, Tisch 11, Nummer 7 Lange, Milan, = Hof 1, Tisch 11, Nummer 7
Meyer, Anton, = Hof 1, Tisch 17, Nummer 2 Meyer, Anton, = Hof 1, Tisch 17, Nummer 4
Meyer, Christian, = Hof 1, Tisch 2, Nummer 7 Meyer, Christian, = Hof 1, Tisch 2, Nummer 6
Meyer, Ida, = Hof 1, Tisch 17, Nummer 3 Meyer, Ida, = Hof 1, Tisch 17, Nummer 5
Meyer, Marco, = Hof 1, Tisch 5, Nummer 6 Meyer, Marco, = Hof 1, Tisch 5, Nummer 8
Meyer, Mila, = Hof 1, Tisch 16, Nummer 13 Meyer, Mila, = Hof 1, Tisch 16, Nummer 11
Meyer, Sandra, = Hof 1, Tisch 5, Nummer 4 Meyer, Sandra, = Hof 1, Tisch 5, Nummer 9
Meyer, Wolfgang, = Hof 1, Tisch 9, Nummer 7 Meyer, Wolfgang, = Hof 1, Tisch 9, Nummer 9
Musikverein, Gast, = Hof 1, Tisch 4, Nummer 2 Musikverein, Gast, = Hof 1, Tisch 4, Nummer 2
Musikverein, Gast, = Hof 1, Tisch 4, Nummer 3
Musikverein, Gast, = Hof 1, Tisch 4, Nummer 4 Musikverein, Gast, = Hof 1, Tisch 4, Nummer 4
Musikverein, Gast, = Hof 1, Tisch 4, Nummer 5 Musikverein, Gast, = Hof 1, Tisch 4, Nummer 5
Musikverein, Gast, = Hof 1, Tisch 4, Nummer 6 Musikverein, Gast, = Hof 1, Tisch 4, Nummer 6
Musikverein, Gast, = Hof 1, Tisch 4, Nummer 7 Musikverein, Gast, = Hof 1, Tisch 4, Nummer 7
Musikverein, Gast, = Hof 1, Tisch 4, Nummer 8 Musikverein, Gast, = Hof 1, Tisch 4, Nummer 8
Musikverein, Gast, = Hof 1, Tisch 4, Nummer 9
Musikverein, Gast, = Hof 1, Tisch 5, Nummer 2 Musikverein, Gast, = Hof 1, Tisch 5, Nummer 2
Musikverein, Gast, = Hof 1, Tisch 5, Nummer 3 Musikverein, Gast, = Hof 1, Tisch 5, Nummer 3
Musikverein, Gast, = Hof 1, Tisch 5, Nummer 4
Musikverein, Gast, = Hof 1, Tisch 5, Nummer 5 Musikverein, Gast, = Hof 1, Tisch 5, Nummer 5
Musikverein, Gast, = Hof 1, Tisch 5, Nummer 6
Musikverein, Gast, = Hof 1, Tisch 5, Nummer 7 Musikverein, Gast, = Hof 1, Tisch 5, Nummer 7
Musikverein, Gast, = Hof 1, Tisch 5, Nummer 8 Peters, Melanie, = Hof 1, Tisch 8, Nummer 9
Musikverein, Gast, = Hof 1, Tisch 5, Nummer 9
Peters, Melanie, = Hof 1, Tisch 8, Nummer 7
Peters, Yusuf, = Hof 1, Tisch 8, Nummer 2 Peters, Yusuf, = Hof 1, Tisch 8, Nummer 2
Polat, Matthias, = Hof 1, Tisch 12, Nummer 7 Polat, Matthias, = Hof 1, Tisch 12, Nummer 3
Roth, Stefanie, = Hof 1, Tisch 2, Nummer 6 Roth, Stefanie, = Hof 1, Tisch 2, Nummer 8
Schmidt, Dennis, = Hof 1, Tisch 2, Nummer 2 Schmidt, Dennis, = Hof 1, Tisch 8, Nummer 5
Schmitt, Markus, = Hof 1, Tisch 11, Nummer 6 Schmitt, Markus, = Hof 1, Tisch 11, Nummer 3
Schwarz, Elias, = Hof 1, Tisch 16, Nummer 4 Schwarz, Elias, = Hof 1, Tisch 16, Nummer 6
Schwarz, Guenter, = Hof 1, Tisch 1, Nummer 9 Schwarz, Guenter, = Hof 1, Tisch 1, Nummer 12
Schwarz, Liam, = Hof 1, Tisch 16, Nummer 5 Schwarz, Liam, = Hof 1, Tisch 16, Nummer 5
Schwarz, Sarah, = Hof 1, Tisch 3, Nummer 2 Schwarz, Sarah, = Hof 1, Tisch 15, Nummer 3
Schwarz, Yusuf, = Hof 1, Tisch 3, Nummer 3 Schwarz, Yusuf, = Hof 1, Tisch 15, Nummer 2
Simon, Jennifer, = Hof 1, Tisch 10, Nummer 2 Simon, Jennifer, = Hof 1, Tisch 10, Nummer 3
Simon, Patrick, = Hof 1, Tisch 2, Nummer 4 Simon, Patrick, = Hof 1, Tisch 8, Nummer 6
Simon, Stefanie, = Hof 1, Tisch 10, Nummer 5 Simon, Stefanie, = Hof 1, Tisch 10, Nummer 8
Sommer, Daniel, = Hof 1, Tisch 1, Nummer 2 Sommer, Daniel, = Hof 1, Tisch 1, Nummer 3
Sommer, Dennis, = Hof 1, Tisch 13, Nummer 4 Sommer, Dennis, = Hof 1, Tisch 13, Nummer 7
Sommer, Dennis, = Hof 1, Tisch 15, Nummer 4 Sommer, Dennis, = Hof 1, Tisch 15, Nummer 8
Sommer, Dieter, = Hof 1, Tisch 1, Nummer 11 Sommer, Dieter, = Hof 1, Tisch 1, Nummer 6
Sommer, Emil, = Hof 1, Tisch 16, Nummer 14 Sommer, Emil, = Hof 1, Tisch 16, Nummer 3
Sommer, Ida, = Hof 1, Tisch 16, Nummer 6 Sommer, Ida, = Hof 1, Tisch 16, Nummer 4
Sommer, Jennifer, = Hof 1, Tisch 15, Nummer 7 Sommer, Jennifer, = Hof 1, Tisch 15, Nummer 9
Sommer, Lina, = Hof 1, Tisch 13, Nummer 9 Sommer, Lina, = Hof 1, Tisch 13, Nummer 9
Sommer, Max, = Hof 1, Tisch 16, Nummer 2 Sommer, Max, = Hof 1, Tisch 16, Nummer 14
Sommer, Nicole, = Hof 1, Tisch 13, Nummer 3 Sommer, Nicole, = Hof 1, Tisch 13, Nummer 8
Sommer, Renate, = Hof 1, Tisch 1, Nummer 13 Sommer, Renate, = Hof 1, Tisch 1, Nummer 7
Sommer, Theo, = Hof 1, Tisch 16, Nummer 11 Sommer, Theo, = Hof 1, Tisch 16, Nummer 13
Stein, Andreas, = Hof 1, Tisch 10, Nummer 4 Stein, Andreas, = Hof 1, Tisch 10, Nummer 4
Stein, Werner, = Hof 1, Tisch 1, Nummer 3 Stein, Werner, = Hof 1, Tisch 1, Nummer 11
Tran, Heinz, = Hof 1, Tisch 14, Nummer 6 Tran, Heinz, = Hof 1, Tisch 15, Nummer 6
Vogel, Anton, = Hof 1, Tisch 17, Nummer 5 Vogel, Anton, = Hof 1, Tisch 17, Nummer 6
Vogel, Max, = Hof 1, Tisch 17, Nummer 7 Vogel, Max, = Hof 1, Tisch 17, Nummer 7
Vogel, Sandra, = Hof 1, Tisch 13, Nummer 7 Vogel, Sandra, = Hof 1, Tisch 13, Nummer 6
Vogel, Svenja, = Hof 1, Tisch 8, Nummer 4 Vogel, Svenja, = Hof 1, Tisch 2, Nummer 2
Vogel, Yusuf, = Hof 1, Tisch 13, Nummer 6 Vogel, Yusuf, = Hof 1, Tisch 13, Nummer 5
Wagner, Daniel, = Hof 1, Tisch 10, Nummer 6 Wagner, Daniel, = Hof 1, Tisch 10, Nummer 7
Wagner, Timo, = Hof 1, Tisch 12, Nummer 9 Wagner, Timo, = Hof 1, Tisch 12, Nummer 6
Winkler, Sarah, = Hof 1, Tisch 1, Nummer 12 Winkler, Sarah, = Hof 1, Tisch 1, Nummer 8
Yilmaz, Olga, = Hof 1, Tisch 11, Nummer 9 Yilmaz, Olga, = Hof 1, Tisch 11, Nummer 4
1 Aksoy Rainer = Hof 1 Tisch 1 Nummer 8 Nummer 13
2 Aksoy Renate = Hof 1 Tisch 1 Nummer 4 Nummer 10
3 Aydin Horst = Hof 1 Tisch 15 Nummer 5 Nummer 4
4 Aydin Ursula = Hof 1 Tisch 15 Nummer 6 Nummer 5
5 Barth Hannelore = Hof 1 Tisch 9 Nummer 3 Nummer 3
6 Berger Sergej = Hof 1 Tisch 8 Nummer 8 Nummer 3
7 Brandt Andreas = Hof 1 Tisch 14 Nummer 2 Nummer 2
8 Brandt Anja = Hof 1 Tisch 14 Nummer 8 Nummer 6
9 Brandt Anton = Hof 1 Tisch 16 Nummer 10 Nummer 9
10 Brandt Ben = Hof 1 Tisch 17 Nummer 6 Nummer 2
11 Brandt Daniel = Hof 1 Tisch 11 Nummer 5 Nummer 8
12 Brandt Felix = Hof 1 Tisch 16 Nummer 12 Nummer 7
13 Brandt Frieda = Hof 1 Tisch 16 Nummer 7 Nummer 10
14 Brandt Greta = Hof 1 Tisch 16 Nummer 8 Nummer 12
15 Brandt Helga = Hof 1 Tisch 1 Nummer 6 Nummer 5
16 Brandt Julia = Hof 1 Tisch 1 Nummer 10 Nummer 2
17 Brandt Kathrin = Hof 1 Tisch 11 Nummer 2 Nummer 9
18 Brandt Lena = Hof 1 Tisch 14 Nummer 4 Nummer 3
19 Brandt Milan = Hof 1 Tisch 14 Nummer 7 Nummer 5
20 Brandt Paul = Hof 1 Tisch 17 Nummer 4 Nummer 3
21 Brandt Sofia = Hof 1 Tisch 14 Nummer 9 Nummer 7
22 Brandt Theo = Hof 1 Tisch 14 Nummer 3 Nummer 4
23 Brandt Werner = Hof 1 Tisch 1 Nummer 5 Nummer 4
24 Busch Stefanie = Hof 1 Tisch 8 Nummer 3 Nummer 7
25 Demir Elif = Hof 1 Tisch 10 Nummer 3 Nummer 2
26 Demir Hannelore = Hof 1 Tisch 13 Nummer 2 Nummer 4
27 Demir Ingrid = Hof 1 Tisch 13 Nummer 8 Nummer 2
28 Demir Monika = Hof 1 Tisch 13 Nummer 5 Nummer 3
29 Dietrich Jennifer = Hof 1 Tisch 2 Nummer 9 Nummer 5
30 Dietrich Nicole = Hof 1 Tisch 12 Nummer 2 Nummer 7
31 Erdem Erika = Hof 1 Tisch 14 Tisch 15 Nummer 5 Nummer 7
32 Erdem Gerhard = Hof 1 Tisch 9 Nummer 4 Nummer 5
33 Erdem Rainer = Hof 1 Tisch 9 Nummer 9 Nummer 6
34 Esposito Christian = Hof 1 Tisch 12 Nummer 3 Nummer 4
35 Esposito Gisela = Hof 1 Tisch 9 Nummer 8 Nummer 7
36 Esposito Julia = Hof 1 Tisch 8 Tisch 2 Nummer 9 Nummer 4
37 Fischer Heinz = Hof 1 Tisch 15 Tisch 3 Nummer 9 Nummer 3
38 Fischer Helga = Hof 1 Tisch 15 Tisch 3 Nummer 2 Nummer 2
39 Fischer Nicole = Hof 1 Tisch 12 Nummer 6 Nummer 2
40 Fischer Sven = Hof 1 Tisch 4 Nummer 3 Nummer 9
41 Frank Erika = Hof 1 Tisch 9 Nummer 2 Nummer 4
42 Frank Nadine = Hof 1 Tisch 11 Nummer 8 Nummer 2
43 Frank Timo = Hof 1 Tisch 10 Nummer 7 Nummer 6
44 Frank Tobias = Hof 1 Tisch 1 Nummer 7 Nummer 9
45 Franke Brigitte = Hof 1 Tisch 9 Nummer 5 Nummer 8
46 Hansen Olga = Hof 1 Tisch 11 Nummer 4 Nummer 5
47 Hansen Wolfgang = Hof 1 Tisch 9 Nummer 6 Nummer 2
48 Hoffmann Lena = Hof 1 Tisch 12 Nummer 5 Nummer 5
49 Horn Daniel = Hof 1 Tisch 11 Nummer 3 Nummer 6
50 Horn Svenja = Hof 1 Tisch 2 Nummer 8 Nummer 7
51 Klein Stefan = Hof 1 Tisch 10 Nummer 8 Nummer 5
52 Koch Andreas = Hof 1 Tisch 8 Nummer 5 Nummer 8
53 Koch Giovanna = Hof 1 Tisch 8 Tisch 2 Nummer 6 Nummer 3
54 Kovac Giovanna = Hof 1 Tisch 2 Tisch 8 Nummer 3 Nummer 4
55 Kraus Dennis = Hof 1 Tisch 12 Nummer 8 Nummer 8
56 Kraus Matteo = Hof 1 Tisch 16 Nummer 3 Nummer 8
57 Kraus Melanie = Hof 1 Tisch 12 Nummer 4 Nummer 9
58 Kuhn Leni = Hof 1 Tisch 16 Nummer 9 Nummer 2
59 Kuhn Sarah = Hof 1 Tisch 15 Tisch 14 Nummer 3 Nummer 9
60 Kuhn Stefan = Hof 1 Tisch 2 Nummer 5 Nummer 9
61 Kuhn Timo = Hof 1 Tisch 15 Tisch 14 Nummer 8 Nummer 8
62 Lange Milan = Hof 1 Tisch 11 Nummer 7 Nummer 7
63 Meyer Anton = Hof 1 Tisch 17 Nummer 2 Nummer 4
64 Meyer Christian = Hof 1 Tisch 2 Nummer 7 Nummer 6
65 Meyer Ida = Hof 1 Tisch 17 Nummer 3 Nummer 5
66 Meyer Marco = Hof 1 Tisch 5 Nummer 6 Nummer 8
67 Meyer Mila = Hof 1 Tisch 16 Nummer 13 Nummer 11
68 Meyer Sandra = Hof 1 Tisch 5 Nummer 4 Nummer 9
69 Meyer Wolfgang = Hof 1 Tisch 9 Nummer 7 Nummer 9
70 Musikverein Gast = Hof 1 Tisch 4 Nummer 2 Nummer 2
71 Musikverein Gast = Hof 1 Tisch 4 Nummer 3
72 Musikverein Gast = Hof 1 Tisch 4 Nummer 4 Nummer 4
73 Musikverein Gast = Hof 1 Tisch 4 Nummer 5 Nummer 5
74 Musikverein Gast = Hof 1 Tisch 4 Nummer 6 Nummer 6
75 Musikverein Gast = Hof 1 Tisch 4 Nummer 7 Nummer 7
76 Musikverein Gast = Hof 1 Tisch 4 Nummer 8 Nummer 8
Musikverein Gast = Hof 1 Tisch 4 Nummer 9
77 Musikverein Gast = Hof 1 Tisch 5 Nummer 2 Nummer 2
78 Musikverein Gast = Hof 1 Tisch 5 Nummer 3 Nummer 3
79 Musikverein Gast = Hof 1 Tisch 5 Nummer 4
80 Musikverein Gast = Hof 1 Tisch 5 Nummer 5 Nummer 5
81 Musikverein Gast = Hof 1 Tisch 5 Nummer 6
82 Musikverein Gast = Hof 1 Tisch 5 Nummer 7 Nummer 7
83 Musikverein Peters Gast Melanie = Hof 1 Tisch 5 Tisch 8 Nummer 8 Nummer 9
Musikverein Gast = Hof 1 Tisch 5 Nummer 9
Peters Melanie = Hof 1 Tisch 8 Nummer 7
84 Peters Yusuf = Hof 1 Tisch 8 Nummer 2 Nummer 2
85 Polat Matthias = Hof 1 Tisch 12 Nummer 7 Nummer 3
86 Roth Stefanie = Hof 1 Tisch 2 Nummer 6 Nummer 8
87 Schmidt Dennis = Hof 1 Tisch 2 Tisch 8 Nummer 2 Nummer 5
88 Schmitt Markus = Hof 1 Tisch 11 Nummer 6 Nummer 3
89 Schwarz Elias = Hof 1 Tisch 16 Nummer 4 Nummer 6
90 Schwarz Guenter = Hof 1 Tisch 1 Nummer 9 Nummer 12
91 Schwarz Liam = Hof 1 Tisch 16 Nummer 5 Nummer 5
92 Schwarz Sarah = Hof 1 Tisch 3 Tisch 15 Nummer 2 Nummer 3
93 Schwarz Yusuf = Hof 1 Tisch 3 Tisch 15 Nummer 3 Nummer 2
94 Simon Jennifer = Hof 1 Tisch 10 Nummer 2 Nummer 3
95 Simon Patrick = Hof 1 Tisch 2 Tisch 8 Nummer 4 Nummer 6
96 Simon Stefanie = Hof 1 Tisch 10 Nummer 5 Nummer 8
97 Sommer Daniel = Hof 1 Tisch 1 Nummer 2 Nummer 3
98 Sommer Dennis = Hof 1 Tisch 13 Nummer 4 Nummer 7
99 Sommer Dennis = Hof 1 Tisch 15 Nummer 4 Nummer 8
100 Sommer Dieter = Hof 1 Tisch 1 Nummer 11 Nummer 6
101 Sommer Emil = Hof 1 Tisch 16 Nummer 14 Nummer 3
102 Sommer Ida = Hof 1 Tisch 16 Nummer 6 Nummer 4
103 Sommer Jennifer = Hof 1 Tisch 15 Nummer 7 Nummer 9
104 Sommer Lina = Hof 1 Tisch 13 Nummer 9 Nummer 9
105 Sommer Max = Hof 1 Tisch 16 Nummer 2 Nummer 14
106 Sommer Nicole = Hof 1 Tisch 13 Nummer 3 Nummer 8
107 Sommer Renate = Hof 1 Tisch 1 Nummer 13 Nummer 7
108 Sommer Theo = Hof 1 Tisch 16 Nummer 11 Nummer 13
109 Stein Andreas = Hof 1 Tisch 10 Nummer 4 Nummer 4
110 Stein Werner = Hof 1 Tisch 1 Nummer 3 Nummer 11
111 Tran Heinz = Hof 1 Tisch 14 Tisch 15 Nummer 6 Nummer 6
112 Vogel Anton = Hof 1 Tisch 17 Nummer 5 Nummer 6
113 Vogel Max = Hof 1 Tisch 17 Nummer 7 Nummer 7
114 Vogel Sandra = Hof 1 Tisch 13 Nummer 7 Nummer 6
115 Vogel Svenja = Hof 1 Tisch 8 Tisch 2 Nummer 4 Nummer 2
116 Vogel Yusuf = Hof 1 Tisch 13 Nummer 6 Nummer 5
117 Wagner Daniel = Hof 1 Tisch 10 Nummer 6 Nummer 7
118 Wagner Timo = Hof 1 Tisch 12 Nummer 9 Nummer 6
119 Winkler Sarah = Hof 1 Tisch 1 Nummer 12 Nummer 8
120 Yilmaz Olga = Hof 1 Tisch 11 Nummer 9 Nummer 4
+181 -164
View File
@@ -1,177 +1,194 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="995.887" height="667.258" viewBox="0 0 995.887 667.258"> <svg xmlns="http://www.w3.org/2000/svg" width="995.887" height="667.258" viewBox="0 0 995.887 667.258">
<rect width="100%" height="100%" fill="white"/> <rect width="100%" height="100%" fill="white"/>
<polyline points="106.785,231.844 255.537,417.47" fill="none" stroke="#4363d8" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="0.5"/> <polyline points="239.695,263.249 374.577,76.1153" fill="none" stroke="#bfef45" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="0.5"/>
<polyline points="412.302,254.956 574.352,245.723" fill="none" stroke="#911eb4" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="0.5"/> <polyline points="419.271,254.956 589.915,255.537" fill="none" stroke="#fabed4" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="0.5"/>
<circle cx="744.415" cy="251.472" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="744.415" cy="251.472" r="12" fill="white" fill-opacity="0.75"/>
<text x="744.415" y="251.472" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">6</text>
<circle cx="87.1573" cy="415.786" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="87.1573" cy="415.786" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="87.1573" cy="415.786" r="12" fill="white" fill-opacity="0.75"/> <ellipse cx="87.1573" cy="415.786" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="87.1573" y="415.786" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">7</text> <text x="87.1573" y="410.986" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">7</text>
<circle cx="251.472" cy="251.472" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/> <text x="87.1573" y="424.186" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">8 Pl.</text>
<circle cx="251.472" cy="216.979" r="12" fill="#e6194b" stroke="black" stroke-width="1"/>
<circle cx="251.472" cy="285.965" r="12" fill="#e6194b" stroke="black" stroke-width="1"/>
<circle cx="251.472" cy="251.472" r="12" fill="white" fill-opacity="0.75"/>
<text x="251.472" y="251.472" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">3</text>
<circle cx="908.73" cy="415.786" r="48.4" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="908.73" cy="389.386" r="12" fill="#888888" stroke="black" stroke-width="1"/>
<circle cx="931.593" cy="402.586" r="12" fill="#888888" stroke="black" stroke-width="1"/>
<circle cx="931.593" cy="428.986" r="12" fill="#888888" stroke="black" stroke-width="1"/>
<circle cx="908.73" cy="442.186" r="12" fill="#888888" stroke="black" stroke-width="1"/>
<circle cx="885.867" cy="428.986" r="12" fill="#888888" stroke="black" stroke-width="1"/>
<circle cx="885.867" cy="402.586" r="12" fill="#888888" stroke="black" stroke-width="1"/>
<circle cx="908.73" cy="415.786" r="12" fill="white" fill-opacity="0.75"/>
<text x="908.73" y="415.786" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">17</text>
<circle cx="580.101" cy="415.786" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="580.101" cy="381.293" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/>
<circle cx="607.069" cy="394.28" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/>
<circle cx="613.729" cy="423.462" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/>
<circle cx="595.067" cy="446.864" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/>
<circle cx="565.135" cy="446.864" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/>
<circle cx="546.472" cy="423.462" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/>
<circle cx="553.133" cy="394.28" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/>
<circle cx="580.101" cy="415.786" r="12" fill="white" fill-opacity="0.75"/>
<text x="580.101" y="415.786" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">10</text>
<circle cx="87.1573" cy="251.472" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="87.1573" cy="216.979" r="12" fill="#4363d8" stroke="black" stroke-width="1"/>
<circle cx="111.548" cy="227.081" r="12" fill="#4363d8" stroke="black" stroke-width="1"/>
<circle cx="121.651" cy="251.472" r="12" fill="#4363d8" stroke="black" stroke-width="1"/>
<circle cx="111.548" cy="275.862" r="12" fill="#f58231" stroke="black" stroke-width="1"/>
<circle cx="87.1573" cy="285.965" r="12" fill="#f58231" stroke="black" stroke-width="1"/>
<circle cx="62.7669" cy="275.862" r="12" fill="#f58231" stroke="black" stroke-width="1"/>
<circle cx="52.664" cy="251.472" r="12" fill="#f58231" stroke="black" stroke-width="1"/>
<circle cx="62.7669" cy="227.081" r="12" fill="#f58231" stroke="black" stroke-width="1"/>
<circle cx="87.1573" cy="251.472" r="12" fill="white" fill-opacity="0.75"/>
<text x="87.1573" y="251.472" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">2</text>
<circle cx="415.786" cy="251.472" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="415.786" cy="216.979" r="12" fill="#911eb4" stroke="black" stroke-width="1"/>
<circle cx="440.177" cy="227.081" r="12" fill="#42d4f4" stroke="black" stroke-width="1"/>
<circle cx="450.28" cy="251.472" r="12" fill="#911eb4" stroke="black" stroke-width="1"/>
<circle cx="440.177" cy="275.862" r="12" fill="#911eb4" stroke="black" stroke-width="1"/>
<circle cx="415.786" cy="285.965" r="12" fill="#911eb4" stroke="black" stroke-width="1"/>
<circle cx="391.396" cy="275.862" r="12" fill="#911eb4" stroke="black" stroke-width="1"/>
<circle cx="381.293" cy="251.472" r="12" fill="#911eb4" stroke="black" stroke-width="1"/>
<circle cx="391.396" cy="227.081" r="12" fill="#911eb4" stroke="black" stroke-width="1"/>
<circle cx="415.786" cy="251.472" r="12" fill="white" fill-opacity="0.75"/>
<text x="415.786" y="251.472" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">4</text>
<circle cx="580.101" cy="251.472" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="580.101" cy="216.979" r="12" fill="#911eb4" stroke="black" stroke-width="1"/>
<circle cx="604.491" cy="227.081" r="12" fill="#911eb4" stroke="black" stroke-width="1"/>
<circle cx="614.594" cy="251.472" r="12" fill="#f032e6" stroke="black" stroke-width="1"/>
<circle cx="604.491" cy="275.862" r="12" fill="#911eb4" stroke="black" stroke-width="1"/>
<circle cx="580.101" cy="285.965" r="12" fill="#f032e6" stroke="black" stroke-width="1"/>
<circle cx="555.711" cy="275.862" r="12" fill="#911eb4" stroke="black" stroke-width="1"/>
<circle cx="545.608" cy="251.472" r="12" fill="#911eb4" stroke="black" stroke-width="1"/>
<circle cx="555.711" cy="227.081" r="12" fill="#911eb4" stroke="black" stroke-width="1"/>
<circle cx="580.101" cy="251.472" r="12" fill="white" fill-opacity="0.75"/>
<text x="580.101" y="251.472" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">5</text>
<circle cx="251.472" cy="415.786" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="251.472" cy="381.293" r="12" fill="#bfef45" stroke="black" stroke-width="1"/>
<circle cx="275.862" cy="391.396" r="12" fill="#4363d8" stroke="black" stroke-width="1"/>
<circle cx="285.965" cy="415.786" r="12" fill="#4363d8" stroke="black" stroke-width="1"/>
<circle cx="275.862" cy="440.177" r="12" fill="#4363d8" stroke="black" stroke-width="1"/>
<circle cx="251.472" cy="450.28" r="12" fill="#4363d8" stroke="black" stroke-width="1"/>
<circle cx="227.081" cy="440.177" r="12" fill="#bfef45" stroke="black" stroke-width="1"/>
<circle cx="216.979" cy="415.786" r="12" fill="#4363d8" stroke="black" stroke-width="1"/>
<circle cx="227.081" cy="391.396" r="12" fill="#4363d8" stroke="black" stroke-width="1"/>
<circle cx="251.472" cy="415.786" r="12" fill="white" fill-opacity="0.75"/>
<text x="251.472" y="415.786" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">8</text>
<circle cx="415.786" cy="415.786" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="415.786" cy="415.786" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="415.786" cy="381.293" r="12" fill="#fabed4" stroke="black" stroke-width="1"/> <ellipse cx="415.786" cy="415.786" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<circle cx="440.177" cy="391.396" r="12" fill="#fabed4" stroke="black" stroke-width="1"/> <text x="415.786" y="410.986" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">9</text>
<circle cx="450.28" cy="415.786" r="12" fill="#fabed4" stroke="black" stroke-width="1"/> <text x="415.786" y="424.186" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">8 Pl.</text>
<circle cx="440.177" cy="440.177" r="12" fill="#fabed4" stroke="black" stroke-width="1"/> <circle cx="744.415" cy="251.472" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="415.786" cy="450.28" r="12" fill="#fabed4" stroke="black" stroke-width="1"/> <circle class="person" data-gid="12" data-gruppe="Onkel und Tante (Braut-Seite)" data-name="Horst Aydin" cx="744.415" cy="216.979" r="12" fill="#e6194b" stroke="black" stroke-width="1"><title>Horst Aydin — Onkel und Tante (Braut-Seite)</title></circle>
<circle cx="391.396" cy="440.177" r="12" fill="#fabed4" stroke="black" stroke-width="1"/> <circle class="person" data-gid="12" data-gruppe="Onkel und Tante (Braut-Seite)" data-name="Ursula Aydin" cx="744.415" cy="285.965" r="12" fill="#e6194b" stroke="black" stroke-width="1"><title>Ursula Aydin — Onkel und Tante (Braut-Seite)</title></circle>
<circle cx="381.293" cy="415.786" r="12" fill="#fabed4" stroke="black" stroke-width="1"/> <ellipse cx="744.415" cy="251.472" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<circle cx="391.396" cy="391.396" r="12" fill="#fabed4" stroke="black" stroke-width="1"/> <text x="744.415" y="246.672" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">6</text>
<circle cx="415.786" cy="415.786" r="12" fill="white" fill-opacity="0.75"/> <text x="744.415" y="259.872" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">8 Pl.</text>
<text x="415.786" y="415.786" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">9</text> <circle cx="908.73" cy="415.786" r="48.4" fill="white" stroke="black" stroke-width="1.5"/>
<circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Ben Brandt" cx="908.73" cy="389.386" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Ben Brandt — VIP / feste Platzierung</title></circle>
<circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Paul Brandt" cx="931.593" cy="402.586" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Paul Brandt — VIP / feste Platzierung</title></circle>
<circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Anton Meyer" cx="931.593" cy="428.986" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Anton Meyer — VIP / feste Platzierung</title></circle>
<circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Ida Meyer" cx="908.73" cy="442.186" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Ida Meyer — VIP / feste Platzierung</title></circle>
<circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Anton Vogel" cx="885.867" cy="428.986" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Anton Vogel — VIP / feste Platzierung</title></circle>
<circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Max Vogel" cx="885.867" cy="402.586" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Max Vogel — VIP / feste Platzierung</title></circle>
<ellipse cx="908.73" cy="415.786" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="908.73" y="410.986" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">17</text>
<text x="908.73" y="424.186" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">6 Pl.</text>
<circle cx="580.101" cy="415.786" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/>
<circle class="person" data-gid="18" data-gruppe="Arbeitskolleginnen der Braut" data-name="Elif Demir" cx="580.101" cy="381.293" r="12" fill="#3cb44b" stroke="black" stroke-width="1"><title>Elif Demir — Arbeitskolleginnen der Braut</title></circle>
<circle class="person" data-gid="18" data-gruppe="Arbeitskolleginnen der Braut" data-name="Jennifer Simon" cx="607.069" cy="394.28" r="12" fill="#3cb44b" stroke="black" stroke-width="1"><title>Jennifer Simon — Arbeitskolleginnen der Braut</title></circle>
<circle class="person" data-gid="18" data-gruppe="Arbeitskolleginnen der Braut" data-name="Andreas Stein" cx="613.729" cy="423.462" r="12" fill="#3cb44b" stroke="black" stroke-width="1"><title>Andreas Stein — Arbeitskolleginnen der Braut</title></circle>
<circle class="person" data-gid="18" data-gruppe="Arbeitskolleginnen der Braut" data-name="Stefan Klein" cx="595.067" cy="446.864" r="12" fill="#3cb44b" stroke="black" stroke-width="1"><title>Stefan Klein — Arbeitskolleginnen der Braut</title></circle>
<circle class="person" data-gid="18" data-gruppe="Arbeitskolleginnen der Braut" data-name="Timo Frank" cx="565.135" cy="446.864" r="12" fill="#3cb44b" stroke="black" stroke-width="1"><title>Timo Frank — Arbeitskolleginnen der Braut</title></circle>
<circle class="person" data-gid="18" data-gruppe="Arbeitskolleginnen der Braut" data-name="Daniel Wagner" cx="546.472" cy="423.462" r="12" fill="#3cb44b" stroke="black" stroke-width="1"><title>Daniel Wagner — Arbeitskolleginnen der Braut</title></circle>
<circle class="person" data-gid="18" data-gruppe="Arbeitskolleginnen der Braut" data-name="Stefanie Simon" cx="553.133" cy="394.28" r="12" fill="#3cb44b" stroke="black" stroke-width="1"><title>Stefanie Simon — Arbeitskolleginnen der Braut</title></circle>
<ellipse cx="580.101" cy="415.786" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="580.101" y="410.986" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">10</text>
<text x="580.101" y="424.186" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">8 Pl.</text>
<circle cx="87.1573" cy="251.472" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/>
<circle class="person" data-gid="11" data-gruppe="Familie Schwarz (Braeutigam-Seite, Geschwister Sarah): Liam (8 J.) am Kindertisch; Elias (8 J.) am Kindertisch" data-name="Yusuf Schwarz" cx="87.1573" cy="216.979" r="12" fill="#4363d8" stroke="black" stroke-width="1"><title>Yusuf Schwarz — Familie Schwarz (Braeutigam-Seite, Geschwister Sarah): Liam (8 J.) am Kindertisch; Elias (8 J.) am Kindertisch</title></circle>
<circle class="person" data-gid="11" data-gruppe="Familie Schwarz (Braeutigam-Seite, Geschwister Sarah): Liam (8 J.) am Kindertisch; Elias (8 J.) am Kindertisch" data-name="Sarah Schwarz" cx="111.548" cy="227.081" r="12" fill="#4363d8" stroke="black" stroke-width="1"><title>Sarah Schwarz — Familie Schwarz (Braeutigam-Seite, Geschwister Sarah): Liam (8 J.) am Kindertisch; Elias (8 J.) am Kindertisch</title></circle>
<circle class="person" data-gid="14" data-gruppe="Onkel und Tante (Braeutigam-Seite)" data-name="Heinz Fischer" cx="121.651" cy="251.472" r="12" fill="#f58231" stroke="black" stroke-width="1"><title>Heinz Fischer — Onkel und Tante (Braeutigam-Seite)</title></circle>
<circle class="person" data-gid="14" data-gruppe="Onkel und Tante (Braeutigam-Seite)" data-name="Helga Fischer" cx="111.548" cy="275.862" r="12" fill="#f58231" stroke="black" stroke-width="1"><title>Helga Fischer — Onkel und Tante (Braeutigam-Seite)</title></circle>
<circle class="person" data-gid="15" data-gruppe="Grosstante mit Begleitung" data-name="Heinz Tran" cx="87.1573" cy="285.965" r="12" fill="#911eb4" stroke="black" stroke-width="1"><title>Heinz Tran — Grosstante mit Begleitung</title></circle>
<circle class="person" data-gid="15" data-gruppe="Grosstante mit Begleitung" data-name="Erika Erdem" cx="62.7669" cy="275.862" r="12" fill="#911eb4" stroke="black" stroke-width="1"><title>Erika Erdem — Grosstante mit Begleitung</title></circle>
<circle class="person" data-gid="10" data-gruppe="Familie Sommer (Braeutigam-Seite, Geschwister Dennis): Emil (8 J.) am Kindertisch; Ida (8 J.) am Kindertisch" data-name="Dennis Sommer" cx="52.664" cy="251.472" r="12" fill="#42d4f4" stroke="black" stroke-width="1"><title>Dennis Sommer — Familie Sommer (Braeutigam-Seite, Geschwister Dennis): Emil (8 J.) am Kindertisch; Ida (8 J.) am Kindertisch</title></circle>
<circle class="person" data-gid="10" data-gruppe="Familie Sommer (Braeutigam-Seite, Geschwister Dennis): Emil (8 J.) am Kindertisch; Ida (8 J.) am Kindertisch" data-name="Jennifer Sommer" cx="62.7669" cy="227.081" r="12" fill="#42d4f4" stroke="black" stroke-width="1"><title>Jennifer Sommer — Familie Sommer (Braeutigam-Seite, Geschwister Dennis): Emil (8 J.) am Kindertisch; Ida (8 J.) am Kindertisch</title></circle>
<ellipse cx="87.1573" cy="251.472" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="87.1573" y="246.672" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">2</text>
<text x="87.1573" y="259.872" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">8 Pl.</text>
<circle cx="251.472" cy="251.472" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/>
<circle class="person" data-gid="13" data-gruppe="Onkel und Tante mit Cousine (Braut-Seite)" data-name="Ingrid Demir" cx="251.472" cy="216.979" r="12" fill="#f032e6" stroke="black" stroke-width="1"><title>Ingrid Demir — Onkel und Tante mit Cousine (Braut-Seite)</title></circle>
<circle class="person" data-gid="13" data-gruppe="Onkel und Tante mit Cousine (Braut-Seite)" data-name="Monika Demir" cx="275.862" cy="227.081" r="12" fill="#f032e6" stroke="black" stroke-width="1"><title>Monika Demir — Onkel und Tante mit Cousine (Braut-Seite)</title></circle>
<circle class="person" data-gid="13" data-gruppe="Onkel und Tante mit Cousine (Braut-Seite)" data-name="Hannelore Demir" cx="285.965" cy="251.472" r="12" fill="#f032e6" stroke="black" stroke-width="1"><title>Hannelore Demir — Onkel und Tante mit Cousine (Braut-Seite)</title></circle>
<circle class="person" data-gid="21" data-gruppe="Fussballverein des Braeutigams" data-name="Svenja Vogel" cx="275.862" cy="275.862" r="12" fill="#bfef45" stroke="black" stroke-width="1"><title>Svenja Vogel — Fussballverein des Braeutigams</title></circle>
<circle class="person" data-gid="21" data-gruppe="Fussballverein des Braeutigams" data-name="Andreas Koch" cx="251.472" cy="285.965" r="12" fill="#bfef45" stroke="black" stroke-width="1"><title>Andreas Koch — Fussballverein des Braeutigams</title></circle>
<circle class="person" data-gid="21" data-gruppe="Fussballverein des Braeutigams" data-name="Stefanie Busch" cx="227.081" cy="275.862" r="12" fill="#bfef45" stroke="black" stroke-width="1"><title>Stefanie Busch — Fussballverein des Braeutigams</title></circle>
<circle class="person" data-gid="21" data-gruppe="Fussballverein des Braeutigams" data-name="Giovanna Koch" cx="216.979" cy="251.472" r="12" fill="#bfef45" stroke="black" stroke-width="1"><title>Giovanna Koch — Fussballverein des Braeutigams</title></circle>
<circle class="person" data-gid="21" data-gruppe="Fussballverein des Braeutigams" data-name="Julia Esposito" cx="227.081" cy="227.081" r="12" fill="#bfef45" stroke="black" stroke-width="1"><title>Julia Esposito — Fussballverein des Braeutigams</title></circle>
<ellipse cx="251.472" cy="251.472" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="251.472" y="246.672" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">3</text>
<text x="251.472" y="259.872" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">8 Pl.</text>
<circle cx="415.786" cy="251.472" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/>
<circle class="person" data-gid="23" data-gruppe="Musikverein (anonyme Sammelbuchung, 13 Karten)" data-name="Gast Musikverein" cx="415.786" cy="216.979" r="12" fill="#fabed4" stroke="black" stroke-width="1"><title>Gast Musikverein — Musikverein (anonyme Sammelbuchung, 13 Karten)</title></circle>
<circle class="person" data-gid="23" data-gruppe="Musikverein (anonyme Sammelbuchung, 13 Karten)" data-name="Gast Musikverein" cx="440.177" cy="227.081" r="12" fill="#fabed4" stroke="black" stroke-width="1"><title>Gast Musikverein — Musikverein (anonyme Sammelbuchung, 13 Karten)</title></circle>
<circle class="person" data-gid="23" data-gruppe="Musikverein (anonyme Sammelbuchung, 13 Karten)" data-name="Gast Musikverein" cx="450.28" cy="251.472" r="12" fill="#fabed4" stroke="black" stroke-width="1"><title>Gast Musikverein — Musikverein (anonyme Sammelbuchung, 13 Karten)</title></circle>
<circle class="person" data-gid="23" data-gruppe="Musikverein (anonyme Sammelbuchung, 13 Karten)" data-name="Gast Musikverein" cx="440.177" cy="275.862" r="12" fill="#fabed4" stroke="black" stroke-width="1"><title>Gast Musikverein — Musikverein (anonyme Sammelbuchung, 13 Karten)</title></circle>
<circle class="person" data-gid="23" data-gruppe="Musikverein (anonyme Sammelbuchung, 13 Karten)" data-name="Gast Musikverein" cx="415.786" cy="285.965" r="12" fill="#fabed4" stroke="black" stroke-width="1"><title>Gast Musikverein — Musikverein (anonyme Sammelbuchung, 13 Karten)</title></circle>
<circle class="person" data-gid="23" data-gruppe="Musikverein (anonyme Sammelbuchung, 13 Karten)" data-name="Gast Musikverein" cx="391.396" cy="275.862" r="12" fill="#fabed4" stroke="black" stroke-width="1"><title>Gast Musikverein — Musikverein (anonyme Sammelbuchung, 13 Karten)</title></circle>
<circle class="person" data-gid="23" data-gruppe="Musikverein (anonyme Sammelbuchung, 13 Karten)" data-name="Gast Musikverein" cx="381.293" cy="251.472" r="12" fill="#fabed4" stroke="black" stroke-width="1"><title>Gast Musikverein — Musikverein (anonyme Sammelbuchung, 13 Karten)</title></circle>
<circle class="person" data-gid="24" data-gruppe="alleinreisender Gast" data-name="Sven Fischer" cx="391.396" cy="227.081" r="12" fill="#469990" stroke="black" stroke-width="1"><title>Sven Fischer — alleinreisender Gast</title></circle>
<ellipse cx="415.786" cy="251.472" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="415.786" y="246.672" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">4</text>
<text x="415.786" y="259.872" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">8 Pl.</text>
<circle cx="580.101" cy="251.472" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/>
<circle class="person" data-gid="23" data-gruppe="Musikverein (anonyme Sammelbuchung, 13 Karten)" data-name="Gast Musikverein" cx="580.101" cy="216.979" r="12" fill="#fabed4" stroke="black" stroke-width="1"><title>Gast Musikverein — Musikverein (anonyme Sammelbuchung, 13 Karten)</title></circle>
<circle class="person" data-gid="23" data-gruppe="Musikverein (anonyme Sammelbuchung, 13 Karten)" data-name="Gast Musikverein" cx="604.491" cy="227.081" r="12" fill="#fabed4" stroke="black" stroke-width="1"><title>Gast Musikverein — Musikverein (anonyme Sammelbuchung, 13 Karten)</title></circle>
<circle class="person" data-gid="23" data-gruppe="Musikverein (anonyme Sammelbuchung, 13 Karten)" data-name="Gast Musikverein" cx="614.594" cy="251.472" r="12" fill="#fabed4" stroke="black" stroke-width="1"><title>Gast Musikverein — Musikverein (anonyme Sammelbuchung, 13 Karten)</title></circle>
<circle class="person" data-gid="23" data-gruppe="Musikverein (anonyme Sammelbuchung, 13 Karten)" data-name="Gast Musikverein" cx="604.491" cy="275.862" r="12" fill="#fabed4" stroke="black" stroke-width="1"><title>Gast Musikverein — Musikverein (anonyme Sammelbuchung, 13 Karten)</title></circle>
<circle class="person" data-gid="23" data-gruppe="Musikverein (anonyme Sammelbuchung, 13 Karten)" data-name="Gast Musikverein" cx="580.101" cy="285.965" r="12" fill="#fabed4" stroke="black" stroke-width="1"><title>Gast Musikverein — Musikverein (anonyme Sammelbuchung, 13 Karten)</title></circle>
<circle class="person" data-gid="23" data-gruppe="Musikverein (anonyme Sammelbuchung, 13 Karten)" data-name="Gast Musikverein" cx="555.711" cy="275.862" r="12" fill="#fabed4" stroke="black" stroke-width="1"><title>Gast Musikverein — Musikverein (anonyme Sammelbuchung, 13 Karten)</title></circle>
<circle class="person" data-gid="3" data-gruppe="Familie Kraus (Braut-Seite, Geschwister Melanie): Matteo (9 J.) am Kindertisch" data-name="Dennis Kraus" cx="545.608" cy="251.472" r="12" fill="#dcbeff" stroke="black" stroke-width="1"><title>Dennis Kraus — Familie Kraus (Braut-Seite, Geschwister Melanie): Matteo (9 J.) am Kindertisch</title></circle>
<circle class="person" data-gid="3" data-gruppe="Familie Kraus (Braut-Seite, Geschwister Melanie): Matteo (9 J.) am Kindertisch" data-name="Melanie Kraus" cx="555.711" cy="227.081" r="12" fill="#dcbeff" stroke="black" stroke-width="1"><title>Melanie Kraus — Familie Kraus (Braut-Seite, Geschwister Melanie): Matteo (9 J.) am Kindertisch</title></circle>
<ellipse cx="580.101" cy="251.472" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="580.101" y="246.672" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">5</text>
<text x="580.101" y="259.872" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">8 Pl.</text>
<circle cx="251.472" cy="415.786" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/>
<circle class="person" data-gid="17" data-gruppe="Kegelclub des Brautvaters" data-name="Wolfgang Hansen" cx="251.472" cy="381.293" r="12" fill="#9a6324" stroke="black" stroke-width="1"><title>Wolfgang Hansen — Kegelclub des Brautvaters</title></circle>
<circle class="person" data-gid="17" data-gruppe="Kegelclub des Brautvaters" data-name="Hannelore Barth" cx="275.862" cy="391.396" r="12" fill="#9a6324" stroke="black" stroke-width="1"><title>Hannelore Barth — Kegelclub des Brautvaters</title></circle>
<circle class="person" data-gid="17" data-gruppe="Kegelclub des Brautvaters" data-name="Erika Frank" cx="285.965" cy="415.786" r="12" fill="#9a6324" stroke="black" stroke-width="1"><title>Erika Frank — Kegelclub des Brautvaters</title></circle>
<circle class="person" data-gid="17" data-gruppe="Kegelclub des Brautvaters" data-name="Gerhard Erdem" cx="275.862" cy="440.177" r="12" fill="#9a6324" stroke="black" stroke-width="1"><title>Gerhard Erdem — Kegelclub des Brautvaters</title></circle>
<circle class="person" data-gid="17" data-gruppe="Kegelclub des Brautvaters" data-name="Rainer Erdem" cx="251.472" cy="450.28" r="12" fill="#9a6324" stroke="black" stroke-width="1"><title>Rainer Erdem — Kegelclub des Brautvaters</title></circle>
<circle class="person" data-gid="17" data-gruppe="Kegelclub des Brautvaters" data-name="Gisela Esposito" cx="227.081" cy="440.177" r="12" fill="#9a6324" stroke="black" stroke-width="1"><title>Gisela Esposito — Kegelclub des Brautvaters</title></circle>
<circle class="person" data-gid="17" data-gruppe="Kegelclub des Brautvaters" data-name="Brigitte Franke" cx="216.979" cy="415.786" r="12" fill="#9a6324" stroke="black" stroke-width="1"><title>Brigitte Franke — Kegelclub des Brautvaters</title></circle>
<circle class="person" data-gid="17" data-gruppe="Kegelclub des Brautvaters" data-name="Wolfgang Meyer" cx="227.081" cy="391.396" r="12" fill="#9a6324" stroke="black" stroke-width="1"><title>Wolfgang Meyer — Kegelclub des Brautvaters</title></circle>
<ellipse cx="251.472" cy="415.786" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="251.472" y="410.986" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">8</text>
<text x="251.472" y="424.186" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">8 Pl.</text>
<circle cx="744.415" cy="415.786" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="744.415" cy="415.786" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="744.415" cy="381.293" r="12" fill="#469990" stroke="black" stroke-width="1"/> <circle class="person" data-gid="19" data-gruppe="Arbeitskollegen des Braeutigams" data-name="Nadine Frank" cx="744.415" cy="381.293" r="12" fill="#800000" stroke="black" stroke-width="1"><title>Nadine Frank — Arbeitskollegen des Braeutigams</title></circle>
<circle cx="768.806" cy="391.396" r="12" fill="#dcbeff" stroke="black" stroke-width="1"/> <circle class="person" data-gid="19" data-gruppe="Arbeitskollegen des Braeutigams" data-name="Markus Schmitt" cx="768.806" cy="391.396" r="12" fill="#800000" stroke="black" stroke-width="1"><title>Markus Schmitt — Arbeitskollegen des Braeutigams</title></circle>
<circle cx="778.909" cy="415.786" r="12" fill="#dcbeff" stroke="black" stroke-width="1"/> <circle class="person" data-gid="19" data-gruppe="Arbeitskollegen des Braeutigams" data-name="Olga Yilmaz" cx="778.909" cy="415.786" r="12" fill="#800000" stroke="black" stroke-width="1"><title>Olga Yilmaz — Arbeitskollegen des Braeutigams</title></circle>
<circle cx="768.806" cy="440.177" r="12" fill="#469990" stroke="black" stroke-width="1"/> <circle class="person" data-gid="19" data-gruppe="Arbeitskollegen des Braeutigams" data-name="Olga Hansen" cx="768.806" cy="440.177" r="12" fill="#800000" stroke="black" stroke-width="1"><title>Olga Hansen — Arbeitskollegen des Braeutigams</title></circle>
<circle cx="744.415" cy="450.28" r="12" fill="#dcbeff" stroke="black" stroke-width="1"/> <circle class="person" data-gid="19" data-gruppe="Arbeitskollegen des Braeutigams" data-name="Daniel Horn" cx="744.415" cy="450.28" r="12" fill="#800000" stroke="black" stroke-width="1"><title>Daniel Horn — Arbeitskollegen des Braeutigams</title></circle>
<circle cx="720.025" cy="440.177" r="12" fill="#dcbeff" stroke="black" stroke-width="1"/> <circle class="person" data-gid="19" data-gruppe="Arbeitskollegen des Braeutigams" data-name="Milan Lange" cx="720.025" cy="440.177" r="12" fill="#800000" stroke="black" stroke-width="1"><title>Milan Lange — Arbeitskollegen des Braeutigams</title></circle>
<circle cx="709.922" cy="415.786" r="12" fill="#dcbeff" stroke="black" stroke-width="1"/> <circle class="person" data-gid="1" data-gruppe="Familie Peters (Braut-Seite, Geschwister Melanie)" data-name="Yusuf Peters" cx="709.922" cy="415.786" r="12" fill="#aaffc3" stroke="black" stroke-width="1"><title>Yusuf Peters — Familie Peters (Braut-Seite, Geschwister Melanie)</title></circle>
<circle cx="720.025" cy="391.396" r="12" fill="#dcbeff" stroke="black" stroke-width="1"/> <circle class="person" data-gid="1" data-gruppe="Familie Peters (Braut-Seite, Geschwister Melanie)" data-name="Melanie Peters" cx="720.025" cy="391.396" r="12" fill="#aaffc3" stroke="black" stroke-width="1"><title>Melanie Peters — Familie Peters (Braut-Seite, Geschwister Melanie)</title></circle>
<circle cx="744.415" cy="415.786" r="12" fill="white" fill-opacity="0.75"/> <ellipse cx="744.415" cy="415.786" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="744.415" y="415.786" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">11</text> <text x="744.415" y="410.986" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">11</text>
<text x="744.415" y="424.186" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">8 Pl.</text>
<circle cx="87.1573" cy="580.101" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="87.1573" cy="580.101" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="87.1573" cy="545.608" r="12" fill="#9a6324" stroke="black" stroke-width="1"/> <circle class="person" data-gid="16" data-gruppe="Studienfreunde der Braut" data-name="Nicole Fischer" cx="87.1573" cy="545.608" r="12" fill="#000075" stroke="black" stroke-width="1"><title>Nicole Fischer — Studienfreunde der Braut</title></circle>
<circle cx="111.548" cy="555.711" r="12" fill="#9a6324" stroke="black" stroke-width="1"/> <circle class="person" data-gid="16" data-gruppe="Studienfreunde der Braut" data-name="Matthias Polat" cx="111.548" cy="555.711" r="12" fill="#000075" stroke="black" stroke-width="1"><title>Matthias Polat — Studienfreunde der Braut</title></circle>
<circle cx="121.651" cy="580.101" r="12" fill="#800000" stroke="black" stroke-width="1"/> <circle class="person" data-gid="16" data-gruppe="Studienfreunde der Braut" data-name="Christian Esposito" cx="121.651" cy="580.101" r="12" fill="#000075" stroke="black" stroke-width="1"><title>Christian Esposito — Studienfreunde der Braut</title></circle>
<circle cx="111.548" cy="604.491" r="12" fill="#9a6324" stroke="black" stroke-width="1"/> <circle class="person" data-gid="16" data-gruppe="Studienfreunde der Braut" data-name="Lena Hoffmann" cx="111.548" cy="604.491" r="12" fill="#000075" stroke="black" stroke-width="1"><title>Lena Hoffmann — Studienfreunde der Braut</title></circle>
<circle cx="87.1573" cy="614.594" r="12" fill="#9a6324" stroke="black" stroke-width="1"/> <circle class="person" data-gid="16" data-gruppe="Studienfreunde der Braut" data-name="Timo Wagner" cx="87.1573" cy="614.594" r="12" fill="#000075" stroke="black" stroke-width="1"><title>Timo Wagner — Studienfreunde der Braut</title></circle>
<circle cx="62.7669" cy="604.491" r="12" fill="#9a6324" stroke="black" stroke-width="1"/> <circle class="person" data-gid="16" data-gruppe="Studienfreunde der Braut" data-name="Nicole Dietrich" cx="62.7669" cy="604.491" r="12" fill="#000075" stroke="black" stroke-width="1"><title>Nicole Dietrich — Studienfreunde der Braut</title></circle>
<circle cx="52.664" cy="580.101" r="12" fill="#800000" stroke="black" stroke-width="1"/> <circle class="person" data-gid="2" data-gruppe="Familie Brandt (Braut-Seite, Geschwister Daniel): Felix (12 J.) am Kindertisch; Ben (13 J.) am Teenager-Tisch" data-name="Daniel Brandt" cx="52.664" cy="580.101" r="12" fill="#e6194b" stroke="black" stroke-width="1"><title>Daniel Brandt — Familie Brandt (Braut-Seite, Geschwister Daniel): Felix (12 J.) am Kindertisch; Ben (13 J.) am Teenager-Tisch</title></circle>
<circle cx="62.7669" cy="555.711" r="12" fill="#9a6324" stroke="black" stroke-width="1"/> <circle class="person" data-gid="2" data-gruppe="Familie Brandt (Braut-Seite, Geschwister Daniel): Felix (12 J.) am Kindertisch; Ben (13 J.) am Teenager-Tisch" data-name="Kathrin Brandt" cx="62.7669" cy="555.711" r="12" fill="#e6194b" stroke="black" stroke-width="1"><title>Kathrin Brandt — Familie Brandt (Braut-Seite, Geschwister Daniel): Felix (12 J.) am Kindertisch; Ben (13 J.) am Teenager-Tisch</title></circle>
<circle cx="87.1573" cy="580.101" r="12" fill="white" fill-opacity="0.75"/> <ellipse cx="87.1573" cy="580.101" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="87.1573" y="580.101" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">12</text> <text x="87.1573" y="575.301" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">12</text>
<text x="87.1573" y="588.501" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">8 Pl.</text>
<circle cx="251.472" cy="580.101" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="251.472" cy="580.101" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="251.472" cy="545.608" r="12" fill="#aaffc3" stroke="black" stroke-width="1"/> <circle class="person" data-gid="22" data-gruppe="Freundinnen aus der Schulzeit" data-name="Jennifer Dietrich" cx="251.472" cy="545.608" r="12" fill="#3cb44b" stroke="black" stroke-width="1"><title>Jennifer Dietrich — Freundinnen aus der Schulzeit</title></circle>
<circle cx="275.862" cy="555.711" r="12" fill="#000075" stroke="black" stroke-width="1"/> <circle class="person" data-gid="22" data-gruppe="Freundinnen aus der Schulzeit" data-name="Christian Meyer" cx="275.862" cy="555.711" r="12" fill="#3cb44b" stroke="black" stroke-width="1"><title>Christian Meyer — Freundinnen aus der Schulzeit</title></circle>
<circle cx="285.965" cy="580.101" r="12" fill="#000075" stroke="black" stroke-width="1"/> <circle class="person" data-gid="22" data-gruppe="Freundinnen aus der Schulzeit" data-name="Svenja Horn" cx="285.965" cy="580.101" r="12" fill="#3cb44b" stroke="black" stroke-width="1"><title>Svenja Horn — Freundinnen aus der Schulzeit</title></circle>
<circle cx="275.862" cy="604.491" r="12" fill="#aaffc3" stroke="black" stroke-width="1"/> <circle class="person" data-gid="22" data-gruppe="Freundinnen aus der Schulzeit" data-name="Stefanie Roth" cx="275.862" cy="604.491" r="12" fill="#3cb44b" stroke="black" stroke-width="1"><title>Stefanie Roth — Freundinnen aus der Schulzeit</title></circle>
<circle cx="251.472" cy="614.594" r="12" fill="#e6194b" stroke="black" stroke-width="1"/> <circle class="person" data-gid="22" data-gruppe="Freundinnen aus der Schulzeit" data-name="Stefan Kuhn" cx="251.472" cy="614.594" r="12" fill="#3cb44b" stroke="black" stroke-width="1"><title>Stefan Kuhn — Freundinnen aus der Schulzeit</title></circle>
<circle cx="227.081" cy="604.491" r="12" fill="#e6194b" stroke="black" stroke-width="1"/> <circle class="person" data-gid="8" data-gruppe="Familie Sommer (Braeutigam-Seite, Geschwister Dennis): Lina (3 J.) sitzt bei den Eltern; Theo (8 J.) am Kindertisch; Max (12 J.) am Kindertisch" data-name="Dennis Sommer" cx="227.081" cy="604.491" r="12" fill="#4363d8" stroke="black" stroke-width="1"><title>Dennis Sommer — Familie Sommer (Braeutigam-Seite, Geschwister Dennis): Lina (3 J.) sitzt bei den Eltern; Theo (8 J.) am Kindertisch; Max (12 J.) am Kindertisch</title></circle>
<circle cx="216.979" cy="580.101" r="12" fill="#aaffc3" stroke="black" stroke-width="1"/> <circle class="person" data-gid="8" data-gruppe="Familie Sommer (Braeutigam-Seite, Geschwister Dennis): Lina (3 J.) sitzt bei den Eltern; Theo (8 J.) am Kindertisch; Max (12 J.) am Kindertisch" data-name="Nicole Sommer" cx="216.979" cy="580.101" r="12" fill="#4363d8" stroke="black" stroke-width="1"><title>Nicole Sommer — Familie Sommer (Braeutigam-Seite, Geschwister Dennis): Lina (3 J.) sitzt bei den Eltern; Theo (8 J.) am Kindertisch; Max (12 J.) am Kindertisch</title></circle>
<circle cx="227.081" cy="555.711" r="12" fill="#000075" stroke="black" stroke-width="1"/> <circle class="person" data-gid="8" data-gruppe="Familie Sommer (Braeutigam-Seite, Geschwister Dennis): Lina (3 J.) sitzt bei den Eltern; Theo (8 J.) am Kindertisch; Max (12 J.) am Kindertisch" data-name="Lina Sommer" cx="227.081" cy="555.711" r="12" fill="#4363d8" stroke="black" stroke-width="1"><title>Lina Sommer — Familie Sommer (Braeutigam-Seite, Geschwister Dennis): Lina (3 J.) sitzt bei den Eltern; Theo (8 J.) am Kindertisch; Max (12 J.) am Kindertisch</title></circle>
<circle cx="251.472" cy="580.101" r="12" fill="white" fill-opacity="0.75"/> <ellipse cx="251.472" cy="580.101" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="251.472" y="580.101" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">13</text> <text x="251.472" y="575.301" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">13</text>
<text x="251.472" y="588.501" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">8 Pl.</text>
<circle cx="415.786" cy="580.101" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="415.786" cy="580.101" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="415.786" cy="545.608" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/> <circle class="person" data-gid="20" data-gruppe="Nachbarn der Brauteltern" data-name="Guenter Schwarz" cx="415.786" cy="545.608" r="12" fill="#f58231" stroke="black" stroke-width="1"><title>Guenter Schwarz — Nachbarn der Brauteltern</title></circle>
<circle cx="440.177" cy="555.711" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/> <circle class="person" data-gid="20" data-gruppe="Nachbarn der Brauteltern" data-name="Rainer Aksoy" cx="440.177" cy="555.711" r="12" fill="#f58231" stroke="black" stroke-width="1"><title>Rainer Aksoy — Nachbarn der Brauteltern</title></circle>
<circle cx="450.28" cy="580.101" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/> <circle class="person" data-gid="20" data-gruppe="Nachbarn der Brauteltern" data-name="Renate Aksoy" cx="450.28" cy="580.101" r="12" fill="#f58231" stroke="black" stroke-width="1"><title>Renate Aksoy — Nachbarn der Brauteltern</title></circle>
<circle cx="440.177" cy="604.491" r="12" fill="#4363d8" stroke="black" stroke-width="1"/> <circle class="person" data-gid="20" data-gruppe="Nachbarn der Brauteltern" data-name="Werner Stein" cx="440.177" cy="604.491" r="12" fill="#f58231" stroke="black" stroke-width="1"><title>Werner Stein — Nachbarn der Brauteltern</title></circle>
<circle cx="415.786" cy="614.594" r="12" fill="#4363d8" stroke="black" stroke-width="1"/> <circle class="person" data-gid="5" data-gruppe="Familie Meyer (Braut-Seite, Geschwister Sandra): Mila (10 J.) am Kindertisch; Anton (16 J.) am Teenager-Tisch; Ida (16 J.) am Teenager-Tisch" data-name="Marco Meyer" cx="415.786" cy="614.594" r="12" fill="#911eb4" stroke="black" stroke-width="1"><title>Marco Meyer — Familie Meyer (Braut-Seite, Geschwister Sandra): Mila (10 J.) am Kindertisch; Anton (16 J.) am Teenager-Tisch; Ida (16 J.) am Teenager-Tisch</title></circle>
<circle cx="391.396" cy="604.491" r="12" fill="#f58231" stroke="black" stroke-width="1"/> <circle class="person" data-gid="5" data-gruppe="Familie Meyer (Braut-Seite, Geschwister Sandra): Mila (10 J.) am Kindertisch; Anton (16 J.) am Teenager-Tisch; Ida (16 J.) am Teenager-Tisch" data-name="Sandra Meyer" cx="391.396" cy="604.491" r="12" fill="#911eb4" stroke="black" stroke-width="1"><title>Sandra Meyer — Familie Meyer (Braut-Seite, Geschwister Sandra): Mila (10 J.) am Kindertisch; Anton (16 J.) am Teenager-Tisch; Ida (16 J.) am Teenager-Tisch</title></circle>
<circle cx="381.293" cy="580.101" r="12" fill="#f58231" stroke="black" stroke-width="1"/> <circle class="person" data-gid="7" data-gruppe="Familie Vogel (Braut-Seite, Geschwister Sandra): Anton (14 J.) am Teenager-Tisch; Max (15 J.) am Teenager-Tisch" data-name="Yusuf Vogel" cx="381.293" cy="580.101" r="12" fill="#42d4f4" stroke="black" stroke-width="1"><title>Yusuf Vogel — Familie Vogel (Braut-Seite, Geschwister Sandra): Anton (14 J.) am Teenager-Tisch; Max (15 J.) am Teenager-Tisch</title></circle>
<circle cx="391.396" cy="555.711" r="12" fill="#f58231" stroke="black" stroke-width="1"/> <circle class="person" data-gid="7" data-gruppe="Familie Vogel (Braut-Seite, Geschwister Sandra): Anton (14 J.) am Teenager-Tisch; Max (15 J.) am Teenager-Tisch" data-name="Sandra Vogel" cx="391.396" cy="555.711" r="12" fill="#42d4f4" stroke="black" stroke-width="1"><title>Sandra Vogel — Familie Vogel (Braut-Seite, Geschwister Sandra): Anton (14 J.) am Teenager-Tisch; Max (15 J.) am Teenager-Tisch</title></circle>
<circle cx="415.786" cy="580.101" r="12" fill="white" fill-opacity="0.75"/> <ellipse cx="415.786" cy="580.101" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="415.786" y="580.101" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">14</text> <text x="415.786" y="575.301" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">14</text>
<text x="415.786" y="588.501" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">8 Pl.</text>
<circle cx="580.101" cy="580.101" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="580.101" cy="580.101" r="56.4933" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="580.101" cy="545.608" r="12" fill="#911eb4" stroke="black" stroke-width="1"/> <circle class="person" data-gid="4" data-gruppe="Familie Brandt (Braut-Seite, Geschwister Andreas): Theo (3 J.) sitzt bei den Eltern; Anton (10 J.) am Kindertisch; Frieda (12 J.) am Kindertisch; Paul (19 J.) am Teenager-Tisch" data-name="Andreas Brandt" cx="580.101" cy="545.608" r="12" fill="#f032e6" stroke="black" stroke-width="1"><title>Andreas Brandt — Familie Brandt (Braut-Seite, Geschwister Andreas): Theo (3 J.) sitzt bei den Eltern; Anton (10 J.) am Kindertisch; Frieda (12 J.) am Kindertisch; Paul (19 J.) am Teenager-Tisch</title></circle>
<circle cx="604.491" cy="555.711" r="12" fill="#42d4f4" stroke="black" stroke-width="1"/> <circle class="person" data-gid="4" data-gruppe="Familie Brandt (Braut-Seite, Geschwister Andreas): Theo (3 J.) sitzt bei den Eltern; Anton (10 J.) am Kindertisch; Frieda (12 J.) am Kindertisch; Paul (19 J.) am Teenager-Tisch" data-name="Lena Brandt" cx="604.491" cy="555.711" r="12" fill="#f032e6" stroke="black" stroke-width="1"><title>Lena Brandt — Familie Brandt (Braut-Seite, Geschwister Andreas): Theo (3 J.) sitzt bei den Eltern; Anton (10 J.) am Kindertisch; Frieda (12 J.) am Kindertisch; Paul (19 J.) am Teenager-Tisch</title></circle>
<circle cx="614.594" cy="580.101" r="12" fill="#f032e6" stroke="black" stroke-width="1"/> <circle class="person" data-gid="4" data-gruppe="Familie Brandt (Braut-Seite, Geschwister Andreas): Theo (3 J.) sitzt bei den Eltern; Anton (10 J.) am Kindertisch; Frieda (12 J.) am Kindertisch; Paul (19 J.) am Teenager-Tisch" data-name="Theo Brandt" cx="614.594" cy="580.101" r="12" fill="#f032e6" stroke="black" stroke-width="1"><title>Theo Brandt — Familie Brandt (Braut-Seite, Geschwister Andreas): Theo (3 J.) sitzt bei den Eltern; Anton (10 J.) am Kindertisch; Frieda (12 J.) am Kindertisch; Paul (19 J.) am Teenager-Tisch</title></circle>
<circle cx="604.491" cy="604.491" r="12" fill="#bfef45" stroke="black" stroke-width="1"/> <circle class="person" data-gid="6" data-gruppe="Familie Brandt (Braut-Seite, Geschwister Milan): Sofia (2 J.) sitzt bei den Eltern; Greta (7 J.) am Kindertisch" data-name="Milan Brandt" cx="604.491" cy="604.491" r="12" fill="#bfef45" stroke="black" stroke-width="1"><title>Milan Brandt — Familie Brandt (Braut-Seite, Geschwister Milan): Sofia (2 J.) sitzt bei den Eltern; Greta (7 J.) am Kindertisch</title></circle>
<circle cx="580.101" cy="614.594" r="12" fill="#bfef45" stroke="black" stroke-width="1"/> <circle class="person" data-gid="6" data-gruppe="Familie Brandt (Braut-Seite, Geschwister Milan): Sofia (2 J.) sitzt bei den Eltern; Greta (7 J.) am Kindertisch" data-name="Anja Brandt" cx="580.101" cy="614.594" r="12" fill="#bfef45" stroke="black" stroke-width="1"><title>Anja Brandt — Familie Brandt (Braut-Seite, Geschwister Milan): Sofia (2 J.) sitzt bei den Eltern; Greta (7 J.) am Kindertisch</title></circle>
<circle cx="555.711" cy="604.491" r="12" fill="#f032e6" stroke="black" stroke-width="1"/> <circle class="person" data-gid="6" data-gruppe="Familie Brandt (Braut-Seite, Geschwister Milan): Sofia (2 J.) sitzt bei den Eltern; Greta (7 J.) am Kindertisch" data-name="Sofia Brandt" cx="555.711" cy="604.491" r="12" fill="#bfef45" stroke="black" stroke-width="1"><title>Sofia Brandt — Familie Brandt (Braut-Seite, Geschwister Milan): Sofia (2 J.) sitzt bei den Eltern; Greta (7 J.) am Kindertisch</title></circle>
<circle cx="545.608" cy="580.101" r="12" fill="#42d4f4" stroke="black" stroke-width="1"/> <circle class="person" data-gid="9" data-gruppe="Familie Kuhn (Braeutigam-Seite, Geschwister Sarah): Leni (10 J.) am Kindertisch" data-name="Timo Kuhn" cx="545.608" cy="580.101" r="12" fill="#fabed4" stroke="black" stroke-width="1"><title>Timo Kuhn — Familie Kuhn (Braeutigam-Seite, Geschwister Sarah): Leni (10 J.) am Kindertisch</title></circle>
<circle cx="555.711" cy="555.711" r="12" fill="#911eb4" stroke="black" stroke-width="1"/> <circle class="person" data-gid="9" data-gruppe="Familie Kuhn (Braeutigam-Seite, Geschwister Sarah): Leni (10 J.) am Kindertisch" data-name="Sarah Kuhn" cx="555.711" cy="555.711" r="12" fill="#fabed4" stroke="black" stroke-width="1"><title>Sarah Kuhn — Familie Kuhn (Braeutigam-Seite, Geschwister Sarah): Leni (10 J.) am Kindertisch</title></circle>
<circle cx="580.101" cy="580.101" r="12" fill="white" fill-opacity="0.75"/> <ellipse cx="580.101" cy="580.101" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="580.101" y="580.101" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">15</text> <text x="580.101" y="575.301" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">15</text>
<text x="580.101" y="588.501" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">8 Pl.</text>
<circle cx="415.786" cy="87.1573" r="73.0009" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="415.786" cy="87.1573" r="73.0009" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="415.786" cy="36.1564" r="12" fill="#888888" stroke="black" stroke-width="1"/> <circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Julia Brandt" cx="415.786" cy="36.1564" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Julia Brandt — VIP / feste Platzierung</title></circle>
<circle cx="441.287" cy="42.9892" r="12" fill="#fabed4" stroke="black" stroke-width="1"/> <circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Daniel Sommer" cx="441.287" cy="42.9892" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Daniel Sommer — VIP / feste Platzierung</title></circle>
<circle cx="459.954" cy="61.6568" r="12" fill="#fabed4" stroke="black" stroke-width="1"/> <circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Werner Brandt" cx="459.954" cy="61.6568" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Werner Brandt — VIP / feste Platzierung</title></circle>
<circle cx="466.787" cy="87.1573" r="12" fill="#888888" stroke="black" stroke-width="1"/> <circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Helga Brandt" cx="466.787" cy="87.1573" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Helga Brandt — VIP / feste Platzierung</title></circle>
<circle cx="459.954" cy="112.658" r="12" fill="#888888" stroke="black" stroke-width="1"/> <circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Dieter Sommer" cx="459.954" cy="112.658" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Dieter Sommer — VIP / feste Platzierung</title></circle>
<circle cx="441.287" cy="131.325" r="12" fill="#888888" stroke="black" stroke-width="1"/> <circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Renate Sommer" cx="441.287" cy="131.325" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Renate Sommer — VIP / feste Platzierung</title></circle>
<circle cx="415.786" cy="138.158" r="12" fill="#fabed4" stroke="black" stroke-width="1"/> <circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Sarah Winkler" cx="415.786" cy="138.158" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Sarah Winkler — VIP / feste Platzierung</title></circle>
<circle cx="390.286" cy="131.325" r="12" fill="#fabed4" stroke="black" stroke-width="1"/> <circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Tobias Frank" cx="390.286" cy="131.325" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Tobias Frank — VIP / feste Platzierung</title></circle>
<circle cx="371.618" cy="112.658" r="12" fill="#888888" stroke="black" stroke-width="1"/> <circle class="person" data-gid="21" data-gruppe="Fussballverein des Braeutigams" data-name="Giovanna Kovac" cx="371.618" cy="112.658" r="12" fill="#bfef45" stroke="black" stroke-width="1"><title>Giovanna Kovac — Fussballverein des Braeutigams</title></circle>
<circle cx="364.785" cy="87.1573" r="12" fill="#888888" stroke="black" stroke-width="1"/> <circle class="person" data-gid="21" data-gruppe="Fussballverein des Braeutigams" data-name="Sergej Berger" cx="364.785" cy="87.1573" r="12" fill="#bfef45" stroke="black" stroke-width="1"><title>Sergej Berger — Fussballverein des Braeutigams</title></circle>
<circle cx="371.618" cy="61.6568" r="12" fill="#888888" stroke="black" stroke-width="1"/> <circle class="person" data-gid="21" data-gruppe="Fussballverein des Braeutigams" data-name="Dennis Schmidt" cx="371.618" cy="61.6568" r="12" fill="#bfef45" stroke="black" stroke-width="1"><title>Dennis Schmidt — Fussballverein des Braeutigams</title></circle>
<circle cx="390.286" cy="42.9892" r="12" fill="#888888" stroke="black" stroke-width="1"/> <circle class="person" data-gid="21" data-gruppe="Fussballverein des Braeutigams" data-name="Patrick Simon" cx="390.286" cy="42.9892" r="12" fill="#bfef45" stroke="black" stroke-width="1"><title>Patrick Simon — Fussballverein des Braeutigams</title></circle>
<circle cx="415.786" cy="87.1573" r="12" fill="white" fill-opacity="0.75"/> <ellipse cx="415.786" cy="87.1573" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="415.786" y="87.1573" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">1</text> <text x="415.786" y="82.3573" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">1</text>
<text x="415.786" y="95.5573" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">12 Pl.</text>
<circle cx="908.73" cy="251.472" r="77.1573" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="908.73" cy="251.472" r="77.1573" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="908.73" cy="196.315" r="12" fill="#888888" stroke="black" stroke-width="1"/> <circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Leni Kuhn" cx="908.73" cy="196.315" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Leni Kuhn — VIP / feste Platzierung</title></circle>
<circle cx="934.363" cy="202.632" r="12" fill="#888888" stroke="black" stroke-width="1"/> <circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Emil Sommer" cx="934.363" cy="202.632" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Emil Sommer — VIP / feste Platzierung</title></circle>
<circle cx="954.124" cy="220.139" r="12" fill="#888888" stroke="black" stroke-width="1"/> <circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Ida Sommer" cx="954.124" cy="220.139" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Ida Sommer — VIP / feste Platzierung</title></circle>
<circle cx="963.485" cy="244.823" r="12" fill="#888888" stroke="black" stroke-width="1"/> <circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Liam Schwarz" cx="963.485" cy="244.823" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Liam Schwarz — VIP / feste Platzierung</title></circle>
<circle cx="960.303" cy="271.031" r="12" fill="#888888" stroke="black" stroke-width="1"/> <circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Elias Schwarz" cx="960.303" cy="271.031" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Elias Schwarz — VIP / feste Platzierung</title></circle>
<circle cx="945.306" cy="292.758" r="12" fill="#888888" stroke="black" stroke-width="1"/> <circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Felix Brandt" cx="945.306" cy="292.758" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Felix Brandt — VIP / feste Platzierung</title></circle>
<circle cx="921.93" cy="305.026" r="12" fill="#888888" stroke="black" stroke-width="1"/> <circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Matteo Kraus" cx="921.93" cy="305.026" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Matteo Kraus — VIP / feste Platzierung</title></circle>
<circle cx="895.53" cy="305.026" r="12" fill="#888888" stroke="black" stroke-width="1"/> <circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Anton Brandt" cx="895.53" cy="305.026" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Anton Brandt — VIP / feste Platzierung</title></circle>
<circle cx="872.154" cy="292.758" r="12" fill="#888888" stroke="black" stroke-width="1"/> <circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Frieda Brandt" cx="872.154" cy="292.758" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Frieda Brandt — VIP / feste Platzierung</title></circle>
<circle cx="857.157" cy="271.031" r="12" fill="#888888" stroke="black" stroke-width="1"/> <circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Mila Meyer" cx="857.157" cy="271.031" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Mila Meyer — VIP / feste Platzierung</title></circle>
<circle cx="853.975" cy="244.823" r="12" fill="#888888" stroke="black" stroke-width="1"/> <circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Greta Brandt" cx="853.975" cy="244.823" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Greta Brandt — VIP / feste Platzierung</title></circle>
<circle cx="863.336" cy="220.139" r="12" fill="#888888" stroke="black" stroke-width="1"/> <circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Theo Sommer" cx="863.336" cy="220.139" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Theo Sommer — VIP / feste Platzierung</title></circle>
<circle cx="883.097" cy="202.632" r="12" fill="#888888" stroke="black" stroke-width="1"/> <circle class="person" data-gid="-1" data-gruppe="VIP / feste Platzierung" data-name="Max Sommer" cx="883.097" cy="202.632" r="12" fill="#888888" stroke="black" stroke-width="1"><title>Max Sommer — VIP / feste Platzierung</title></circle>
<circle cx="908.73" cy="251.472" r="12" fill="white" fill-opacity="0.75"/> <ellipse cx="908.73" cy="251.472" rx="12" ry="15.6" fill="white" fill-opacity="0.75"/>
<text x="908.73" y="251.472" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">16</text> <text x="908.73" y="246.672" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">16</text>
<text x="908.73" y="259.872" text-anchor="middle" dominant-baseline="central" font-size="7.44" fill="#333">13 Pl.</text>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 42 KiB

+100 -100
View File
@@ -1,50 +1,50 @@
[1] [1]
Daniel Sommer = Hof 1, Tisch 1, Nummer 1 Julia Brandt = Hof 1, Tisch 1, Nummer 1
Werner Stein = Hof 1, Tisch 1, Nummer 2 Daniel Sommer = Hof 1, Tisch 1, Nummer 2
Renate Aksoy = Hof 1, Tisch 1, Nummer 3 Werner Brandt = Hof 1, Tisch 1, Nummer 3
Werner Brandt = Hof 1, Tisch 1, Nummer 4 Helga Brandt = Hof 1, Tisch 1, Nummer 4
Helga Brandt = Hof 1, Tisch 1, Nummer 5 Dieter Sommer = Hof 1, Tisch 1, Nummer 5
Tobias Frank = Hof 1, Tisch 1, Nummer 6 Renate Sommer = Hof 1, Tisch 1, Nummer 6
Rainer Aksoy = Hof 1, Tisch 1, Nummer 7 Sarah Winkler = Hof 1, Tisch 1, Nummer 7
Guenter Schwarz = Hof 1, Tisch 1, Nummer 8 Tobias Frank = Hof 1, Tisch 1, Nummer 8
Julia Brandt = Hof 1, Tisch 1, Nummer 9 Renate Aksoy = Hof 1, Tisch 1, Nummer 9
Dieter Sommer = Hof 1, Tisch 1, Nummer 10 Werner Stein = Hof 1, Tisch 1, Nummer 10
Sarah Winkler = Hof 1, Tisch 1, Nummer 11 Guenter Schwarz = Hof 1, Tisch 1, Nummer 11
Renate Sommer = Hof 1, Tisch 1, Nummer 12 Rainer Aksoy = Hof 1, Tisch 1, Nummer 12
[2] [2]
Dennis Schmidt = Hof 1, Tisch 2, Nummer 1 Svenja Vogel = Hof 1, Tisch 2, Nummer 1
Giovanna Kovac = Hof 1, Tisch 2, Nummer 2 Giovanna Koch = Hof 1, Tisch 2, Nummer 2
Patrick Simon = Hof 1, Tisch 2, Nummer 3 Julia Esposito = Hof 1, Tisch 2, Nummer 3
Stefan Kuhn = Hof 1, Tisch 2, Nummer 4 Jennifer Dietrich = Hof 1, Tisch 2, Nummer 4
Stefanie Roth = Hof 1, Tisch 2, Nummer 5 Christian Meyer = Hof 1, Tisch 2, Nummer 5
Christian Meyer = Hof 1, Tisch 2, Nummer 6 Svenja Horn = Hof 1, Tisch 2, Nummer 6
Svenja Horn = Hof 1, Tisch 2, Nummer 7 Stefanie Roth = Hof 1, Tisch 2, Nummer 7
Jennifer Dietrich = Hof 1, Tisch 2, Nummer 8 Stefan Kuhn = Hof 1, Tisch 2, Nummer 8
[3] [3]
Sarah Schwarz = Hof 1, Tisch 3, Nummer 1 Helga Fischer = Hof 1, Tisch 3, Nummer 1
Yusuf Schwarz = Hof 1, Tisch 3, Nummer 2 Heinz Fischer = Hof 1, Tisch 3, Nummer 2
[4] [4]
Gast Musikverein = Hof 1, Tisch 4, Nummer 1 Gast Musikverein = Hof 1, Tisch 4, Nummer 1
Sven Fischer = Hof 1, Tisch 4, Nummer 2 Gast Musikverein = Hof 1, Tisch 4, Nummer 2
Gast Musikverein = Hof 1, Tisch 4, Nummer 3 Gast Musikverein = Hof 1, Tisch 4, Nummer 3
Gast Musikverein = Hof 1, Tisch 4, Nummer 4 Gast Musikverein = Hof 1, Tisch 4, Nummer 4
Gast Musikverein = Hof 1, Tisch 4, Nummer 5 Gast Musikverein = Hof 1, Tisch 4, Nummer 5
Gast Musikverein = Hof 1, Tisch 4, Nummer 6 Gast Musikverein = Hof 1, Tisch 4, Nummer 6
Gast Musikverein = Hof 1, Tisch 4, Nummer 7 Gast Musikverein = Hof 1, Tisch 4, Nummer 7
Gast Musikverein = Hof 1, Tisch 4, Nummer 8 Sven Fischer = Hof 1, Tisch 4, Nummer 8
[5] [5]
Gast Musikverein = Hof 1, Tisch 5, Nummer 1 Gast Musikverein = Hof 1, Tisch 5, Nummer 1
Gast Musikverein = Hof 1, Tisch 5, Nummer 2 Gast Musikverein = Hof 1, Tisch 5, Nummer 2
Sandra Meyer = Hof 1, Tisch 5, Nummer 3 Gast Musikverein = Hof 1, Tisch 5, Nummer 3
Gast Musikverein = Hof 1, Tisch 5, Nummer 4 Gast Musikverein = Hof 1, Tisch 5, Nummer 4
Marco Meyer = Hof 1, Tisch 5, Nummer 5 Gast Musikverein = Hof 1, Tisch 5, Nummer 5
Gast Musikverein = Hof 1, Tisch 5, Nummer 6 Gast Musikverein = Hof 1, Tisch 5, Nummer 6
Gast Musikverein = Hof 1, Tisch 5, Nummer 7 Marco Meyer = Hof 1, Tisch 5, Nummer 7
Gast Musikverein = Hof 1, Tisch 5, Nummer 8 Sandra Meyer = Hof 1, Tisch 5, Nummer 8
[6] [6]
@@ -52,103 +52,103 @@
[8] [8]
Yusuf Peters = Hof 1, Tisch 8, Nummer 1 Yusuf Peters = Hof 1, Tisch 8, Nummer 1
Stefanie Busch = Hof 1, Tisch 8, Nummer 2 Sergej Berger = Hof 1, Tisch 8, Nummer 2
Svenja Vogel = Hof 1, Tisch 8, Nummer 3 Giovanna Kovac = Hof 1, Tisch 8, Nummer 3
Andreas Koch = Hof 1, Tisch 8, Nummer 4 Dennis Schmidt = Hof 1, Tisch 8, Nummer 4
Giovanna Koch = Hof 1, Tisch 8, Nummer 5 Patrick Simon = Hof 1, Tisch 8, Nummer 5
Melanie Peters = Hof 1, Tisch 8, Nummer 6 Stefanie Busch = Hof 1, Tisch 8, Nummer 6
Sergej Berger = Hof 1, Tisch 8, Nummer 7 Andreas Koch = Hof 1, Tisch 8, Nummer 7
Julia Esposito = Hof 1, Tisch 8, Nummer 8 Melanie Peters = Hof 1, Tisch 8, Nummer 8
[9] [9]
Erika Frank = Hof 1, Tisch 9, Nummer 1 Wolfgang Hansen = Hof 1, Tisch 9, Nummer 1
Hannelore Barth = Hof 1, Tisch 9, Nummer 2 Hannelore Barth = Hof 1, Tisch 9, Nummer 2
Gerhard Erdem = Hof 1, Tisch 9, Nummer 3 Erika Frank = Hof 1, Tisch 9, Nummer 3
Brigitte Franke = Hof 1, Tisch 9, Nummer 4 Gerhard Erdem = Hof 1, Tisch 9, Nummer 4
Wolfgang Hansen = Hof 1, Tisch 9, Nummer 5 Rainer Erdem = Hof 1, Tisch 9, Nummer 5
Wolfgang Meyer = Hof 1, Tisch 9, Nummer 6 Gisela Esposito = Hof 1, Tisch 9, Nummer 6
Gisela Esposito = Hof 1, Tisch 9, Nummer 7 Brigitte Franke = Hof 1, Tisch 9, Nummer 7
Rainer Erdem = Hof 1, Tisch 9, Nummer 8 Wolfgang Meyer = Hof 1, Tisch 9, Nummer 8
[10] [10]
Jennifer Simon = Hof 1, Tisch 10, Nummer 1 Elif Demir = Hof 1, Tisch 10, Nummer 1
Elif Demir = Hof 1, Tisch 10, Nummer 2 Jennifer Simon = Hof 1, Tisch 10, Nummer 2
Andreas Stein = Hof 1, Tisch 10, Nummer 3 Andreas Stein = Hof 1, Tisch 10, Nummer 3
Stefanie Simon = Hof 1, Tisch 10, Nummer 4 Stefan Klein = Hof 1, Tisch 10, Nummer 4
Daniel Wagner = Hof 1, Tisch 10, Nummer 5 Timo Frank = Hof 1, Tisch 10, Nummer 5
Timo Frank = Hof 1, Tisch 10, Nummer 6 Daniel Wagner = Hof 1, Tisch 10, Nummer 6
Stefan Klein = Hof 1, Tisch 10, Nummer 7 Stefanie Simon = Hof 1, Tisch 10, Nummer 7
[11] [11]
Kathrin Brandt = Hof 1, Tisch 11, Nummer 1 Nadine Frank = Hof 1, Tisch 11, Nummer 1
Daniel Horn = Hof 1, Tisch 11, Nummer 2 Markus Schmitt = Hof 1, Tisch 11, Nummer 2
Olga Hansen = Hof 1, Tisch 11, Nummer 3 Olga Yilmaz = Hof 1, Tisch 11, Nummer 3
Daniel Brandt = Hof 1, Tisch 11, Nummer 4 Olga Hansen = Hof 1, Tisch 11, Nummer 4
Markus Schmitt = Hof 1, Tisch 11, Nummer 5 Daniel Horn = Hof 1, Tisch 11, Nummer 5
Milan Lange = Hof 1, Tisch 11, Nummer 6 Milan Lange = Hof 1, Tisch 11, Nummer 6
Nadine Frank = Hof 1, Tisch 11, Nummer 7 Daniel Brandt = Hof 1, Tisch 11, Nummer 7
Olga Yilmaz = Hof 1, Tisch 11, Nummer 8 Kathrin Brandt = Hof 1, Tisch 11, Nummer 8
[12] [12]
Nicole Dietrich = Hof 1, Tisch 12, Nummer 1 Nicole Fischer = Hof 1, Tisch 12, Nummer 1
Christian Esposito = Hof 1, Tisch 12, Nummer 2 Matthias Polat = Hof 1, Tisch 12, Nummer 2
Melanie Kraus = Hof 1, Tisch 12, Nummer 3 Christian Esposito = Hof 1, Tisch 12, Nummer 3
Lena Hoffmann = Hof 1, Tisch 12, Nummer 4 Lena Hoffmann = Hof 1, Tisch 12, Nummer 4
Nicole Fischer = Hof 1, Tisch 12, Nummer 5 Timo Wagner = Hof 1, Tisch 12, Nummer 5
Matthias Polat = Hof 1, Tisch 12, Nummer 6 Nicole Dietrich = Hof 1, Tisch 12, Nummer 6
Dennis Kraus = Hof 1, Tisch 12, Nummer 7 Dennis Kraus = Hof 1, Tisch 12, Nummer 7
Timo Wagner = Hof 1, Tisch 12, Nummer 8 Melanie Kraus = Hof 1, Tisch 12, Nummer 8
[13] [13]
Hannelore Demir = Hof 1, Tisch 13, Nummer 1 Ingrid Demir = Hof 1, Tisch 13, Nummer 1
Nicole Sommer = Hof 1, Tisch 13, Nummer 2 Monika Demir = Hof 1, Tisch 13, Nummer 2
Dennis Sommer = Hof 1, Tisch 13, Nummer 3 Hannelore Demir = Hof 1, Tisch 13, Nummer 3
Monika Demir = Hof 1, Tisch 13, Nummer 4 Yusuf Vogel = Hof 1, Tisch 13, Nummer 4
Yusuf Vogel = Hof 1, Tisch 13, Nummer 5 Sandra Vogel = Hof 1, Tisch 13, Nummer 5
Sandra Vogel = Hof 1, Tisch 13, Nummer 6 Dennis Sommer = Hof 1, Tisch 13, Nummer 6
Ingrid Demir = Hof 1, Tisch 13, Nummer 7 Nicole Sommer = Hof 1, Tisch 13, Nummer 7
Lina Sommer = Hof 1, Tisch 13, Nummer 8 Lina Sommer = Hof 1, Tisch 13, Nummer 8
[14] [14]
Andreas Brandt = Hof 1, Tisch 14, Nummer 1 Andreas Brandt = Hof 1, Tisch 14, Nummer 1
Theo Brandt = Hof 1, Tisch 14, Nummer 2 Lena Brandt = Hof 1, Tisch 14, Nummer 2
Lena Brandt = Hof 1, Tisch 14, Nummer 3 Theo Brandt = Hof 1, Tisch 14, Nummer 3
Erika Erdem = Hof 1, Tisch 14, Nummer 4 Milan Brandt = Hof 1, Tisch 14, Nummer 4
Heinz Tran = Hof 1, Tisch 14, Nummer 5 Anja Brandt = Hof 1, Tisch 14, Nummer 5
Milan Brandt = Hof 1, Tisch 14, Nummer 6 Sofia Brandt = Hof 1, Tisch 14, Nummer 6
Anja Brandt = Hof 1, Tisch 14, Nummer 7 Timo Kuhn = Hof 1, Tisch 14, Nummer 7
Sofia Brandt = Hof 1, Tisch 14, Nummer 8 Sarah Kuhn = Hof 1, Tisch 14, Nummer 8
[15] [15]
Helga Fischer = Hof 1, Tisch 15, Nummer 1 Yusuf Schwarz = Hof 1, Tisch 15, Nummer 1
Sarah Kuhn = Hof 1, Tisch 15, Nummer 2 Sarah Schwarz = Hof 1, Tisch 15, Nummer 2
Dennis Sommer = Hof 1, Tisch 15, Nummer 3 Horst Aydin = Hof 1, Tisch 15, Nummer 3
Horst Aydin = Hof 1, Tisch 15, Nummer 4 Ursula Aydin = Hof 1, Tisch 15, Nummer 4
Ursula Aydin = Hof 1, Tisch 15, Nummer 5 Heinz Tran = Hof 1, Tisch 15, Nummer 5
Jennifer Sommer = Hof 1, Tisch 15, Nummer 6 Erika Erdem = Hof 1, Tisch 15, Nummer 6
Timo Kuhn = Hof 1, Tisch 15, Nummer 7 Dennis Sommer = Hof 1, Tisch 15, Nummer 7
Heinz Fischer = Hof 1, Tisch 15, Nummer 8 Jennifer Sommer = Hof 1, Tisch 15, Nummer 8
[16] [16]
Max Sommer = Hof 1, Tisch 16, Nummer 1 Leni Kuhn = Hof 1, Tisch 16, Nummer 1
Matteo Kraus = Hof 1, Tisch 16, Nummer 2 Emil Sommer = Hof 1, Tisch 16, Nummer 2
Elias Schwarz = Hof 1, Tisch 16, Nummer 3 Ida Sommer = Hof 1, Tisch 16, Nummer 3
Liam Schwarz = Hof 1, Tisch 16, Nummer 4 Liam Schwarz = Hof 1, Tisch 16, Nummer 4
Ida Sommer = Hof 1, Tisch 16, Nummer 5 Elias Schwarz = Hof 1, Tisch 16, Nummer 5
Frieda Brandt = Hof 1, Tisch 16, Nummer 6 Felix Brandt = Hof 1, Tisch 16, Nummer 6
Greta Brandt = Hof 1, Tisch 16, Nummer 7 Matteo Kraus = Hof 1, Tisch 16, Nummer 7
Leni Kuhn = Hof 1, Tisch 16, Nummer 8 Anton Brandt = Hof 1, Tisch 16, Nummer 8
Anton Brandt = Hof 1, Tisch 16, Nummer 9 Frieda Brandt = Hof 1, Tisch 16, Nummer 9
Theo Sommer = Hof 1, Tisch 16, Nummer 10 Mila Meyer = Hof 1, Tisch 16, Nummer 10
Felix Brandt = Hof 1, Tisch 16, Nummer 11 Greta Brandt = Hof 1, Tisch 16, Nummer 11
Mila Meyer = Hof 1, Tisch 16, Nummer 12 Theo Sommer = Hof 1, Tisch 16, Nummer 12
Emil Sommer = Hof 1, Tisch 16, Nummer 13 Max Sommer = Hof 1, Tisch 16, Nummer 13
[17] [17]
Anton Meyer = Hof 1, Tisch 17, Nummer 1 Ben Brandt = Hof 1, Tisch 17, Nummer 1
Ida Meyer = Hof 1, Tisch 17, Nummer 2 Paul Brandt = Hof 1, Tisch 17, Nummer 2
Paul Brandt = Hof 1, Tisch 17, Nummer 3 Anton Meyer = Hof 1, Tisch 17, Nummer 3
Anton Vogel = Hof 1, Tisch 17, Nummer 4 Ida Meyer = Hof 1, Tisch 17, Nummer 4
Ben Brandt = Hof 1, Tisch 17, Nummer 5 Anton Vogel = Hof 1, Tisch 17, Nummer 5
Max Vogel = Hof 1, Tisch 17, Nummer 6 Max Vogel = Hof 1, Tisch 17, Nummer 6
+291 -291
View File
@@ -1,300 +1,300 @@
Aksoy, Luca, = Hof 1, Tisch 44, Nummer 3 Aksoy, Luca, = Hof 1, Tisch 33, Nummer 2
Aksoy, Marie, = Hof 1, Tisch 37, Nummer 4 Aksoy, Marie, = Hof 1, Tisch 25, Nummer 4
Aksoy, Marija, = Hof 2, Tisch 53, Nummer 3 Aksoy, Marija, = Hof 2, Tisch 59, Nummer 5
Aksoy, Michael, Dr. = Hof 1, Tisch 40, Nummer 5 Aksoy, Michael, Dr. = Hof 2, Tisch 53, Nummer 3
Aksoy, Nadine, = Hof 1, Tisch 44, Nummer 2 Aksoy, Nadine, = Hof 1, Tisch 25, Nummer 2
Aksoy, Nicole, = Hof 2, Tisch 54, Nummer 2 Aksoy, Nicole, = Hof 2, Tisch 57, Nummer 4
Aksoy, Sergej, = Hof 1, Tisch 37, Nummer 2 Aksoy, Sergej, = Hof 1, Tisch 33, Nummer 4
Aksoy, Sofia, = Hof 1, Tisch 37, Nummer 5 Aksoy, Sofia, = Hof 1, Tisch 33, Nummer 3
Aksoy, Thomas, = Hof 1, Tisch 37, Nummer 3 Aksoy, Thomas, = Hof 1, Tisch 25, Nummer 3
Albrecht, Andreas, = Hof 1, Tisch 12, Nummer 4 Albrecht, Andreas, = Hof 1, Tisch 12, Nummer 4
Albrecht, Emre, Prof. Dr. = Hof 1, Tisch 36, Nummer 4 Albrecht, Emre, Prof. Dr. = Hof 2, Tisch 82, Nummer 3
Albrecht, Sarah, = Hof 1, Tisch 12, Nummer 5 Albrecht, Sarah, = Hof 1, Tisch 12, Nummer 3
Albrecht, Yusuf, Prof. Dr. = Hof 1, Tisch 10, Nummer 4 Albrecht, Yusuf, Prof. Dr. = Hof 1, Tisch 13, Nummer 2
Arnold, Christian, = Hof 2, Tisch 51, Nummer 4 Arnold, Christian, = Hof 1, Tisch 35, Nummer 3
Arnold, Jennifer, = Hof 2, Tisch 51, Nummer 2 Arnold, Jennifer, = Hof 1, Tisch 43, Nummer 2
Arnold, Jennifer, Dr. = Hof 1, Tisch 36, Nummer 3 Arnold, Jennifer, Dr. = Hof 2, Tisch 88, Nummer 3
Arnold, Leni, = Hof 2, Tisch 52, Nummer 4 Arnold, Leni, = Hof 1, Tisch 35, Nummer 2
Arnold, Mila, = Hof 2, Tisch 52, Nummer 2 Arnold, Mila, = Hof 1, Tisch 35, Nummer 4
Arnold, Nadine, = Hof 2, Tisch 60, Nummer 3 Arnold, Nadine, = Hof 2, Tisch 65, Nummer 2
Arnold, Patrick, = Hof 2, Tisch 52, Nummer 3 Arnold, Patrick, = Hof 1, Tisch 43, Nummer 3
Barth, Lina, = Hof 1, Tisch 14, Nummer 5 Barth, Lina, = Hof 2, Tisch 74, Nummer 5
Barth, Markus, = Hof 1, Tisch 35, Nummer 5 Barth, Markus, = Hof 1, Tisch 39, Nummer 2
Barth, Nadine, = Hof 1, Tisch 14, Nummer 3 Barth, Nadine, = Hof 2, Tisch 74, Nummer 3
Barth, Patrick, = Hof 1, Tisch 14, Nummer 4 Barth, Patrick, = Hof 2, Tisch 74, Nummer 2
Barth, Timo, = Hof 1, Tisch 14, Nummer 2 Barth, Timo, = Hof 2, Tisch 74, Nummer 4
Bauer, Dragana, = Hof 2, Tisch 48, Nummer 2 Bauer, Dragana, = Hof 1, Tisch 45, Nummer 4
Bauer, Yusuf, = Hof 1, Tisch 3, Nummer 5 Bauer, Yusuf, = Hof 1, Tisch 4, Nummer 4
Becker, Jan, = Hof 2, Tisch 65, Nummer 3 Becker, Jan, = Hof 1, Tisch 14, Nummer 3
Becker, Marija, = Hof 2, Tisch 49, Nummer 4 Becker, Marija, = Hof 2, Tisch 76, Nummer 3
Becker, Nicole, = Hof 2, Tisch 65, Nummer 2 Becker, Nicole, = Hof 1, Tisch 14, Nummer 2
Becker, Sandra, = Hof 2, Tisch 65, Nummer 4 Becker, Sandra, = Hof 1, Tisch 14, Nummer 4
Berger, Andreas, = Hof 1, Tisch 27, Nummer 3 Berger, Andreas, = Hof 1, Tisch 24, Nummer 2
Berger, Anton, = Hof 1, Tisch 26, Nummer 2 Berger, Anton, = Hof 1, Tisch 32, Nummer 3
Berger, Jennifer, = Hof 1, Tisch 26, Nummer 3 Berger, Jennifer, = Hof 1, Tisch 32, Nummer 2
Berger, Layla, = Hof 1, Tisch 26, Nummer 5 Berger, Layla, = Hof 1, Tisch 32, Nummer 4
Berger, Nadine, Dr. = Hof 2, Tisch 81, Nummer 4 Berger, Nadine, Dr. = Hof 1, Tisch 26, Nummer 3
Berger, Stefan, = Hof 1, Tisch 27, Nummer 5 Berger, Stefan, = Hof 1, Tisch 32, Nummer 5
Berger, Svenja, = Hof 1, Tisch 26, Nummer 4 Berger, Svenja, = Hof 1, Tisch 24, Nummer 5
Bianchi, Jan, Dr. = Hof 1, Tisch 4, Nummer 3 Bianchi, Jan, Dr. = Hof 1, Tisch 4, Nummer 5
Bianchi, Mia, = Hof 1, Tisch 43, Nummer 2 Bianchi, Mia, = Hof 2, Tisch 54, Nummer 4
Bianchi, Sandra, = Hof 1, Tisch 43, Nummer 4 Bianchi, Sandra, = Hof 2, Tisch 54, Nummer 2
Bianchi, Thomas, = Hof 1, Tisch 35, Nummer 4 Bianchi, Thomas, = Hof 2, Tisch 54, Nummer 3
Bianchi, Thomas, = Hof 1, Tisch 43, Nummer 3 Bianchi, Thomas, = Hof 2, Tisch 82, Nummer 4
Braun, Christian, = Hof 1, Tisch 19, Nummer 3 Braun, Christian, = Hof 1, Tisch 42, Nummer 4
Braun, Dragana, = Hof 1, Tisch 19, Nummer 4 Braun, Dragana, = Hof 1, Tisch 42, Nummer 3
Braun, Jan, = Hof 1, Tisch 20, Nummer 3 Braun, Jan, = Hof 1, Tisch 42, Nummer 2
Braun, Julia, = Hof 1, Tisch 19, Nummer 5 Braun, Julia, = Hof 1, Tisch 41, Nummer 2
Braun, Milan, = Hof 1, Tisch 20, Nummer 2 Braun, Milan, = Hof 1, Tisch 41, Nummer 3
Braun, Nadine, = Hof 1, Tisch 19, Nummer 2 Braun, Nadine, = Hof 1, Tisch 41, Nummer 4
Busch, Emre, = Hof 2, Tisch 55, Nummer 4 Busch, Emre, = Hof 2, Tisch 56, Nummer 3
Busch, Marie, = Hof 2, Tisch 55, Nummer 3 Busch, Marie, = Hof 2, Tisch 56, Nummer 4
Busch, Michael, = Hof 2, Tisch 55, Nummer 2 Busch, Michael, = Hof 2, Tisch 56, Nummer 5
Busch, Olga, = Hof 2, Tisch 55, Nummer 5 Busch, Olga, = Hof 2, Tisch 56, Nummer 2
Busch, Patrick, = Hof 1, Tisch 40, Nummer 3 Busch, Patrick, = Hof 2, Tisch 64, Nummer 3
Celik, Elif, = Hof 1, Tisch 22, Nummer 3 Celik, Elif, = Hof 1, Tisch 24, Nummer 4
Celik, Patrick, = Hof 1, Tisch 22, Nummer 4 Celik, Patrick, = Hof 1, Tisch 24, Nummer 3
Dallmann, Charlotte, = Hof 1, Tisch 7, Nummer 5 Dallmann, Charlotte, = Hof 1, Tisch 7, Nummer 5
Dallmann, Heinrich, = Hof 1, Tisch 7, Nummer 2 Dallmann, Heinrich, = Hof 1, Tisch 7, Nummer 2
Dallmann, Margarete, = Hof 1, Tisch 7, Nummer 4 Dallmann, Margarete, = Hof 1, Tisch 7, Nummer 3
Dallmann, Maximilian, = Hof 1, Tisch 7, Nummer 3 Dallmann, Maximilian, = Hof 1, Tisch 7, Nummer 4
Demir, Sandra, Dr. = Hof 1, Tisch 22, Nummer 2 Demir, Sandra, Dr. = Hof 1, Tisch 28, Nummer 3
Dietrich, Dragana, Prof. Dr. = Hof 1, Tisch 40, Nummer 2 Dietrich, Dragana, Prof. Dr. = Hof 2, Tisch 53, Nummer 2
Dietrich, Jennifer, = Hof 1, Tisch 1, Nummer 3 Dietrich, Jennifer, = Hof 1, Tisch 27, Nummer 2
Dietrich, Marco, = Hof 1, Tisch 1, Nummer 4 Dietrich, Marco, = Hof 1, Tisch 27, Nummer 3
Dietrich, Sofia, = Hof 1, Tisch 1, Nummer 2 Dietrich, Sofia, = Hof 1, Tisch 27, Nummer 4
Engel, Anja, = Hof 1, Tisch 25, Nummer 4 Engel, Anja, = Hof 1, Tisch 21, Nummer 3
Engel, Anton, = Hof 1, Tisch 25, Nummer 3 Engel, Anton, = Hof 1, Tisch 20, Nummer 5
Engel, Julia, = Hof 1, Tisch 24, Nummer 4 Engel, Julia, = Hof 1, Tisch 20, Nummer 4
Engel, Nicole, = Hof 1, Tisch 25, Nummer 2 Engel, Nicole, = Hof 1, Tisch 21, Nummer 2
Engel, Yusuf, = Hof 1, Tisch 24, Nummer 2 Engel, Yusuf, = Hof 1, Tisch 21, Nummer 4
Esposito, Jan, Dr. = Hof 1, Tisch 16, Nummer 4 Esposito, Jan, Dr. = Hof 1, Tisch 17, Nummer 3
Esposito, Yusuf, Prof. Dr. = Hof 2, Tisch 49, Nummer 3 Esposito, Yusuf, Prof. Dr. = Hof 2, Tisch 76, Nummer 2
Frank, Dennis, = Hof 1, Tisch 33, Nummer 4 Frank, Dennis, = Hof 2, Tisch 88, Nummer 5
Frank, Finn, = Hof 1, Tisch 33, Nummer 3 Frank, Finn, = Hof 2, Tisch 87, Nummer 4
Frank, Lena, = Hof 1, Tisch 24, Nummer 3 Frank, Lena, = Hof 2, Tisch 87, Nummer 2
Frank, Marie, = Hof 1, Tisch 33, Nummer 2 Frank, Marie, = Hof 2, Tisch 87, Nummer 3
Frank, Nadine, = Hof 1, Tisch 24, Nummer 5 Frank, Nadine, = Hof 2, Tisch 88, Nummer 4
Franke, Amira, = Hof 2, Tisch 76, Nummer 2 Franke, Amira, = Hof 2, Tisch 69, Nummer 3
Franke, Julia, = Hof 2, Tisch 76, Nummer 4 Franke, Julia, = Hof 2, Tisch 78, Nummer 5
Franke, Marco, = Hof 2, Tisch 77, Nummer 2 Franke, Marco, = Hof 2, Tisch 69, Nummer 4
Franke, Michael, = Hof 2, Tisch 76, Nummer 3 Franke, Michael, = Hof 2, Tisch 78, Nummer 4
Franke, Olga, = Hof 2, Tisch 77, Nummer 5 Franke, Olga, = Hof 2, Tisch 69, Nummer 2
Freifrau von Waldeck, Antonia, = Hof 1, Tisch 6, Nummer 3 Freifrau von Waldeck, Antonia, = Hof 1, Tisch 6, Nummer 4
Freiherr von Waldeck, Konstantin, Dr. = Hof 1, Tisch 6, Nummer 4 Freiherr von Waldeck, Konstantin, Dr. = Hof 1, Tisch 6, Nummer 3
Grothe, Alexander, Dr. h.c. = Hof 1, Tisch 5, Nummer 3 Grothe, Alexander, Dr. h.c. = Hof 1, Tisch 5, Nummer 2
Grothe, Beate, = Hof 1, Tisch 5, Nummer 2 Grothe, Beate, = Hof 1, Tisch 5, Nummer 3
Haas, Jennifer, Dr. = Hof 1, Tisch 34, Nummer 4 Haas, Jennifer, Dr. = Hof 1, Tisch 31, Nummer 3
Haas, Patrick, = Hof 2, Tisch 48, Nummer 4 Haas, Patrick, = Hof 1, Tisch 45, Nummer 2
Hansen, Giovanna, = Hof 1, Tisch 29, Nummer 4 Hansen, Giovanna, = Hof 1, Tisch 8, Nummer 2
Hansen, Markus, = Hof 1, Tisch 29, Nummer 3 Hansen, Markus, = Hof 1, Tisch 8, Nummer 3
Hansen, Nicole, Dr. = Hof 2, Tisch 47, Nummer 3 Hansen, Nicole, Dr. = Hof 1, Tisch 38, Nummer 2
Hansen, Olga, = Hof 1, Tisch 29, Nummer 2 Hansen, Olga, = Hof 1, Tisch 8, Nummer 4
Hansen, Thomas, = Hof 1, Tisch 16, Nummer 2 Hansen, Thomas, = Hof 1, Tisch 16, Nummer 2
Hartmann, Deniz, = Hof 2, Tisch 88, Nummer 4 Hartmann, Deniz, = Hof 2, Tisch 78, Nummer 2
Hartmann, Marija, = Hof 2, Tisch 87, Nummer 2 Hartmann, Marija, = Hof 2, Tisch 84, Nummer 2
Hartmann, Nadine, = Hof 2, Tisch 87, Nummer 4 Hartmann, Nadine, = Hof 2, Tisch 78, Nummer 3
Hartmann, Olga, = Hof 2, Tisch 88, Nummer 3 Hartmann, Olga, = Hof 2, Tisch 84, Nummer 4
Hartmann, Thomas, = Hof 2, Tisch 87, Nummer 3 Hartmann, Thomas, = Hof 2, Tisch 84, Nummer 3
Hoffmann, Emre, = Hof 1, Tisch 40, Nummer 4 Hoffmann, Emre, = Hof 2, Tisch 64, Nummer 4
Hoffmann, Patrick, Prof. Dr. = Hof 2, Tisch 60, Nummer 5 Hoffmann, Patrick, Prof. Dr. = Hof 2, Tisch 65, Nummer 4
Hoffmann, Thomas, Dr. = Hof 2, Tisch 46, Nummer 3 Hoffmann, Thomas, Dr. = Hof 2, Tisch 51, Nummer 3
Horn, Kathrin, = Hof 2, Tisch 72, Nummer 5 Horn, Kathrin, = Hof 2, Tisch 79, Nummer 2
Horn, Layla, = Hof 2, Tisch 72, Nummer 2 Horn, Layla, = Hof 2, Tisch 79, Nummer 4
Horn, Leon, = Hof 2, Tisch 72, Nummer 4 Horn, Leon, = Hof 2, Tisch 79, Nummer 5
Horn, Michael, = Hof 2, Tisch 72, Nummer 3 Horn, Michael, = Hof 2, Tisch 79, Nummer 3
Kaya, Christina, = Hof 2, Tisch 56, Nummer 3 Kaya, Christina, = Hof 2, Tisch 77, Nummer 3
Kaya, Luca, = Hof 2, Tisch 56, Nummer 2 Kaya, Luca, = Hof 2, Tisch 77, Nummer 2
Kaya, Nicole, = Hof 2, Tisch 56, Nummer 4 Kaya, Nicole, = Hof 2, Tisch 77, Nummer 4
Kaya, Patrick, Dr. = Hof 1, Tisch 3, Nummer 3 Kaya, Patrick, Dr. = Hof 1, Tisch 3, Nummer 3
Kaya, Timo, Prof. Dr. = Hof 1, Tisch 22, Nummer 5 Kaya, Timo, Prof. Dr. = Hof 1, Tisch 28, Nummer 2
Kessler, Ferdinand, Dr. = Hof 1, Tisch 5, Nummer 4 Kessler, Ferdinand, Dr. = Hof 1, Tisch 5, Nummer 4
Kessler, Viktoria, = Hof 1, Tisch 5, Nummer 5 Kessler, Viktoria, = Hof 1, Tisch 5, Nummer 5
Klein, Emre, = Hof 1, Tisch 4, Nummer 2 Klein, Emre, = Hof 1, Tisch 3, Nummer 2
Klein, Lina, = Hof 2, Tisch 78, Nummer 4 Klein, Lina, = Hof 1, Tisch 18, Nummer 4
Klein, Markus, = Hof 2, Tisch 54, Nummer 5 Klein, Markus, = Hof 2, Tisch 57, Nummer 5
Klein, Milan, = Hof 2, Tisch 78, Nummer 2 Klein, Milan, = Hof 1, Tisch 18, Nummer 3
Klein, Olga, Dr. = Hof 1, Tisch 36, Nummer 2 Klein, Olga, Dr. = Hof 2, Tisch 88, Nummer 2
Klein, Stefanie, = Hof 2, Tisch 78, Nummer 3 Klein, Stefanie, = Hof 1, Tisch 18, Nummer 2
Koch, Emil, = Hof 1, Tisch 42, Nummer 5 Koch, Emil, = Hof 2, Tisch 48, Nummer 3
Koch, Jan, = Hof 1, Tisch 42, Nummer 3 Koch, Jan, = Hof 2, Tisch 49, Nummer 3
Koch, Kathrin, Dr. = Hof 2, Tisch 68, Nummer 4 Koch, Kathrin, Dr. = Hof 2, Tisch 52, Nummer 4
Koch, Marie, = Hof 1, Tisch 41, Nummer 2 Koch, Marie, = Hof 2, Tisch 49, Nummer 4
Koch, Michael, = Hof 1, Tisch 42, Nummer 2 Koch, Michael, = Hof 2, Tisch 48, Nummer 2
Koch, Olga, = Hof 1, Tisch 41, Nummer 3 Koch, Olga, = Hof 2, Tisch 48, Nummer 4
Koch, Sarah, = Hof 1, Tisch 42, Nummer 4 Koch, Sarah, = Hof 2, Tisch 49, Nummer 2
Kovac, Anja, = Hof 1, Tisch 18, Nummer 3 Kovac, Anja, = Hof 1, Tisch 36, Nummer 3
Kovac, Henry, = Hof 1, Tisch 18, Nummer 2 Kovac, Henry, = Hof 1, Tisch 36, Nummer 4
Kovac, Lena, = Hof 1, Tisch 18, Nummer 5 Kovac, Lena, = Hof 1, Tisch 28, Nummer 4
Kovac, Luca, = Hof 2, Tisch 71, Nummer 4 Kovac, Luca, = Hof 2, Tisch 62, Nummer 2
Kovac, Marco, = Hof 1, Tisch 18, Nummer 4 Kovac, Marco, = Hof 1, Tisch 36, Nummer 2
Kovac, Marija, = Hof 1, Tisch 27, Nummer 2 Kovac, Marija, = Hof 1, Tisch 36, Nummer 5
Kovac, Matthias, = Hof 2, Tisch 49, Nummer 2 Kovac, Matthias, = Hof 2, Tisch 76, Nummer 4
Kovac, Tobias, = Hof 1, Tisch 27, Nummer 4 Kovac, Tobias, = Hof 1, Tisch 28, Nummer 5
Kraus, Markus, = Hof 1, Tisch 8, Nummer 2 Kraus, Markus, = Hof 1, Tisch 11, Nummer 4
Kraus, Patrick, Dr. = Hof 2, Tisch 70, Nummer 3 Kraus, Patrick, Dr. = Hof 2, Tisch 67, Nummer 3
Krause, Andreas, = Hof 1, Tisch 13, Nummer 2 Krause, Andreas, = Hof 2, Tisch 63, Nummer 2
Krause, Arda, = Hof 1, Tisch 13, Nummer 5 Krause, Arda, = Hof 2, Tisch 63, Nummer 4
Krause, Christina, Dr. = Hof 1, Tisch 3, Nummer 2 Krause, Christina, Dr. = Hof 1, Tisch 3, Nummer 4
Krause, Daniel, = Hof 2, Tisch 54, Nummer 3 Krause, Daniel, = Hof 2, Tisch 57, Nummer 3
Krause, Dragana, Dr. = Hof 2, Tisch 71, Nummer 3 Krause, Dragana, Dr. = Hof 2, Tisch 62, Nummer 3
Krause, Emma, = Hof 1, Tisch 13, Nummer 3 Krause, Emma, = Hof 2, Tisch 63, Nummer 3
Krause, Julia, = Hof 1, Tisch 13, Nummer 4 Krause, Julia, = Hof 2, Tisch 63, Nummer 5
Krause, Matthias, = Hof 2, Tisch 70, Nummer 5 Krause, Matthias, = Hof 2, Tisch 58, Nummer 3
Krause, Thomas, = Hof 2, Tisch 47, Nummer 2 Krause, Thomas, = Hof 1, Tisch 38, Nummer 3
Kuhn, Julia, Dr. = Hof 2, Tisch 69, Nummer 4 Kuhn, Julia, Dr. = Hof 2, Tisch 52, Nummer 5
Lange, Dragana, = Hof 1, Tisch 23, Nummer 4 Lange, Dragana, = Hof 1, Tisch 43, Nummer 4
Lange, Jan, = Hof 1, Tisch 23, Nummer 3 Lange, Jan, = Hof 1, Tisch 44, Nummer 2
Lange, Michael, = Hof 1, Tisch 31, Nummer 3 Lange, Michael, = Hof 1, Tisch 43, Nummer 5
Lange, Sergej, = Hof 1, Tisch 39, Nummer 4 Lange, Sergej, = Hof 2, Tisch 64, Nummer 5
Lange, Sofia, = Hof 1, Tisch 31, Nummer 5 Lange, Sofia, = Hof 1, Tisch 44, Nummer 4
Lange, Svenja, = Hof 1, Tisch 23, Nummer 2 Lange, Svenja, = Hof 1, Tisch 44, Nummer 3
Lehmann, Giovanna, = Hof 1, Tisch 21, Nummer 5 Lehmann, Giovanna, = Hof 1, Tisch 13, Nummer 3
Lehmann, Layla, = Hof 1, Tisch 21, Nummer 3 Lehmann, Layla, = Hof 1, Tisch 2, Nummer 2
Lehmann, Markus, = Hof 1, Tisch 10, Nummer 3 Lehmann, Markus, = Hof 1, Tisch 2, Nummer 5
Lehmann, Milan, = Hof 1, Tisch 10, Nummer 2 Lehmann, Milan, = Hof 1, Tisch 13, Nummer 4
Lehmann, Nicole, = Hof 1, Tisch 21, Nummer 4 Lehmann, Nicole, = Hof 1, Tisch 2, Nummer 4
Lehmann, Patrick, = Hof 2, Tisch 81, Nummer 3 Lehmann, Patrick, = Hof 1, Tisch 26, Nummer 4
Lehmann, Thomas, = Hof 1, Tisch 21, Nummer 2 Lehmann, Thomas, = Hof 1, Tisch 2, Nummer 3
Ludwig, Aylin, Dr. = Hof 2, Tisch 70, Nummer 4 Ludwig, Aylin, Dr. = Hof 2, Tisch 67, Nummer 4
Ludwig, Elias, = Hof 2, Tisch 64, Nummer 5 Ludwig, Elias, = Hof 1, Tisch 9, Nummer 5
Ludwig, Elif, = Hof 2, Tisch 64, Nummer 2 Ludwig, Elif, = Hof 1, Tisch 9, Nummer 4
Ludwig, Emre, = Hof 2, Tisch 64, Nummer 3 Ludwig, Emre, = Hof 1, Tisch 9, Nummer 3
Ludwig, Emre, Prof. Dr. = Hof 2, Tisch 54, Nummer 4 Ludwig, Emre, Prof. Dr. = Hof 2, Tisch 57, Nummer 2
Ludwig, Giovanna, = Hof 2, Tisch 64, Nummer 4 Ludwig, Giovanna, = Hof 1, Tisch 9, Nummer 2
Maier, Arda, = Hof 2, Tisch 66, Nummer 4 Maier, Arda, = Hof 2, Tisch 61, Nummer 5
Maier, Christian, = Hof 2, Tisch 66, Nummer 2 Maier, Christian, = Hof 2, Tisch 61, Nummer 3
Maier, Olga, = Hof 2, Tisch 66, Nummer 5 Maier, Olga, = Hof 2, Tisch 61, Nummer 4
Maier, Sarah, = Hof 2, Tisch 66, Nummer 3 Maier, Sarah, = Hof 2, Tisch 61, Nummer 2
Neumann, Jennifer, = Hof 2, Tisch 73, Nummer 2 Neumann, Jennifer, = Hof 2, Tisch 73, Nummer 2
Neumann, Lina, = Hof 2, Tisch 73, Nummer 4 Neumann, Lina, = Hof 2, Tisch 73, Nummer 4
Neumann, Matteo, = Hof 2, Tisch 73, Nummer 3 Neumann, Matteo, = Hof 2, Tisch 73, Nummer 5
Neumann, Thomas, = Hof 2, Tisch 73, Nummer 5 Neumann, Thomas, = Hof 2, Tisch 73, Nummer 3
Nguyen, Anja, = Hof 2, Tisch 62, Nummer 3 Nguyen, Anja, = Hof 1, Tisch 15, Nummer 2
Nguyen, Daniel, = Hof 2, Tisch 62, Nummer 4 Nguyen, Daniel, = Hof 1, Tisch 15, Nummer 3
Nguyen, Julia, = Hof 1, Tisch 17, Nummer 2 Nguyen, Julia, = Hof 1, Tisch 16, Nummer 4
Nguyen, Sofia, = Hof 2, Tisch 62, Nummer 2 Nguyen, Sofia, = Hof 1, Tisch 15, Nummer 4
Nowak, Aylin, = Hof 1, Tisch 38, Nummer 3 Nowak, Aylin, = Hof 1, Tisch 37, Nummer 2
Nowak, Felix, = Hof 1, Tisch 38, Nummer 2 Nowak, Felix, = Hof 1, Tisch 29, Nummer 2
Nowak, Kathrin, = Hof 1, Tisch 38, Nummer 4 Nowak, Kathrin, = Hof 1, Tisch 29, Nummer 5
Nowak, Lina, = Hof 1, Tisch 45, Nummer 2 Nowak, Lina, = Hof 1, Tisch 37, Nummer 4
Nowak, Markus, = Hof 1, Tisch 45, Nummer 3 Nowak, Markus, = Hof 1, Tisch 37, Nummer 3
Nowak, Noah, = Hof 1, Tisch 45, Nummer 4 Nowak, Noah, = Hof 1, Tisch 37, Nummer 5
Ott, Daniel, = Hof 2, Tisch 88, Nummer 5 Ott, Daniel, = Hof 2, Tisch 80, Nummer 5
Ott, Hannah, = Hof 2, Tisch 82, Nummer 4 Ott, Hannah, = Hof 2, Tisch 72, Nummer 3
Ott, Luca, = Hof 2, Tisch 61, Nummer 2 Ott, Luca, = Hof 2, Tisch 71, Nummer 2
Ott, Matthias, = Hof 2, Tisch 82, Nummer 2 Ott, Matthias, = Hof 2, Tisch 72, Nummer 2
Ott, Melanie, = Hof 2, Tisch 82, Nummer 3 Ott, Melanie, = Hof 2, Tisch 80, Nummer 4
Ott, Olga, = Hof 2, Tisch 88, Nummer 2 Ott, Olga, = Hof 2, Tisch 72, Nummer 4
Ott, Sergej, Prof. Dr. = Hof 2, Tisch 47, Nummer 4 Ott, Sergej, Prof. Dr. = Hof 1, Tisch 45, Nummer 3
Ott, Yusuf, Prof. Dr. = Hof 2, Tisch 81, Nummer 2 Ott, Yusuf, Prof. Dr. = Hof 1, Tisch 26, Nummer 2
Peters, Christian, = Hof 1, Tisch 8, Nummer 5 Peters, Christian, = Hof 1, Tisch 10, Nummer 5
Peters, Nicole, = Hof 2, Tisch 48, Nummer 3 Peters, Nicole, = Hof 1, Tisch 45, Nummer 5
Petrov, Giovanna, = Hof 1, Tisch 8, Nummer 4 Petrov, Giovanna, = Hof 1, Tisch 10, Nummer 2
Petrov, Kathrin, = Hof 1, Tisch 39, Nummer 3 Petrov, Kathrin, = Hof 1, Tisch 38, Nummer 4
Petrov, Kathrin, Prof. Dr. = Hof 1, Tisch 9, Nummer 4 Petrov, Kathrin, Prof. Dr. = Hof 1, Tisch 11, Nummer 2
Petrov, Matthias, = Hof 1, Tisch 35, Nummer 2 Petrov, Matthias, = Hof 1, Tisch 39, Nummer 3
Petrov, Milan, = Hof 1, Tisch 39, Nummer 2 Petrov, Milan, = Hof 1, Tisch 38, Nummer 5
Petrov, Sergej, = Hof 2, Tisch 53, Nummer 5 Petrov, Sergej, = Hof 2, Tisch 59, Nummer 3
Pohl, Dragana, = Hof 2, Tisch 85, Nummer 2 Pohl, Dragana, = Hof 2, Tisch 75, Nummer 2
Pohl, Emre, = Hof 2, Tisch 85, Nummer 5 Pohl, Emre, = Hof 2, Tisch 75, Nummer 3
Pohl, Mia, = Hof 2, Tisch 85, Nummer 4 Pohl, Mia, = Hof 2, Tisch 75, Nummer 4
Pohl, Theo, = Hof 2, Tisch 85, Nummer 3 Pohl, Theo, = Hof 2, Tisch 75, Nummer 5
Polat, Kathrin, = Hof 2, Tisch 53, Nummer 4 Polat, Kathrin, = Hof 2, Tisch 59, Nummer 4
Polat, Katrin, = Hof 2, Tisch 84, Nummer 3 Polat, Katrin, = Hof 2, Tisch 81, Nummer 4
Polat, Marija, = Hof 2, Tisch 60, Nummer 2 Polat, Marija, = Hof 2, Tisch 65, Nummer 5
Polat, Markus, = Hof 2, Tisch 77, Nummer 3 Polat, Markus, = Hof 2, Tisch 81, Nummer 3
Polat, Sarah, = Hof 2, Tisch 77, Nummer 4 Polat, Sarah, = Hof 2, Tisch 81, Nummer 2
Polat, Stefan, = Hof 2, Tisch 84, Nummer 4 Polat, Stefan, = Hof 2, Tisch 80, Nummer 3
Polat, Stefanie, = Hof 2, Tisch 84, Nummer 2 Polat, Stefanie, = Hof 2, Tisch 80, Nummer 2
Popescu, Matthias, = Hof 1, Tisch 12, Nummer 3 Popescu, Matthias, = Hof 1, Tisch 12, Nummer 2
Richter, Anja, = Hof 1, Tisch 30, Nummer 4 Richter, Anja, = Hof 2, Tisch 50, Nummer 2
Richter, Anja, Prof. Dr. = Hof 2, Tisch 80, Nummer 2 Richter, Anja, Prof. Dr. = Hof 1, Tisch 22, Nummer 2
Richter, Anton, = Hof 1, Tisch 30, Nummer 5 Richter, Anton, = Hof 2, Tisch 50, Nummer 5
Richter, Greta, = Hof 1, Tisch 30, Nummer 3 Richter, Greta, = Hof 2, Tisch 50, Nummer 4
Richter, Julia, Prof. Dr. = Hof 1, Tisch 34, Nummer 3 Richter, Julia, Prof. Dr. = Hof 1, Tisch 31, Nummer 2
Richter, Marco, = Hof 2, Tisch 60, Nummer 4 Richter, Marco, = Hof 2, Tisch 65, Nummer 3
Richter, Matthias, = Hof 1, Tisch 30, Nummer 2 Richter, Matthias, = Hof 2, Tisch 50, Nummer 3
Richter, Stefan, = Hof 2, Tisch 71, Nummer 2 Richter, Stefan, = Hof 2, Tisch 71, Nummer 4
Rossi, Emilia, = Hof 1, Tisch 28, Nummer 4 Rossi, Emilia, = Hof 1, Tisch 40, Nummer 4
Rossi, Luca, = Hof 1, Tisch 28, Nummer 2 Rossi, Luca, = Hof 1, Tisch 40, Nummer 3
Rossi, Melanie, = Hof 1, Tisch 28, Nummer 3 Rossi, Melanie, = Hof 1, Tisch 40, Nummer 2
Roth, Christian, = Hof 2, Tisch 79, Nummer 4 Roth, Christian, = Hof 1, Tisch 23, Nummer 3
Roth, Julia, Prof. Dr. = Hof 1, Tisch 17, Nummer 5 Roth, Julia, Prof. Dr. = Hof 1, Tisch 17, Nummer 4
Roth, Olga, = Hof 1, Tisch 35, Nummer 3 Roth, Olga, = Hof 2, Tisch 82, Nummer 2
Roth, Sarah, = Hof 2, Tisch 79, Nummer 3 Roth, Sarah, = Hof 1, Tisch 23, Nummer 2
Roth, Sofia, = Hof 2, Tisch 79, Nummer 2 Roth, Sofia, = Hof 1, Tisch 23, Nummer 4
Sahin, Kathrin, = Hof 1, Tisch 11, Nummer 5 Sahin, Kathrin, = Hof 2, Tisch 60, Nummer 4
Sahin, Markus, = Hof 1, Tisch 11, Nummer 2 Sahin, Markus, = Hof 2, Tisch 60, Nummer 3
Sahin, Nicole, = Hof 1, Tisch 11, Nummer 3 Sahin, Nicole, = Hof 2, Tisch 60, Nummer 2
Sahin, Patrick, = Hof 1, Tisch 11, Nummer 4 Sahin, Patrick, = Hof 2, Tisch 60, Nummer 5
Sahin, Thomas, = Hof 2, Tisch 80, Nummer 3 Sahin, Thomas, = Hof 1, Tisch 22, Nummer 4
Schmidt, Giovanna, = Hof 2, Tisch 57, Nummer 3 Schmidt, Giovanna, = Hof 2, Tisch 85, Nummer 4
Schmidt, Marie, = Hof 2, Tisch 57, Nummer 4 Schmidt, Marie, = Hof 2, Tisch 85, Nummer 3
Schmidt, Matthias, = Hof 2, Tisch 57, Nummer 2 Schmidt, Matthias, = Hof 2, Tisch 85, Nummer 2
Schmidt, Nicole, = Hof 1, Tisch 17, Nummer 4 Schmidt, Nicole, = Hof 1, Tisch 16, Nummer 3
Schmitt, Dennis, Prof. Dr. = Hof 2, Tisch 71, Nummer 5 Schmitt, Dennis, Prof. Dr. = Hof 2, Tisch 62, Nummer 4
Schmitt, Markus, = Hof 1, Tisch 15, Nummer 4 Schmitt, Markus, = Hof 1, Tisch 10, Nummer 4
Schmitt, Markus, = Hof 1, Tisch 9, Nummer 3 Schmitt, Markus, = Hof 2, Tisch 47, Nummer 3
Schmitt, Sarah, = Hof 1, Tisch 15, Nummer 2 Schmitt, Sarah, = Hof 2, Tisch 47, Nummer 2
Schmitt, Sofia, = Hof 1, Tisch 15, Nummer 3 Schmitt, Sofia, = Hof 2, Tisch 47, Nummer 4
Schmitt, Stefan, Prof. Dr. = Hof 2, Tisch 69, Nummer 3 Schmitt, Stefan, Prof. Dr. = Hof 2, Tisch 52, Nummer 2
Schwarz, Giovanna, = Hof 2, Tisch 61, Nummer 5 Schwarz, Giovanna, = Hof 2, Tisch 58, Nummer 4
Seidel, Anja, Dr. = Hof 2, Tisch 46, Nummer 2 Seidel, Anja, Dr. = Hof 2, Tisch 51, Nummer 5
Seidel, Markus, Dr. = Hof 1, Tisch 9, Nummer 2 Seidel, Markus, Dr. = Hof 1, Tisch 11, Nummer 3
Seidel, Yusuf, Prof. Dr. = Hof 1, Tisch 3, Nummer 4 Seidel, Yusuf, Prof. Dr. = Hof 1, Tisch 4, Nummer 3
Seifert, Elif, = Hof 2, Tisch 50, Nummer 3 Seifert, Elif, = Hof 1, Tisch 20, Nummer 3
Seifert, Leni, = Hof 2, Tisch 50, Nummer 2 Seifert, Leni, = Hof 1, Tisch 19, Nummer 4
Seifert, Marco, Prof. Dr. = Hof 2, Tisch 70, Nummer 2 Seifert, Marco, Prof. Dr. = Hof 2, Tisch 58, Nummer 2
Seifert, Nicole, = Hof 2, Tisch 51, Nummer 3 Seifert, Nicole, = Hof 1, Tisch 19, Nummer 2
Seifert, Stefanie, Dr. = Hof 1, Tisch 17, Nummer 3 Seifert, Stefanie, Dr. = Hof 1, Tisch 16, Nummer 5
Seifert, Timo, = Hof 2, Tisch 51, Nummer 5 Seifert, Timo, = Hof 1, Tisch 20, Nummer 2
Seifert, Yusuf, = Hof 2, Tisch 50, Nummer 4 Seifert, Yusuf, = Hof 1, Tisch 19, Nummer 3
Simon, Andreas, = Hof 2, Tisch 75, Nummer 2 Simon, Andreas, = Hof 2, Tisch 66, Nummer 5
Simon, Emma, = Hof 2, Tisch 75, Nummer 3 Simon, Emma, = Hof 2, Tisch 66, Nummer 4
Simon, Lena, = Hof 2, Tisch 75, Nummer 5 Simon, Lena, = Hof 2, Tisch 66, Nummer 2
Simon, Markus, = Hof 2, Tisch 75, Nummer 4 Simon, Markus, = Hof 2, Tisch 66, Nummer 3
Simon, Svenja, = Hof 1, Tisch 10, Nummer 5 Simon, Svenja, = Hof 1, Tisch 13, Nummer 5
Stein, Ben, = Hof 2, Tisch 83, Nummer 2 Stein, Ben, = Hof 2, Tisch 86, Nummer 4
Stein, Emilia, = Hof 2, Tisch 83, Nummer 4 Stein, Emilia, = Hof 2, Tisch 86, Nummer 3
Stein, Giovanna, = Hof 2, Tisch 83, Nummer 3 Stein, Giovanna, = Hof 2, Tisch 86, Nummer 5
Stein, Markus, Prof. Dr. = Hof 1, Tisch 12, Nummer 2 Stein, Markus, Prof. Dr. = Hof 1, Tisch 12, Nummer 5
Stein, Nadine, Dr. = Hof 1, Tisch 8, Nummer 3 Stein, Nadine, Dr. = Hof 1, Tisch 10, Nummer 3
Stein, Thomas, = Hof 2, Tisch 83, Nummer 5 Stein, Thomas, = Hof 2, Tisch 86, Nummer 2
Steinbach, Elisabeth, = Hof 1, Tisch 6, Nummer 5 Steinbach, Elisabeth, = Hof 1, Tisch 6, Nummer 2
Steinbach, Georg, = Hof 1, Tisch 6, Nummer 2 Steinbach, Georg, = Hof 1, Tisch 6, Nummer 5
Thiel, Christina, = Hof 1, Tisch 2, Nummer 3 Thiel, Christina, = Hof 2, Tisch 46, Nummer 3
Thiel, Jan, Dr. = Hof 2, Tisch 80, Nummer 4 Thiel, Jan, Dr. = Hof 1, Tisch 22, Nummer 3
Thiel, Julia, = Hof 1, Tisch 2, Nummer 2 Thiel, Julia, = Hof 2, Tisch 46, Nummer 4
Thiel, Yusuf, = Hof 1, Tisch 2, Nummer 4 Thiel, Yusuf, = Hof 2, Tisch 46, Nummer 2
Tran, Marija, = Hof 2, Tisch 68, Nummer 2 Tran, Marija, = Hof 2, Tisch 52, Nummer 3
Tran, Olga, = Hof 2, Tisch 46, Nummer 4 Tran, Olga, = Hof 2, Tisch 51, Nummer 4
Tran, Thomas, Prof. Dr. = Hof 2, Tisch 53, Nummer 2 Tran, Thomas, Prof. Dr. = Hof 2, Tisch 59, Nummer 2
Wagner, Henry, = Hof 2, Tisch 63, Nummer 3 Wagner, Henry, = Hof 2, Tisch 68, Nummer 5
Wagner, Marco, = Hof 2, Tisch 63, Nummer 5 Wagner, Marco, = Hof 2, Tisch 68, Nummer 3
Wagner, Nicole, = Hof 2, Tisch 63, Nummer 2 Wagner, Nicole, = Hof 2, Tisch 68, Nummer 2
Wagner, Sarah, = Hof 2, Tisch 63, Nummer 4 Wagner, Sarah, = Hof 2, Tisch 68, Nummer 4
Weber, Andreas, = Hof 1, Tisch 34, Nummer 2 Weber, Andreas, = Hof 1, Tisch 39, Nummer 4
Weber, Julia, = Hof 1, Tisch 4, Nummer 5 Weber, Julia, = Hof 1, Tisch 3, Nummer 5
Weber, Katrin, = Hof 2, Tisch 69, Nummer 2 Weber, Katrin, = Hof 2, Tisch 53, Nummer 4
Weber, Yusuf, = Hof 2, Tisch 61, Nummer 4 Weber, Yusuf, = Hof 2, Tisch 67, Nummer 2
Werner, Andreas, = Hof 2, Tisch 59, Nummer 2 Werner, Andreas, = Hof 2, Tisch 55, Nummer 3
Werner, Dennis, Prof. Dr. = Hof 2, Tisch 46, Nummer 5 Werner, Dennis, Prof. Dr. = Hof 2, Tisch 51, Nummer 2
Werner, Katrin, = Hof 1, Tisch 39, Nummer 5 Werner, Katrin, = Hof 2, Tisch 64, Nummer 2
Werner, Luca, = Hof 2, Tisch 68, Nummer 3 Werner, Luca, = Hof 2, Tisch 53, Nummer 5
Werner, Marco, = Hof 2, Tisch 59, Nummer 4 Werner, Marco, = Hof 2, Tisch 55, Nummer 5
Werner, Nadine, = Hof 2, Tisch 59, Nummer 3 Werner, Nadine, = Hof 2, Tisch 55, Nummer 4
Werner, Sandra, = Hof 2, Tisch 59, Nummer 5 Werner, Sandra, = Hof 2, Tisch 55, Nummer 2
Winkler, Lena, = Hof 1, Tisch 31, Nummer 4 Winkler, Lena, = Hof 1, Tisch 29, Nummer 3
Winkler, Marco, = Hof 1, Tisch 4, Nummer 4 Winkler, Marco, = Hof 1, Tisch 4, Nummer 2
Winkler, Patrick, = Hof 1, Tisch 31, Nummer 2 Winkler, Patrick, = Hof 1, Tisch 29, Nummer 4
Winkler, Thomas, = Hof 1, Tisch 16, Nummer 3 Winkler, Thomas, = Hof 1, Tisch 17, Nummer 2
Wolf, Ben, = Hof 2, Tisch 74, Nummer 4 Wolf, Ben, = Hof 2, Tisch 83, Nummer 3
Wolf, Emma, = Hof 2, Tisch 74, Nummer 2 Wolf, Emma, = Hof 2, Tisch 83, Nummer 2
Wolf, Julia, = Hof 2, Tisch 74, Nummer 3 Wolf, Julia, = Hof 2, Tisch 83, Nummer 4
Wolf, Thomas, = Hof 2, Tisch 74, Nummer 5 Wolf, Thomas, = Hof 2, Tisch 83, Nummer 5
Zimmermann, Jan, = Hof 2, Tisch 67, Nummer 5 Zimmermann, Jan, = Hof 2, Tisch 70, Nummer 3
Zimmermann, Markus, = Hof 2, Tisch 67, Nummer 4 Zimmermann, Markus, = Hof 2, Tisch 70, Nummer 5
Zimmermann, Mia, = Hof 2, Tisch 67, Nummer 3 Zimmermann, Mia, = Hof 2, Tisch 70, Nummer 4
Zimmermann, Patrick, = Hof 2, Tisch 61, Nummer 3 Zimmermann, Patrick, = Hof 2, Tisch 71, Nummer 3
Zimmermann, Svenja, = Hof 2, Tisch 67, Nummer 2 Zimmermann, Svenja, = Hof 2, Tisch 70, Nummer 2
1 Aksoy Luca = Hof 1 Tisch 44 Tisch 33 Nummer 3 Nummer 2
2 Aksoy Marie = Hof 1 Tisch 37 Tisch 25 Nummer 4 Nummer 4
3 Aksoy Marija = Hof 2 Tisch 53 Tisch 59 Nummer 3 Nummer 5
4 Aksoy Michael Dr. = Hof 1 Dr. = Hof 2 Tisch 40 Tisch 53 Nummer 5 Nummer 3
5 Aksoy Nadine = Hof 1 Tisch 44 Tisch 25 Nummer 2 Nummer 2
6 Aksoy Nicole = Hof 2 Tisch 54 Tisch 57 Nummer 2 Nummer 4
7 Aksoy Sergej = Hof 1 Tisch 37 Tisch 33 Nummer 2 Nummer 4
8 Aksoy Sofia = Hof 1 Tisch 37 Tisch 33 Nummer 5 Nummer 3
9 Aksoy Thomas = Hof 1 Tisch 37 Tisch 25 Nummer 3 Nummer 3
10 Albrecht Andreas = Hof 1 Tisch 12 Tisch 12 Nummer 4 Nummer 4
11 Albrecht Emre Prof. Dr. = Hof 1 Prof. Dr. = Hof 2 Tisch 36 Tisch 82 Nummer 4 Nummer 3
12 Albrecht Sarah = Hof 1 Tisch 12 Tisch 12 Nummer 5 Nummer 3
13 Albrecht Yusuf Prof. Dr. = Hof 1 Tisch 10 Tisch 13 Nummer 4 Nummer 2
14 Arnold Christian = Hof 2 = Hof 1 Tisch 51 Tisch 35 Nummer 4 Nummer 3
15 Arnold Jennifer = Hof 2 = Hof 1 Tisch 51 Tisch 43 Nummer 2 Nummer 2
16 Arnold Jennifer Dr. = Hof 1 Dr. = Hof 2 Tisch 36 Tisch 88 Nummer 3 Nummer 3
17 Arnold Leni = Hof 2 = Hof 1 Tisch 52 Tisch 35 Nummer 4 Nummer 2
18 Arnold Mila = Hof 2 = Hof 1 Tisch 52 Tisch 35 Nummer 2 Nummer 4
19 Arnold Nadine = Hof 2 Tisch 60 Tisch 65 Nummer 3 Nummer 2
20 Arnold Patrick = Hof 2 = Hof 1 Tisch 52 Tisch 43 Nummer 3 Nummer 3
21 Barth Lina = Hof 1 = Hof 2 Tisch 14 Tisch 74 Nummer 5 Nummer 5
22 Barth Markus = Hof 1 Tisch 35 Tisch 39 Nummer 5 Nummer 2
23 Barth Nadine = Hof 1 = Hof 2 Tisch 14 Tisch 74 Nummer 3 Nummer 3
24 Barth Patrick = Hof 1 = Hof 2 Tisch 14 Tisch 74 Nummer 4 Nummer 2
25 Barth Timo = Hof 1 = Hof 2 Tisch 14 Tisch 74 Nummer 2 Nummer 4
26 Bauer Dragana = Hof 2 = Hof 1 Tisch 48 Tisch 45 Nummer 2 Nummer 4
27 Bauer Yusuf = Hof 1 Tisch 3 Tisch 4 Nummer 5 Nummer 4
28 Becker Jan = Hof 2 = Hof 1 Tisch 65 Tisch 14 Nummer 3 Nummer 3
29 Becker Marija = Hof 2 Tisch 49 Tisch 76 Nummer 4 Nummer 3
30 Becker Nicole = Hof 2 = Hof 1 Tisch 65 Tisch 14 Nummer 2 Nummer 2
31 Becker Sandra = Hof 2 = Hof 1 Tisch 65 Tisch 14 Nummer 4 Nummer 4
32 Berger Andreas = Hof 1 Tisch 27 Tisch 24 Nummer 3 Nummer 2
33 Berger Anton = Hof 1 Tisch 26 Tisch 32 Nummer 2 Nummer 3
34 Berger Jennifer = Hof 1 Tisch 26 Tisch 32 Nummer 3 Nummer 2
35 Berger Layla = Hof 1 Tisch 26 Tisch 32 Nummer 5 Nummer 4
36 Berger Nadine Dr. = Hof 2 Dr. = Hof 1 Tisch 81 Tisch 26 Nummer 4 Nummer 3
37 Berger Stefan = Hof 1 Tisch 27 Tisch 32 Nummer 5 Nummer 5
38 Berger Svenja = Hof 1 Tisch 26 Tisch 24 Nummer 4 Nummer 5
39 Bianchi Jan Dr. = Hof 1 Tisch 4 Tisch 4 Nummer 3 Nummer 5
40 Bianchi Mia = Hof 1 = Hof 2 Tisch 43 Tisch 54 Nummer 2 Nummer 4
41 Bianchi Sandra = Hof 1 = Hof 2 Tisch 43 Tisch 54 Nummer 4 Nummer 2
42 Bianchi Thomas = Hof 1 = Hof 2 Tisch 35 Tisch 54 Nummer 4 Nummer 3
43 Bianchi Thomas = Hof 1 = Hof 2 Tisch 43 Tisch 82 Nummer 3 Nummer 4
44 Braun Christian = Hof 1 Tisch 19 Tisch 42 Nummer 3 Nummer 4
45 Braun Dragana = Hof 1 Tisch 19 Tisch 42 Nummer 4 Nummer 3
46 Braun Jan = Hof 1 Tisch 20 Tisch 42 Nummer 3 Nummer 2
47 Braun Julia = Hof 1 Tisch 19 Tisch 41 Nummer 5 Nummer 2
48 Braun Milan = Hof 1 Tisch 20 Tisch 41 Nummer 2 Nummer 3
49 Braun Nadine = Hof 1 Tisch 19 Tisch 41 Nummer 2 Nummer 4
50 Busch Emre = Hof 2 Tisch 55 Tisch 56 Nummer 4 Nummer 3
51 Busch Marie = Hof 2 Tisch 55 Tisch 56 Nummer 3 Nummer 4
52 Busch Michael = Hof 2 Tisch 55 Tisch 56 Nummer 2 Nummer 5
53 Busch Olga = Hof 2 Tisch 55 Tisch 56 Nummer 5 Nummer 2
54 Busch Patrick = Hof 1 = Hof 2 Tisch 40 Tisch 64 Nummer 3 Nummer 3
55 Celik Elif = Hof 1 Tisch 22 Tisch 24 Nummer 3 Nummer 4
56 Celik Patrick = Hof 1 Tisch 22 Tisch 24 Nummer 4 Nummer 3
57 Dallmann Charlotte = Hof 1 Tisch 7 Tisch 7 Nummer 5 Nummer 5
58 Dallmann Heinrich = Hof 1 Tisch 7 Tisch 7 Nummer 2 Nummer 2
59 Dallmann Margarete = Hof 1 Tisch 7 Tisch 7 Nummer 4 Nummer 3
60 Dallmann Maximilian = Hof 1 Tisch 7 Tisch 7 Nummer 3 Nummer 4
61 Demir Sandra Dr. = Hof 1 Tisch 22 Tisch 28 Nummer 2 Nummer 3
62 Dietrich Dragana Prof. Dr. = Hof 1 Prof. Dr. = Hof 2 Tisch 40 Tisch 53 Nummer 2 Nummer 2
63 Dietrich Jennifer = Hof 1 Tisch 1 Tisch 27 Nummer 3 Nummer 2
64 Dietrich Marco = Hof 1 Tisch 1 Tisch 27 Nummer 4 Nummer 3
65 Dietrich Sofia = Hof 1 Tisch 1 Tisch 27 Nummer 2 Nummer 4
66 Engel Anja = Hof 1 Tisch 25 Tisch 21 Nummer 4 Nummer 3
67 Engel Anton = Hof 1 Tisch 25 Tisch 20 Nummer 3 Nummer 5
68 Engel Julia = Hof 1 Tisch 24 Tisch 20 Nummer 4 Nummer 4
69 Engel Nicole = Hof 1 Tisch 25 Tisch 21 Nummer 2 Nummer 2
70 Engel Yusuf = Hof 1 Tisch 24 Tisch 21 Nummer 2 Nummer 4
71 Esposito Jan Dr. = Hof 1 Tisch 16 Tisch 17 Nummer 4 Nummer 3
72 Esposito Yusuf Prof. Dr. = Hof 2 Tisch 49 Tisch 76 Nummer 3 Nummer 2
73 Frank Dennis = Hof 1 = Hof 2 Tisch 33 Tisch 88 Nummer 4 Nummer 5
74 Frank Finn = Hof 1 = Hof 2 Tisch 33 Tisch 87 Nummer 3 Nummer 4
75 Frank Lena = Hof 1 = Hof 2 Tisch 24 Tisch 87 Nummer 3 Nummer 2
76 Frank Marie = Hof 1 = Hof 2 Tisch 33 Tisch 87 Nummer 2 Nummer 3
77 Frank Nadine = Hof 1 = Hof 2 Tisch 24 Tisch 88 Nummer 5 Nummer 4
78 Franke Amira = Hof 2 Tisch 76 Tisch 69 Nummer 2 Nummer 3
79 Franke Julia = Hof 2 Tisch 76 Tisch 78 Nummer 4 Nummer 5
80 Franke Marco = Hof 2 Tisch 77 Tisch 69 Nummer 2 Nummer 4
81 Franke Michael = Hof 2 Tisch 76 Tisch 78 Nummer 3 Nummer 4
82 Franke Olga = Hof 2 Tisch 77 Tisch 69 Nummer 5 Nummer 2
83 Freifrau von Waldeck Antonia = Hof 1 Tisch 6 Tisch 6 Nummer 3 Nummer 4
84 Freiherr von Waldeck Konstantin Dr. = Hof 1 Tisch 6 Tisch 6 Nummer 4 Nummer 3
85 Grothe Alexander Dr. h.c. = Hof 1 Tisch 5 Tisch 5 Nummer 3 Nummer 2
86 Grothe Beate = Hof 1 Tisch 5 Tisch 5 Nummer 2 Nummer 3
87 Haas Jennifer Dr. = Hof 1 Tisch 34 Tisch 31 Nummer 4 Nummer 3
88 Haas Patrick = Hof 2 = Hof 1 Tisch 48 Tisch 45 Nummer 4 Nummer 2
89 Hansen Giovanna = Hof 1 Tisch 29 Tisch 8 Nummer 4 Nummer 2
90 Hansen Markus = Hof 1 Tisch 29 Tisch 8 Nummer 3 Nummer 3
91 Hansen Nicole Dr. = Hof 2 Dr. = Hof 1 Tisch 47 Tisch 38 Nummer 3 Nummer 2
92 Hansen Olga = Hof 1 Tisch 29 Tisch 8 Nummer 2 Nummer 4
93 Hansen Thomas = Hof 1 Tisch 16 Tisch 16 Nummer 2 Nummer 2
94 Hartmann Deniz = Hof 2 Tisch 88 Tisch 78 Nummer 4 Nummer 2
95 Hartmann Marija = Hof 2 Tisch 87 Tisch 84 Nummer 2 Nummer 2
96 Hartmann Nadine = Hof 2 Tisch 87 Tisch 78 Nummer 4 Nummer 3
97 Hartmann Olga = Hof 2 Tisch 88 Tisch 84 Nummer 3 Nummer 4
98 Hartmann Thomas = Hof 2 Tisch 87 Tisch 84 Nummer 3 Nummer 3
99 Hoffmann Emre = Hof 1 = Hof 2 Tisch 40 Tisch 64 Nummer 4 Nummer 4
100 Hoffmann Patrick Prof. Dr. = Hof 2 Tisch 60 Tisch 65 Nummer 5 Nummer 4
101 Hoffmann Thomas Dr. = Hof 2 Tisch 46 Tisch 51 Nummer 3 Nummer 3
102 Horn Kathrin = Hof 2 Tisch 72 Tisch 79 Nummer 5 Nummer 2
103 Horn Layla = Hof 2 Tisch 72 Tisch 79 Nummer 2 Nummer 4
104 Horn Leon = Hof 2 Tisch 72 Tisch 79 Nummer 4 Nummer 5
105 Horn Michael = Hof 2 Tisch 72 Tisch 79 Nummer 3 Nummer 3
106 Kaya Christina = Hof 2 Tisch 56 Tisch 77 Nummer 3 Nummer 3
107 Kaya Luca = Hof 2 Tisch 56 Tisch 77 Nummer 2 Nummer 2
108 Kaya Nicole = Hof 2 Tisch 56 Tisch 77 Nummer 4 Nummer 4
109 Kaya Patrick Dr. = Hof 1 Tisch 3 Tisch 3 Nummer 3 Nummer 3
110 Kaya Timo Prof. Dr. = Hof 1 Tisch 22 Tisch 28 Nummer 5 Nummer 2
111 Kessler Ferdinand Dr. = Hof 1 Tisch 5 Tisch 5 Nummer 4 Nummer 4
112 Kessler Viktoria = Hof 1 Tisch 5 Tisch 5 Nummer 5 Nummer 5
113 Klein Emre = Hof 1 Tisch 4 Tisch 3 Nummer 2 Nummer 2
114 Klein Lina = Hof 2 = Hof 1 Tisch 78 Tisch 18 Nummer 4 Nummer 4
115 Klein Markus = Hof 2 Tisch 54 Tisch 57 Nummer 5 Nummer 5
116 Klein Milan = Hof 2 = Hof 1 Tisch 78 Tisch 18 Nummer 2 Nummer 3
117 Klein Olga Dr. = Hof 1 Dr. = Hof 2 Tisch 36 Tisch 88 Nummer 2 Nummer 2
118 Klein Stefanie = Hof 2 = Hof 1 Tisch 78 Tisch 18 Nummer 3 Nummer 2
119 Koch Emil = Hof 1 = Hof 2 Tisch 42 Tisch 48 Nummer 5 Nummer 3
120 Koch Jan = Hof 1 = Hof 2 Tisch 42 Tisch 49 Nummer 3 Nummer 3
121 Koch Kathrin Dr. = Hof 2 Tisch 68 Tisch 52 Nummer 4 Nummer 4
122 Koch Marie = Hof 1 = Hof 2 Tisch 41 Tisch 49 Nummer 2 Nummer 4
123 Koch Michael = Hof 1 = Hof 2 Tisch 42 Tisch 48 Nummer 2 Nummer 2
124 Koch Olga = Hof 1 = Hof 2 Tisch 41 Tisch 48 Nummer 3 Nummer 4
125 Koch Sarah = Hof 1 = Hof 2 Tisch 42 Tisch 49 Nummer 4 Nummer 2
126 Kovac Anja = Hof 1 Tisch 18 Tisch 36 Nummer 3 Nummer 3
127 Kovac Henry = Hof 1 Tisch 18 Tisch 36 Nummer 2 Nummer 4
128 Kovac Lena = Hof 1 Tisch 18 Tisch 28 Nummer 5 Nummer 4
129 Kovac Luca = Hof 2 Tisch 71 Tisch 62 Nummer 4 Nummer 2
130 Kovac Marco = Hof 1 Tisch 18 Tisch 36 Nummer 4 Nummer 2
131 Kovac Marija = Hof 1 Tisch 27 Tisch 36 Nummer 2 Nummer 5
132 Kovac Matthias = Hof 2 Tisch 49 Tisch 76 Nummer 2 Nummer 4
133 Kovac Tobias = Hof 1 Tisch 27 Tisch 28 Nummer 4 Nummer 5
134 Kraus Markus = Hof 1 Tisch 8 Tisch 11 Nummer 2 Nummer 4
135 Kraus Patrick Dr. = Hof 2 Tisch 70 Tisch 67 Nummer 3 Nummer 3
136 Krause Andreas = Hof 1 = Hof 2 Tisch 13 Tisch 63 Nummer 2 Nummer 2
137 Krause Arda = Hof 1 = Hof 2 Tisch 13 Tisch 63 Nummer 5 Nummer 4
138 Krause Christina Dr. = Hof 1 Tisch 3 Tisch 3 Nummer 2 Nummer 4
139 Krause Daniel = Hof 2 Tisch 54 Tisch 57 Nummer 3 Nummer 3
140 Krause Dragana Dr. = Hof 2 Tisch 71 Tisch 62 Nummer 3 Nummer 3
141 Krause Emma = Hof 1 = Hof 2 Tisch 13 Tisch 63 Nummer 3 Nummer 3
142 Krause Julia = Hof 1 = Hof 2 Tisch 13 Tisch 63 Nummer 4 Nummer 5
143 Krause Matthias = Hof 2 Tisch 70 Tisch 58 Nummer 5 Nummer 3
144 Krause Thomas = Hof 2 = Hof 1 Tisch 47 Tisch 38 Nummer 2 Nummer 3
145 Kuhn Julia Dr. = Hof 2 Tisch 69 Tisch 52 Nummer 4 Nummer 5
146 Lange Dragana = Hof 1 Tisch 23 Tisch 43 Nummer 4 Nummer 4
147 Lange Jan = Hof 1 Tisch 23 Tisch 44 Nummer 3 Nummer 2
148 Lange Michael = Hof 1 Tisch 31 Tisch 43 Nummer 3 Nummer 5
149 Lange Sergej = Hof 1 = Hof 2 Tisch 39 Tisch 64 Nummer 4 Nummer 5
150 Lange Sofia = Hof 1 Tisch 31 Tisch 44 Nummer 5 Nummer 4
151 Lange Svenja = Hof 1 Tisch 23 Tisch 44 Nummer 2 Nummer 3
152 Lehmann Giovanna = Hof 1 Tisch 21 Tisch 13 Nummer 5 Nummer 3
153 Lehmann Layla = Hof 1 Tisch 21 Tisch 2 Nummer 3 Nummer 2
154 Lehmann Markus = Hof 1 Tisch 10 Tisch 2 Nummer 3 Nummer 5
155 Lehmann Milan = Hof 1 Tisch 10 Tisch 13 Nummer 2 Nummer 4
156 Lehmann Nicole = Hof 1 Tisch 21 Tisch 2 Nummer 4 Nummer 4
157 Lehmann Patrick = Hof 2 = Hof 1 Tisch 81 Tisch 26 Nummer 3 Nummer 4
158 Lehmann Thomas = Hof 1 Tisch 21 Tisch 2 Nummer 2 Nummer 3
159 Ludwig Aylin Dr. = Hof 2 Tisch 70 Tisch 67 Nummer 4 Nummer 4
160 Ludwig Elias = Hof 2 = Hof 1 Tisch 64 Tisch 9 Nummer 5 Nummer 5
161 Ludwig Elif = Hof 2 = Hof 1 Tisch 64 Tisch 9 Nummer 2 Nummer 4
162 Ludwig Emre = Hof 2 = Hof 1 Tisch 64 Tisch 9 Nummer 3 Nummer 3
163 Ludwig Emre Prof. Dr. = Hof 2 Tisch 54 Tisch 57 Nummer 4 Nummer 2
164 Ludwig Giovanna = Hof 2 = Hof 1 Tisch 64 Tisch 9 Nummer 4 Nummer 2
165 Maier Arda = Hof 2 Tisch 66 Tisch 61 Nummer 4 Nummer 5
166 Maier Christian = Hof 2 Tisch 66 Tisch 61 Nummer 2 Nummer 3
167 Maier Olga = Hof 2 Tisch 66 Tisch 61 Nummer 5 Nummer 4
168 Maier Sarah = Hof 2 Tisch 66 Tisch 61 Nummer 3 Nummer 2
169 Neumann Jennifer = Hof 2 Tisch 73 Tisch 73 Nummer 2 Nummer 2
170 Neumann Lina = Hof 2 Tisch 73 Tisch 73 Nummer 4 Nummer 4
171 Neumann Matteo = Hof 2 Tisch 73 Tisch 73 Nummer 3 Nummer 5
172 Neumann Thomas = Hof 2 Tisch 73 Tisch 73 Nummer 5 Nummer 3
173 Nguyen Anja = Hof 2 = Hof 1 Tisch 62 Tisch 15 Nummer 3 Nummer 2
174 Nguyen Daniel = Hof 2 = Hof 1 Tisch 62 Tisch 15 Nummer 4 Nummer 3
175 Nguyen Julia = Hof 1 Tisch 17 Tisch 16 Nummer 2 Nummer 4
176 Nguyen Sofia = Hof 2 = Hof 1 Tisch 62 Tisch 15 Nummer 2 Nummer 4
177 Nowak Aylin = Hof 1 Tisch 38 Tisch 37 Nummer 3 Nummer 2
178 Nowak Felix = Hof 1 Tisch 38 Tisch 29 Nummer 2 Nummer 2
179 Nowak Kathrin = Hof 1 Tisch 38 Tisch 29 Nummer 4 Nummer 5
180 Nowak Lina = Hof 1 Tisch 45 Tisch 37 Nummer 2 Nummer 4
181 Nowak Markus = Hof 1 Tisch 45 Tisch 37 Nummer 3 Nummer 3
182 Nowak Noah = Hof 1 Tisch 45 Tisch 37 Nummer 4 Nummer 5
183 Ott Daniel = Hof 2 Tisch 88 Tisch 80 Nummer 5 Nummer 5
184 Ott Hannah = Hof 2 Tisch 82 Tisch 72 Nummer 4 Nummer 3
185 Ott Luca = Hof 2 Tisch 61 Tisch 71 Nummer 2 Nummer 2
186 Ott Matthias = Hof 2 Tisch 82 Tisch 72 Nummer 2 Nummer 2
187 Ott Melanie = Hof 2 Tisch 82 Tisch 80 Nummer 3 Nummer 4
188 Ott Olga = Hof 2 Tisch 88 Tisch 72 Nummer 2 Nummer 4
189 Ott Sergej Prof. Dr. = Hof 2 Prof. Dr. = Hof 1 Tisch 47 Tisch 45 Nummer 4 Nummer 3
190 Ott Yusuf Prof. Dr. = Hof 2 Prof. Dr. = Hof 1 Tisch 81 Tisch 26 Nummer 2 Nummer 2
191 Peters Christian = Hof 1 Tisch 8 Tisch 10 Nummer 5 Nummer 5
192 Peters Nicole = Hof 2 = Hof 1 Tisch 48 Tisch 45 Nummer 3 Nummer 5
193 Petrov Giovanna = Hof 1 Tisch 8 Tisch 10 Nummer 4 Nummer 2
194 Petrov Kathrin = Hof 1 Tisch 39 Tisch 38 Nummer 3 Nummer 4
195 Petrov Kathrin Prof. Dr. = Hof 1 Tisch 9 Tisch 11 Nummer 4 Nummer 2
196 Petrov Matthias = Hof 1 Tisch 35 Tisch 39 Nummer 2 Nummer 3
197 Petrov Milan = Hof 1 Tisch 39 Tisch 38 Nummer 2 Nummer 5
198 Petrov Sergej = Hof 2 Tisch 53 Tisch 59 Nummer 5 Nummer 3
199 Pohl Dragana = Hof 2 Tisch 85 Tisch 75 Nummer 2 Nummer 2
200 Pohl Emre = Hof 2 Tisch 85 Tisch 75 Nummer 5 Nummer 3
201 Pohl Mia = Hof 2 Tisch 85 Tisch 75 Nummer 4 Nummer 4
202 Pohl Theo = Hof 2 Tisch 85 Tisch 75 Nummer 3 Nummer 5
203 Polat Kathrin = Hof 2 Tisch 53 Tisch 59 Nummer 4 Nummer 4
204 Polat Katrin = Hof 2 Tisch 84 Tisch 81 Nummer 3 Nummer 4
205 Polat Marija = Hof 2 Tisch 60 Tisch 65 Nummer 2 Nummer 5
206 Polat Markus = Hof 2 Tisch 77 Tisch 81 Nummer 3 Nummer 3
207 Polat Sarah = Hof 2 Tisch 77 Tisch 81 Nummer 4 Nummer 2
208 Polat Stefan = Hof 2 Tisch 84 Tisch 80 Nummer 4 Nummer 3
209 Polat Stefanie = Hof 2 Tisch 84 Tisch 80 Nummer 2 Nummer 2
210 Popescu Matthias = Hof 1 Tisch 12 Tisch 12 Nummer 3 Nummer 2
211 Richter Anja = Hof 1 = Hof 2 Tisch 30 Tisch 50 Nummer 4 Nummer 2
212 Richter Anja Prof. Dr. = Hof 2 Prof. Dr. = Hof 1 Tisch 80 Tisch 22 Nummer 2 Nummer 2
213 Richter Anton = Hof 1 = Hof 2 Tisch 30 Tisch 50 Nummer 5 Nummer 5
214 Richter Greta = Hof 1 = Hof 2 Tisch 30 Tisch 50 Nummer 3 Nummer 4
215 Richter Julia Prof. Dr. = Hof 1 Tisch 34 Tisch 31 Nummer 3 Nummer 2
216 Richter Marco = Hof 2 Tisch 60 Tisch 65 Nummer 4 Nummer 3
217 Richter Matthias = Hof 1 = Hof 2 Tisch 30 Tisch 50 Nummer 2 Nummer 3
218 Richter Stefan = Hof 2 Tisch 71 Tisch 71 Nummer 2 Nummer 4
219 Rossi Emilia = Hof 1 Tisch 28 Tisch 40 Nummer 4 Nummer 4
220 Rossi Luca = Hof 1 Tisch 28 Tisch 40 Nummer 2 Nummer 3
221 Rossi Melanie = Hof 1 Tisch 28 Tisch 40 Nummer 3 Nummer 2
222 Roth Christian = Hof 2 = Hof 1 Tisch 79 Tisch 23 Nummer 4 Nummer 3
223 Roth Julia Prof. Dr. = Hof 1 Tisch 17 Tisch 17 Nummer 5 Nummer 4
224 Roth Olga = Hof 1 = Hof 2 Tisch 35 Tisch 82 Nummer 3 Nummer 2
225 Roth Sarah = Hof 2 = Hof 1 Tisch 79 Tisch 23 Nummer 3 Nummer 2
226 Roth Sofia = Hof 2 = Hof 1 Tisch 79 Tisch 23 Nummer 2 Nummer 4
227 Sahin Kathrin = Hof 1 = Hof 2 Tisch 11 Tisch 60 Nummer 5 Nummer 4
228 Sahin Markus = Hof 1 = Hof 2 Tisch 11 Tisch 60 Nummer 2 Nummer 3
229 Sahin Nicole = Hof 1 = Hof 2 Tisch 11 Tisch 60 Nummer 3 Nummer 2
230 Sahin Patrick = Hof 1 = Hof 2 Tisch 11 Tisch 60 Nummer 4 Nummer 5
231 Sahin Thomas = Hof 2 = Hof 1 Tisch 80 Tisch 22 Nummer 3 Nummer 4
232 Schmidt Giovanna = Hof 2 Tisch 57 Tisch 85 Nummer 3 Nummer 4
233 Schmidt Marie = Hof 2 Tisch 57 Tisch 85 Nummer 4 Nummer 3
234 Schmidt Matthias = Hof 2 Tisch 57 Tisch 85 Nummer 2 Nummer 2
235 Schmidt Nicole = Hof 1 Tisch 17 Tisch 16 Nummer 4 Nummer 3
236 Schmitt Dennis Prof. Dr. = Hof 2 Tisch 71 Tisch 62 Nummer 5 Nummer 4
237 Schmitt Markus = Hof 1 Tisch 15 Tisch 10 Nummer 4 Nummer 4
238 Schmitt Markus = Hof 1 = Hof 2 Tisch 9 Tisch 47 Nummer 3 Nummer 3
239 Schmitt Sarah = Hof 1 = Hof 2 Tisch 15 Tisch 47 Nummer 2 Nummer 2
240 Schmitt Sofia = Hof 1 = Hof 2 Tisch 15 Tisch 47 Nummer 3 Nummer 4
241 Schmitt Stefan Prof. Dr. = Hof 2 Tisch 69 Tisch 52 Nummer 3 Nummer 2
242 Schwarz Giovanna = Hof 2 Tisch 61 Tisch 58 Nummer 5 Nummer 4
243 Seidel Anja Dr. = Hof 2 Tisch 46 Tisch 51 Nummer 2 Nummer 5
244 Seidel Markus Dr. = Hof 1 Tisch 9 Tisch 11 Nummer 2 Nummer 3
245 Seidel Yusuf Prof. Dr. = Hof 1 Tisch 3 Tisch 4 Nummer 4 Nummer 3
246 Seifert Elif = Hof 2 = Hof 1 Tisch 50 Tisch 20 Nummer 3 Nummer 3
247 Seifert Leni = Hof 2 = Hof 1 Tisch 50 Tisch 19 Nummer 2 Nummer 4
248 Seifert Marco Prof. Dr. = Hof 2 Tisch 70 Tisch 58 Nummer 2 Nummer 2
249 Seifert Nicole = Hof 2 = Hof 1 Tisch 51 Tisch 19 Nummer 3 Nummer 2
250 Seifert Stefanie Dr. = Hof 1 Tisch 17 Tisch 16 Nummer 3 Nummer 5
251 Seifert Timo = Hof 2 = Hof 1 Tisch 51 Tisch 20 Nummer 5 Nummer 2
252 Seifert Yusuf = Hof 2 = Hof 1 Tisch 50 Tisch 19 Nummer 4 Nummer 3
253 Simon Andreas = Hof 2 Tisch 75 Tisch 66 Nummer 2 Nummer 5
254 Simon Emma = Hof 2 Tisch 75 Tisch 66 Nummer 3 Nummer 4
255 Simon Lena = Hof 2 Tisch 75 Tisch 66 Nummer 5 Nummer 2
256 Simon Markus = Hof 2 Tisch 75 Tisch 66 Nummer 4 Nummer 3
257 Simon Svenja = Hof 1 Tisch 10 Tisch 13 Nummer 5 Nummer 5
258 Stein Ben = Hof 2 Tisch 83 Tisch 86 Nummer 2 Nummer 4
259 Stein Emilia = Hof 2 Tisch 83 Tisch 86 Nummer 4 Nummer 3
260 Stein Giovanna = Hof 2 Tisch 83 Tisch 86 Nummer 3 Nummer 5
261 Stein Markus Prof. Dr. = Hof 1 Tisch 12 Tisch 12 Nummer 2 Nummer 5
262 Stein Nadine Dr. = Hof 1 Tisch 8 Tisch 10 Nummer 3 Nummer 3
263 Stein Thomas = Hof 2 Tisch 83 Tisch 86 Nummer 5 Nummer 2
264 Steinbach Elisabeth = Hof 1 Tisch 6 Tisch 6 Nummer 5 Nummer 2
265 Steinbach Georg = Hof 1 Tisch 6 Tisch 6 Nummer 2 Nummer 5
266 Thiel Christina = Hof 1 = Hof 2 Tisch 2 Tisch 46 Nummer 3 Nummer 3
267 Thiel Jan Dr. = Hof 2 Dr. = Hof 1 Tisch 80 Tisch 22 Nummer 4 Nummer 3
268 Thiel Julia = Hof 1 = Hof 2 Tisch 2 Tisch 46 Nummer 2 Nummer 4
269 Thiel Yusuf = Hof 1 = Hof 2 Tisch 2 Tisch 46 Nummer 4 Nummer 2
270 Tran Marija = Hof 2 Tisch 68 Tisch 52 Nummer 2 Nummer 3
271 Tran Olga = Hof 2 Tisch 46 Tisch 51 Nummer 4 Nummer 4
272 Tran Thomas Prof. Dr. = Hof 2 Tisch 53 Tisch 59 Nummer 2 Nummer 2
273 Wagner Henry = Hof 2 Tisch 63 Tisch 68 Nummer 3 Nummer 5
274 Wagner Marco = Hof 2 Tisch 63 Tisch 68 Nummer 5 Nummer 3
275 Wagner Nicole = Hof 2 Tisch 63 Tisch 68 Nummer 2 Nummer 2
276 Wagner Sarah = Hof 2 Tisch 63 Tisch 68 Nummer 4 Nummer 4
277 Weber Andreas = Hof 1 Tisch 34 Tisch 39 Nummer 2 Nummer 4
278 Weber Julia = Hof 1 Tisch 4 Tisch 3 Nummer 5 Nummer 5
279 Weber Katrin = Hof 2 Tisch 69 Tisch 53 Nummer 2 Nummer 4
280 Weber Yusuf = Hof 2 Tisch 61 Tisch 67 Nummer 4 Nummer 2
281 Werner Andreas = Hof 2 Tisch 59 Tisch 55 Nummer 2 Nummer 3
282 Werner Dennis Prof. Dr. = Hof 2 Tisch 46 Tisch 51 Nummer 5 Nummer 2
283 Werner Katrin = Hof 1 = Hof 2 Tisch 39 Tisch 64 Nummer 5 Nummer 2
284 Werner Luca = Hof 2 Tisch 68 Tisch 53 Nummer 3 Nummer 5
285 Werner Marco = Hof 2 Tisch 59 Tisch 55 Nummer 4 Nummer 5
286 Werner Nadine = Hof 2 Tisch 59 Tisch 55 Nummer 3 Nummer 4
287 Werner Sandra = Hof 2 Tisch 59 Tisch 55 Nummer 5 Nummer 2
288 Winkler Lena = Hof 1 Tisch 31 Tisch 29 Nummer 4 Nummer 3
289 Winkler Marco = Hof 1 Tisch 4 Tisch 4 Nummer 4 Nummer 2
290 Winkler Patrick = Hof 1 Tisch 31 Tisch 29 Nummer 2 Nummer 4
291 Winkler Thomas = Hof 1 Tisch 16 Tisch 17 Nummer 3 Nummer 2
292 Wolf Ben = Hof 2 Tisch 74 Tisch 83 Nummer 4 Nummer 3
293 Wolf Emma = Hof 2 Tisch 74 Tisch 83 Nummer 2 Nummer 2
294 Wolf Julia = Hof 2 Tisch 74 Tisch 83 Nummer 3 Nummer 4
295 Wolf Thomas = Hof 2 Tisch 74 Tisch 83 Nummer 5 Nummer 5
296 Zimmermann Jan = Hof 2 Tisch 67 Tisch 70 Nummer 5 Nummer 3
297 Zimmermann Markus = Hof 2 Tisch 67 Tisch 70 Nummer 4 Nummer 5
298 Zimmermann Mia = Hof 2 Tisch 67 Tisch 70 Nummer 3 Nummer 4
299 Zimmermann Patrick = Hof 2 Tisch 61 Tisch 71 Nummer 3 Nummer 3
300 Zimmermann Svenja = Hof 2 Tisch 67 Tisch 70 Nummer 2 Nummer 2
File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 122 KiB

+291 -291
View File
@@ -1,476 +1,476 @@
[1] [1]
Sofia Dietrich = Hof 1, Tisch 1, Nummer 1
Jennifer Dietrich = Hof 1, Tisch 1, Nummer 2
Marco Dietrich = Hof 1, Tisch 1, Nummer 3
[2] [2]
Julia Thiel = Hof 1, Tisch 2, Nummer 1 Layla Lehmann = Hof 1, Tisch 2, Nummer 1
Christina Thiel = Hof 1, Tisch 2, Nummer 2 Thomas Lehmann = Hof 1, Tisch 2, Nummer 2
Yusuf Thiel = Hof 1, Tisch 2, Nummer 3 Nicole Lehmann = Hof 1, Tisch 2, Nummer 3
Markus Lehmann = Hof 1, Tisch 2, Nummer 4
[3] [3]
Dr. Christina Krause = Hof 1, Tisch 3, Nummer 1 Emre Klein = Hof 1, Tisch 3, Nummer 1
Dr. Patrick Kaya = Hof 1, Tisch 3, Nummer 2 Dr. Patrick Kaya = Hof 1, Tisch 3, Nummer 2
Prof. Dr. Yusuf Seidel = Hof 1, Tisch 3, Nummer 3 Dr. Christina Krause = Hof 1, Tisch 3, Nummer 3
Yusuf Bauer = Hof 1, Tisch 3, Nummer 4 Julia Weber = Hof 1, Tisch 3, Nummer 4
[4] [4]
Emre Klein = Hof 1, Tisch 4, Nummer 1 Marco Winkler = Hof 1, Tisch 4, Nummer 1
Dr. Jan Bianchi = Hof 1, Tisch 4, Nummer 2 Prof. Dr. Yusuf Seidel = Hof 1, Tisch 4, Nummer 2
Marco Winkler = Hof 1, Tisch 4, Nummer 3 Yusuf Bauer = Hof 1, Tisch 4, Nummer 3
Julia Weber = Hof 1, Tisch 4, Nummer 4 Dr. Jan Bianchi = Hof 1, Tisch 4, Nummer 4
[5] [5]
Beate Grothe = Hof 1, Tisch 5, Nummer 1 Dr. h.c. Alexander Grothe = Hof 1, Tisch 5, Nummer 1
Dr. h.c. Alexander Grothe = Hof 1, Tisch 5, Nummer 2 Beate Grothe = Hof 1, Tisch 5, Nummer 2
Dr. Ferdinand Kessler = Hof 1, Tisch 5, Nummer 3 Dr. Ferdinand Kessler = Hof 1, Tisch 5, Nummer 3
Viktoria Kessler = Hof 1, Tisch 5, Nummer 4 Viktoria Kessler = Hof 1, Tisch 5, Nummer 4
[6] [6]
Georg Steinbach = Hof 1, Tisch 6, Nummer 1 Elisabeth Steinbach = Hof 1, Tisch 6, Nummer 1
Antonia Freifrau von Waldeck = Hof 1, Tisch 6, Nummer 2 Dr. Konstantin Freiherr von Waldeck = Hof 1, Tisch 6, Nummer 2
Dr. Konstantin Freiherr von Waldeck = Hof 1, Tisch 6, Nummer 3 Antonia Freifrau von Waldeck = Hof 1, Tisch 6, Nummer 3
Elisabeth Steinbach = Hof 1, Tisch 6, Nummer 4 Georg Steinbach = Hof 1, Tisch 6, Nummer 4
[7] [7]
Heinrich Dallmann = Hof 1, Tisch 7, Nummer 1 Heinrich Dallmann = Hof 1, Tisch 7, Nummer 1
Maximilian Dallmann = Hof 1, Tisch 7, Nummer 2 Margarete Dallmann = Hof 1, Tisch 7, Nummer 2
Margarete Dallmann = Hof 1, Tisch 7, Nummer 3 Maximilian Dallmann = Hof 1, Tisch 7, Nummer 3
Charlotte Dallmann = Hof 1, Tisch 7, Nummer 4 Charlotte Dallmann = Hof 1, Tisch 7, Nummer 4
[8] [8]
Markus Kraus = Hof 1, Tisch 8, Nummer 1 Giovanna Hansen = Hof 1, Tisch 8, Nummer 1
Dr. Nadine Stein = Hof 1, Tisch 8, Nummer 2 Markus Hansen = Hof 1, Tisch 8, Nummer 2
Giovanna Petrov = Hof 1, Tisch 8, Nummer 3 Olga Hansen = Hof 1, Tisch 8, Nummer 3
Christian Peters = Hof 1, Tisch 8, Nummer 4
[9] [9]
Dr. Markus Seidel = Hof 1, Tisch 9, Nummer 1 Giovanna Ludwig = Hof 1, Tisch 9, Nummer 1
Markus Schmitt = Hof 1, Tisch 9, Nummer 2 Emre Ludwig = Hof 1, Tisch 9, Nummer 2
Prof. Dr. Kathrin Petrov = Hof 1, Tisch 9, Nummer 3 Elif Ludwig = Hof 1, Tisch 9, Nummer 3
Elias Ludwig = Hof 1, Tisch 9, Nummer 4
[10] [10]
Milan Lehmann = Hof 1, Tisch 10, Nummer 1 Giovanna Petrov = Hof 1, Tisch 10, Nummer 1
Markus Lehmann = Hof 1, Tisch 10, Nummer 2 Dr. Nadine Stein = Hof 1, Tisch 10, Nummer 2
Prof. Dr. Yusuf Albrecht = Hof 1, Tisch 10, Nummer 3 Markus Schmitt = Hof 1, Tisch 10, Nummer 3
Svenja Simon = Hof 1, Tisch 10, Nummer 4 Christian Peters = Hof 1, Tisch 10, Nummer 4
[11] [11]
Markus Sahin = Hof 1, Tisch 11, Nummer 1 Prof. Dr. Kathrin Petrov = Hof 1, Tisch 11, Nummer 1
Nicole Sahin = Hof 1, Tisch 11, Nummer 2 Dr. Markus Seidel = Hof 1, Tisch 11, Nummer 2
Patrick Sahin = Hof 1, Tisch 11, Nummer 3 Markus Kraus = Hof 1, Tisch 11, Nummer 3
Kathrin Sahin = Hof 1, Tisch 11, Nummer 4
[12] [12]
Prof. Dr. Markus Stein = Hof 1, Tisch 12, Nummer 1 Matthias Popescu = Hof 1, Tisch 12, Nummer 1
Matthias Popescu = Hof 1, Tisch 12, Nummer 2 Sarah Albrecht = Hof 1, Tisch 12, Nummer 2
Andreas Albrecht = Hof 1, Tisch 12, Nummer 3 Andreas Albrecht = Hof 1, Tisch 12, Nummer 3
Sarah Albrecht = Hof 1, Tisch 12, Nummer 4 Prof. Dr. Markus Stein = Hof 1, Tisch 12, Nummer 4
[13] [13]
Andreas Krause = Hof 1, Tisch 13, Nummer 1 Prof. Dr. Yusuf Albrecht = Hof 1, Tisch 13, Nummer 1
Emma Krause = Hof 1, Tisch 13, Nummer 2 Giovanna Lehmann = Hof 1, Tisch 13, Nummer 2
Julia Krause = Hof 1, Tisch 13, Nummer 3 Milan Lehmann = Hof 1, Tisch 13, Nummer 3
Arda Krause = Hof 1, Tisch 13, Nummer 4 Svenja Simon = Hof 1, Tisch 13, Nummer 4
[14] [14]
Timo Barth = Hof 1, Tisch 14, Nummer 1 Nicole Becker = Hof 1, Tisch 14, Nummer 1
Nadine Barth = Hof 1, Tisch 14, Nummer 2 Jan Becker = Hof 1, Tisch 14, Nummer 2
Patrick Barth = Hof 1, Tisch 14, Nummer 3 Sandra Becker = Hof 1, Tisch 14, Nummer 3
Lina Barth = Hof 1, Tisch 14, Nummer 4
[15] [15]
Sarah Schmitt = Hof 1, Tisch 15, Nummer 1 Anja Nguyen = Hof 1, Tisch 15, Nummer 1
Sofia Schmitt = Hof 1, Tisch 15, Nummer 2 Daniel Nguyen = Hof 1, Tisch 15, Nummer 2
Markus Schmitt = Hof 1, Tisch 15, Nummer 3 Sofia Nguyen = Hof 1, Tisch 15, Nummer 3
[16] [16]
Thomas Hansen = Hof 1, Tisch 16, Nummer 1 Thomas Hansen = Hof 1, Tisch 16, Nummer 1
Thomas Winkler = Hof 1, Tisch 16, Nummer 2 Nicole Schmidt = Hof 1, Tisch 16, Nummer 2
Dr. Jan Esposito = Hof 1, Tisch 16, Nummer 3 Julia Nguyen = Hof 1, Tisch 16, Nummer 3
Dr. Stefanie Seifert = Hof 1, Tisch 16, Nummer 4
[17] [17]
Julia Nguyen = Hof 1, Tisch 17, Nummer 1 Thomas Winkler = Hof 1, Tisch 17, Nummer 1
Dr. Stefanie Seifert = Hof 1, Tisch 17, Nummer 2 Dr. Jan Esposito = Hof 1, Tisch 17, Nummer 2
Nicole Schmidt = Hof 1, Tisch 17, Nummer 3 Prof. Dr. Julia Roth = Hof 1, Tisch 17, Nummer 3
Prof. Dr. Julia Roth = Hof 1, Tisch 17, Nummer 4
[18] [18]
Henry Kovac = Hof 1, Tisch 18, Nummer 1 Stefanie Klein = Hof 1, Tisch 18, Nummer 1
Anja Kovac = Hof 1, Tisch 18, Nummer 2 Milan Klein = Hof 1, Tisch 18, Nummer 2
Marco Kovac = Hof 1, Tisch 18, Nummer 3 Lina Klein = Hof 1, Tisch 18, Nummer 3
Lena Kovac = Hof 1, Tisch 18, Nummer 4
[19] [19]
Nadine Braun = Hof 1, Tisch 19, Nummer 1 Nicole Seifert = Hof 1, Tisch 19, Nummer 1
Christian Braun = Hof 1, Tisch 19, Nummer 2 Yusuf Seifert = Hof 1, Tisch 19, Nummer 2
Dragana Braun = Hof 1, Tisch 19, Nummer 3 Leni Seifert = Hof 1, Tisch 19, Nummer 3
Julia Braun = Hof 1, Tisch 19, Nummer 4
[20] [20]
Milan Braun = Hof 1, Tisch 20, Nummer 1 Timo Seifert = Hof 1, Tisch 20, Nummer 1
Jan Braun = Hof 1, Tisch 20, Nummer 2 Elif Seifert = Hof 1, Tisch 20, Nummer 2
Julia Engel = Hof 1, Tisch 20, Nummer 3
Anton Engel = Hof 1, Tisch 20, Nummer 4
[21] [21]
Thomas Lehmann = Hof 1, Tisch 21, Nummer 1 Nicole Engel = Hof 1, Tisch 21, Nummer 1
Layla Lehmann = Hof 1, Tisch 21, Nummer 2 Anja Engel = Hof 1, Tisch 21, Nummer 2
Nicole Lehmann = Hof 1, Tisch 21, Nummer 3 Yusuf Engel = Hof 1, Tisch 21, Nummer 3
Giovanna Lehmann = Hof 1, Tisch 21, Nummer 4
[22] [22]
Dr. Sandra Demir = Hof 1, Tisch 22, Nummer 1 Prof. Dr. Anja Richter = Hof 1, Tisch 22, Nummer 1
Elif Celik = Hof 1, Tisch 22, Nummer 2 Dr. Jan Thiel = Hof 1, Tisch 22, Nummer 2
Patrick Celik = Hof 1, Tisch 22, Nummer 3 Thomas Sahin = Hof 1, Tisch 22, Nummer 3
Prof. Dr. Timo Kaya = Hof 1, Tisch 22, Nummer 4
[23] [23]
Svenja Lange = Hof 1, Tisch 23, Nummer 1 Sarah Roth = Hof 1, Tisch 23, Nummer 1
Jan Lange = Hof 1, Tisch 23, Nummer 2 Christian Roth = Hof 1, Tisch 23, Nummer 2
Dragana Lange = Hof 1, Tisch 23, Nummer 3 Sofia Roth = Hof 1, Tisch 23, Nummer 3
[24] [24]
Yusuf Engel = Hof 1, Tisch 24, Nummer 1 Andreas Berger = Hof 1, Tisch 24, Nummer 1
Lena Frank = Hof 1, Tisch 24, Nummer 2 Patrick Celik = Hof 1, Tisch 24, Nummer 2
Julia Engel = Hof 1, Tisch 24, Nummer 3 Elif Celik = Hof 1, Tisch 24, Nummer 3
Nadine Frank = Hof 1, Tisch 24, Nummer 4 Svenja Berger = Hof 1, Tisch 24, Nummer 4
[25] [25]
Nicole Engel = Hof 1, Tisch 25, Nummer 1 Nadine Aksoy = Hof 1, Tisch 25, Nummer 1
Anton Engel = Hof 1, Tisch 25, Nummer 2 Thomas Aksoy = Hof 1, Tisch 25, Nummer 2
Anja Engel = Hof 1, Tisch 25, Nummer 3 Marie Aksoy = Hof 1, Tisch 25, Nummer 3
[26] [26]
Anton Berger = Hof 1, Tisch 26, Nummer 1 Prof. Dr. Yusuf Ott = Hof 1, Tisch 26, Nummer 1
Jennifer Berger = Hof 1, Tisch 26, Nummer 2 Dr. Nadine Berger = Hof 1, Tisch 26, Nummer 2
Svenja Berger = Hof 1, Tisch 26, Nummer 3 Patrick Lehmann = Hof 1, Tisch 26, Nummer 3
Layla Berger = Hof 1, Tisch 26, Nummer 4
[27] [27]
Marija Kovac = Hof 1, Tisch 27, Nummer 1 Jennifer Dietrich = Hof 1, Tisch 27, Nummer 1
Andreas Berger = Hof 1, Tisch 27, Nummer 2 Marco Dietrich = Hof 1, Tisch 27, Nummer 2
Tobias Kovac = Hof 1, Tisch 27, Nummer 3 Sofia Dietrich = Hof 1, Tisch 27, Nummer 3
Stefan Berger = Hof 1, Tisch 27, Nummer 4
[28] [28]
Luca Rossi = Hof 1, Tisch 28, Nummer 1 Prof. Dr. Timo Kaya = Hof 1, Tisch 28, Nummer 1
Melanie Rossi = Hof 1, Tisch 28, Nummer 2 Dr. Sandra Demir = Hof 1, Tisch 28, Nummer 2
Emilia Rossi = Hof 1, Tisch 28, Nummer 3 Lena Kovac = Hof 1, Tisch 28, Nummer 3
Tobias Kovac = Hof 1, Tisch 28, Nummer 4
[29] [29]
Olga Hansen = Hof 1, Tisch 29, Nummer 1 Felix Nowak = Hof 1, Tisch 29, Nummer 1
Markus Hansen = Hof 1, Tisch 29, Nummer 2 Lena Winkler = Hof 1, Tisch 29, Nummer 2
Giovanna Hansen = Hof 1, Tisch 29, Nummer 3 Patrick Winkler = Hof 1, Tisch 29, Nummer 3
Kathrin Nowak = Hof 1, Tisch 29, Nummer 4
[30] [30]
Matthias Richter = Hof 1, Tisch 30, Nummer 1
Greta Richter = Hof 1, Tisch 30, Nummer 2
Anja Richter = Hof 1, Tisch 30, Nummer 3
Anton Richter = Hof 1, Tisch 30, Nummer 4
[31] [31]
Patrick Winkler = Hof 1, Tisch 31, Nummer 1 Prof. Dr. Julia Richter = Hof 1, Tisch 31, Nummer 1
Michael Lange = Hof 1, Tisch 31, Nummer 2 Dr. Jennifer Haas = Hof 1, Tisch 31, Nummer 2
Lena Winkler = Hof 1, Tisch 31, Nummer 3
Sofia Lange = Hof 1, Tisch 31, Nummer 4
[32] [32]
Jennifer Berger = Hof 1, Tisch 32, Nummer 1
Anton Berger = Hof 1, Tisch 32, Nummer 2
Layla Berger = Hof 1, Tisch 32, Nummer 3
Stefan Berger = Hof 1, Tisch 32, Nummer 4
[33] [33]
Marie Frank = Hof 1, Tisch 33, Nummer 1 Luca Aksoy = Hof 1, Tisch 33, Nummer 1
Finn Frank = Hof 1, Tisch 33, Nummer 2 Sofia Aksoy = Hof 1, Tisch 33, Nummer 2
Dennis Frank = Hof 1, Tisch 33, Nummer 3 Sergej Aksoy = Hof 1, Tisch 33, Nummer 3
[34] [34]
Andreas Weber = Hof 1, Tisch 34, Nummer 1
Prof. Dr. Julia Richter = Hof 1, Tisch 34, Nummer 2
Dr. Jennifer Haas = Hof 1, Tisch 34, Nummer 3
[35] [35]
Matthias Petrov = Hof 1, Tisch 35, Nummer 1 Leni Arnold = Hof 1, Tisch 35, Nummer 1
Olga Roth = Hof 1, Tisch 35, Nummer 2 Christian Arnold = Hof 1, Tisch 35, Nummer 2
Thomas Bianchi = Hof 1, Tisch 35, Nummer 3 Mila Arnold = Hof 1, Tisch 35, Nummer 3
Markus Barth = Hof 1, Tisch 35, Nummer 4
[36] [36]
Dr. Olga Klein = Hof 1, Tisch 36, Nummer 1 Marco Kovac = Hof 1, Tisch 36, Nummer 1
Dr. Jennifer Arnold = Hof 1, Tisch 36, Nummer 2 Anja Kovac = Hof 1, Tisch 36, Nummer 2
Prof. Dr. Emre Albrecht = Hof 1, Tisch 36, Nummer 3 Henry Kovac = Hof 1, Tisch 36, Nummer 3
Marija Kovac = Hof 1, Tisch 36, Nummer 4
[37] [37]
Sergej Aksoy = Hof 1, Tisch 37, Nummer 1 Aylin Nowak = Hof 1, Tisch 37, Nummer 1
Thomas Aksoy = Hof 1, Tisch 37, Nummer 2 Markus Nowak = Hof 1, Tisch 37, Nummer 2
Marie Aksoy = Hof 1, Tisch 37, Nummer 3 Lina Nowak = Hof 1, Tisch 37, Nummer 3
Sofia Aksoy = Hof 1, Tisch 37, Nummer 4 Noah Nowak = Hof 1, Tisch 37, Nummer 4
[38] [38]
Felix Nowak = Hof 1, Tisch 38, Nummer 1 Dr. Nicole Hansen = Hof 1, Tisch 38, Nummer 1
Aylin Nowak = Hof 1, Tisch 38, Nummer 2 Thomas Krause = Hof 1, Tisch 38, Nummer 2
Kathrin Nowak = Hof 1, Tisch 38, Nummer 3 Kathrin Petrov = Hof 1, Tisch 38, Nummer 3
Milan Petrov = Hof 1, Tisch 38, Nummer 4
[39] [39]
Milan Petrov = Hof 1, Tisch 39, Nummer 1 Markus Barth = Hof 1, Tisch 39, Nummer 1
Kathrin Petrov = Hof 1, Tisch 39, Nummer 2 Matthias Petrov = Hof 1, Tisch 39, Nummer 2
Sergej Lange = Hof 1, Tisch 39, Nummer 3 Andreas Weber = Hof 1, Tisch 39, Nummer 3
Katrin Werner = Hof 1, Tisch 39, Nummer 4
[40] [40]
Prof. Dr. Dragana Dietrich = Hof 1, Tisch 40, Nummer 1 Melanie Rossi = Hof 1, Tisch 40, Nummer 1
Patrick Busch = Hof 1, Tisch 40, Nummer 2 Luca Rossi = Hof 1, Tisch 40, Nummer 2
Emre Hoffmann = Hof 1, Tisch 40, Nummer 3 Emilia Rossi = Hof 1, Tisch 40, Nummer 3
Dr. Michael Aksoy = Hof 1, Tisch 40, Nummer 4
[41] [41]
Marie Koch = Hof 1, Tisch 41, Nummer 1 Julia Braun = Hof 1, Tisch 41, Nummer 1
Olga Koch = Hof 1, Tisch 41, Nummer 2 Milan Braun = Hof 1, Tisch 41, Nummer 2
Nadine Braun = Hof 1, Tisch 41, Nummer 3
[42] [42]
Michael Koch = Hof 1, Tisch 42, Nummer 1 Jan Braun = Hof 1, Tisch 42, Nummer 1
Jan Koch = Hof 1, Tisch 42, Nummer 2 Dragana Braun = Hof 1, Tisch 42, Nummer 2
Sarah Koch = Hof 1, Tisch 42, Nummer 3 Christian Braun = Hof 1, Tisch 42, Nummer 3
Emil Koch = Hof 1, Tisch 42, Nummer 4
[43] [43]
Mia Bianchi = Hof 1, Tisch 43, Nummer 1 Jennifer Arnold = Hof 1, Tisch 43, Nummer 1
Thomas Bianchi = Hof 1, Tisch 43, Nummer 2 Patrick Arnold = Hof 1, Tisch 43, Nummer 2
Sandra Bianchi = Hof 1, Tisch 43, Nummer 3 Dragana Lange = Hof 1, Tisch 43, Nummer 3
Michael Lange = Hof 1, Tisch 43, Nummer 4
[44] [44]
Nadine Aksoy = Hof 1, Tisch 44, Nummer 1 Jan Lange = Hof 1, Tisch 44, Nummer 1
Luca Aksoy = Hof 1, Tisch 44, Nummer 2 Svenja Lange = Hof 1, Tisch 44, Nummer 2
Sofia Lange = Hof 1, Tisch 44, Nummer 3
[45] [45]
Lina Nowak = Hof 1, Tisch 45, Nummer 1 Patrick Haas = Hof 1, Tisch 45, Nummer 1
Markus Nowak = Hof 1, Tisch 45, Nummer 2 Prof. Dr. Sergej Ott = Hof 1, Tisch 45, Nummer 2
Noah Nowak = Hof 1, Tisch 45, Nummer 3 Dragana Bauer = Hof 1, Tisch 45, Nummer 3
Nicole Peters = Hof 1, Tisch 45, Nummer 4
[46] [46]
Dr. Anja Seidel = Hof 2, Tisch 46, Nummer 1 Yusuf Thiel = Hof 2, Tisch 46, Nummer 1
Dr. Thomas Hoffmann = Hof 2, Tisch 46, Nummer 2 Christina Thiel = Hof 2, Tisch 46, Nummer 2
Olga Tran = Hof 2, Tisch 46, Nummer 3 Julia Thiel = Hof 2, Tisch 46, Nummer 3
Prof. Dr. Dennis Werner = Hof 2, Tisch 46, Nummer 4
[47] [47]
Thomas Krause = Hof 2, Tisch 47, Nummer 1 Sarah Schmitt = Hof 2, Tisch 47, Nummer 1
Dr. Nicole Hansen = Hof 2, Tisch 47, Nummer 2 Markus Schmitt = Hof 2, Tisch 47, Nummer 2
Prof. Dr. Sergej Ott = Hof 2, Tisch 47, Nummer 3 Sofia Schmitt = Hof 2, Tisch 47, Nummer 3
[48] [48]
Dragana Bauer = Hof 2, Tisch 48, Nummer 1 Michael Koch = Hof 2, Tisch 48, Nummer 1
Nicole Peters = Hof 2, Tisch 48, Nummer 2 Emil Koch = Hof 2, Tisch 48, Nummer 2
Patrick Haas = Hof 2, Tisch 48, Nummer 3 Olga Koch = Hof 2, Tisch 48, Nummer 3
[49] [49]
Matthias Kovac = Hof 2, Tisch 49, Nummer 1 Sarah Koch = Hof 2, Tisch 49, Nummer 1
Prof. Dr. Yusuf Esposito = Hof 2, Tisch 49, Nummer 2 Jan Koch = Hof 2, Tisch 49, Nummer 2
Marija Becker = Hof 2, Tisch 49, Nummer 3 Marie Koch = Hof 2, Tisch 49, Nummer 3
[50] [50]
Leni Seifert = Hof 2, Tisch 50, Nummer 1 Anja Richter = Hof 2, Tisch 50, Nummer 1
Elif Seifert = Hof 2, Tisch 50, Nummer 2 Matthias Richter = Hof 2, Tisch 50, Nummer 2
Yusuf Seifert = Hof 2, Tisch 50, Nummer 3 Greta Richter = Hof 2, Tisch 50, Nummer 3
Anton Richter = Hof 2, Tisch 50, Nummer 4
[51] [51]
Jennifer Arnold = Hof 2, Tisch 51, Nummer 1 Prof. Dr. Dennis Werner = Hof 2, Tisch 51, Nummer 1
Nicole Seifert = Hof 2, Tisch 51, Nummer 2 Dr. Thomas Hoffmann = Hof 2, Tisch 51, Nummer 2
Christian Arnold = Hof 2, Tisch 51, Nummer 3 Olga Tran = Hof 2, Tisch 51, Nummer 3
Timo Seifert = Hof 2, Tisch 51, Nummer 4 Dr. Anja Seidel = Hof 2, Tisch 51, Nummer 4
[52] [52]
Mila Arnold = Hof 2, Tisch 52, Nummer 1 Prof. Dr. Stefan Schmitt = Hof 2, Tisch 52, Nummer 1
Patrick Arnold = Hof 2, Tisch 52, Nummer 2 Marija Tran = Hof 2, Tisch 52, Nummer 2
Leni Arnold = Hof 2, Tisch 52, Nummer 3 Dr. Kathrin Koch = Hof 2, Tisch 52, Nummer 3
Dr. Julia Kuhn = Hof 2, Tisch 52, Nummer 4
[53] [53]
Prof. Dr. Thomas Tran = Hof 2, Tisch 53, Nummer 1 Prof. Dr. Dragana Dietrich = Hof 2, Tisch 53, Nummer 1
Marija Aksoy = Hof 2, Tisch 53, Nummer 2 Dr. Michael Aksoy = Hof 2, Tisch 53, Nummer 2
Kathrin Polat = Hof 2, Tisch 53, Nummer 3 Katrin Weber = Hof 2, Tisch 53, Nummer 3
Sergej Petrov = Hof 2, Tisch 53, Nummer 4 Luca Werner = Hof 2, Tisch 53, Nummer 4
[54] [54]
Nicole Aksoy = Hof 2, Tisch 54, Nummer 1 Sandra Bianchi = Hof 2, Tisch 54, Nummer 1
Daniel Krause = Hof 2, Tisch 54, Nummer 2 Thomas Bianchi = Hof 2, Tisch 54, Nummer 2
Prof. Dr. Emre Ludwig = Hof 2, Tisch 54, Nummer 3 Mia Bianchi = Hof 2, Tisch 54, Nummer 3
Markus Klein = Hof 2, Tisch 54, Nummer 4
[55] [55]
Michael Busch = Hof 2, Tisch 55, Nummer 1 Sandra Werner = Hof 2, Tisch 55, Nummer 1
Marie Busch = Hof 2, Tisch 55, Nummer 2 Andreas Werner = Hof 2, Tisch 55, Nummer 2
Emre Busch = Hof 2, Tisch 55, Nummer 3 Nadine Werner = Hof 2, Tisch 55, Nummer 3
Olga Busch = Hof 2, Tisch 55, Nummer 4 Marco Werner = Hof 2, Tisch 55, Nummer 4
[56] [56]
Luca Kaya = Hof 2, Tisch 56, Nummer 1 Olga Busch = Hof 2, Tisch 56, Nummer 1
Christina Kaya = Hof 2, Tisch 56, Nummer 2 Emre Busch = Hof 2, Tisch 56, Nummer 2
Nicole Kaya = Hof 2, Tisch 56, Nummer 3 Marie Busch = Hof 2, Tisch 56, Nummer 3
Michael Busch = Hof 2, Tisch 56, Nummer 4
[57] [57]
Matthias Schmidt = Hof 2, Tisch 57, Nummer 1 Prof. Dr. Emre Ludwig = Hof 2, Tisch 57, Nummer 1
Giovanna Schmidt = Hof 2, Tisch 57, Nummer 2 Daniel Krause = Hof 2, Tisch 57, Nummer 2
Marie Schmidt = Hof 2, Tisch 57, Nummer 3 Nicole Aksoy = Hof 2, Tisch 57, Nummer 3
Markus Klein = Hof 2, Tisch 57, Nummer 4
[58] [58]
Prof. Dr. Marco Seifert = Hof 2, Tisch 58, Nummer 1
Matthias Krause = Hof 2, Tisch 58, Nummer 2
Giovanna Schwarz = Hof 2, Tisch 58, Nummer 3
[59] [59]
Andreas Werner = Hof 2, Tisch 59, Nummer 1 Prof. Dr. Thomas Tran = Hof 2, Tisch 59, Nummer 1
Nadine Werner = Hof 2, Tisch 59, Nummer 2 Sergej Petrov = Hof 2, Tisch 59, Nummer 2
Marco Werner = Hof 2, Tisch 59, Nummer 3 Kathrin Polat = Hof 2, Tisch 59, Nummer 3
Sandra Werner = Hof 2, Tisch 59, Nummer 4 Marija Aksoy = Hof 2, Tisch 59, Nummer 4
[60] [60]
Marija Polat = Hof 2, Tisch 60, Nummer 1 Nicole Sahin = Hof 2, Tisch 60, Nummer 1
Nadine Arnold = Hof 2, Tisch 60, Nummer 2 Markus Sahin = Hof 2, Tisch 60, Nummer 2
Marco Richter = Hof 2, Tisch 60, Nummer 3 Kathrin Sahin = Hof 2, Tisch 60, Nummer 3
Prof. Dr. Patrick Hoffmann = Hof 2, Tisch 60, Nummer 4 Patrick Sahin = Hof 2, Tisch 60, Nummer 4
[61] [61]
Luca Ott = Hof 2, Tisch 61, Nummer 1 Sarah Maier = Hof 2, Tisch 61, Nummer 1
Patrick Zimmermann = Hof 2, Tisch 61, Nummer 2 Christian Maier = Hof 2, Tisch 61, Nummer 2
Yusuf Weber = Hof 2, Tisch 61, Nummer 3 Olga Maier = Hof 2, Tisch 61, Nummer 3
Giovanna Schwarz = Hof 2, Tisch 61, Nummer 4 Arda Maier = Hof 2, Tisch 61, Nummer 4
[62] [62]
Sofia Nguyen = Hof 2, Tisch 62, Nummer 1 Luca Kovac = Hof 2, Tisch 62, Nummer 1
Anja Nguyen = Hof 2, Tisch 62, Nummer 2 Dr. Dragana Krause = Hof 2, Tisch 62, Nummer 2
Daniel Nguyen = Hof 2, Tisch 62, Nummer 3 Prof. Dr. Dennis Schmitt = Hof 2, Tisch 62, Nummer 3
[63] [63]
Nicole Wagner = Hof 2, Tisch 63, Nummer 1 Andreas Krause = Hof 2, Tisch 63, Nummer 1
Henry Wagner = Hof 2, Tisch 63, Nummer 2 Emma Krause = Hof 2, Tisch 63, Nummer 2
Sarah Wagner = Hof 2, Tisch 63, Nummer 3 Arda Krause = Hof 2, Tisch 63, Nummer 3
Marco Wagner = Hof 2, Tisch 63, Nummer 4 Julia Krause = Hof 2, Tisch 63, Nummer 4
[64] [64]
Elif Ludwig = Hof 2, Tisch 64, Nummer 1 Katrin Werner = Hof 2, Tisch 64, Nummer 1
Emre Ludwig = Hof 2, Tisch 64, Nummer 2 Patrick Busch = Hof 2, Tisch 64, Nummer 2
Giovanna Ludwig = Hof 2, Tisch 64, Nummer 3 Emre Hoffmann = Hof 2, Tisch 64, Nummer 3
Elias Ludwig = Hof 2, Tisch 64, Nummer 4 Sergej Lange = Hof 2, Tisch 64, Nummer 4
[65] [65]
Nicole Becker = Hof 2, Tisch 65, Nummer 1 Nadine Arnold = Hof 2, Tisch 65, Nummer 1
Jan Becker = Hof 2, Tisch 65, Nummer 2 Marco Richter = Hof 2, Tisch 65, Nummer 2
Sandra Becker = Hof 2, Tisch 65, Nummer 3 Prof. Dr. Patrick Hoffmann = Hof 2, Tisch 65, Nummer 3
Marija Polat = Hof 2, Tisch 65, Nummer 4
[66] [66]
Christian Maier = Hof 2, Tisch 66, Nummer 1 Lena Simon = Hof 2, Tisch 66, Nummer 1
Sarah Maier = Hof 2, Tisch 66, Nummer 2 Markus Simon = Hof 2, Tisch 66, Nummer 2
Arda Maier = Hof 2, Tisch 66, Nummer 3 Emma Simon = Hof 2, Tisch 66, Nummer 3
Olga Maier = Hof 2, Tisch 66, Nummer 4 Andreas Simon = Hof 2, Tisch 66, Nummer 4
[67] [67]
Svenja Zimmermann = Hof 2, Tisch 67, Nummer 1 Yusuf Weber = Hof 2, Tisch 67, Nummer 1
Mia Zimmermann = Hof 2, Tisch 67, Nummer 2 Dr. Patrick Kraus = Hof 2, Tisch 67, Nummer 2
Markus Zimmermann = Hof 2, Tisch 67, Nummer 3 Dr. Aylin Ludwig = Hof 2, Tisch 67, Nummer 3
Jan Zimmermann = Hof 2, Tisch 67, Nummer 4
[68] [68]
Marija Tran = Hof 2, Tisch 68, Nummer 1 Nicole Wagner = Hof 2, Tisch 68, Nummer 1
Luca Werner = Hof 2, Tisch 68, Nummer 2 Marco Wagner = Hof 2, Tisch 68, Nummer 2
Dr. Kathrin Koch = Hof 2, Tisch 68, Nummer 3 Sarah Wagner = Hof 2, Tisch 68, Nummer 3
Henry Wagner = Hof 2, Tisch 68, Nummer 4
[69] [69]
Katrin Weber = Hof 2, Tisch 69, Nummer 1 Olga Franke = Hof 2, Tisch 69, Nummer 1
Prof. Dr. Stefan Schmitt = Hof 2, Tisch 69, Nummer 2 Amira Franke = Hof 2, Tisch 69, Nummer 2
Dr. Julia Kuhn = Hof 2, Tisch 69, Nummer 3 Marco Franke = Hof 2, Tisch 69, Nummer 3
[70] [70]
Prof. Dr. Marco Seifert = Hof 2, Tisch 70, Nummer 1 Svenja Zimmermann = Hof 2, Tisch 70, Nummer 1
Dr. Patrick Kraus = Hof 2, Tisch 70, Nummer 2 Jan Zimmermann = Hof 2, Tisch 70, Nummer 2
Dr. Aylin Ludwig = Hof 2, Tisch 70, Nummer 3 Mia Zimmermann = Hof 2, Tisch 70, Nummer 3
Matthias Krause = Hof 2, Tisch 70, Nummer 4 Markus Zimmermann = Hof 2, Tisch 70, Nummer 4
[71] [71]
Stefan Richter = Hof 2, Tisch 71, Nummer 1 Luca Ott = Hof 2, Tisch 71, Nummer 1
Dr. Dragana Krause = Hof 2, Tisch 71, Nummer 2 Patrick Zimmermann = Hof 2, Tisch 71, Nummer 2
Luca Kovac = Hof 2, Tisch 71, Nummer 3 Stefan Richter = Hof 2, Tisch 71, Nummer 3
Prof. Dr. Dennis Schmitt = Hof 2, Tisch 71, Nummer 4
[72] [72]
Layla Horn = Hof 2, Tisch 72, Nummer 1 Matthias Ott = Hof 2, Tisch 72, Nummer 1
Michael Horn = Hof 2, Tisch 72, Nummer 2 Hannah Ott = Hof 2, Tisch 72, Nummer 2
Leon Horn = Hof 2, Tisch 72, Nummer 3 Olga Ott = Hof 2, Tisch 72, Nummer 3
Kathrin Horn = Hof 2, Tisch 72, Nummer 4
[73] [73]
Jennifer Neumann = Hof 2, Tisch 73, Nummer 1 Jennifer Neumann = Hof 2, Tisch 73, Nummer 1
Matteo Neumann = Hof 2, Tisch 73, Nummer 2 Thomas Neumann = Hof 2, Tisch 73, Nummer 2
Lina Neumann = Hof 2, Tisch 73, Nummer 3 Lina Neumann = Hof 2, Tisch 73, Nummer 3
Thomas Neumann = Hof 2, Tisch 73, Nummer 4 Matteo Neumann = Hof 2, Tisch 73, Nummer 4
[74] [74]
Emma Wolf = Hof 2, Tisch 74, Nummer 1 Patrick Barth = Hof 2, Tisch 74, Nummer 1
Julia Wolf = Hof 2, Tisch 74, Nummer 2 Nadine Barth = Hof 2, Tisch 74, Nummer 2
Ben Wolf = Hof 2, Tisch 74, Nummer 3 Timo Barth = Hof 2, Tisch 74, Nummer 3
Thomas Wolf = Hof 2, Tisch 74, Nummer 4 Lina Barth = Hof 2, Tisch 74, Nummer 4
[75] [75]
Andreas Simon = Hof 2, Tisch 75, Nummer 1 Dragana Pohl = Hof 2, Tisch 75, Nummer 1
Emma Simon = Hof 2, Tisch 75, Nummer 2 Emre Pohl = Hof 2, Tisch 75, Nummer 2
Markus Simon = Hof 2, Tisch 75, Nummer 3 Mia Pohl = Hof 2, Tisch 75, Nummer 3
Lena Simon = Hof 2, Tisch 75, Nummer 4 Theo Pohl = Hof 2, Tisch 75, Nummer 4
[76] [76]
Amira Franke = Hof 2, Tisch 76, Nummer 1 Prof. Dr. Yusuf Esposito = Hof 2, Tisch 76, Nummer 1
Michael Franke = Hof 2, Tisch 76, Nummer 2 Marija Becker = Hof 2, Tisch 76, Nummer 2
Julia Franke = Hof 2, Tisch 76, Nummer 3 Matthias Kovac = Hof 2, Tisch 76, Nummer 3
[77] [77]
Marco Franke = Hof 2, Tisch 77, Nummer 1 Luca Kaya = Hof 2, Tisch 77, Nummer 1
Markus Polat = Hof 2, Tisch 77, Nummer 2 Christina Kaya = Hof 2, Tisch 77, Nummer 2
Sarah Polat = Hof 2, Tisch 77, Nummer 3 Nicole Kaya = Hof 2, Tisch 77, Nummer 3
Olga Franke = Hof 2, Tisch 77, Nummer 4
[78] [78]
Milan Klein = Hof 2, Tisch 78, Nummer 1 Deniz Hartmann = Hof 2, Tisch 78, Nummer 1
Stefanie Klein = Hof 2, Tisch 78, Nummer 2 Nadine Hartmann = Hof 2, Tisch 78, Nummer 2
Lina Klein = Hof 2, Tisch 78, Nummer 3 Michael Franke = Hof 2, Tisch 78, Nummer 3
Julia Franke = Hof 2, Tisch 78, Nummer 4
[79] [79]
Sofia Roth = Hof 2, Tisch 79, Nummer 1 Kathrin Horn = Hof 2, Tisch 79, Nummer 1
Sarah Roth = Hof 2, Tisch 79, Nummer 2 Michael Horn = Hof 2, Tisch 79, Nummer 2
Christian Roth = Hof 2, Tisch 79, Nummer 3 Layla Horn = Hof 2, Tisch 79, Nummer 3
Leon Horn = Hof 2, Tisch 79, Nummer 4
[80] [80]
Prof. Dr. Anja Richter = Hof 2, Tisch 80, Nummer 1 Stefanie Polat = Hof 2, Tisch 80, Nummer 1
Thomas Sahin = Hof 2, Tisch 80, Nummer 2 Stefan Polat = Hof 2, Tisch 80, Nummer 2
Dr. Jan Thiel = Hof 2, Tisch 80, Nummer 3 Melanie Ott = Hof 2, Tisch 80, Nummer 3
Daniel Ott = Hof 2, Tisch 80, Nummer 4
[81] [81]
Prof. Dr. Yusuf Ott = Hof 2, Tisch 81, Nummer 1 Sarah Polat = Hof 2, Tisch 81, Nummer 1
Patrick Lehmann = Hof 2, Tisch 81, Nummer 2 Markus Polat = Hof 2, Tisch 81, Nummer 2
Dr. Nadine Berger = Hof 2, Tisch 81, Nummer 3 Katrin Polat = Hof 2, Tisch 81, Nummer 3
[82] [82]
Matthias Ott = Hof 2, Tisch 82, Nummer 1 Olga Roth = Hof 2, Tisch 82, Nummer 1
Melanie Ott = Hof 2, Tisch 82, Nummer 2 Prof. Dr. Emre Albrecht = Hof 2, Tisch 82, Nummer 2
Hannah Ott = Hof 2, Tisch 82, Nummer 3 Thomas Bianchi = Hof 2, Tisch 82, Nummer 3
[83] [83]
Ben Stein = Hof 2, Tisch 83, Nummer 1 Emma Wolf = Hof 2, Tisch 83, Nummer 1
Giovanna Stein = Hof 2, Tisch 83, Nummer 2 Ben Wolf = Hof 2, Tisch 83, Nummer 2
Emilia Stein = Hof 2, Tisch 83, Nummer 3 Julia Wolf = Hof 2, Tisch 83, Nummer 3
Thomas Stein = Hof 2, Tisch 83, Nummer 4 Thomas Wolf = Hof 2, Tisch 83, Nummer 4
[84] [84]
Stefanie Polat = Hof 2, Tisch 84, Nummer 1 Marija Hartmann = Hof 2, Tisch 84, Nummer 1
Katrin Polat = Hof 2, Tisch 84, Nummer 2 Thomas Hartmann = Hof 2, Tisch 84, Nummer 2
Stefan Polat = Hof 2, Tisch 84, Nummer 3 Olga Hartmann = Hof 2, Tisch 84, Nummer 3
[85] [85]
Dragana Pohl = Hof 2, Tisch 85, Nummer 1 Matthias Schmidt = Hof 2, Tisch 85, Nummer 1
Theo Pohl = Hof 2, Tisch 85, Nummer 2 Marie Schmidt = Hof 2, Tisch 85, Nummer 2
Mia Pohl = Hof 2, Tisch 85, Nummer 3 Giovanna Schmidt = Hof 2, Tisch 85, Nummer 3
Emre Pohl = Hof 2, Tisch 85, Nummer 4
[86] [86]
Thomas Stein = Hof 2, Tisch 86, Nummer 1
Emilia Stein = Hof 2, Tisch 86, Nummer 2
Ben Stein = Hof 2, Tisch 86, Nummer 3
Giovanna Stein = Hof 2, Tisch 86, Nummer 4
[87] [87]
Marija Hartmann = Hof 2, Tisch 87, Nummer 1 Lena Frank = Hof 2, Tisch 87, Nummer 1
Thomas Hartmann = Hof 2, Tisch 87, Nummer 2 Marie Frank = Hof 2, Tisch 87, Nummer 2
Nadine Hartmann = Hof 2, Tisch 87, Nummer 3 Finn Frank = Hof 2, Tisch 87, Nummer 3
[88] [88]
Olga Ott = Hof 2, Tisch 88, Nummer 1 Dr. Olga Klein = Hof 2, Tisch 88, Nummer 1
Olga Hartmann = Hof 2, Tisch 88, Nummer 2 Dr. Jennifer Arnold = Hof 2, Tisch 88, Nummer 2
Deniz Hartmann = Hof 2, Tisch 88, Nummer 3 Nadine Frank = Hof 2, Tisch 88, Nummer 3
Daniel Ott = Hof 2, Tisch 88, Nummer 4 Dennis Frank = Hof 2, Tisch 88, Nummer 4
+9 -9
View File
@@ -1,17 +1,17 @@
AA, A, Dipl. Ing. = Hof 1, Tisch 1, Nummer 2
AA, A, Dipl. Ing. = Hof 1, Tisch 1, Nummer 3
AA, A, Dipl. Ing. = Hof 1, Tisch 1, Nummer 4
AA, A, Dipl. Ing. = Hof 1, Tisch 1, Nummer 5
AA, A, Dipl. Ing. = Hof 1, Tisch 1, Nummer 6
AA, A, Dipl. Ing. = Hof 1, Tisch 2, Nummer 2 AA, A, Dipl. Ing. = Hof 1, Tisch 2, Nummer 2
AA, A, Dipl. Ing. = Hof 1, Tisch 2, Nummer 3 AA, A, Dipl. Ing. = Hof 1, Tisch 2, Nummer 3
AA, A, Dipl. Ing. = Hof 1, Tisch 2, Nummer 4 AA, A, Dipl. Ing. = Hof 1, Tisch 2, Nummer 4
AA, A, Dipl. Ing. = Hof 1, Tisch 2, Nummer 5 AA, A, Dipl. Ing. = Hof 1, Tisch 2, Nummer 5
AA, A, Dipl. Ing. = Hof 1, Tisch 2, Nummer 6 AA, A, Dipl. Ing. = Hof 1, Tisch 2, Nummer 6
AA, A, Dipl. Ing. = Hof 1, Tisch 3, Nummer 2 BB, B, Prof. = Hof 1, Tisch 3, Nummer 2
AA, A, Dipl. Ing. = Hof 1, Tisch 3, Nummer 3 BB, B, Prof. = Hof 1, Tisch 3, Nummer 3
AA, A, Dipl. Ing. = Hof 1, Tisch 3, Nummer 4 BB, B, Prof. = Hof 1, Tisch 3, Nummer 4
AA, A, Dipl. Ing. = Hof 1, Tisch 3, Nummer 5 BB, B, Prof. = Hof 1, Tisch 3, Nummer 5
AA, A, Dipl. Ing. = Hof 1, Tisch 3, Nummer 6
BB, B, Prof. = Hof 1, Tisch 1, Nummer 2
BB, B, Prof. = Hof 1, Tisch 1, Nummer 3
BB, B, Prof. = Hof 1, Tisch 1, Nummer 4
BB, B, Prof. = Hof 1, Tisch 1, Nummer 5
CC, C, Dr. = Hof 1, Tisch 4, Nummer 2 CC, C, Dr. = Hof 1, Tisch 4, Nummer 2
CC, C, Dr. = Hof 1, Tisch 4, Nummer 3 CC, C, Dr. = Hof 1, Tisch 4, Nummer 3
CC, C, Dr. = Hof 1, Tisch 4, Nummer 4 CC, C, Dr. = Hof 1, Tisch 4, Nummer 4
1 AA A Dipl. Ing. = Hof 1 Tisch 2 Tisch 1 Nummer 2
1 AA A Dipl. Ing. = Hof 1 Tisch 1 Nummer 2
2 AA A Dipl. Ing. = Hof 1 Tisch 1 Nummer 3
3 AA A Dipl. Ing. = Hof 1 Tisch 1 Nummer 4
4 AA A Dipl. Ing. = Hof 1 Tisch 1 Nummer 5
5 AA A Dipl. Ing. = Hof 1 Tisch 1 Nummer 6
6 AA A Dipl. Ing. = Hof 1 Tisch 2 Tisch 2 Nummer 2
7 AA A Dipl. Ing. = Hof 1 Tisch 2 Tisch 2 Nummer 3
8 AA A Dipl. Ing. = Hof 1 Tisch 2 Tisch 2 Nummer 4
9 AA A Dipl. Ing. = Hof 1 Tisch 2 Tisch 2 Nummer 5
10 AA A Dipl. Ing. = Hof 1 Tisch 2 Tisch 2 Nummer 6
11 AA BB A B Dipl. Ing. = Hof 1 Prof. = Hof 1 Tisch 3 Tisch 3 Nummer 2
12 AA BB A B Dipl. Ing. = Hof 1 Prof. = Hof 1 Tisch 3 Tisch 3 Nummer 3
13 AA BB A B Dipl. Ing. = Hof 1 Prof. = Hof 1 Tisch 3 Tisch 3 Nummer 4
14 AA BB A B Dipl. Ing. = Hof 1 Prof. = Hof 1 Tisch 3 Tisch 3 Nummer 5
AA A Dipl. Ing. = Hof 1 Tisch 3 Nummer 6
BB B Prof. = Hof 1 Tisch 1 Nummer 2
BB B Prof. = Hof 1 Tisch 1 Nummer 3
BB B Prof. = Hof 1 Tisch 1 Nummer 4
BB B Prof. = Hof 1 Tisch 1 Nummer 5
15 CC C Dr. = Hof 1 Tisch 4 Tisch 4 Nummer 2
16 CC C Dr. = Hof 1 Tisch 4 Tisch 4 Nummer 3
17 CC C Dr. = Hof 1 Tisch 4 Tisch 4 Nummer 4
+13 -13
View File
@@ -1,12 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="405.657" height="108.914" viewBox="0 0 405.657 108.914"> <svg xmlns="http://www.w3.org/2000/svg" width="405.657" height="108.914" viewBox="0 0 405.657 108.914">
<rect width="100%" height="100%" fill="white"/> <rect width="100%" height="100%" fill="white"/>
<polyline points="153.372,54.4572 252.286,54.4572" fill="none" stroke="#3cb44b" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="0.5"/> <polyline points="54.4572,54.4572 153.372,54.4572" fill="none" stroke="#3cb44b" stroke-width="12" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="0.5"/>
<circle cx="252.286" cy="54.4572" r="44.4572" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="252.286" cy="32" r="12" fill="#e6194b" stroke="black" stroke-width="1"/>
<circle cx="274.743" cy="54.4572" r="12" fill="#e6194b" stroke="black" stroke-width="1"/>
<circle cx="252.286" cy="76.9144" r="12" fill="#e6194b" stroke="black" stroke-width="1"/>
<circle cx="229.829" cy="54.4572" r="12" fill="#e6194b" stroke="black" stroke-width="1"/>
<circle cx="252.286" cy="54.4572" r="12" fill="white" fill-opacity="0.75"/>
<text x="252.286" y="54.4572" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">3</text>
<circle cx="54.4572" cy="54.4572" r="44.4572" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="54.4572" cy="54.4572" r="44.4572" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="54.4572" cy="32" r="12" fill="#e6194b" stroke="black" stroke-width="1"/> <circle cx="54.4572" cy="32" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/>
<circle cx="76.9144" cy="54.4572" r="12" fill="#e6194b" stroke="black" stroke-width="1"/> <circle cx="75.8152" cy="47.5175" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/>
<circle cx="54.4572" cy="76.9144" r="12" fill="#e6194b" stroke="black" stroke-width="1"/> <circle cx="67.6572" cy="72.6254" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/>
<circle cx="32" cy="54.4572" r="12" fill="#e6194b" stroke="black" stroke-width="1"/> <circle cx="41.2572" cy="72.6254" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/>
<circle cx="33.0991" cy="47.5175" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/>
<circle cx="54.4572" cy="54.4572" r="12" fill="white" fill-opacity="0.75"/> <circle cx="54.4572" cy="54.4572" r="12" fill="white" fill-opacity="0.75"/>
<text x="54.4572" y="54.4572" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">1</text> <text x="54.4572" y="54.4572" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">1</text>
<circle cx="153.372" cy="54.4572" r="44.4572" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="153.372" cy="54.4572" r="44.4572" fill="white" stroke="black" stroke-width="1.5"/>
@@ -17,14 +25,6 @@
<circle cx="132.013" cy="47.5175" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/> <circle cx="132.013" cy="47.5175" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/>
<circle cx="153.372" cy="54.4572" r="12" fill="white" fill-opacity="0.75"/> <circle cx="153.372" cy="54.4572" r="12" fill="white" fill-opacity="0.75"/>
<text x="153.372" y="54.4572" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">2</text> <text x="153.372" y="54.4572" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">2</text>
<circle cx="252.286" cy="54.4572" r="44.4572" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="252.286" cy="32" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/>
<circle cx="273.644" cy="47.5175" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/>
<circle cx="265.486" cy="72.6254" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/>
<circle cx="239.086" cy="72.6254" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/>
<circle cx="230.928" cy="47.5175" r="12" fill="#3cb44b" stroke="black" stroke-width="1"/>
<circle cx="252.286" cy="54.4572" r="12" fill="white" fill-opacity="0.75"/>
<text x="252.286" y="54.4572" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">3</text>
<circle cx="351.2" cy="54.4572" r="44.4572" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="351.2" cy="54.4572" r="44.4572" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="351.2" cy="32" r="12" fill="#4363d8" stroke="black" stroke-width="1"/> <circle cx="351.2" cy="32" r="12" fill="#4363d8" stroke="black" stroke-width="1"/>
<circle cx="372.558" cy="47.5175" r="12" fill="#4363d8" stroke="black" stroke-width="1"/> <circle cx="372.558" cy="47.5175" r="12" fill="#4363d8" stroke="black" stroke-width="1"/>

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

+9 -9
View File
@@ -1,8 +1,9 @@
[1] [1]
Prof. B BB = Hof 1, Tisch 1, Nummer 1 Dipl. Ing. A AA = Hof 1, Tisch 1, Nummer 1
Prof. B BB = Hof 1, Tisch 1, Nummer 2 Dipl. Ing. A AA = Hof 1, Tisch 1, Nummer 2
Prof. B BB = Hof 1, Tisch 1, Nummer 3 Dipl. Ing. A AA = Hof 1, Tisch 1, Nummer 3
Prof. B BB = Hof 1, Tisch 1, Nummer 4 Dipl. Ing. A AA = Hof 1, Tisch 1, Nummer 4
Dipl. Ing. A AA = Hof 1, Tisch 1, Nummer 5
[2] [2]
Dipl. Ing. A AA = Hof 1, Tisch 2, Nummer 1 Dipl. Ing. A AA = Hof 1, Tisch 2, Nummer 1
@@ -12,11 +13,10 @@ Dipl. Ing. A AA = Hof 1, Tisch 2, Nummer 4
Dipl. Ing. A AA = Hof 1, Tisch 2, Nummer 5 Dipl. Ing. A AA = Hof 1, Tisch 2, Nummer 5
[3] [3]
Dipl. Ing. A AA = Hof 1, Tisch 3, Nummer 1 Prof. B BB = Hof 1, Tisch 3, Nummer 1
Dipl. Ing. A AA = Hof 1, Tisch 3, Nummer 2 Prof. B BB = Hof 1, Tisch 3, Nummer 2
Dipl. Ing. A AA = Hof 1, Tisch 3, Nummer 3 Prof. B BB = Hof 1, Tisch 3, Nummer 3
Dipl. Ing. A AA = Hof 1, Tisch 3, Nummer 4 Prof. B BB = Hof 1, Tisch 3, Nummer 4
Dipl. Ing. A AA = Hof 1, Tisch 3, Nummer 5
[4] [4]
Dr. C CC = Hof 1, Tisch 4, Nummer 1 Dr. C CC = Hof 1, Tisch 4, Nummer 1
+9 -9
View File
@@ -1,17 +1,17 @@
Bloedkopf, Bestelli, = Hof 1, Tisch 2, Nummer 2 Bloedkopf, Bestelli, = Hof 1, Tisch 2, Nummer 2
Bloedkopf, Bestelli, = Hof 1, Tisch 2, Nummer 3 Bloedkopf, Bestelli, = Hof 1, Tisch 2, Nummer 3
Bloedkopf, Bestelli, = Hof 1, Tisch 2, Nummer 4 Bloedkopf, Bestelli, = Hof 1, Tisch 2, Nummer 4
Brandt, Willi, Dr. = Hof 1, Tisch 4, Nummer 2 Brandt, Willi, Dr. = Hof 1, Tisch 4, Nummer 5
Bruegge, Heinz, = Hof 1, Tisch 5, Nummer 2 Bruegge, Heinz, = Hof 1, Tisch 5, Nummer 2
Dietrich, Marlene, = Hof 1, Tisch 5, Nummer 5 Dietrich, Marlene, = Hof 1, Tisch 5, Nummer 5
Emmerlich, Walter, = Hof 1, Tisch 3, Nummer 3 Emmerlich, Walter, = Hof 1, Tisch 4, Nummer 3
Frenzen, Heinz Harald, = Hof 1, Tisch 3, Nummer 4 Frenzen, Heinz Harald, = Hof 1, Tisch 3, Nummer 4
Hoehn, Bernd Robert, Professor = Hof 1, Tisch 1, Nummer 2 Hoehn, Bernd Robert, Professor = Hof 1, Tisch 1, Nummer 4
Junke, Harald, = Hof 1, Tisch 4, Nummer 4 Junke, Harald, = Hof 1, Tisch 4, Nummer 4
K, Hubert, = Hof 1, Tisch 5, Nummer 4 K, Hubert, = Hof 1, Tisch 5, Nummer 3
Leone, Sergio, = Hof 1, Tisch 3, Nummer 2 Leone, Sergio, = Hof 1, Tisch 4, Nummer 2
Mueller, Magnus, Professor = Hof 1, Tisch 1, Nummer 3 Mueller, Magnus, Professor = Hof 1, Tisch 1, Nummer 3
Ruehmann, Heinz, = Hof 1, Tisch 5, Nummer 3 Ruehmann, Heinz, = Hof 1, Tisch 5, Nummer 4
Schumacher, Michael, = Hof 1, Tisch 4, Nummer 3 Schumacher, Michael, = Hof 1, Tisch 3, Nummer 3
Schumacher, Ralf, = Hof 1, Tisch 4, Nummer 5 Schumacher, Ralf, = Hof 1, Tisch 3, Nummer 2
Stangl, Michael, Dipl. Ing. = Hof 1, Tisch 1, Nummer 4 Stangl, Michael, Dipl. Ing. = Hof 1, Tisch 1, Nummer 2
1 Bloedkopf Bestelli = Hof 1 Tisch 2 Nummer 2
2 Bloedkopf Bestelli = Hof 1 Tisch 2 Nummer 3
3 Bloedkopf Bestelli = Hof 1 Tisch 2 Nummer 4
4 Brandt Willi Dr. = Hof 1 Tisch 4 Nummer 2 Nummer 5
5 Bruegge Heinz = Hof 1 Tisch 5 Nummer 2
6 Dietrich Marlene = Hof 1 Tisch 5 Nummer 5
7 Emmerlich Walter = Hof 1 Tisch 3 Tisch 4 Nummer 3
8 Frenzen Heinz Harald = Hof 1 Tisch 3 Nummer 4
9 Hoehn Bernd Robert Professor = Hof 1 Tisch 1 Nummer 2 Nummer 4
10 Junke Harald = Hof 1 Tisch 4 Nummer 4
11 K Hubert = Hof 1 Tisch 5 Nummer 4 Nummer 3
12 Leone Sergio = Hof 1 Tisch 3 Tisch 4 Nummer 2
13 Mueller Magnus Professor = Hof 1 Tisch 1 Nummer 3
14 Ruehmann Heinz = Hof 1 Tisch 5 Nummer 3 Nummer 4
15 Schumacher Michael = Hof 1 Tisch 4 Tisch 3 Nummer 3
16 Schumacher Ralf = Hof 1 Tisch 4 Tisch 3 Nummer 5 Nummer 2
17 Stangl Michael Dipl. Ing. = Hof 1 Tisch 1 Nummer 4 Nummer 2
+2 -2
View File
@@ -29,8 +29,8 @@
<text x="351.2" y="54.4572" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">4</text> <text x="351.2" y="54.4572" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">4</text>
<circle cx="450.115" cy="54.4572" r="40.6676" fill="white" stroke="black" stroke-width="1.5"/> <circle cx="450.115" cy="54.4572" r="40.6676" fill="white" stroke="black" stroke-width="1.5"/>
<circle cx="450.115" cy="35.7896" r="12" fill="#4363d8" stroke="black" stroke-width="1"/> <circle cx="450.115" cy="35.7896" r="12" fill="#4363d8" stroke="black" stroke-width="1"/>
<circle cx="468.782" cy="54.4572" r="12" fill="#f58231" stroke="black" stroke-width="1"/> <circle cx="468.782" cy="54.4572" r="12" fill="#4363d8" stroke="black" stroke-width="1"/>
<circle cx="450.115" cy="73.1248" r="12" fill="#4363d8" stroke="black" stroke-width="1"/> <circle cx="450.115" cy="73.1248" r="12" fill="#f58231" stroke="black" stroke-width="1"/>
<circle cx="431.447" cy="54.4572" r="12" fill="#f58231" stroke="black" stroke-width="1"/> <circle cx="431.447" cy="54.4572" r="12" fill="#f58231" stroke="black" stroke-width="1"/>
<circle cx="450.115" cy="54.4572" r="12" fill="white" fill-opacity="0.75"/> <circle cx="450.115" cy="54.4572" r="12" fill="white" fill-opacity="0.75"/>
<text x="450.115" y="54.4572" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">5</text> <text x="450.115" y="54.4572" text-anchor="middle" dominant-baseline="central" font-size="13.2" font-weight="bold" fill="black">5</text>

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

+9 -9
View File
@@ -1,7 +1,7 @@
[1] [1]
Professor Bernd Robert Hoehn = Hof 1, Tisch 1, Nummer 1 Dipl. Ing. Michael Stangl = Hof 1, Tisch 1, Nummer 1
Professor Magnus Mueller = Hof 1, Tisch 1, Nummer 2 Professor Magnus Mueller = Hof 1, Tisch 1, Nummer 2
Dipl. Ing. Michael Stangl = Hof 1, Tisch 1, Nummer 3 Professor Bernd Robert Hoehn = Hof 1, Tisch 1, Nummer 3
[2] [2]
Bestelli Bloedkopf = Hof 1, Tisch 2, Nummer 1 Bestelli Bloedkopf = Hof 1, Tisch 2, Nummer 1
@@ -9,19 +9,19 @@ Dipl. Ing. Michael Stangl = Hof 1, Tisch 1, Nummer 3
Bestelli Bloedkopf = Hof 1, Tisch 2, Nummer 3 Bestelli Bloedkopf = Hof 1, Tisch 2, Nummer 3
[3] [3]
Sergio Leone = Hof 1, Tisch 3, Nummer 1 Ralf Schumacher = Hof 1, Tisch 3, Nummer 1
Walter Emmerlich = Hof 1, Tisch 3, Nummer 2 Michael Schumacher = Hof 1, Tisch 3, Nummer 2
Heinz Harald Frenzen = Hof 1, Tisch 3, Nummer 3 Heinz Harald Frenzen = Hof 1, Tisch 3, Nummer 3
[4] [4]
Dr. Willi Brandt = Hof 1, Tisch 4, Nummer 1 Sergio Leone = Hof 1, Tisch 4, Nummer 1
Michael Schumacher = Hof 1, Tisch 4, Nummer 2 Walter Emmerlich = Hof 1, Tisch 4, Nummer 2
Harald Junke = Hof 1, Tisch 4, Nummer 3 Harald Junke = Hof 1, Tisch 4, Nummer 3
Ralf Schumacher = Hof 1, Tisch 4, Nummer 4 Dr. Willi Brandt = Hof 1, Tisch 4, Nummer 4
[5] [5]
Heinz Bruegge = Hof 1, Tisch 5, Nummer 1 Heinz Bruegge = Hof 1, Tisch 5, Nummer 1
Heinz Ruehmann = Hof 1, Tisch 5, Nummer 2 Hubert K = Hof 1, Tisch 5, Nummer 2
Hubert K = Hof 1, Tisch 5, Nummer 3 Heinz Ruehmann = Hof 1, Tisch 5, Nummer 3
Marlene Dietrich = Hof 1, Tisch 5, Nummer 4 Marlene Dietrich = Hof 1, Tisch 5, Nummer 4