Converted data transfer to binary key-value method

This commit is contained in:
Pax1601
2023-06-26 18:53:04 +02:00
parent 1989219579
commit 4d9dd364b6
22 changed files with 858 additions and 885 deletions

View File

@@ -6,8 +6,6 @@ class Aircraft : public AirUnit
public:
Aircraft(json::value json, unsigned int ID);
virtual string getCategory() { return "Aircraft"; };
virtual void changeSpeed(string change);
virtual void changeAltitude(string change);
};

View File

@@ -14,7 +14,6 @@ public:
virtual void setState(unsigned char newState);
virtual string getCategory() = 0;
virtual void changeSpeed(string change) = 0;
virtual void changeAltitude(string change) = 0;

View File

@@ -7,7 +7,6 @@ class GroundUnit : public Unit
{
public:
GroundUnit(json::value json, unsigned int ID);
virtual string getCategory() { return "GroundUnit"; };
virtual void setState(unsigned char newState);

View File

@@ -6,8 +6,6 @@ class Helicopter : public AirUnit
public:
Helicopter(json::value json, unsigned int ID);
virtual string getCategory() { return "Helicopter"; };
virtual void changeSpeed(string change);
virtual void changeAltitude(string change);
};

View File

@@ -7,7 +7,6 @@ public:
NavyUnit(json::value json, unsigned int ID);
virtual void AIloop();
virtual string getCategory() { return "NavyUnit"; };
virtual void changeSpeed(string change);
};

View File

