Stadionzeitung: Ausgabe 19.09., Gegnerseiten ohne Fest, Gegner-Kurzname
Gegnerseiten lassen sich jetzt ueber `gegner_teams` auch ohne Veranstaltung fuer weitere Mannschaften anlegen (Fenster zwei Tage vor bis drei Tage nach dem Ausgabedatum, auch auswaerts), und `opponent_short` liefert den gedruckten Anzeigenamen, waehrend `opponent` die BFV-Schreibweise fuer den Namensvergleich behaelt. Dazu die Ausgabe zum Heimspiel gegen Wirsberg/Kupferberg als Entwurf samt Seitenbildern. Die gemeinsamen QR-Codes sind neu erzeugt (die vendorte Bibliothek arbeitet nicht reproduzierbar, das Maskenmuster wechselt). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hv9SGDu3m3diiPrW9Fmj3v
@@ -31,7 +31,7 @@ $issues = $issues ?? [];
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="stadionzeitung-card__body">
|
||||
<h3 class="stadionzeitung-card__name">Stadionzeitung zum Heimspiel gegen <?= e($issue['opponent']) ?></h3>
|
||||
<h3 class="stadionzeitung-card__name">Stadionzeitung zum Heimspiel gegen <?= e(stadionzeitung_opponent_display($issue)) ?></h3>
|
||||
<p class="stadionzeitung-card__meta">
|
||||
<time datetime="<?= e($issue['date']) ?>"><?= e(german_date($issue['date'])) ?></time>
|
||||
· <?= (int) $issue['pages'] ?> Seiten
|
||||
|
||||
@@ -32,7 +32,7 @@ declare(strict_types=1);
|
||||
* der Gegner läuft über den Initialen-Fallback der crest-Komponente.
|
||||
*/
|
||||
$issue = $issue ?? [];
|
||||
$opponent = (string) ($issue['opponent'] ?? '');
|
||||
$opponent = stadionzeitung_opponent_display($issue);
|
||||
$date = (string) ($issue['date'] ?? '');
|
||||
$teamKey = (string) ($issue['team_key'] ?? '');
|
||||
$playerImage = $issue['player_image'] ?? null;
|
||||
|
||||
@@ -26,7 +26,7 @@ $total = count($images);
|
||||
if ($images === []) {
|
||||
return;
|
||||
}
|
||||
$opponent = (string) ($issue['opponent'] ?? '');
|
||||
$opponent = stadionzeitung_opponent_display($issue);
|
||||
|
||||
// Live-Daten nur laden, wenn die Ausgabe tatsächlich eine Live-Seite enthält.
|
||||
$hasLive = false;
|
||||
|
||||
103
app/helpers.php
@@ -992,6 +992,22 @@ function stadionzeitung_teaser(array $issue): string
|
||||
return trim((string) ($issue['interview']['teaser'] ?? ''));
|
||||
}
|
||||
|
||||
/**
|
||||
* Der Name des Gegners, wie er GEDRUCKT wird — Cover, Archivzeile, Kopf, Meta.
|
||||
*
|
||||
* `opponent` muss die BFV-Schreibweise tragen, weil die Gegnerseite damit ihre
|
||||
* Tabellenzeile und ihre Begegnung in matchcenter.json findet (exakter
|
||||
* Namensvergleich). Bei Spielgemeinschaften ist das eine Zeile wie
|
||||
* „(SG1) TSV Wirsberg I/ FC Kupferberg I", die auf einem Cover nichts zu
|
||||
* suchen hat. `opponent_short` ist deshalb der im Chat gepflegte Anzeigename
|
||||
* („Wirsberg/Kupferberg"); fehlt er, bleibt es beim vollen Namen.
|
||||
*/
|
||||
function stadionzeitung_opponent_display(array $issue): string
|
||||
{
|
||||
$short = trim((string) ($issue['opponent_short'] ?? ''));
|
||||
return $short !== '' ? $short : trim((string) ($issue['opponent'] ?? ''));
|
||||
}
|
||||
|
||||
/**
|
||||
* Welche Mannschaften bekommen in einer Ausgabe eine Gegnerseite — die EINE
|
||||
* Logik dafür, benutzt von bin/stadionzeitung-add.php (Seitenplanung) UND
|
||||
@@ -999,10 +1015,19 @@ function stadionzeitung_teaser(array $issue): string
|
||||
* oder Daten ohne Seite entstehen.
|
||||
*
|
||||
* Immer: die tragende Mannschaft (Gegner = `opponent`, Tag = `date`).
|
||||
* Zusätzlich, wenn die Ausgabe eine `veranstaltung` (Slug) mit Zeitraum trägt
|
||||
* (Sportfest-Ausgabe): jede weitere Mannschaft aus matchcenter.json mit einem
|
||||
* HEIMspiel in diesem Zeitraum — drei Heimspiele am Fest, drei Gegnerseiten.
|
||||
* Der Gegner ist dann der andere Verein der Begegnung. Reihenfolge wie in
|
||||
* Zusätzlich auf zwei Wegen, die sich nicht in die Quere kommen:
|
||||
*
|
||||
* 1. `veranstaltung` (Slug) mit Zeitraum — die Sportfest-Ausgabe: jede weitere
|
||||
* Mannschaft aus matchcenter.json mit einem HEIMspiel in diesem Zeitraum.
|
||||
* Am Fest spielen alle zuhause, das ist der Aufhänger.
|
||||
* 2. `gegner_teams` (Liste von Team-Keys, im Chat gepflegt) — für ein normales
|
||||
* Spielwochenende, an dem auch die anderen Mannschaften antreten. Genommen
|
||||
* wird ihr nächstes Spiel im Fenster von zwei Tagen vor bis drei Tage nach
|
||||
* dem Ausgabedatum, AUCH auswärts: der Gegner der Frauen ist auch dann eine
|
||||
* Seite wert, wenn wir zu ihm fahren. Ohne Spiel in diesem Fenster entsteht
|
||||
* keine Seite; bin/stadionzeitung-add.php meldet das.
|
||||
*
|
||||
* Der Gegner ist jeweils der andere Verein der Begegnung. Reihenfolge wie in
|
||||
* matchcenter.json (= config 'matchcenter.teams').
|
||||
*
|
||||
* Rückgabe: [team_key => ['opponent' => string, 'date' => 'YYYY-MM-DD']]
|
||||
@@ -1013,14 +1038,19 @@ function stadionzeitung_gegner_fixtures(array $issue): array
|
||||
$issueTeam = (string) ($issue['team_key'] ?? '');
|
||||
$issueOpponent = trim((string) ($issue['opponent'] ?? ''));
|
||||
|
||||
$von = '';
|
||||
$bis = '';
|
||||
$eventVon = '';
|
||||
$eventBis = '';
|
||||
$veranstaltung = veranstaltung_find((string) ($issue['veranstaltung'] ?? ''));
|
||||
if ($veranstaltung !== null) {
|
||||
$von = (string) ($veranstaltung['date_start'] ?? '');
|
||||
$bis = (string) ($veranstaltung['date_end'] ?? $von);
|
||||
$eventVon = (string) ($veranstaltung['date_start'] ?? '');
|
||||
$eventBis = (string) ($veranstaltung['date_end'] ?? $eventVon);
|
||||
}
|
||||
|
||||
$extraTeams = array_values(array_filter(array_map(
|
||||
static fn ($k): string => trim((string) $k),
|
||||
is_array($issue['gegner_teams'] ?? null) ? $issue['gegner_teams'] : []
|
||||
)));
|
||||
|
||||
$fixtures = [];
|
||||
foreach (json_load('matchcenter')['teams'] ?? [] as $team) {
|
||||
$key = (string) ($team['key'] ?? '');
|
||||
@@ -1033,18 +1063,32 @@ function stadionzeitung_gegner_fixtures(array $issue): array
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Weg 2: ausdrücklich benannte Mannschaft, Fenster ums Ausgabedatum,
|
||||
// Heim wie auswärts. Steht sie in `gegner_teams`, gilt dieses Fenster
|
||||
// und nicht der Veranstaltungszeitraum.
|
||||
if (in_array($key, $extraTeams, true) && $date !== '') {
|
||||
$von = date('Y-m-d', strtotime($date . ' -2 days'));
|
||||
$bis = date('Y-m-d', strtotime($date . ' +3 days'));
|
||||
$nurHeim = false;
|
||||
} else {
|
||||
$von = $eventVon;
|
||||
$bis = $eventBis;
|
||||
$nurHeim = true;
|
||||
}
|
||||
if ($von === '') {
|
||||
continue;
|
||||
}
|
||||
foreach ($team['next_matches'] ?? [] as $match) {
|
||||
if (empty($match['is_home'])) {
|
||||
$istHeim = !empty($match['is_home']);
|
||||
if ($nurHeim && !$istHeim) {
|
||||
continue;
|
||||
}
|
||||
$matchDate = substr((string) ($match['kickoff'] ?? ''), 0, 10);
|
||||
if ($matchDate < $von || $matchDate > $bis) {
|
||||
continue;
|
||||
}
|
||||
$opponent = trim((string) ($match['away'] ?? ''));
|
||||
$opponent = trim((string) ($istHeim ? ($match['away'] ?? '') : ($match['home'] ?? '')));
|
||||
if ($opponent === '' || $opponent === 'SPIELFREI') {
|
||||
continue;
|
||||
}
|
||||
@@ -1140,14 +1184,53 @@ function stadionzeitung_build_snapshot(array $issue): array
|
||||
}
|
||||
}
|
||||
|
||||
// `opponent` behält die BFV-Schreibweise (der Namensvergleich oben
|
||||
// hängt daran), gedruckt wird `opponent_display`: bei der tragenden
|
||||
// Mannschaft der Kurzname der Ausgabe, sonst der volle Name.
|
||||
$gegnerDisplay = strcasecmp($gegnerName, trim((string) ($issue['opponent'] ?? ''))) === 0
|
||||
? stadionzeitung_opponent_display($issue)
|
||||
: $gegnerName;
|
||||
|
||||
// Tabellenausschnitt statt zweier loser Platz-Ziffern im Kopf: ein
|
||||
// Fenster um beide Mannschaften herum (mit einer Zeile Luft davor
|
||||
// und dahinter). Liegen sie weit auseinander, werden es zwei
|
||||
// Blöcke — gerendert wird beides mit der geteilten
|
||||
// league-table-Komponente, nie mit einer zweiten Tabelle.
|
||||
$ausschnitt = [];
|
||||
if ($ownRow !== null && $opponentRow !== null && $table !== []) {
|
||||
$ranks = [(int) ($ownRow['rank'] ?? 0), (int) ($opponentRow['rank'] ?? 0)];
|
||||
sort($ranks);
|
||||
$fenster = static function (int $von, int $bis) use ($table): array {
|
||||
return array_values(array_filter($table, static function (array $row) use ($von, $bis): bool {
|
||||
$rank = (int) ($row['rank'] ?? 0);
|
||||
return $rank >= $von && $rank <= $bis;
|
||||
}));
|
||||
};
|
||||
if ($ranks[1] - $ranks[0] <= 5) {
|
||||
$block = $fenster($ranks[0], $ranks[1]);
|
||||
if ($block !== []) {
|
||||
$ausschnitt[] = $block;
|
||||
}
|
||||
} else {
|
||||
foreach ($ranks as $rank) {
|
||||
$block = $fenster($rank, $rank + 1);
|
||||
if ($block !== []) {
|
||||
$ausschnitt[] = $block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$gegner[$key] = [
|
||||
'team_name' => (string) ($team['name'] ?? ''),
|
||||
'opponent' => $gegnerName,
|
||||
'opponent_display' => $gegnerDisplay,
|
||||
'league' => (string) ($team['league'] ?? ''),
|
||||
'season' => (string) ($team['season'] ?? ''),
|
||||
'fixture' => $fixture,
|
||||
'own' => $ownRow,
|
||||
'opponent_stats' => $opponentRow,
|
||||
'table_excerpt' => $ausschnitt,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -78,14 +78,14 @@ $firstImage = $issue['images'][0] ?? null;
|
||||
$cover = ($firstImage !== null && ($firstImage['type'] ?? 'image') === 'image') ? $firstImage : null;
|
||||
|
||||
$meta = [
|
||||
'title' => 'Stadionzeitung gegen ' . $issue['opponent'] . ($isDruck ? ' (Druckfassung)' : ''),
|
||||
'description' => 'Stadionzeitung zum Heimspiel gegen ' . $issue['opponent'] . ' am ' . german_date($issue['date']) . ' – digital zum Durchblättern.',
|
||||
'title' => 'Stadionzeitung gegen ' . stadionzeitung_opponent_display($issue) . ($isDruck ? ' (Druckfassung)' : ''),
|
||||
'description' => 'Stadionzeitung zum Heimspiel gegen ' . stadionzeitung_opponent_display($issue) . ' am ' . german_date($issue['date']) . ' – digital zum Durchblättern.',
|
||||
'scripts' => [$isDruck ? 'stadionzeitung-druck.js' : 'stadionzeitung-viewer.js'],
|
||||
'schema' => page_schema([
|
||||
['name' => 'Startseite', 'slug' => ''],
|
||||
['name' => 'Fußball', 'slug' => 'fussball'],
|
||||
['name' => 'Stadionzeitung', 'slug' => 'stadionzeitung'],
|
||||
['name' => 'Gegen ' . $issue['opponent'], 'slug' => 'stadionzeitung/' . $issue['slug']],
|
||||
['name' => 'Gegen ' . stadionzeitung_opponent_display($issue), 'slug' => 'stadionzeitung/' . $issue['slug']],
|
||||
]),
|
||||
];
|
||||
if ($cover !== null) {
|
||||
@@ -113,7 +113,7 @@ $druckBlaetter = (int) ceil($druckSeiten / 4);
|
||||
<a class="stadionzeitung-issue-head__back" href="<?= e($isDruck ? url('stadionzeitung/' . $issue['slug']) : url('stadionzeitung')) ?>">
|
||||
<?= icon('chevron-left') ?> <?= $isDruck ? 'Ausgabe' : 'Archiv' ?>
|
||||
</a>
|
||||
<p class="stadionzeitung-issue-head__title">Gegen <?= e($issue['opponent']) ?></p>
|
||||
<p class="stadionzeitung-issue-head__title">Gegen <?= e(stadionzeitung_opponent_display($issue)) ?></p>
|
||||
<?php if ($isDruck): ?>
|
||||
<p class="stadionzeitung-issue-head__actions">
|
||||
<button class="btn btn--sm stadionzeitung-issue-head__print" type="button" data-druck-print hidden>
|
||||
|
||||
@@ -202,6 +202,11 @@ $oldAufruf = $oldIssue['aufruf'] ?? null;
|
||||
// Turnierpläne, Gegnerseiten je Heimspiel) und Cover-Kennung — chat-gepflegt.
|
||||
$oldVeranstaltung = $oldIssue['veranstaltung'] ?? null;
|
||||
$oldCover = $oldIssue['cover'] ?? null;
|
||||
// Anzeigename des Gegners fürs Cover und die Liste ("Wirsberg/Kupferberg" statt
|
||||
// der BFV-Zeile) und die Liste der Mannschaften, die zusätzlich eine
|
||||
// Gegnerseite bekommen — beides Chat-Pflege, überlebt erneute Läufe wie vorwort.
|
||||
$oldOpponentShort = $oldIssue['opponent_short'] ?? null;
|
||||
$oldGegnerTeams = is_array($oldIssue['gegner_teams'] ?? null) ? array_values($oldIssue['gegner_teams']) : null;
|
||||
$veranstaltung = null;
|
||||
if (is_string($oldVeranstaltung) && $oldVeranstaltung !== '') {
|
||||
$veranstaltung = veranstaltung_find($oldVeranstaltung);
|
||||
@@ -376,13 +381,22 @@ try {
|
||||
// dieselbe Funktion, aus der stadionzeitung_build_snapshot() die Daten baut,
|
||||
// damit nie eine Seite ohne Daten oder Daten ohne Seite entstehen.
|
||||
$gegnerSeiten = [];
|
||||
foreach (stadionzeitung_gegner_fixtures([
|
||||
$gegnerFixtures = stadionzeitung_gegner_fixtures([
|
||||
'date' => $date, 'team_key' => $teamKey, 'opponent' => $opponent,
|
||||
'veranstaltung' => $oldVeranstaltung,
|
||||
]) as $gegnerTeam => $fixture) {
|
||||
'veranstaltung' => $oldVeranstaltung, 'gegner_teams' => $oldGegnerTeams ?? [],
|
||||
]);
|
||||
foreach ($gegnerFixtures as $gegnerTeam => $fixture) {
|
||||
$gegnerSeiten[] = $live('gegner', ['team' => (string) $gegnerTeam]);
|
||||
$log("Gegnerseite {$gegnerTeam}: {$fixture['opponent']} ({$fixture['date']}).");
|
||||
}
|
||||
// Eine benannte Mannschaft ohne Spiel im Fenster bekommt keine Seite. Das ist
|
||||
// richtig so, darf aber nicht stillschweigend passieren: ein Tippfehler im
|
||||
// Team-Key sähe genauso aus wie ein spielfreies Wochenende.
|
||||
foreach ($oldGegnerTeams ?? [] as $gewuenscht) {
|
||||
if (!isset($gegnerFixtures[(string) $gewuenscht])) {
|
||||
$log("gegner_teams: '{$gewuenscht}' hat kein Spiel im Fenster um {$date} (oder der Team-Key ist falsch) — keine Gegnerseite.", 'WARN');
|
||||
}
|
||||
}
|
||||
if ($gegnerSeiten === []) {
|
||||
// Ohne Treffer (Gegner leer) bleibt die Seite der tragenden Mannschaft —
|
||||
// sie meldet dann selbst, dass keine Vergleichsdaten vorliegen.
|
||||
@@ -425,7 +439,7 @@ try {
|
||||
if ($rueckseite !== null) {
|
||||
$bloecke[] = [
|
||||
'name' => 'rueckseite',
|
||||
'seiten' => [$bild($rueckseite, 'rueckseite', "Rückseite der Stadionzeitung gegen {$opponent}")],
|
||||
'seiten' => [$bild($rueckseite, 'rueckseite', "Rückseite der Stadionzeitung gegen " . stadionzeitung_opponent_display(['opponent' => $opponent, 'opponent_short' => $oldOpponentShort]))],
|
||||
'anzeigen_danach' => false,
|
||||
];
|
||||
}
|
||||
@@ -734,6 +748,8 @@ if ($oldIssue !== null && ($oldIssue['status'] ?? '') === 'veroeffentlicht') {
|
||||
$issues[] = [
|
||||
'slug' => $slug,
|
||||
'opponent' => $opponent,
|
||||
'opponent_short' => $oldOpponentShort,
|
||||
'gegner_teams' => $oldGegnerTeams,
|
||||
'date' => $date,
|
||||
'team_key' => $teamKey,
|
||||
'status' => 'entwurf',
|
||||
|
||||
@@ -1,5 +1,520 @@
|
||||
{
|
||||
"issues": [
|
||||
{
|
||||
"slug": "2026-09-19-sg-wirsberg-kupferberg",
|
||||
"opponent": "(SG1) TSV Wirsberg I/ FC Kupferberg I",
|
||||
"opponent_short": "Wirsberg/Kupferberg",
|
||||
"gegner_teams": [
|
||||
"zweite-mannschaft",
|
||||
"damen"
|
||||
],
|
||||
"date": "2026-09-19",
|
||||
"team_key": "erste-mannschaft",
|
||||
"status": "entwurf",
|
||||
"pages": 44,
|
||||
"player_image": {
|
||||
"base": "img/stadionzeitung/2026-09-19-sg-wirsberg-kupferberg/spieler",
|
||||
"widths": [
|
||||
320,
|
||||
640,
|
||||
1000
|
||||
],
|
||||
"ext": "png",
|
||||
"alt": ""
|
||||
},
|
||||
"qr_image": "img/stadionzeitung/2026-09-19-sg-wirsberg-kupferberg/qr.png",
|
||||
"vorwort": {
|
||||
"heading": "Herzlich willkommen im Katzbachtal",
|
||||
"paragraphs": [
|
||||
"Liebe Fußballfreunde,",
|
||||
"herzlich willkommen im Katzbachtal. Ein besonderer Gruß gilt dem Schiedsrichtergespann und unseren Gästen von der SG Wirsberg/Kupferberg.",
|
||||
"Das 0:2 in Trebgast war ein Rückschlag. Die letzten beiden Heimspiele haben wir aber gewonnen, und an diese Auftritte wollen wir heute gegen den Spitzenreiter anknüpfen.",
|
||||
"Und es bleibt ein volles Wochenende: Um 16 Uhr spielt unsere Zweite gegen Leuchau II, am Sonntag fahren unsere Frauen als Tabellenführer nach Weidenberg. Darauf freuen wir uns. Auf geht's!"
|
||||
],
|
||||
"closing": "Rot-schwarze Grüße",
|
||||
"signee_name": "Benedikt Höfner",
|
||||
"signee_role": "Sportlicher Leiter"
|
||||
},
|
||||
"interview": {
|
||||
"teaser": "Unser Trainer Ali Kilic über die Niederlage in Trebgast und den heutigen Gegner",
|
||||
"heading": "Zwei Fragen an Ali Kilic",
|
||||
"person_name": "Ali Kilic",
|
||||
"person_role": "Trainer 1. Mannschaft",
|
||||
"intro": null,
|
||||
"fragen": [
|
||||
{
|
||||
"frage": "Ali, in Trebgast hat es mit 0:2 nicht geklappt. Wie hast du das Spiel gesehen?",
|
||||
"antwort": "Der Sieg für Trebgast war grundsätzlich verdient. Wir sind früh in Rückstand geraten, und das hat ihnen bei dem regnerischen Wetter und den schwierigen Verhältnissen in die Karten gespielt. Gerade in unserem Ballbesitzspiel hatten wir zu viele einfache Fehler in der Annahme und der Mitnahme des Balls. Nach der Halbzeitpause hatten wir zwar eine gute Drangphase, aber ohne echte Durchschlagskraft und ohne klare Chancen."
|
||||
},
|
||||
{
|
||||
"frage": "Heute kommt der Spitzenreiter mit sieben Siegen aus acht Spielen. Was erwartest du?",
|
||||
"antwort": "Wirsberg hat sich mit teilweise starken Spielern verstärkt und steht nicht unerwartet oben in der Tabelle. Wir rechnen damit, dass sie sich anders als Trebgast nicht so tief hinten reinstellen, sondern aktiver sind. Darauf müssen wir uns vorbereiten und gerade in der Defensivarbeit wieder konzentriert sein. Nach vorne bekommen wir dafür vielleicht mehr Räume, die wir trotz einiger Ausfälle nutzen wollen."
|
||||
}
|
||||
],
|
||||
"photo": "img/persons/ali-kilic.jpg"
|
||||
},
|
||||
"aufruf": null,
|
||||
"veranstaltung": null,
|
||||
"cover": null,
|
||||
"verfasser_photo": {
|
||||
"base": "img/stadionzeitung/2026-09-19-sg-wirsberg-kupferberg/verfasser",
|
||||
"widths": [
|
||||
120,
|
||||
222
|
||||
],
|
||||
"alt": ""
|
||||
},
|
||||
"termine_snapshot": [
|
||||
{
|
||||
"date": "2026-09-20",
|
||||
"date_end": null,
|
||||
"title": "(SG) SV Weidenberg/TSV Bayreuth-St. Johannis 2 – TSV 08 Kulmbach",
|
||||
"department": "fussball",
|
||||
"type": "spiel",
|
||||
"meta": "Auswärtsspiel · Frauen KL Ost",
|
||||
"href": "/matchcenter",
|
||||
"kickoff": "2026-09-20T13:00",
|
||||
"team_name": "Frauenmannschaft",
|
||||
"league": "Frauen KL Ost",
|
||||
"raw": {
|
||||
"kickoff": "2026-09-20T13:00",
|
||||
"date_display": "So, 20.09.",
|
||||
"time_display": "13:00 Uhr",
|
||||
"competition": "Liga",
|
||||
"home": "(SG) SV Weidenberg/TSV Bayreuth-St. Johannis 2",
|
||||
"away": "TSV 08 Kulmbach",
|
||||
"home_crest": "img/crests/00ES8GNK4O000013VV0AG08LVUPGND5I.png",
|
||||
"away_crest": "img/crests/00ES8GNK3G000012VV0AG08LVUPGND5I.png",
|
||||
"is_home": false,
|
||||
"team_key": "damen",
|
||||
"team_name": "Frauenmannschaft"
|
||||
}
|
||||
},
|
||||
{
|
||||
"date": "2026-09-27",
|
||||
"date_end": null,
|
||||
"title": "TSV 08 Kulmbach – (SG) SpVgg Döbra/FC Konradsreuth/ATS Selbitz",
|
||||
"department": "fussball",
|
||||
"type": "spiel",
|
||||
"meta": "Heimspiel · Frauen KL Ost",
|
||||
"href": "/matchcenter",
|
||||
"kickoff": "2026-09-27T10:30",
|
||||
"team_name": "Frauenmannschaft",
|
||||
"league": "Frauen KL Ost",
|
||||
"raw": {
|
||||
"kickoff": "2026-09-27T10:30",
|
||||
"date_display": "So, 27.09.",
|
||||
"time_display": "10:30 Uhr",
|
||||
"competition": "Liga",
|
||||
"home": "TSV 08 Kulmbach",
|
||||
"away": "(SG) SpVgg Döbra/FC Konradsreuth/ATS Selbitz",
|
||||
"home_crest": "img/crests/00ES8GNK3G000012VV0AG08LVUPGND5I.png",
|
||||
"away_crest": "img/crests/00ES8GNK8G00000IVV0AG08LVUPGND5I.png",
|
||||
"is_home": true,
|
||||
"team_key": "damen",
|
||||
"team_name": "Frauenmannschaft"
|
||||
}
|
||||
},
|
||||
{
|
||||
"date": "2026-09-27",
|
||||
"date_end": null,
|
||||
"title": "1. FC Kirchleus – TSV 08 Kulmbach",
|
||||
"department": "fussball",
|
||||
"type": "spiel",
|
||||
"meta": "Auswärtsspiel · Kreisklasse",
|
||||
"href": "/matchcenter",
|
||||
"kickoff": "2026-09-27T14:00",
|
||||
"team_name": "1. Mannschaft",
|
||||
"league": "Kreisklasse",
|
||||
"raw": {
|
||||
"kickoff": "2026-09-27T14:00",
|
||||
"date_display": "So, 27.09.",
|
||||
"time_display": "14:00 Uhr",
|
||||
"competition": "Liga",
|
||||
"home": "1. FC Kirchleus",
|
||||
"away": "TSV 08 Kulmbach",
|
||||
"home_crest": "img/crests/00ES8GNK3G00000RVV0AG08LVUPGND5I.png",
|
||||
"away_crest": "img/crests/00ES8GNK3G000012VV0AG08LVUPGND5I.png",
|
||||
"is_home": false,
|
||||
"team_key": "erste-mannschaft",
|
||||
"team_name": "1. Mannschaft"
|
||||
}
|
||||
},
|
||||
{
|
||||
"date": "2027-02-20",
|
||||
"date_end": null,
|
||||
"title": "Tagesskifahrt 2027",
|
||||
"department": "verein",
|
||||
"type": "event",
|
||||
"meta": "Skigebiet Hochzillertal",
|
||||
"href": "/veranstaltungen/tagesskifahrt-2027",
|
||||
"time": "",
|
||||
"location": "Skigebiet Hochzillertal",
|
||||
"raw": {
|
||||
"slug": "tagesskifahrt-2027",
|
||||
"title": "Tagesskifahrt 2027",
|
||||
"date_start": "2027-02-20",
|
||||
"date_end": null,
|
||||
"time": "",
|
||||
"location": "Skigebiet Hochzillertal",
|
||||
"department": "verein",
|
||||
"status": "veroeffentlicht",
|
||||
"text": "Wir fahren für einen Tag zum Skifahren ins Skigebiet Hochzillertal. Die Plätze sind auf 40 Personen begrenzt, angemeldet wird bei Fabian Früh.",
|
||||
"ankuendigung": [
|
||||
"Einmal im Winter machen wir uns gemeinsam auf und fahren für einen Tag ins Skigebiet Hochzillertal bei Kaltenbach. Ob Erwachsene, Jugendliche oder Kinder: Auf den Pisten ist für alle etwas dabei. Die Fahrt ist auf 40 Personen begrenzt, wer dabei sein möchte, meldet sich am besten früh.",
|
||||
"Erwachsene zahlen 115 Euro, Jugendliche 95 Euro und Kinder 70 Euro. Anmelden könnt ihr euch bei Fabian Früh unter 0160 97516797."
|
||||
],
|
||||
"rueckblick": null,
|
||||
"karte": "",
|
||||
"anfahrt": [],
|
||||
"plakate": [
|
||||
{
|
||||
"base": "img/veranstaltungen/tagesskifahrt-2027/plakat-01",
|
||||
"widths": [
|
||||
640,
|
||||
1000,
|
||||
1024
|
||||
],
|
||||
"alt": "Plakat zu unserer Tagesskifahrt am Samstag, 20. Februar 2027 ins Skigebiet Hochzillertal, mit den Preisen für Erwachsene, Jugendliche und Kinder und der Anmeldung bei Fabian Früh.",
|
||||
"source": "1-ankuendigung.jpeg"
|
||||
}
|
||||
],
|
||||
"galerie": []
|
||||
}
|
||||
}
|
||||
],
|
||||
"images": [
|
||||
{
|
||||
"type": "live",
|
||||
"page": "cover"
|
||||
},
|
||||
{
|
||||
"type": "live",
|
||||
"page": "vorwort"
|
||||
},
|
||||
{
|
||||
"type": "live",
|
||||
"page": "interview"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"base": "img/anzeigen/eldorado",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1440
|
||||
],
|
||||
"alt": "Anzeige: eldorado Radsporttechnik Kulmbach"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"base": "img/anzeigen/egu",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1440
|
||||
],
|
||||
"alt": "Anzeige: Erfrischungsgetränke-Union Kulmbacher Gruppe GmbH"
|
||||
},
|
||||
{
|
||||
"type": "live",
|
||||
"page": "ergebnisse"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"base": "img/anzeigen/hofmann-graef",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1440
|
||||
],
|
||||
"alt": "Anzeige: Buchhandlung Hofmann, Kulmbach, und Automobilwerkstatt Gräf, Thurnau"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"base": "img/anzeigen/muench-richterstegner",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1440
|
||||
],
|
||||
"alt": "Anzeige: Planungsbüro Münch und Richter & Stegner Steuerungstechnik"
|
||||
},
|
||||
{
|
||||
"type": "live",
|
||||
"page": "gegner",
|
||||
"team": "erste-mannschaft"
|
||||
},
|
||||
{
|
||||
"type": "live",
|
||||
"page": "gegner",
|
||||
"team": "zweite-mannschaft"
|
||||
},
|
||||
{
|
||||
"type": "live",
|
||||
"page": "gegner",
|
||||
"team": "damen"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"base": "img/anzeigen/malteser-herrmann",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1440
|
||||
],
|
||||
"alt": "Anzeige: Malteser-Hilfsdienst und Schlosserei Herrmann, Kulmbach"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"base": "img/anzeigen/apotheken-wenkel",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1440
|
||||
],
|
||||
"alt": "Anzeige: Apotheke im Fritz, Stadtpark Apotheke und Schlüsseldienst Wenkel, Kulmbach"
|
||||
},
|
||||
{
|
||||
"type": "live",
|
||||
"page": "tabelle",
|
||||
"team": "erste-mannschaft"
|
||||
},
|
||||
{
|
||||
"type": "live",
|
||||
"page": "tabelle",
|
||||
"team": "zweite-mannschaft"
|
||||
},
|
||||
{
|
||||
"type": "live",
|
||||
"page": "tabelle",
|
||||
"team": "damen"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"base": "img/anzeigen/karl-geyer",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1440
|
||||
],
|
||||
"alt": "Anzeige: Geyer Farbe + Raum, Kulmbach, Starthilfe Boden"
|
||||
},
|
||||
{
|
||||
"type": "live",
|
||||
"page": "vorschau"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"base": "img/anzeigen/gsb",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1440
|
||||
],
|
||||
"alt": "Anzeige: GSB Security und GSB Gebäude Service, Bindlach"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"base": "img/anzeigen/physiofit-wohlfart",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1440
|
||||
],
|
||||
"alt": "Anzeige: Physio Fit Neudrossenfeld und Textilpflege Wohlfart, Kulmbach"
|
||||
},
|
||||
{
|
||||
"type": "live",
|
||||
"page": "termine"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"base": "img/anzeigen/sport2000-pizza",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1440
|
||||
],
|
||||
"alt": "Anzeige: Sport 2000 Downstairs und Kulmbacher Pizza-Service"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"base": "img/anzeigen/schulz-csu",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1440
|
||||
],
|
||||
"alt": "Anzeige: Schreinerei Schulz, Mainleus, und CSU Stadtverband Kulmbach"
|
||||
},
|
||||
{
|
||||
"type": "live",
|
||||
"page": "news"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"base": "img/anzeigen/mattis-ka2",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1440
|
||||
],
|
||||
"alt": "Anzeige: Karl Mattis Flaschnerei und KA2 Fitness, Kulmbach"
|
||||
},
|
||||
{
|
||||
"type": "live",
|
||||
"page": "kontakt"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"base": "img/anzeigen/motor-nuetzel",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1440
|
||||
],
|
||||
"alt": "Anzeige: Motor-Nützel Vertriebs-GmbH, Bayreuth"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"base": "img/anzeigen/vereinskarte-edeka",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1410
|
||||
],
|
||||
"alt": "Eigenanzeige: So funktioniert die Vereinskarte beim E center Seidl Kulmbach"
|
||||
},
|
||||
{
|
||||
"type": "live",
|
||||
"page": "mitglied"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"base": "img/anzeigen/trapper-verkehrsakademie",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1440
|
||||
],
|
||||
"alt": "Anzeige: Trapper GmbH Entsorgungsfachbetrieb und Verkehrsakademie, Kulmbach"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"base": "img/anzeigen/ohnemueller-dippold",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1440
|
||||
],
|
||||
"alt": "Anzeige: Gaststätte und Metzgerei Ohne-Müller, Kulmbach-Weiher, und Bäckerei Dippold, Melkendorf"
|
||||
},
|
||||
{
|
||||
"type": "live",
|
||||
"page": "historie"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"base": "img/anzeigen/hanft",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1440
|
||||
],
|
||||
"alt": "Anzeige: Hanft Bürotechnik GmbH, Kulmbach"
|
||||
},
|
||||
{
|
||||
"type": "live",
|
||||
"page": "sportheim"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"base": "img/anzeigen/elma-kleinheinz",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1440
|
||||
],
|
||||
"alt": "Anzeige: elma GmbH Bayreuth und Metzgerei Kleinheinz, Kulmbach"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"base": "img/anzeigen/stadionzeitung-digital",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1440
|
||||
],
|
||||
"alt": "Eigenanzeige: Unsere Stadionzeitung gibt es jetzt auch online, mit QR-Code zum Scannen"
|
||||
},
|
||||
{
|
||||
"type": "live",
|
||||
"page": "partner"
|
||||
},
|
||||
{
|
||||
"type": "live",
|
||||
"page": "danke",
|
||||
"anzeige": {
|
||||
"base": "img/anzeigen/emons",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1141
|
||||
],
|
||||
"alt": "Anzeige: Emons Spedition Himmelkron, Ihr Partner für nationale und internationale Transporte"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"base": "img/anzeigen/gagel-pickelmann",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1440
|
||||
],
|
||||
"alt": "Anzeige: Gagel Bäder und Mineralölhandel Pickelmann"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"base": "img/anzeigen/schramm",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1440
|
||||
],
|
||||
"alt": "Anzeige: Landgasthof und Metzgerei Schramm, Forstlahm"
|
||||
},
|
||||
{
|
||||
"type": "live",
|
||||
"page": "momente"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"base": "img/anzeigen/tagesskifahrt-2027",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1440
|
||||
],
|
||||
"alt": "Eigenanzeige: Unsere Tagesskifahrt ins Hochzillertal am 20. Februar 2027"
|
||||
},
|
||||
{
|
||||
"type": "live",
|
||||
"page": "impressum"
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"base": "img/stadionzeitung/2026-09-19-sg-wirsberg-kupferberg/rueckseite",
|
||||
"widths": [
|
||||
480,
|
||||
960,
|
||||
1410
|
||||
],
|
||||
"alt": "Rückseite der Stadionzeitung gegen Wirsberg/Kupferberg"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"slug": "2026-09-04-ats-wartenfels",
|
||||
"opponent": "ATS Wartenfels",
|
||||
|
||||
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 589 B |
|
After Width: | Height: | Size: 398 KiB |
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 222 KiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 227 KiB |
|
After Width: | Height: | Size: 840 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 440 B After Width: | Height: | Size: 426 B |
|
Before Width: | Height: | Size: 431 B After Width: | Height: | Size: 419 B |
|
Before Width: | Height: | Size: 431 B After Width: | Height: | Size: 432 B |
|
Before Width: | Height: | Size: 503 B After Width: | Height: | Size: 488 B |
|
Before Width: | Height: | Size: 421 B After Width: | Height: | Size: 422 B |
|
Before Width: | Height: | Size: 497 B After Width: | Height: | Size: 500 B |
|
Before Width: | Height: | Size: 496 B After Width: | Height: | Size: 506 B |
|
Before Width: | Height: | Size: 426 B After Width: | Height: | Size: 427 B |