{"version":3,"sources":["api/constants/config.ts","features/board/types/utility.ts","features/game/types/state.ts","api/socketClient.ts","features/lobby/contexts/userContext.tsx","features/game/constants/size.ts","features/board/types/battleship.ts","features/game/constants/state.ts","features/game/contexts/gameStateContext.tsx","styles/theme.ts","features/board/types/board.ts","features/board/components/Ship.tsx","features/board/functions/posToString.ts","features/board/components/Square.tsx","features/board/functions/mapPosToBattleshipPart.ts","features/setup/types/placement.ts","features/board/functions/generateArrayOfNumbers.ts","features/board/index.tsx","features/result/components/win.tsx","features/result/components/lose.tsx","features/result/index.tsx","features/routing/hooks/useQuery.ts","features/game/reducers/gameStateReducer.ts","features/setup/constants/list.ts","features/avatar/types/avatar.ts","features/setup/components/ship.tsx","features/setup/components/refresh.tsx","features/setup/functions/deserializePlacements.ts","features/setup/functions/serializePlacements.ts","features/board/functions/getAvailableSquares.ts","features/game/components/left.tsx","features/setup/index.tsx","features/game/screens/hostWelcome.tsx","features/game/contexts/chatContext.tsx","features/avatar/components/chatBubbleList.tsx","features/avatar/components/userAvatar.tsx","features/avatar/components/avatarContainer.tsx","features/avatar/components/avatarVersus.tsx","features/lobby/components/base.styled.tsx","features/lobby/components/basicButton.tsx","features/game/components/chatBox.tsx","features/board/functions/serializePos.ts","features/board/functions/deserializePos.ts","features/game/functions/deserializeBattleship.ts","features/avatar/hooks/useChatQueue.ts","features/game/functions/useAutoWithdraw.ts","features/tutorial/constants/tutorial.ts","features/tutorial/components/arrowIcon.tsx","features/tutorial/components/tutorialModal.tsx","features/game/wrappers/tutorialWrapper.tsx","features/game/components/volumeMute.tsx","features/game/components/volumeUp.tsx","features/game/functions/useStickyState.ts","features/game/screens/gamePage.tsx","features/game/functions/useOnStart.ts","features/game/functions/useOnEnd.ts","features/game/functions/useOnAdminSpectate.ts","features/game/functions/useOnAvatar.ts","features/game/functions/useOnChat.ts","features/game/functions/useOnShoot.ts","features/game/functions/useOnShipDestroyed.ts","features/game/functions/useOnStatistics.ts","features/lobby/types/utility.ts","features/lobby/components/roomModeSlider.tsx","features/lobby/screens/createRoomPage.tsx","features/game/functions/useOnJoin.ts","features/lobby/components/basicInput.tsx","features/lobby/contexts/roomContext.tsx","features/lobby/components/publicRoomsList.tsx","features/lobby/screens/joinRoomPage.tsx","features/avatar/components/avatarSelector.tsx","features/lobby/wrappers/labelWrapper.tsx","features/lobby/components/creditsBox.tsx","features/lobby/wrappers/lobbyLayoutWrapper.tsx","features/lobby/components/battleshipIcon.tsx","features/lobby/hooks/useKeySequenceListener.tsx","features/lobby/screens/welcomePage.tsx","features/routing/components/lobbyRoute.tsx","features/routing/components/mainRouter.tsx","styles/globalStyles.tsx","App.tsx","reportWebVitals.ts","index.tsx"],"names":["SocketEvent","SetupResponseStatus","Side","Phase","SocketClient","socket","this","io","process","disconnect","Promise","resolve","reject","emit","GetRoomList","on","GetRoomListResponse","responseStatus","roomList","AdminGetRoomList","AdminGetRoomListResponse","username","CreateRoom","CreateRoomResponse","roomID","roomId","JoinRoom","ChangeLock","ChangeLockResponse","avatarSeed","SetAvatar","SetupResponse","status","hostReady","guestReady","Completed","message","Chat","password","AdminLogin","AdminLoginResponse","nums","length","retry","fallback","Error","promise","handler","reason","RandomShip","RandomShipResponse","_","ships","setTimeout","i","catch","Setup","InvalidPlacement","pos","Shoot","subscribeShootResponse","Withdraw","callback","AdminSpectate","room","ShipDestroyed","side","ship","JoinRoomResponse","StartResponse","firstPlayer","EndResponse","previousRoundWinner","hostScore","guestScore","ShootResponse","location","currentTurnPlayer","nextTurnPlayer","turnCount","SetAvatarResponse","hostUsername","hostAvatar","guestUsername","guestAvatar","msg","StatResponse","hostTotal","hostHit","hostMiss","hostAcc","guestTotal","guestHit","guestMiss","guestAcc","time","host","total","hit","miss","acc","guest","UserContext","createContext","userAvatarSeed","isAdmin","setUsername","setUserAvatarSeed","setIsAdmin","useUserContext","useContext","BattleshipType","BattleshipPartType","BattleshipDirection","BattleshipStatus","initialGameState","meta","turn","round","phase","board","gridSize","ally","enemy","battleship","GameStateContext","state","dispatch","useGameStateContext","theme","colors","square","circle","background","light","medium","text","position","danger","main","tutorial","modal","primary","infoButton","lobby","avatar","white","selected","name","versus","score","chat","backdrop","dark","shadedLight","button","secondary","startGame","roomDark","slider","default","input","placeholder","info","heading","label","guidelines","credits","breakPoints","mobile","tablet","desktop","widescreen","styled","baseStyled","BoardSquareStatus","ROTATE_DEG_MAP","ShipPart","part","direction","size","zIndex","translateFixed","color","type","rotateDeg","Default","renderedShip","Front","viewBox","fill","xmlns","d","Middle","Back","Single","SingleShip","style","backgroundColor","Wrapper","rotate","fixed","div","css","posToString","row","col","Container","props","squareType","selectable","ColumnAlphabet","RowNumber","Circle","Hit","Missed","Square","Ally","onClick","onHoverStart","onHoverEnd","delegated","isSunken","Sunken","handleSelectClick","useCallback","payload","onMouseEnter","onMouseLeave","className","String","fromCharCode","partType","undefined","mapPosToBattleshipPart","PlacementStatus","shipYard","validate","map","Map","forEach","has","j","rowOffset","Math","floor","colOffset","targetPosition","potentialAdjacent","get","set","Vertical","Horizontal","VerticalRev","HorizontalRev","generateArrayOfNumbers","a","Array","HitCount","Board","hitCount","boardType","availability","onSquareHoverEnd","onSquareHoverStart","onSquareClick","mappedBattleshipPart","useMemo","filter","Hidden","renderedSquares","key","isPlacing","Placeholder","isHead","interactive","opacity","pointerEvents","e","Win","width","height","Lose","clipPath","id","Result","stats","winners","st","index","winner","timestamp","moment","format","Row","LeftStats","toFixed","RoundInfo","RoundTime","RightStats","span","useQuery","URLSearchParams","useLocation","search","gameStateReducer","prevState","action","shipyard","Enemy","toString","findIndex","s","slice","AvatarSide","INIT_BATTLESHIP","INIT_PLACEMENT_LIST","Undecided","Ship","Placed","ShipWrapper","ShipNumber","RefreshIcon","RandomSvg","svg","COLUMN","A","B","C","D","E","F","G","H","deserializePlacements","toUpperCase","parseInt","stringToPos","reverse","random","axis","DELTA","serializePlacements","delta","cells","origin","push","safeSet","arr","value","getDeltaFromDirection","dir","deltaX","deltaY","getAvailableSquares","x","y","visited","sum","begin","end","depth","Left","SetupModal","onSubmit","useState","placements","setPlacements","setDirection","waiting","setWaiting","p","availableSquares","find","onRandomize","_e","socketClient","randomize","formattedShips","nextPlacements","fs","onReady","serialized","setup","waitReady","onShipClick","onRotate","Placing","useEffect","fn","code","document","addEventListener","removeEventListener","HeaderWrapper","HeaderText","RandomButton","Spacer","BodyWrapper","ShipyardWrapper","ShipyardText","BoardWrapper","_position","MoreAction","RotateButton","ResetButton","ReadyButton","Welcome","StartGameContainer","HostWelcome","avatarVersusComponent","onHostStartCallback","ChatContext","chatSide","left","queue","addMessage","removeMessage","right","useChatContext","ChatBubble","isFlipped","ChatBubbleList","displayedBubbles","idx","Right","content","variants","fadeIn","initial","animate","transition","delay","duration","moveInLeft","exit","moveInRight","notSelected","none","motion","isRounded","isSelected","Username","UserAvatar","seed","variant","onClickHandler","whileHover","scale","AnimatePresence","scaleX","image","xlinkHref","AvatarContainer","isExpanded","VS","AvatarVersus","hasLeftScore","hasRightScore","LabelText","h1","WhiteBox","Tag","Backdrop","StyledButton","BasicButton","children","Chatbox","inputRef","useRef","chatContext","inputFocused","setInputFocused","setMessage","sendChat","preventDefault","useLayoutEffect","current","focus","blur","StyledInput","ref","onChange","target","onBlur","HintBox","SendButton","serializePos","deserializePos","deserializeBattleship","useChatQueue","setQueue","Date","now","useAutoWithdraw","history","useHistory","duplicateGuard","guarded","withdraw","TUTORIAL_INFO_LIST","imgSrc","imgAlt","ArrowIcon","isRotated","path","Header","Content","Instructions","BackdropGradient","ArrowContainer","TutorialModal","onCloseHandler","pageNumber","setPageNumber","hover","src","alt","TutorialButton","StyledBackdrop","TutorialWrapper","React","ThemeContext","tutorialModalShown","setTutorialModalShown","VolumeMute","transform","VolumeUp","useStickyState","defaultValue","stickyValue","window","localStorage","getItem","JSON","parse","setValue","setItem","stringify","GamePage","yourTurn","setYourTurn","setPhase","useReducer","second","setSecond","setTurn","mute","setMute","endReason","setEndReason","setRound","setWinners","allyScore","setAllyScore","allyHit","setAllyHit","enemyHit","setEnemyHit","enemyScore","setEnemyScore","enemyAvatarSeed","setEnemyAvatarSeed","enemyUsername","setEnemyUsername","statistic","setStatistic","timerRef","forceWithdraw","statsLock","query","playerChatQueue","enemyChatQueue","isHost","yourSide","spectatorMode","option","volume","soundEnabled","useSound","playShootHit","playShootFire","playChat","playMatchmake","playDefeat","stopDefeat","stop","playVictory","stopVictory","interrupt","playPlanning","stopPlanning","playPlaying","stopPlaying","avatarProps","onShoot","shoot","onToggleMute","onNewCount","clearInterval","setInterval","subscribeStartResponse","res","useOnStart","r","prev","subscribeEndResponse","useOnEnd","Finish","subscribeAdminSpectate","useOnAdminSpectate","subscribeAvatarResponse","useOnAvatar","subscribeChat","useOnChat","useOnShoot","subscribeShipDestroyed","useOnShipDestroyed","subscribeStatistic","useOnStatistics","joinRoom","setAvatar","Playing","MuteButton","borderRadius","result","RoundCount","timer","Timer","BoardContainer","footer","Footer","OneMoreRound","disabled","canPlayAgain","ReasonWrapper","formalizeReason","Provider","youWon","RoomMode","Slider","isChecked","TextContainer","RoomModeSlider","roomMode","onRoomModeToggleHandler","Private","Public","InfoBox","HeadingBox","Title","Guidelines","GameCode","DisappearingNotification","CreateRoomPage","roomComplete","setRoomId","setRoomMode","linkCopied","setLinkCopied","asyncCreateRoom","createRoom","createdRoomId","subscribeJoinResponse","useOnJoinSingle","pathname","alert","mode","toggleLock","title","link","href","split","join","navigator","clipboard","writeText","handleCopyLink","marginLeft","BasicInput","RoomContext","hoveredRoom","setHoveredRoom","container","hidden","show","staggerChildren","listItem","OverflowContainer","SingleRoom","PublicRoomsList","onRoomJoinHandler","setRoomList","allowOverflowY","setOverflowY","handleFetchRoomList","fetchedRoomList","adminGetRooms","adminFetchedRoomList","getRooms","interval","asyncRefreshRoomList","displayedRooms","onAnimationStart","onAnimationComplete","overflowY","PrivateRoomContainer","AdminRoomContainer","JoinRoomPage","privateRoomId","setPrivateRoomId","handleJoinRoom","maxLength","DEFAULT_AVATARS","getRandomSeed","substring","randomizing","repeat","Infinity","static","DiceButton","AvatarSelector","savedAvatarSeed","reduce","randomSeed","includes","getDefaultAvatars","randomSeeds","setRandomSeeds","actualUserAvatarSeed","controls","useAnimation","displayedAvatars","start","newSeeds","LabelWrapper","CreditsBox","LobbyLayoutWrapper","BattleshipIcon","useKeySequenceListener","onSequenceSubmitCallback","buffer","setBuffer","lastKeyTime","setLastKeyTime","keySequenceListener","currentTime","inputVariants","shake","ease","Rectangle","FormBox","form","ButtonContainer","fullButton","WelcomePage","console","log","showUsernameError","setShowUsernameError","sequence","adminLogin","validateUsername","handleEnterRoom","border","LobbyRoute","userRequired","renderedComponent","to","MainRouter","globalStyle","createGlobalStyle","App","reportWebVitals","onPerfEntry","Function","then","getCLS","getFID","getFCP","getLCP","getTTFB","ReactDOM","render","StrictMode","getElementById"],"mappings":"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","file":"static/js/main.e62f6656.chunk.js","sourcesContent":["export const API_URL =\n process.env.NODE_ENV === \"development\"\n ? \"https://game.motorhub-th.com\"\n : process.env.REACT_APP_API_URL;\n\nexport enum SocketEvent {\n CreateRoom = \"createRoom\",\n CreateRoomResponse = \"createRoomResponse\",\n ChangeLock = \"changeLock\",\n ChangeLockResponse = \"changeLockResponse\",\n GetRoomList = \"getRoomList\",\n GetRoomListResponse = \"getRoomListResponse\",\n JoinRoom = \"joinRoom\",\n JoinRoomResponse = \"joinRoomResponse\",\n SetAvatar = \"setAvatar\",\n SetAvatarResponse = \"setAvatarResponse\",\n RandomShip = \"randomShip\",\n RandomShipResponse = \"randomShipResponse\",\n Setup = \"setup\",\n SetupResponse = \"setupResponse\",\n Shoot = \"shoot\",\n ShootResponse = \"shootResponse\",\n StartResponse = \"gameStartResponse\",\n EndResponse = \"endResponse\",\n ShipDestroyed = \"shipDestroyed\",\n Chat = \"chat\",\n Stat = \"stat\",\n StatResponse = \"statResponse\",\n Withdraw = \"withdraw\",\n SocketId = \"SocketID\",\n Disconnect = \"disconnect\",\n AdminLogin = \"adminLogin\",\n AdminLoginResponse = \"adminLoginResponse\",\n AdminGetRoomList = \"adminGetRoomList\",\n AdminGetRoomListResponse = \"adminGetRoomListResponse\",\n AdminSpectate = \"adminSpectate\",\n AdminSpectateResponse = \"adminSpectateResponse\",\n AdminStopSpectate = \"adminStopSpectate\",\n AdminStopSpectateResponse = \"adminStopSpectateResponse\",\n}\n\nexport enum SetupResponseStatus {\n Completed = \"Completed\",\n InvalidPlacement = \"Invalid Placement\",\n}\n\nexport type InfallibleResponse = \"Completed\";\n","export enum Side {\n Ally = \"ally\", \n Enemy = \"enemy\",\n};\n\nexport interface Position {\n col: number;\n row: number;\n}","import { BattleshipState } from \"../../board/types/battleship\";\nimport { BoardState } from \"../../board/types/board\";\n\nexport interface GameState {\n meta: MetaState; \n board: BoardState;\n battleship: BattleshipState;\n}\n\nexport interface MetaState {\n round: number; \n turn: number; \n phase: Phase; \n}\n\nexport enum Phase {\n Welcome = 0, \n Setup, \n Playing, \n Finish, \n}","import { io, Socket } from \"socket.io-client\";\nimport {\n API_URL,\n InfallibleResponse,\n SetupResponseStatus,\n SocketEvent,\n} from \"./constants/config\";\nimport {\n AdminGetRoomListResponse,\n AdminLoginResponse,\n AdminRoomObserver,\n AdminSpectateResponse,\n AdminSpectateRoom,\n AvatarResponse,\n ChangeLockResponse,\n CreateRoomResponse,\n EndResponse,\n GetRoomListResponse,\n JoinRoomResponse,\n ShipDestroyedResponse,\n ShootResponse,\n StartResponse,\n StatResponse,\n} from \"./types/transport\";\n\nclass SocketClient {\n private socket?: Socket;\n\n constructor() {\n this.socket = io(API_URL!);\n }\n\n public disconnect() {\n if (this.socket) this.socket.disconnect();\n }\n\n ////////////////////////////\n // Asynchronous Setup API //\n ////////////////////////////\n\n public async getRooms(): Promise {\n return new Promise((resolve, reject) => {\n if (!this.socket) {\n reject(\"Socket not initialized\");\n } else {\n this.socket.emit(SocketEvent.GetRoomList);\n this.socket.on(\n SocketEvent.GetRoomListResponse,\n (\n responseStatus: GetRoomListResponse[\"responseStatus\"],\n roomList: GetRoomListResponse[\"roomList\"]\n ) => {\n resolve({ responseStatus, roomList });\n }\n );\n }\n });\n }\n\n public async adminGetRooms(): Promise {\n return new Promise((resolve, reject) => {\n if (!this.socket) {\n reject(\"Socket not initialized\");\n } else {\n this.socket.emit(SocketEvent.AdminGetRoomList);\n this.socket.on(\n SocketEvent.AdminGetRoomListResponse,\n (\n responseStatus: AdminGetRoomListResponse[\"responseStatus\"],\n roomList: AdminGetRoomListResponse[\"roomList\"]\n ) => {\n resolve({ responseStatus, roomList });\n }\n );\n }\n });\n }\n\n public async createRoom(username: string): Promise {\n return new Promise((resolve, reject) => {\n if (!this.socket) {\n reject(\"Socket not initialized\");\n } else {\n this.socket.emit(SocketEvent.CreateRoom, username, \"\");\n this.socket.on(\n SocketEvent.CreateRoomResponse,\n (\n responseStatus: CreateRoomResponse[\"responseStatus\"],\n roomID: string\n ) => {\n resolve({\n responseStatus,\n roomID,\n });\n }\n );\n }\n });\n }\n\n public async joinRoom(username: string, roomId: string): Promise {\n return new Promise((resolve, reject) => {\n if (!this.socket) {\n reject(\"Socket not initialized\");\n } else {\n this.socket.emit(SocketEvent.JoinRoom, username, roomId);\n resolve();\n }\n });\n }\n\n public async toggleLock(): Promise {\n return new Promise((resolve, reject) => {\n if (!this.socket) {\n reject(\"Socket not initialized\");\n } else {\n this.socket.emit(SocketEvent.ChangeLock, \"\");\n this.socket.on(\n SocketEvent.ChangeLockResponse,\n (responseStatus: ChangeLockResponse[\"responseStatus\"]) => {\n resolve({\n responseStatus,\n });\n }\n );\n }\n });\n }\n\n public async setAvatar(avatarSeed: string): Promise {\n return new Promise((resolve, reject) => {\n if (!this.socket) {\n reject(\"Socket not initialized\");\n } else {\n this.socket.emit(SocketEvent.SetAvatar, avatarSeed);\n resolve();\n }\n });\n }\n\n public async waitReady(): Promise {\n return new Promise((resolve, reject) => {\n if (!this.socket) return reject(\"Socket not initialized\");\n\n // TODO: Heartbeating\n // let intervalId: NodeJS.Timeout | null = null;\n\n this.socket.on(\n SocketEvent.SetupResponse,\n (\n status: SetupResponseStatus,\n hostReady: boolean,\n guestReady: boolean\n ) => {\n // intervalId && clearInterval(intervalId);\n // intervalId = setTimeout(() => {\n // reject(\"Connection timeout 30s.\");\n // }, 30000);\n\n if (status === SetupResponseStatus.Completed)\n hostReady && guestReady && resolve();\n }\n );\n\n // intervalId = setTimeout(() => {\n // reject(\"Connection timeout 30s.\");\n // }, 30000);\n });\n }\n\n public async sendChat(message: string): Promise {\n return new Promise((resolve, reject) => {\n if (!this.socket) {\n reject(\"Socket not initialized\");\n } else {\n this.socket.emit(SocketEvent.Chat, message);\n resolve();\n }\n });\n }\n\n public async adminLogin(password: string): Promise {\n return new Promise((resolve, reject) => {\n if (!this.socket) {\n reject(\"Socket not initialized\");\n } else {\n this.socket.emit(SocketEvent.AdminLogin, password);\n this.socket.on(\n SocketEvent.AdminLoginResponse,\n (responseStatus: AdminLoginResponse[\"responseStatus\"]) => {\n if (responseStatus === \"Completed\") {\n resolve();\n } else {\n reject(responseStatus);\n }\n }\n );\n }\n });\n }\n\n ///////////////////////////\n // Asynchronous Game API //\n ///////////////////////////\n\n public async randomize(\n nums: number,\n length: number,\n retry: number,\n fallback: string[][] = [\n [\"A1\", \"A2\", \"A3\", \"A4\"],\n [\"C2\", \"D2\", \"E2\", \"F2\"],\n [\"C4\", \"C5\", \"C6\", \"C7\"],\n [\"H1\", \"H2\", \"H3\", \"H4\"],\n ]\n ): Promise {\n if (!this.socket) throw new Error(\"Socket not initialized\");\n\n let handler = (reason: string) =>\n new Promise((resolve, reject) => {\n if (reason === \"Connection timeout 30s.\")\n reject(\"Connection timeout 30s\");\n\n this.socket?.emit(SocketEvent.RandomShip, nums, length);\n this.socket?.on(\n SocketEvent.RandomShipResponse,\n (_: InfallibleResponse, ships: string[][]) => {\n if (ships.length !== length)\n reject(\n \"Backend returns empty placements. Retrying...\"\n );\n\n resolve(ships);\n }\n );\n\n setTimeout(() => {\n reject(\"Connection timeout 30s.\");\n }, 3000);\n });\n\n let promise = handler(\"\");\n\n for (let i = 0; i < retry; i++) promise = promise.catch(handler);\n\n return promise.catch((_) => fallback);\n }\n\n public async setup(ships: string[][]): Promise<[boolean, boolean]> {\n return new Promise((resolve, reject) => {\n if (!this.socket) return reject(\"Socket not initialized\");\n\n this.socket.emit(SocketEvent.Setup, ships);\n this.socket.on(\n SocketEvent.SetupResponse,\n (\n status: SetupResponseStatus,\n hostReady: boolean,\n guestReady: boolean\n ) => {\n switch (status) {\n case SetupResponseStatus.Completed:\n return resolve([hostReady, guestReady]);\n case SetupResponseStatus.InvalidPlacement:\n return reject(\"Invalid placements.\");\n }\n }\n );\n\n setTimeout(() => {\n reject(\"Connection timeout 30s.\");\n }, 3000);\n });\n }\n\n public async shoot(pos: string): Promise {\n return new Promise((resolve, reject) => {\n if (!this.socket) {\n reject(\"Socket not initialized.\");\n } else {\n this.socket.emit(SocketEvent.Shoot, pos);\n this.subscribeShootResponse(resolve);\n }\n });\n }\n\n public async withdraw(): Promise {\n return new Promise((resolve, reject) => {\n if (!this.socket) {\n reject(\"Socket not initialized\");\n } else {\n this.socket.emit(SocketEvent.Withdraw);\n // this.subscribeEndResponse(resolve);\n }\n });\n }\n\n ////////////////////\n // Subscriber API //\n ////////////////////\n\n public subscribeAdminSpectate(\n callback: (res: AdminSpectateResponse) => void\n ): void {\n if (!this.socket) return;\n this.socket.on(\n SocketEvent.AdminSpectate,\n (\n responseStatus: AdminSpectateResponse[\"responseStatus\"],\n room: AdminRoomObserver\n ) => {\n callback({\n responseStatus,\n room,\n });\n }\n );\n }\n\n public subscribeShipDestroyed(\n callback: (res: ShipDestroyedResponse) => void\n ) {\n if (!this.socket) return;\n this.socket.on(\n SocketEvent.ShipDestroyed,\n (\n side: ShipDestroyedResponse[\"side\"],\n ship: ShipDestroyedResponse[\"ship\"]\n ) => {\n callback({ side, ship });\n }\n );\n }\n\n public subscribeJoinResponse(callback: (res: JoinRoomResponse) => void) {\n if (this.socket) {\n this.socket.on(\n SocketEvent.JoinRoomResponse,\n (\n responseStatus: JoinRoomResponse[\"responseStatus\"],\n username: JoinRoomResponse[\"username\"]\n ) => {\n callback({ responseStatus, username });\n }\n );\n }\n }\n\n public subscribeStartResponse(callback: (res: StartResponse) => void) {\n if (!this.socket) return;\n this.socket.on(\n SocketEvent.StartResponse,\n (\n responseStatus: StartResponse[\"responseStatus\"],\n firstPlayer: StartResponse[\"firstPlayer\"]\n ) => {\n callback({\n responseStatus,\n firstPlayer,\n });\n }\n );\n }\n\n public subscribeEndResponse(callback: (res: EndResponse) => void) {\n if (!this.socket) return;\n this.socket.on(\n SocketEvent.EndResponse,\n (\n responseStatus: EndResponse[\"responseStatus\"],\n previousRoundWinner: EndResponse[\"previousRoundWinner\"],\n hostScore: EndResponse[\"hostScore\"],\n guestScore: EndResponse[\"guestScore\"]\n ) => {\n callback &&\n callback({\n responseStatus,\n previousRoundWinner,\n hostScore,\n guestScore,\n });\n }\n );\n }\n\n public subscribeShootResponse(callback: (res: ShootResponse) => void) {\n if (!this.socket) return;\n this.socket.on(\n SocketEvent.ShootResponse,\n (\n responseStatus: ShootResponse[\"responseStatus\"],\n location: ShootResponse[\"location\"],\n currentTurnPlayer: ShootResponse[\"currentTurnPlayer\"],\n nextTurnPlayer: ShootResponse[\"nextTurnPlayer\"],\n turnCount: ShootResponse[\"turnCount\"]\n ) => {\n callback({\n responseStatus,\n location,\n currentTurnPlayer,\n nextTurnPlayer,\n turnCount,\n });\n }\n );\n }\n\n public subscribeAvatarResponse(callback: (res: AvatarResponse) => void) {\n if (!this.socket) return;\n this.socket.on(\n SocketEvent.SetAvatarResponse,\n (\n responseStatus: AvatarResponse[\"responseStatus\"],\n hostUsername: AvatarResponse[\"hostUsername\"],\n hostAvatar: AvatarResponse[\"hostAvatar\"],\n guestUsername: AvatarResponse[\"guestUsername\"],\n guestAvatar: AvatarResponse[\"guestAvatar\"]\n ) => {\n callback({\n responseStatus,\n hostAvatar,\n guestAvatar,\n hostUsername,\n guestUsername,\n });\n }\n );\n }\n\n public subscribeChat(callback: (msg: string) => void) {\n if (!this.socket) return;\n this.socket.on(SocketEvent.Chat, (msg: string) => {\n callback(msg);\n });\n }\n\n public subscribeStatistic(callback: (res: StatResponse) => void) {\n if (!this.socket) return;\n this.socket.on(\n SocketEvent.StatResponse,\n (\n responseStatus: InfallibleResponse,\n hostTotal: number,\n hostHit: number,\n hostMiss: number,\n hostAcc: number,\n guestTotal: number,\n guestHit: number,\n guestMiss: number,\n guestAcc: number,\n time: number,\n turnCount: number\n ) => {\n callback({\n responseStatus,\n time,\n turnCount,\n host: {\n total: hostTotal,\n hit: hostHit,\n miss: hostMiss,\n acc: hostAcc,\n },\n guest: {\n total: guestTotal,\n hit: guestHit,\n miss: guestMiss,\n acc: guestAcc,\n },\n });\n }\n );\n }\n}\n\nconst socket = new SocketClient(); // singleton pattern\n\nexport default socket;\n","import { createContext, useContext } from \"react\";\n\n// initializes with empty Product\nexport const UserContext = createContext<{\n username: string;\n userAvatarSeed: string;\n isAdmin: boolean;\n setUsername: (username: string) => void;\n setUserAvatarSeed: (userAvatarSeed: string) => void;\n setIsAdmin: (isAdmin: boolean) => void;\n}>({\n username: \"\",\n userAvatarSeed: \"\",\n isAdmin: false,\n setUsername: () => {},\n setUserAvatarSeed: () => {},\n setIsAdmin: () => {},\n});\n\nexport const useUserContext = () => useContext(UserContext);\n","export const DEFAULT_GRID_SIZE = 8;\n","import { Position } from \"./utility\";\n\nexport enum BattleshipType {\n Default,\n Submarine,\n ACC,\n}\n\nexport enum BattleshipPartType {\n Front = 0,\n Middle,\n Back,\n Single,\n}\n\nexport enum BattleshipDirection {\n Vertical = 0,\n Horizontal = 1,\n VerticalRev = 2,\n HorizontalRev = 3,\n}\n\nexport enum BattleshipStatus {\n Default = 0,\n Hidden,\n Sunken,\n Placeholder,\n}\n\nexport interface BattleshipBase {\n name: string;\n length: number;\n status: BattleshipStatus;\n}\n\nexport interface BattleshipKnown extends BattleshipBase {\n position: Position;\n direction: BattleshipDirection;\n}\n\nexport interface BattleshipAlly extends BattleshipKnown {\n status: BattleshipStatus.Default;\n}\n\nexport interface BattleshipSunken extends BattleshipKnown {\n status: BattleshipStatus.Sunken;\n}\n\nexport interface BattleshipPlaceholder extends BattleshipKnown {\n status: BattleshipStatus.Placeholder;\n}\n\nexport interface BattleshipHidden extends BattleshipBase {\n status: BattleshipStatus.Hidden;\n}\n\nexport type BattleshipAllyYard = (BattleshipAlly | BattleshipSunken | BattleshipPlaceholder)[];\n\nexport type BattleshipYard = (\n | BattleshipAlly\n | BattleshipSunken\n | BattleshipHidden\n | BattleshipPlaceholder\n)[];\n\nexport interface BattleshipState {\n ally: BattleshipAllyYard;\n enemy: BattleshipYard;\n}\n\n/**\n * Rendering State Wrapper\n */\n\nexport interface BattleshipPartRdState {\n battleship: BattleshipKnown;\n partType: BattleshipPartType;\n}\n","import { GameState, Phase } from \"../types/state\";\nimport { DEFAULT_GRID_SIZE } from \"./size\";\n\nexport const initialGameState: GameState = {\n meta: {\n turn: 1, \n round: 1,\n phase: Phase.Setup, \n }, \n board: {\n gridSize: DEFAULT_GRID_SIZE,\n ally: {},\n enemy: {},\n },\n battleship: {\n ally: [], \n enemy: [], \n },\n};\n","import { createContext, useContext } from \"react\";\nimport { GameAction } from \"../types/action\";\nimport { GameState, Phase } from \"../types/state\";\n\n// initializes with empty Product\nexport const GameStateContext = createContext<{\n state: GameState;\n dispatch: React.Dispatch;\n}>({\n state: {\n meta: {\n turn: 1,\n round: 1,\n phase: Phase.Setup,\n },\n board: {\n ally: {},\n enemy: {},\n gridSize: 0,\n },\n battleship: {\n ally: [],\n enemy: [],\n },\n },\n dispatch: () => {},\n});\n\nexport const useGameStateContext = () => useContext(GameStateContext);\n","import React from \"react\";\nimport baseStyled, {\n ThemeContext,\n ThemedBaseStyledInterface,\n} from \"styled-components\";\n\nconst theme = {\n colors: {\n square: {\n ally: {\n circle: \"#6745FF\",\n background: {\n light: \"#947EFF\",\n medium: \"#947EFF\",\n },\n },\n enemy: {\n circle: \"#6745FF\",\n background: {\n light: \"#947EFF\",\n medium: \"#947EFF\",\n },\n },\n text: {\n position: \"white\",\n },\n },\n danger: {\n main: \"#FF9A61\",\n },\n tutorial: {\n modal: {\n background: {\n primary: \"#674def\",\n light: \"#FFFFFF\",\n },\n },\n infoButton: {\n background: \"#FFFFFF\",\n text: \"#917DF8\",\n },\n },\n lobby: {\n avatar: {\n background: {\n light: \"#FFDBB4\",\n medium: \"#FFB463\",\n white: \"#FFFFFF\",\n },\n selected: \"#674DEF\",\n text: {\n name: \"#3A2105\",\n versus: \"#d57f23\",\n score: \"#743c00\",\n chat: \"#6d3900\",\n },\n },\n backdrop: {\n medium: \"#7B61FF\",\n dark: \"#674DEF\",\n shadedLight: \"#F8F7FF\",\n light: \"#FFFFFF\",\n },\n button: {\n background: {\n primary: \"#6D51FD\",\n secondary: \"#F0EDFF\",\n room: \"#FFFFFF\",\n startGame: \"#FFFFFF\",\n },\n text: {\n primary: \"#FFFFFF\",\n secondary: \"#6D51FD\",\n room: \"#8A77EF\",\n roomDark: \"#1C0B76\",\n startGame: \"#674def\",\n },\n },\n slider: {\n background: {\n dark: \"#302B4A\",\n light: \"#FFFFFF\",\n },\n text: {\n selected: \"#7b61ff\",\n default: \"#D1CCEA\",\n },\n },\n input: {\n background: {\n light: \"#F5F3FC\",\n },\n text: {\n placeholder: \"#bcb7e2\",\n },\n },\n info: {\n heading: \"#1E088E\",\n label: \"#9591a4\",\n guidelines: \"#b0aace\",\n battleship: \"#ffffff\",\n },\n credits: {\n light: \"#9a86ff\",\n medium: \"#C0B4F9\",\n },\n },\n },\n breakPoints: {\n mobile: 860,\n tablet: 1200,\n desktop: 1920,\n widescreen: 2560,\n },\n};\n\nexport type Theme = typeof theme;\n\nconst useTheme = (): Theme => {\n return React.useContext(ThemeContext);\n};\n\nexport { theme, useTheme };\n\nconst styled: ThemedBaseStyledInterface = baseStyled;\n\nexport default styled;\n","import { Position, Side } from \"./utility\";\n\nexport enum BoardSquareStatus {\n Missed,\n Hit,\n}\n\nexport interface ContactedBoardSquare {\n position: Position;\n status: BoardSquareStatus;\n}\n\nexport type UniBoardState = Record; // key = posToString(position)\n\nexport type BoardState = {\n gridSize: number;\n} & Record;\n","import { FC } from \"react\";\nimport styled, { css } from \"styled-components\";\nimport {\n BattleshipDirection,\n BattleshipPartType,\n BattleshipType,\n} from \"../types/battleship\";\n\nconst ROTATE_DEG_MAP = [0, 270, 180, 90];\n\nexport interface Props {\n size?: number;\n color?: string;\n zIndex?: number;\n translateFixed?: boolean;\n part: BattleshipPartType;\n direction: BattleshipDirection;\n type?: BattleshipType;\n}\n\nconst ShipPart: FC = ({\n part,\n direction,\n size = 32,\n zIndex = 1,\n translateFixed = true,\n color = \"rgba(100%, 100%, 100%)\",\n type = BattleshipType.Default,\n}) => {\n let rotateDeg = ROTATE_DEG_MAP[direction];\n let renderedShip = null;\n\n switch (part) {\n case BattleshipPartType.Front:\n renderedShip = (\n \n \n \n );\n break;\n case BattleshipPartType.Middle:\n renderedShip = (\n \n \n \n );\n break;\n case BattleshipPartType.Back:\n renderedShip = (\n \n \n \n );\n break;\n case BattleshipPartType.Single:\n renderedShip = ;\n }\n\n return (\n \n {renderedShip}\n \n );\n};\n\nexport default ShipPart;\n\ninterface WrapperProps {\n rotate: number;\n size: number;\n fixed: boolean;\n}\n\nconst Wrapper = styled.div`\n display: flex;\n align-items: center;\n justify-content: center;\n width: 2rem;\n height: 2rem;\n opacity: 0.9;\n transform-origin: center center;\n\n ${({ fixed, rotate }) =>\n !fixed\n ? \"\"\n : css`\n transform: translate(-0.125rem, -0.125rem)\n rotate(${rotate}deg);\n `}\n\n & > svg {\n height: ${({ size }) => `${size / 16}rem`};\n width: ${({ size }) => `${size / 16}rem`};\n }\n`;\n\nconst SingleShip = styled.div`\n width: 1.75rem;\n height: 1.75rem;\n border-radius: 0.625rem;\n`;\n","import { Position } from \"../types/utility\";\n\nfunction posToString({ row, col }: Position): string {\n return `${row},${col}`;\n}\n\nexport default posToString; ","import styled from \"../../../styles/theme\";\nimport ShipPart from \"./Ship\";\nimport { BattleshipPartRdState, BattleshipStatus } from \"../types/battleship\";\nimport { BoardSquareStatus } from \"../types/board\";\nimport { Position, Side } from \"../types/utility\";\nimport { useGameStateContext } from \"../../game/contexts/gameStateContext\";\nimport posToString from \"../functions/posToString\";\nimport { MouseEventHandler, useCallback } from \"react\";\nimport { css } from \"styled-components\";\n\ninterface Props {\n squareType?: Side;\n position?: Position;\n part?: BattleshipPartRdState;\n selectable?: boolean;\n onClick?: MouseEventHandler;\n onHoverStart?: MouseEventHandler;\n onHoverEnd?: MouseEventHandler;\n [key: string]: any; \n}\n\nconst Square: React.FC = ({\n squareType = Side.Ally,\n position,\n part,\n onClick,\n onHoverStart,\n onHoverEnd,\n selectable = true,\n ...delegated\n}) => {\n const { state, dispatch } = useGameStateContext();\n\n const status =\n position && state.board[squareType][posToString(position)]?.status;\n const isSunken = part && part.battleship.status === BattleshipStatus.Sunken;\n\n const handleSelectClick = useCallback(() => {\n if (position && selectable) {\n dispatch({\n type: \"MARK_SQUARE\",\n payload: {\n side: squareType,\n position,\n status: BoardSquareStatus.Missed,\n },\n });\n }\n }, [dispatch, position, selectable, squareType]);\n\n return (\n \n {position?.row === 1 && (\n \n {String.fromCharCode(65 + position?.col - 1)}\n \n )}\n {position?.col === 1 && (\n {position.row}\n )}\n {part && (\n \n )}\n \n \n );\n};\n\nconst Container = styled.div<{ squareType: Side, selectable: boolean }>`\n position: relative;\n\n background: ${(props) =>\n (props.theme.colors.square as any)[props.squareType].background.light};\n\n border: 0.125rem solid\n ${(props) => props.theme.colors.lobby.backdrop.medium};\n border-radius: 0.25rem;\n\n width: 2rem;\n height: 2rem;\n\n display: grid;\n place-items: center;\n\n cursor: pointer;\n\n & > .positional {\n font-weight: bold;\n\n height: 100%;\n width: 100%;\n\n display: grid;\n place-items: center;\n\n color: ${(props) => props.theme.colors.square.text.position};\n\n user-select: none;\n }\n\n ${({ selectable, theme }) => selectable && css`\n &::after {\n content: \"\";\n width: 0.875rem;\n height: 0.875rem;\n border-radius: 50%;\n position: absolute;\n background: ${theme.colors.square.ally.circle};\n z-index: 1;\n opacity: 0;\n transition: opacity 350ms ease;\n }\n\n &:hover::after {\n opacity: 0.75;\n }\n `}\n`;\n\nconst ColumnAlphabet = styled.div`\n position: absolute;\n top: -2rem;\n`;\n\nconst RowNumber = styled.div`\n position: absolute;\n left: -2rem;\n`;\n\nconst Circle = styled.div<{ squareType: Side; status?: BoardSquareStatus }>`\n width: 0.875rem;\n height: 0.875rem;\n position: absolute;\n z-index: 2;\n border-radius: 50%;\n\n background: ${({ theme, status, squareType }) => {\n switch (status) {\n case BoardSquareStatus.Hit:\n return theme.colors.danger.main;\n case BoardSquareStatus.Missed:\n return (theme.colors.square as any)[squareType].circle;\n }\n }};\n`;\n\nexport default Square;\n","import posToString from \"./posToString\";\nimport {\n BattleshipAllyYard,\n BattleshipDirection,\n BattleshipPartType,\n BattleshipPartRdState,\n} from \"../types/battleship\";\n\nfunction mapPosToBattleshipPart(\n shipYard: BattleshipAllyYard, \n validate: boolean = true, \n): Map {\n const map: Map = new Map();\n\n shipYard.forEach((battleship) => {\n const { length, direction } = battleship;\n const position = { ...battleship.position };\n\n for (let i = 0; i < length; i++) {\n if (validate) {\n if (map.has(posToString(position)))\n throw Error(\"The ally grid has overlapped battleships.\");\n \n for (let j = 0; j < 9; j++) {\n const rowOffset = Math.floor(j / 3) - 1;\n const colOffset = (j % 3) - 1;\n \n if (rowOffset === 0 && colOffset === 0) continue;\n \n const targetPosition = {\n col: position.col + colOffset,\n row: position.row + rowOffset,\n };\n \n const potentialAdjacent = map.get(posToString(targetPosition));\n if (\n potentialAdjacent &&\n potentialAdjacent.battleship !== battleship\n )\n throw Error(\"Two ships are too close to each other.\");\n }\n }\n\n let partType: BattleshipPartType;\n\n if (i === 0) partType = BattleshipPartType.Front;\n else if (i === length - 1) partType = BattleshipPartType.Back;\n else partType = BattleshipPartType.Middle;\n\n if (length === 1) partType = BattleshipPartType.Single;\n\n map.set(posToString(position), {\n battleship,\n partType,\n });\n\n switch (direction) {\n case BattleshipDirection.Vertical:\n position.row++;\n break;\n case BattleshipDirection.Horizontal:\n position.col++;\n break;\n case BattleshipDirection.VerticalRev:\n position.row--;\n break;\n case BattleshipDirection.HorizontalRev:\n position.col--;\n break;\n }\n }\n });\n\n return map;\n}\n\nexport default mapPosToBattleshipPart;\n","import { BattleshipHidden, BattleshipKnown } from \"../../board/types/battleship\";\n\nexport enum PlacementStatus {\n Placed = 0,\n Placing, \n Undecided, \n}\n\nexport type Placement =\n | {\n battleship: BattleshipKnown;\n selected: boolean; \n status: PlacementStatus.Placed | PlacementStatus.Placing;\n }\n | {\n battleship: BattleshipHidden;\n selected: boolean; \n status: PlacementStatus.Undecided;\n };\n\nexport type PlacementList = Placement[];\n","const generateArrayOfNumbers = (length: number): number[] => {\n let i = 0,\n a = Array(length);\n while (i < length) a[i++] = i;\n return a;\n};\n\nexport default generateArrayOfNumbers;\n","import { MouseEvent, useMemo } from \"react\";\nimport styled from \"styled-components\";\nimport Square from \"./components/Square\";\nimport mapPosToBattleshipPart from \"./functions/mapPosToBattleshipPart\";\nimport posToString from \"./functions/posToString\";\nimport {\n BattleshipAllyYard,\n BattleshipPartType,\n BattleshipStatus,\n BattleshipYard,\n} from \"./types/battleship\";\nimport { Position, Side } from \"./types/utility\";\nimport { useGameStateContext } from \"../game/contexts/gameStateContext\";\nimport generateArrayOfNumbers from \"./functions/generateArrayOfNumbers\";\n\ntype Props = InteractiveProps & (AllyProps | EnemyProps);\n\ninterface InteractiveProps {\n hitCount?: number; \n selectable?: boolean;\n validate?: boolean;\n availability?: boolean[][];\n onSquareHoverStart?: (p: Position, e: MouseEvent) => any;\n onSquareHoverEnd?: (p: Position, e: MouseEvent) => any;\n onSquareClick?: (p: Position, e: MouseEvent) => any;\n [key: string]: any; \n}\n\ninterface AllyProps {\n boardType: Side.Ally;\n shipYard: BattleshipAllyYard;\n}\n\ninterface EnemyProps {\n boardType: Side.Enemy;\n shipYard: BattleshipYard;\n}\n\nconst Board: React.FC = ({\n hitCount, \n boardType,\n shipYard,\n selectable,\n validate,\n availability,\n onSquareHoverEnd,\n onSquareHoverStart,\n onSquareClick,\n ...delegated\n}) => {\n const { board } = useGameStateContext().state;\n\n const mappedBattleshipPart = useMemo(() => {\n if (boardType === Side.Ally)\n return mapPosToBattleshipPart(\n shipYard as BattleshipAllyYard,\n validate\n );\n return mapPosToBattleshipPart(\n shipYard.filter(\n ({ status }) => status !== BattleshipStatus.Hidden\n ) as BattleshipAllyYard,\n validate\n );\n }, [shipYard, boardType, validate]);\n\n const renderedSquares = useMemo(() => {\n return generateArrayOfNumbers(board.gridSize).map((row) =>\n generateArrayOfNumbers(board.gridSize).map((col) => {\n const position = { row, col };\n const key = posToString(position);\n\n const isPlacing =\n mappedBattleshipPart.get(key)?.battleship.status ===\n BattleshipStatus.Placeholder;\n\n const isHead =\n mappedBattleshipPart.get(key)?.partType ===\n BattleshipPartType.Front;\n\n const interactive =\n availability === undefined ||\n (!isHead && isPlacing) ||\n (availability !== undefined &&\n availability[row - 1][col - 1]);\n\n return (\n \n onSquareClick && onSquareClick(position, e)\n }\n onHoverStart={(e) =>\n onSquareHoverStart &&\n onSquareHoverStart(position, e)\n }\n onHoverEnd={(e) =>\n onSquareHoverEnd && onSquareHoverEnd(position, e)\n }\n />\n );\n })\n );\n }, [\n board.gridSize,\n boardType,\n mappedBattleshipPart,\n selectable,\n availability,\n onSquareClick,\n onSquareHoverEnd,\n onSquareHoverStart,\n ]);\n\n return (\n \n {renderedSquares}\n {hitCount !== undefined && {hitCount} / 16}\n \n );\n};\n\ninterface ContainerProps {\n gridSize: number;\n}\n\nconst Container = styled.div`\n position: relative;\n z-index: 0;\n display: grid;\n grid-template-columns: repeat(\n ${({ gridSize }) => `${gridSize}`},\n min-content\n );\n grid-template-rows: repeat(${({ gridSize }) => `${gridSize}`}, min-content);\n`;\n\nconst HitCount = styled.div`\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0.25rem 0.5rem;\n border-radius: 0.375rem;\n background: #7b61ff;\n color: white;\n\n position: absolute;\n bottom: -2.5rem;\n left: 50%;\n transform: translateX(-50%);\n font-size: 1rem; \n font-weight: 500; \n`;\n\nexport default Board;\n","import { FC } from \"react\";\n\ninterface Props {\n size: number; \n color?: string; \n [key: string]: any; \n}; \n\nconst Win: FC = ({ size, color, ...delegated }) => {\n return (\n \n \n \n );\n\n}\n\nexport default Win;","import { FC } from \"react\";\n\ninterface Props {\n size: number;\n color?: string;\n [key: string]: any;\n}\n\nconst Lose: FC = ({ size, color, ...delegated }) => {\n return (\n \n \n \n \n \n \n \n \n \n \n );\n};\n\nexport default Lose;\n","import styled from \"styled-components\";\nimport moment from 'moment';\nimport { FC } from \"react\";\nimport { StatResponse } from \"../../api/types/transport\";\nimport Win from \"./components/win\";\nimport Lose from \"./components/lose\";\n\ninterface Props {\n winners: (\"Host\" | \"Guest\")[];\n stats: StatResponse[];\n}\n\nconst Result: FC = ({ stats, winners }) => {\n return (\n \n {stats.map((st, index) => {\n const winner = winners[index];\n const timestamp = moment(st.time).format(\"m:ss\");\n return (\n \n \n {st.host.hit}/{st.host.total}/{st.host.acc.toFixed(0)}%\n \n \n {winner === \"Host\" ? (\n \n ) : (\n \n )}\n \n {timestamp} ({st.turnCount})\n \n {winner === \"Guest\" ? (\n \n ) : (\n \n )}\n \n \n {st.guest.hit}/{st.guest.total}/{st.guest.acc.toFixed(0)}%\n \n \n );\n })}\n \n );\n};\n\nexport default Result;\n\nconst Wrapper = styled.div`\n display: flex;\n flex-flow: column;\n max-height: 15rem; \n height: min-content; \n min-width: 38.9375rem;\n background: white;\n border-radius: 0 0 0.75rem 0.75rem;\n overflow: auto; \n`;\n\nconst Row = styled.div`\n width: 100%;\n background: white;\n min-height: 3rem; \n height: 3rem; \n position: relative; \n display: flex; \n flex-flow: row; \n align-items: center; \n justify-content: center;\n\n &:nth-child(even) {\n background: #f3f1ff;\n }\n`;\n\nconst LeftStats = styled.span`\n font-size: 1rem;\n color: #b1a5ec;\n position: absolute; \n left: 3.125rem; \n`;\n\nconst RightStats = styled(LeftStats)`\n right: 3.125rem; \n left: auto; \n`;\n\n\nconst RoundInfo = styled.span`\n display: flex; \n flex-flow: row; \n align-items: center;\n justify-content: space-between;\n width: 13.5rem; \n`;\n\nconst RoundTime = styled.span`\n color: #584f86;\n font-size: 1rem;\n font-weight: 500; \n`;","import { useLocation } from \"react-router-dom\";\n\nconst useQuery = () => {\n return new URLSearchParams(useLocation().search);\n};\n\nexport default useQuery;\n","import posToString from \"../../board/functions/posToString\";\nimport { BattleshipStatus } from \"../../board/types/battleship\";\nimport { Side } from \"../../board/types/utility\";\nimport { GameAction } from \"../types/action\";\nimport { GameState } from \"../types/state\";\n\nconst gameStateReducer = (\n prevState: GameState,\n action: GameAction\n): GameState => {\n switch (action.type) {\n case \"GAME_START\":\n return {\n ...prevState,\n battleship: {\n ...prevState.battleship,\n ally: action.payload.shipyard,\n enemy: [],\n },\n };\n case \"MARK_SQUARE\":\n return {\n ...prevState,\n board: {\n ...prevState.board,\n [action.payload.side]: {\n ...prevState.board[action.payload.side],\n [posToString(action.payload.position)]: {\n position: action.payload.position,\n status: action.payload.status,\n },\n },\n },\n };\n case \"RESET_BOARD\":\n return {\n ...prevState,\n board: {\n ...prevState.board, \n ally: {},\n enemy: {},\n },\n battleship: {\n ally: [],\n enemy: [],\n },\n };\n case \"SUNK_SHIP\":\n if (action.payload.side === Side.Enemy) {\n const length = prevState.battleship.enemy.length;\n return {\n ...prevState,\n battleship: {\n ...prevState.battleship,\n enemy: [\n ...prevState.battleship.enemy,\n {\n ...action.payload.battleship, \n name: length.toString(), \n status: BattleshipStatus.Sunken\n },\n ],\n },\n };\n }\n \n const length = prevState.battleship.ally.length; \n const index = prevState.battleship.ally.findIndex(\n (s) =>\n s.position.col === action.payload.battleship.position.col &&\n s.position.row === action.payload.battleship.position.row\n );\n\n if (index === -1)\n throw new Error('Unexpected sunked ship reported by server'); \n\n return {\n ...prevState,\n battleship: {\n ...prevState.battleship, \n ally: [\n ...prevState.battleship.ally.slice(0, index),\n {\n ...action.payload.battleship, \n name: length.toString(), \n status: BattleshipStatus.Sunken, \n }, \n ...prevState.battleship.ally.slice(index + 1),\n ]\n },\n };\n default:\n return prevState;\n }\n};\n\nexport default gameStateReducer;\n","import { BattleshipHidden, BattleshipStatus } from '../../board/types/battleship'\nimport { PlacementList, PlacementStatus } from '../types/placement'\n\nexport const INIT_BATTLESHIP: BattleshipHidden = {\n name: '0', \n length: 4, \n status: BattleshipStatus.Hidden, \n}\n\nexport const INIT_PLACEMENT_LIST: PlacementList = [\n {\n selected: false, \n status: PlacementStatus.Undecided, \n battleship: {\n ...INIT_BATTLESHIP, \n name: '1', \n },\n },\n {\n selected: false, \n status: PlacementStatus.Undecided, \n battleship: {\n ...INIT_BATTLESHIP, \n name: '2', \n },\n },\n {\n selected: false, \n status: PlacementStatus.Undecided, \n battleship: {\n ...INIT_BATTLESHIP, \n name: '3', \n },\n },\n {\n selected: false, \n status: PlacementStatus.Undecided, \n battleship: {\n ...INIT_BATTLESHIP, \n name: '4', \n },\n }\n]","export interface AvatarProperties {\n username?: string;\n seed?: string;\n score?: number;\n}\n\nexport enum AvatarSide {\n Left = \"left\",\n Right = \"right\",\n}\n","import { FC, MouseEvent } from \"react\";\nimport styled, { css } from \"styled-components\";\nimport ShipPart from \"../../board/components/Ship\";\nimport {\n BattleshipBase,\n BattleshipDirection,\n BattleshipPartType,\n} from \"../../board/types/battleship\";\nimport { PlacementStatus } from \"../types/placement\";\n\ninterface ShipProps {\n battleship: BattleshipBase;\n status: PlacementStatus;\n selected: boolean; \n onClick: (e: MouseEvent) => void;\n}\n\nconst Ship: FC = ({ battleship, status, selected, onClick }) => {\n const opacity = status === PlacementStatus.Placed ? 0.4 : 1.0;\n const pointerEvents = status === PlacementStatus.Placed ? 'none' : 'auto';\n\n return (\n \n \n \n \n \n {battleship.name}\n \n );\n};\n\nexport default Ship;\n\ninterface ShipWrapperProps {\n selected: boolean;\n}\n\nconst ShipWrapper = styled.div`\n display: flex;\n flex-flow: column nowrap;\n align-items: center;\n justify-content: center;\n height: min-content;\n margin: 0.375rem 1px 0;\n position: relative; \n\n ${({ selected }) => {\n if (selected) return css`\n &::before {\n content: \"\";\n border-radius: 8px;\n border: 4px solid #fff06b;\n position: absolute;\n width: calc(100% - 3px);\n height: calc(100% - 3px);\n box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.15),\n inset 0 0 8px rgba(0, 0, 0, 0.15);\n }\n `;\n }}\n`;\n\nconst ShipNumber = styled.span`\n position: absolute;\n font-size: 1.75rem;\n color: #bbb1e9;\n font-weight: 700;\n z-index: 2;\n`;\n","import { FC } from 'react'; \nimport styled from 'styled-components';\n\nconst RefreshIcon: FC = () => {\n return (\n \n \n \n );\n};\n\nexport default RefreshIcon; \n\nconst RandomSvg = styled.svg`\n margin-right: 0.375rem;\n`;","import {\n BattleshipAlly,\n BattleshipDirection,\n BattleshipStatus,\n} from \"../../board/types/battleship\";\nimport { Position } from \"../../board/types/utility\";\n\nconst COLUMN: { [index: string]: number } = {\n A: 1,\n B: 2,\n C: 3,\n D: 4,\n E: 5,\n F: 6,\n G: 7,\n H: 8,\n};\n\nconst stringToPos = (s: string): Position => {\n const col = COLUMN[s[0].toUpperCase()];\n const row = parseInt(s[1]);\n\n return { row, col };\n};\n\nconst deserializePlacements = (ships: string[][]): BattleshipAlly[] => {\n const fmShips = ships.map((i) => i.map((j) => stringToPos(j)));\n const fmShipyard: BattleshipAlly[] = fmShips.map((pos, index) => {\n const reverse = Math.random() > 0.5;\n\n const deltaY = pos[1].row - pos[0].row;\n const axis =\n deltaY !== 0\n ? BattleshipDirection.Vertical\n : BattleshipDirection.Horizontal;\n\n const direction = (reverse ? axis + 2 : axis) as BattleshipDirection;\n const head = reverse ? pos[pos.length - 1] : pos[0];\n \n return {\n direction, \n position: head, \n length: pos.length, \n name: (index + 1).toString(),\n status: BattleshipStatus.Default, \n }\n });\n\n return fmShipyard;\n};\n\nexport default deserializePlacements;\n","import { BattleshipKnown } from \"../../board/types/battleship\";\nimport { Position } from \"../../board/types/utility\";\n\nconst COLUMN: string[] = [\"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\"];\nconst DELTA: Position[] = [\n { row: 1, col: 0 },\n { row: 0, col: 1 },\n { row: -1, col: 0 },\n { row: 0, col: -1 },\n];\n\nconst serializePlacements = (shipyard: BattleshipKnown[]): string[][] => {\n return shipyard.map((ship) => {\n const { position, direction } = ship; \n const delta = DELTA[direction]; \n\n let cells: string[] = [];\n let origin = { ...position }; \n for (let i = 0; i < ship.length; i++){\n cells.push(`${COLUMN[origin.col - 1]}${origin.row}`); \n origin.col += delta.col; \n origin.row += delta.row; \n }\n\n return cells; \n });\n};\n\nexport default serializePlacements;\n","import { BattleshipDirection, BattleshipKnown } from \"../types/battleship\";\nimport { Position } from \"../types/utility\";\n\nconst safeSet = (arr: T[][], value: T, row: number, col: number) => {\n const gridSize = arr.length;\n if (row >= gridSize || row < 0 || col >= gridSize || col < 0) return;\n else arr[row][col] = value;\n};\n\nconst getDeltaFromDirection = (dir: BattleshipDirection): Position => {\n let deltaX = 0,\n deltaY = 0;\n\n if (dir === BattleshipDirection.Horizontal) deltaX = 1;\n else if (dir === BattleshipDirection.HorizontalRev) deltaX = -1;\n\n if (dir === BattleshipDirection.Vertical) deltaY = 1;\n else if (dir === BattleshipDirection.VerticalRev) deltaY = -1;\n\n return { row: deltaY, col: deltaX };\n};\n\nconst getAvailableSquares = (\n length: number,\n direction: BattleshipDirection,\n shipyard: BattleshipKnown[],\n gridSize: number = 8\n) => {\n const board: boolean[][] = [];\n\n for (let i = 0; i < gridSize; i++) {\n board.push([]);\n for (let j = 0; j < gridSize; j++) {\n board[i].push(true);\n }\n }\n\n shipyard.forEach((ship) => {\n const delta = getDeltaFromDirection(ship.direction);\n let pos = { ...ship.position };\n\n for (let i = 0; i < ship.length; i++) {\n const row = pos.row - 1;\n const col = pos.col - 1;\n\n for (let x = -1; x <= 1; x++)\n for (let y = -1; y <= 1; y++)\n safeSet(board, false, row + y, col + x);\n\n pos = {\n row: pos.row + delta.row,\n col: pos.col + delta.col,\n };\n }\n });\n\n const visited = board.map((x) => x.map((y) => !y));\n const delta = getDeltaFromDirection(direction);\n const sum = delta.row + delta.col;\n const begin = sum >= 0 ? gridSize - 1 : 0;\n const end = sum >= 0 ? -1 : gridSize;\n\n const search = (i: number, j: number, depth: number) => {\n if (i >= gridSize || j >= gridSize || i < 0 || j < 0) return;\n if (visited[i][j]) return;\n else visited[i][j] = true;\n if (depth < length) board[i][j] = false;\n search(i - delta.row, j - delta.col, depth + 1);\n };\n\n for (let i = begin; i !== end; i -= sum) {\n for (let j = begin; j !== end; j -= sum) {\n board[i][j] && search(i, j, 1);\n }\n }\n\n return board;\n};\n\nexport default getAvailableSquares;\n","import { FC } from \"react\";\n\ninterface Props {\n size?: number | string;\n color?: string;\n}\n\nconst Left: FC = ({ size, color }) => {\n return (\n \n \n \n );\n};\n\nexport default Left;\n","import { FC, MouseEvent, useState, useEffect, useMemo, useCallback } from \"react\";\nimport { Position, Side } from \"../board/types/utility\";\nimport { PlacementList, PlacementStatus } from \"./types/placement\";\nimport { INIT_PLACEMENT_LIST } from \"./constants/list\";\nimport styled, { css } from \"styled-components\";\nimport Board from \"../board\";\nimport Ship from \"./components/ship\";\nimport Refresh from \"./components/refresh\";\nimport socketClient from \"../../api/socketClient\";\nimport deserializePlacements from \"./functions/deserializePlacements\";\nimport serializePlacements from \"./functions/serializePlacements\";\nimport {\n BattleshipAlly,\n BattleshipAllyYard,\n BattleshipBase,\n BattleshipDirection,\n BattleshipStatus,\n} from \"../board/types/battleship\";\nimport getAvailableSquares from \"../board/functions/getAvailableSquares\";\nimport Left from \"../game/components/left\";\n\ninterface Props {\n onSubmit: (shipyard: BattleshipAllyYard) => void;\n}\n\nconst SetupModal: FC = ({ onSubmit }) => {\n const [placements, setPlacements] = useState(INIT_PLACEMENT_LIST);\n const [direction, setDirection] = useState(BattleshipDirection.Vertical);\n const [waiting, setWaiting] = useState(false);\n\n const shipyard = placements\n .filter(\n (p) =>\n p.battleship.status === BattleshipStatus.Default ||\n p.battleship.status === BattleshipStatus.Placeholder\n )\n .map((p) => p.battleship) as BattleshipAllyYard;\n\n const availableSquares = useMemo(() => {\n const selected = placements.find((p) => p.selected);\n if (!selected) return undefined;\n return getAvailableSquares(\n selected.battleship.length,\n direction,\n shipyard.filter((s) => s.status !== BattleshipStatus.Placeholder)\n );\n }, [placements, shipyard, direction]);\n\n const onShipClick = (battleship: BattleshipBase, _e: MouseEvent) => {\n const index = placements.findIndex((p) => p.battleship === battleship);\n const nextPlacements = placements.map((p, i) => {\n if (i === index) return { ...p, selected: true };\n return { ...p, selected: false };\n });\n\n setPlacements(nextPlacements);\n };\n\n const onSquareHoverStart = (position: Position, _e: MouseEvent) => {\n const index = placements.findIndex((p) => p.selected);\n\n if (index === -1) return;\n\n const nextPlacements: PlacementList = placements.map((p, i) => {\n if (i !== index) return p;\n\n return {\n battleship: {\n ...p.battleship,\n position,\n direction,\n status: BattleshipStatus.Placeholder,\n },\n selected: p.selected,\n status: PlacementStatus.Placing,\n };\n });\n\n setPlacements(nextPlacements);\n };\n\n const onSquareHoverEnd = (_position: Position, _e: MouseEvent) => {\n const index = placements.findIndex((p) => p.selected);\n\n if (index === -1) return;\n\n const nextPlacements: PlacementList = placements.map((p, i) => {\n if (i !== index) return p;\n return {\n battleship: {\n name: p.battleship.name,\n length: p.battleship.length,\n status: BattleshipStatus.Hidden,\n },\n selected: p.selected,\n status: PlacementStatus.Undecided,\n };\n });\n\n setPlacements(nextPlacements);\n };\n\n const onSquareClick = (_position: Position, _e: MouseEvent) => {\n const index = placements.findIndex((p) => p.selected);\n\n if (index === -1) return;\n\n const nextPlacements: PlacementList = placements.map((p, i) => {\n if (i !== index || p.battleship.status === BattleshipStatus.Hidden)\n return p;\n\n return {\n battleship: {\n ...p.battleship,\n status: BattleshipStatus.Default,\n },\n selected: false,\n status: PlacementStatus.Placed,\n };\n });\n\n setPlacements(nextPlacements);\n };\n\n const onReset = (_e: MouseEvent) => {\n setPlacements(INIT_PLACEMENT_LIST);\n };\n\n const onRandomize = async (_e: MouseEvent) => {\n const ships = await socketClient.randomize(4, 4, 30);\n const formattedShips = deserializePlacements(ships);\n\n const nextPlacements: PlacementList = formattedShips.map((fs) => ({\n battleship: fs,\n selected: false,\n status: PlacementStatus.Placed,\n }));\n\n setPlacements(nextPlacements);\n };\n\n const onReady = async (_e: MouseEvent) => {\n if (placements.find((p) => p.status !== PlacementStatus.Placed))\n throw new Error(\"Not all battleships are placed\");\n\n const shipyard = placements.map((p) => p.battleship as BattleshipAlly);\n const serialized = serializePlacements(shipyard);\n const [hostReady, guestReady] = await socketClient.setup(serialized);\n\n if (hostReady && guestReady) return onSubmit(shipyard);\n\n setWaiting(true);\n await socketClient.waitReady();\n return onSubmit(shipyard);\n };\n\n const renderedShip = placements.map((p) => (\n onShipClick(p.battleship, e)}\n />\n ));\n\n const onRotate = useCallback(() => {\n const index = placements.findIndex((p) => p.selected);\n setDirection((direction + 1) % 4);\n\n if (index === -1) return;\n\n const nextPlacements: PlacementList = placements.map((p, i) => {\n if (i !== index || p.status === PlacementStatus.Undecided)\n return p;\n return {\n battleship: {\n ...p.battleship,\n direction: (p.battleship.direction + 1) % 4,\n },\n selected: p.selected,\n status: PlacementStatus.Placing,\n };\n });\n\n setPlacements(nextPlacements);\n }, [placements, direction]);\n\n useEffect(() => {\n const fn = (e: KeyboardEvent) => {\n if (e.code === \"Space\") {\n onRotate();\n }\n };\n\n document.addEventListener(\"keypress\", fn);\n return () => document.removeEventListener(\"keypress\", fn);\n }, [placements, direction, onRotate]);\n\n return (\n \n \n Plan your ship positions...\n \n \n Random\n \n \n \n \n \n Shipyard\n {renderedShip}\n \n \n \n \n \n Reset\n \n \n \n \n {waiting ? \"Waiting for another player...\" : \"Ready!\"}\n \n );\n};\n\nexport default SetupModal;\n\nconst Spacer = styled.div``;\n\nconst Wrapper = styled.div`\n display: grid;\n grid-template-columns: 1fr;\n grid-template-rows: min-content 3rem minmax(0, 19rem) 1.5rem min-content;\n padding: 1.75rem;\n border-radius: 1rem;\n height: auto;\n position: absolute;\n background: #674def;\n z-index: 99;\n`;\n\nconst HeaderWrapper = styled.div`\n border-radius: 0.75rem;\n display: flex;\n background: #7b61ff;\n flex-flow: row;\n padding: 1rem 1.5rem;\n align-items: center;\n justify-content: space-between;\n`;\n\nconst HeaderText = styled.div`\n font-size: 1rem;\n font-weight: 600;\n color: white;\n`;\n\nconst MoreAction = styled.div`\n display: flex; \n flex-flow: row; \n align-items: center;\n justify-content: center;\n gap: 1rem;\n width: 100%;\n margin-top: 1rem;\n`;\n\nconst RandomButton = styled.button`\n outline: none;\n font-size: 1rem;\n padding: 0.5rem 0.75rem;\n border-radius: 100px;\n height: 2rem;\n display: inline-flex;\n flex-flow: row;\n align-items: center;\n justify-content: center;\n background: #674def;\n transition: transform 300ms ease;\n transform: scaleX(1) scaleY(1);\n color: white;\n cursor: pointer;\n font-weight: 600;\n width: auto;\n\n &:hover {\n transform: scaleX(1.04) scaleY(1.08);\n }\n\n &:active {\n transform: scaleX(0.96) scaleY(0.92);\n }\n`;\n\n\nconst BodyWrapper = styled.div`\n display: flex;\n flex-flow: row;\n height: 100%;\n`;\n\nconst ShipyardWrapper = styled.div`\n position: relative;\n display: flex;\n flex-flow: column wrap;\n flex-grow: 1;\n height: 100%;\n margin-right: 3rem;\n align-items: center;\n align-content: center;\n justify-content: center;\n width: 6rem;\n background: #7b61ff;\n border-radius: 12px;\n`;\n\nconst ShipyardText = styled.span`\n position: absolute;\n top: -1.75rem;\n color: #bbb3e0;\n font-weight: 500;\n font-size: 1rem;\n margin-bottom: 1rem;\n`;\n\nconst BoardWrapper = styled.div`\n position: relative;\n`;\n\nconst ReadyButton = styled.button`\n background: #ffdbb4;\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n border-radius: 12px;\n height: 48px;\n color: #4328c9;\n font-weight: 700;\n cursor: pointer;\n transform: scale(1);\n transition: all 300ms ease;\n font-size: 1.125rem;\n\n &:hover {\n transform: scale(1.04);\n }\n`;\n\nconst ResetButton = styled.button`\n outline: none;\n font-size: 1rem;\n padding: 0.5rem 0.75rem;\n border-radius: 100px;\n height: 2rem;\n display: inline-flex;\n flex-flow: row;\n align-items: center;\n justify-content: center;\n background: #7b61ff;\n transition: transform 300ms ease;\n transform: scaleX(1) scaleY(1);\n color: white;\n cursor: pointer;\n font-weight: 500;\n bottom: 0;\n flex-grow: 1; \n\n &:hover {\n transform: scaleX(1.04) scaleY(1.08);\n }\n\n &:active {\n transform: scaleX(0.96) scaleY(0.92);\n }\n`;\n\nconst RotateButton = styled(ResetButton)<{ direction: BattleshipDirection }>`\n padding: 0.5rem;\n flex-grow: 0;\n\n & > svg {\n transition: transform 200ms ease; \n\n ${({ direction }) => {\n switch (direction) {\n case BattleshipDirection.Horizontal:\n return css`\n transform: rotate(0deg);\n `;\n case BattleshipDirection.Vertical:\n return css`\n transform: rotate(90deg);\n `;\n case BattleshipDirection.HorizontalRev:\n return css`\n transform: rotate(180deg);\n `;\n case BattleshipDirection.VerticalRev:\n return css`\n transform: rotate(270deg);\n `;\n }\n }}\n }\n`;","import styled from \"../../../styles/theme\";\n\ninterface Props {\n avatarVersusComponent: JSX.Element;\n onHostStartCallback: () => void;\n}\n\nconst HostWelcome: React.FC = ({\n avatarVersusComponent,\n onHostStartCallback,\n}) => {\n return (\n \n Welcome!\n {avatarVersusComponent}\n \n Start Game\n \n \n );\n};\n\nconst Welcome = styled.span`\n font-weight: 600; \n font-size: 1rem; \n color: white; \n height: min-content; \n width: 100%; \n display: flex; \n align-items: center; \n justify-content: center;\n padding: 0.5rem 0.75rem; \n width: min-content; \n border-radius: 8px; \n background: #947EFF; \n`;\n\nconst Container = styled.div`\n display: flex;\n flex-flow: column;\n align-items: center;\n gap: 1.4375rem;\n\n & > *:nth-child(2) {\n width: 28.6875rem;\n height: 8.125rem;\n }\n`;\n\nconst StartGameContainer = styled.div`\n display: grid;\n place-items: center;\n\n width: 8.6875rem;\n height: 2.3125rem;\n\n background: ${(props) =>\n props.theme.colors.lobby.button.background.startGame};\n border-radius: 0.5rem;\n\n font-weight: 700;\n font-size: 1rem;\n line-height: 1.3125rem;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n\n cursor: pointer;\n\n color: ${(props) => props.theme.colors.lobby.button.text.startGame};\n\n transition: scale 100ms ease-in-out;\n &:hover {\n transition: scale 100ms ease-in-out;\n scale: 1.025;\n }\n`;\n\nexport default HostWelcome;\n","import { createContext, useContext } from \"react\";\nimport { AvatarSide } from \"../../avatar/types/avatar\";\nimport { Message } from \"../types/chat\";\n\n// initializes with empty Product\nexport const ChatContext = createContext<{\n chatSide: AvatarSide;\n left: {\n queue: Message[];\n addMessage: (message: string) => void;\n removeMessage: () => void;\n };\n right: {\n queue: Message[];\n addMessage: (message: string) => void;\n removeMessage: () => void;\n };\n}>({\n chatSide: AvatarSide.Left,\n left: {\n queue: [],\n addMessage: () => {},\n removeMessage: () => {},\n },\n right: {\n queue: [],\n addMessage: () => {},\n removeMessage: () => {},\n },\n});\n\nexport const useChatContext = () => useContext(ChatContext);\n","import React from \"react\";\nimport styled from \"styled-components\";\nimport { useChatContext } from \"../../game/contexts/chatContext\";\nimport { AvatarSide } from \"../types/avatar\";\n\nconst ChatBubbleList: React.FC<{ side: AvatarSide }> = ({ side }) => {\n const { queue } = useChatContext()[side];\n\n const displayedBubbles = queue\n .reverse()\n .slice(0, 2)\n .map((message, idx) => (\n \n
{message.content}
\n \n ));\n\n if (!queue.length) return null;\n return {displayedBubbles};\n};\n\nconst Container = styled.div`\n position: relative;\n top: -2rem;\n\n display: flex;\n flex-flow: column-reverse;\n gap: 0.4375rem;\n`;\n\nconst ChatBubble = styled.div<{\n isFlipped?: boolean;\n opacity?: number;\n hasTail?: boolean;\n}>`\n width: 12rem;\n\n font-weight: 500;\n\n font-size: 1rem;\n line-height: 1.3125rem;\n\n color: ${(props) => props.theme.colors.lobby.avatar.text.chat};\n opacity: ${(props) => props.opacity || 1};\n\n display: flex;\n\n &:first-child > div::before {\n content: \"\";\n position: absolute;\n width: 0.875rem;\n height: 0.875rem;\n bottom: -0.4375rem;\n\n background: ${(props) =>\n props.theme.colors.lobby.avatar.background.white};\n\n transform: rotate(-45deg);\n\n ${(props) => (props.isFlipped ? \"right\" : \"left\")}: 1em;\n }\n\n & > div {\n position: relative;\n top: 0rem;\n\n max-width: 12rem;\n width: max-content;\n background: ${(props) =>\n props.theme.colors.lobby.avatar.background.white};\n padding: 0.625rem 0.875rem;\n border-radius: 0.375rem;\n\n overflow-wrap: break-word;\n word-wrap: break-word;\n -webkit-hyphens: auto;\n -ms-hyphens: auto;\n -moz-hyphens: auto;\n hyphens: auto;\n\n ${(props) =>\n `transform: translateX(${props.isFlipped ? \"-4em\" : \"4em\"})`}\n }\n\n ${(props) =>\n `justify-content: ${props.isFlipped ? \"flex-end\" : \"flex-start\"}`}\n`;\n\nexport default ChatBubbleList;\n","import { AnimatePresence, motion } from \"framer-motion\";\nimport React from \"react\";\nimport styled from \"styled-components\";\n\nconst variants = {\n fadeIn: {\n initial: {\n opacity: 0,\n },\n animate: {\n opacity: 1,\n },\n transition: {\n delay: 0.35,\n duration: 0.2,\n },\n },\n moveInLeft: {\n initial: {\n x: -40,\n opacity: 0,\n },\n animate: {\n x: 0,\n opacity: 1,\n },\n exit: {\n x: -40,\n opacity: 0,\n },\n transition: {\n type: \"spring\",\n },\n },\n moveInRight: {\n initial: {\n x: 40,\n opacity: 0,\n },\n animate: {\n x: 0,\n opacity: 1,\n },\n exit: {\n x: 40,\n opacity: 0,\n },\n transition: {\n type: \"spring\",\n },\n },\n notSelected: {\n animate: { opacity: 0.7 },\n transition: {\n duration: 0.1,\n },\n },\n selected: {\n animate: {\n opacity: 1,\n },\n transition: {\n duration: 0.1,\n },\n },\n none: {},\n};\n\ninterface Props {\n seed?: string;\n username?: string;\n isRounded?: boolean;\n isSelected?: boolean;\n isFlipped?: boolean;\n variant?: keyof typeof variants;\n onClickHandler?: () => void;\n}\n\nconst UserAvatar: React.FC = ({\n seed = \"123\",\n username,\n isRounded,\n isSelected,\n isFlipped,\n variant,\n onClickHandler,\n}) => {\n // errors for devs\n if (isSelected && !isRounded)\n throw new Error(\"isSelected is only valid for 30 avatars\");\n if (isRounded && username)\n throw new Error(\"You can only have usernames for non-rounded avatars\");\n\n return (\n onClickHandler && onClickHandler()}\n isRounded={isRounded}\n isSelected={isSelected}\n isFlipped={isFlipped}\n {...variants[\n variant ??\n (!isRounded\n ? isFlipped\n ? \"moveInRight\"\n : \"moveInLeft\"\n : isSelected\n ? \"selected\"\n : \"notSelected\")\n ]}\n whileHover={isRounded ? { scale: 1.05, opacity: 1 } : undefined}\n >\n \n {username && {username}}\n \n \n \n \n \n );\n};\n\nconst Container = styled(motion.div)<{\n isRounded?: boolean;\n isSelected?: boolean;\n isFlipped?: boolean;\n}>`\n width: 5rem;\n height: 5rem;\n\n position: relative;\n\n border-radius: ${(props) => (props.isRounded ? \"50%\" : \"0\")};\n border: ${(props) =>\n props.isSelected\n ? `solid 0.25rem ${props.theme.colors.lobby.avatar.selected}`\n : \"none\"};\n background: ${(props) =>\n props.isRounded\n ? props.theme.colors.lobby.avatar.background.white\n : \"none\"};\n\n display: flex;\n justify-content: center;\n\n & > svg,\n & > svg > image {\n width: inherit;\n height: inherit;\n\n transform: ${(props) =>\n props.isSelected\n ? \"translateY(-0.125rem) translateX(-0.227rem)\"\n : \"translateX(-0.1rem)\"};\n }\n\n ${(props) => props.isRounded && \"overflow: hidden\"};\n`;\n\nconst Username = styled(motion.span)`\n position: absolute;\n top: -1rem;\n\n user-select: none;\n\n font-weight: 500;\n font-size: 1rem;\n line-height: 1.3125rem;\n\n color: ${(props) => props.theme.colors.lobby.avatar.text.name};\n`;\n\nexport default UserAvatar;\n","import { AnimatePresence } from \"framer-motion\";\nimport React from \"react\";\nimport styled from \"styled-components\";\nimport { AvatarProperties, AvatarSide } from \"../types/avatar\";\nimport ChatBubbleList from \"./chatBubbleList\";\nimport UserAvatar from \"./userAvatar\";\n\nconst AvatarContainer: React.FC = ({\n seed,\n username,\n side,\n}) => {\n return (\n \n \n {seed && (\n <>\n \n \n \n )}\n \n \n );\n};\n\nconst Container = styled.div`\n display: flex;\n flex-flow: column;\n align-items: center;\n\n width: 5rem;\n`;\n\nexport default AvatarContainer;\n","import styled from \"styled-components\";\nimport { Side } from \"../../board/types/utility\";\nimport { AvatarProperties, AvatarSide } from \"../types/avatar\";\nimport AvatarContainer from \"./avatarContainer\";\n\nconst AvatarVersus: React.FC<\n Partial> & { style?: any; side?: Side }\n> = ({ left, right, ...delegated }) => {\n const hasLeftScore = typeof left?.score !== \"undefined\";\n const hasRightScore = typeof right?.score !== \"undefined\";\n\n if ((hasLeftScore && !hasRightScore) || (!hasLeftScore && hasRightScore))\n throw new Error(\"Both players need scores\");\n\n return (\n \n \n {left?.seed && right?.seed && (\n \n {hasLeftScore && (\n {left.score}\n )}\n vs\n {hasRightScore && (\n {right.score}\n )}\n \n )}\n \n \n );\n};\n\nconst Container = styled.div<{ isExpanded?: boolean }>`\n padding: 0 2.5625rem;\n\n border-radius: 0.75rem;\n\n height: 8.125rem;\n min-width: ${(props) => (props.isExpanded ? \"38.9375rem\" : \"100%\")};\n background: ${(props) => props.theme.colors.lobby.avatar.background.light};\n\n display: flex;\n align-items: flex-end;\n justify-content: space-between;\n`;\n\nconst VS = styled.div`\n display: flex;\n flex-flow: row;\n align-items: center;\n align-self: center;\n justify-content: center;\n gap: 2.75rem;\n position: relative;\n width: 10rem;\n transform: translateY(0.25rem);\n\n & > .vs-text {\n font-weight: 500;\n font-size: 3rem;\n line-height: 3.875rem;\n\n color: ${(props) => props.theme.colors.lobby.avatar.text.versus};\n }\n\n & > .score-left {\n font-weight: 500;\n font-size: 4.5rem;\n line-height: 5.875rem;\n position: absolute;\n transform-origin: center center;\n transform: translateX(-6rem);\n\n color: ${(props) => props.theme.colors.lobby.avatar.text.score};\n }\n\n & > .score-right {\n font-weight: 500;\n font-size: 4.5rem;\n line-height: 5.875rem;\n position: absolute;\n transform-origin: center center;\n transform: translateX(6rem);\n\n color: ${(props) => props.theme.colors.lobby.avatar.text.score};\n }\n`;\n\nexport default AvatarVersus;\n","import styled from \"../../../styles/theme\";\n\nexport const LabelText = styled.label`\n margin: 0;\n padding: 0;\n\n font-weight: 400;\n font-size: 0.875rem;\n line-height: 1.125rem;\n\n color: ${(props) => props.theme.colors.lobby.info.label};\n`;\n\nexport const HeaderText = styled.h1`\n margin: 0;\n padding: 0;\n\n font-weight: 500;\n font-size: 1rem;\n line-height: 1.3125rem;\n\n user-select: none;\n\n color: ${(props) => props.theme.colors.lobby.info.heading};\n`;\n\nexport const WhiteBox = styled.div`\n background: ${(props) => props.theme.colors.lobby.backdrop.light};\n border-radius: 0.75rem;\n\n width: 28.6875rem;\n\n display: flex;\n flex-flow: column;\n`;\n\nexport const Tag = styled.span`\n background: ${(props) =>\n props.theme.colors.lobby.button.background.secondary};\n border-radius: 0.375rem;\n padding: 0.125rem 0.375rem;\n margin: 0 0.375rem;\n\n font-weight: 500;\n font-size: 0.875rem;\n line-height: 1.125rem;\n\n color: ${(props) => props.theme.colors.lobby.button.text.secondary};\n\n cursor: pointer;\n`;\n\nexport const Backdrop = styled.div`\n position: fixed;\n z-index: 5;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n background-color: rgba(0, 0, 0, 0.6);\n`;\n","import { ButtonHTMLAttributes } from \"react\";\nimport styled from \"../../../styles/theme\";\n\ntype ButtonVariant = \"primary\" | \"secondary\";\n\ninterface Props extends ButtonHTMLAttributes {\n variant?: ButtonVariant;\n}\n\nconst BasicButton: React.FC = ({\n variant = \"primary\",\n children,\n ...delegated\n}) => {\n return (\n \n {children}\n \n );\n};\n\nconst StyledButton = styled.button<{ variant: ButtonVariant }>`\n background: ${(props) =>\n props.theme.colors.lobby.button.background[props.variant]};\n border-radius: 0.375rem;\n\n height: 3.25rem;\n\n color: ${(props) => props.theme.colors.lobby.button.text[props.variant]};\n\n font-family: DM Sans;\n font-weight: ${(props) => (props.variant === \"primary\" ? 700 : 500)};\n font-size: 1rem;\n line-height: 1.3125rem;\n\n cursor: pointer;\n\n transition: scale 100ms ease-in-out;\n &:hover {\n transition: scale 100ms ease-in-out;\n scale: 1.025;\n }\n`;\n\nexport default BasicButton;\n","import {\n useCallback,\n useState,\n useEffect,\n useRef,\n useLayoutEffect,\n} from \"react\";\nimport styled from \"styled-components\";\nimport socketClient from \"../../../api/socketClient\";\nimport { Tag } from \"../../lobby/components/base.styled\";\nimport BasicButton from \"../../lobby/components/basicButton\";\nimport { useChatContext } from \"../contexts/chatContext\";\n\nconst Chatbox = () => {\n const inputRef = useRef(null);\n const chatContext = useChatContext();\n\n const { addMessage } = chatContext[chatContext.chatSide];\n\n const [inputFocused, setInputFocused] = useState(false);\n const [message, setMessage] = useState(\"\");\n\n const sendChat = useCallback(() => {\n if (!message) return;\n socketClient.sendChat(message);\n addMessage(message);\n setMessage(\"\");\n }, [message, addMessage]);\n\n useOnKeyDown(\n useCallback(\n (e: KeyboardEvent) => {\n if (e.key === \"Enter\") sendChat();\n else if (e.key === \"Escape\") setInputFocused(false);\n else if (e.key === \"t\" && !inputFocused) {\n e.preventDefault(); \n setInputFocused(true);\n }\n },\n [sendChat, inputFocused]\n )\n );\n\n useLayoutEffect(() => {\n if (inputFocused) inputRef.current?.focus();\n else inputRef.current?.blur();\n }, [inputFocused]);\n\n return (\n {\n setInputFocused(true);\n inputRef.current?.focus();\n }}\n >\n setMessage(e.target.value)}\n onBlur={(e) => setInputFocused(false)}\n />\n {!inputFocused && !message && (\n \n Press t to type in chat and Enter to\n send\n \n )}\n sendChat()}>\n Send\n \n \n );\n};\n\nexport default Chatbox;\n\nfunction useOnKeyDown(callback: (e: KeyboardEvent) => void) {\n useEffect(() => {\n document.addEventListener(\"keydown\", callback);\n return () => {\n document.removeEventListener(\"keydown\", callback);\n };\n }, [callback]);\n}\n\nconst Container = styled.div`\n width: 38.9375rem;\n height: 3rem;\n background: #ffffff;\n border-radius: 0.75rem;\n\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-top: 1rem; \n\n cursor: pointer;\n`;\n\nconst StyledInput = styled.input`\n padding-left: 1.75rem;\n padding-right: 0.5rem;\n height: 100%;\n flex: 1;\n font-family: DM Sans;\n font-size: 1rem;\n color: #15046d;\n`;\n\nconst HintBox = styled.div`\n margin-left: 1.75rem;\n user-select: none;\n pointer-events: none;\n position: absolute;\n color: #200c83;\n`;\n\nconst SendButton = styled(BasicButton)`\n height: 2.125rem;\n width: 4.875rem;\n margin-right: 0.5rem;\n`;\n","import { Position } from \"../types/utility\"\n\nconst COLUMN: string[] = [\"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\"];\n\nconst serializePos = (pos: Position): string => {\n const col = COLUMN[pos.col - 1]; \n const row = pos.row.toString(); \n return `${col}${row}`;\n}\n\nexport default serializePos; ","import { Position } from \"../types/utility\"\n\nconst COLUMN: { [index: string]: number } = {\n A: 1,\n B: 2,\n C: 3,\n D: 4,\n E: 5,\n F: 6,\n G: 7,\n H: 8,\n};\n\nconst deserializePos = (pos: string): Position => {\n const col = COLUMN[pos[0]]; \n const row = parseInt(pos[1]); \n return { row, col }; \n}\n\nexport default deserializePos; ","import {\n BattleshipDirection,\n BattleshipKnown,\n BattleshipStatus,\n} from \"../../board/types/battleship\";\nimport { Position } from \"../../board/types/utility\";\n\nconst COLUMN: { [index: string]: number } = {\n A: 1,\n B: 2,\n C: 3,\n D: 4,\n E: 5,\n F: 6,\n G: 7,\n H: 8,\n};\n\nconst stringToPos = (s: string): Position => {\n const col = COLUMN[s[0].toUpperCase()];\n const row = parseInt(s[1]);\n\n return { row, col };\n};\n\nconst deserializeBattleship = (ship: string[]): BattleshipKnown => {\n const pos = ship.map((j) => stringToPos(j));\n\n const deltaY = pos[1].row - pos[0].row;\n const deltaX = pos[1].col - pos[0].col;\n\n const reverse = deltaX + deltaY < 0;\n const axis =\n deltaY !== 0\n ? BattleshipDirection.Vertical\n : BattleshipDirection.Horizontal;\n\n const direction = (reverse ? axis + 2 : axis) as BattleshipDirection;\n \n return {\n direction,\n name: \"\",\n position: pos[0],\n length: pos.length,\n status: BattleshipStatus.Default,\n };\n};\n\nexport default deserializeBattleship; ","import { useCallback, useState } from \"react\";\nimport { Message } from \"../../game/types/chat\";\n\nconst CHAT_TIMEOUT = 6000;\n\nconst useChatQueue = () => {\n const [queue, setQueue] = useState([]);\n\n const removeMessage = useCallback(() => {\n setQueue((queue) => queue.slice(0, -1));\n }, []);\n\n const addMessage = useCallback(\n (message: string) => {\n setQueue((queue) => [\n {\n timestamp: Date.now(),\n content: message,\n },\n ...queue,\n ]);\n setTimeout(() => {\n removeMessage();\n }, CHAT_TIMEOUT);\n },\n [removeMessage]\n );\n\n return { addMessage, removeMessage, queue };\n};\n\nexport default useChatQueue;\n","import { useEffect, useRef } from \"react\";\nimport socketClient from \"../../../api/socketClient\";\nimport { useHistory } from \"react-router\";\n\nconst useAutoWithdraw = (): [() => boolean, () => void] => {\n const history = useHistory();\n\n const duplicateGuard = useRef(false);\n const guarded = () => duplicateGuard.current;\n\n useEffect(() => {\n return () => {\n // eslint-disable-next-line react-hooks/exhaustive-deps\n if (!duplicateGuard.current) {\n duplicateGuard.current = true;\n socketClient.withdraw();\n }\n };\n }, []);\n\n const forceWithdraw = () => {\n if (guarded()) return;\n duplicateGuard.current = true;\n socketClient.withdraw();\n history.push(\"/\");\n };\n\n return [guarded, forceWithdraw];\n};\n\nexport default useAutoWithdraw;\n","import { TutorialInfoList } from \"../types/info\";\n\nexport const TUTORIAL_INFO_LIST: TutorialInfoList = [\n {\n text: \"You can simply select a ship to place, then click on the available square to place. You can also use spacebar or rotate button to rotate.\",\n imgSrc: \"/images/place-ships.gif\",\n imgAlt: \"Placing Ships\",\n },\n {\n text: \"For you sake, our game also lets you randomize your ship placement to save time.\",\n imgSrc: \"/images/randomize-ships.gif\",\n imgAlt: \"Random Ships\",\n },\n {\n text: \"Your goal is to destroy all of enemy shps before they destroy all of yours. \",\n imgSrc: \"/images/cannon-fire.gif\",\n imgAlt: \"Destroy Enemy Ships \",\n },\n];\n","import { motion } from \"framer-motion\";\nimport styled from \"styled-components\";\n\nconst ArrowIcon: React.FC<{\n onClickHandler?: () => void;\n direction?: \"left\" | \"right\";\n}> = ({ onClickHandler, direction = \"left\" }) => {\n const isRotated = direction === \"left\";\n\n return (\n onClickHandler && onClickHandler()}\n initial={{ rotate: isRotated ? 180 : 0 }}\n whileHover={{ rotate: isRotated ? 180 : 0, scale: 1.1 }}\n >\n \n \n \n \n );\n};\n\nconst Container = styled(motion.div)`\n width: 2.4rem;\n height: 2.4rem;\n background: rgba(0, 0, 0, 0.2);\n\n display: grid;\n place-items: center;\n\n border-radius: 50%;\n\n cursor: pointer;\n`;\n\nexport default ArrowIcon;\n","import { motion } from \"framer-motion\";\nimport { useState } from \"react\";\nimport styled from \"../../../styles/theme\";\nimport { TUTORIAL_INFO_LIST } from \"../constants/tutorial\";\nimport ArrowIcon from \"./arrowIcon\";\n\nconst TutorialModal: React.FC<{ onCloseHandler: () => void }> = ({\n onCloseHandler,\n}) => {\n const [pageNumber, setPageNumber] = useState(0);\n const { imgSrc, imgAlt, text } = TUTORIAL_INFO_LIST[pageNumber];\n\n return (\n \n
\n Tutorial\n \n {pageNumber + 1}/{TUTORIAL_INFO_LIST.length}\n \n onCloseHandler()}\n initial=\"default\"\n whileHover=\"hover\"\n >\n \n \n
\n \n {imgAlt}\n \n {text}\n \n {pageNumber - 1 >= 0 ? (\n setPageNumber(pageNumber - 1)}\n />\n ) : (\n
\n )}\n {pageNumber + 1 < TUTORIAL_INFO_LIST.length ? (\n setPageNumber(pageNumber + 1)}\n />\n ) : (\n
\n )}\n \n \n \n );\n};\n\nconst Container = styled.div`\n z-index: 4;\n position: absolute;\n background: ${(props) =>\n props.theme.colors.tutorial.modal.background.primary};\n\n width: 37.875rem;\n height: 25.125rem;\n\n border-radius: 0.75rem;\n`;\n\nconst Header = styled.div`\n display: flex;\n justify-content: space-between;\n align-items: center;\n\n position: relative;\n\n padding: 0 1.125rem 0 1.8125rem;\n\n width: 100%;\n height: 3.625rem;\n\n border-radius: 0.75rem 0.75rem 0 0;\n\n background: ${(props) =>\n props.theme.colors.tutorial.modal.background.light};\n\n & > * {\n font-weight: 700;\n font-size: 1.25rem;\n line-height: 1.625rem;\n\n display: flex;\n align-items: center;\n letter-spacing: 0.05em;\n\n &:first-child {\n color: #160668;\n }\n\n &:nth-child(2) {\n color: #674def;\n position: absolute;\n left: 50%;\n transform: translateX(-50%);\n }\n\n &:last-child {\n width: 1.5625rem;\n height: 1.5625rem;\n\n cursor: pointer;\n }\n }\n`;\n\nconst Content = styled.div`\n height: calc(100% - 3.625rem);\n\n position: relative;\n\n display: flex;\n flex-flow: column;\n\n overflow: hidden;\n\n border-radius: 0 0 0.75rem 0.75rem;\n\n & > *:first-child {\n height: 100%;\n width: 100%;\n object-fit: cover;\n }\n`;\n\nconst Instructions = styled.p`\n padding: 0;\n margin: 0;\n\n position: absolute;\n z-index: 2;\n left: 2.25rem;\n bottom: 1.25rem;\n\n width: 26.9375rem;\n\n font-weight: 700;\n font-size: 1.25rem;\n line-height: 1.625rem;\n\n display: flex;\n align-items: center;\n letter-spacing: 0.05em;\n\n color: #ffffff;\n`;\n\nconst BackdropGradient = styled.div`\n position: absolute;\n bottom: 0;\n z-index: 1;\n\n width: 100%;\n height: 10rem;\n background: linear-gradient(\n 360deg,\n rgba(0, 0, 0, 0.7) 1.4%,\n rgba(0, 0, 0, 0) 98.46%\n );\n`;\n\nconst ArrowContainer = styled.div`\n position: absolute;\n height: 100%;\n width: 100%;\n\n display: flex;\n align-items: center;\n justify-content: space-between;\n\n padding: 0 1.125rem;\n`;\n\nexport default TutorialModal;\n","import { useState } from \"react\";\nimport styled from \"styled-components\";\nimport { useTheme } from \"../../../styles/theme\";\nimport { Backdrop } from \"../../lobby/components/base.styled\";\nimport BasicButton from \"../../lobby/components/basicButton\";\nimport TutorialModal from \"../../tutorial/components/tutorialModal\";\n\nconst TutorialWrapper: React.FC = ({ children }) => {\n const theme = useTheme();\n const [tutorialModalShown, setTutorialModalShown] =\n useState(false);\n\n return (\n <>\n {children}\n setTutorialModalShown(true)}>\n \n \n \n \n {tutorialModalShown && (\n <>\n setTutorialModalShown(false)}\n />\n setTutorialModalShown(false)}\n />\n \n )}\n \n );\n};\n\nconst TutorialButton = styled(BasicButton)`\n position: absolute;\n\n bottom: 1.625rem;\n right: 1.625rem;\n width: 3rem;\n height: 3rem;\n border-radius: 50%;\n\n display: grid;\n place-items: center;\n\n background: ${(props) => props.theme.colors.tutorial.infoButton.background};\n\n &:hover {\n transform: scale(1.1);\n }\n`;\n\nconst StyledBackdrop = styled(Backdrop)`\n z-index: 4;\n`;\n\nexport default TutorialWrapper;\n","import { FC } from \"react\";\n\ninterface Props {\n size?: number | string;\n color?: string;\n}\n\nconst VolumeMute: FC = ({ size, color }) => {\n return (\n \n \n \n \n \n \n \n \n \n \n );\n};\n\nexport default VolumeMute;\n","import { FC } from \"react\";\n\ninterface Props {\n size?: number | string; \n color?: string; \n}\n\nconst VolumeUp: FC = ({ size, color }) => {\n return (\n \n \n \n \n \n \n \n \n \n \n );\n};\n\nexport default VolumeUp;\n","import { useState, useEffect } from 'react'; \n\nfunction useStickyState(defaultValue: T, key: string): [T, (prev: T) => void] {\n const [value, setValue] = useState(() => {\n const stickyValue = window.localStorage.getItem(key);\n return stickyValue !== null ? JSON.parse(stickyValue) : defaultValue;\n });\n\n useEffect(() => {\n window.localStorage.setItem(key, JSON.stringify(value));\n }, [key, value]);\n\n return [value, setValue];\n}\n\nexport default useStickyState; \n","import {\n useLayoutEffect,\n useReducer,\n useState,\n MouseEvent,\n useRef,\n useEffect,\n} from \"react\";\nimport { useHistory } from \"react-router\";\nimport { Position, Side } from \"../../board/types/utility\";\nimport { initialGameState } from \"../constants/state\";\nimport { GameStateContext } from \"../contexts/gameStateContext\";\nimport { Phase } from \"../types/state\";\nimport Board from \"../../board\";\nimport Result from \"../../result\";\nimport styled, { css } from \"styled-components\";\nimport useQuery from \"../../routing/hooks/useQuery\";\nimport gameStateReducer from \"../reducers/gameStateReducer\";\nimport SetupModal from \"../../setup\";\nimport HostWelcome from \"./hostWelcome\";\nimport AvatarVersus from \"../../avatar/components/avatarVersus\";\nimport Chatbox from \"../components/chatBox\";\nimport socket from \"../../../api/socketClient\";\nimport serializePos from \"../../board/functions/serializePos\";\nimport deserializePos from \"../../board/functions/deserializePos\";\nimport deserializeBattleship from \"../functions/deserializeBattleship\";\nimport useChatQueue from \"../../avatar/hooks/useChatQueue\";\nimport useAutoWithdraw from \"../functions/useAutoWithdraw\";\nimport useSound from \"use-sound\";\n\nimport { useUserContext } from \"../../lobby/contexts/userContext\";\nimport { useOnStart } from \"../functions/useOnStart\";\nimport { useOnEnd } from \"../functions/useOnEnd\";\nimport { useOnShoot } from \"../functions/useOnShoot\";\nimport { BoardSquareStatus } from \"../../board/types/board\";\nimport { useOnAvatar } from \"../functions/useOnAvatar\";\nimport { BattleshipAllyYard } from \"../../board/types/battleship\";\nimport { useOnShipDestroyed } from \"../functions/useOnShipDestroyed\";\nimport { useOnChat } from \"../functions/useOnChat\";\nimport { AvatarProperties, AvatarSide } from \"../../avatar/types/avatar\";\nimport { ChatContext } from \"../contexts/chatContext\";\nimport { useOnStatistics } from \"../functions/useOnStatistics\";\nimport { StatResponse } from \"../../../api/types/transport\";\nimport TutorialWrapper from \"../wrappers/tutorialWrapper\";\nimport { Backdrop } from \"../../lobby/components/base.styled\";\nimport VolumeMute from \"../components/volumeMute\";\nimport VolumeUp from \"../components/volumeUp\";\nimport useStickyState from \"../functions/useStickyState\";\nimport { useOnAdminSpectate } from \"../functions/useOnAdminSpectate\";\n\nconst GamePage = () => {\n const [yourTurn, setYourTurn] = useState(false);\n const [phase, setPhase] = useState(Phase.Welcome);\n const [state, dispatch] = useReducer(gameStateReducer, initialGameState);\n\n const [second, setSecond] = useState(10);\n const [turn, setTurn] = useState(1);\n\n const [mute, setMute] = useStickyState(false, \"soundMute\");\n const [endReason, setEndReason] = useState();\n const [, setRound] = useState(0);\n const [winners, setWinners] = useState<(\"Host\" | \"Guest\")[]>([]);\n const [allyScore, setAllyScore] = useState(0);\n const [allyHit, setAllyHit] = useState(0);\n const [enemyHit, setEnemyHit] = useState(0);\n const [enemyScore, setEnemyScore] = useState(0);\n const [enemyAvatarSeed, setEnemyAvatarSeed] = useState(\"\");\n const [enemyUsername, setEnemyUsername] = useState(\"\");\n const [statistic, setStatistic] = useState([]);\n\n const { battleship } = state;\n const { username, userAvatarSeed, isAdmin } = useUserContext();\n\n const timerRef = useRef(undefined);\n const forceWithdraw = useAutoWithdraw()[1];\n const statsLock = useRef(false);\n const query = useQuery();\n const history = useHistory();\n const playerChatQueue = useChatQueue();\n const enemyChatQueue = useChatQueue();\n\n const roomId = query.get(\"roomId\");\n const isHost = query.get(\"isHost\") === \"true\";\n const yourSide = isHost ? \"Host\" : \"Guest\";\n const spectatorMode = query.get(\"spectator\") === \"true\" && isAdmin;\n\n const option = { volume: 0.6, soundEnabled: !mute };\n const [playShootHit] = useSound(\"/sounds/shoot-hit.wav\", option);\n const [playShootFire] = useSound(\"/sounds/shoot-fire.wav\", option);\n const [playChat] = useSound(\"/sounds/notification-chat.wav\", option);\n\n const [playMatchmake] = useSound(\n \"/sounds/notification-matchmake.wav\",\n option\n );\n\n const [playDefeat, { stop: stopDefeat }] = useSound(\n \"/sounds/result-defeat.wav\",\n option\n );\n\n const [playVictory, { stop: stopVictory }] = useSound(\n \"/sounds/result-victory.wav\",\n option\n );\n\n const [playPlanning, { stop: stopPlanning }] = useSound(\n \"/sounds/atmosphere-planning.wav\",\n { ...option, volume: 0.35, interrupt: false }\n );\n\n const [playPlaying, { stop: stopPlaying }] = useSound(\n \"/sounds/atmosphere-playing.wav\",\n { ...option, volume: 0.35, interrupt: false }\n );\n\n const avatarProps: Record = {\n left: {\n seed: isHost ? userAvatarSeed : enemyAvatarSeed,\n username: isHost ? username : enemyUsername,\n score:\n phase !== Phase.Welcome\n ? isHost\n ? allyScore\n : enemyScore\n : undefined,\n },\n right: {\n seed: isHost ? enemyAvatarSeed : userAvatarSeed,\n username: isHost ? enemyUsername : username,\n score:\n phase !== Phase.Welcome\n ? isHost\n ? enemyScore\n : allyScore\n : undefined,\n },\n };\n\n const onShoot = async (pos: Position, _e: MouseEvent) => {\n if (!yourTurn) return;\n const serialized = serializePos(pos);\n await socket.shoot(serialized);\n };\n\n const onSubmit = (shipyard: BattleshipAllyYard) => {\n dispatch({ type: \"GAME_START\", payload: { shipyard } });\n setPhase(Phase.Playing);\n };\n\n const onOneMoreRound = (_e: MouseEvent) => {\n playPlanning();\n\n if (phase !== Phase.Finish) return;\n dispatch({ type: \"RESET_BOARD\" });\n if (winners[winners.length - 1] === yourSide) setYourTurn(true);\n setPhase(Phase.Setup);\n };\n\n const onWithdraw = (_e: MouseEvent) => {\n forceWithdraw();\n };\n\n const onStart = () => {\n playPlanning();\n setPhase(Phase.Setup);\n };\n\n const onToggleMute = () => {\n setMute(!mute);\n };\n\n const onNewCount = () => {\n setSecond(10);\n timerRef.current && clearInterval(timerRef.current);\n timerRef.current = setInterval(() => {\n setSecond((p) => p - 1);\n }, 1000);\n };\n\n useOnStart((r) => {\n stopPlanning();\n setTurn(1);\n setAllyHit(0);\n setEnemyHit(0);\n onNewCount();\n setRound((prev) => prev + 1);\n r.firstPlayer === yourSide && setYourTurn(true);\n });\n\n useOnEnd(\n ({ responseStatus, previousRoundWinner, hostScore, guestScore }) => {\n stopPlaying();\n switch (responseStatus) {\n case \"Reset by Admin\":\n dispatch({ type: \"RESET_BOARD\" });\n setPhase(Phase.Welcome);\n setAllyScore(0);\n setEnemyScore(0);\n setWinners([]);\n setRound(0);\n return setStatistic([]);\n case \"Closed by Admin\":\n return setPhase(Phase.Finish);\n case \"Withdrew\":\n case \"Abandoned\":\n case \"Destroyed\":\n default:\n setEndReason(responseStatus);\n if (phase === Phase.Finish)\n return (statsLock.current = true);\n previousRoundWinner === yourSide && playVictory();\n previousRoundWinner !== yourSide && playDefeat();\n setPhase(Phase.Finish);\n setAllyScore(isHost ? hostScore : guestScore);\n setEnemyScore(isHost ? guestScore : hostScore);\n return setWinners((prev) => [\n ...prev,\n previousRoundWinner as any,\n ]);\n }\n }\n );\n\n useOnAdminSpectate(({ responseStatus, room }) => {\n if (responseStatus === \"Connection Not Verified\") {\n return history.push(\"/\");\n }\n });\n\n useOnAvatar(({ hostAvatar, guestAvatar, hostUsername, guestUsername }) => {\n setEnemyAvatarSeed(isHost ? guestAvatar : hostAvatar);\n setEnemyUsername(isHost ? guestUsername : hostUsername);\n });\n\n useOnChat((msg) => {\n playChat();\n enemyChatQueue.addMessage(msg);\n });\n\n useOnShoot((r) => {\n playShootFire();\n let status;\n switch (r.responseStatus) {\n case \"Hit\":\n status = BoardSquareStatus.Hit;\n break;\n case \"Miss\":\n status = BoardSquareStatus.Missed;\n break;\n default:\n return;\n }\n\n if (!r.location) return;\n const side = r.currentTurnPlayer === yourSide ? Side.Enemy : Side.Ally;\n const position = deserializePos(r.location);\n\n if (r.nextTurnPlayer === yourSide) setYourTurn(true);\n else setYourTurn(false);\n\n onNewCount();\n dispatch({\n type: \"MARK_SQUARE\",\n payload: {\n side,\n position,\n status,\n },\n });\n\n setTurn((p) => p + 1);\n if (status === BoardSquareStatus.Hit) {\n side === Side.Enemy && setEnemyHit((prev) => prev + 1);\n side === Side.Ally && setAllyHit((prev) => prev + 1);\n }\n });\n\n useOnShipDestroyed(({ side, ship }) => {\n setTimeout(() => {\n playShootHit();\n }, 1000);\n\n if (ship.length <= 0) return;\n\n // waiting for backend ghostship fix\n dispatch({\n type: \"SUNK_SHIP\",\n payload: {\n battleship: deserializeBattleship(ship),\n side: side === yourSide ? Side.Ally : Side.Enemy,\n },\n });\n });\n\n useOnStatistics((r) => {\n if (statsLock.current) return;\n setStatistic((prev) => [...prev, r]);\n });\n\n useLayoutEffect(() => {\n if (!roomId) {\n history.push(\"/\");\n return;\n }\n\n if (!isHost) {\n socket.joinRoom(username, roomId);\n socket.setAvatar(userAvatarSeed);\n }\n }, [history, isHost, roomId, username, userAvatarSeed]);\n\n useLayoutEffect(() => {\n phase === Phase.Welcome && playMatchmake();\n }, [phase, playMatchmake]);\n\n useEffect(() => {\n if (!enemyUsername || !enemyAvatarSeed)\n socket.setAvatar(userAvatarSeed);\n }, [userAvatarSeed, enemyUsername, enemyAvatarSeed]);\n\n useEffect(() => {\n if (mute) {\n stopPlanning();\n stopPlaying();\n stopVictory();\n stopDefeat();\n } else {\n if (phase === Phase.Setup) playPlanning();\n if (phase === Phase.Playing) playPlaying();\n }\n }, [\n mute,\n phase,\n playPlaying,\n playPlanning,\n stopPlaying,\n stopPlanning,\n stopDefeat,\n stopVictory,\n ]);\n\n if (phase === Phase.Welcome && !spectatorMode)\n return (\n <>\n }\n />\n \n {mute ? (\n \n ) : (\n \n )}\n \n \n );\n\n const borderRadius =\n phase === Phase.Finish ? \"0.75rem 0.75rem 0 0\" : \"0.75rem\";\n const avatar = ;\n const result = ;\n const turnCount = Turn {turn};\n\n const timer = {second}s;\n\n const chat = {\n chatSide: yourSide === \"Host\" ? AvatarSide.Left : AvatarSide.Right,\n left: isHost ? playerChatQueue : enemyChatQueue,\n right: isHost ? enemyChatQueue : playerChatQueue,\n };\n\n const board = isHost ? (\n \n \n \n \n ) : (\n \n \n \n \n );\n\n const footer = (\n
\n Withdraw\n \n One More Round\n \n
\n );\n\n const reason = (\n \n {formalizeReason(\n endReason,\n winners[winners.length - 1] === yourSide\n )}\n \n );\n\n return (\n \n \n\n \n {mute ? (\n \n ) : (\n \n )}\n \n \n \n {phase === Phase.Playing && timer}\n {phase === Phase.Playing && turnCount}\n {phase === Phase.Finish && reason}\n {avatar}\n {phase !== Phase.Finish && board}\n {phase === Phase.Finish && result}\n {!spectatorMode && }\n {phase === Phase.Finish && footer}\n {phase === Phase.Setup && }\n {phase === Phase.Setup && (\n \n )}\n \n \n \n \n );\n};\n\nexport default GamePage;\n\nfunction formalizeReason(reason: string | undefined, youWon: boolean): string {\n switch (reason) {\n case \"Closed by Admin\":\n return \"Room Closed by Admin\";\n case \"Withdrew\":\n return \"Enemy Withdrew\";\n case \"Abandoned\":\n return \"Enemy Abandoned\";\n case \"Destroyed\":\n default:\n if (youWon) return \"You Won!\";\n return \"You Lose!\";\n }\n}\n\nfunction canPlayAgain(reason: string | undefined): boolean {\n return reason === undefined || reason === \"Destroyed\";\n}\n\nconst Wrapper = styled.div`\n display: flex;\n justify-content: center;\n align-items: center;\n height: auto;\n flex-flow: column;\n position: relative;\n min-width: 38.9375rem;\n`;\n\nconst BoardContainer = styled.div`\n display: flex;\n justify-content: center;\n align-items: center;\n gap: 6.9375rem;\n\n margin-top: 4.3125rem;\n margin-bottom: 3.25rem;\n position: relative;\n`;\n\nconst Footer = styled.div`\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-top: 1rem;\n width: 100%;\n`;\n\nconst OneMoreRound = styled.button<{ disabled?: boolean }>`\n outline: none;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0.375rem 0.5rem;\n background: #ffdbb4;\n color: #674def;\n text-transform: uppercase;\n border-radius: 0.5rem;\n font-weight: 600;\n cursor: pointer;\n transform: scale(1, 1);\n\n ${({ disabled }) => {\n if (!disabled)\n return css`\n &:hover {\n transform: scale(1.03, 1.06);\n }\n\n &:active {\n transform: scale(0.97, 0.94);\n }\n `;\n return css`\n opacity: 0.5;\n cursor: default;\n `;\n }}\n`;\n\nconst Withdraw = styled(OneMoreRound)`\n background: #8972ff;\n color: white;\n font-weight: 500;\n letter-spacing: 0.5px;\n`;\n\nconst ReasonWrapper = styled.div`\n background: #947eff;\n border-radius: 0.75rem;\n font-weight: 700;\n font-size: 2.25rem;\n padding: 1rem 2.5rem;\n display: flex;\n align-items: center;\n justify-content: center;\n color: white;\n margin-bottom: 1rem;\n`;\n\nconst MuteButton = styled.button`\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0.5rem;\n outline: none;\n opacity: 0.7;\n transition: all 120ms ease;\n position: fixed;\n left: 2rem;\n bottom: 2rem;\n cursor: pointer;\n z-index: 6;\n\n &:hover {\n opacity: 1;\n }\n\n &:active {\n opacity: 0.85;\n }\n`;\n\nconst Timer = styled.span<{ yourTurn: boolean }>`\n color: #c2b6ff;\n font-size: 1.25rem;\n font-weight: 500;\n position: absolute;\n top: -3.25rem;\n\n & > svg {\n position: absolute;\n transition: all 200ms ease;\n transform: rotate(${({ yourTurn }) => (yourTurn ? 0 : 180)}deg);\n }\n`;\n\nconst RoundCount = styled.div`\n display: flex;\n width: auto;\n height: auto;\n padding: 0.375rem 0.625rem;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n align-items: center;\n justify-content: center;\n color: #674def;\n font-weight: 600;\n background: white;\n border-radius: 6px;\n z-index: 4;\n position: absolute;\n top: -1.375rem;\n`;\n","import { useEffect, useRef } from \"react\";\nimport { StartResponse } from \"../../../api/types/transport\";\nimport socket from \"../../../api/socketClient\";\n\nexport const useOnStart = (callback: (res: StartResponse) => void) => {\n const ref = useRef(callback);\n\n ref.current = callback; \n\n useEffect(() => {\n socket.subscribeStartResponse((res) => {\n ref.current(res);\n });\n }, []);\n};\n\nexport const useOnStartSingle = (callback: (res: StartResponse) => void) => {\n const guarded = useRef(false);\n const ref = useRef(callback);\n\n if (!guarded.current) ref.current = callback;\n\n useEffect(() => {\n socket.subscribeStartResponse((res) => {\n if (guarded.current) return;\n guarded.current = true;\n ref.current(res);\n });\n }, []);\n};\n","import { useEffect, useRef } from \"react\";\nimport socket from \"../../../api/socketClient\";\nimport { EndResponse } from \"../../../api/types/transport\";\n\nexport const useOnEnd = (callback: (res: EndResponse) => void) => {\n const ref = useRef(callback);\n\n ref.current = callback; \n\n useEffect(() => {\n socket.subscribeEndResponse((res) => {\n ref.current(res);\n });\n }, []);\n};\n\nexport const useOnEndSingle = (callback: (res: EndResponse) => void) => {\n const guarded = useRef(false);\n const ref = useRef(callback);\n\n if (!guarded.current) ref.current = callback;\n\n useEffect(() => {\n socket.subscribeEndResponse((res) => {\n if (guarded.current) return;\n guarded.current = true;\n ref.current(res);\n });\n }, []);\n};\n","import { useRef, useEffect } from \"react\";\nimport { AdminSpectateResponse } from \"../../../api/types/transport\";\nimport socket from \"../../../api/socketClient\";\n\nexport const useOnAdminSpectate = (\n callback: (res: AdminSpectateResponse) => void\n) => {\n const ref = useRef(callback);\n\n ref.current = callback;\n\n useEffect(() => {\n socket.subscribeAdminSpectate((res) => {\n ref.current(res);\n });\n }, []);\n};\n","import { useEffect, useRef } from \"react\";\nimport { AvatarResponse } from \"../../../api/types/transport\";\nimport socket from \"../../../api/socketClient\";\n\nexport const useOnAvatar = (callback: (res: AvatarResponse) => void) => {\n const ref = useRef(callback);\n\n ref.current = callback; \n\n useEffect(() => {\n socket.subscribeAvatarResponse((res) => {\n ref.current(res);\n });\n }, []);\n};\n\nexport const useOnAvatarSingle = (callback: (res: AvatarResponse) => void) => {\n const guarded = useRef(false);\n const ref = useRef(callback);\n\n if (!guarded.current) ref.current = callback;\n\n useEffect(() => {\n socket.subscribeAvatarResponse((res) => {\n if (guarded.current) return;\n guarded.current = true;\n ref.current(res);\n });\n }, []);\n};\n","import { useEffect, useRef } from \"react\";\nimport socket from \"../../../api/socketClient\";\n\nexport const useOnChat = (callback: (msg: string) => void) => {\n const ref = useRef(callback);\n\n ref.current = callback; \n\n useEffect(() => {\n socket.subscribeChat((msg) => {\n ref.current(msg);\n });\n }, []);\n};\n\nexport const useOnChatSingle = (callback: (msg: string) => void) => {\n const guarded = useRef(false);\n const ref = useRef(callback);\n\n if (!guarded.current) ref.current = callback;\n\n useEffect(() => {\n socket.subscribeChat((msg) => {\n if (guarded.current) return;\n guarded.current = true;\n ref.current(msg);\n });\n }, []);\n};\n","import { useEffect, useRef } from \"react\";\nimport socket from \"../../../api/socketClient\";\nimport { ShootResponse } from \"../../../api/types/transport\";\n\nexport const useOnShoot = (callback: (res: ShootResponse) => void) => {\n const ref = useRef(callback);\n\n ref.current = callback; \n\n useEffect(() => {\n socket.subscribeShootResponse((res) => {\n ref.current(res);\n });\n }, []);\n};\n\nexport const useOnShootSingle = (callback: (res: ShootResponse) => void) => {\n const guarded = useRef(false);\n const ref = useRef(callback);\n\n if (!guarded.current) ref.current = callback;\n\n useEffect(() => {\n socket.subscribeShootResponse((res) => {\n if (guarded.current) return;\n guarded.current = true;\n ref.current(res);\n });\n }, []);\n};\n","import { useEffect, useRef } from \"react\";\nimport { ShipDestroyedResponse } from \"../../../api/types/transport\";\nimport socket from \"../../../api/socketClient\";\n\nexport const useOnShipDestroyed = (callback: (res: ShipDestroyedResponse) => void) => {\n const ref = useRef(callback);\n\n ref.current = callback; \n\n useEffect(() => {\n socket.subscribeShipDestroyed((res) => {\n ref.current(res);\n });\n }, []);\n};\n\nexport const useOnShipDestroyedSingle = (callback: (res: ShipDestroyedResponse) => void) => {\n const guarded = useRef(false);\n const ref = useRef(callback);\n\n if (!guarded.current) ref.current = callback;\n\n useEffect(() => {\n socket.subscribeShipDestroyed((res) => {\n if (guarded.current) return;\n guarded.current = true;\n ref.current(res);\n });\n }, []);\n};\n","import { useEffect, useRef } from \"react\";\nimport { StatResponse } from \"../../../api/types/transport\";\nimport socket from \"../../../api/socketClient\";\n\nexport const useOnStatistics = (callback: (res: StatResponse) => void) => {\n const ref = useRef(callback);\n\n ref.current = callback; \n\n useEffect(() => {\n socket.subscribeStatistic((res) => {\n ref.current(res);\n });\n }, []);\n};\n\nexport const useOnStatisticsSingle = (callback: (res: StatResponse) => void) => {\n const guarded = useRef(false);\n const ref = useRef(callback);\n\n if (!guarded.current) ref.current = callback;\n\n useEffect(() => {\n socket.subscribeStatistic((res) => {\n if (guarded.current) return;\n guarded.current = true;\n ref.current(res);\n });\n }, []);\n};\n","export enum RoomMode {\n Public = \"public\",\n Private = \"private\",\n}\n","import styled from \"../../../styles/theme\";\nimport { RoomMode } from \"../types/utility\";\n\ninterface Props {\n roomMode: RoomMode;\n onRoomModeToggleHandler: (value: RoomMode) => void;\n}\n\nconst RoomModeSlider: React.FC = ({\n roomMode,\n onRoomModeToggleHandler,\n}) => {\n const isChecked = roomMode === RoomMode.Private;\n\n const handleSwitchClick = () => {\n onRoomModeToggleHandler(isChecked ? RoomMode.Public : RoomMode.Private);\n };\n\n return (\n \n \n \n Public\n Private\n \n \n );\n};\n\nconst Container = styled.div`\n width: 7.8125rem;\n height: 1.875rem;\n\n background: #302b4a;\n border-radius: 0.375rem;\n\n position: relative;\n\n cursor: pointer;\n`;\n\nconst Slider = styled.span<{ isChecked: boolean }>`\n position: absolute;\n cursor: pointer;\n top: -1rem;\n\n &::before {\n position: absolute;\n content: \"\";\n height: 1.375rem;\n width: 3.75rem;\n transition: 0.4s;\n border-radius: 0.3125rem;\n background-color: ${(props) =>\n props.theme.colors.lobby.slider.background.light};\n transform: translateX(0.25rem);\n top: 1.25rem;\n\n ${(props) =>\n props.isChecked &&\n `\n transform: translateX(4rem);\n width: 3.6rem;`}\n }\n`;\n\nconst TextContainer = styled.div<{ isChecked: boolean }>`\n position: relative;\n\n height: 100%;\n width: 100%;\n\n display: flex;\n align-items: center;\n\n & > * {\n user-select: none;\n }\n\n & > *:first-child {\n margin: 0 1.0625rem 0 0.84375rem;\n }\n\n font-weight: 500;\n font-size: 0.875rem;\n line-height: 1.125rem;\n\n color: ${(props) => props.theme.colors.lobby.slider.text.default};\n\n flex: none;\n order: 0;\n flex-grow: 0;\n\n ${(props) =>\n props.isChecked\n ? `\n & > *:last-child { \n color: ${props.theme.colors.lobby.slider.text.selected};\n\n }\n `\n : `\n & > *:first-child {\n color: ${props.theme.colors.lobby.slider.text.selected};\n }\n `}\n`;\n\nexport default RoomModeSlider;\n","import { AnimatePresence, motion } from \"framer-motion\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { useHistory } from \"react-router\";\nimport socketClient from \"../../../api/socketClient\";\nimport styled from \"../../../styles/theme\";\nimport AvatarVersus from \"../../avatar/components/avatarVersus\";\nimport { useOnJoinSingle } from \"../../game/functions/useOnJoin\";\nimport { HeaderText, Tag, WhiteBox } from \"../components/base.styled\";\nimport RoomModeSlider from \"../components/roomModeSlider\";\nimport { useUserContext } from \"../contexts/userContext\";\nimport { RoomMode } from \"../types/utility\";\n\nconst CreateRoomPage = () => {\n const { username, userAvatarSeed } = useUserContext();\n const history = useHistory();\n\n const roomComplete = useRef(false);\n\n const [roomId, setRoomId] = useState(\"\");\n const [roomMode, setRoomMode] = useState(RoomMode.Public);\n const [linkCopied, setLinkCopied] = useState(false);\n\n const handleRoomModeToggle = (mode: RoomMode) => {\n setRoomMode(mode);\n socketClient.toggleLock();\n };\n\n const handleCopyLink = () => {\n if (!roomId) return;\n\n const link =\n window.location.href.split(\"/\").slice(0, -1).join(\"/\") +\n \"/rooms?roomId=\" +\n roomId;\n navigator.clipboard.writeText(link);\n if (!linkCopied) {\n setLinkCopied(true);\n setTimeout(() => {\n setLinkCopied(false);\n }, 1000);\n }\n };\n\n useEffect(() => {\n const asyncCreateRoom = async () => {\n const createdRoomId = (await socketClient.createRoom(username))\n .roomID;\n setRoomId(createdRoomId);\n socketClient.setAvatar(userAvatarSeed);\n };\n\n asyncCreateRoom();\n\n return () => {\n if (!roomComplete.current) {\n socketClient.withdraw();\n }\n };\n }, [userAvatarSeed, username]);\n\n useOnJoinSingle(({ responseStatus }) => {\n if (!roomId) return;\n switch (responseStatus) {\n case \"Completed\":\n roomComplete.current = true;\n history.push({\n pathname: \"/room\",\n search:\n \"?\" +\n new URLSearchParams({\n roomId,\n isHost: \"true\",\n }),\n });\n break;\n default:\n alert(responseStatus);\n }\n });\n\n return (\n \n \n \n \n Waiting for other player...\n \n \n \n \n Share the code below with the other player. Ask them to\n click\n \n Join Room\n and enter the code.\n \n \n handleCopyLink()}\n >\n \n {roomId && (\n \n \n \n \n \n {roomId.toUpperCase()}\n \n \n )}\n \n \n \n {linkCopied && (\n \n \n \n \n Link Copied\n \n )}\n \n \n );\n};\n\nconst Container = styled(WhiteBox)`\n background: none;\n\n & > *:first-child {\n margin-bottom: 1.6875rem;\n }\n`;\n\nconst InfoBox = styled.div`\n display: flex;\n flex-flow: column;\n\n padding: 1.75rem 2rem 0;\n\n background: ${(props) => props.theme.colors.lobby.backdrop.light};\n\n border-radius: 0.75rem 0.75rem 0 0;\n`;\n\nconst HeadingBox = styled.div`\n display: flex;\n justify-content: space-between;\n align-items: center;\n\n margin-bottom: 1.3125rem;\n`;\n\nconst Title = styled(HeaderText)`\n font-weight: 500;\n font-size: 1rem;\n line-height: 1.3125rem;\n`;\n\nconst Guidelines = styled.p`\n margin: 0;\n margin-bottom: 1.375rem;\n padding: 0;\n\n font-weight: 500;\n font-size: 1rem;\n line-height: 1.75rem;\n\n user-select: none;\n\n color: ${(props) => props.theme.colors.lobby.info.guidelines};\n`;\n\nconst GameCode = styled.div`\n background: ${(props) => props.theme.colors.lobby.backdrop.shadedLight};\n\n font-weight: 700;\n font-size: 2.25rem;\n line-height: 2.9375rem;\n height: 5.4375rem;\n\n letter-spacing: 0.2em;\n\n color: ${(props) => props.theme.colors.lobby.info.heading};\n\n display: grid;\n place-items: center;\n padding: 1.375rem 0;\n\n border-radius: 0 0 0.75rem 0.75rem;\n\n cursor: pointer;\n`;\n\nconst DisappearingNotification = styled(motion.div)`\n align-self: center;\n\n position: fixed;\n top: 2rem;\n width: 10rem;\n height: 2.4rem;\n background: white;\n\n font-weight: 500;\n\n display: flex;\n align-items: center;\n justify-content: space-between;\n\n padding: 0 1rem;\n\n border-radius: 0.25rem;\n`;\n\nexport default CreateRoomPage;\n","import { useEffect, useRef } from \"react\";\nimport socket from \"../../../api/socketClient\";\nimport { JoinRoomResponse } from \"../../../api/types/transport\";\n\nexport const useOnJoin = (callback: (res: JoinRoomResponse) => void) => {\n const ref = useRef(callback);\n\n ref.current = callback;\n\n useEffect(() => {\n socket.subscribeJoinResponse((res) => {\n ref.current(res);\n });\n }, []);\n};\n\nexport const useOnJoinSingle = (callback: (res: JoinRoomResponse) => void) => {\n const guarded = useRef(false);\n const ref = useRef(callback);\n\n if (!guarded.current) ref.current = callback;\n\n useEffect(() => {\n socket.subscribeJoinResponse((res) => {\n if (guarded.current) return;\n guarded.current = true;\n ref.current(res);\n });\n\n return () => {\n guarded.current = true; \n }\n }, []);\n};\n","import { motion, MotionProps } from \"framer-motion\";\nimport { InputHTMLAttributes } from \"react\";\nimport styled from \"../../../styles/theme\";\n\nconst BasicInput: React.FC<\n InputHTMLAttributes & MotionProps\n> = ({ ...delegated }) => {\n return ;\n};\n\nconst StyledInput = styled(motion.input)`\n background: ${(props) => props.theme.colors.lobby.input.background.light};\n border-radius: 0.375rem;\n\n width: 100%;\n height: 3.5rem;\n\n font-weight: 400;\n font-size: 1rem;\n line-height: 1.3125rem;\n\n padding-left: 1.375rem;\n\n color: black;\n\n &::placeholder {\n color: ${(props) => props.theme.colors.lobby.input.text.placeholder};\n }\n`;\n\nexport default BasicInput;\n","import { createContext, useContext } from \"react\";\nimport { Room } from \"../../../api/types/transport\";\n\n// initializes with empty Product\nexport const RoomContext = createContext<{\n hoveredRoom?: Room;\n setHoveredRoom: (room?: Room) => void;\n}>({\n hoveredRoom: undefined,\n setHoveredRoom: () => {},\n});\n\nexport const useRoomContext = () => useContext(RoomContext);\n","import { AnimatePresence, motion, Variants } from \"framer-motion\";\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useHistory } from \"react-router\";\nimport socketClient from \"../../../api/socketClient\";\nimport { AdminSpectateRoom, Room } from \"../../../api/types/transport\";\nimport styled from \"../../../styles/theme\";\nimport UserAvatar from \"../../avatar/components/userAvatar\";\nimport useQuery from \"../../routing/hooks/useQuery\";\nimport { useRoomContext } from \"../contexts/roomContext\";\nimport { useUserContext } from \"../contexts/userContext\";\n\n// ping getRooms every 1 second\nconst REFRESH_INTERVAL = 1000;\n\nconst container: Variants = {\n hidden: { height: 0 },\n show: {\n height: \"14.375rem\",\n transition: {\n delay: 0.2,\n staggerChildren: 0.25,\n duration: 0.25,\n },\n },\n};\n\nconst listItem: Variants = {\n hidden: { y: -5, opacity: 0 },\n show: { y: 0, opacity: 1, transition: { duration: 0.2 } },\n};\n\ninterface Props {\n onRoomJoinHandler: (roomID: string) => void;\n}\n\nconst PublicRoomsList: React.FC = ({ onRoomJoinHandler }) => {\n const { setHoveredRoom } = useRoomContext();\n const { isAdmin } = useUserContext();\n\n const query = useQuery();\n const spectatorMode = query.get(\"spectator\") === \"true\" && isAdmin;\n\n const [roomList, setRoomList] = useState<(Room | AdminSpectateRoom)[]>([]);\n const [allowOverflowY, setOverflowY] = useState(false);\n\n const handleFetchRoomList = useCallback(async () => {\n let fetchedRoomList: (Room | AdminSpectateRoom)[] = [];\n if (spectatorMode) {\n const { roomList: adminFetchedRoomList } =\n await socketClient.adminGetRooms();\n fetchedRoomList = adminFetchedRoomList;\n } else {\n fetchedRoomList = (await socketClient.getRooms()).roomList;\n }\n setRoomList(fetchedRoomList);\n }, [spectatorMode]);\n\n useEffect(() => {\n let interval: ReturnType;\n\n const asyncRefreshRoomList = async () => {\n handleFetchRoomList();\n interval = setInterval(async () => {\n handleFetchRoomList();\n }, REFRESH_INTERVAL);\n };\n\n asyncRefreshRoomList();\n\n return () => {\n clearInterval(interval);\n };\n }, [handleFetchRoomList]);\n\n const displayedRooms = roomList.map((room) => {\n const { roomID, hostAvatar, hostUsername } = room;\n return (\n !spectatorMode && onRoomJoinHandler(roomID)}\n onHoverStart={() => setHoveredRoom(room)}\n onHoverEnd={() => setHoveredRoom(undefined)}\n variants={listItem}\n exit={{ opacity: 0, transition: { duration: 0.2 } }}\n >\n
\n
\n \n {spectatorMode &&\n (room as AdminSpectateRoom).guestUsername && (\n \n )}\n
\n \n {hostUsername}\n {spectatorMode &&\n (room as AdminSpectateRoom).guestUsername\n ? \" vs \" + (room as AdminSpectateRoom).guestUsername\n : \"\"}\n \n
\n {spectatorMode ? \"\" : \"Join\"}\n \n );\n });\n\n return (\n \n \n {roomList.length > 0 && (\n setOverflowY(false)}\n onAnimationComplete={() => setOverflowY(true)}\n style={{\n overflowY: allowOverflowY ? \"auto\" : \"hidden\",\n }}\n >\n {displayedRooms}\n \n )}\n \n \n );\n};\n\nconst Container = styled(motion.div)`\n display: flex;\n flex-flow: column;\n\n margin: 2.25rem 0 1.0625rem;\n\n width: 28.6875rem;\n\n gap: 1.0625rem;\n\n & > * {\n font-weight: 500;\n font-size: 1rem;\n line-height: 1.3125rem;\n\n color: ${(props) => props.theme.colors.lobby.button.text.primary};\n }\n`;\n\nconst OverflowContainer = styled(motion.div)`\n overflow-x: hidden;\n`;\n\n// const RoomsContainer = styled(motion.div)`\n// display: flex;\n// flex-flow: column;\n// gap: 0.625rem;\n// `;\n\nconst SingleRoom = styled(motion.div)`\n display: flex;\n justify-content: space-between;\n align-items: flex-end;\n\n margin-bottom: 0.625rem;\n\n background: ${(props) => props.theme.colors.lobby.button.background.room};\n color: ${(props) => props.theme.colors.lobby.button.text.room};\n\n /* padding: 0.875rem 1.9375rem; */\n height: 3.125rem;\n\n border-radius: 0.75rem;\n cursor: pointer;\n\n & > *:first-child {\n display: flex;\n align-items: flex-end;\n\n & > .avatarContainer {\n display: flex;\n margin: 0 1rem 0 1.3125rem;\n position: relative;\n\n & > * {\n width: 2.5rem;\n height: 2.5rem;\n\n &:nth-child(2) {\n position: absolute;\n transform: translateX(1.5rem);\n }\n }\n }\n & > .username {\n color: ${(props) => props.theme.colors.lobby.button.text.roomDark};\n height: 3.125rem;\n\n display: grid;\n place-items: center;\n }\n }\n\n & > *:last-child {\n width: 6rem;\n height: 100%;\n\n border-radius: 0 0.75rem 0.75rem 0;\n\n display: grid;\n place-items: center;\n }\n`;\n\nexport default PublicRoomsList;\n","import { useCallback, useEffect, useState } from \"react\";\nimport { useHistory } from \"react-router\";\nimport { Room } from \"../../../api/types/transport\";\nimport styled from \"../../../styles/theme\";\nimport AvatarVersus from \"../../avatar/components/avatarVersus\";\nimport useQuery from \"../../routing/hooks/useQuery\";\nimport { HeaderText, WhiteBox } from \"../components/base.styled\";\nimport BasicInput from \"../components/basicInput\";\nimport PublicRoomsList from \"../components/publicRoomsList\";\nimport { RoomContext } from \"../contexts/roomContext\";\nimport { useUserContext } from \"../contexts/userContext\";\n\nconst JoinRoomPage = () => {\n const { userAvatarSeed, username, isAdmin } = useUserContext();\n const history = useHistory();\n const query = useQuery();\n\n const [privateRoomId, setPrivateRoomId] = useState(\n query.get(\"roomId\") || \"\"\n );\n const [hoveredRoom, setHoveredRoom] = useState();\n\n const spectatorMode = query.get(\"spectator\") === \"true\" && isAdmin;\n\n const handleJoinRoom = useCallback(\n (roomId: string) => {\n if (username && roomId)\n history.push({\n pathname: \"/room\",\n search: \"?\" + new URLSearchParams({ roomId }),\n });\n else\n history.push({\n pathname: \"/\",\n search: \"?\" + new URLSearchParams({ roomId }),\n });\n },\n [history, username]\n );\n\n useEffect(() => {\n if (privateRoomId.length === 6) handleJoinRoom(privateRoomId);\n }, [handleJoinRoom, privateRoomId]);\n\n return (\n \n \n {!spectatorMode && (\n <>\n \n \n Join Private Room\n \n setPrivateRoomId(e.target.value)\n }\n placeholder=\"Enter a 6-digit room code\"\n />\n \n \n )}\n {spectatorMode && (\n \n Admin Spectate Mode\n \n )}\n \n \n \n );\n};\n\nconst Container = styled(WhiteBox)`\n background: none;\n\n & > *:first-child {\n border-radius: 0.75rem 0.75rem 0 0;\n }\n`;\n\nconst PrivateRoomContainer = styled.div`\n display: flex;\n flex-flow: column;\n padding: 1.625rem 2rem;\n\n background: ${(props) => props.theme.colors.lobby.backdrop.light};\n\n border-radius: 0 0 0.75rem 0.75rem;\n`;\n\nconst AdminRoomContainer = styled(PrivateRoomContainer)`\n border-radius: 0.75rem !important;\n align-items: center;\n justify-content: center;\n\n padding: 1rem 2rem;\n\n & > * {\n margin-bottom: 0 !important;\n }\n`;\n\nconst Title = styled(HeaderText)`\n margin-bottom: 1.1875rem;\n`;\n\nexport default JoinRoomPage;\n","import { motion, useAnimation } from \"framer-motion\";\nimport { useState } from \"react\";\nimport styled from \"styled-components\";\nimport { useUserContext } from \"../../lobby/contexts/userContext\";\nimport UserAvatar from \"./userAvatar\";\n\nconst DEFAULT_AVATARS: string[] = [\"nnaries\", \"wt\", \"dinger\", \"rocks\"];\n\nconst getRandomSeed = (): string => {\n return Math.random().toString(36).substring(2, 5);\n};\n\nconst getDefaultAvatars = (): string[] => {\n const savedAvatarSeed = localStorage.getItem(\"userAvatarSeed\");\n\n return DEFAULT_AVATARS.reduce((acc, seed, idx) => {\n if (idx === 0 && savedAvatarSeed) return [savedAvatarSeed];\n if (seed === savedAvatarSeed) {\n let randomSeed = getRandomSeed();\n while (acc.includes(randomSeed)) randomSeed = getRandomSeed();\n return [...acc, randomSeed];\n }\n return [...acc, seed];\n }, [] as string[]);\n};\n\nconst variants = {\n randomizing: {\n rotate: [0, 20, -15, 10, -5, 0, 0],\n x: [0, -2, 4, 0, 4, -2, 0],\n y: [0, 4, -2, 0, -4, -2, 0],\n transition: {\n repeat: Infinity,\n duration: 0.5,\n },\n },\n static: {\n rotate: 0,\n },\n};\n\nconst AvatarSelector = () => {\n const [randomSeeds, setRandomSeeds] = useState(\n getDefaultAvatars()\n );\n const { userAvatarSeed: actualUserAvatarSeed, setUserAvatarSeed } =\n useUserContext();\n const controls = useAnimation();\n\n const userAvatarSeed = actualUserAvatarSeed || randomSeeds[0];\n\n const displayedAvatars = randomSeeds.map((seed) => (\n {\n setUserAvatarSeed(seed);\n localStorage.setItem(\"userAvatarSeed\", seed);\n }}\n />\n ));\n\n const handleRandomize = () => {\n controls.start(\"randomizing\");\n setTimeout(() => {\n controls.stop();\n controls.set(\"static\");\n }, 500);\n const newSeeds: string[] = randomSeeds.reduce((acc, seed) => {\n if (seed === userAvatarSeed) return [...acc, seed];\n let randomSeed = getRandomSeed();\n while (acc.includes(randomSeed)) randomSeed = getRandomSeed();\n return [...acc, randomSeed];\n }, [] as string[]);\n setRandomSeeds(newSeeds);\n };\n\n return (\n \n {displayedAvatars}\n \n \n \n \n \n \n );\n};\n\nconst Container = styled.div`\n height: 9.0625rem;\n\n background: ${(props) => props.theme.colors.lobby.avatar.background.light};\n\n padding: 1.75rem;\n\n display: flex;\n justify-content: space-between;\n align-items: center;\n\n border-radius: 0.75rem 0.75rem 0 0;\n`;\n\nconst AvatarContainer = styled.div`\n display: flex;\n align-items: center;\n\n & > * {\n cursor: pointer;\n margin-right: 1rem;\n }\n`;\n\nconst DiceButton = styled(motion.div)`\n height: 3rem;\n width: 3rem;\n\n display: grid;\n place-items: center;\n\n background: ${(props) => props.theme.colors.lobby.avatar.background.medium};\n\n border-radius: 0.75rem;\n\n cursor: pointer;\n`;\n\nexport default AvatarSelector;\n","import React from \"react\";\nimport styled from \"../../../styles/theme\";\nimport { LabelText } from \"../components/base.styled\";\n\nconst LabelWrapper: React.FC<{ label: string }> = ({ label, children }) => {\n return (\n \n {label}\n {children}\n \n );\n};\n\nconst Container = styled.div`\n display: flex;\n flex-flow: column;\n\n gap: 0.4375rem;\n`;\n\nexport default LabelWrapper;\n","import styled from \"../../../styles/theme\";\n\nconst CreditsBox = () => {\n return (\n \n
Authored By
\n
\n @winnaries @wasurocks\n
\n @mossdinger @bosswt\n
\n
\n );\n};\n\nconst Container = styled.div`\n position: absolute;\n bottom: 1.75rem;\n height: 4.6875rem;\n font-family: \"DM Mono\", sans-serif;\n\n & > * {\n text-align: center;\n font-size: 1rem;\n line-height: 1.3125rem;\n &:first-child {\n color: ${(props) => props.theme.colors.lobby.credits.light};\n font-weight: 500;\n height: 1.875rem;\n }\n\n &:last-child {\n color: ${(props) => props.theme.colors.lobby.credits.medium};\n font-weight: 400;\n }\n }\n`;\n\nexport default CreditsBox;\n","import styled from \"../../../styles/theme\";\nimport CreditsBox from \"../components/creditsBox\";\n\nconst LobbyLayoutWrapper: React.FC = ({ children }) => {\n return (\n \n \n {children}\n \n );\n};\n\nconst Container = styled.div`\n background: ${(props) => props.theme.colors.lobby.backdrop.dark};\n\n position: relative;\n\n width: 100%;\n height: 100vh;\n overflow: hidden;\n\n display: flex;\n flex-flow: column;\n align-items: center;\n justify-content: center;\n`;\n\nexport default LobbyLayoutWrapper;\n","import React from \"react\";\n\nconst BattleshipIcon = () => {\n return (\n \n \n \n \n \n \n \n \n \n );\n};\n\nexport default BattleshipIcon;\n","import { useCallback, useEffect, useState } from \"react\";\n\nconst charList =\n \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\nconst MAX_TIME_LIMIT = 5000;\n\nconst useKeySequenceListener = (\n onSequenceSubmitCallback: (sequence: string) => Promise\n) => {\n const [buffer, setBuffer] = useState([]);\n const [lastKeyTime, setLastKeyTime] = useState(Date.now());\n\n const keySequenceListener = useCallback(\n async (e: KeyboardEvent) => {\n const key = e.key;\n\n if (key === \"Enter\") {\n await onSequenceSubmitCallback(buffer.join(\"\"));\n setBuffer([]);\n }\n if (!charList.includes(key)) return;\n\n const currentTime = Date.now();\n\n if (currentTime - lastKeyTime > MAX_TIME_LIMIT) setBuffer([]);\n\n setBuffer((buffer) => [...buffer, key]);\n\n setLastKeyTime(currentTime);\n },\n [buffer, lastKeyTime, onSequenceSubmitCallback]\n );\n\n useEffect(() => {\n document.addEventListener(\"keydown\", keySequenceListener);\n return () => {\n document.removeEventListener(\"keydown\", keySequenceListener);\n };\n }, [keySequenceListener]);\n};\n\nexport default useKeySequenceListener;\n","import { useHistory } from \"react-router\";\nimport styled from \"styled-components\";\nimport useQuery from \"../../routing/hooks/useQuery\";\nimport { Backdrop, HeaderText, WhiteBox } from \"../components/base.styled\";\nimport BasicButton from \"../components/basicButton\";\nimport BasicInput from \"../components/basicInput\";\nimport AvatarSelector from \"../../avatar/components/avatarSelector\";\nimport { useUserContext } from \"../contexts/userContext\";\nimport LabelWrapper from \"../wrappers/labelWrapper\";\nimport LobbyLayoutWrapper from \"../wrappers/lobbyLayoutWrapper\";\nimport { useEffect, useState } from \"react\";\nimport BattleshipIcon from \"../components/battleshipIcon\";\nimport useKeySequenceListener from \"../hooks/useKeySequenceListener\";\nimport socketClient from \"../../../api/socketClient\";\nimport { useAnimation, Variants } from \"framer-motion\";\n\n// shakes the input when it is invalid\nconst inputVariants: Variants = {\n shake: {\n transition: {\n duration: 0.3,\n ease: \"easeInOut\",\n },\n x: [0, -5, 0, 5, 0, -2, 0, 2, 0],\n },\n};\n\nconst WelcomePage = () => {\n const history = useHistory();\n const query = useQuery();\n\n const roomId = query.get(\"roomId\");\n\n console.log(\"Roomid\", roomId);\n\n const controls = useAnimation();\n\n const { username, setUsername, setIsAdmin } = useUserContext();\n\n const [showUsernameError, setShowUsernameError] = useState(false);\n\n // admin cheat code login (but password is verified on server so it's secure)\n useKeySequenceListener(async (sequence) => {\n try {\n await socketClient.adminLogin(sequence);\n setIsAdmin(true);\n history.push(\"/rooms?spectator=true\");\n } catch (e) {} // fail silently\n });\n\n const validateUsername = () => {\n if (!username) {\n controls.start(\"shake\");\n }\n setShowUsernameError(!username);\n return !!username;\n };\n\n const handleEnterRoom = () => {\n if (!validateUsername()) return;\n if (roomId) {\n history.push({\n pathname: \"/room\",\n search: \"?\" + new URLSearchParams({ roomId }),\n });\n } else history.push(\"/rooms\" + (roomId ? `?roomId=${roomId}` : \"\"));\n };\n\n useEffect(() => {\n if (username && showUsernameError) {\n setShowUsernameError(false);\n }\n }, [username, showUsernameError]);\n\n return (\n \n \n \n \n <BattleshipIcon />\n <span>Battleship</span>\n \n \n handleEnterRoom()}>\n \n setUsername(e.target.value)}\n placeholder=\"Tofu, Dinger, Wasu, or etc.\"\n animate={controls}\n variants={inputVariants}\n style={{\n border: showUsernameError\n ? \"solid 0.125rem #FF9A61\"\n : \"none\",\n }}\n />\n \n \n {!roomId && (\n \n validateUsername() && history.push(\"/new\")\n }\n >\n Create Room\n \n )}\n handleEnterRoom()}\n >\n Join Room\n \n \n \n {/* \n \n \n Single Mode\n \n \n */}\n \n \n );\n};\n\nconst Rectangle = styled.div`\n position: absolute;\n width: 150%;\n height: 7.5rem;\n margin: 0 auto;\n\n background: #7c62ff;\n transform: rotate(-25.47deg);\n`;\n\nconst Container = styled(WhiteBox)`\n width: 32.3125rem;\n position: relative;\n`;\n\nconst FormBox = styled.form`\n display: flex;\n flex-flow: column;\n\n padding: 1.75rem 2rem 0;\n`;\n\nconst Title = styled(HeaderText)`\n display: flex;\n flex-flow: column;\n\n & > *:first-child {\n transform: translateY(0.4rem) translateX(-0.4rem);\n }\n\n position: absolute;\n\n top: -7.75rem;\n left: 1.875rem;\n\n color: ${(props) => props.theme.colors.lobby.info.battleship};\n\n font-weight: 700;\n font-size: 2.25rem;\n line-height: 2.9375rem;\n`;\n\nconst ButtonContainer = styled.div<{ fullButton?: boolean }>`\n display: flex;\n gap: 0.9375rem;\n\n margin: 1.875rem 0 1.5rem;\n\n & > * {\n &:first-child {\n flex: 0.452;\n }\n &:last-child {\n flex: ${(props) => (props.fullButton ? 1 : 0.548)};\n }\n }\n`;\n\n// const ExperimentalZone = styled.div`\n// background: ${(props) => props.theme.colors.lobby.backdrop.shadedLight};\n\n// padding: 1.1875rem 2rem 1.75rem;\n// `;\n\nexport default WelcomePage;\n","import React from \"react\";\nimport { Route, RouteProps, Redirect } from \"react-router\";\nimport { useUserContext } from \"../../lobby/contexts/userContext\";\nimport LobbyLayoutWrapper from \"../../lobby/wrappers/lobbyLayoutWrapper\";\n\nconst LobbyRoute: React.FC<{ userRequired?: boolean } & RouteProps> = ({\n userRequired,\n children,\n ...delegated\n}) => {\n const renderedComponent = (\n {children}\n );\n const { username } = useUserContext();\n\n if (userRequired && !username) return ;\n return {renderedComponent};\n};\n\nexport default LobbyRoute;\n","import { BrowserRouter as Router, Switch } from \"react-router-dom\";\nimport GamePage from \"../../game/screens/gamePage\";\nimport CreateRoomPage from \"../../lobby/screens/createRoomPage\";\nimport JoinRoomPage from \"../../lobby/screens/joinRoomPage\";\nimport WelcomePage from \"../../lobby/screens/welcomePage\";\nimport LobbyRoute from \"./lobbyRoute\";\n\nconst MainRouter = () => {\n return (\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n );\n};\n\nexport default MainRouter;\n","import { createGlobalStyle } from \"styled-components\";\n\nimport { Theme } from \"./theme\";\n\nconst globalStyle = createGlobalStyle<{\n theme: Theme;\n}>`\n\nhtml {\n text-rendering: optimizeLegibility;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\nbody {\n margin: 0;\n padding: 0;\n font-family: 'DM Sans', sans-serif;\n}\n\ninput, button {\n border: none;\n background-color: transparent;\n -webkit-box-shadow: none;\n -moz-box-shadow: none;\n box-shadow: none;\n font-size: 16px;\n outline: none;\n}\n\n* {\n box-sizing: border-box;\n}\n\n\n@media (min-width: ${(props) => props.theme.breakPoints.desktop}px) {\n html {\n font-size: 18px;\n }\n}\n\n@media (min-width: ${(props) => props.theme.breakPoints.widescreen}px) {\n html {\n font-size: 24px;\n }\n}\n\n`;\n\nexport default globalStyle;\n","import { useEffect, useState } from \"react\";\nimport { ThemeProvider } from \"styled-components\";\nimport socketClient from \"./api/socketClient\";\nimport { UserContext } from \"./features/lobby/contexts/userContext\";\nimport MainRouter from \"./features/routing/components/mainRouter\";\nimport GlobalStyles from \"./styles/globalStyles\";\nimport { theme } from \"./styles/theme\";\n\nconst App = () => {\n const [username, setUsername] = useState(\n localStorage.getItem(\"username\") || \"\"\n );\n const [userAvatarSeed, setUserAvatarSeed] = useState(\n localStorage.getItem(\"userAvatarSeed\") || \"nnaries\"\n );\n const [isAdmin, setIsAdmin] = useState(false);\n\n useEffect(() => {\n localStorage.setItem(\"username\", username);\n }, [username]);\n\n useEffect(() => {\n return () => {\n socketClient.disconnect();\n };\n }, []);\n\n return (\n \n \n \n \n \n \n );\n};\n\nexport default App;\n","import { ReportHandler } from 'web-vitals';\n\nconst reportWebVitals = (onPerfEntry?: ReportHandler) => {\n if (onPerfEntry && onPerfEntry instanceof Function) {\n import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {\n getCLS(onPerfEntry);\n getFID(onPerfEntry);\n getFCP(onPerfEntry);\n getLCP(onPerfEntry);\n getTTFB(onPerfEntry);\n });\n }\n};\n\nexport default reportWebVitals;\n","import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.css';\nimport App from './App';\nimport reportWebVitals from './reportWebVitals';\n\nReactDOM.render(\n \n \n ,\n document.getElementById('root')\n);\n\n// If you want to start measuring performance in your app, pass a function\n// to log results (for example: reportWebVitals(console.log))\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\nreportWebVitals();\n"],"sourceRoot":""}