import { ObjectId } from "mongodb"; import MissionType from "../../../types/MissionType"; import DBFleet from "../../../types/db/DBFleet"; import { updateFleet } from "../../db/fleet"; import { Planet } from "./PlanetManager"; import SystemManager, { System } from "./SystemManager"; import { sendMail } from "../../db/mails"; export type Fleet = { id: ObjectId, source: Planet | SystemManager, destination: Planet | SystemManager, departureTime: Date, arrivalTime: Date, returning: boolean, mission: MissionType, ships: Array<{ id: string, amount: number }>, cargo: Array<{ id: string, amount: number }> } export default class FleetManager { data: Fleet; constructor(id: ObjectId, source: Planet | SystemManager, destination: Planet | SystemManager, departureTime: Date, arrivalTime: Date, returning: boolean, mission: MissionType, ships: Array<{ id: string, amount: number }>, cargo: Array<{ id: string, amount: number }>) { this.data = { id, source, destination, departureTime, arrivalTime, returning, mission, ships, cargo } } isSourcePlanet(): this is { data: { source: Planet } } { return 'resources' in this.data.source; } isSourceSystem(): this is { data: { source: SystemManager } } { return 'structures' in this.data.source; } isDestinationPlanet(): this is { data: { destination: Planet } } { return 'resources' in this.data.destination; } isDestinationSystem(): this is { data: { destination: SystemManager } } { return 'structures' in this.data.destination; } getSourceOwner() { if(this.isSourcePlanet()) return this.data.source.system.data.ownedBy; if(this.isSourceSystem()) return this.data.source.data.ownedBy; } getDestinationOwner() { if(this.isDestinationPlanet()) return this.data.destination.system.data.ownedBy; if(this.isDestinationSystem()) return this.data.destination.data.ownedBy; } async checkStatus(): Promise<{ finished: boolean, fleet: Fleet }> { if(this.data.arrivalTime.getTime() < Date.now()) { const finished = await this.finish(); return { finished, fleet: this.data }; } return { finished: false, fleet: this.data }; } async finish() { if(this.data.returning) { for(const ship of this.data.ships) { this.data.source.ships.addShips(ship.id, ship.amount); } await this.data.source.resources.updateAmount(this.data.cargo); await this.data.source.ships.sync(); await this.data.source.resources.sync(); await sendMail( null, this.data.source instanceof SystemManager ? this.data.source.data.ownedBy.id : this.data.source.system.data.ownedBy.id, this.data.arrivalTime, "Fleet Returned", `Your fleet from ${this.data.destination instanceof SystemManager ? `${this.data.destination.data.name} system` : `planet ${this.data.destination.name}`} has returned.\n Ships: ${this.data.ships.map(ship => `${ship.amount} ${ship.id}`).join(', ')}\n Cargo: ${this.data.cargo.length > 0 ? this.data.cargo.map(cargo => `${cargo.amount} ${cargo.id}`).join(', ') : 'None'}` ); return true; } else { switch(this.data.mission) { case 'ATTACK': return false; case 'TRANSPORT': await this.data.destination.resources.updateAmount(this.data.cargo); await this.data.destination.resources.sync(); const cargo = JSON.parse(JSON.stringify(this.data.cargo)) as Array<{ id: string, amount: number }>; this.data.cargo = []; const arrived = new Date(this.data.arrivalTime); await this.initiateReturn(); await sendMail( null, this.data.source instanceof SystemManager ? this.data.source.data.ownedBy.id : this.data.source.system.data.ownedBy.id, arrived, "Fleet Arrived", `Your fleet has arrived at ${this.data.destination instanceof SystemManager ? `${this.data.destination.data.name} system` : `planet ${this.data.destination.name}`}.\n Ships: ${this.data.ships.map(ship => `${ship.amount} ${ship.id}`).join(', ')}\n Cargo delivered: ${cargo.length > 0 ? cargo.map(cargo => `${cargo.amount} ${cargo.id}`).join(', ') : 'None'}\n Fleet will return at ${this.data.arrivalTime}` ); return false; case 'TRANSFER': await this.data.destination.resources.updateAmount(this.data.cargo); await this.data.destination.resources.sync(); for(const ship of this.data.ships) { this.data.destination.ships.addShips(ship.id, ship.amount); } await this.data.destination.ships.sync(); await sendMail( null, this.data.source instanceof SystemManager ? this.data.source.data.ownedBy.id : this.data.source.system.data.ownedBy.id, this.data.arrivalTime, "Fleet Arrived", `Your fleet has arrived at ${this.data.destination instanceof SystemManager ? `${this.data.destination.data.name} system` : `planet ${this.data.destination.name}`}.\n Ships: ${this.data.ships.map(ship => `${ship.amount} ${ship.id}`).join(', ')}\n Cargo delivered: ${this.data.cargo.length > 0 ? this.data.cargo.map(cargo => `${cargo.amount} ${cargo.id}`).join(', ') : 'None'}\n Ships will stay at the destination.` ); return true; } } } async initiateReturn() { this.data.returning = true; this.data.departureTime = new Date(this.data.arrivalTime); this.data.arrivalTime = new Date(this.data.departureTime.getTime() + 1000 * 30); await this.sync(); } async sync() { const source = this.data.source instanceof SystemManager ? this.data.source.data._id : this.data.source._id; const destination = this.data.destination instanceof SystemManager ? this.data.destination.data._id : this.data.destination._id; const data: DBFleet = { _id: this.data.id, source, destination, departureTime: this.data.departureTime, arrivalTime: this.data.arrivalTime, returning: this.data.returning, mission: this.data.mission, ships: this.data.ships, cargo: this.data.cargo } await updateFleet(data); } }