Added new method for handling data

This commit is contained in:
Pax1601
2023-06-21 20:05:41 +02:00
parent 61d6d9f16c
commit 9d0e2239e4
16 changed files with 137 additions and 93 deletions

View File

@@ -5,7 +5,7 @@
#include "logger.h"
namespace CommandPriority {
enum CommandPriorities { LOW, MEDIUM, HIGH };
enum CommandPriorities { LOW, MEDIUM, HIGH, IMMEDIATE };
};
namespace SetCommandType {
@@ -151,7 +151,7 @@ public:
location(location),
immediate(immediate)
{
priority = CommandPriority::LOW;
priority = immediate? CommandPriority::IMMEDIATE: CommandPriority::LOW;
};
virtual wstring getString(lua_State* L);
virtual int getLoad() { return 100 * !immediate; }
@@ -175,7 +175,7 @@ public:
airbaseName(airbaseName),
immediate(immediate)
{
priority = CommandPriority::LOW;
priority = immediate ? CommandPriority::IMMEDIATE : CommandPriority::LOW;
};
virtual wstring getString(lua_State* L);
virtual int getLoad() { return 100 * !immediate; }

View File

@@ -15,6 +15,8 @@ public:
void start(lua_State* L);
void stop(lua_State* L);
json::value& getUpdateJson() { return updateJson; }
json::value& getRefreshJson() { return refreshJson; }
private:
std::thread* serverThread;
@@ -27,6 +29,8 @@ private:
void task();
atomic<bool> runListener;
json::value updateJson;
json::value refreshJson;
wstring password = L"";
};

View File

@@ -65,7 +65,7 @@ public:
void setDefaults(bool force = false);
int getID() { return ID; }
void runAILoop();
void updateExportData(json::value json);
void updateExportData(json::value json, double dt = 0);
void updateMissionData(json::value json);
json::value getData(long long time, bool getAll = false);
virtual wstring getCategory() { return L"No category"; };

View File

@@ -10,16 +10,18 @@ public:
UnitsManager(lua_State* L);
~UnitsManager();
map<int, Unit*>& getUnits() { return units; };
Unit* getUnit(int ID);
bool isUnitInGroup(Unit* unit);
bool isUnitGroupLeader(Unit* unit);
Unit* getGroupLeader(int ID);
Unit* getGroupLeader(Unit* unit);
vector<Unit*> getGroupMembers(wstring groupName);
void updateExportData(lua_State* L);
void updateExportData(lua_State* L, double dt = 0);
void updateMissionData(json::value missionData);
void runAILoop();
void getData(json::value& answer, long long time);
void getUnitData(json::value& answer, long long time);
void appendUnitData(int ID, json::value& answer, long long time);
void deleteUnit(int ID, bool explosion);
void acquireControl(int ID);

View File

@@ -6,6 +6,8 @@
#include "scheduler.h"
#include "scriptLoader.h"
#include "luatools.h"
#include <chrono>
using namespace std::chrono;
auto before = std::chrono::system_clock::now();
UnitsManager* unitsManager = nullptr;
@@ -17,6 +19,10 @@ json::value mission;
mutex mutexLock;
bool initialized = false;
string sessionHash;
int lastUpdateIndex = 0;
int frameCounter = 0;
double frameRate = 30;
long long lastUpdateTime = 0;
/* Called when DCS simulation stops. All singleton instances are deleted. */
extern "C" DllExport int coreDeinit(lua_State* L)
@@ -61,21 +67,44 @@ extern "C" DllExport int coreFrame(lua_State* L)
/* Lock for thread safety */
lock_guard<mutex> guard(mutexLock);
frameCounter++;
const std::chrono::duration<double> duration = std::chrono::system_clock::now() - before;
/* TODO make intervals editable */
if (duration.count() > UPDATE_TIME_INTERVAL)
if (unitsManager != nullptr) {
// TODO put in a function
vector<int> IDs;
for (auto iter = unitsManager->getUnits().begin(); iter != unitsManager->getUnits().end(); ++iter)
IDs.push_back(iter->first);
int updateChunk = 20;
int finalUpdateIndex = lastUpdateIndex + updateChunk;
/* Get all the new data (with some margin) */
while (lastUpdateIndex < unitsManager->getUnits().size() && lastUpdateIndex <= finalUpdateIndex)
unitsManager->appendUnitData(IDs[lastUpdateIndex++], server->getUpdateJson(), lastUpdateTime - 1000);
}
if (duration.count() > UPDATE_TIME_INTERVAL && lastUpdateIndex == unitsManager->getUnits().size())
{
milliseconds ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
lastUpdateTime = ms.count();
frameRate = frameCounter / duration.count();
frameCounter = 0;
if (unitsManager != nullptr)
{
unitsManager->updateExportData(L);
unitsManager->runAILoop();
}
unitsManager->updateExportData(L, duration.count());
before = std::chrono::system_clock::now();
/* Restart the update counter */
lastUpdateIndex = 0;
}
if (scheduler != nullptr)
scheduler->execute(L);
if (duration.count() > UPDATE_TIME_INTERVAL && unitsManager != nullptr)
unitsManager->runAILoop();
return(0);
}

View File

