diff --git a/client/src/sockets.ts b/client/src/sockets.ts index 3c27298fa63cf6a18027b013c45f4d469b960498..d7795f843ccc70ef1d6784b8d8c8f4c72d17c5f8 100644 --- a/client/src/sockets.ts +++ b/client/src/sockets.ts @@ -1,8 +1,17 @@ +/** + * Handles everything that has to do with syncing active competitions. + * + * @module + */ + import io from 'socket.io-client' import { setCurrentSlideByOrder, setPresentationShowScoreboard, setPresentationTimer } from './actions/presentation' import { TimerState } from './interfaces/Timer' import store from './store' +/** + * The values that can be synced between clients connected to the same presentation. + */ interface SyncInterface { slide_order?: number timer?: TimerState @@ -11,9 +20,15 @@ interface SyncInterface { let socket: SocketIOClient.Socket +/** + * Connect to server, setup authorization header and listen to some events. + * + * @param role The role the connecting client has + */ export const socketConnect = (role: 'Judge' | 'Operator' | 'Team' | 'Audience') => { if (socket) return + // The token is the JWT returned from the login/code API call. const token = localStorage[`${role}Token`] socket = io('localhost:5000', { transportOptions: { @@ -26,7 +41,7 @@ export const socketConnect = (role: 'Judge' | 'Operator' | 'Team' | 'Audience') }) socket.on('sync', (data: SyncInterface) => { - // The order of these is important, for some reason + // The order of these is important, for some reason, so dont change it if (data.timer !== undefined) setPresentationTimer(data.timer)(store.dispatch) if (data.slide_order !== undefined) setCurrentSlideByOrder(data.slide_order)(store.dispatch, store.getState) if (data.show_scoreboard !== undefined) setPresentationShowScoreboard(data.show_scoreboard)(store.dispatch) @@ -37,10 +52,18 @@ export const socketConnect = (role: 'Judge' | 'Operator' | 'Team' | 'Audience') }) } +/** + * Disconnect all clients. + */ export const socketEndPresentation = () => { socket.emit('end_presentation') } +/** + * Sync data between all connected clients. + * + * @param syncData The data to sync between all clients connected to the same presentation + */ export const socketSync = (syncData: SyncInterface) => { socket.emit('sync', syncData) } diff --git a/server/app/core/sockets.py b/server/app/core/sockets.py index 47af826bb00fe468eaae0b4eca40c8f3c21f196b..e2e6037e0ec018e81c3a49c6b15ed80dc8789015 100644 --- a/server/app/core/sockets.py +++ b/server/app/core/sockets.py @@ -26,7 +26,7 @@ active_competitions = {} def _unpack_claims(): """ - :return: A tuple containing competition_id and view, gotten from claim + :return: A tuple containing competition_id and view from claim :rtype: tuple """ @@ -39,10 +39,19 @@ def is_active_competition(competition_id): :return: True if competition with competition_id is currently active else False :rtype: bool """ + return competition_id in active_competitions def _get_sync_variables(active_competition, sync_values): + """ + Returns a dictionary with all values from active_competition that is to be + synced. + + :return: A dicationary containg key-value pairs from active_competition + thats in sync_values + :rtype: dictionary + """ return {key: value for key, value in active_competition.items() if key in sync_values} @@ -83,7 +92,7 @@ def authorize_client(f, allowed_views=None, require_active_competition=True, *ar def connect() -> None: """ Connect to a active competition. If competition with competition_id is not active, - start it if client is an operator, otherwise ignore it. + start it if client is an operator, otherwise do nothing. """ competition_id, view = _unpack_claims() @@ -133,7 +142,7 @@ def disconnect() -> None: @authorize_client(allowed_views=["Operator"]) def end_presentation() -> None: """ - End a active_competition by sending end_presentation to all connected clients. + End a presentation by sending end_presentation to all connected clients. """ competition_id, _ = _unpack_claims() @@ -144,7 +153,8 @@ def end_presentation() -> None: @authorize_client(allowed_views=["Operator"]) def sync(data) -> None: """ - Sync active_competition for all clients connected to competition. + Update all values from data thats in an active_competitions. Also sync all + the updated values to all clients connected to the same competition. """ competition_id, view = _unpack_claims() @@ -153,6 +163,7 @@ def sync(data) -> None: for key, value in data.items(): if key not in active_competition: logger.warning(f"Invalid sync data: '{key}':'{value}'") + continue active_competition[key] = value