239 lines
7.4 KiB
Python
239 lines
7.4 KiB
Python
from flask import Blueprint, jsonify, render_template, request
|
|
|
|
from . import db
|
|
from .game import (
|
|
_game_date, compare, daily_target, existing_daily_session, finish_session,
|
|
get_max_attempts, get_or_create_player, get_streaks, is_correct, random_target,
|
|
)
|
|
from .models import Movie, Player, Session
|
|
|
|
bp = Blueprint("main", __name__)
|
|
|
|
|
|
# ---------- Seiten ----------
|
|
|
|
@bp.route("/")
|
|
def index():
|
|
return render_template("index.html", mode="daily")
|
|
|
|
|
|
@bp.route("/unlimited")
|
|
def unlimited():
|
|
return render_template("index.html", mode="unlimited")
|
|
|
|
|
|
# ---------- API ----------
|
|
|
|
@bp.route("/api/player", methods=["POST"])
|
|
def api_player():
|
|
data = request.get_json(silent=True) or {}
|
|
nickname = (data.get("nickname") or "").strip()
|
|
if not nickname:
|
|
return jsonify({"error": "nickname required"}), 400
|
|
player = get_or_create_player(nickname)
|
|
return jsonify({
|
|
"player": {"id": player.id, "nickname": player.nickname},
|
|
"streaks": get_streaks(player.id),
|
|
})
|
|
|
|
|
|
@bp.route("/api/search")
|
|
def api_search():
|
|
from difflib import SequenceMatcher
|
|
|
|
q = (request.args.get("q") or "").strip().lower()
|
|
if not q:
|
|
return jsonify([])
|
|
movies = Movie.query.filter(Movie.title.ilike(f"%{q}%")).limit(50).all()
|
|
results = []
|
|
for m in movies:
|
|
score = SequenceMatcher(None, q, m.title.lower()).ratio()
|
|
# Substring-Treffer gelten bereits als starke Uebereinstimmung
|
|
if q in m.title.lower():
|
|
score = max(score, 0.6)
|
|
if score >= 0.6:
|
|
results.append((score, m))
|
|
results.sort(key=lambda x: x[1].year, reverse=True)
|
|
results.sort(key=lambda x: x[0], reverse=True)
|
|
return jsonify([
|
|
{"id": m.id, "title": m.title, "year": m.year}
|
|
for _, m in results[:10]
|
|
])
|
|
|
|
|
|
@bp.route("/api/start", methods=["POST"])
|
|
def api_start():
|
|
data = request.get_json(silent=True) or {}
|
|
player_id = data.get("player_id")
|
|
mode = data.get("mode", "daily")
|
|
if not player_id:
|
|
return jsonify({"error": "player_id required"}), 400
|
|
if Player.query.get(player_id) is None:
|
|
return jsonify({"error": "player not found"}), 404
|
|
if mode not in ("daily", "unlimited"):
|
|
return jsonify({"error": "invalid mode"}), 400
|
|
|
|
max_attempts = get_max_attempts()
|
|
|
|
if mode == "daily":
|
|
game_date = _game_date()
|
|
target = daily_target(game_date)
|
|
# Bereits heute gespielt?
|
|
existing = existing_daily_session(player_id, game_date)
|
|
if existing and existing.status != "in_progress":
|
|
return jsonify({
|
|
"session_id": existing.id,
|
|
"mode": mode,
|
|
"max_attempts": max_attempts,
|
|
"status": existing.status,
|
|
"already_played": True,
|
|
"target": _movie_public(target),
|
|
"attempts_used": existing.attempts_used,
|
|
})
|
|
# In-progress Rueckgabe, sonst neue Runde
|
|
if existing:
|
|
return jsonify({
|
|
"session_id": existing.id,
|
|
"mode": mode,
|
|
"max_attempts": max_attempts,
|
|
"status": existing.status,
|
|
"already_played": False,
|
|
"attempts_used": existing.attempts_used,
|
|
})
|
|
session = Session(
|
|
player_id=player_id, mode=mode, target_movie_id=target.id,
|
|
status="in_progress", attempts_used=0, date=game_date,
|
|
)
|
|
db.session.add(session)
|
|
db.session.commit()
|
|
return jsonify({
|
|
"session_id": session.id,
|
|
"mode": mode,
|
|
"max_attempts": max_attempts,
|
|
"status": "in_progress",
|
|
"already_played": False,
|
|
"attempts_used": 0,
|
|
})
|
|
|
|
# Unbegrenzt: neue Zufallsrunde
|
|
target = random_target()
|
|
if target is None:
|
|
return jsonify({"error": "no movies"}), 500
|
|
session = Session(
|
|
player_id=player_id, mode="unlimited", target_movie_id=target.id,
|
|
status="in_progress", attempts_used=0,
|
|
)
|
|
db.session.add(session)
|
|
db.session.commit()
|
|
return jsonify({
|
|
"session_id": session.id,
|
|
"mode": mode,
|
|
"max_attempts": max_attempts,
|
|
"status": "in_progress",
|
|
"already_played": False,
|
|
"attempts_used": 0,
|
|
})
|
|
|
|
|
|
@bp.route("/api/guess", methods=["POST"])
|
|
def api_guess():
|
|
data = request.get_json(silent=True) or {}
|
|
session_id = data.get("session_id")
|
|
movie_id = data.get("movie_id")
|
|
if not session_id or not movie_id:
|
|
return jsonify({"error": "session_id and movie_id required"}), 400
|
|
|
|
session = Session.query.get(session_id)
|
|
if session is None:
|
|
return jsonify({"error": "session not found"}), 404
|
|
if session.status != "in_progress":
|
|
return jsonify({"error": "session already finished", "status": session.status}), 409
|
|
|
|
guess = Movie.query.get(movie_id)
|
|
if guess is None:
|
|
return jsonify({"error": "movie not found"}), 404
|
|
|
|
target = Movie.query.get(session.target_movie_id)
|
|
max_attempts = get_max_attempts()
|
|
|
|
compared = compare(guess, target)
|
|
session.attempts_used += 1
|
|
used = session.attempts_used
|
|
finished = False
|
|
status = "in_progress"
|
|
won = False
|
|
|
|
if is_correct(compared):
|
|
finish_session(session, True)
|
|
finished = True
|
|
won = True
|
|
status = "won"
|
|
elif used >= max_attempts:
|
|
finish_session(session, False)
|
|
finished = True
|
|
won = False
|
|
status = "lost"
|
|
|
|
response = {
|
|
"session_id": session.id,
|
|
"attempts_used": used,
|
|
"max_attempts": max_attempts,
|
|
"status": status,
|
|
"finished": finished,
|
|
"won": won,
|
|
"row": compared,
|
|
}
|
|
if finished:
|
|
response["target"] = _movie_public(target)
|
|
response["streaks"] = get_streaks(session.player_id)
|
|
return jsonify(response)
|
|
|
|
|
|
@bp.route("/api/streaks", methods=["POST"])
|
|
def api_streaks():
|
|
data = request.get_json(silent=True) or {}
|
|
player_id = data.get("player_id")
|
|
if not player_id:
|
|
return jsonify({"error": "player_id required"}), 400
|
|
return jsonify(get_streaks(player_id) or {"error": "player not found"})
|
|
|
|
|
|
@bp.route("/api/new-game", methods=["POST"])
|
|
def api_new_game():
|
|
"""Startet (fuer den Unbegrenzt-Modus) eine neue Zufallsrunde."""
|
|
data = request.get_json(silent=True) or {}
|
|
player_id = data.get("player_id")
|
|
if not player_id or Player.query.get(player_id) is None:
|
|
return jsonify({"error": "player not found"}), 404
|
|
target = random_target()
|
|
if target is None:
|
|
return jsonify({"error": "no movies"}), 500
|
|
session = Session(
|
|
player_id=player_id, mode="unlimited", target_movie_id=target.id,
|
|
status="in_progress", attempts_used=0,
|
|
)
|
|
db.session.add(session)
|
|
db.session.commit()
|
|
return jsonify({
|
|
"session_id": session.id,
|
|
"mode": "unlimited",
|
|
"max_attempts": get_max_attempts(),
|
|
"status": "in_progress",
|
|
"attempts_used": 0,
|
|
})
|
|
|
|
|
|
def _movie_public(movie):
|
|
return {
|
|
"id": movie.id,
|
|
"title": movie.title,
|
|
"year": movie.year,
|
|
"fsk": movie.fsk,
|
|
"studio": movie.studio.name if movie.studio else None,
|
|
"director": movie.director,
|
|
"budget": movie.budget,
|
|
"universe": movie.universe.name if movie.universe else None,
|
|
"genres": [g.name for g in movie.genres],
|
|
"platforms": [p.name for p in movie.platforms],
|
|
}
|