193 lines
6.4 KiB
Python
193 lines
6.4 KiB
Python
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
|
|
from ..services.match_modes import handle_final_round_vote, is_final_round_mode
|
|
from ..services.session_recipes import add_recipe_batch, replace_recipe_batch, serialize_recipe
|
|
from ..services.session_settings import get_match_mode, get_required_likes, get_voting_round, set_match_mode, set_required_likes, set_voting_round
|
|
|
|
|
|
def room_name(code):
|
|
return f"session:{code.upper()}"
|
|
|
|
|
|
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
|
|
],
|
|
"recipes": [serialize_recipe(recipe) for recipe in session.recipes],
|
|
"requiredLikes": get_required_likes(session),
|
|
"matchMode": get_match_mode(session),
|
|
"votingRound": get_voting_round(session),
|
|
},
|
|
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
|
|
session.matched_recipe_id = None
|
|
set_voting_round(session, 1)
|
|
db.session.commit()
|
|
emit_session_update(session)
|
|
|
|
|
|
@socketio.on("session:set_required_likes")
|
|
def update_required_likes(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 die Match-Regel ändern."})
|
|
return
|
|
|
|
if session.status != "waiting":
|
|
emit("error", {"message": "Die Match-Regel kann nur in der Lobby geändert werden."})
|
|
return
|
|
|
|
set_required_likes(session, data.get("requiredLikes", len(session.participants)))
|
|
db.session.commit()
|
|
emit_session_update(session)
|
|
|
|
|
|
@socketio.on("session:set_match_mode")
|
|
def update_match_mode(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 den Modus ändern."})
|
|
return
|
|
|
|
if session.status != "waiting":
|
|
emit("error", {"message": "Der Modus kann nur in der Lobby geändert werden."})
|
|
return
|
|
|
|
set_match_mode(session, data.get("matchMode"))
|
|
db.session.commit()
|
|
emit_session_update(session)
|
|
|
|
|
|
@socketio.on("session:restart")
|
|
def restart_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 neu starten."})
|
|
return
|
|
|
|
session.status = "running"
|
|
session.current_recipe_index = 0
|
|
set_voting_round(session, 1)
|
|
replace_recipe_batch(session)
|
|
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
|
|
|
|
if is_final_round_mode(session):
|
|
result = handle_final_round_vote(session, recipe)
|
|
db.session.commit()
|
|
if result == "match":
|
|
matched_recipe = next((r for r in session.recipes if r.id == session.matched_recipe_id), recipe)
|
|
socketio.emit("session:match", {"recipe": serialize_recipe(matched_recipe)}, room=room_name(code))
|
|
emit_session_update(session)
|
|
return
|
|
|
|
yes_count = Vote.query.filter_by(session_id=session.id, recipe_id=recipe.id, vote="yes").count()
|
|
if yes_count >= get_required_likes(session):
|
|
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
|
|
|
|
participant_vote_count = Vote.query.filter_by(
|
|
session_id=session.id,
|
|
participant_id=participant_id,
|
|
).count()
|
|
if participant_vote_count >= len(session.recipes):
|
|
add_recipe_batch(session)
|
|
|
|
db.session.commit()
|
|
emit_session_update(session)
|