Common unit functions moved to unit class

This commit is contained in:
Pax1601
2023-06-06 12:50:18 +02:00
parent dca3438db0
commit 1d20a3b017
19 changed files with 274 additions and 197 deletions

View File

@@ -1,5 +1,6 @@
import { getUnitsManager } from "../.."; import { getUnitsManager } from "../..";
import { Dropdown } from "../../controls/dropdown"; import { Dropdown } from "../../controls/dropdown";
import { mToFt, msToKnots } from "../../other/utils";
import { ATC } from "../atc"; import { ATC } from "../atc";
import { ATCBoard } from "../atcboard"; import { ATCBoard } from "../atcboard";
@@ -139,7 +140,7 @@ export class ATCBoardTower extends ATCBoard {
assignedAltitude.value = flight.assignedAltitude; assignedAltitude.value = flight.assignedAltitude;
} }
flightData.altitude = Math.floor( flightData.altitude / 0.3048 ); flightData.altitude = Math.floor( mToFt(flightData.altitude) );
strip.element.querySelectorAll( `[data-point="altitude"]` ).forEach( el => { strip.element.querySelectorAll( `[data-point="altitude"]` ).forEach( el => {
if ( el instanceof HTMLElement ) { if ( el instanceof HTMLElement ) {
@@ -163,7 +164,7 @@ export class ATCBoardTower extends ATCBoard {
assignedSpeed.value = flight.assignedSpeed; assignedSpeed.value = flight.assignedSpeed;
} }
flightData.speed = Math.floor( flightData.speed * 1.94384 ); flightData.speed = Math.floor( msToKnots(flightData.speed) );
strip.element.querySelectorAll( `[data-point="speed"]` ).forEach( el => { strip.element.querySelectorAll( `[data-point="speed"]` ).forEach( el => {
if ( el instanceof HTMLElement ) { if ( el instanceof HTMLElement ) {

View File

@@ -7,6 +7,7 @@ import { ContextMenu } from "./contextmenu";
import { Dropdown } from "./dropdown"; import { Dropdown } from "./dropdown";
import { Switch } from "./switch"; import { Switch } from "./switch";
import { Slider } from "./slider"; import { Slider } from "./slider";
import { ftToM } from "../other/utils";
export interface SpawnOptions { export interface SpawnOptions {
role: string; role: string;
@@ -26,7 +27,7 @@ export class MapContextMenu extends ContextMenu {
#aircrafSpawnAltitudeSlider: Slider; #aircrafSpawnAltitudeSlider: Slider;
#groundUnitRoleDropdown: Dropdown; #groundUnitRoleDropdown: Dropdown;
#groundUnitTypeDropdown: Dropdown; #groundUnitTypeDropdown: Dropdown;
#spawnOptions: SpawnOptions = { role: "", type: "", latlng: new LatLng(0, 0), loadout: null, coalition: "blue", airbaseName: null, altitude: 20000 * 0.3048 }; #spawnOptions: SpawnOptions = { role: "", type: "", latlng: new LatLng(0, 0), loadout: null, coalition: "blue", airbaseName: null, altitude: ftToM(20000) };
constructor(id: string) { constructor(id: string) {
super(id); super(id);
@@ -37,7 +38,7 @@ export class MapContextMenu extends ContextMenu {
this.#aircraftRoleDropdown = new Dropdown("aircraft-role-options", (role: string) => this.#setAircraftRole(role)); this.#aircraftRoleDropdown = new Dropdown("aircraft-role-options", (role: string) => this.#setAircraftRole(role));
this.#aircraftTypeDropdown = new Dropdown("aircraft-type-options", (type: string) => this.#setAircraftType(type)); this.#aircraftTypeDropdown = new Dropdown("aircraft-type-options", (type: string) => this.#setAircraftType(type));
this.#aircraftLoadoutDropdown = new Dropdown("loadout-options", (loadout: string) => this.#setAircraftLoadout(loadout)); this.#aircraftLoadoutDropdown = new Dropdown("loadout-options", (loadout: string) => this.#setAircraftLoadout(loadout));
this.#aircrafSpawnAltitudeSlider = new Slider("aircraft-spawn-altitude-slider", 0, 50000, "ft", (value: number) => {this.#spawnOptions.altitude = value * 0.3048;}); this.#aircrafSpawnAltitudeSlider = new Slider("aircraft-spawn-altitude-slider", 0, 50000, "ft", (value: number) => {this.#spawnOptions.altitude = ftToM(value);});
this.#groundUnitRoleDropdown = new Dropdown("ground-unit-role-options", (role: string) => this.#setGroundUnitRole(role)); this.#groundUnitRoleDropdown = new Dropdown("ground-unit-role-options", (role: string) => this.#setGroundUnitRole(role));
this.#groundUnitTypeDropdown = new Dropdown("ground-unit-type-options", (type: string) => this.#setGroundUnitType(type)); this.#groundUnitTypeDropdown = new Dropdown("ground-unit-type-options", (type: string) => this.#setGroundUnitType(type));

View File

@@ -1,4 +1,4 @@
import { deg2rad } from "../other/utils"; import { deg2rad, ftToM } from "../other/utils";
import { ContextMenu } from "./contextmenu"; import { ContextMenu } from "./contextmenu";
export class UnitContextMenu extends ContextMenu { export class UnitContextMenu extends ContextMenu {
@@ -19,8 +19,8 @@ export class UnitContextMenu extends ContextMenu {
} }
var angleDeg = 360 - (clock - 1) * 45; var angleDeg = 360 - (clock - 1) * 45;
var angleRad = deg2rad(angleDeg); var angleRad = deg2rad(angleDeg);
var distance = parseInt((<HTMLInputElement>dialog.querySelector(`#distance`)?.querySelector("input")).value) * 0.3048; var distance = ftToM(parseInt((<HTMLInputElement>dialog.querySelector(`#distance`)?.querySelector("input")).value));
var upDown = parseInt((<HTMLInputElement>dialog.querySelector(`#up-down`)?.querySelector("input")).value) * 0.3048; var upDown = ftToM(parseInt((<HTMLInputElement>dialog.querySelector(`#up-down`)?.querySelector("input")).value));
// X: front-rear, positive front // X: front-rear, positive front
// Y: top-bottom, positive top // Y: top-bottom, positive top

View File

@@ -160,4 +160,20 @@ export function createDivWithClass(className: string) {
var el = document.createElement("div"); var el = document.createElement("div");
el.classList.add(className); el.classList.add(className);
return el; return el;
}
export function knotsToMs(knots: number) {
return knots / 1.94384;
}
export function msToKnots(ms: number) {
return ms * 1.94384;
}
export function ftToM(ft: number) {
return ft * 0.3048;
}
export function mToFt(m: number) {
return m / 0.3048;
} }

View File

@@ -7,6 +7,7 @@ import { Unit } from "../units/unit";
import { Panel } from "./panel"; import { Panel } from "./panel";
import { Switch } from "../controls/switch"; import { Switch } from "../controls/switch";
import { ROEDescriptions, ROEs, altitudeIncrements, emissionsCountermeasures, emissionsCountermeasuresDescriptions, maxAltitudeValues, maxSpeedValues, minAltitudeValues, minSpeedValues, reactionsToThreat, reactionsToThreatDescriptions, speedIncrements } from "../constants/constants"; import { ROEDescriptions, ROEs, altitudeIncrements, emissionsCountermeasures, emissionsCountermeasuresDescriptions, maxAltitudeValues, maxSpeedValues, minAltitudeValues, minSpeedValues, reactionsToThreat, reactionsToThreatDescriptions, speedIncrements } from "../constants/constants";
import { ftToM, knotsToMs, mToFt, msToKnots } from "../other/utils";
export class UnitControlPanel extends Panel { export class UnitControlPanel extends Panel {
#altitudeSlider: Slider; #altitudeSlider: Slider;
@@ -25,10 +26,10 @@ export class UnitControlPanel extends Panel {
super(ID); super(ID);
/* Unit control sliders */ /* Unit control sliders */
this.#altitudeSlider = new Slider("altitude-slider", 0, 100, "ft", (value: number) => { getUnitsManager().selectedUnitsSetAltitude(value * 0.3048); }); this.#altitudeSlider = new Slider("altitude-slider", 0, 100, "ft", (value: number) => { getUnitsManager().selectedUnitsSetAltitude(ftToM(value)); });
this.#altitudeTypeSwitch = new Switch("altitude-type-switch", (value: boolean) => { getUnitsManager().selectedUnitsSetAltitudeType(value? "AGL": "ASL"); }); this.#altitudeTypeSwitch = new Switch("altitude-type-switch", (value: boolean) => { getUnitsManager().selectedUnitsSetAltitudeType(value? "AGL": "ASL"); });
this.#speedSlider = new Slider("speed-slider", 0, 100, "kts", (value: number) => { getUnitsManager().selectedUnitsSetSpeed(value / 1.94384); }); this.#speedSlider = new Slider("speed-slider", 0, 100, "kts", (value: number) => { getUnitsManager().selectedUnitsSetSpeed(knotsToMs(value)); });
this.#speedTypeSwitch = new Switch("speed-type-switch", (value: boolean) => { getUnitsManager().selectedUnitsSetSpeedType(value? "GS": "CAS"); }); this.#speedTypeSwitch = new Switch("speed-type-switch", (value: boolean) => { getUnitsManager().selectedUnitsSetSpeedType(value? "GS": "CAS"); });
/* Option buttons */ /* Option buttons */
@@ -156,11 +157,11 @@ export class UnitControlPanel extends Panel {
this.#speedSlider.setActive(targetSpeed != undefined); this.#speedSlider.setActive(targetSpeed != undefined);
if (targetSpeed != undefined) if (targetSpeed != undefined)
this.#speedSlider.setValue(targetSpeed * 1.94384, false); this.#speedSlider.setValue(msToKnots(targetSpeed), false);
this.#altitudeSlider.setActive(targetAltitude != undefined); this.#altitudeSlider.setActive(targetAltitude != undefined);
if (targetAltitude != undefined) if (targetAltitude != undefined)
this.#altitudeSlider.setValue(targetAltitude / 0.3048, false); this.#altitudeSlider.setValue(mToFt(targetAltitude), false);
} }
else { else {
this.#speedSlider.setActive(false); this.#speedSlider.setActive(false);

View File

@@ -57,15 +57,8 @@ export class UnitInfoPanel extends Panel {
this.#unitLabel.innerText = aircraftDatabase.getByName(baseData.name)?.label || baseData.name; this.#unitLabel.innerText = aircraftDatabase.getByName(baseData.name)?.label || baseData.name;
this.#unitName.innerText = baseData.unitName; this.#unitName.innerText = baseData.unitName;
this.#unitControl.innerText = ( ( baseData.AI ) ? "AI" : "Human" ) + " controlled"; this.#unitControl.innerText = ( ( baseData.AI ) ? "AI" : "Human" ) + " controlled";
// this.#groupName.innerText = baseData.groupName;
//this.#name.innerText = baseData.name;
//this.#heading.innerText = String(Math.floor(rad2deg(unit.getFlightData().heading)) + " °");
//this.#altitude.innerText = String(Math.floor(unit.getFlightData().altitude / 0.3048) + " ft");
//this.#groundSpeed.innerText = String(Math.floor(unit.getFlightData().speed * 1.94384) + " kts");
this.#fuelBar.style.width = String(unit.getMissionData().fuel + "%"); this.#fuelBar.style.width = String(unit.getMissionData().fuel + "%");
this.#fuelPercentage.dataset.percentage = "" + unit.getMissionData().fuel; this.#fuelPercentage.dataset.percentage = "" + unit.getMissionData().fuel;
//this.#latitude.innerText = ConvertDDToDMS(unit.getFlightData().latitude, false);
//this.#longitude.innerText = ConvertDDToDMS(unit.getFlightData().longitude, true);
this.#currentTask.dataset.currentTask = unit.getTaskData().currentTask !== ""? unit.getTaskData().currentTask: "No task"; this.#currentTask.dataset.currentTask = unit.getTaskData().currentTask !== ""? unit.getTaskData().currentTask: "No task";
this.#currentTask.dataset.coalition = unit.getMissionData().coalition; this.#currentTask.dataset.coalition = unit.getMissionData().coalition;

View File

@@ -1,6 +1,6 @@
import { Marker, LatLng, Polyline, Icon, DivIcon, CircleMarker, Map } from 'leaflet'; import { Marker, LatLng, Polyline, Icon, DivIcon, CircleMarker, Map } from 'leaflet';
import { getMap, getUnitsManager } from '..'; import { getMap, getUnitsManager } from '..';
import { rad2deg } from '../other/utils'; import { mToFt, msToKnots, rad2deg } from '../other/utils';
import { addDestination, attackUnit, changeAltitude, changeSpeed, createFormation as setLeader, deleteUnit, getUnits, landAt, setAltitude, setReactionToThreat, setROE, setSpeed, refuel, setAdvacedOptions, followUnit, setEmissionsCountermeasures, setSpeedType, setAltitudeType, setOnOff, setFollowRoads } from '../server/server'; import { addDestination, attackUnit, changeAltitude, changeSpeed, createFormation as setLeader, deleteUnit, getUnits, landAt, setAltitude, setReactionToThreat, setROE, setSpeed, refuel, setAdvacedOptions, followUnit, setEmissionsCountermeasures, setSpeedType, setAltitudeType, setOnOff, setFollowRoads } from '../server/server';
import { aircraftDatabase } from './aircraftdatabase'; import { aircraftDatabase } from './aircraftdatabase';
import { groundUnitsDatabase } from './groundunitsdatabase'; import { groundUnitsDatabase } from './groundunitsdatabase';
@@ -668,9 +668,9 @@ export class Unit extends CustomMarker {
/* Set altitude and speed */ /* Set altitude and speed */
if (element.querySelector(".unit-altitude")) if (element.querySelector(".unit-altitude"))
(<HTMLElement>element.querySelector(".unit-altitude")).innerText = "FL" + String(Math.floor(this.getFlightData().altitude / 0.3048 / 100)); (<HTMLElement>element.querySelector(".unit-altitude")).innerText = "FL" + String(Math.floor(mToFt(this.getFlightData().altitude) / 100));
if (element.querySelector(".unit-speed")) if (element.querySelector(".unit-speed"))
(<HTMLElement>element.querySelector(".unit-speed")).innerText = String(Math.floor(this.getFlightData().speed * 1.94384)); (<HTMLElement>element.querySelector(".unit-speed")).innerText = String(Math.floor(msToKnots(this.getFlightData().speed))) + "GS";
/* Rotate elements according to heading */ /* Rotate elements according to heading */
element.querySelectorAll("[data-rotate-to-heading]").forEach(el => { element.querySelectorAll("[data-rotate-to-heading]").forEach(el => {

View File

@@ -3,7 +3,7 @@ import { getHotgroupPanel, getInfoPopup, getMap, getUnitDataTable } from "..";
import { Unit } from "./unit"; import { Unit } from "./unit";
import { cloneUnit } from "../server/server"; import { cloneUnit } from "../server/server";
import { IDLE, MOVE_UNIT } from "../map/map"; import { IDLE, MOVE_UNIT } from "../map/map";
import { deg2rad, keyEventWasInInput, latLngToMercator, mercatorToLatLng } from "../other/utils"; import { deg2rad, keyEventWasInInput, latLngToMercator, mToFt, mercatorToLatLng, msToKnots } from "../other/utils";
export class UnitsManager { export class UnitsManager {
#units: { [ID: number]: Unit }; #units: { [ID: number]: Unit };
@@ -250,7 +250,7 @@ export class UnitsManager {
for (let idx in selectedUnits) { for (let idx in selectedUnits) {
selectedUnits[idx].setSpeed(speed); selectedUnits[idx].setSpeed(speed);
} }
this.#showActionMessage(selectedUnits, `setting speed to ${speed * 1.94384} kts`); this.#showActionMessage(selectedUnits, `setting speed to ${msToKnots(speed)} kts`);
} }
selectedUnitsSetSpeedType(speedType: string) { selectedUnitsSetSpeedType(speedType: string) {
@@ -266,7 +266,7 @@ export class UnitsManager {
for (let idx in selectedUnits) { for (let idx in selectedUnits) {
selectedUnits[idx].setAltitude(altitude); selectedUnits[idx].setAltitude(altitude);
} }
this.#showActionMessage(selectedUnits, `setting altitude to ${altitude / 0.3048} ft`); this.#showActionMessage(selectedUnits, `setting altitude to ${mToFt(altitude)} ft`);
} }
selectedUnitsSetAltitudeType(altitudeType: string) { selectedUnitsSetAltitudeType(altitudeType: string) {

View File

@@ -12,19 +12,12 @@ class AirUnit : public Unit
public: public:
AirUnit(json::value json, int ID); AirUnit(json::value json, int ID);
virtual wstring getCategory() = 0; virtual void setState(int newState);
virtual void changeSpeed(wstring change) {};
virtual void changeAltitude(wstring change) {};
virtual void setTargetSpeed(double newTargetSpeed);
virtual void setTargetAltitude(double newTargetAltitude);
virtual void setTargetSpeedType(wstring newTargetSpeedType);
virtual void setTargetAltitudeType(wstring newTargetAltitudeType);
virtual wstring getCategory() = 0;
virtual void changeSpeed(wstring change) = 0;
virtual void changeAltitude(wstring change) = 0;
protected: protected:
virtual void AIloop(); virtual void AIloop();
virtual void setState(int newState);
bool isDestinationReached();
bool setActiveDestination();
bool updateActivePath(bool looping);
void goToDestination(wstring enrouteTask = L"nil");
}; };

View File

@@ -7,12 +7,14 @@ class GroundUnit : public Unit
{ {
public: public:
GroundUnit(json::value json, int ID); GroundUnit(json::value json, int ID);
virtual void AIloop();
virtual wstring getCategory() { return L"GroundUnit"; }; virtual wstring getCategory() { return L"GroundUnit"; };
virtual void setState(int newState);
virtual void changeSpeed(wstring change); virtual void changeSpeed(wstring change);
virtual void changeAltitude(wstring change) {};
virtual void setOnOff(bool newOnOff); virtual void setOnOff(bool newOnOff);
virtual void setFollowRoads(bool newFollowRoads); virtual void setFollowRoads(bool newFollowRoads);
protected:
virtual void AIloop();
}; };

View File

@@ -9,6 +9,5 @@ public:
virtual wstring getCategory() { return L"NavyUnit"; }; virtual wstring getCategory() { return L"NavyUnit"; };
virtual void changeSpeed(wstring change); virtual void changeSpeed(wstring change);
virtual void changeAltitude(wstring change) {};
}; };

View File

@@ -70,6 +70,7 @@ public:
void setAlive(bool newAlive) { alive = newAlive; addMeasure(L"alive", json::value(newAlive));} void setAlive(bool newAlive) { alive = newAlive; addMeasure(L"alive", json::value(newAlive));}
void setType(json::value newType) { type = newType; addMeasure(L"type", newType);} void setType(json::value newType) { type = newType; addMeasure(L"type", newType);}
void setCountry(int newCountry) { country = newCountry; addMeasure(L"country", json::value(newCountry));} void setCountry(int newCountry) { country = newCountry; addMeasure(L"country", json::value(newCountry));}
bool getAI() { return AI; } bool getAI() { return AI; }
wstring getName() { return name; } wstring getName() { return name; }
wstring getUnitName() { return unitName; } wstring getUnitName() { return unitName; }
@@ -84,6 +85,7 @@ public:
void setAltitude(double newAltitude) {altitude = newAltitude; addMeasure(L"altitude", json::value(newAltitude));} void setAltitude(double newAltitude) {altitude = newAltitude; addMeasure(L"altitude", json::value(newAltitude));}
void setHeading(double newHeading) {heading = newHeading; addMeasure(L"heading", json::value(newHeading));} void setHeading(double newHeading) {heading = newHeading; addMeasure(L"heading", json::value(newHeading));}
void setSpeed(double newSpeed) {speed = newSpeed; addMeasure(L"speed", json::value(newSpeed));} void setSpeed(double newSpeed) {speed = newSpeed; addMeasure(L"speed", json::value(newSpeed));}
double getLatitude() { return latitude; } double getLatitude() { return latitude; }
double getLongitude() { return longitude; } double getLongitude() { return longitude; }
double getAltitude() { return altitude; } double getAltitude() { return altitude; }
@@ -97,6 +99,7 @@ public:
void setHasTask(bool newHasTask) { hasTask = newHasTask; addMeasure(L"hasTask", json::value(newHasTask)); } void setHasTask(bool newHasTask) { hasTask = newHasTask; addMeasure(L"hasTask", json::value(newHasTask)); }
void setCoalitionID(int newCoalitionID); void setCoalitionID(int newCoalitionID);
void setFlags(json::value newFlags) { flags = newFlags; addMeasure(L"flags", json::value(newFlags));} void setFlags(json::value newFlags) { flags = newFlags; addMeasure(L"flags", json::value(newFlags));}
double getFuel() { return fuel; } double getFuel() { return fuel; }
json::value getAmmo() { return ammo; } json::value getAmmo() { return ammo; }
json::value getTargets() { return targets; } json::value getTargets() { return targets; }
@@ -108,21 +111,18 @@ public:
/********** Formation data **********/ /********** Formation data **********/
void setLeaderID(int newLeaderID) { leaderID = newLeaderID; addMeasure(L"leaderID", json::value(newLeaderID)); } void setLeaderID(int newLeaderID) { leaderID = newLeaderID; addMeasure(L"leaderID", json::value(newLeaderID)); }
void setFormationOffset(Offset formationOffset); void setFormationOffset(Offset formationOffset);
int getLeaderID() { return leaderID; } int getLeaderID() { return leaderID; }
Offset getFormationoffset() { return formationOffset; } Offset getFormationoffset() { return formationOffset; }
/********** Task data **********/ /********** Task data **********/
void setCurrentTask(wstring newCurrentTask) { currentTask = newCurrentTask; addMeasure(L"currentTask", json::value(newCurrentTask)); } void setCurrentTask(wstring newCurrentTask) { currentTask = newCurrentTask; addMeasure(L"currentTask", json::value(newCurrentTask)); }
virtual void setTargetSpeed(double newTargetSpeed) { targetSpeed = newTargetSpeed; addMeasure(L"targetSpeed", json::value(newTargetSpeed));} void setTargetSpeed(double newTargetSpeed);
virtual void setTargetAltitude(double newTargetAltitude) { targetAltitude = newTargetAltitude; addMeasure(L"targetAltitude", json::value(newTargetAltitude));} void setTargetAltitude(double newTargetAltitude);
virtual void setTargetSpeedType(wstring newTargetSpeedType) { targetSpeedType = newTargetSpeedType; addMeasure(L"targetSpeedType", json::value(newTargetSpeedType)); } void setTargetSpeedType(wstring newTargetSpeedType);
virtual void setTargetAltitudeType(wstring newTargetAltitudeType) { targetAltitudeType = newTargetAltitudeType; addMeasure(L"targetAltitudeType", json::value(newTargetAltitudeType)); } void setTargetAltitudeType(wstring newTargetAltitudeType);
void setActiveDestination(Coords newActiveDestination) { activeDestination = newActiveDestination; addMeasure(L"activeDestination", json::value("")); } // TODO fix void setActiveDestination(Coords newActiveDestination) { activeDestination = newActiveDestination; addMeasure(L"activeDestination", json::value("")); } // TODO fix
void setActivePath(list<Coords> newActivePath); void setActivePath(list<Coords> newActivePath);
void clearActivePath();
void pushActivePathFront(Coords newActivePathFront);
void pushActivePathBack(Coords newActivePathBack);
void popActivePathFront();
void setTargetID(int newTargetID) { targetID = newTargetID; addMeasure(L"targetID", json::value(newTargetID));} void setTargetID(int newTargetID) { targetID = newTargetID; addMeasure(L"targetID", json::value(newTargetID));}
void setIsTanker(bool newIsTanker); void setIsTanker(bool newIsTanker);
void setIsAWACS(bool newIsAWACS); void setIsAWACS(bool newIsAWACS);
@@ -150,6 +150,7 @@ public:
void setRadio(Options::Radio newradio); void setRadio(Options::Radio newradio);
void setGeneralSettings(Options::GeneralSettings newGeneralSettings); void setGeneralSettings(Options::GeneralSettings newGeneralSettings);
void setEPLRS(bool newEPLRS); void setEPLRS(bool newEPLRS);
wstring getROE() { return ROE; } wstring getROE() { return ROE; }
wstring getReactionToThreat() { return reactionToThreat; } wstring getReactionToThreat() { return reactionToThreat; }
wstring getEmissionsCountermeasures() { return emissionsCountermeasures; }; wstring getEmissionsCountermeasures() { return emissionsCountermeasures; };
@@ -160,11 +161,15 @@ public:
/********** Control functions **********/ /********** Control functions **********/
void landAt(Coords loc); void landAt(Coords loc);
virtual void changeSpeed(wstring change){}; virtual void changeSpeed(wstring change) {};
virtual void changeAltitude(wstring change){}; virtual void changeAltitude(wstring change) {};
void resetActiveDestination(); void resetActiveDestination();
virtual void setState(int newState) { state = newState; }; virtual void setState(int newState) { state = newState; };
void resetTask(); void resetTask();
void clearActivePath();
void pushActivePathFront(Coords newActivePathFront);
void pushActivePathBack(Coords newActivePathBack);
void popActivePathFront();
protected: protected:
int ID; int ID;
@@ -236,4 +241,8 @@ protected:
bool isLeaderAlive(); bool isLeaderAlive();
virtual void AIloop() = 0; virtual void AIloop() = 0;
void addMeasure(wstring key, json::value value); void addMeasure(wstring key, json::value value);
bool isDestinationReached(double threshold);
bool setActiveDestination();
bool updateActivePath(bool looping);
void goToDestination(wstring enrouteTask = L"nil");
}; };

View File

@@ -18,8 +18,8 @@ Aircraft::Aircraft(json::value json, int ID) : AirUnit(json, ID)
log("New Aircraft created with ID: " + to_string(ID)); log("New Aircraft created with ID: " + to_string(ID));
addMeasure(L"category", json::value(getCategory())); addMeasure(L"category", json::value(getCategory()));
double targetSpeed = 300 / 1.94384; double targetSpeed = knotsToMs(300);
double targetAltitude = 20000 * 0.3048; double targetAltitude = ftToM(20000);
setTargetSpeed(targetSpeed); setTargetSpeed(targetSpeed);
setTargetAltitude(targetAltitude); setTargetAltitude(targetAltitude);
}; };
@@ -27,16 +27,14 @@ Aircraft::Aircraft(json::value json, int ID) : AirUnit(json, ID)
void Aircraft::changeSpeed(wstring change) void Aircraft::changeSpeed(wstring change)
{ {
if (change.compare(L"stop") == 0) if (change.compare(L"stop") == 0)
{
setState(State::IDLE); setState(State::IDLE);
}
else if (change.compare(L"slow") == 0) else if (change.compare(L"slow") == 0)
setTargetSpeed(getTargetSpeed() - 25 / 1.94384); setTargetSpeed(getTargetSpeed() - knotsToMs(25));
else if (change.compare(L"fast") == 0) else if (change.compare(L"fast") == 0)
setTargetSpeed(getTargetSpeed() + 25 / 1.94384); setTargetSpeed(getTargetSpeed() + knotsToMs(25));
if (getTargetSpeed() < 50 / 1.94384) if (getTargetSpeed() < knotsToMs(50))
setTargetSpeed(50 / 1.94384); setTargetSpeed(knotsToMs(50));
goToDestination(); /* Send the command to reach the destination */ goToDestination(); /* Send the command to reach the destination */
} }
@@ -46,16 +44,16 @@ void Aircraft::changeAltitude(wstring change)
if (change.compare(L"descend") == 0) if (change.compare(L"descend") == 0)
{ {
if (getTargetAltitude() > 5000) if (getTargetAltitude() > 5000)
setTargetAltitude(getTargetAltitude() - 2500 / 3.28084); setTargetAltitude(getTargetAltitude() - ftToM(2500));
else if (getTargetAltitude() > 0) else if (getTargetAltitude() > 0)
setTargetAltitude(getTargetAltitude() - 500 / 3.28084); setTargetAltitude(getTargetAltitude() - ftToM(500));
} }
else if (change.compare(L"climb") == 0) else if (change.compare(L"climb") == 0)
{ {
if (getTargetAltitude() > 5000) if (getTargetAltitude() > 5000)
setTargetAltitude(getTargetAltitude() + 2500 / 3.28084); setTargetAltitude(getTargetAltitude() + ftToM(2500));
else if (getTargetAltitude() >= 0) else if (getTargetAltitude() >= 0)
setTargetAltitude(getTargetAltitude() + 500 / 3.28084); setTargetAltitude(getTargetAltitude() + ftToM(500));
} }
if (getTargetAltitude() < 0) if (getTargetAltitude() < 0)
setTargetAltitude(0); setTargetAltitude(0);

View File

@@ -20,7 +20,7 @@ AirUnit::AirUnit(json::value json, int ID) : Unit(json, ID)
void AirUnit::setState(int newState) void AirUnit::setState(int newState)
{ {
/************ Perform any action required when LEAVING a certain state ************/ /************ Perform any action required when LEAVING a state ************/
if (newState != state) { if (newState != state) {
switch (state) { switch (state) {
case State::IDLE: { case State::IDLE: {
@@ -48,7 +48,7 @@ void AirUnit::setState(int newState)
} }
} }
/************ Perform any action required when ENTERING a certain state ************/ /************ Perform any action required when ENTERING a state ************/
switch (newState) { switch (newState) {
case State::IDLE: { case State::IDLE: {
clearActivePath(); clearActivePath();
@@ -100,67 +100,6 @@ void AirUnit::setState(int newState)
state = newState; state = newState;
} }
bool AirUnit::isDestinationReached()
{
if (activeDestination != NULL)
{
double dist = 0;
Geodesic::WGS84().Inverse(latitude, longitude, activeDestination.lat, activeDestination.lng, dist);
if (dist < AIR_DEST_DIST_THR)
{
log(unitName + L" destination reached");
return true;
}
else {
return false;
}
}
else
return true;
}
bool AirUnit::setActiveDestination()
{
if (activePath.size() > 0)
{
activeDestination = activePath.front();
log(unitName + L" active destination set to queue front");
return true;
}
else
{
activeDestination = Coords(0);
log(unitName + L" active destination set to NULL");
return false;
}
}
bool AirUnit::updateActivePath(bool looping)
{
if (activePath.size() > 0)
{
/* Push the next destination in the queue to the front */
if (looping)
pushActivePathBack(activePath.front());
popActivePathFront();
log(unitName + L" active path front popped");
return true;
}
else {
return false;
}
}
void AirUnit::goToDestination(wstring enrouteTask)
{
if (activeDestination != NULL)
{
Command* command = dynamic_cast<Command*>(new Move(ID, activeDestination, getTargetSpeed(), getTargetSpeedType(), getTargetAltitude(), getTargetAltitudeType(), enrouteTask));
scheduler->appendCommand(command);
setHasTask(true);
}
}
void AirUnit::AIloop() void AirUnit::AIloop()
{ {
/* State machine */ /* State machine */
@@ -168,7 +107,7 @@ void AirUnit::AIloop()
case State::IDLE: { case State::IDLE: {
currentTask = L"Idle"; currentTask = L"Idle";
if (!hasTask) if (!getHasTask())
{ {
std::wostringstream taskSS; std::wostringstream taskSS;
if (isTanker) { if (isTanker) {
@@ -206,7 +145,7 @@ void AirUnit::AIloop()
currentTask = L"Reaching destination"; currentTask = L"Reaching destination";
} }
if (activeDestination == NULL || !hasTask) if (activeDestination == NULL || !getHasTask())
{ {
if (!setActiveDestination()) if (!setActiveDestination())
setState(State::IDLE); setState(State::IDLE);
@@ -214,7 +153,7 @@ void AirUnit::AIloop()
goToDestination(enrouteTask); goToDestination(enrouteTask);
} }
else { else {
if (isDestinationReached()) { if (isDestinationReached(AIR_DEST_DIST_THR)) {
if (updateActivePath(looping) && setActiveDestination()) if (updateActivePath(looping) && setActiveDestination())
goToDestination(enrouteTask); goToDestination(enrouteTask);
else else
@@ -251,7 +190,7 @@ void AirUnit::AIloop()
wstring enrouteTask = enrouteTaskSS.str(); wstring enrouteTask = enrouteTaskSS.str();
currentTask = L"Attacking " + getTargetName(); currentTask = L"Attacking " + getTargetName();
if (!hasTask) if (!getHasTask())
{ {
setActiveDestination(); setActiveDestination();
goToDestination(enrouteTask); goToDestination(enrouteTask);
@@ -272,7 +211,7 @@ void AirUnit::AIloop()
currentTask = L"Following " + getTargetName(); currentTask = L"Following " + getTargetName();
Unit* leader = unitsManager->getUnit(leaderID); Unit* leader = unitsManager->getUnit(leaderID);
if (!hasTask) { if (!getHasTask()) {
if (leader != nullptr && leader->getAlive() && formationOffset != NULL) if (leader != nullptr && leader->getAlive() && formationOffset != NULL)
{ {
std::wostringstream taskSS; std::wostringstream taskSS;
@@ -295,7 +234,7 @@ void AirUnit::AIloop()
case State::REFUEL: { case State::REFUEL: {
currentTask = L"Refueling"; currentTask = L"Refueling";
if (!hasTask) { if (!getHasTask()) {
if (fuel <= initialFuel) { if (fuel <= initialFuel) {
std::wostringstream taskSS; std::wostringstream taskSS;
taskSS << "{" taskSS << "{"
@@ -316,23 +255,3 @@ void AirUnit::AIloop()
addMeasure(L"currentTask", json::value(currentTask)); addMeasure(L"currentTask", json::value(currentTask));
} }
void AirUnit::setTargetSpeed(double newTargetSpeed) {
Unit::setTargetSpeed(newTargetSpeed);
goToDestination();
}
void AirUnit::setTargetAltitude(double newTargetAltitude) {
Unit::setTargetAltitude(newTargetAltitude);
goToDestination();
}
void AirUnit::setTargetSpeedType(wstring newTargetSpeedType) {
Unit::setTargetSpeedType(newTargetSpeedType);
goToDestination();
}
void AirUnit::setTargetAltitudeType(wstring newTargetAltitudeType) {
Unit::setTargetAltitudeType(newTargetAltitudeType);
goToDestination();
}

View File

@@ -22,60 +22,98 @@ GroundUnit::GroundUnit(json::value json, int ID) : Unit(json, ID)
setTargetSpeed(targetSpeed); setTargetSpeed(targetSpeed);
}; };
void GroundUnit::setState(int newState)
{
/************ Perform any action required when LEAVING a state ************/
if (newState != state) {
switch (state) {
case State::IDLE: {
break;
}
case State::REACH_DESTINATION: {
break;
}
default:
break;
}
}
/************ Perform any action required when ENTERING a state ************/
switch (newState) {
case State::IDLE: {
clearActivePath();
resetActiveDestination();
addMeasure(L"currentState", json::value(L"Idle"));
break;
}
case State::REACH_DESTINATION: {
resetActiveDestination();
addMeasure(L"currentState", json::value(L"Reach destination"));
break;
}
default:
break;
}
resetTask();
log(unitName + L" setting state from " + to_wstring(state) + L" to " + to_wstring(newState));
state = newState;
}
void GroundUnit::AIloop() void GroundUnit::AIloop()
{ {
/* Set the active destination to be always equal to the first point of the active path. This is in common with all AI units */
if (activePath.size() > 0)
{
if (activeDestination != activePath.front())
{
activeDestination = activePath.front();
std::wostringstream taskSS; switch (state) {
taskSS << "{ id = 'FollowRoads', value = " << (getFollowRoads()? "true" : "false") << " }"; case State::IDLE: {
currentTask = L"Idle";
Command* command = dynamic_cast<Command*>(new Move(ID, activeDestination, getTargetSpeed(), getTargetSpeedType(), getTargetAltitude(), getTargetAltitudeType(), taskSS.str())); if (getHasTask())
scheduler->appendCommand(command); resetTask();
} break;
} }
else case State::REACH_DESTINATION: {
{ wstring enrouteTask = L"";
if (activeDestination != NULL) bool looping = false;
std::wostringstream taskSS;
taskSS << "{ id = 'FollowRoads', value = " << (getFollowRoads() ? "true" : "false") << " }";
enrouteTask = taskSS.str();
if (activeDestination == NULL || !getHasTask())
{ {
log(unitName + L" no more points in active path"); if (!setActiveDestination())
activeDestination = Coords(0); // Set the active path to NULL setState(State::IDLE);
currentTask = L"Idle"; else
goToDestination(enrouteTask);
} }
else {
if (isDestinationReached(GROUND_DEST_DIST_THR)) {
if (updateActivePath(looping) && setActiveDestination())
goToDestination(enrouteTask);
else
setState(State::IDLE);
}
}
break;
}
default:
break;
} }
/* Ground unit AI Loop */ addMeasure(L"currentTask", json::value(currentTask));
if (activeDestination != NULL)
{
double newDist = 0;
Geodesic::WGS84().Inverse(latitude, longitude, activeDestination.lat, activeDestination.lng, newDist);
if (newDist < GROUND_DEST_DIST_THR)
{
/* Destination reached */
popActivePathFront();
log(unitName + L" destination reached");
}
}
} }
void GroundUnit::changeSpeed(wstring change) void GroundUnit::changeSpeed(wstring change)
{ {
if (change.compare(L"stop") == 0) if (change.compare(L"stop") == 0)
{ setState(State::IDLE);
}
else if (change.compare(L"slow") == 0) else if (change.compare(L"slow") == 0)
{ setTargetSpeed(getTargetSpeed() - knotsToMs(5));
}
else if (change.compare(L"fast") == 0) else if (change.compare(L"fast") == 0)
{ setTargetSpeed(getTargetSpeed() + knotsToMs(5));
} if (getTargetSpeed() < 0)
setTargetSpeed(0);
} }
void GroundUnit::setOnOff(bool newOnOff) void GroundUnit::setOnOff(bool newOnOff)

View File

@@ -18,8 +18,8 @@ Helicopter::Helicopter(json::value json, int ID) : AirUnit(json, ID)
log("New Helicopter created with ID: " + to_string(ID)); log("New Helicopter created with ID: " + to_string(ID));
addMeasure(L"category", json::value(getCategory())); addMeasure(L"category", json::value(getCategory()));
double targetSpeed = 100 / 1.94384; double targetSpeed = knotsToMs(100);
double targetAltitude = 5000 * 0.3048; double targetAltitude = ftToM(5000);
setTargetSpeed(targetSpeed); setTargetSpeed(targetSpeed);
setTargetAltitude(targetAltitude); setTargetAltitude(targetAltitude);
}; };
@@ -32,9 +32,9 @@ void Helicopter::changeSpeed(wstring change)
clearActivePath(); clearActivePath();
} }
else if (change.compare(L"slow") == 0) else if (change.compare(L"slow") == 0)
targetSpeed -= 10 / 1.94384; targetSpeed -= knotsToMs(10);
else if (change.compare(L"fast") == 0) else if (change.compare(L"fast") == 0)
targetSpeed += 10 / 1.94384; targetSpeed += knotsToMs(10);
if (targetSpeed < 0) if (targetSpeed < 0)
targetSpeed = 0; targetSpeed = 0;
@@ -46,16 +46,16 @@ void Helicopter::changeAltitude(wstring change)
if (change.compare(L"descend") == 0) if (change.compare(L"descend") == 0)
{ {
if (targetAltitude > 100) if (targetAltitude > 100)
targetAltitude -= 100 / 3.28084; targetAltitude -= ftToM(100);
else if (targetAltitude > 0) else if (targetAltitude > 0)
targetAltitude -= 10 / 3.28084; targetAltitude -= ftToM(10);
} }
else if (change.compare(L"climb") == 0) else if (change.compare(L"climb") == 0)
{ {
if (targetAltitude > 100) if (targetAltitude > 100)
targetAltitude += 100 / 3.28084; targetAltitude += ftToM(100);
else if (targetAltitude >= 0) else if (targetAltitude >= 0)
targetAltitude += 10 / 3.28084; targetAltitude += ftToM(10);
} }
if (targetAltitude < 0) if (targetAltitude < 0)
targetAltitude = 0; targetAltitude = 0;

View File

@@ -324,6 +324,7 @@ void Unit::resetTask()
{ {
Command* command = dynamic_cast<Command*>(new ResetTask(ID)); Command* command = dynamic_cast<Command*>(new ResetTask(ID));
scheduler->appendCommand(command); scheduler->appendCommand(command);
setHasTask(false);
} }
void Unit::setFormationOffset(Offset newFormationOffset) void Unit::setFormationOffset(Offset newFormationOffset)
@@ -576,3 +577,87 @@ void Unit::setGeneralSettings(Options::GeneralSettings newGeneralSettings) {
} }
} }
void Unit::setTargetSpeed(double newTargetSpeed) {
targetSpeed = newTargetSpeed;
addMeasure(L"targetSpeed", json::value(newTargetSpeed));
goToDestination();
}
void Unit::setTargetAltitude(double newTargetAltitude) {
targetAltitude = newTargetAltitude;
addMeasure(L"targetAltitude", json::value(newTargetAltitude));
goToDestination();
}
void Unit::setTargetSpeedType(wstring newTargetSpeedType) {
targetSpeedType = newTargetSpeedType;
addMeasure(L"targetSpeedType", json::value(newTargetSpeedType));
goToDestination();
}
void Unit::setTargetAltitudeType(wstring newTargetAltitudeType) {
targetAltitudeType = newTargetAltitudeType;
addMeasure(L"targetAltitudeType", json::value(newTargetAltitudeType));
goToDestination();
}
void Unit::goToDestination(wstring enrouteTask)
{
if (activeDestination != NULL)
{
Command* command = dynamic_cast<Command*>(new Move(ID, activeDestination, getTargetSpeed(), getTargetSpeedType(), getTargetAltitude(), getTargetAltitudeType(), enrouteTask));
scheduler->appendCommand(command);
setHasTask(true);
}
}
bool Unit::isDestinationReached(double threshold)
{
if (activeDestination != NULL)
{
double dist = 0;
Geodesic::WGS84().Inverse(latitude, longitude, activeDestination.lat, activeDestination.lng, dist);
if (dist < threshold)
{
log(unitName + L" destination reached");
return true;
}
else {
return false;
}
}
else
return true;
}
bool Unit::setActiveDestination()
{
if (activePath.size() > 0)
{
activeDestination = activePath.front();
log(unitName + L" active destination set to queue front");
return true;
}
else
{
activeDestination = Coords(0);
log(unitName + L" active destination set to NULL");
return false;
}
}
bool Unit::updateActivePath(bool looping)
{
if (activePath.size() > 0)
{
/* Push the next destination in the queue to the front */
if (looping)
pushActivePathBack(activePath.front());
popActivePathFront();
log(unitName + L" active path front popped");
return true;
}
else {
return false;
}
}

View File

@@ -29,3 +29,8 @@ bool DllExport operator!= (const Offset& a, const Offset& b);
bool DllExport operator== (const Offset& a, const int& b); bool DllExport operator== (const Offset& a, const int& b);
bool DllExport operator!= (const Offset& a, const int& b); bool DllExport operator!= (const Offset& a, const int& b);
double DllExport knotsToMs(const double knots);
double DllExport msToKnots(const double ms);
double DllExport ftToM(const double ft);
double DllExport mToFt(const double m);

View File

@@ -63,3 +63,20 @@ bool operator== (const Offset& a, const Offset& b) { return a.x == b.x && a.y ==
bool operator!= (const Offset& a, const Offset& b) { return !(a == b); } bool operator!= (const Offset& a, const Offset& b) { return !(a == b); }
bool operator== (const Offset& a, const int& b) { return a.x == b && a.y == b && a.z == b; } bool operator== (const Offset& a, const int& b) { return a.x == b && a.y == b && a.z == b; }
bool operator!= (const Offset& a, const int& b) { return !(a == b); } bool operator!= (const Offset& a, const int& b) { return !(a == b); }
double knotsToMs(const double knots) {
return knots / 1.94384;
}
double msToKnots(const double ms) {
return ms * 1.94384;
}
double ftToM(const double ft) {
return ft * 0.3048;
}
double mToFt(const double m) {
return m / 0.3048;
}