from flask_socketio import emit, join_room from sqlalchemy.exc import IntegrityError from .. import socketio from ..models import db from ..models.session import Session, Vote def room_name(code): return f"session:{code.upper()}" def serialize_recipe(recipe): return { "id": recipe.id, "title": recipe.title, "url": recipe.url, "imageUrl": recipe.image_url, "meta": recipe.meta, "position": recipe.position, } def emit_session_update(session): socketio.emit( "session:update", { "code": session.code, "status": session.status, "currentRecipeIndex": session.current_recipe_index, "matchedRecipeId": session.matched_recipe_id, "participants": [ {"id": p.id, "name": p.name, "isHost": p.is_host} for p in session.participants ], }, room=room_name(session.code), ) @socketio.on("session:subscribe") def subscribe(data): code = data.get("code", "").upper() session = Session.query.filter_by(code=code).first() if not session: emit("error", {"message": "Session nicht gefunden."}) return join_room(room_name(code)) emit_session_update(session) @socketio.on("session:start") def start_session(data): code = data.get("code", "").upper() participant_id = data.get("participantId") session = Session.query.filter_by(code=code).first() if not session: emit("error", {"message": "Session nicht gefunden."}) return host = next((p for p in session.participants if p.id == participant_id and p.is_host), None) if not host: emit("error", {"message": "Nur der Host kann starten."}) return session.status = "running" session.current_recipe_index = 0 db.session.commit() emit_session_update(session) @socketio.on("vote") def vote(data): code = data.get("code", "").upper() participant_id = data.get("participantId") recipe_id = data.get("recipeId") vote_value = data.get("vote") if vote_value not in ["yes", "no"]: emit("error", {"message": "Ungültige Stimme."}) return session = Session.query.filter_by(code=code).first() if not session or session.status != "running": emit("error", {"message": "Session läuft nicht."}) return recipe = next((r for r in session.recipes if r.id == recipe_id), None) if not recipe: emit("error", {"message": "Rezept nicht gefunden."}) return db.session.add(Vote(session_id=session.id, participant_id=participant_id, recipe_id=recipe.id, vote=vote_value)) try: db.session.commit() except IntegrityError: db.session.rollback() return participant_count = len(session.participants) yes_count = Vote.query.filter_by(session_id=session.id, recipe_id=recipe.id, vote="yes").count() vote_count = Vote.query.filter_by(session_id=session.id, recipe_id=recipe.id).count() if yes_count == participant_count: session.status = "finished" session.matched_recipe_id = recipe.id db.session.commit() socketio.emit("session:match", {"recipe": serialize_recipe(recipe)}, room=room_name(code)) emit_session_update(session) return if vote_count == participant_count: session.current_recipe_index += 1 if session.current_recipe_index >= len(session.recipes): session.status = "finished" db.session.commit() emit_session_update(session)