Skip to content
Snippets Groups Projects
sockets.py 6.69 KiB
Newer Older
  • Learn to ignore specific revisions
  • Victor Löfgren's avatar
    Victor Löfgren committed
    import app.database.controller as dbc
    from app.core import db
    
    Victor Löfgren's avatar
    Victor Löfgren committed
    from app.database.models import Competition, Slide, Team, ViewType, Code
    
    from flask.globals import request
    from flask_socketio import SocketIO, emit, join_room
    
    Victor Löfgren's avatar
    Victor Löfgren committed
    import logging
    
    Victor Löfgren's avatar
    Victor Löfgren committed
    logger = logging.getLogger(__name__)
    logger.propagate = False
    logger.setLevel(logging.INFO)
    
    Victor Löfgren's avatar
    Victor Löfgren committed
    formatter = logging.Formatter('[%(levelname)s] %(funcName)s: %(message)s')
    stream_handler = logging.StreamHandler()
    stream_handler.setFormatter(formatter)
    logger.addHandler(stream_handler)
    
    sio = SocketIO(cors_allowed_origins="http://localhost:3000")
    
    
    Victor Löfgren's avatar
    Victor Löfgren committed
    presentations = {}
    
    
    
    @sio.on("connect")
    def connect():
    
    Victor Löfgren's avatar
    Victor Löfgren committed
        logger.info(f"Client '{request.sid}' connected")
    
    
    
    @sio.on("disconnect")
    def disconnect():
    
    Victor Löfgren's avatar
    Victor Löfgren committed
        for competition_id, presentation in presentations.items():
            if request.sid in presentation["clients"]:
                del presentation["clients"][request.sid]
    
    Victor Löfgren's avatar
    Victor Löfgren committed
                logger.debug(f"Client '{request.sid}' left presentation '{competition_id}'")
    
    Victor Löfgren's avatar
    Victor Löfgren committed
                break
    
        if presentations and not presentations[competition_id]["clients"]:
            del presentations[competition_id]
    
    Victor Löfgren's avatar
    Victor Löfgren committed
            logger.info(f"No people left in presentation '{competition_id}', ended presentation")
    
    Victor Löfgren's avatar
    Victor Löfgren committed
        logger.info(f"Client '{request.sid}' disconnected")
    
    Victor Löfgren's avatar
    Victor Löfgren committed
    @sio.on("start_presentation")
    def start_presentation(data):
        competition_id = data["competition_id"]
    
        if competition_id in presentations:
    
    Victor Löfgren's avatar
    Victor Löfgren committed
            logger.error(f"Client '{request.sid}' failed to start competition '{competition_id}', presentation already active")
    
    Victor Löfgren's avatar
    Victor Löfgren committed
            return
    
        presentations[competition_id] = {
            "clients": {request.sid: {"view_type": "Operator"}},
            "slide": None,
            "timer": {"enabled": False, "start_value": None, "value": None},
        }
    
        join_room(competition_id)
    
    Victor Löfgren's avatar
    Victor Löfgren committed
        logger.debug(f"Client '{request.sid}' joined room {competition_id}")
    
    Victor Löfgren's avatar
    Victor Löfgren committed
        logger.info(f"Client '{request.sid}' started competition '{competition_id}'")
    
    Victor Löfgren's avatar
    Victor Löfgren committed
    
    @sio.on("end_presentation")
    def end_presentation(data):
        competition_id = data["competition_id"]
    
        if competition_id not in presentations:
    
    Victor Löfgren's avatar
    Victor Löfgren committed
            logger.error(f"Client '{request.sid}' failed to end presentation '{competition_id}', no such presentation exists")
            return
    
        if request.sid not in presentations[competition_id]["clients"]:
            logger.error(f"Client '{request.sid}' failed to end presentation '{competition_id}', client not in presentation")
    
    Victor Löfgren's avatar
    Victor Löfgren committed
            return
    
        if presentations[competition_id]["clients"][request.sid]["view_type"] != "Operator":
    
    Victor Löfgren's avatar
    Victor Löfgren committed
            logger.error(f"Client '{request.sid}' failed to end presentation '{competition_id}', client is not operator")
    
    Victor Löfgren's avatar
    Victor Löfgren committed
            return
    
        del presentations[competition_id]
    
    Victor Löfgren's avatar
    Victor Löfgren committed
        logger.debug(f"Deleted presentation {competition_id}")
    
    Victor Löfgren's avatar
    Victor Löfgren committed
    
        emit("end_presentation", room=competition_id, include_self=True)
    
    Victor Löfgren's avatar
    Victor Löfgren committed
        logger.debug(f"Emitting event 'end_presentation' to room {competition_id} including self")
    
        logger.info(f"Client '{request.sid}' ended presentation '{competition_id}'")
    
    Victor Löfgren's avatar
    Victor Löfgren committed
    
    
    @sio.on("join_presentation")
    def join_presentation(data):
        team_view_id = 1
        code = data["code"]
    
    Victor Löfgren's avatar
    Victor Löfgren committed
        item_code = db.session.query(Code).filter(Code.code == code).first()
    
    Victor Löfgren's avatar
    Victor Löfgren committed
    
        if not item_code:
    
    Victor Löfgren's avatar
    Victor Löfgren committed
            logger.error(f"Client '{request.sid}' failed to join presentation with code '{code}', no such code exists")
    
    Victor Löfgren's avatar
    Victor Löfgren committed
            return
    
    Victor Löfgren's avatar
    Victor Löfgren committed
        competition_id = (
            item_code.pointer
            if item_code.view_type_id != team_view_id
            else db.session.query(Team).filter(Team.id == item_code.pointer).one().competition_id
        )
    
    Victor Löfgren's avatar
    Victor Löfgren committed
        if competition_id not in presentations:
    
    Victor Löfgren's avatar
    Victor Löfgren committed
            logger.error(f"Client '{request.sid}' failed to join presentation '{competition_id}', no such presentation exists")
    
    Victor Löfgren's avatar
    Victor Löfgren committed
            return
    
    Victor Löfgren's avatar
    Victor Löfgren committed
        if request.sid in presentations[competition_id]["clients"]:
    
    Victor Löfgren's avatar
    Victor Löfgren committed
            logger.error(f"Client '{request.sid}' failed to join presentation '{competition_id}', client already in presentation")
    
    Victor Löfgren's avatar
    Victor Löfgren committed
            return
    
    Victor Löfgren's avatar
    Victor Löfgren committed
        # TODO: Write function in database controller to do this
        view_type_name = db.session.query(ViewType).filter(ViewType.id == item_code.view_type_id).one().name
    
        presentations[competition_id]["clients"][request.sid] = {"view_type": view_type_name}
    
    
    Victor Löfgren's avatar
    Victor Löfgren committed
        join_room(competition_id)
        logger.debug(f"Client '{request.sid}' joined room {competition_id}")
    
    Victor Löfgren's avatar
    Victor Löfgren committed
        logger.info(f"Client '{request.sid}' joined competition '{competition_id}'")
    
    Victor Löfgren's avatar
    Victor Löfgren committed
    
    
    @sio.on("set_slide")
    def set_slide(data):
        competition_id = data["competition_id"]
        slide_order = data["slide_order"]
    
        if competition_id not in presentations:
    
    Victor Löfgren's avatar
    Victor Löfgren committed
            logger.error(f"Client '{request.sid}' failed to set slide in presentation '{competition_id}', no such presentation exists")
            return
    
        if request.sid not in presentations[competition_id]["clients"]:
            logger.error(f"Client '{request.sid}' failed to set slide in presentation '{competition_id}', client not in presentation")
    
    Victor Löfgren's avatar
    Victor Löfgren committed
            return
    
        if presentations[competition_id]["clients"][request.sid]["view_type"] != "Operator":
    
    Victor Löfgren's avatar
    Victor Löfgren committed
            logger.error(f"Client '{request.sid}' failed to set slide in presentation '{competition_id}', client is not operator")
    
    Victor Löfgren's avatar
    Victor Löfgren committed
            return
    
        num_slides = db.session.query(Slide).filter(Slide.competition_id == competition_id).count()
    
        if not (0 <= slide_order < num_slides):
    
    Victor Löfgren's avatar
    Victor Löfgren committed
            logger.error(f"Client '{request.sid}' failed to set slide in presentation '{competition_id}', slide number {slide_order} does not exist")
    
    Victor Löfgren's avatar
    Victor Löfgren committed
            return
    
        presentations[competition_id]["slide"] = slide_order
    
        emit("set_slide", {"slide_order": slide_order}, room=competition_id, include_self=True)
    
    Victor Löfgren's avatar
    Victor Löfgren committed
        logger.debug(f"Emitting event 'set_slide' to room {competition_id} including self")
    
        logger.info(f"Client '{request.sid}' set slide '{slide_order}' in competition '{competition_id}'")
    
    Victor Löfgren's avatar
    Victor Löfgren committed
    
    
    @sio.on("set_timer")
    
    Victor Löfgren's avatar
    Victor Löfgren committed
    def set_timer(data):
    
    Victor Löfgren's avatar
    Victor Löfgren committed
        competition_id = data["competition_id"]
    
        timer = data["timer"]
    
    Victor Löfgren's avatar
    Victor Löfgren committed
    
        if competition_id not in presentations:
    
    Victor Löfgren's avatar
    Victor Löfgren committed
            logger.error(f"Client '{request.sid}' failed to set slide in presentation '{competition_id}', no such presentation exists")
            return
    
        if request.sid not in presentations[competition_id]["clients"]:
            logger.error(f"Client '{request.sid}' failed to set slide in presentation '{competition_id}', client not in presentation")
    
    Victor Löfgren's avatar
    Victor Löfgren committed
            return
    
        if presentations[competition_id]["clients"][request.sid]["view_type"] != "Operator":
    
    Victor Löfgren's avatar
    Victor Löfgren committed
            logger.error(f"Client '{request.sid}' failed to set slide in presentation '{competition_id}', client is not operator")
    
    Victor Löfgren's avatar
    Victor Löfgren committed
            return
    
        # TODO: Save timer in presentation, maybe?
    
        emit("set_timer", {"timer": timer}, room=competition_id, include_self=True)
    
    Victor Löfgren's avatar
    Victor Löfgren committed
        logger.debug(f"Emitting event 'set_timer' to room {competition_id} including self")
    
        logger.info(f"Client '{request.sid}' set timer '{timer}' in presentation '{competition_id}'")