Compare commits
3 Commits
be19c0ec83
...
b2f03b6cfb
| Author | SHA1 | Date | |
|---|---|---|---|
| b2f03b6cfb | |||
| 3457705be5 | |||
| 3f66ba877e |
+69
-45
@@ -5,30 +5,12 @@ article_pipeline.py — Stage 0: Input-Preparation für den BSN-Artikel-Workflow
|
||||
Liest Topic, PDFs, URLs und baut einen strukturierten Prompt für den Hermes-Agenten,
|
||||
der dann via delegate_task Research (Stage 1) und Write+QC (Stage 2+3) durchführt.
|
||||
Stage 4 (Git, Verify) macht der Agent selbst.
|
||||
|
||||
Usage:
|
||||
# Thema + PDF
|
||||
python3 article_pipeline.py --topic "Gamegenic × TCC" --pdf pm.pdf --rubric "Nachrichten"
|
||||
|
||||
# Thema + URL
|
||||
python3 article_pipeline.py --topic "Neue Kennerspiel-Nominierungen" --url "https://..."
|
||||
|
||||
# Nur Thema (autonome Recherche)
|
||||
python3 article_pipeline.py --topic "Spiel des Jahres 2026" --rubric "Nachrichten"
|
||||
|
||||
# Batch (JSON)
|
||||
python3 article_pipeline.py --batch topics.json
|
||||
|
||||
Output: Strukturierter Prompt nach stdout (wird vom Hermes-Cronjob als Context injiziert)
|
||||
Exit-Codes: 0 = Prompt bereit, 1 = Fehler in Stage 0
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import tempfile
|
||||
from datetime import datetime
|
||||
|
||||
WORKSPACE = "/home/hermes/workspace"
|
||||
@@ -46,23 +28,6 @@ def ocr_pdf(pdf_path: str) -> str:
|
||||
return "\n\n".join(texts)
|
||||
|
||||
|
||||
def extract_url_text(url: str) -> str:
|
||||
"""URL-Inhalt via 5-Stufen-Eskalation abrufen."""
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
|
||||
# Stufe 1: curl direkt
|
||||
try:
|
||||
req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
|
||||
with urllib.request.urlopen(req, timeout=15) as resp:
|
||||
return resp.read().decode("utf-8", errors="ignore")[:5000]
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Stufe 2-5 wäre hier — für Stage 0 reicht Stufe 1
|
||||
return f"[URL nicht direkt abrufbar: {url}]"
|
||||
|
||||
|
||||
def build_prompt(topic: str, sources: list[str], rubric: str,
|
||||
category_id: int, image_urls: list[str],
|
||||
deadline: str | None,
|
||||
@@ -72,7 +37,48 @@ def build_prompt(topic: str, sources: list[str], rubric: str,
|
||||
now = datetime.now()
|
||||
date_str = now.strftime("%d. %B %Y")
|
||||
slug = topic.lower().replace(" ", "_").replace(":", "").replace("×", "x")[:40]
|
||||
date_slug = now.strftime("%Y-%m-%d")
|
||||
filename = f"artikel_{slug}_{date_slug}.html"
|
||||
|
||||
# --- WRITE+QC CONTEXT (most complex part) ---
|
||||
write_context = (
|
||||
"STRUKTUR (exakt einhalten, nummeriert):\n"
|
||||
"1. <h1>TITEL</h1>\n"
|
||||
'2. DACHZEILE: <div style="font-size:1.1rem;color:#555;margin-bottom:1.5rem;'
|
||||
'border-bottom:2px solid #e0e0e0;padding-bottom:1rem;">'
|
||||
'Zusammenfassung in 1-2 Sätzen</div>\n'
|
||||
'3. <p class="meta" style="font-size:0.85rem;color:#888;margin-bottom:2rem;">'
|
||||
'DATUM · Lesezeit: ca. N Minuten</p>\n'
|
||||
'4. Einleitungs-Absatz <p>\n'
|
||||
'5. INFOBOX (PFLICHT bei Unternehmen/Produkt-News): '
|
||||
'<div style="background:#f0f4f8;border:1px solid #d0d8e0;border-radius:6px;'
|
||||
'padding:1.2rem 1.5rem;margin:2rem 0;">'
|
||||
'<h3 style="margin-top:0;color:#20228A;font-family:Arial,sans-serif;font-size:1.15rem;">'
|
||||
'NAME — Fakten</h3><table style="width:100%;border-collapse:collapse;">'
|
||||
'<tr><td style="padding:0.3rem 0.5rem;font-weight:bold;color:#444;width:160px;">'
|
||||
'Label</td><td style="padding:0.3rem 0.5rem;">Wert</td></tr></table></div>\n'
|
||||
'6. ALLE Inhalts-Abschnitte (<h2> + <p>)\n'
|
||||
'7. <hr id="system-readmore" /> <-- NACH allen Inhalten, VOR Quellen!\n'
|
||||
'8. Quellen-Überschrift: <span style="font-size:1.17em;font-weight:bold;'
|
||||
'display:block;margin:1em 0;"><strong>Quellen</strong></span>\n'
|
||||
'9. JEDE Quelle als: <li><a href="URL" target="_blank" rel="noopener" '
|
||||
'style="color:#0075FF;">Name</a> — Beschreibung</li>\n'
|
||||
'10. <p class="qc"><!-- QC: Quelle1=AAA|URL1, Quelle2=AA|URL2 --></p>\n'
|
||||
'11. <p style="margin-top:2.5rem;padding-top:1rem;border-top:1px solid #ddd;'
|
||||
'font-size:0.9rem;color:#777;"><em>Recherchestand: DATUM. '
|
||||
'Basierend auf QUELLEN.</em></p>\n'
|
||||
'\n'
|
||||
'KRITISCHE REGELN (QC-Fail bei Verstoß):\n'
|
||||
'- Read-More NACH allen Inhalten, VOR Quellen (NICHT nach Absatz 1!)\n'
|
||||
'- JEDE Quelle als <a href> mit target="_blank" — KEINE unverlinkten Quellen!\n'
|
||||
'- Dachzeile + Infobox sind PFLICHT\n'
|
||||
'- Quellen-Überschrift: font-size:1.17em (NICHT 0.9rem)\n'
|
||||
'- Kein "XML API v2", kein "Betriebsgeheimnis", keine Emojis\n'
|
||||
'- Datei endet mit </html>\n'
|
||||
f'- Rubrik: {rubric}'
|
||||
)
|
||||
|
||||
# --- BUILD OUTPUT ---
|
||||
lines = []
|
||||
lines.append(f"Führe den BSN-Artikel-Workflow für folgendes Thema aus:")
|
||||
lines.append(f"**Thema:** {topic}")
|
||||
@@ -80,7 +86,7 @@ def build_prompt(topic: str, sources: list[str], rubric: str,
|
||||
lines.append(f"**Rubrik:** {rubric} (Joomla catid={category_id})")
|
||||
if deadline:
|
||||
lines.append(f"**Deadline:** {deadline}")
|
||||
lines.append(f"**Dateiname:** artikel_{slug}_{now.strftime('%Y-%m-%d')}.html")
|
||||
lines.append(f"**Dateiname:** {filename}")
|
||||
lines.append("")
|
||||
|
||||
# PDF-OCR-Ergebnisse
|
||||
@@ -106,11 +112,24 @@ def build_prompt(topic: str, sources: list[str], rubric: str,
|
||||
lines.append("")
|
||||
lines.append("Nutze **delegate_task** um einen Research-Subagent zu starten:")
|
||||
lines.append("")
|
||||
lines.append(f"- goal: \"Recherchiere zum Thema: {topic}. Sammle Fakten aus allen Quellen, bewerte sie (AAA/AA/A), ergänze BGG-Daten (Designer, Verlag, Jahr). Erstelle Research-Brief in /tmp/research_brief.md. Bei unvollständigen Kern-Fakten → Exit 1.\"")
|
||||
lines.append("- context: Enthält PDF-Texte und URLs (siehe oben). Nutze 5-Stufen-Eskalation für unerreichbare URLs. web_search site:boardgamegeek.com für BGG-Daten.")
|
||||
lines.append(
|
||||
f'- goal: "Recherchiere zum Thema: {topic}. '
|
||||
f'Sammle Fakten aus allen Quellen, bewerte sie (AAA/AA/A), '
|
||||
f'ergänze BGG-Daten (Designer, Verlag, Jahr). '
|
||||
f'Erstelle Research-Brief in /tmp/research_brief.md. '
|
||||
f'Bei unvollständigen Kern-Fakten → Exit 1."'
|
||||
)
|
||||
lines.append(
|
||||
'- context: "Enthält PDF-Texte und URLs (siehe oben). '
|
||||
'Nutze 5-Stufen-Eskalation für unerreichbare URLs. '
|
||||
'web_search site:boardgamegeek.com für BGG-Daten."'
|
||||
)
|
||||
lines.append('- toolsets: ["web", "terminal", "file", "search", "skills"]')
|
||||
lines.append("")
|
||||
lines.append("**WICHTIG:** Warte bis Sub-Agent #1 fertig ist. Prüfe /tmp/research_brief.md. Bei Exit-Code 1 → MELDUNG an Basti, NICHT fortfahren.")
|
||||
lines.append(
|
||||
"**WICHTIG:** Warte bis Sub-Agent #1 fertig ist. "
|
||||
"Prüfe /tmp/research_brief.md. Bei Exit-Code 1 → MELDUNG an Basti, NICHT fortfahren."
|
||||
)
|
||||
lines.append("")
|
||||
|
||||
# STAGE 2+3: Write+QC
|
||||
@@ -118,8 +137,15 @@ def build_prompt(topic: str, sources: list[str], rubric: str,
|
||||
lines.append("")
|
||||
lines.append("Nutze **delegate_task** für einen Write+QC-Subagent:")
|
||||
lines.append("")
|
||||
lines.append(f'- goal: "Schreibe HTML-Artikel zum Thema: {topic}. Nutze Research-Brief aus /tmp/research_brief.md. Datei: artikel_{slug}_{now.strftime("%Y-%m-%d")}.html in /home/hermes/workspace/. Danach: bash /home/hermes/workspace/verify_article.sh artikel_{slug}_{now.strftime("%Y-%m-%d")}.html. Bei Fehlern korrigieren, max 3 Versuche."')
|
||||
lines.append(f'- context: "HTML-Regeln: KEIN XML API v2, KEIN Betriebsgeheimnis, KEINE Emojis. <p class=\\"meta\\"> mit Datum+Lesezeit. Genau 1× <hr id=\\"system-readmore\\" />. Quellen als <span><strong>Quellen</strong></span> + <ol> mit <a target=\\"_blank\\">. <p class=\\"qc\\"> mit Quellen-Ratings. Datei endet mit </html>. Rubrik: {rubric}."')
|
||||
lines.append(
|
||||
f'- goal: "Schreibe HTML-Artikel zum Thema: {topic}. '
|
||||
f'Nutze Research-Brief aus /tmp/research_brief.md. '
|
||||
f'Datei: /home/hermes/workspace/{filename}. '
|
||||
f'Danach: bash /home/hermes/workspace/verify_article.sh '
|
||||
f'/home/hermes/workspace/{filename}. '
|
||||
f'Bei Fehlern korrigieren, max 3 Versuche."'
|
||||
)
|
||||
lines.append(f'- context: """\n{write_context}\n"""')
|
||||
lines.append('- toolsets: ["web", "terminal", "file", "search", "skills"]')
|
||||
lines.append("")
|
||||
lines.append("**WICHTIG:** Warte bis Sub-Agent #2 fertig. Prüfe Exit-Code und Datei.")
|
||||
@@ -129,15 +155,13 @@ def build_prompt(topic: str, sources: list[str], rubric: str,
|
||||
lines.append("## STAGE 4: Deliver")
|
||||
lines.append("")
|
||||
lines.append("1. Git-Commit:")
|
||||
lines.append(f" ```bash")
|
||||
lines.append(f" cd /home/hermes/workspace && git add artikel_{slug}_{now.strftime('%Y-%m-%d')}.html")
|
||||
lines.append(f" cd /home/hermes/workspace && git add {filename}")
|
||||
lines.append(f' git commit -m "artikel: {topic[:50]}"')
|
||||
lines.append(f" ```")
|
||||
lines.append("2. Prüfen ob Article-Server erreichbar:")
|
||||
lines.append(" curl -s 'http://185.162.249.159:8890/?key=br3ttsp1el-n3ws-2026' | head -3")
|
||||
lines.append("3. Basti benachrichtigen per send_message (Telegram):")
|
||||
lines.append(f" ✅ Artikel fertig: {topic}")
|
||||
lines.append(f" 📄 /home/hermes/workspace/artikel_{slug}_{now.strftime('%Y-%m-%d')}.html")
|
||||
lines.append(f" 📄 /home/hermes/workspace/{filename}")
|
||||
lines.append(" 📊 verify_article.sh: 0 Fehler")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="description" content="Chivalry (BGG 472579) ist das neue Kennerspiel von Erfolgsdesigner Dávid Turczi im Artus-Universum. Alle Fakten zum 2026 erscheinenden Strategiespiel für 1–4 Personen von dlp games und Game's Up.">
|
||||
<title>Chivalry: Dávid Turczi entführt mit dlp games in die Welt von König Artus</title>
|
||||
</head>
|
||||
<body>
|
||||
<article>
|
||||
|
||||
<h1>Chivalry: Dávid Turczi entführt mit dlp games in die Welt von König Artus</h1>
|
||||
|
||||
<div style="font-size:1.1rem;color:#555;margin-bottom:1.5rem;border-bottom:2px solid #e0e0e0;padding-bottom:1rem;">Chivalry (BGG 472579) ist das neue Kennerspiel von Erfolgsdesigner Dávid Turczi. Das 2026 erscheinende Strategiespiel für 1–4 Personen verbindet Area Majority, Deck-Building und Worker Placement im mythologischen Camelot-Universum.</div>
|
||||
|
||||
<p class="meta" style="font-size:0.85rem;color:#888;margin-bottom:2rem;">23. Juni 2026 · Lesezeit: ca. 5 Minuten</p>
|
||||
|
||||
<p>Dávid Turczi gehört zu den produktivsten und gefragtesten Brettspiel-Designern der letzten Jahre. Nach Hits wie <em>Anachrony</em>, <em>Imperium</em> und <em>Tiletum</em> wendet er sich nun dem vielleicht klassischsten aller Fantasy-Settings zu: der Tafelrunde von König Artus. <strong>Chivalry</strong> (engl. für „Ritterlichkeit") erscheint 2026 beim deutschen Verlag <strong>dlp games</strong> (Reiner Stockhausen) in Kooperation mit <strong>Game's Up</strong> (Ralph Bienert, Ingolstadt) — ein Kennerspiel, das taktische Tiefe mit thematischer Dichte verbindet.</p>
|
||||
|
||||
<div style="background:#f0f4f8;border:1px solid #d0d8e0;border-radius:6px;padding:1.2rem 1.5rem;margin:2rem 0;">
|
||||
<h3 style="margin-top:0;color:#20228A;font-family:Arial,sans-serif;font-size:1.15rem;">Chivalry — Fakten</h3>
|
||||
<table style="width:100%;border-collapse:collapse;">
|
||||
<tr><td style="padding:0.3rem 0.5rem;font-weight:bold;color:#444;width:160px;">Designer</td><td style="padding:0.3rem 0.5rem;">Dávid Turczi</td></tr>
|
||||
<tr><td style="padding:0.3rem 0.5rem;font-weight:bold;color:#444;">Verlag</td><td style="padding:0.3rem 0.5rem;">dlp games (Reiner Stockhausen) / Game's Up (Ralph Bienert)</td></tr>
|
||||
<tr><td style="padding:0.3rem 0.5rem;font-weight:bold;color:#444;">Grafik</td><td style="padding:0.3rem 0.5rem;">Fiore GmbH</td></tr>
|
||||
<tr><td style="padding:0.3rem 0.5rem;font-weight:bold;color:#444;">Redaktion</td><td style="padding:0.3rem 0.5rem;">Ralph Bienert, Florian Kumschier</td></tr>
|
||||
<tr><td style="padding:0.3rem 0.5rem;font-weight:bold;color:#444;">Erscheinungsjahr</td><td style="padding:0.3rem 0.5rem;">2026</td></tr>
|
||||
<tr><td style="padding:0.3rem 0.5rem;font-weight:bold;color:#444;">Spielerzahl</td><td style="padding:0.3rem 0.5rem;">1–4</td></tr>
|
||||
<tr><td style="padding:0.3rem 0.5rem;font-weight:bold;color:#444;">Altersempfehlung</td><td style="padding:0.3rem 0.5rem;">ab 12 Jahren</td></tr>
|
||||
<tr><td style="padding:0.3rem 0.5rem;font-weight:bold;color:#444;">Spieldauer</td><td style="padding:0.3rem 0.5rem;">45–120 Minuten</td></tr>
|
||||
<tr><td style="padding:0.3rem 0.5rem;font-weight:bold;color:#444;">Mechaniken</td><td style="padding:0.3rem 0.5rem;">Area Majority / Influence, Deck/Bag/Pool Building, Variable Player Powers, Worker Placement mit verschiedenen Arbeitertypen</td></tr>
|
||||
<tr><td style="padding:0.3rem 0.5rem;font-weight:bold;color:#444;">Kategorien</td><td style="padding:0.3rem 0.5rem;">Mittelalter, Mythologie</td></tr>
|
||||
<tr><td style="padding:0.3rem 0.5rem;font-weight:bold;color:#444;">BGG-Rating</td><td style="padding:0.3rem 0.5rem;">Keine Bewertungen (Neuerscheinung)</td></tr>
|
||||
<tr><td style="padding:0.3rem 0.5rem;font-weight:bold;color:#444;">Versionen</td><td style="padding:0.3rem 0.5rem;">Englische Edition, Deutsche Edition</td></tr>
|
||||
<tr><td style="padding:0.3rem 0.5rem;font-weight:bold;color:#444;">BGG-ID</td><td style="padding:0.3rem 0.5rem;"><a href="https://web.archive.org/web/20260621090044/https://boardgamegeek.com/boardgame/472579/chivalry" target="_blank" rel="noopener" style="color:#0075FF;">472579</a></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h2>Von Merlin und Morgana: Das Spielprinzip</h2>
|
||||
|
||||
<p>Chivalry entführt die Spieler an den Hof von König Artus. Jeder übernimmt die Rolle eines ehrgeizigen Ritters, der mit seinem Gefolge durch die Lande zieht, um Ruhm, Einfluss und Ehre zu erlangen. Jede Runde repräsentiert einen vollständigen Tag im Leben der Ritter — von der Morgendämmerung bis zum abendlichen Festmahl in Camelot.</p>
|
||||
|
||||
<p>Der Tagesablauf gliedert sich in drei Phasen: Bei <strong>Tagesanbruch</strong> reiten die Ritter aus zu Marktstädten, Landstrichen, Häfen oder direkt nach Camelot. <strong>Tagsüber</strong> führen sie Aktionen aus, die von den besuchten Orten abhängen — je nachdem, welche Fähigkeiten ihr Gefolge bereitstellt. Bei <strong>Einbruch der Dämmerung</strong> schlagen sie ihr Lager auf, rufen ihr Gefolge zurück und nehmen — sofern geladen — am Festmahl in Camelot teil.</p>
|
||||
|
||||
<p>Das Herzstück des Spiels sind die <strong>Gefolgsleute (Retainers)</strong>. Durch geschicktes Platzieren auf dem eigenen Spielertableau erhalten die Spieler temporäre Fertigkeiten für mehr Bewegung, mächtigere Ortsaktionen und die Erfüllung von Quests und Begegnungen. Ein zentrales Spannungselement ist das <strong>Aufziehen der Siegel von Merlin und Morgana</strong> — zwei konkurrierende Mächte, die das Schicksal jeder Region prägen und bestimmen, welche Taten bei der Regionswertung den meisten Ruhm einbringen.</p>
|
||||
|
||||
<h2>Mechanische Tiefe: Mehr als nur ein Ritter-Spiel</h2>
|
||||
|
||||
<p>Die BGG-klassifizierten Mechaniken deuten auf ein anspruchsvolles Kennerspiel hin: <strong>Area Majority</strong> für die Kontrolle der Landstriche, <strong>Deck-, Bag- und Pool-Building</strong> für den Ausbau des eigenen Gefolges, <strong>Variable Player Powers</strong> für asymmetrische Startbedingungen und <strong>Worker Placement mit verschiedenen Arbeitertypen</strong> für die Aktionsauswahl. Diese Kombination erinnert an Spiele wie <em>Anachrony</em> oder <em>Tiletum</em>, in denen Turczi bereits bewies, wie er mehrere Mechaniken zu einem stimmigen Ganzen verwebt.</p>
|
||||
|
||||
<p>Zusätzlich können Ritter <strong>verborgene Runen</strong> entdecken, die <strong>Patronage von Mitgliedern des Hofes von Camelot</strong> gewinnen und sogar eine <strong>Audienz bei König Artus</strong> ersuchen — narrative Elemente, die das Artus-Thema über reine Mechanik hinaus mit Leben füllen. Mit einer Spieldauer von 45 bis 120 Minuten und einem Solo-Modus (ohne namentlich gelisteten Solo-Designer, vermutlich von Turczi selbst implementiert) richtet sich Chivalry an Vielspieler, die abendfüllende Strategie schätzen.</p>
|
||||
|
||||
<h2>Dávid Turczi: Der Mann hinter der Tafelrunde</h2>
|
||||
|
||||
<p>Dávid Turczi ist einer der meistbeschäftigten Designer der Branche. Der gebürtige Ungar hat sich vor allem mit Solo-Modi und komplexen Eurogames einen Namen gemacht. Seine bekanntesten Werke umfassen:</p>
|
||||
|
||||
<p><strong>Anachrony</strong> (2017, mit Richard Amann und Viktor Peter) — ein zeitreisendes Worker-Placement-Epos, das auf BGG einen Weight-Wert von 4,04 erreicht und zu den höchstbewerteten Strategiespielen zählt.<br>
|
||||
<strong>Imperium</strong> (2021, mit Nigel Buckle) — ein innovatives Deck-Building-Civ-Spiel, das Turczis Gespür für elegante Mechaniken-Integration zeigt.<br>
|
||||
<strong>Tiletum</strong> (2022, mit Simone Luciani) — ein Würfel-Action-Selection-Spiel in der Renaissance, das Turczis Vielseitigkeit unter Beweis stellt.</p>
|
||||
|
||||
<p>Mit Chivalry wendet sich Turczi nun einem stark thematisch geprägten Setting zu. Die Kooperation mit dlp games ist neu — bislang erschienen Turczis Spiele vor allem bei Mindclash Games, Osprey Games und Board&Dice. Dass mit Game's Up ein zweiter, noch junger Verlag aus Ingolstadt an Bord ist (Ralph Bienert fungiert sowohl als Co-Verleger als auch als Redakteur), spricht für eine bewusst deutsche Entwicklungs-Pipeline mit internationaler Ausrichtung — das Spiel erscheint parallel auf Englisch und Deutsch.</p>
|
||||
|
||||
<h2>Ausblick: Was wir über Chivalry noch nicht wissen</h2>
|
||||
|
||||
<p>Als <strong>Upcoming Release 2026</strong> befindet sich Chivalry noch in einer frühen Phase. Auf BoardGameGeek verzeichnet das Spiel erst 296 Views, 7 Wishlist-Einträge und 8 Fans — Zahlen, die für eine Neuankündigung ohne begleitende Marketingkampagne typisch sind. Es gibt noch keine Bewertungen, kein Weight-Voting und keine redaktionellen Previews.</p>
|
||||
|
||||
<p>Offene Fragen bleiben: Wann genau erscheint das Spiel? Welche Komponenten enthält die Box — Miniaturen, Karten, ein modulares Spielbrett? Wird es eine Crowdfunding-Kampagne geben oder erscheint Chivalry direkt im Handel? Der UVP steht noch aus, ebenso Informationen zu möglichen Erweiterungen.</p>
|
||||
|
||||
<p>Für Fans von Turczis bisherigem Werk und Liebhaber des Artus-Stoffes lohnt sich ein genauer Blick auf Chivalry. Die Mechaniken-Kombination aus Area Majority, Deck-Building und variablem Worker Placement verspricht ein eigenständiges Spielerlebnis, das sich von anderen Camelot-Titeln wie <em>Tainted Grail</em> oder <em>Shadows over Camelot</em> abhebt. Sobald erste Preview-Exemplare die Runde machen, werden wir berichten.</p>
|
||||
|
||||
<hr id="system-readmore" />
|
||||
|
||||
<span style="font-size:1.17em;font-weight:bold;display:block;margin:1em 0;"><strong>Quellen</strong></span>
|
||||
|
||||
<ol>
|
||||
<li><a href="https://web.archive.org/web/20260621090044/https://boardgamegeek.com/boardgame/472579/chivalry" target="_blank" rel="noopener" style="color:#0075FF;">BoardGameGeek: Chivalry (2026)</a> — Offizielle BGG-Datenbank mit allen Kern-Metadaten, Mechaniken und Publisher-Beschreibung. Abgerufen am 21.06.2026.</li>
|
||||
<li><a href="https://web.archive.org/web/2025/https://boardgamegeek.com/boardgamepublisher/10848/dlp-games" target="_blank" rel="noopener" style="color:#0075FF;">BoardGameGeek: Verlagseintrag dlp games</a> — Primärquelle, bestätigt dlp games (Reiner Stockhausen) als Publisher von Chivalry.</li>
|
||||
<li><a href="https://web.archive.org/web/2025/https://boardgamegeek.com/boardgamepublisher/33525/games-up" target="_blank" rel="noopener" style="color:#0075FF;">BoardGameGeek: Verlagseintrag Game's Up</a> — Etablierte Quelle zum Co-Verlag (Ralph Bienert, Ingolstadt).</li>
|
||||
<li><a href="https://web.archive.org/web/2025/https://games-up.de/" target="_blank" rel="noopener" style="color:#0075FF;">Game's Up — Offizielle Website</a> — Website des Co-Verlags, ergänzende Informationen zu Chivalry.</li>
|
||||
</ol>
|
||||
|
||||
<p style="margin-top:2.5rem;padding-top:1rem;border-top:1px solid #ddd;font-size:0.9rem;color:#777;"><em>Recherchestand: 23. Juni 2026. Basierend auf BoardGameGeek-Einträgen und Verlagsinformationen. Chivalry befindet sich als Upcoming Release 2026 noch vor der Markteinführung — Previews und Rezensionen liegen noch nicht vor.</em></p>
|
||||
|
||||
<p class="qc"><!-- QC: Quelle1=AAA|https://web.archive.org/web/20260621090044/https://boardgamegeek.com/boardgame/472579/chivalry, Quelle2=AAA|https://web.archive.org/web/2025/https://boardgamegeek.com/boardgamepublisher/10848/dlp-games, Quelle3=AA|https://web.archive.org/web/2025/https://boardgamegeek.com/boardgamepublisher/33525/games-up, Quelle4=A|https://web.archive.org/web/2025/https://games-up.de/ --></p>
|
||||
|
||||
</article>
|
||||
</body>
|
||||
</html>
|
||||
@@ -141,6 +141,54 @@ else
|
||||
fail "Kein Quellen-Block gefunden (h2/span>Quellen fehlt)"
|
||||
fi
|
||||
|
||||
# ── CHECK 14: Dachzeile vorhanden (div unter h1 mit border-bottom) ──
|
||||
if echo "$BODY" | grep -qP '<div style="[^"]*border-bottom:2px solid #e0e0e0[^"]*"'; then
|
||||
ok "Dachzeile vorhanden"
|
||||
else
|
||||
fail "Dachzeile fehlt (grauer Div-Balken unter h1)"
|
||||
fi
|
||||
|
||||
# ── CHECK 15: Infobox vorhanden (f0f4f8 Hintergrund) ─────────────────
|
||||
if echo "$BODY" | grep -q 'background:#f0f4f8'; then
|
||||
ok "Infobox vorhanden"
|
||||
else
|
||||
fail "Infobox fehlt (Fakten-Tabelle mit #f0f4f8 Hintergrund)"
|
||||
fi
|
||||
|
||||
# ── CHECK 16: Read-More NACH allen h2 (Position prüfen) ──────────────
|
||||
READMORE_LINE=$(grep -n 'system-readmore' "$FILE" | head -1 | cut -d: -f1)
|
||||
LAST_H2_LINE=$(grep -n '<h2>' "$FILE" | tail -1 | cut -d: -f1 || echo "0")
|
||||
if [ "$LAST_H2_LINE" = "0" ]; then
|
||||
warn "Keine <h2> im Artikel — Read-More-Position nicht prüfbar"
|
||||
elif [ "$READMORE_LINE" -gt "$LAST_H2_LINE" ]; then
|
||||
ok "Read-More NACH allen h2 (Zeile $READMORE_LINE > $LAST_H2_LINE)"
|
||||
else
|
||||
fail "Read-More VOR letztem h2 (Zeile $READMORE_LINE < $LAST_H2_LINE). Joomla schneidet Inhalte ab!"
|
||||
fi
|
||||
|
||||
# ── CHECK 17: JEDE Quelle im Quellen-Block hat <a href> ─────────────
|
||||
# Extrahiere Quellen-Block (nach "Quellen" bis </ol>)
|
||||
SRC_START=$(grep -n 'Quellen' "$FILE" | tail -1 | cut -d: -f1 || echo "")
|
||||
if [ -n "$SRC_START" ]; then
|
||||
SRC_LI=$(sed -n "$SRC_START,\$p" "$FILE" | grep -c '<li>' || true)
|
||||
SRC_LINKED=$(sed -n "$SRC_START,\$p" "$FILE" | grep -c '<li>.*<a href=' || true)
|
||||
if [ "$SRC_LI" -eq 0 ]; then
|
||||
fail "Keine <li> im Quellen-Block"
|
||||
elif [ "$SRC_LI" != "$SRC_LINKED" ]; then
|
||||
UNLINKED=$((SRC_LI - SRC_LINKED))
|
||||
fail "$UNLINKED von $SRC_LI Quellen ohne <a href> Link"
|
||||
else
|
||||
ok "Alle $SRC_LI Quellen verlinkt"
|
||||
fi
|
||||
fi
|
||||
|
||||
# ── CHECK 18: Recherchestand-Zeile vorhanden ─────────────────────────
|
||||
if echo "$BODY" | grep -q 'Recherchestand:'; then
|
||||
ok "Recherchestand-Zeile vorhanden"
|
||||
else
|
||||
fail "Recherchestand-Zeile fehlt"
|
||||
fi
|
||||
|
||||
# ── SUMMARY ─────────────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "═══════════════════════════════════════"
|
||||
|
||||
Reference in New Issue
Block a user