170 lines
No EOL
5.3 KiB
Python
170 lines
No EOL
5.3 KiB
Python
from flask import Flask, request, session, redirect
|
|
import html
|
|
import sqlite3
|
|
from pathlib import Path
|
|
|
|
app = Flask(__name__)
|
|
app.secret_key = "hier-eigenen-geheimen-text" # für session nötig
|
|
DB_PATH = Path(__file__).with_name("adventure.db")
|
|
|
|
|
|
def get_db():
|
|
db = sqlite3.connect(DB_PATH)
|
|
db.row_factory = sqlite3.Row
|
|
return db
|
|
|
|
|
|
BASE_CSS = """... (unverändert, deine bestehende CSS bleibt) ..."""
|
|
BASE_JS = """... (unverändert) ..."""
|
|
|
|
|
|
def render_page(title, body_html):
|
|
return f"""<!doctype html>
|
|
<html lang=\"de\">
|
|
<head>
|
|
<meta charset=\"utf-8\">
|
|
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">
|
|
<title>{html.escape(title)}</title>
|
|
<style>{BASE_CSS}</style>
|
|
</head>
|
|
<body>
|
|
<main class=\"shell\">
|
|
<section class=\"card\">
|
|
{body_html}
|
|
</section>
|
|
</main>
|
|
<script>{BASE_JS}</script>
|
|
</body>
|
|
</html>"""
|
|
|
|
|
|
@app.route("/", methods=["GET", "POST"])
|
|
@app.route("/app", methods=["GET", "POST"])
|
|
@app.route("/app/", methods=["GET", "POST"])
|
|
def start():
|
|
if request.method == "POST":
|
|
name = request.form.get("name", "").strip()
|
|
if name != "":
|
|
session["spieler"] = name
|
|
db = get_db()
|
|
db.execute(
|
|
"INSERT OR IGNORE INTO spielstand (spieler, raum_id) VALUES (?, 1)",
|
|
(name,)
|
|
)
|
|
db.commit()
|
|
db.close()
|
|
return redirect("/app/raum/1")
|
|
|
|
db = get_db()
|
|
anzahl = db.execute("SELECT COUNT(*) AS n FROM spielstand").fetchone()
|
|
|
|
weiterspielen_html = ""
|
|
if "spieler" in session:
|
|
s = db.execute(
|
|
"SELECT raum_id FROM spielstand WHERE spieler=?",
|
|
(session["spieler"],)
|
|
).fetchone()
|
|
if s:
|
|
weiterspielen_html = f"""
|
|
<p>Willkommen zurück, {html.escape(session['spieler'])}!</p>
|
|
<div class="actions">
|
|
<a class="btn" href="/app/raum/{s['raum_id']}">Weiterspielen</a>
|
|
<a class="btn secondary" href="/app/reset">Neues Abenteuer</a>
|
|
</div>
|
|
<hr>
|
|
"""
|
|
db.close()
|
|
|
|
body = f"""
|
|
<h1>Verlassenes Raumschiff</h1>
|
|
<p>Du bist der einzige Überlebende an Bord. Erkunde das Schiff und aktiviere das Notsignal.</p>
|
|
{weiterspielen_html}
|
|
<form method="post">
|
|
<input name="name" placeholder="Dein Name" autocomplete="off">
|
|
<button type="submit">Abenteuer starten</button>
|
|
</form>
|
|
<p><small>{anzahl['n']} Abenteurer waren schon hier.</small></p>
|
|
"""
|
|
return render_page("Verlassenes Raumschiff", body)
|
|
|
|
|
|
@app.route("/raum/<int:id>", methods=["GET", "POST"])
|
|
@app.route("/app/raum/<int:id>", methods=["GET", "POST"])
|
|
def raum(id):
|
|
db = get_db()
|
|
|
|
# Spielstand fortschreiben, sobald jemand angemeldet ist
|
|
if "spieler" in session:
|
|
db.execute(
|
|
"UPDATE spielstand SET raum_id=? WHERE spieler=?",
|
|
(id, session["spieler"])
|
|
)
|
|
db.commit()
|
|
|
|
r = db.execute("SELECT * FROM raeume WHERE id=?", (id,)).fetchone()
|
|
if not r:
|
|
db.close()
|
|
return render_page(
|
|
"Raum nicht gefunden",
|
|
'<h1>Raum nicht gefunden</h1><p>Der angeforderte Raum existiert nicht.</p>'
|
|
'<div class="actions"><a class="btn secondary" href="/app/">Zurück zum Start</a></div>'
|
|
)
|
|
|
|
unterwegs_html = ""
|
|
if "spieler" in session:
|
|
unterwegs_html = f'<p><small>Unterwegs als: {html.escape(session["spieler"])}</small></p>'
|
|
|
|
if r["raetsel_frage"]:
|
|
if request.method == "POST":
|
|
if request.form.get("antwort", "").strip() == r["raetsel_antwort"]:
|
|
db.close()
|
|
return render_page(
|
|
"Notsignal aktiviert",
|
|
'<h1>Notsignal erfolgreich aktiviert</h1><p>Rettung ist unterwegs.</p>'
|
|
'<div class="actions"><a class="btn" href="/app/">Zurück zum Start</a></div>'
|
|
)
|
|
db.close()
|
|
return render_page(
|
|
"Falscher Code",
|
|
'<h1>Falscher Code</h1><p>Der KI-Kern reagiert nicht.</p>'
|
|
'<div class="actions"><a class="btn secondary" href="/app/raum/' + str(id) + '">nochmal versuchen</a></div>'
|
|
)
|
|
|
|
db.close()
|
|
body = f"""
|
|
<h1>{html.escape(r['name'])}</h1>
|
|
<p>{html.escape(r['beschreibung'])}</p>
|
|
{unterwegs_html}
|
|
<form method="post">
|
|
<input id="antwort" name="antwort" placeholder="Antwort eingeben" autocomplete="off">
|
|
<button type="submit">OK</button>
|
|
</form>
|
|
"""
|
|
return render_page(html.escape(r["name"]), body)
|
|
|
|
ausgaenge = db.execute(
|
|
"SELECT richtung, nach_raum FROM ausgaenge WHERE von_raum=?", (id,)
|
|
).fetchall()
|
|
db.close()
|
|
|
|
body = f"""
|
|
<h1>{html.escape(r['name'])}</h1>
|
|
<p>{html.escape(r['beschreibung'])}</p>
|
|
{unterwegs_html}
|
|
<div class="links">
|
|
"""
|
|
for a in ausgaenge:
|
|
body += f'<a class="btn secondary" href="/app/raum/{a["nach_raum"]}">{html.escape(a["richtung"])}</a>'
|
|
body += "</div>"
|
|
return render_page(html.escape(r["name"]), body)
|
|
|
|
|
|
@app.route("/reset")
|
|
@app.route("/app/reset")
|
|
def reset():
|
|
session.pop("spieler", None) # Session vergessen (DB bleibt!)
|
|
return redirect("/app/")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
app.run(host="0.0.0.0", port=9004) |