import app/clients/host_client import app/clients/new_user_client import app/clients/player_client import config import gleam/erlang/process import gleam/float import gleam/int import gleam/io import gleam/json import player_manager import session_manager import socket_manager pub type Error { InvalidToken } pub type Context { Context( config: config.Config, sessions: session_manager.SessionManager, players: player_manager.PlayerManager, socket_manager: socket_manager.SocketManager(String), ) } pub type ClientState { Host(host_client.HostState) Player(player_client.PlayerState) NewUser(new_user_client.NewUserState) } pub type SocketState { SocketState( ctx: Context, id: Int, subject: process.Subject(String), state: ClientState, ) } pub fn handle_client_msg( socket_state: SocketState, msg: String, ) -> #(SocketState, String) { case socket_state.state { Host(state) -> handle_host(socket_state, state, msg) NewUser(state) -> handle_new_user(socket_state, state, msg) Player(state) -> handle_player(socket_state, state, msg) } } fn handle_player( socket_state: SocketState, player_state: player_client.PlayerState, msg: String, ) -> #(SocketState, String) { let assert Ok(msg) = json.parse(msg, player_client.player_client_messages_decoder()) case msg { player_client.BuzzIn(time) -> { io.println( "Got buzz in from " <> int.to_string(player_state.user_id) <> " at " <> float.to_string(time), ) let assert Ok(_) = session_manager.buzz_in_player( socket_state.ctx.sessions, player_state.game_id, player_state.user_id, time, ) #( socket_state, json.to_string(player_client.encode_player_server_messages( player_client.Ack, )), ) } } } fn handle_new_user( socket_state: SocketState, _new_user_state: new_user_client.NewUserState, msg: String, ) -> #(SocketState, String) { let assert Ok(msg) = json.parse(msg, new_user_client.new_user_client_messages_decoder()) let #(socket_state, new_user_msg) = case msg { new_user_client.JoinAsHost(token, user_id, game_id) -> { let assert Ok(_) = player_manager.attack_socket_to_player( socket_state.ctx.players, user_id, socket_state.id, token, ) #( SocketState( ..socket_state, state: Host(host_client.HostState(user_id:, game_id:)), ), new_user_client.HostRegisterResponse, ) } new_user_client.JoinAsPlayer(token, user_id, game_id) -> { let assert Ok(_) = player_manager.attack_socket_to_player( socket_state.ctx.players, user_id, socket_state.id, token, ) #( SocketState( ..socket_state, state: Player(player_client.PlayerState(user_id:, game_id:)), ), new_user_client.RegisterResponse, ) } } #( socket_state, json.to_string(new_user_client.encode_new_user_server_messages(new_user_msg)), ) } fn handle_host( socket_state: SocketState, host_state: host_client.HostState, msg: String, ) -> #(SocketState, String) { let assert Ok(msg) = json.parse(msg, host_client.host_client_messages_decoder()) let #(socket_state, resp) = case msg { host_client.ResetAllBuzers -> { let assert Ok(_) = session_manager.reset_all_buzzers( socket_state.ctx.sessions, host_state.game_id, ) #(socket_state, host_client.Ack) } host_client.ResetPlayerBuzzer(id) -> { let assert Ok(_) = session_manager.reset_player_buzzer( socket_state.ctx.sessions, host_state.game_id, id, ) #(socket_state, host_client.Ack) } host_client.UpdateScore(id, score) -> { let assert Ok(_) = session_manager.updater_player_score( socket_state.ctx.sessions, host_state.game_id, id, score, ) #(socket_state, host_client.Ack) } host_client.EndGame -> { let assert Ok(_) = session_manager.end_game(socket_state.ctx.sessions, host_state.game_id) #(socket_state, host_client.Ack) } } let resp = json.to_string(host_client.encode_host_server_messages(resp)) #(socket_state, resp) }