import { ObjectId } from "mongodb"; import { getAllFleet } from "../../db/fleet"; import { getAllGalaxies } from "../../db/galaxies"; import { getSectorById } from "../../db/sectors"; import { getSystemById } from "../../db/systems"; import { getAllUsers } from "../../db/users"; import User from "../User"; import FleetManager from "./FleetManager"; import { Planet } from "./PlanetManager"; import SystemManager, { System } from "./SystemManager"; export type Galaxy = { _id: ObjectId, name: string, sectors: Array coords: { x: number, y: number } } export type Sector = { _id: ObjectId, galaxy: Galaxy, name: string, expedition: null, systems: Array } class LocationManager { private static instance: LocationManager; private constructor() {} public static getInstance(): LocationManager { if (!LocationManager.instance) { LocationManager.instance = new LocationManager(); } return LocationManager.instance; } galaxies: Galaxy[] = []; users: User[] = []; fleet: FleetManager[] = []; async init() { const currentTime = new Date(); this.galaxies = []; this.users = []; this.fleet = []; const users = await getAllUsers(); users.forEach(async user => { this.users.push(new User(user._id, user.username, user.email, user.createdAt, user.updatedAt, user.lastLogin)); }); console.log(`Loaded ${users.length} users from database`); const galaxies = await getAllGalaxies(); for(const galaxy of galaxies) { const galaxyObject: Galaxy = { _id: galaxy._id, name: galaxy.name, sectors: [], coords: galaxy.coords }; for(const sectorId of galaxy.sectors) { const sectorData = await getSectorById(sectorId); const sectorObject: Sector = { _id: sectorData._id, galaxy: galaxyObject, name: sectorData.name, expedition: null, systems: [] }; for(const systemId of sectorData.systems) { const systemData = await getSystemById(systemId); const user = this.users.find(user => user.id.equals(systemData.ownedBy)); if(!user) throw new Error("User not found"); const systemObject: System = { _id: systemData._id, sector: sectorObject, name: systemData.name, ownedBy: user, //@ts-ignore structures: null, //@ts-ignore resources: null, //@ts-ignore ships: null, planets: [], asteroids: [], }; const s = await new SystemManager(systemObject).fillData(systemData); sectorObject.systems.push(s); }; console.log(`Loaded ${sectorObject.systems.length} systems from sector ${sectorObject.name}`); galaxyObject.sectors.push(sectorObject); }; console.log(`Loaded ${galaxyObject.sectors.length} sectors from galaxy ${galaxyObject.name}`); this.galaxies.push(galaxyObject); }; console.log(`Loaded ${this.galaxies.length} galaxies from database`); for(const user of this.users) { await user.init(); const userDB = users.find(u => u._id.equals(user.id)); const mainPlanet = this.getPlanet(userDB?.mainPlanet as ObjectId); if(!mainPlanet) throw new Error(`Main planet not found for user ${user.username} (${user.id})`); user.mainPlanet = mainPlanet; }; const fleets = await getAllFleet(); for(const fleet of fleets) { if(fleet.arrivalTime > currentTime) { const source = this.getPlanet(fleet.source) || this.getSystem(fleet.source); const destination = this.getPlanet(fleet.destination) || this.getSystem(fleet.destination); if(source && destination) this.fleet.push(new FleetManager( fleet._id, source, destination, fleet.departureTime, fleet.arrivalTime, fleet.returning, fleet.mission, fleet.ships, fleet.cargo, fleet.additionalData )); } } console.log(`Loaded ${this.fleet.length} active fleet from database`); return this; } findId(id: ObjectId) { let found: SystemManager | Planet | null = null; for(const galaxy of this.galaxies) { for(const sector of galaxy.sectors) { for(const system of sector.systems) { if(system.data._id.equals(id)) { found = system; break; } for(const planet of system.planets) { if(planet._id.equals(id)) { found = planet; break; } } } } } return found; } getGalaxy(_id: ObjectId) { return this.galaxies.find(galaxy => galaxy._id.equals(_id)); } getSector(_id: ObjectId) { let foundSector: Sector | undefined; this.galaxies.find(galaxy => galaxy.sectors.find(sector => { if(sector._id.equals(_id)) foundSector = sector; })); return foundSector; } getSystem(_id: ObjectId) { let foundSystem: SystemManager | undefined; this.galaxies.find(galaxy => galaxy.sectors.find(sector => sector.systems.find(system => { if(system.data._id.equals(_id)) foundSystem = system }))); return foundSystem } getSystemsOwnedBy(id: ObjectId) { const systems: SystemManager[] = []; for(const galaxy of this.galaxies) { for(const sector of galaxy.sectors) { for(const system of sector.systems) { if(system.data.ownedBy.id.equals(id)) systems.push(system); } } } return systems; } getPlanet(_id: ObjectId) { let foundPlanet: Planet | undefined; for(const galaxy of this.galaxies) { for(const sector of galaxy.sectors) { for(const system of sector.systems) { foundPlanet = system.planets.find(planet => planet._id.equals(_id)); if(foundPlanet) break; } if(foundPlanet) break; } if(foundPlanet) break; } return foundPlanet; } getUser(_id: ObjectId) { return this.users.find(user => user.id.equals(_id)); } async updateFleet() { for(const fleet of this.fleet) { const { finished } = await fleet.checkStatus(); if(finished) { this.fleet = this.fleet.filter(f => !f.data.id.equals(fleet.data.id)); } } } async getAllFleetByUserId(userId: string) { await this.updateFleet(); return userId === '' ? [] : this.fleet.filter(fleet => { let found = false; if(fleet.data.source instanceof SystemManager) found = fleet.data.source.data.ownedBy.id.equals(userId); else found = fleet.data.source.system.data.ownedBy.id.equals(userId); if(fleet.data.destination instanceof SystemManager) found = fleet.data.destination.data.ownedBy.id.equals(userId); else if(!("expedition" in fleet.data.destination)) found = fleet.data.destination.system.data.ownedBy.id.equals(userId); return found; }); } addFleet(fleet: FleetManager) { this.fleet.push(fleet); } } const locationManager = LocationManager.getInstance(); (async () => { await locationManager.init(); })(); export default locationManager;