-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: copy over inflated chickens types and ws
- Loading branch information
1 parent
4bc0f8e
commit 811b9d5
Showing
6 changed files
with
305 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
// For DB | ||
export type Match = { | ||
match_key: string | ||
event_key: string | ||
} | ||
|
||
export type User = { | ||
id: string | ||
name: string | ||
is_admin: boolean | ||
slack_token: string | ||
} | ||
|
||
// DB Tables | ||
|
||
/// Auto actions table stored and retreived from the backend | ||
export type AutoActionsTM = ActionsTM & { | ||
coral_l1: number | ||
coral_l2: number | ||
coral_l3: number | ||
coral_l4: number | ||
algae_l2: number | ||
algae_l3: number | ||
// TODE | ||
actions: AutoActionData[] | ||
} | ||
|
||
export type TeleActionsTM = ActionsTM & { | ||
actions: TeleActionData[] | ||
} | ||
|
||
export type ActionsTM = { | ||
id: number | ||
// TODO | ||
} | ||
|
||
/// TeamMatch data that gets sent to the backend | ||
export type TeamMatch = { | ||
id: number | ||
scout_id: string | ||
match_key: string | ||
team_key: string | ||
leave: boolean | ||
skill: number | ||
notes: string | ||
broke: boolean | ||
died: boolean | ||
auto_actions: AutoActionData[] | ||
tele_actions: TeleActionData[] | ||
} | ||
|
||
export type AutoActionData = { | ||
action: AutoAction | ||
success: boolean | ||
ok: boolean | ||
} | ||
|
||
export type TeleActionData = { | ||
action: TeleAction | ||
success: boolean | ||
ok: boolean | ||
} | ||
|
||
// Action Types | ||
// Naming Convention: action_type + game_piece + where | ||
// TODO | ||
export type TeleAction = "" | ||
|
||
export type PreAction = "" | "" | ||
export type AutoAction = TeleAction | PreAction | ||
|
||
export type TeleHeldItems = { | ||
// TODO | ||
} | ||
export type AutoHeldItems = TeleHeldItems | ||
|
||
// For state machine | ||
// TODO Decide in intake semantics | ||
export type ItemInputState = "Intake" | "Score" | "Eject" | "None" | ||
export type TeleInputState = TeleAction | ItemInputState | ||
export type AutoInputState = TeleInputState |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,12 @@ | ||
import { sveltekit } from "@sveltejs/kit/vite" | ||
import { defineConfig } from "vite" | ||
import webSocketServer from "./ws.js" | ||
|
||
export default defineConfig({ | ||
plugins: [sveltekit()], | ||
plugins: [sveltekit(), webSocketServer], | ||
server: { | ||
fs: { | ||
allow: ["./"], | ||
}, | ||
}, | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
import type { TeamMatch } from "$lib/types" | ||
import { Server } from "socket.io" | ||
import { type ViteDevServer } from "vite" | ||
const info = (s: string) => console.log(`\x1b[32m ${s} \x1b[0m`) | ||
|
||
const sid_to_username: Map<string, string> = new Map() | ||
let robot_queue: [string, "red" | "blue"][] = [] | ||
let curr_match_key: string = "" | ||
|
||
const webSocketServer = { | ||
name: "webSocketServer", | ||
configureServer(server: ViteDevServer) { | ||
if (!server.httpServer) return | ||
const io = new Server(server.httpServer) | ||
|
||
io.use((socket, next) => { | ||
const username = socket.handshake.auth.username | ||
if (!username) { | ||
return next(new Error("invalid username")) | ||
} | ||
|
||
// erroring in prod | ||
let old_entries = Object.entries(sid_to_username).find( | ||
([_key, value]) => value === username | ||
) | ||
if (old_entries) { | ||
old_entries | ||
.map(([key, _value]) => key) | ||
.forEach(key => sid_to_username.delete(key)) | ||
} | ||
|
||
sid_to_username.set(socket.id, username) | ||
|
||
next() | ||
}) | ||
|
||
io.on("connect", socket => { | ||
if (socket.handshake.auth.token === "celary") { | ||
info("Admin Aquired") | ||
socket.join("admin_room") | ||
} | ||
|
||
socket.on("join_queue", () => { | ||
const username = sid_to_username.get(socket.id) | ||
|
||
const team_data = robot_queue.pop() | ||
if (!team_data) { | ||
io.to("admin_room").emit("scout_joined_queue", username) | ||
socket.join("scout_queue") | ||
return | ||
} | ||
io.to("admin_room").emit("robot_left_queue", team_data) | ||
socket.emit("time_to_scout", [curr_match_key, ...team_data]) | ||
}) | ||
|
||
socket.on("leave_scout_queue", (scout_id: string) => { | ||
const scout_sid = Object.entries(sid_to_username) | ||
.filter(([_sid, scout]) => scout === scout_id) | ||
.map(([sid, _]) => sid)[0] | ||
// This event exist in the cast that the scout removed itself from the queue | ||
io.emit("scout_left_queue", scout_id) | ||
// This event exists in the case that the admin removed the scout from the queue | ||
// io.to(scout_sid).emit('you_left_queue'); | ||
io.sockets.sockets.get(scout_sid)?.leave("scout_queue") | ||
}) | ||
|
||
socket.on( | ||
"leave_robot_queue", | ||
(robot: [string, "red" | "blue"]) => { | ||
const robotsEqual = ( | ||
robot1: [string, "red" | "blue"], | ||
robot2: [string, "red" | "blue"] | ||
): boolean => { | ||
return ( | ||
robot1[0] === robot2[0] && robot1[1] === robot2[1] | ||
) | ||
} | ||
const index = robot_queue.findIndex(robot_t => | ||
robotsEqual(robot_t, robot) | ||
) | ||
if (index === -1) return | ||
|
||
robot_queue.splice(index, 1) | ||
} | ||
) | ||
|
||
socket.on( | ||
"send_match", | ||
async ([match_key, teams]: [ | ||
string, | ||
[string, "red" | "blue"][], | ||
]) => { | ||
if (!socket.rooms.has("admin_room")) return | ||
|
||
// TODO: New TeamMatch in DB request here | ||
|
||
info(`${match_key}: ${teams}`) | ||
robot_queue = [] | ||
|
||
const scout_queue = ( | ||
await io.in("scout_queue").fetchSockets() | ||
).reverse() | ||
for (const socket of scout_queue) { | ||
const team_data = teams.pop() | ||
if (!team_data) break | ||
|
||
const username = sid_to_username.get(socket.id) | ||
if (!username) { | ||
console.error("Scout in queue not in map") | ||
continue | ||
} | ||
|
||
socket.leave("scout_queue") | ||
socket.emit("time_to_scout", [match_key, ...team_data]) | ||
io.to("admin_room").emit("scout_left_queue", username) | ||
} | ||
|
||
io.to("admin_room").emit("robot_joined_queue", teams) | ||
robot_queue.push(...teams) | ||
|
||
// Update all connected sockets with new match info (for cosmetic purposes) | ||
io.emit("new_match", match_key) | ||
curr_match_key = match_key | ||
} | ||
) | ||
|
||
// Event-listener sockets that were offline to sync back up with the current match key | ||
socket.on("get_curr_match", callback => { | ||
callback({ | ||
curr_match_key, | ||
}) | ||
}) | ||
|
||
socket.on("get_robot_queue", callback => { | ||
callback({ | ||
robots: robot_queue ?? [], | ||
}) | ||
}) | ||
|
||
socket.on("get_scout_queue", async callback => { | ||
callback({ | ||
scouts: ( | ||
(await io.in("scout_queue").fetchSockets()) ?? [] | ||
).reverse(), | ||
}) | ||
}) | ||
|
||
// For these two, the team match has already been sent or removed by the client sending a request to the server | ||
|
||
socket.on("submit_team_match", (team_match: TeamMatch) => { | ||
io.to("admin_room").emit("new_team_match", team_match) | ||
}) | ||
|
||
socket.on("failed_submit_team_match", (team_match: TeamMatch) => { | ||
io.to("admin_room").emit("failed_team_match", team_match) | ||
}) | ||
|
||
socket.on("disconnect", _reason => { | ||
const scout_id = sid_to_username.get(socket.id) | ||
io.to("admin_room").emit("scout_left_queue", scout_id) | ||
}) | ||
}) | ||
}, | ||
} | ||
|
||
export default webSocketServer |