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.
167 lines
3.3 KiB
167 lines
3.3 KiB
import User from "./User";
|
|
import { getTimeline, getTimelineNames } from "./timeline";
|
|
import { getCurrentTime } from "./util";
|
|
|
|
export interface RoomOptions {
|
|
seekTime: number;
|
|
timelineName: string;
|
|
}
|
|
|
|
export interface TickerMessage {
|
|
user: User;
|
|
message: string;
|
|
}
|
|
|
|
// FIXME: dedupe with frontend
|
|
export interface SerializedRoom {
|
|
id: number;
|
|
userCount: number;
|
|
isLeader: boolean;
|
|
running: boolean;
|
|
startTime?: number;
|
|
seekTime: number;
|
|
timelineName: string;
|
|
readyToParticipate: boolean;
|
|
speedFactor: number;
|
|
ticker: string[];
|
|
users?: { id: string; readyToParticipate: boolean }[];
|
|
}
|
|
|
|
export default class Room {
|
|
id = 0;
|
|
users: User[] = [];
|
|
leader: User | null = null;
|
|
|
|
ticker: TickerMessage[] = [];
|
|
|
|
running = false;
|
|
startTime: number | undefined = undefined;
|
|
|
|
seekTime = 0;
|
|
timelineName = "Centurion";
|
|
|
|
// For debugging purposes
|
|
speedFactor = 1;
|
|
|
|
constructor(name: number) {
|
|
this.id = name;
|
|
}
|
|
|
|
serialize(user?: User) {
|
|
const obj: SerializedRoom = {
|
|
id: this.id,
|
|
userCount: this.users.length,
|
|
isLeader: this.leader === user,
|
|
running: this.running,
|
|
startTime: this.startTime,
|
|
timelineName: this.timelineName,
|
|
seekTime: this.seekTime,
|
|
readyToParticipate: this.getLeader()?.readyToParticipate || false,
|
|
speedFactor: this.speedFactor,
|
|
ticker: this.ticker.map((i) => i.message),
|
|
};
|
|
|
|
if (typeof user === "undefined" || this.leader === user) {
|
|
obj["users"] = this.users.map((u) => u.serialize());
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
|
|
serializeTimeline() {
|
|
return getTimeline(this.timelineName);
|
|
}
|
|
|
|
sync() {
|
|
this.users.forEach((u) => u.sync());
|
|
}
|
|
|
|
async join(user: User) {
|
|
this.users.push(user);
|
|
await user.setRoom(this);
|
|
|
|
if (!this.hasLeader()) {
|
|
this.setLeader(user);
|
|
}
|
|
|
|
this.sync();
|
|
}
|
|
|
|
async leave(user: User) {
|
|
this.removeTickerMessageForUser(user);
|
|
this.users.splice(this.users.indexOf(user), 1);
|
|
await user.setRoom(null);
|
|
|
|
if (this.leader == user) {
|
|
this.setRandomLeader();
|
|
}
|
|
|
|
this.sync();
|
|
}
|
|
|
|
setOptions(options: { seekTime: number; timelineName: string }) {
|
|
this.seekTime = Math.max(0, Math.min(options.seekTime, 250 * 60 * 1000));
|
|
if (getTimelineNames().indexOf(options.timelineName) >= 0) {
|
|
this.timelineName = options.timelineName;
|
|
}
|
|
this.sync();
|
|
}
|
|
|
|
start() {
|
|
this.running = true;
|
|
this.startTime = getCurrentTime() - this.seekTime;
|
|
this.sync();
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @returns {boolean}
|
|
*/
|
|
hasUsers() {
|
|
return this.users.length !== 0;
|
|
}
|
|
|
|
setRandomLeader() {
|
|
if (this.hasUsers()) {
|
|
this.leader = this.users[0];
|
|
}
|
|
}
|
|
|
|
hasLeader(): boolean {
|
|
return this.leader != null;
|
|
}
|
|
|
|
setLeader(user: User) {
|
|
this.leader = user;
|
|
}
|
|
|
|
getLeader(): User | null {
|
|
return this.leader;
|
|
}
|
|
|
|
submitTickerMessage(user: User, message: string) {
|
|
message = message.replace("\n", "");
|
|
|
|
this.removeTickerMessageForUser(user);
|
|
|
|
this.ticker.push({
|
|
user: user,
|
|
message: message,
|
|
});
|
|
|
|
this.sync();
|
|
}
|
|
|
|
removeTickerMessageForUser(user: User) {
|
|
let existing = -1;
|
|
for (let i = 0; i < this.ticker.length; i++) {
|
|
if (this.ticker[i].user === user) {
|
|
existing = i;
|
|
break;
|
|
}
|
|
}
|
|
if (existing >= 0) {
|
|
this.ticker.splice(existing, 1);
|
|
}
|
|
}
|
|
}
|
|
|