From b43afd4e9c5393246d1df39d3c69f8fd9dd80292 Mon Sep 17 00:00:00 2001 From: PeekabooSteam Date: Wed, 8 Nov 2023 14:09:35 +0000 Subject: [PATCH] Export customisation working - but ugly. --- client/src/constants/constants.ts | 6 +-- client/src/controls/unitspawnmenu.ts | 6 +-- client/src/map/map.ts | 2 +- client/src/olympusapp.ts | 1 + client/src/unit/unitdatafileexport.ts | 52 +++++++++++++++++++-- client/src/unit/unitsmanager.ts | 19 +------- client/views/other/dialogs/importexport.ejs | 6 +-- 7 files changed, 59 insertions(+), 33 deletions(-) diff --git a/client/src/constants/constants.ts b/client/src/constants/constants.ts index 8eb1663f..c529386b 100644 --- a/client/src/constants/constants.ts +++ b/client/src/constants/constants.ts @@ -111,7 +111,7 @@ export const mapBounds = { "Nevada": { bounds: new LatLngBounds([34.4037128, -119.7806729], [39.7372411, -112.1130805]), zoom: 5 }, "PersianGulf": { bounds: new LatLngBounds([21.729393, 47.572675], [33.131584, 64.7313594]), zoom: 5 }, "Caucasus": { bounds: new LatLngBounds([39.6170191, 27.634935], [47.3907982, 49.3101946]), zoom: 4 }, - // TODO "Falklands" + // TODO "Falklands", "Sinai", "Normandy 2" } export const mapLayers = { @@ -157,9 +157,6 @@ export const mapLayers = { export const IDLE = "Idle"; export const MOVE_UNIT = "Move unit"; export const COALITIONAREA_DRAW_POLYGON = "Draw Coalition Area"; -export const visibilityControls: string[] = ["human", "dcs", "aircraft", "helicopter", "groundunit-sam", "groundunit-other", "navyunit", "airbase"]; -export const visibilityControlsTypes: string[][] = [["human"], ["dcs"], ["aircraft"], ["helicopter"], ["groundunit-sam", "groundunit-sam-radar", "groundunit-sam-launcher"], ["groundunit-other", "groundunit-ewr"], ["navyunit"], ["airbase"]]; -export const visibilityControlsTooltips: string[] = ["Toggle human players visibility", "Toggle DCS controlled units visibility", "Toggle aircrafts visibility", "Toggle helicopter visibility", "Toggle SAM units visibility", "Toggle ground units (not SAM) visibility", "Toggle navy units visibility", "Toggle airbases visibility"]; export const MAP_MARKER_CONTROLS:MapMarkerControl[] = [{ "name":"Human", "image": "visibility/human.svg", @@ -206,6 +203,7 @@ export const MAP_MARKER_CONTROLS:MapMarkerControl[] = [{ export const IADSTypes = ["AAA", "MANPADS", "SAM Site", "Radar"]; export const IADSDensities: {[key: string]: number}= {"AAA": 0.8, "MANPADS": 0.3, "SAM Site": 0.1, "Radar": 0.05}; +export const GROUND_UNIT_AIR_DEFENCE_REGEX:RegExp = /(\b(AAA|SAM|MANPADS?|[mM]anpads?)|[sS]tinger\b)/; export const HIDE_GROUP_MEMBERS = "Hide group members when zoomed out"; export const SHOW_UNIT_LABELS = "Show unit labels (L)"; diff --git a/client/src/controls/unitspawnmenu.ts b/client/src/controls/unitspawnmenu.ts index b0ee3fd4..42b7a2ca 100644 --- a/client/src/controls/unitspawnmenu.ts +++ b/client/src/controls/unitspawnmenu.ts @@ -3,7 +3,7 @@ import { Dropdown } from "./dropdown"; import { Slider } from "./slider"; import { UnitDatabase } from "../unit/databases/unitdatabase"; import { getApp } from ".."; -import { GAME_MASTER } from "../constants/constants"; +import { GAME_MASTER, GROUND_UNIT_AIR_DEFENCE_REGEX } from "../constants/constants"; import { Airbase } from "../mission/airbase"; import { ftToM } from "../other/utils"; import { aircraftDatabase } from "../unit/databases/aircraftdatabase"; @@ -586,7 +586,7 @@ export class HelicopterSpawnMenu extends UnitSpawnMenu { export class GroundUnitSpawnMenu extends UnitSpawnMenu { protected showRangeCircles: boolean = true; - protected unitTypeFilter = (unit:any) => {return !(/\bAAA|SAM\b/.test(unit.type) || /\bmanpad|stinger\b/i.test(unit.type))}; + protected unitTypeFilter = (unit:any) => {return !(GROUND_UNIT_AIR_DEFENCE_REGEX.test(unit.type))}; /** * @@ -627,7 +627,7 @@ export class GroundUnitSpawnMenu extends UnitSpawnMenu { export class AirDefenceUnitSpawnMenu extends GroundUnitSpawnMenu { - protected unitTypeFilter = (unit:any) => {return /\bAAA|SAM\b/.test(unit.type) || /\bmanpad|stinger\b/i.test(unit.type)}; + protected unitTypeFilter = (unit:any) => {return GROUND_UNIT_AIR_DEFENCE_REGEX.test(unit.type)}; /** * diff --git a/client/src/map/map.ts b/client/src/map/map.ts index b82feb05..3563b14f 100644 --- a/client/src/map/map.ts +++ b/client/src/map/map.ts @@ -12,7 +12,7 @@ import { DestinationPreviewMarker } from "./markers/destinationpreviewmarker"; import { TemporaryUnitMarker } from "./markers/temporaryunitmarker"; import { ClickableMiniMap } from "./clickableminimap"; import { SVGInjector } from '@tanem/svg-injector' -import { mapLayers, mapBounds, minimapBoundaries, IDLE, COALITIONAREA_DRAW_POLYGON, visibilityControls, visibilityControlsTooltips, MOVE_UNIT, SHOW_UNIT_CONTACTS, HIDE_GROUP_MEMBERS, SHOW_UNIT_PATHS, SHOW_UNIT_TARGETS, visibilityControlsTypes, SHOW_UNIT_LABELS, SHOW_UNITS_ENGAGEMENT_RINGS, SHOW_UNITS_ACQUISITION_RINGS, HIDE_UNITS_SHORT_RANGE_RINGS, FILL_SELECTED_RING, MAP_MARKER_CONTROLS } from "../constants/constants"; +import { mapLayers, mapBounds, minimapBoundaries, IDLE, COALITIONAREA_DRAW_POLYGON, MOVE_UNIT, SHOW_UNIT_CONTACTS, HIDE_GROUP_MEMBERS, SHOW_UNIT_PATHS, SHOW_UNIT_TARGETS, SHOW_UNIT_LABELS, SHOW_UNITS_ENGAGEMENT_RINGS, SHOW_UNITS_ACQUISITION_RINGS, HIDE_UNITS_SHORT_RANGE_RINGS, FILL_SELECTED_RING, MAP_MARKER_CONTROLS } from "../constants/constants"; import { TargetMarker } from "./markers/targetmarker"; import { CoalitionArea } from "./coalitionarea/coalitionarea"; import { CoalitionAreaContextMenu } from "../contextmenus/coalitionareacontextmenu"; diff --git a/client/src/olympusapp.ts b/client/src/olympusapp.ts index 22f2ebf8..e6999bb3 100644 --- a/client/src/olympusapp.ts +++ b/client/src/olympusapp.ts @@ -400,6 +400,7 @@ export class OlympusApp { // TODO: move from here in dedicated class document.addEventListener("closeDialog", (ev: CustomEventInit) => { ev.detail._element.closest(".ol-dialog").classList.add("hide"); + document.getElementById("gray-out")?.classList.toggle("hide", true); }); /* Try and connect with the Olympus REST server */ diff --git a/client/src/unit/unitdatafileexport.ts b/client/src/unit/unitdatafileexport.ts index bef50a07..6f88ddda 100644 --- a/client/src/unit/unitdatafileexport.ts +++ b/client/src/unit/unitdatafileexport.ts @@ -1,9 +1,12 @@ +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 UnitDataFileExport extends unitDataFile { + #data!:any; #dialog:Dialog; #element!:HTMLElement; #categoryCoalitionHeaders!: HTMLElement; @@ -15,6 +18,10 @@ export class UnitDataFileExport extends unitDataFile { this.#element = this.#dialog.getElement(); this.#categoryCoalitionMatrix = this.#element.querySelector("tbody"); this.#categoryCoalitionHeaders = this.#element.querySelector("thead"); + + this.#element.querySelector(".start-transfer")?.addEventListener("click", (ev:MouseEventInit) => { + this.#doExport(); + }); } /** @@ -28,8 +35,8 @@ export class UnitDataFileExport extends unitDataFile { const categories:string[] = []; const coalitions:string[] = []; - units.filter((unit:Unit) => unit.getControlled() && unit.getAlive()).forEach((unit:Unit) => { - const category = 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"); const coalition = unit.getCoalition(); if (!coalitions.includes(coalition)) @@ -47,11 +54,13 @@ export class UnitDataFileExport extends unitDataFile { data[category][coalition].push(unit); }); + this.#data = data; + categories.sort(); coalitions.sort(); let headersHTML:string = ``; - let matrixHTML:string = ``; + let matrixHTML:string = ``; categories.forEach((category:string, index) => { matrixHTML += `${category}`; @@ -59,7 +68,7 @@ export class UnitDataFileExport extends unitDataFile { coalitions.forEach((coalition:string) => { if (index === 0) headersHTML += `${coalition}`; - matrixHTML += `${(data[category].hasOwnProperty(coalition)) ? ``: "-"}`; + matrixHTML += `${(data[category].hasOwnProperty(coalition)) ? ``: "-"}`; }); matrixHTML += ""; @@ -70,4 +79,39 @@ export class UnitDataFileExport extends unitDataFile { this.#dialog.show(); } + + #doExport() { + + let selectedUnits:Unit[] = []; + + this.#element.querySelectorAll(`input[type="checkbox"][name="category-coalition-selection"]:checked`).forEach((checkbox:HTMLInputElement) => { + if (checkbox instanceof HTMLInputElement) { + const [category, coalition] = checkbox.value.split(":"); // e.g. "category:coalition" + selectedUnits = selectedUnits.concat(this.#data[category][coalition]); + } + }); + + if (selectedUnits.length === 0) { + alert("Please select at least one option for export."); + return; + } + + var unitsToExport: { [key: string]: any } = {}; + selectedUnits.forEach((unit:Unit) => { + var data: any = unit.getData(); + if (unit.getGroupName() in unitsToExport) + unitsToExport[unit.getGroupName()].push(data); + else + unitsToExport[unit.getGroupName()] = [data]; + }); + + const date = new Date(); + 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.click(); + this.#dialog.hide(); + } + } \ No newline at end of file diff --git a/client/src/unit/unitsmanager.ts b/client/src/unit/unitsmanager.ts index 80f5b5da..f39e4542 100644 --- a/client/src/unit/unitsmanager.ts +++ b/client/src/unit/unitsmanager.ts @@ -988,25 +988,8 @@ export class UnitsManager { exportToFile() { const fileExport = new UnitDataFileExport("unit-import-export-dialog"); fileExport.showForm(Object.values(this.#units)); - return; - var unitsToExport: { [key: string]: any } = {}; - for (let ID in this.#units) { - var unit = this.#units[ID]; - if (!["Aircraft", "Helicopter"].includes(unit.getCategory())) { - var data: any = unit.getData(); - if (unit.getGroupName() in unitsToExport) - unitsToExport[unit.getGroupName()].push(data); - else - unitsToExport[unit.getGroupName()] = [data]; - } - } - var a = document.createElement("a"); - var file = new Blob([JSON.stringify(unitsToExport)], { type: 'text/plain' }); - a.href = URL.createObjectURL(file); - a.download = 'export.json'; - a.click(); } - + /** Import ground and navy units from file * TODO: extend to support aircraft and helicopters */ diff --git a/client/views/other/dialogs/importexport.ejs b/client/views/other/dialogs/importexport.ejs index e5e626c2..ff6e8ffe 100644 --- a/client/views/other/dialogs/importexport.ejs +++ b/client/views/other/dialogs/importexport.ejs @@ -4,7 +4,7 @@
-

This data will only include Olympus-controlled units.

+

This data will include DCS and Olympus-controlled units.

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