const User = require("./User.js"); const timeline = require("./timeline.js"); module.exports = class Lobby { /** * @type {User[]} */ users = []; /** * @type {string|undefined} */ leaderId = undefined; running = false; startTime = 0; currentSeconds = 0; timelineIndex = 0; // For debugging purposes speedFactor = 1; constructor(name) { this.name = name; } run(io) { this.running = true; this.startTime = Date.now(); const doTick = () => { if (this.users.length === 0) { // this lobby is over. return; } const timestamp = timeline.getIndex(this.timelineIndex); const nextShot = timeline.getNextShot(this.timelineIndex); if (!timestamp) { // We are done. io.to(this.name + "").emit('tick_event', { current: this.currentSeconds }); console.log("Done"); this.running = false; return; } console.log("ticking", this.currentSeconds); io.to(this.name + "").emit('tick_event', { current: this.currentSeconds, next: timestamp, nextShot: nextShot }); if (this.currentSeconds >= timestamp.timestamp) { this.timelineIndex += 1; } this.currentSeconds += 1; // We spend some time processing, wait a bit less than 1000ms const nextTickTime = this.startTime + (1000 * this.currentSeconds / this.speedFactor); const waitTime = nextTickTime - Date.now(); console.log("waiting", waitTime); setTimeout(doTick, Math.floor(waitTime / this.speedFactor)); }; doTick(); } /** * * @param io * @param {number} time */ seek(io, time) { this.currentSeconds = time; this.startTime = Date.now() - time * 1000; this.timelineIndex = timeline.indexForTime(this.currentSeconds); io.to(this.name + "").emit('seek', time); } /** * * @returns {boolean} */ hasUsers() { return this.users.length !== 0; } setRandomLeader() { if (this.hasUsers()) { this.leaderId = this.users[0].id; } } /** * * @param {User} user */ addUser(user) { this.users.push(user); } /** * * @param id * @returns {User|undefined} */ getUser(id) { return this.users.find(u => u.id === id); } /** * * @param {string} id */ removeUser(id) { this.users = this.users.filter(u => u.id !== id); } /** * * @returns {boolean} */ hasLeader() { return !!this.leaderId; } /** * * @param {string} id * @returns {boolean} */ isLeader(id) { return this.leaderId === id; } /** * * @param {string} id */ setLeader(id) { if (!this.getUser(id)) { throw new Error('user_not_in_lobby'); } this.leaderId = id; } /** * * @returns {User|undefined} */ getLeader() { return this.users.find(u => u.id === this.leaderId) } };