Files
qt5-legatus-legacy/Lts/Services/ParticipantManagement/UasHandling/object_mission_plan.cpp
T
2026-08-13 18:33:10 +02:00

399 lines
14 KiB
C++
Executable File

/**
* The ObjectMissionPlan class represents a ObjectMissionPlan. It holds the data and offers some conversion methods.
* $Id$
* $HeadURL$
* $Author$
* Created by Steve Kemayou, ESZS, 2025-04-08
*/
#include "object_mission_plan.h"
#include <ngldb/dbtransaction.h>
namespace ParticipantManagement
{
namespace UasHandling
{
ObjectMissionPlan::ObjectMissionPlan(const std::shared_ptr<DdsHandler> &ddsHandler,
const std::shared_ptr<DatabaseInterface> &db,
const ParticipantManagement::MissionPlan & missionPlan,
QObject *parent)
: QObject(parent)
, m_ddsHandler(ddsHandler)
, m_db(db)
, m_missionplan(missionPlan)
, m_logger(getLogger("ObjectMissionPlan"))
{
DEBUG_LOG(m_logger)<<" - ctor ObjectMissionPlan: planId: "<<m_missionplan.id();
}
int32_t ObjectMissionPlan::id() const
{
return m_missionplan.id();
}
int32_t ObjectMissionPlan::participantId() const
{
return m_missionplan.participantId();
}
Database::PpmMissionPlan ObjectMissionPlan::toDbMissionPlan(const ModifyMissionPlanRequest &mp)
{
Database::PpmMissionPlan result;
result.id = mp.id();
result.name = QString::fromStdString(mp.name());
result.missionStart = QDateTime::fromMSecsSinceEpoch(mp.missionStart());
result.repeat = mp.repeat();
result.jumpToStart = mp.jumpToStart();
result.participantId = mp.participantId();
return result;
}
MissionPlan ObjectMissionPlan::fillMissionPlanData(const ModifyMissionPlanRequest &in)
{
MissionPlan out;
out.id(in.id());
out.name(in.name());
out.missionStart(in.missionStart());
out.properties(in.properties());
out.items(in.items());
out.participantId(in.participantId());
out.jumpToStart(in.jumpToStart());
out.repeat(in.repeat());
return out;
}
MissionPlan ObjectMissionPlan::getMissionPlanData() const
{
return m_missionplan;
}
void ObjectMissionPlan::setDbMissionItems(const QMap<int, ParticipantManagement::Database::PpmMissionItem> &dbItems,
const QMap<int, Database::PpmMissionAction> &dbActions)
{
m_mapMissionItems.clear();
m_dbMissionActions.clear();
for (const ParticipantManagement::Database::PpmMissionItem &item : qAsConst(dbItems))
{
ParticipantManagement::MissionItem msi;
msi.actions().reserve(dbActions.size());
msi.name(item.name.toStdString());
msi.location(Core::GeoPosition(item.location.x(), item.location.y(), item.location.z()));
msi.itemNumber(item.elementNumber);
std::vector<Database::PpmMissionAction> actionsVec;
for (const auto &action : dbActions)
{
if (action.missionItemId == item.id)
{
ParticipantManagement::MissionAction msa;
msa.actionType(action.missionActionTypeId);
msa.duration(action.duration);
msa.fulfilled(action.fulfilled.toMSecsSinceEpoch());
msa.properties(action.properties.toStdString());
msa.name(action.name.toStdString());
msa.actionNumber(action.elementNumber);
msa.planId(item.missionPlanId);
msi.actions().push_back(msa);
actionsVec.push_back(action);
}
}
m_mapMissionItems.insert(item.id, msi);
m_dbMissionActions.push_back(actionsVec);
}
}
const MissionPlan &ObjectMissionPlan::missionPlan() const
{
return m_missionplan;
}
Core::FunctionReplyObject ObjectMissionPlan::createMissionPlan(Database::PpmMissionPlan newMissionPlan, const std::vector<MissionItem> &missionItems)
{
/// 1- insert in DB Mission plan
/// 2- insert in DB Mission Items
/// 3- insert in DB Mission Actions
DBTransaction trans(m_db->database());
newMissionPlan.aborted = false;
if (!m_db->insert(newMissionPlan))
{
QString error = QStringLiteral("Could not insert mission plan into database");
ERROR_LOG(m_logger)<< error;
return Core::FunctionReplyObject(error.toStdString().c_str());
}
std::vector<MissionItem> itemVec = missionItems;
m_mapMissionItems.clear();
m_mapMissionItems.reserve(itemVec.size());
std::vector<std::vector<Database::PpmMissionAction>>itemsVec;
m_dbMissionActions.clear();
for ( auto &item : itemVec)
{
Database::PpmMissionItem dbItem;
dbItem.missionPlanId = newMissionPlan.id;
dbItem.name = QString::fromStdString(item.name());
dbItem.elementNumber = item.itemNumber();
dbItem.location = LtsUtils::QPoint3D(item.location().lon(),item.location().lat(), item.location().z());
if (!m_db->insert(dbItem))
return Core::FunctionReplyObject(0, tr_lts("dds", "Error adding 'Mission Item' to database"));
std::vector<Database::PpmMissionAction> actionsVec;
actionsVec.reserve(item.actions().size());
for (auto &action : item.actions())
{
action.planId(newMissionPlan.id);
Database::PpmMissionAction dbAction;
dbAction.missionActionTypeId = action.actionType();
dbAction.missionItemId = dbItem.id;
dbAction.duration = action.duration();
dbAction.name = QString::fromStdString(action.name());
dbAction.properties = QString::fromStdString(action.properties());
dbAction.fulfilled = QDateTime::fromMSecsSinceEpoch(action.fulfilled());
dbAction.elementNumber = action.actionNumber();
if (!m_db->insert(dbAction))
return Core::FunctionReplyObject(0, tr_lts("dds", "Error adding 'Mission Action' to database"));
actionsVec.push_back(dbAction);
}//loop mission actions
m_mapMissionItems.insert(dbItem.id, item);
m_dbMissionActions.push_back(actionsVec); // [elNumber][actionNumber]
}//loop mission items
m_missionplan.id(newMissionPlan.id);
m_missionplan.name(newMissionPlan.name.toStdString());
m_missionplan.missionStart(newMissionPlan.missionStart.toMSecsSinceEpoch());
m_missionplan.participantId(newMissionPlan.participantId);
m_missionplan.jumpToStart(newMissionPlan.jumpToStart);
m_missionplan.repeat(newMissionPlan.repeat);
m_missionplan.items(itemVec);
m_missionplan.fulfilled(0);
m_missionplan.itemsFulfilled(0);
for (auto &item : m_missionplan.items())
{
for (auto &action : item.actions())
DEBUG_LOG(m_logger)<<"[CREATE] itemIdx: "<<item.itemNumber()
<<" act.Num: "<<action.actionNumber()<<" act.ItemNum: "<<action.itemNumber()<<" itemFul:"<<action.fulfilled();
}
trans.commit();
DEBUG_LOG(m_logger)<< ">> [NEW] mission plan with id( "<<newMissionPlan.id<<" ) inserted !!";
return Core::FunctionReplyObject(newMissionPlan.id);
}
Core::FunctionReplyObject ObjectMissionPlan::updateMissionPlan(Database::PpmMissionPlan newMissionPlan, const std::vector<MissionItem> &missionItems)
{
if (missionItems.size() == 0)
return Core::FunctionReplyObject(newMissionPlan.id, tr_lts("dds", "Could not modify MissionPlan without segments."));
/// 1- update missipn plan table
/// 2- remove items and their actions
/// 3- insert new items and their actions
DBTransaction trans(m_db->database());
const auto tmpDbMissionItems = m_mapMissionItems;
newMissionPlan.aborted = false;
/// update mission plan table
if (!m_db->update(newMissionPlan))
{
QString error = QStringLiteral("Could not update mission plan! ");
ERROR_LOG(m_logger)<< error;
return Core::FunctionReplyObject(error.toStdString().c_str());
}
/// remove all items and their actions from the database
for (const auto &itemId : tmpDbMissionItems.keys())
{
if (!m_db->removePpmMissionItem(itemId))
{
QString error = QStringLiteral("Could not remove mission plan from database");
ERROR_LOG(m_logger)<< error;
return Core::FunctionReplyObject(0, tr_lts("dds", "Could not update mission plan into!"));
}
}
/// insert new items with their actions in the data base;
m_mapMissionItems.clear();
m_mapMissionItems.reserve(missionItems.size());
m_dbMissionActions.clear();
std::vector<MissionItem> itemVec = missionItems;
for (auto &item : itemVec)
{
Database::PpmMissionItem dbItem;
dbItem.missionPlanId = newMissionPlan.id;
dbItem.name = QString::fromStdString(item.name());
dbItem.elementNumber = item.itemNumber();
dbItem.location = LtsUtils::QPoint3D(item.location().lon(),item.location().lat(), item.location().z());
if (!m_db->insert(dbItem))
return Core::FunctionReplyObject(0, tr_lts("dds", "Error adding 'Mission Item' to database"));
std::vector<Database::PpmMissionAction> actionsVec;
actionsVec.reserve(item.actions().size());
for (auto &action : item.actions())
{
action.planId(newMissionPlan.id);
Database::PpmMissionAction dbAction;
dbAction.missionActionTypeId = action.actionType();
dbAction.missionItemId = dbItem.id;
dbAction.duration = action.duration();
dbAction.name = QString::fromStdString(action.name());
dbAction.properties = QString::fromStdString(action.properties());
dbAction.fulfilled = QDateTime::fromMSecsSinceEpoch(action.fulfilled());
dbAction.elementNumber = action.actionNumber();
if (!m_db->insert(dbAction))
return Core::FunctionReplyObject(0, tr_lts("dds", "Error adding 'Mission Action' to database"));
actionsVec.push_back(dbAction);
}//loop mission actions
m_mapMissionItems.insert(dbItem.id, item);
m_dbMissionActions.push_back(actionsVec); // [elNumber][actionNumber]
}//loop mission items
trans.commit();
m_missionplan.id(newMissionPlan.id);
m_missionplan.name(newMissionPlan.name.toStdString());
m_missionplan.missionStart(newMissionPlan.missionStart.toMSecsSinceEpoch());
m_missionplan.participantId(newMissionPlan.participantId);
m_missionplan.jumpToStart(newMissionPlan.jumpToStart);
m_missionplan.repeat(newMissionPlan.repeat);
m_missionplan.items(itemVec);
m_missionplan.itemsFulfilled(0); // on update items and action entries will be cleared
m_missionplan.fulfilled(0);
DEBUG_LOG(m_logger)<< ">> [UPDATE] mission plan with id( "<<m_missionplan.id()<<" ) Updated !!";
return Core::FunctionReplyObject(m_missionplan.id());
}
Core::FunctionReplyObject ObjectMissionPlan::removeMissionPlan(int id)
{
DBTransaction trans(m_db->database());
if (!m_db->removePpmMissionPlan(id))
{
QString error = QStringLiteral("Could not remove mission plan ! ");
ERROR_LOG(m_logger)<< error;
return Core::FunctionReplyObject(error.toStdString().c_str());
}
trans.commit();
m_dbMissionActions.clear();
m_mapMissionItems.clear();
DEBUG_LOG(m_logger)<< ">> [REMOVE] mission Action with id( "<<id<<" ) deleted !!";
return Core::FunctionReplyObject();
}
Core::FunctionReplyObject ObjectMissionPlan::setMissionActionFulfilled(SetMissionActionFulfilledRequest req, qint64 currentTimeMSec)
{
//0- if actionNumb and itemNumb are -1 -> missionplan is aborted. only update missionPlan table with status aborted = true
//1- get db mission action from actionNumber
//2- set mission action as fulfilled
//3- set mission action save in db
//4- update cache data
if (!m_db)
{
ERROR_LOG(m_logger) << "no init yet....";
return Core::FunctionReplyObject("");
}
if (req.missionId() != m_missionplan.id())
{
QString error = QStringLiteral("Wrong missionPlan Object caught Request: %1 / currPlanId: %2").arg(req.missionId()).arg(m_missionplan.id());
ERROR_LOG(m_logger)<< error;
return Core::FunctionReplyObject(error.toStdString().c_str());
}
// Abort in case itemNumb=-1 && actionNumb=-1
if (req.actionNumber() < 0 && req.itemNumber() < 0)
{
m_missionplan.aborted(true);
return setMissionPlanAborted(true);
}
auto &dbActions = m_dbMissionActions[req.itemNumber()]; //[elemNum][actionNum]
if (dbActions.empty()
|| req.actionNumber() >= static_cast<int>(dbActions.size())
|| req.actionNumber() < 0
|| req.itemNumber() < 0) // actionNumber start by 0
{
QString error = QStringLiteral("Could not set mission action with id: %1 ! ").arg(req.actionNumber());
ERROR_LOG(m_logger)<< error;
return Core::FunctionReplyObject(error.toStdString().c_str());
}
Database::PpmMissionAction &dbAction = dbActions[req.actionNumber()];
dbAction.fulfilled = QDateTime::fromMSecsSinceEpoch(currentTimeMSec);
if (!m_db->update(dbAction))
{
QString error = QStringLiteral("Could not update mission action! ");
ERROR_LOG(m_logger)<< error;
return Core::FunctionReplyObject(error.toStdString().c_str());
}
//update item in case actions fulfilled
//1- actions count
//2- number of actions fulfilled
//3- check if action count == item.actions.size()
//4- if yes update missioPlan & missionItem fulfilled
MissionItem &msi = m_mapMissionItems[dbAction.missionItemId];
msi.fulfilled(dbAction.fulfilled.toMSecsSinceEpoch());
msi.actionsFulfilled(msi.actionsFulfilled() + 1);
MissionAction &msa = m_mapMissionItems[dbAction.missionItemId].actions()[dbAction.elementNumber];
msa.fulfilled(dbAction.fulfilled.toMSecsSinceEpoch());
m_missionplan.items()[req.itemNumber()] = m_mapMissionItems[dbAction.missionItemId]; // item in MissionPlan updated through elementNumber
/// update fulfilled time for items and mission plan
/// update fulfilled items count
int numbItemFulfilled = 0;
for(const auto &item : m_mapMissionItems)
{
if (item.actionsFulfilled() == static_cast<int>(item.actions().size()))
numbItemFulfilled++;
}
m_missionplan.itemsFulfilled(numbItemFulfilled);
m_missionplan.fulfilled(dbAction.fulfilled.toMSecsSinceEpoch());
return Core::FunctionReplyObject(m_missionplan.id());
}
Core::FunctionReplyObject ObjectMissionPlan::setMissionPlanAborted(bool state)
{
DEBUG_LOG(m_logger)<<" -- [setMissionPlanAborted] abort mission plan: "<<m_missionplan.id();
Database::PpmMissionPlan dbMissionPlan;
// m_db->selectPpmMissionPlan(m_missionplan.id(),dbMissionPlan);
dbMissionPlan.missionStart = QDateTime::fromMSecsSinceEpoch(m_missionplan.missionStart());
dbMissionPlan.jumpToStart = m_missionplan.jumpToStart();
dbMissionPlan.id = m_missionplan.id();
dbMissionPlan.name = QString::fromStdString(m_missionplan.name());
dbMissionPlan.participantId = m_missionplan.participantId();
dbMissionPlan.repeat = m_missionplan.repeat();
dbMissionPlan.aborted = state;
/// update mission plan table
if (!m_db->update(dbMissionPlan))
{
QString error = QStringLiteral("Could not update mission plan! ");
ERROR_LOG(m_logger)<< error;
return Core::FunctionReplyObject(error.toStdString().c_str());
}
return Core::FunctionReplyObject(m_missionplan.id());
}
} // namespace UasHandling
} // namespace ParticipantManagement