@@ -32,7 +32,7 @@ void Scheduler::execute(lua_State* L)
return;
}
int priority = CommandPriority::HIGH;
int priority = CommandPriority::IMMEDIATE;
while (priority >= CommandPriority::LOW)
{
for (auto command : commands)

View File

@@ -36,7 +36,8 @@ Server::Server(lua_State* L):
serverThread(nullptr),
runListener(true)
{
refreshJson = json::value::object();
updateJson = json::value::object();
}
void Server::start(lua_State* L)
@@ -93,7 +94,10 @@ void Server::handle_get(http_request request)
time = 0;
}
}
unitsManager->getData(answer, time);
if (time == 0)
unitsManager->getUnitData(answer, 0);
else
answer[L"units"] = updateJson;
}
else if (path[0] == LOGS_URI)
{

View File

@@ -92,31 +92,31 @@ void Unit::addMeasure(wstring key, json::value value)
}
void Unit::runAILoop() {
/* If the unit is alive and it is not a human, run the AI Loop that performs the requested commands and instructions (moving, attacking, etc) */
const bool isUnitControlledByOlympus = getControlled();
const bool isUnitAlive = getAlive();
const bool isUnitLeader = unitsManager->isUnitGroupLeader(this);
const bool isUnitLeaderOfAGroupWithOtherUnits = unitsManager->isUnitInGroup(this) && unitsManager->isUnitGroupLeader(this);
const bool isUnitHuman = getFlags()[L"Human"].as_bool();
/* If the unit is alive, controlled and it is not a human, run the AI Loop that performs the requested commands and instructions (moving, attacking, etc) */
if (!getControlled()) return;
if (!unitsManager->isUnitGroupLeader(this)) return;
if (getFlags()[L"Human"].as_bool()) return;
// Keep running the AI loop even if the unit is dead if it is the leader of a group which has other members in it
if (isUnitControlledByOlympus && (isUnitAlive || isUnitLeaderOfAGroupWithOtherUnits) && isUnitLeader && !isUnitHuman)
{
if (checkTaskFailed() && state != State::IDLE && State::LAND)
setState(State::IDLE);
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);
AIloop();
}
AIloop();
}
void Unit::updateExportData(json::value json)
void Unit::updateExportData(json::value json, double dt)
{
/* Compute speed (loGetWorldObjects does not provide speed, we compute it for better performance instead of relying on many lua calls) */
if (oldPosition != NULL)
{
double dist = 0;
Geodesic::WGS84().Inverse(latitude, longitude, oldPosition.lat, oldPosition.lng, dist);
setSpeed(getSpeed() * 0.95 + (dist / UPDATE_TIME_INTERVAL) * 0.05);
if (dt > 0)
setSpeed(getSpeed() * 0.95 + (dist / dt) * 0.05);
}
oldPosition = Coords(latitude, longitude, altitude);
@@ -160,7 +160,7 @@ void Unit::updateMissionData(json::value json)
setHasTask(json[L"hasTask"].as_bool());
}
json::value Unit::getData(long long time, bool sendAll)
json::value Unit::getData(long long time, bool getAll)
{
auto json = json::value::object();
@@ -178,7 +178,7 @@ json::value Unit::getData(long long time, bool sendAll)
if (json[L"baseData"].size() == 0)
json.erase(L"baseData");
if (alive || sendAll) {
if (alive || getAll) {
/********** Flight data **********/
json[L"flightData"] = json::value::object();
for (auto key : { L"latitude", L"longitude", L"altitude", L"speed", L"heading" })

View File

@@ -59,18 +59,11 @@ Unit* UnitsManager::getGroupLeader(Unit* unit)
if (unit != nullptr) {
wstring groupName = unit->getGroupName();
/* Get the unit IDs in order */
std::vector<int> keys;
for (auto const& p : units)
keys.push_back(p.first);
sort(keys.begin(), keys.end());
/* Find the first unit that has the same groupName */
for (auto const& tempID : keys)
for (auto const& p : units)
{
Unit* tempUnit = getUnit(tempID);
if (tempUnit != nullptr && tempUnit->getGroupName().compare(groupName) == 0)
return tempUnit;
if (p.second->getGroupName().compare(groupName) == 0)
return p.second;
}
}
return nullptr;
@@ -93,7 +86,7 @@ Unit* UnitsManager::getGroupLeader(int ID)
return getGroupLeader(unit);
}
void UnitsManager::updateExportData(lua_State* L)
void UnitsManager::updateExportData(lua_State* L, double dt)
{
map<int, json::value> unitJSONs = getAllUnits(L);
@@ -132,15 +125,13 @@ void UnitsManager::updateExportData(lua_State* L)
else {
/* Update the unit if present*/
if (units.count(ID) != 0)
units[ID]->updateExportData(p.second);
units[ID]->updateExportData(p.second, dt);
}
}
/* Set the units that are not present in the JSON as dead (probably have been destroyed) */
for (auto const& unit : units)
{
unit.second->setAlive(unitJSONs.find(unit.first) != unitJSONs.end());
}
}
void UnitsManager::updateMissionData(json::value missionData)
@@ -150,32 +141,38 @@ void UnitsManager::updateMissionData(json::value missionData)
{
int ID = p.first;
if (missionData.has_field(to_wstring(ID)))
{
p.second->updateMissionData(missionData[to_wstring(ID)]);
}
}
}
void UnitsManager::runAILoop() {
/* Run the AI Loop on all units */
for (auto const& unit : units)
{
unit.second->runAILoop();
}
}
void UnitsManager::getData(json::value& answer, long long time)
void UnitsManager::getUnitData(json::value& answer, long long time)
{
auto unitsJson = json::value::object();
for (auto const& p : units)
{
auto unitJson = p.second->getData(time);
if (unitJson.size() > 0)
unitsJson[to_wstring(p.first)] = p.second->getData(time);
unitsJson[to_wstring(p.first)] = unitJson;
}
answer[L"units"] = unitsJson;
}
void UnitsManager::appendUnitData(int ID, json::value& answer, long long time)
{
Unit* unit = getUnit(ID);
if (unit != nullptr) {
auto unitJson = unit->getData(time);
if (unitJson.size() > 0)
answer[to_wstring(ID)] = unitJson;
}
}
void UnitsManager::deleteUnit(int ID, bool explosion)
{
if (getUnit(ID) != nullptr)