eis-website/app/app.py

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)