Mid-way commit

This commit is contained in:
PeekabooSteam 2023-11-12 16:18:31 +00:00
parent b43afd4e9c
commit 9ef6efa3e0
8 changed files with 142 additions and 42 deletions

View File

@ -138,6 +138,7 @@ export interface Offset {
export interface UnitData {
category: string,
categoryDisplayName: string,
ID: number;
alive: boolean;
human: boolean;

View File

@ -35,6 +35,10 @@ export class MissionManager {
this.#commandModeErasDropdown = new Dropdown("command-mode-era-options", () => {});
}
/** Update location of bullseyes
*
* @param object <BulleyesData>
*/
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 <AirbasesData>
*/
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 <MissionData>
*/
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;

View File

@ -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,

View File

@ -1,3 +1,3 @@
export abstract class unitDataFile {
export abstract class UnitDataFile {
constructor() {}
}

View File

@ -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 = <HTMLElement>this.#element.querySelector("tbody");
this.#categoryCoalitionHeaders = <HTMLElement>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 += `<th data-coalition="${coalition}">${coalition}</th>`;
matrixHTML += `<td data-coalition="${coalition}">${(data[category].hasOwnProperty(coalition)) ? `<input type="checkbox" name="category-coalition-selection" value="${category}:${coalition}" checked />`: "-"}</td>`;
matrixHTML += `<td data-coalition="${coalition}"><input type="checkbox" name="category-coalition-selection" value="${category}:${coalition}" ${(data[category].hasOwnProperty(coalition)) ? "checked": "disabled readonly"} /></td>`;
});
matrixHTML += "</tr>";
@ -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();
}

View File

@ -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 = <HTMLElement>this.#element.querySelector("tbody");
this.#categoryCoalitionHeaders = <HTMLElement>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();
}
}

View File

@ -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

View File

@ -1,10 +1,10 @@
<div id="unit-import-export-dialog" class="ol-panel ol-dialog hide" oncontextmenu="return false;">
<div class="ol-dialog-header">
<h3>Export unit data to file</h3>
<h3 class="export">Export unit data to file</h3>
</div>
<div class="ol-dialog-content">
<p>This data will include DCS and Olympus-controlled units.</p>
<p>Note: only ground and naval units can be exported at this time. (Air units will be possible <em>soon</em>.)</p>
<table>
<thead>
</thead>
@ -14,7 +14,8 @@
</div>
<div class="ol-dialog-footer ol-group">
<button class="start-transfer">Export units to file</button>
<button class="start-transfer import">Import units into mission</button>
<button class="start-transfer export">Export units to file</button>
<button data-on-click="closeDialog">Cancel</button>
</div>
</div>