From 9ef6efa3e0e3444ab70d2245ee0256feb4c4dc65 Mon Sep 17 00:00:00 2001 From: PeekabooSteam Date: Sun, 12 Nov 2023 16:18:31 +0000 Subject: [PATCH] Mid-way commit --- client/src/interfaces.ts | 1 + client/src/mission/missionmanager.ts | 45 +++++++++++++++ client/src/unit/unit.ts | 11 +++- client/src/unit/unitdatafile.ts | 2 +- client/src/unit/unitdatafileexport.ts | 20 +++---- client/src/unit/unitdatafileimport.ts | 62 +++++++++++++++++++++ client/src/unit/unitsmanager.ts | 36 +++--------- client/views/other/dialogs/importexport.ejs | 7 ++- 8 files changed, 142 insertions(+), 42 deletions(-) create mode 100644 client/src/unit/unitdatafileimport.ts diff --git a/client/src/interfaces.ts b/client/src/interfaces.ts index c13419f5..a165176f 100644 --- a/client/src/interfaces.ts +++ b/client/src/interfaces.ts @@ -138,6 +138,7 @@ export interface Offset { export interface UnitData { category: string, + categoryDisplayName: string, ID: number; alive: boolean; human: boolean; diff --git a/client/src/mission/missionmanager.ts b/client/src/mission/missionmanager.ts index 599ca900..2ff2d713 100644 --- a/client/src/mission/missionmanager.ts +++ b/client/src/mission/missionmanager.ts @@ -35,6 +35,10 @@ export class MissionManager { this.#commandModeErasDropdown = new Dropdown("command-mode-era-options", () => {}); } + /** Update location of bullseyes + * + * @param object + */ updateBullseyes(data: BullseyesData) { const commandMode = getApp().getMissionManager().getCommandModeOptions().commandMode; for (let idx in data.bullseyes) { @@ -56,6 +60,10 @@ export class MissionManager { } } + /** Update airbase information + * + * @param object + */ updateAirbases(data: AirbasesData) { for (let idx in data.airbases) { var airbase = data.airbases[idx] @@ -75,6 +83,10 @@ export class MissionManager { } } + /** Update mission information + * + * @param object + */ updateMission(data: MissionData) { if (data.mission) { @@ -109,30 +121,63 @@ export class MissionManager { } } + /** Get the bullseyes set in this theatre + * + * @returns object + */ getBullseyes() { return this.#bullseyes; } + /** Get the airbases in this theatre + * + * @returns object + */ getAirbases() { return this.#airbases; } + /** Get the options/settings as set in the command mode + * + * @returns object + */ getCommandModeOptions() { return this.#commandModeOptions; } + /** Get the current date and time of the mission (based on local time) + * + * @returns object + */ getDateAndTime() { return this.#dateAndTime; } + /** + * Get the number of seconds left of setup time + * @returns number + */ getRemainingSetupTime() { return this.#remainingSetupTime; } + /** Get an object with the coalitions in it + * + * @returns object + */ getCoalitions() { return this.#coalitions; } + /** Get the current theatre (map) name + * + * @returns string + */ + getTheatre() { + return this.#theatre; + } + + getAvailableSpawnPoints() { if (this.getCommandModeOptions().commandMode === GAME_MASTER) return Infinity; diff --git a/client/src/unit/unit.ts b/client/src/unit/unit.ts index a8a13198..19f66abd 100644 --- a/client/src/unit/unit.ts +++ b/client/src/unit/unit.ts @@ -5,7 +5,7 @@ import { CustomMarker } from '../map/markers/custommarker'; import { SVGInjector } from '@tanem/svg-injector'; import { UnitDatabase } from './databases/unitdatabase'; import { TargetMarker } from '../map/markers/targetmarker'; -import { DLINK, DataIndexes, GAME_MASTER, HIDE_GROUP_MEMBERS, IDLE, IRST, MOVE_UNIT, OPTIC, RADAR, ROEs, RWR, SHOW_UNIT_CONTACTS, SHOW_UNITS_ENGAGEMENT_RINGS, SHOW_UNIT_PATHS, SHOW_UNIT_TARGETS, VISUAL, emissionsCountermeasures, reactionsToThreat, states, SHOW_UNITS_ACQUISITION_RINGS, HIDE_UNITS_SHORT_RANGE_RINGS, FILL_SELECTED_RING } from '../constants/constants'; +import { DLINK, DataIndexes, GAME_MASTER, HIDE_GROUP_MEMBERS, IDLE, IRST, MOVE_UNIT, OPTIC, RADAR, ROEs, RWR, SHOW_UNIT_CONTACTS, SHOW_UNITS_ENGAGEMENT_RINGS, SHOW_UNIT_PATHS, SHOW_UNIT_TARGETS, VISUAL, emissionsCountermeasures, reactionsToThreat, states, SHOW_UNITS_ACQUISITION_RINGS, HIDE_UNITS_SHORT_RANGE_RINGS, FILL_SELECTED_RING, GROUND_UNIT_AIR_DEFENCE_REGEX } from '../constants/constants'; import { DataExtractor } from '../server/dataextractor'; import { groundUnitDatabase } from './databases/groundunitdatabase'; import { navyUnitDatabase } from './databases/navyunitdatabase'; @@ -211,6 +211,14 @@ export class Unit extends CustomMarker { return ""; } + /** Get the category but for display use - for the user. (i.e. has spaces in it) + * + * @returns string + */ + getCategoryLabel() { + return ((GROUND_UNIT_AIR_DEFENCE_REGEX.test(this.getType())) ? "Air Defence" : this.getCategory()).replace(/([a-z])([A-Z])/g, "$1 $2"); + } + /********************** Unit data *************************/ setData(dataExtractor: DataExtractor) { var updateMarker = !getApp().getMap().hasLayer(this); @@ -291,6 +299,7 @@ export class Unit extends CustomMarker { getData(): UnitData { return { category: this.getCategory(), + categoryDisplayName: this.getCategoryLabel(), ID: this.ID, alive: this.#alive, human: this.#human, diff --git a/client/src/unit/unitdatafile.ts b/client/src/unit/unitdatafile.ts index b471ce40..91baddd1 100644 --- a/client/src/unit/unitdatafile.ts +++ b/client/src/unit/unitdatafile.ts @@ -1,3 +1,3 @@ -export abstract class unitDataFile { +export abstract class UnitDataFile { constructor() {} } \ No newline at end of file diff --git a/client/src/unit/unitdatafileexport.ts b/client/src/unit/unitdatafileexport.ts index 6f88ddda..35986d45 100644 --- a/client/src/unit/unitdatafileexport.ts +++ b/client/src/unit/unitdatafileexport.ts @@ -1,10 +1,11 @@ +import { getApp } from ".."; import { GROUND_UNIT_AIR_DEFENCE_REGEX } from "../constants/constants"; import { Dialog } from "../dialog/dialog"; import { zeroAppend } from "../other/utils"; import { Unit } from "./unit"; -import { unitDataFile } from "./unitdatafile"; +import { UnitDataFile } from "./unitdatafile"; -export class UnitDataFileExport extends unitDataFile { +export class UnitDataFileExport extends UnitDataFile { #data!:any; #dialog:Dialog; @@ -19,7 +20,7 @@ export class UnitDataFileExport extends unitDataFile { this.#categoryCoalitionMatrix = this.#element.querySelector("tbody"); this.#categoryCoalitionHeaders = this.#element.querySelector("thead"); - this.#element.querySelector(".start-transfer")?.addEventListener("click", (ev:MouseEventInit) => { + this.#element.querySelector(".start-transfer.export")?.addEventListener("click", (ev:MouseEventInit) => { this.#doExport(); }); } @@ -30,13 +31,13 @@ export class UnitDataFileExport extends unitDataFile { showForm(units:Unit[]) { this.#element.setAttribute( "data-mode", "export" ); - const data:any = {}; - + const data:any = {}; const categories:string[] = []; const coalitions:string[] = []; + const unitCanBeExported = (unit:Unit) => ["GroundUnit", "NavyUnit"].includes(unit.getCategory()); - units.filter((unit:Unit) => unit.getAlive()).forEach((unit:Unit) => { - const category = ((GROUND_UNIT_AIR_DEFENCE_REGEX.test(unit.getType())) ? "Air Defence" : unit.getCategory()).replace( /(\w)([A-Z])/g, "$1 $2"); + units.filter((unit:Unit) => unit.getAlive() && unitCanBeExported(unit)).forEach((unit:Unit) => { + const category = unit.getCategoryLabel(); const coalition = unit.getCoalition(); if (!coalitions.includes(coalition)) @@ -68,7 +69,7 @@ export class UnitDataFileExport extends unitDataFile { coalitions.forEach((coalition:string) => { if (index === 0) headersHTML += `${coalition}`; - matrixHTML += `${(data[category].hasOwnProperty(coalition)) ? ``: "-"}`; + matrixHTML += ``; }); matrixHTML += ""; @@ -78,7 +79,6 @@ export class UnitDataFileExport extends unitDataFile { this.#categoryCoalitionMatrix.innerHTML = matrixHTML; this.#dialog.show(); } - #doExport() { @@ -109,7 +109,7 @@ export class UnitDataFileExport extends unitDataFile { const a = document.createElement("a"); const file = new Blob([JSON.stringify(unitsToExport)], { type: 'text/plain' }); a.href = URL.createObjectURL(file); - a.download = `olympus_export_${date.getFullYear()}-${zeroAppend(date.getMonth()+1, 2)}-${zeroAppend(date.getDate(), 2)}_${zeroAppend(date.getHours(), 2)}${zeroAppend(date.getMinutes(), 2)}${zeroAppend(date.getSeconds(), 2)}.json`; + a.download = `olympus_${getApp().getMissionManager().getTheatre().replace( /[^\w]/gi, "" ).toLowerCase()}_${date.getFullYear()}${zeroAppend(date.getMonth()+1, 2)}${zeroAppend(date.getDate(), 2)}_${zeroAppend(date.getHours(), 2)}${zeroAppend(date.getMinutes(), 2)}${zeroAppend(date.getSeconds(), 2)}.json`; a.click(); this.#dialog.hide(); } diff --git a/client/src/unit/unitdatafileimport.ts b/client/src/unit/unitdatafileimport.ts new file mode 100644 index 00000000..e91af4d0 --- /dev/null +++ b/client/src/unit/unitdatafileimport.ts @@ -0,0 +1,62 @@ +import { getApp } from ".."; +import { GROUND_UNIT_AIR_DEFENCE_REGEX } from "../constants/constants"; +import { Dialog } from "../dialog/dialog"; +import { zeroAppend } from "../other/utils"; +import { Unit } from "./unit"; +import { UnitDataFile } from "./unitdatafile"; + +export class UnitDataFileImport extends UnitDataFile { + + #data!:any; + #dialog:Dialog; + #element!:HTMLElement; + #categoryCoalitionHeaders!: HTMLElement; + #categoryCoalitionMatrix!: HTMLElement; + + constructor( elementId:string ) { + super(); + this.#dialog = new Dialog(elementId); + this.#element = this.#dialog.getElement(); + this.#categoryCoalitionMatrix = this.#element.querySelector("tbody"); + this.#categoryCoalitionHeaders = this.#element.querySelector("thead"); + + // this.#element.querySelector(".start-transfer.import")?.addEventListener("click", (ev:MouseEventInit) => { + // this.#doImport(); + // }); + } + + #doImport() { + + /* + for (let groupName in groups) { + if (groupName !== "" && groups[groupName].length > 0 && (groups[groupName].every((unit: UnitData) => { return unit.category == "GroundUnit"; }) || groups[groupName].every((unit: any) => { return unit.category == "NavyUnit"; }))) { + var aliveUnits = groups[groupName].filter((unit: UnitData) => { return unit.alive }); + var units = aliveUnits.map((unit: UnitData) => { + return { unitType: unit.name, location: unit.position, liveryID: "" } + }); + getApp().getUnitsManager().spawnUnits(groups[groupName][0].category, units, groups[groupName][0].coalition, true); + } + } + //*/ + } + + selectFile() { + var input = document.createElement("input"); + input.type = "file"; + input.addEventListener("change", (e: any) => { + var file = e.target.files[0]; + if (!file) { + return; + } + var reader = new FileReader(); + reader.onload = function (e: any) { + var contents = e.target.result; + var groups = JSON.parse(contents); + console.log(groups); + }; + reader.readAsText(file); + }) + input.click(); + } + +} \ No newline at end of file diff --git a/client/src/unit/unitsmanager.ts b/client/src/unit/unitsmanager.ts index f39e4542..971a70c1 100644 --- a/client/src/unit/unitsmanager.ts +++ b/client/src/unit/unitsmanager.ts @@ -16,6 +16,7 @@ import { HotgroupPanel } from "../panels/hotgrouppanel"; import { Contact, UnitData, UnitSpawnTable } from "../interfaces"; import { Dialog } from "../dialog/dialog"; import { UnitDataFileExport } from "./unitdatafileexport"; +import { UnitDataFileImport } from "./unitdatafileimport"; /** The UnitsManager handles the creation, update, and control of units. Data is strictly updated by the server ONLY. This means that any interaction from the user will always and only * result in a command to the server, executed by means of a REST PUT request. Any subsequent change in data will be reflected only when the new data is sent back by the server. This strategy allows @@ -28,7 +29,8 @@ export class UnitsManager { #selectionEventDisabled: boolean = false; #slowDeleteDialog!:Dialog; #units: { [ID: number]: Unit }; - + #unitDataExport!:UnitDataFileExport; + #unitDataImport!:UnitDataFileImport; constructor() { this.#copiedUnits = []; @@ -986,38 +988,18 @@ export class UnitsManager { * TODO: Extend to aircraft and helicopters */ exportToFile() { - const fileExport = new UnitDataFileExport("unit-import-export-dialog"); - fileExport.showForm(Object.values(this.#units)); + if (!this.#unitDataExport) + this.#unitDataExport = new UnitDataFileExport("unit-import-export-dialog"); + this.#unitDataExport.showForm(Object.values(this.#units)); } /** Import ground and navy units from file * TODO: extend to support aircraft and helicopters */ importFromFile() { - var input = document.createElement("input"); - input.type = "file"; - input.addEventListener("change", (e: any) => { - var file = e.target.files[0]; - if (!file) { - return; - } - var reader = new FileReader(); - reader.onload = function (e: any) { - var contents = e.target.result; - var groups = JSON.parse(contents); - for (let groupName in groups) { - if (groupName !== "" && groups[groupName].length > 0 && (groups[groupName].every((unit: UnitData) => { return unit.category == "GroundUnit"; }) || groups[groupName].every((unit: any) => { return unit.category == "NavyUnit"; }))) { - var aliveUnits = groups[groupName].filter((unit: UnitData) => { return unit.alive }); - var units = aliveUnits.map((unit: UnitData) => { - return { unitType: unit.name, location: unit.position, liveryID: "" } - }); - getApp().getUnitsManager().spawnUnits(groups[groupName][0].category, units, groups[groupName][0].coalition, true); - } - } - }; - reader.readAsText(file); - }) - input.click(); + if (!this.#unitDataImport) + this.#unitDataImport = new UnitDataFileImport("unit-import-export-dialog"); + this.#unitDataImport.selectFile(); } /** Spawn a new group of units diff --git a/client/views/other/dialogs/importexport.ejs b/client/views/other/dialogs/importexport.ejs index ff6e8ffe..b33a73a3 100644 --- a/client/views/other/dialogs/importexport.ejs +++ b/client/views/other/dialogs/importexport.ejs @@ -1,10 +1,10 @@
-

Export unit data to file

+

Export unit data to file

-

This data will include DCS and Olympus-controlled units.

+

Note: only ground and naval units can be exported at this time. (Air units will be possible soon.)

@@ -14,7 +14,8 @@ \ No newline at end of file