Kopie van https://gitlab.com/studieverenigingvia/ict/centurion met een paar aanpassingen
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
centurion/backend/src/Service.ts

163 lines
3.6 KiB

import { Socket } from "socket.io";
import User from "./User";
import Room, { RoomOptions } from "./Room";
import { getCurrentTime } from "./util";
export default class Service {
private roomIdToRooms = new Map<number, Room>();
private socketsToUsers = new Map<string, User>();
get rooms(): Room[] {
const rooms = [];
for (const [, room] of this.roomIdToRooms) {
rooms.push(room);
}
return rooms;
}
onSocketConnect(socket: Socket) {
const user = new User(socket);
this.socketsToUsers.set(socket.id, user);
user.sync();
}
async onSocketDisconnect(socket: Socket) {
const user = this.getUser(socket);
if (user.room != null) {
await user.room.leave(user);
}
this.deleteEmptyRooms();
}
onTimeSync(socket: Socket, requestId: number, clientTime: number) {
const user = this.getUser(socket);
const now = getCurrentTime();
user.emit("time_sync", {
requestId: requestId,
clientDiff: now - clientTime,
serverTime: now,
});
}
onSetRoomOptions(socket: Socket, options: RoomOptions) {
const user = this.getUser(socket);
if (user.room?.getLeader() == user) {
user.room.setOptions(options);
}
}
onRequestStart(socket: Socket) {
const user = this.getUser(socket);
if (user.room?.getLeader() === user) {
user.room.start();
user.room.sync();
}
}
async onRequestJoin(socket: Socket, roomId: number) {
const user = this.getUser(socket);
if (user.room && user.room.id == roomId) return false;
if (user.room) {
await user.room.leave(user);
this.deleteEmptyRooms();
}
if (!this.roomIdToRooms.has(roomId)) {
this.createRoomWithId(roomId);
}
const room = this.roomIdToRooms.get(roomId);
if (!room) {
return false;
}
await room.join(user);
return true;
}
onRequestSetReady(socket: Socket) {
const user = this.getUser(socket);
if (!user.room || user.readyToParticipate) return;
user.readyToParticipate = true;
user.room.sync();
}
async onRequestJoinRandom(socket: Socket) {
const user = this.getUser(socket);
if (user.room) {
await user.room.leave(user);
this.deleteEmptyRooms();
}
const room = this.createRandomRoom();
if (!room) throw Error("Too many rooms active");
await room.join(user);
}
hasRoomId(roomId: number): boolean {
return this.roomIdToRooms.has(roomId);
}
submitTickerMessage(socket: Socket, message: string) {
const user = this.getUser(socket);
if (!user.room) {
throw new Error("User has no room");
}
user.room.submitTickerMessage(user, message);
}
private getUser(socket: Socket): User {
const user = this.socketsToUsers.get(socket.id);
if (!user) {
throw new Error("User not found");
}
return user;
}
private deleteEmptyRooms() {
for (const room of this.roomIdToRooms.values()) {
if (room.users.length == 0) {
this.deleteRoom(room);
}
}
}
private createRandomRoom(): Room | null {
let tries = 0;
let i = 1;
while (tries++ < 1000) {
if (this.roomIdToRooms.has(i)) {
i++;
} else {
return this.createRoomWithId(i);
}
}
return null;
}
private createRoomWithId(roomId: number): Room {
if (this.roomIdToRooms.has(roomId)) {
throw new Error("A room with the given id already exists");
}
const room = new Room(roomId);
this.roomIdToRooms.set(roomId, room);
return room;
}
private deleteRoom(room: Room) {
this.roomIdToRooms.delete(room.id);
}
}