@@ -12,6 +12,50 @@ using namespace std::chrono;
#define TASK_CHECK_INIT_VALUE 10
namespace DataIndex {
enum DataIndexes {
startOfData = 0,
category,
alive,
human,
controlled,
coalition,
country,
name,
unitName,
groupName,
state,
task,
hasTask,
position,
speed,
heading,
isTanker,
isAWACS,
onOff,
followRoads,
fuel,
desiredSpeed,
desiredSpeedType,
desiredAltitude,
desiredAltitudeType,
leaderID,
formationOffset,
targetID,
targetPosition,
ROE,
reactionToThreat,
emissionsCountermeasures,
TACAN,
radio,
generalSettings,
ammo,
contacts,
activePath,
endOfData = 255
};
}
namespace State
{
enum States
@@ -33,7 +77,7 @@ namespace State
};
#pragma pack(push, 1)
namespace Options {
namespace DataTypes {
struct TACAN
{
bool isOn = false;
@@ -57,9 +101,7 @@ namespace Options {
bool prohibitAfterburner = false;
bool prohibitAirWpn = false;
};
}
namespace DataTypes {
struct Ammo {
unsigned short quantity = 0;
char name[32];
@@ -72,31 +114,6 @@ namespace DataTypes {
unsigned int ID = 0;
unsigned char detectionMethod = 0;
};
struct DataPacket {
unsigned int ID;
unsigned int bitmask;
Coords position;
double speed;
double heading;
unsigned short fuel;
double desiredSpeed;
double desiredAltitude;
unsigned int leaderID;
unsigned int targetID;
Coords targetPosition;
unsigned char coalition;
unsigned char state;
unsigned char ROE;
unsigned char reactionToThreat;
unsigned char emissionsCountermeasures;
Options::TACAN TACAN;
Options::Radio Radio;
unsigned short pathLength;
unsigned short ammoLength;
unsigned short contactsLength;
unsigned char taskLength;
};
}
#pragma pack(pop)
@@ -106,209 +123,213 @@ public:
Unit(json::value json, unsigned int ID);
~Unit();
/********** Public methods **********/
/********** Methods **********/
void initialize(json::value json);
void setDefaults(bool force = false);
unsigned int getID() { return ID; }
void runAILoop();
void updateExportData(json::value json, double dt = 0);
void updateMissionData(json::value json);
unsigned int getDataPacket(char* &data);
void getData(stringstream &ss, unsigned long long time, bool refresh);
virtual string getCategory() { return "No category"; };
/********** Base data **********/
void setControlled(bool newValue) { updateValue(controlled, newValue); }
void setName(string newValue) { updateValue(name, newValue); }
void setUnitName(string newValue) { updateValue(unitName, newValue); }
void setGroupName(string newValue) { updateValue(groupName, newValue); }
void setAlive(bool newValue) { updateValue(alive, newValue); }
void setCountry(unsigned int newValue) { updateValue(country, newValue); }
void setHuman(bool newValue) { updateValue(human, newValue); }
bool getControlled() { return controlled; }
string getName() { return name; }
string getUnitName() { return unitName; }
string getGroupName() { return groupName; }
bool getAlive() { return alive; }
unsigned int getCountry() { return country; }
bool getHuman() { return human; }
/********** Flight data **********/
void setPosition(Coords newValue) { updateValue(position, newValue); }
void setHeading(double newValue) { updateValue(heading, newValue); }
void setSpeed(double newValue) { updateValue(speed, newValue); }
Coords getPosition() { return position; }
double getHeading() { return heading; }
double getSpeed() { return speed; }
/********** Mission data **********/
void setFuel(unsigned short newValue) { updateValue(fuel, newValue); }
void setAmmo(vector<DataTypes::Ammo> newAmmo) { ammo = newAmmo; }
void setContacts(vector<DataTypes::Contact> newContacts) { contacts = newContacts; }
void setHasTask(bool newValue) { updateValue(hasTask, newValue); }
void setCoalition(unsigned char newValue) { updateValue(coalition, newValue);}
double getFuel() { return fuel; }
vector<DataTypes::Ammo> getAmmo() { return ammo; }
vector<DataTypes::Contact> getTargets() { return contacts; }
bool getHasTask() { return hasTask; }
unsigned int getCoalition() { return coalition; }
/********** Formation data **********/
void setLeaderID(unsigned int newValue) { updateValue(leaderID, newValue); }
void setFormationOffset(Offset formationOffset);
unsigned int getLeaderID() { return leaderID; }
Offset getFormationoffset() { return formationOffset; }
/********** Task data **********/
void setTask(string newValue) { updateValue(task, newValue); }
void setDesiredSpeed(double newValue);
void setDesiredAltitude(double newValue);
void setDesiredSpeedType(string newValue);
void setDesiredAltitudeType(string newValue);
void setActiveDestination(Coords newValue) { updateValue(activeDestination, newValue); }
void setActivePath(list<Coords> newValue);
void setTargetID(unsigned int newValue) { updateValue(targetID, newValue); }
void setTargetPosition(Coords newValue) { updateValue(targetPosition, newValue); }
void setIsTanker(bool newValue);
void setIsAWACS(bool newValue);
virtual void setOnOff(bool newValue) { updateValue(onOff, newValue); };
virtual void setFollowRoads(bool newValue) { updateValue(followRoads, newValue); };
string getTask() { return task; }
virtual double getDesiredSpeed() { return desiredSpeed; };
virtual double getDesiredAltitude() { return desiredAltitude; };
virtual bool getDesiredSpeedType() { return desiredSpeedType; };
virtual bool getDesiredAltitudeType() { return desiredAltitudeType; };
unsigned int getDataPacket(char*& data);
unsigned int getID() { return ID; }
void getData(stringstream& ss, unsigned long long time, bool refresh);
Coords getActiveDestination() { return activeDestination; }
list<Coords> getActivePath() { return activePath; }
unsigned int getTargetID() { return targetID; }
Coords getTargetPosition() { return targetPosition; }
bool getIsTanker() { return isTanker; }
bool getIsAWACS() { return isAWACS; }
bool getOnOff() { return onOff; };
bool getFollowRoads() { return followRoads; };
/********** Options data **********/
void setROE(unsigned char newValue, bool force = false);
void setReactionToThreat(unsigned char newValue, bool force = false);
void setEmissionsCountermeasures(unsigned char newValue, bool force = false);
void setTACAN(Options::TACAN newValue, bool force = false);
void setRadio(Options::Radio newValue, bool force = false);
void setGeneralSettings(Options::GeneralSettings newValue, bool force = false);
void setEPLRS(bool newValue, bool force = false);
unsigned char getROE() { return ROE; }
unsigned char getReactionToThreat() { return reactionToThreat; }
unsigned char getEmissionsCountermeasures() { return emissionsCountermeasures; };
Options::TACAN getTACAN() { return TACAN; }
Options::Radio getRadio() { return radio; }
Options::GeneralSettings getGeneralSettings() { return generalSettings; }
bool getEPLRS() { return EPLRS; }
/********** Control functions **********/
void landAt(Coords loc);
virtual void changeSpeed(string change) {};
virtual void changeAltitude(string change) {};
bool setActiveDestination();
void resetActiveDestination();
virtual void setState(unsigned char newState) { state = newState; };
void resetTask();
void landAt(Coords loc);
bool updateActivePath(bool looping);
void clearActivePath();
void pushActivePathFront(Coords newActivePathFront);
void pushActivePathBack(Coords newActivePathBack);
void popActivePathFront();
void triggerUpdate() { lastUpdateTime = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count(); }
unsigned long long getLastUpdateTime() { return lastUpdateTime; };
void goToDestination(string enrouteTask = "nil");
bool isDestinationReached(double threshold);
protected:
unsigned int ID;
map<string, Measure*> measures;
unsigned int taskCheckCounter = 0;
/********** Base data **********/
bool controlled = false;
string name = "undefined";
string unitName = "undefined";
string groupName = "undefined";
bool alive = true;
bool human = false;
unsigned int country = NULL;
/********** Flight data **********/
Coords position = Coords(NULL);
double speed = NULL;
double heading = NULL;
/********** Mission data **********/
unsigned short fuel = 0;
double initialFuel = 0; // Used internally to detect refueling completed
vector<DataTypes::Ammo> ammo;
vector<DataTypes::Contact> contacts;
bool hasTask = false;
unsigned char coalition;
/********** Formation data **********/
unsigned int leaderID = NULL;
Offset formationOffset = Offset(NULL);
/********** Task data **********/
string task = "";
double desiredSpeed = 0;
double desiredAltitude = 0;
bool desiredSpeedType = 1;
bool desiredAltitudeType = 1;
list<Coords> activePath;
Coords activeDestination = Coords(NULL);
unsigned int targetID = NULL;
Coords targetPosition = Coords(NULL);
bool isTanker = false;
bool isAWACS = false;
bool onOff = true;
bool followRoads = false;
/********** Options data **********/
unsigned char ROE = ROE::OPEN_FIRE_WEAPON_FREE;
unsigned char reactionToThreat = ReactionToThreat::EVADE_FIRE;
unsigned char emissionsCountermeasures = EmissionCountermeasure::DEFEND;
Options::TACAN TACAN;
Options::Radio radio;
Options::GeneralSettings generalSettings;
bool EPLRS = false;
/********** Data packet **********/
DataTypes::DataPacket dataPacket;
/********** State machine **********/
unsigned char state = State::NONE;
/********** Other **********/
unsigned long long lastUpdateTime = 0;
Coords oldPosition = Coords(0); // Used to approximate speed
/********** Functions **********/
string getTargetName();
string getLeaderName();
bool isTargetAlive();
bool isLeaderAlive();
virtual void AIloop() = 0;
bool isDestinationReached(double threshold);
bool setActiveDestination();
bool updateActivePath(bool looping);
void goToDestination(string enrouteTask = "nil");
void resetTask();
bool checkTaskFailed();
void resetTaskFailedCounter();
void triggerUpdate(unsigned char datumIndex);
/********** Setters **********/
virtual void setCategory(string newValue) { updateValue(category, newValue, DataIndex::category); }
virtual void setAlive(bool newValue) { updateValue(alive, newValue, DataIndex::alive); }
virtual void setHuman(bool newValue) { updateValue(human, newValue, DataIndex::human); }
virtual void setControlled(bool newValue) { updateValue(controlled, newValue, DataIndex::controlled); }
virtual void setCoalition(unsigned char newValue) { updateValue(coalition, newValue, DataIndex::coalition); }
virtual void setCountry(unsigned int newValue) { updateValue(country, newValue, DataIndex::country); }
virtual void setName(string newValue) { updateValue(name, newValue, DataIndex::name); }
virtual void setUnitName(string newValue) { updateValue(unitName, newValue, DataIndex::unitName); }
virtual void setGroupName(string newValue) { updateValue(groupName, newValue, DataIndex::groupName); }
virtual void setState(unsigned char newValue) { updateValue(state, newValue, DataIndex::state); };
virtual void setTask(string newValue) { updateValue(task, newValue, DataIndex::task); }
virtual void setHasTask(bool newValue) { updateValue(hasTask, newValue, DataIndex::hasTask); }
virtual void setPosition(Coords newValue) { updateValue(position, newValue, DataIndex::position); }
virtual void setSpeed(double newValue) { updateValue(speed, newValue, DataIndex::speed); }
virtual void setHeading(double newValue) { updateValue(heading, newValue, DataIndex::heading); }
virtual void setIsTanker(bool newValue);
virtual void setIsAWACS(bool newValue);
virtual void setOnOff(bool newValue) { updateValue(onOff, newValue, DataIndex::onOff); };
virtual void setFollowRoads(bool newValue) { updateValue(followRoads, newValue, DataIndex::followRoads); };
virtual void setFuel(unsigned short newValue) { updateValue(fuel, newValue, DataIndex::fuel); }
virtual void setDesiredSpeed(double newValue);
virtual void setDesiredSpeedType(string newValue);
virtual void setDesiredAltitude(double newValue);
virtual void setDesiredAltitudeType(string newValue);
virtual void setLeaderID(unsigned int newValue) { updateValue(leaderID, newValue, DataIndex::leaderID); }
virtual void setFormationOffset(Offset formationOffset);
virtual void setTargetID(unsigned int newValue) { updateValue(targetID, newValue, DataIndex::targetID); }
virtual void setTargetPosition(Coords newValue) { updateValue(targetPosition, newValue, DataIndex::targetPosition); }
virtual void setROE(unsigned char newValue, bool force = false);
virtual void setReactionToThreat(unsigned char newValue, bool force = false);
virtual void setEmissionsCountermeasures(unsigned char newValue, bool force = false);
virtual void setTACAN(DataTypes::TACAN newValue, bool force = false);
virtual void setRadio(DataTypes::Radio newValue, bool force = false);
virtual void setGeneralSettings(DataTypes::GeneralSettings newValue, bool force = false);
virtual void setAmmo(vector<DataTypes::Ammo> newAmmo) { ammo = newAmmo; }
virtual void setContacts(vector<DataTypes::Contact> newContacts) { contacts = newContacts; }
virtual void setActivePath(list<Coords> newValue);
/********** Getters **********/
virtual string getCategory() { return category; };
virtual bool getAlive() { return alive; }
virtual bool getHuman() { return human; }
virtual bool getControlled() { return controlled; }
virtual unsigned int getCoalition() { return coalition; }
virtual unsigned int getCountry() { return country; }
virtual string getName() { return name; }
virtual string getUnitName() { return unitName; }
virtual string getGroupName() { return groupName; }
virtual unsigned char getState() { return state; }
virtual string getTask() { return task; }
virtual bool getHasTask() { return hasTask; }
virtual Coords getPosition() { return position; }
virtual double getSpeed() { return speed; }
virtual double getHeading() { return heading; }
virtual bool getIsTanker() { return isTanker; }
virtual bool getIsAWACS() { return isAWACS; }
virtual bool getOnOff() { return onOff; };
virtual bool getFollowRoads() { return followRoads; };
virtual double getFuel() { return fuel; }
virtual double getDesiredSpeed() { return desiredSpeed; };
virtual bool getDesiredSpeedType() { return desiredSpeedType; };
virtual double getDesiredAltitude() { return desiredAltitude; };
virtual bool getDesiredAltitudeType() { return desiredAltitudeType; };
virtual unsigned int getLeaderID() { return leaderID; }
virtual Offset getFormationoffset() { return formationOffset; }
virtual unsigned int getTargetID() { return targetID; }
virtual Coords getTargetPosition() { return targetPosition; }
virtual unsigned char getROE() { return ROE; }
virtual unsigned char getReactionToThreat() { return reactionToThreat; }
virtual unsigned char getEmissionsCountermeasures() { return emissionsCountermeasures; };
virtual DataTypes::TACAN getTACAN() { return TACAN; }
virtual DataTypes::Radio getRadio() { return radio; }
virtual DataTypes::GeneralSettings getGeneralSettings() { return generalSettings; }
virtual vector<DataTypes::Ammo> getAmmo() { return ammo; }
virtual vector<DataTypes::Contact> getTargets() { return contacts; }
virtual list<Coords> getActivePath() { return activePath; }
protected:
unsigned int ID;
string category;
bool alive = true;
bool human = false;
bool controlled = false;
unsigned char coalition;
unsigned int country = NULL;
string name = "undefined";
string unitName = "undefined";
string groupName = "undefined";
unsigned char state = State::NONE;
string task = "";
bool hasTask = false;
Coords position = Coords(NULL);
double speed = NULL;
double heading = NULL;
bool isTanker = false;
bool isAWACS = false;
bool onOff = true;
bool followRoads = false;
unsigned short fuel = 0;
double desiredSpeed = 0;
bool desiredSpeedType = 1;
double desiredAltitude = 0;
bool desiredAltitudeType = 1;
unsigned int leaderID = NULL;
Offset formationOffset = Offset(NULL);
unsigned int targetID = NULL;
Coords targetPosition = Coords(NULL);
unsigned char ROE = ROE::OPEN_FIRE_WEAPON_FREE;
unsigned char reactionToThreat = ReactionToThreat::EVADE_FIRE;
unsigned char emissionsCountermeasures = EmissionCountermeasure::DEFEND;
DataTypes::TACAN TACAN;
DataTypes::Radio radio;
DataTypes::GeneralSettings generalSettings;
vector<DataTypes::Ammo> ammo;
vector<DataTypes::Contact> contacts;
list<Coords> activePath;
/********** Other **********/
unsigned int taskCheckCounter = 0;
Coords activeDestination = Coords(NULL);
double initialFuel = 0;
Coords oldPosition = Coords(0);
map<unsigned char, unsigned long long> updateTimeMap;
/********** Private methods **********/
virtual void AIloop() = 0;
/********** Template methods **********/
template <typename T>
void updateValue(T& value, T& newValue)
void updateValue(T& value, T& newValue, unsigned char datumIndex)
{
if (newValue != value)
{
triggerUpdate();
triggerUpdate(datumIndex);
*(&value) = newValue;
}
}
template <typename T>
void appendNumeric(stringstream& ss, const unsigned char& datumIndex, T& datumValue) {
ss.write((const char*)&datumIndex, sizeof(unsigned char));
ss.write((const char*)&datumValue, sizeof(T));
}
void appendString(stringstream& ss, const unsigned char& datumIndex, string& datumValue) {
const unsigned short size = datumValue.size();
ss.write((const char*)&datumIndex, sizeof(unsigned char));
ss.write((const char*)&size, sizeof(unsigned short));
ss << datumValue;
}
template <typename T>
void appendVector(stringstream& ss, const unsigned char& datumIndex, vector<T>& datumValue) {
const unsigned short size = datumValue.size();
ss.write((const char*)&datumIndex, sizeof(unsigned char));
ss.write((const char*)&size, sizeof(unsigned short));
ss.write((const char*)&datumValue, size * sizeof(T));
}
template <typename T>
void appendList(stringstream& ss, const unsigned char& datumIndex, list<T>& datumValue) {
const unsigned short size = datumValue.size();
ss.write((const char*)&datumIndex, sizeof(unsigned char));
ss.write((const char*)&size, sizeof(unsigned short));
for (auto el: datumValue)
ss.write((const char*)&el, sizeof(T));
}
};

View File

@@ -5,9 +5,6 @@ class Weapon : public Unit
{
public:
Weapon(json::value json, unsigned int ID);
virtual string getCategory() = 0;
protected:
/* Weapons are not controllable and have no AIloop */
virtual void AIloop() {};
@@ -17,14 +14,10 @@ class Missile : public Weapon
{
public:
Missile(json::value json, unsigned int ID);
virtual string getCategory() { return "Missile"; };
};
class Bomb : public Weapon
{
public:
Bomb(json::value json, unsigned int ID);
virtual string getCategory() { return "Bomb"; };
};

View File

@@ -17,10 +17,10 @@ Aircraft::Aircraft(json::value json, unsigned int ID) : AirUnit(json, ID)
{
log("New Aircraft created with ID: " + to_string(ID));
double desiredSpeed = knotsToMs(300);
double desiredAltitude = ftToM(20000);
setDesiredSpeed(desiredSpeed);
setDesiredAltitude(desiredAltitude);
setCategory("Aircraft");
setDesiredSpeed(knotsToMs(300));
setDesiredAltitude(ftToM(20000));
};
void Aircraft::changeSpeed(string change)

View File

@@ -17,8 +17,8 @@ GroundUnit::GroundUnit(json::value json, unsigned int ID) : Unit(json, ID)
{
log("New Ground Unit created with ID: " + to_string(ID));
double desiredSpeed = 10;
setDesiredSpeed(desiredSpeed);
setCategory("GroundUnit");
setDesiredSpeed(10);
};
void GroundUnit::setState(unsigned char newState)

View File

@@ -17,10 +17,9 @@ Helicopter::Helicopter(json::value json, unsigned int ID) : AirUnit(json, ID)
{
log("New Helicopter created with ID: " + to_string(ID));
double desiredSpeed = knotsToMs(100);
double desiredAltitude = ftToM(5000);
setDesiredSpeed(desiredSpeed);
setDesiredAltitude(desiredAltitude);
setCategory("Helicopter");
setDesiredSpeed(knotsToMs(100));
setDesiredAltitude(ftToM(5000));
};
void Helicopter::changeSpeed(string change)

View File

@@ -17,8 +17,8 @@ NavyUnit::NavyUnit(json::value json, unsigned int ID) : Unit(json, ID)
{
log("New Navy Unit created with ID: " + to_string(ID));
double desiredSpeed = 10;
setDesiredSpeed(desiredSpeed);
setCategory("NavyUnit");
setDesiredSpeed(10);
};
void NavyUnit::AIloop()

View File

@@ -288,7 +288,7 @@ void Scheduler::handleRequest(string key, json::value value)
unit->setIsAWACS(value[L"isAWACS"].as_bool());
/* TACAN Options */
Options::TACAN TACAN;
DataTypes::TACAN TACAN;
TACAN.isOn = value[L"TACAN"][L"isOn"].as_bool();
TACAN.channel = static_cast<unsigned char>(value[L"TACAN"][L"channel"].as_number().to_uint32());
TACAN.XY = to_string(value[L"TACAN"][L"XY"]).at(0);

View File

@@ -16,20 +16,20 @@ extern Scheduler* scheduler;
extern UnitsManager* unitsManager;
// TODO: Make dedicated file
bool operator==(const Options::TACAN& lhs, const Options::TACAN& rhs)
bool operator==(const DataTypes::TACAN& lhs, const DataTypes::TACAN& rhs)
{
return lhs.isOn == rhs.isOn && lhs.channel == rhs.channel && lhs.XY == rhs.XY && lhs.callsign == rhs.callsign;
}
bool operator==(const Options::Radio& lhs, const Options::Radio& rhs)
bool operator==(const DataTypes::Radio& lhs, const DataTypes::Radio& rhs)
{
return lhs.frequency == rhs.frequency && lhs.callsign == rhs.callsign && lhs.callsignNumber == rhs.callsignNumber;
}
bool operator==(const Options::GeneralSettings& lhs, const Options::GeneralSettings& rhs)
bool operator==(const DataTypes::GeneralSettings& lhs, const DataTypes::GeneralSettings& rhs)
{
return lhs.prohibitAA == rhs.prohibitAA && lhs.prohibitAfterburner == rhs.prohibitAfterburner && lhs.prohibitAG == rhs.prohibitAG &&
lhs.prohibitAirWpn == rhs.prohibitAirWpn && lhs.prohibitJettison == rhs.prohibitJettison;
lhs.prohibitAirWpn == rhs.prohibitAirWpn && lhs.prohibitJettison == rhs.prohibitJettison;
}
Unit::Unit(json::value json, unsigned int ID) :
@@ -87,7 +87,6 @@ void Unit::setDefaults(bool force)
strcpy_s(TACAN.callsign, 4, "TKR");
setTACAN(TACAN, force);
setRadio(radio, force);
setEPLRS(EPLRS, force);
setGeneralSettings(generalSettings, force);
}
@@ -101,7 +100,7 @@ void Unit::runAILoop() {
const bool isUnitAlive = getAlive();
const bool isUnitLeaderOfAGroupWithOtherUnits = unitsManager->isUnitInGroup(this) && unitsManager->isUnitGroupLeader(this);
if (!(isUnitAlive || isUnitLeaderOfAGroupWithOtherUnits)) return;
if (checkTaskFailed() && state != State::IDLE && State::LAND)
setState(State::IDLE);
@@ -113,14 +112,14 @@ void Unit::updateExportData(json::value json, double dt)
Coords newPosition = Coords(NULL);
double newHeading = 0;
double newSpeed = 0;
if (json.has_object_field(L"LatLongAlt"))
{
setPosition({
json[L"LatLongAlt"][L"Lat"].as_number().to_double(),
json[L"LatLongAlt"][L"Long"].as_number().to_double(),
json[L"LatLongAlt"][L"Alt"].as_number().to_double()
});
});
}
if (json.has_number_field(L"Heading"))
setHeading(json[L"Heading"].as_number().to_double());
@@ -133,7 +132,7 @@ void Unit::updateExportData(json::value json, double dt)
if (dt > 0)
setSpeed(getSpeed() * 0.95 + (dist / dt) * 0.05);
}
oldPosition = position;
}
@@ -180,120 +179,67 @@ void Unit::updateMissionData(json::value json)
setHasTask(json[L"hasTask"].as_bool());
}
unsigned int Unit::getDataPacket(char* &data)
void Unit::getData(stringstream& ss, unsigned long long time, bool refresh)
{
/* Reserve data for:
1) DataPacket;
2) Active path;
3) Ammo vector;
4) Contacts vector;
*/
data = (char*)malloc(sizeof(DataTypes::DataPacket) +
activePath.size() * sizeof(Coords) +
ammo.size() * sizeof(Coords) +
contacts.size() * sizeof(Coords));
unsigned int offset = 0;
/* Prepare the data packet and copy it to memory */
unsigned int bitmask = 0;
bitmask |= alive << 0;
bitmask |= human << 1;
bitmask |= controlled << 2;
bitmask |= hasTask << 3;
bitmask |= desiredAltitudeType << 16;
bitmask |= desiredSpeedType << 17;
bitmask |= isTanker << 18;
bitmask |= isAWACS << 19;
bitmask |= onOff << 20;
bitmask |= followRoads << 21;
bitmask |= EPLRS << 22;
bitmask |= generalSettings.prohibitAA << 23;
bitmask |= generalSettings.prohibitAfterburner << 24;
bitmask |= generalSettings.prohibitAG << 25;
bitmask |= generalSettings.prohibitAirWpn << 26;
bitmask |= generalSettings.prohibitJettison << 27;
/* If the unit is in a group, get the update data from the group leader and only replace the position: speed and heading */
//if (unitsManager->isUnitInGroup(this) && !unitsManager->isUnitGroupLeader(this)) {
// DataTypes::DataPacket* p = (DataTypes::DataPacket*)data;
// p->position = position;
// p->speed = speed;
// p->heading = heading;
//}
DataTypes::DataPacket dataPacket{
ID,
bitmask,
position,
speed,
heading,
fuel,
desiredSpeed,
desiredAltitude,
leaderID,
targetID,
targetPosition,
state,
ROE,
reactionToThreat,
emissionsCountermeasures,
coalition,
TACAN,
radio,
activePath.size(),
ammo.size(),
contacts.size(),
task.size()
};
const unsigned char startOfData = DataIndex::startOfData;
const unsigned char endOfData = DataIndex::endOfData;
memcpy(data + offset, &dataPacket, sizeof(dataPacket));
offset += sizeof(dataPacket);
/* Prepare the path vector and copy it to memory */
for (const Coords& c : activePath) {
memcpy(data + offset, &c, sizeof(Coords));
offset += sizeof(Coords);
ss.write((const char*)&ID, sizeof(ID));
ss.write((const char*)&startOfData, sizeof(startOfData));
for (auto d : updateTimeMap) {
if (d.second > time) {
switch (d.first) {
case DataIndex::category: appendString(ss, d.first, category); break;
case DataIndex::alive: appendNumeric(ss, d.first, alive); break;
case DataIndex::human: appendNumeric(ss, d.first, human); break;
case DataIndex::controlled: appendNumeric(ss, d.first, controlled); break;
case DataIndex::coalition: appendNumeric(ss, d.first, coalition); break;
case DataIndex::country: appendNumeric(ss, d.first, country); break;
case DataIndex::name: appendString(ss, d.first, name); break;
case DataIndex::unitName: appendString(ss, d.first, unitName); break;
case DataIndex::groupName: appendString(ss, d.first, groupName); break;
case DataIndex::state: appendNumeric(ss, d.first, state); break;
case DataIndex::task: appendString(ss, d.first, task); break;
case DataIndex::hasTask: appendNumeric(ss, d.first, hasTask); break;
case DataIndex::position: appendNumeric(ss, d.first, position); break;
case DataIndex::speed: appendNumeric(ss, d.first, speed); break;
case DataIndex::heading: appendNumeric(ss, d.first, heading); break;
case DataIndex::isTanker: appendNumeric(ss, d.first, isTanker); break;
case DataIndex::isAWACS: appendNumeric(ss, d.first, isAWACS); break;
case DataIndex::onOff: appendNumeric(ss, d.first, onOff); break;
case DataIndex::followRoads: appendNumeric(ss, d.first, followRoads); break;
case DataIndex::fuel: appendNumeric(ss, d.first, fuel); break;
case DataIndex::desiredSpeed: appendNumeric(ss, d.first, desiredSpeed); break;
case DataIndex::desiredSpeedType: appendNumeric(ss, d.first, desiredSpeedType); break;
case DataIndex::desiredAltitude: appendNumeric(ss, d.first, desiredAltitude); break;
case DataIndex::desiredAltitudeType: appendNumeric(ss, d.first, desiredAltitudeType); break;
case DataIndex::leaderID: appendNumeric(ss, d.first, leaderID); break;
case DataIndex::formationOffset: appendNumeric(ss, d.first, formationOffset); break;
case DataIndex::targetID: appendNumeric(ss, d.first, targetID); break;
case DataIndex::targetPosition: appendNumeric(ss, d.first, targetPosition); break;
case DataIndex::ROE: appendNumeric(ss, d.first, ROE); break;
case DataIndex::reactionToThreat: appendNumeric(ss, d.first, reactionToThreat); break;
case DataIndex::emissionsCountermeasures: appendNumeric(ss, d.first, emissionsCountermeasures); break;
case DataIndex::TACAN: appendNumeric(ss, d.first, TACAN); break;
case DataIndex::radio: appendNumeric(ss, d.first, radio); break;
case DataIndex::generalSettings: appendNumeric(ss, d.first, generalSettings); break;
case DataIndex::ammo: appendVector(ss, d.first, ammo); break;
case DataIndex::contacts: appendVector(ss, d.first, contacts); break;
case DataIndex::activePath: appendList(ss, d.first, activePath); break;
}
}
}
/* Copy the ammo vector to memory */
memcpy(data + offset, &ammo, ammo.size() * sizeof(DataTypes::Ammo));
offset += ammo.size() * sizeof(DataTypes::Ammo);
/* Copy the contacts vector to memory */
memcpy(data + offset, &contacts, contacts.size() * sizeof(DataTypes::Contact));
offset += contacts.size() * sizeof(DataTypes::Contact);
return offset;
}
void Unit::getData(stringstream &ss, unsigned long long time, bool refresh)
{
if (time > lastUpdateTime && !refresh) return;
char* data;
unsigned int size = getDataPacket(data);
/* Prepare the data packet and copy it to memory */
/* If the unit is in a group, get the update data from the group leader and only replace the position, speed and heading */
if (unitsManager->isUnitInGroup(this) && !unitsManager->isUnitGroupLeader(this)) {
DataTypes::DataPacket* p = (DataTypes::DataPacket*)data;
p->position = position;
p->speed = speed;
p->heading = heading;
}
ss.write(data, size);
ss << task;
unsigned short nameLength = name.length();
unsigned short unitNameLength = unitName.length();
unsigned short groupNameLength = groupName.length();
unsigned short categoryLength = getCategory().length();
ss.write((char*)&nameLength, sizeof(nameLength));
ss.write((char*)&unitNameLength, sizeof(unitNameLength));
ss.write((char*)&groupNameLength, sizeof(groupNameLength));
ss.write((char*)&categoryLength, sizeof(categoryLength));
ss << name;
ss << unitName;
ss << groupName;
ss << getCategory();
delete data;
ss.write((const char*)&endOfData, sizeof(endOfData));
}
void Unit::setActivePath(list<Coords> newPath)
@@ -393,17 +339,17 @@ void Unit::setFormationOffset(Offset newFormationOffset)
formationOffset = newFormationOffset;
resetTask();
triggerUpdate();
triggerUpdate(DataIndex::formationOffset);
}
void Unit::setROE(unsigned char newROE, bool force)
void Unit::setROE(unsigned char newROE, bool force)
{
if (ROE != newROE || force) {
ROE = newROE;
Command* command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::ROE, static_cast<unsigned int>(ROE)));
scheduler->appendCommand(command);
triggerUpdate();
triggerUpdate(DataIndex::ROE);
}
}
@@ -415,7 +361,7 @@ void Unit::setReactionToThreat(unsigned char newReactionToThreat, bool force)
Command* command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::REACTION_ON_THREAT, static_cast<unsigned int>(reactionToThreat)));
scheduler->appendCommand(command);
triggerUpdate();
triggerUpdate(DataIndex::reactionToThreat);
}
}
@@ -465,39 +411,38 @@ void Unit::setEmissionsCountermeasures(unsigned char newEmissionsCountermeasures
command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::ECM_USING, ECMEnum));
scheduler->appendCommand(command);
triggerUpdate();
triggerUpdate(DataIndex::emissionsCountermeasures);
}
}
void Unit::landAt(Coords loc)
void Unit::landAt(Coords loc)
{
clearActivePath();
pushActivePathBack(loc);
setState(State::LAND);
}
void Unit::setIsTanker(bool newIsTanker)
{
void Unit::setIsTanker(bool newIsTanker)
{
if (isTanker != newIsTanker) {
isTanker = newIsTanker;
resetTask();
triggerUpdate();
triggerUpdate(DataIndex::isTanker);
}
}
void Unit::setIsAWACS(bool newIsAWACS)
{
{
if (isAWACS != newIsAWACS) {
isAWACS = newIsAWACS;
resetTask();
setEPLRS(isAWACS);
triggerUpdate();
triggerUpdate(DataIndex::isAWACS);
}
}
void Unit::setTACAN(Options::TACAN newTACAN, bool force)
void Unit::setTACAN(DataTypes::TACAN newTACAN, bool force)
{
if (TACAN != newTACAN || force)
{
@@ -528,11 +473,11 @@ void Unit::setTACAN(Options::TACAN newTACAN, bool force)
scheduler->appendCommand(command);
}
triggerUpdate();
triggerUpdate(DataIndex::TACAN);
}
}
void Unit::setRadio(Options::Radio newRadio, bool force)
void Unit::setRadio(DataTypes::Radio newRadio, bool force)
{
if (radio != newRadio || force)
{
@@ -564,30 +509,11 @@ void Unit::setRadio(Options::Radio newRadio, bool force)
command = dynamic_cast<Command*>(new SetCommand(groupName, commandSS.str()));
scheduler->appendCommand(command);
triggerUpdate();
triggerUpdate(DataIndex::radio);
}
}
void Unit::setEPLRS(bool newEPLRS, bool force)
{
//addMeasure("EPLRS", json::value(newEPLRS));
//
//if (EPLRS != newEPLRS || force) {
// EPLRS = newEPLRS;
//
// std::ostringstream commandSS;
// commandSS << "{"
// << "id = 'EPLRS',"
// << "params = {"
// << "value = " << (EPLRS ? "true" : "false") << ", "
// << "}"
// << "}";
// Command* command = dynamic_cast<Command*>(new SetCommand(ID, commandSS.str()));
// scheduler->appendCommand(command);
//}
}
void Unit::setGeneralSettings(Options::GeneralSettings newGeneralSettings, bool force)
void Unit::setGeneralSettings(DataTypes::GeneralSettings newGeneralSettings, bool force)
{
if (generalSettings != newGeneralSettings)
{
@@ -605,22 +531,22 @@ void Unit::setGeneralSettings(Options::GeneralSettings newGeneralSettings, bool
command = dynamic_cast<Command*>(new SetOption(groupName, SetCommandType::ENGAGE_AIR_WEAPONS, !generalSettings.prohibitAirWpn));
scheduler->appendCommand(command);
triggerUpdate();
triggerUpdate(DataIndex::generalSettings);
}
}
void Unit::setDesiredSpeed(double newDesiredSpeed)
void Unit::setDesiredSpeed(double newDesiredSpeed)
{
desiredSpeed = newDesiredSpeed;
desiredSpeed = newDesiredSpeed;
if (state == State::IDLE)
resetTask();
else
goToDestination(); /* Send the command to reach the destination */
triggerUpdate();
triggerUpdate(DataIndex::desiredSpeed);
}
void Unit::setDesiredAltitude(double newDesiredAltitude)
void Unit::setDesiredAltitude(double newDesiredAltitude)
{
desiredAltitude = newDesiredAltitude;
if (state == State::IDLE)
@@ -628,10 +554,10 @@ void Unit::setDesiredAltitude(double newDesiredAltitude)
else
goToDestination(); /* Send the command to reach the destination */
triggerUpdate();
triggerUpdate(DataIndex::desiredAltitude);
}
void Unit::setDesiredSpeedType(string newDesiredSpeedType)
void Unit::setDesiredSpeedType(string newDesiredSpeedType)
{
desiredSpeedType = newDesiredSpeedType.compare("GS") == 0;
if (state == State::IDLE)
@@ -639,10 +565,10 @@ void Unit::setDesiredSpeedType(string newDesiredSpeedType)
else
goToDestination(); /* Send the command to reach the destination */
triggerUpdate();
triggerUpdate(DataIndex::desiredSpeedType);
}
void Unit::setDesiredAltitudeType(string newDesiredAltitudeType)
void Unit::setDesiredAltitudeType(string newDesiredAltitudeType)
{
desiredAltitudeType = newDesiredAltitudeType.compare("AGL") == 0;
if (state == State::IDLE)
@@ -650,14 +576,14 @@ void Unit::setDesiredAltitudeType(string newDesiredAltitudeType)
else
goToDestination(); /* Send the command to reach the destination */
triggerUpdate();
triggerUpdate(DataIndex::desiredAltitudeType);
}
void Unit::goToDestination(string enrouteTask)
{
if (activeDestination != NULL)
{
Command* command = dynamic_cast<Command*>(new Move(groupName, activeDestination, getDesiredSpeed(), getDesiredSpeedType()? "GS": "CAS", getDesiredAltitude(), getDesiredAltitudeType()? "AGL" : "ASL", enrouteTask, getCategory()));
Command* command = dynamic_cast<Command*>(new Move(groupName, activeDestination, getDesiredSpeed(), getDesiredSpeedType() ? "GS" : "CAS", getDesiredAltitude(), getDesiredAltitudeType() ? "AGL" : "ASL", enrouteTask, getCategory()));
scheduler->appendCommand(command);
setHasTask(true);
}
@@ -668,7 +594,7 @@ bool Unit::isDestinationReached(double threshold)
if (activeDestination != NULL)
{
/* Check if any unit in the group has reached the point */
for (auto const& p: unitsManager->getGroupMembers(groupName))
for (auto const& p : unitsManager->getGroupMembers(groupName))
{
double dist = 0;
Geodesic::WGS84().Inverse(p->getPosition().lat, p->getPosition().lng, activeDestination.lat, activeDestination.lng, dist);
@@ -694,7 +620,7 @@ bool Unit::setActiveDestination()
activeDestination = activePath.front();
log(unitName + " active destination set to queue front");
triggerUpdate();
triggerUpdate(DataIndex::activePath);
return true;
}
else
@@ -702,7 +628,7 @@ bool Unit::setActiveDestination()
activeDestination = Coords(0);
log(unitName + " active destination set to NULL");
triggerUpdate();
triggerUpdate(DataIndex::activePath);
return false;
}
}
@@ -723,9 +649,9 @@ bool Unit::updateActivePath(bool looping)
}
}
bool Unit::checkTaskFailed()
bool Unit::checkTaskFailed()
{
if (getHasTask())
if (getHasTask())
return false;
else {
if (taskCheckCounter > 0)
@@ -737,3 +663,7 @@ bool Unit::checkTaskFailed()
void Unit::resetTaskFailedCounter() {
taskCheckCounter = TASK_CHECK_INIT_VALUE;
}
void Unit::triggerUpdate(unsigned char datumIndex) {
updateTimeMap[datumIndex] = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
}

View File

@@ -22,10 +22,12 @@ Weapon::Weapon(json::value json, unsigned int ID) : Unit(json, ID)
Missile::Missile(json::value json, unsigned int ID) : Weapon(json, ID)
{
log("New Missile created with ID: " + to_string(ID));
setCategory("Missile");
};
/* Bomb */
Bomb::Bomb(json::value json, unsigned int ID) : Weapon(json, ID)
{
log("New Bomb created with ID: " + to_string(ID));
setCategory("Bomb");
};