Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

@@ -0,0 +1,826 @@
/**
* Handler for player data
* $Id$
* $HeadURL$
* $Author$
* Created by gr, SLSE, 2017-02-20
*/
#include "handler_functional_area.h"
#include <QTimer>
#include <QDateTime>
#include <LtsUtilsCore/dds_bitarray.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <ProjectDataManagement/pdm_enums.hpp>
namespace dds
{
namespace core
{
inline uint qHash(ProjectDataManagement::EventType et)
{
return ::qHash(et.underlying());
}
}
}
namespace CES_FUNCTIONAL_AREA
{
inline uint qHash(EffectType et)
{
return ::qHash(int(et));
}
QString toString(EffectType et)
{
switch (et)
{
case EffectType::Unknown: return QStringLiteral("Unknown");
case EffectType::EffectiveMineRangeEnter: return QStringLiteral("EffectiveMineRangeEnter");
case EffectType::EffectiveMineRangeLeave: return QStringLiteral("EffectiveMineRangeLeave");
case EffectType::NContaminationLeave: return QStringLiteral("NContaminationLeave");
case EffectType::NContaminationEnterArea1: return QStringLiteral("NContaminationEnterArea1");
case EffectType::NContaminationEnterArea2: return QStringLiteral("NContaminationEnterArea2");
case EffectType::NContaminationDetonation: return QStringLiteral("NContaminationDetonation");
case EffectType::FunctionalAreaLeave: return QStringLiteral("FunctionalAreaLeave");
case EffectType::FunctionalAreaEnter: return QStringLiteral("FunctionalAreaEnter");
case EffectType::ExplosionArea: return QStringLiteral("ExplosionArea");
case EffectType::ExplosionSingle: return QStringLiteral("ExplosionSingle");
case EffectType::BCContaminationLeave: return QStringLiteral("BCContaminationLeave");
case EffectType::BCContaminationEnterFloating: return QStringLiteral("BCContaminationEnterFloating");
case EffectType::BCContaminationEnterResident: return QStringLiteral("BCContaminationEnterResident");
case EffectType::BCContaminationEnterFloatingArea: return QStringLiteral("BCContaminationEnterFloatingArea");
case EffectType::BeStillWarning: return QStringLiteral("BeStillWarning");
}
return QStringLiteral("Unknown (%1)").arg(int(et));
}
HandlerFunctionalAreas::HandlerFunctionalAreas(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &participantHandler,
const std::shared_ptr<CentralEffectSimulation::HandlerBuildingData> &handlerBuildingData,
QObject *parent)
: QObject(parent)
, m_ddsHandler(ddsHandler)
, m_handlerParticipant(participantHandler)
, m_handlerBuildingData(handlerBuildingData)
, m_logger(CentralEffectSimulation::getLogger("Plugin.FunctionalAreas.HandlerFunctionalAreas"))
{
} // end of ctor()
//-----------------------------------------------------------------------------
HandlerFunctionalAreas::~HandlerFunctionalAreas()
{
} // end of dtor()
//-----------------------------------------------------------------------------
bool HandlerFunctionalAreas::init()
{
auto dtcAes = m_ddsHandler->dtcAes();
dtcAes->waitForHistoricalDataFunctionalArea(2000);
dtcAes->waitForHistoricalDataAesItemView(1000);
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::aesItemViewChanged,
this, &HandlerFunctionalAreas::onAesItemViewChanged);
// TAB FTC
m_ddsHandler->ftcTab()->enableDemandInit();
connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::newOutdoorPosition,
this, &HandlerFunctionalAreas::onNewParticipantPosition);
connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::newIndoorPosition,
this, &HandlerFunctionalAreas::onNewIndoorParticipantPosition);
connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::restoreRadioReadinessChanged,
this, &HandlerFunctionalAreas::onRestoreRadioReadinessChanged);
// Get 'static' data for all onAesItemView
{
auto cb = [this](const AreaEffectSimulation::AesItemView & aiv)
{
onAesItemViewChanged(aiv, DataModification::eAdded);
};
if (!dtcAes->aesItemViews(cb))
return false;
}
INFO_LOG(m_logger) << "HandlerParticipantArea::init() finished.";
return true;
} // end of init()
//-----------------------------------------------------------------------------
void HandlerFunctionalAreas::onSendCesHitReply(const Core::FunctionReplyObject &replyObject)
{
DEBUG_LOG(m_logger) << "onSendCesHitReply for id " << replyObject.id() << " success= " << replyObject.error();
if (replyObject.error())
WARNING_LOG(m_logger) << "Can not send enter/leave Area to participant in training area: " << replyObject();
// Send next Request, if available
if (!m_sendCesHitRequestQueue.isEmpty())
{
DEBUG_LOG(m_logger) << "m_sendCesAreaActionRequestQueue.size()=" << m_sendCesHitRequestQueue.size();
m_sendCesHitRequestQueue.dequeue();
// Send next Message
if (!m_sendCesHitRequestQueue.isEmpty())
{
const auto &hr = m_sendCesHitRequestQueue.head();
DEBUG_LOG(m_logger) << "sendCesHitRequest: " << hr;
m_ddsHandler->ftcTab()->sendCesHitRequest(hr, this);
}
}
}
void HandlerFunctionalAreas::onDemandInitReply(const Core::FunctionReplyObject &replyObject)
{
DEBUG_LOG(m_logger) << "onDemandInitReply for id " << replyObject.id() << " success= " << replyObject.error();
if (replyObject.error())
WARNING_LOG(m_logger) << "Can not send Init to participant in training area: " << replyObject();
// Send next Request, if available
if (!m_sendInitRequestQueue.isEmpty())
{
DEBUG_LOG(m_logger) << "m_sendInitRequestQueue.size()=" << m_sendInitRequestQueue.size();
m_sendInitRequestQueue.dequeue();
// Send next Message
if (!m_sendInitRequestQueue.isEmpty())
{
const auto &hr = m_sendInitRequestQueue.head();
DEBUG_LOG(m_logger) << "demandInitRequest: " << hr;
m_ddsHandler->ftcTab()->demandInitRequest(hr, this);
}
}
}
// ///////////////////////////////////
// A E S (AreaEffectSimulation)
// ///////////////////////////////////
void HandlerFunctionalAreas::onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType)
{
const int aesItemId = data.aesItemId();
const AreaEffectSimulation::AesEffectState &effectState = data.effectStateId();
if (data.aesTypeId().underlying() != AreaEffectSimulation::AesType_def::AtFunctionalArea)
return;
const AreaEffectSimulation::FunctionalArea &fa = m_ddsHandler->dtcAes()->functionalArea(data.aesItemId());
if (!fa.isCentral())
{
DEBUG_LOG(m_logger) << " !isCentral"
" Got AesItemView id: " << aesItemId
<< ", type: " << data.aesTypeId()
<< ", effectState: " << data.effectStateId()
<< ", modType: " << modType;
if (m_aesItemViews.contains(aesItemId))
m_aesItemViews.remove(aesItemId);
return;
}
DEBUG_LOG(m_logger) << "Got AesItemView id: " << aesItemId
<< ", type: " << data.aesTypeId()
<< ", effectState: " << data.effectStateId()
<< ", modType: " << modType;
switch (effectState.underlying())
{
case AreaEffectSimulation::AesEffectState_def::EsPrepared:
break;
case AreaEffectSimulation::AesEffectState_def::EsActivated:
{
bool isSupplyTruck = false;
if (fa.supplyMode() == AreaEffectSimulation::AesOperatingMode_def::OmWaitingTime)
{
DEBUG_LOG(m_logger) << "isSupplyTruck = true";
isSupplyTruck = true;
}
auto aesItemViewUtm(CentralEffectSimulation::AesItemViewUtm::create(data, m_aesItemViews[data.aesItemId()], 0, isSupplyTruck));
if (fa.participantId().is_set())
aesItemViewUtm.participantId = fa.participantId().get();
if (!m_aesPolygonEncloseBuilding.contains(data.aesItemId()))
{
QVector<int> enclosedBuildings;
QPolygonF polygon;
polygon.reserve(data.form().size());
for (size_t i = 0; i < data.form().size(); i++)
{
//QPointF point(itemView.form[i].x(), itemView.form[i].y());
QPointF point(data.form().at(i).lon(), data.form().at(i).lat());
polygon.append(point);
}
enclosedBuildings = m_handlerBuildingData->polygonEncloseBuildings(polygon);
DEBUG_LOG(m_logger) << "enclosedBuildings.size=" << enclosedBuildings.size();
// local memory for the results, so that the polygonEncloseBuildings method is only run once for each effective field
// and not for each position report
m_aesPolygonEncloseBuilding.insert(data.aesItemId(), enclosedBuildings);
DEBUG_LOG(m_logger) << "insert enclosedBuildings.size=" << enclosedBuildings.size();
}
calculateFunctionalArea(aesItemViewUtm);
m_aesItemViews.insert(data.aesItemId(), aesItemViewUtm);
DEBUG_LOG(m_logger) << "insert Functiona Area AesItemView id: " << aesItemId
<< ", type: " << data.aesTypeId();
break;
} // case EsActivated
case AreaEffectSimulation::AesEffectState_def::EsRemoved:
case AreaEffectSimulation::AesEffectState_def::EsExpired:
{
aesItemViewRemoved(aesItemId);
m_aesPolygonEncloseBuilding.remove(aesItemId);
break;
}
default:
// do nothing
break;
} // switch effectStateId
} // onAesItemViewChanged
void HandlerFunctionalAreas::calculateFunctionalArea(const CentralEffectSimulation::AesItemViewUtm &itemView)
{
bool inForm = false;
DEBUG_LOG(m_logger) << "HandlerParticipantArea::calculateFunctionalArea aesItemId =" << itemView.aesItemId;
const auto participantsMap = m_handlerParticipant->positions();
for (const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPos : participantsMap)
{
if (m_handlerParticipant->isOutdated(participantPos))
continue;
DEBUG_LOG(m_logger) << "participant id= " << participantPos.participantId()
<< " buildingId=" << participantPos.buildingId();
if ( participantPos.buildingId() ==0 )
inForm = inFormCheck(itemView, participantPos);
else
{
for (int i = 0; i < m_aesPolygonEncloseBuilding.value(itemView.aesItemId).size(); i++)
{
inForm = false;
if (m_aesPolygonEncloseBuilding.value(itemView.aesItemId).at(i) == participantPos.buildingId())
{
inForm = true;
m_handlerParticipant->setNotfightMode(participantPos.participantId(), true);
DEBUG_LOG(m_logger) << "!m_aesPolygonEncloseBuilding buildingId=" << participantPos.buildingId()
<< " aesId=" << itemView.aesItemId
<< " in Form = true";
break;
}
else
{
DEBUG_LOG(m_logger) << "!m_aesPolygonEncloseBuilding buildingId=" << participantPos.buildingId()
<< " aesId=" << itemView.aesItemId
<< " in Form = false";
}
}
}
sendEnterLeave(itemView, participantPos.participantId(), inForm);
}
// for
} // calculateFunctionalArea
void HandlerFunctionalAreas::onNewParticipantPosition(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData)
{
DEBUG_LOG(m_logger) << "++++++++ onNewParticipantPosition participantId=" << participantData.participantId();
if (m_handlerParticipant->isOutdated(participantData))
return;
const int equipmentNumber = m_ddsHandler->participantId2EquipNo(participantData.participantId());
if (equipmentNumber <= 0)
{
DEBUG_LOG(m_logger) << "equipmentNumber <=0";
return;
}
DEBUG_LOG(m_logger) << "HandlerParticipantArea::calculateAesParticipant paricipantId: " << participantData.participantId();
for (const CentralEffectSimulation::AesItemViewUtm &itemView : qAsConst(m_aesItemViews))
{
DEBUG_LOG(m_logger) << " itemView: " << itemView.aesItemId << ", " << itemView.aesTypeId;
switch (itemView.aesTypeId.underlying())
{
case AreaEffectSimulation::AesType_def::AtFunctionalArea:
{
///////////////////
/// \brief [GUEZE-2256] 3D Wirksim - Funktionsraum Nicht Kampffähig
/// Die Teilnehmer der Partei des Wirkfeldes werden nicht berücksichtig.
///
AreaEffectSimulation::FunctionalArea functionalArea = m_ddsHandler->dtcAes()->functionalArea(itemView.aesItemId);
DEBUG_LOG(m_logger) << "functionalArea Typ=" << functionalArea.functionalAreaTypeId()
<< " itemView.partyId=" << itemView.partyId
<< " participantData.partyId=" << participantData.partyId()
<< " insideBuilding=" << participantData.insideBuilding();
///////////////////
bool inForm = inFormCheck(itemView, participantData);
sendEnterLeave(itemView, participantData.participantId(), inForm);
break;
}
default:
// nothing
break;
} // switch
} // for
} // onNewParticipantPosition
void HandlerFunctionalAreas::onNewIndoorParticipantPosition(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData)
{
DEBUG_LOG(m_logger) << "New Indoor Position paticipantId=" << participantData.participantId();
if (m_handlerParticipant->isOutdated(participantData))
return;
const int equipmentNumber = m_ddsHandler->participantId2EquipNo(participantData.participantId());
if (equipmentNumber <= 0)
{
DEBUG_LOG(m_logger) << "equipmentNumber <=0";
return;
}
DEBUG_LOG(m_logger) << "HandlerParticipantArea::calculateAesParticipant paricipantId: " << participantData.participantId();
for (const CentralEffectSimulation::AesItemViewUtm &itemView : qAsConst(m_aesItemViews))
{
DEBUG_LOG(m_logger) << " itemView: " << itemView.aesItemId << ", " << itemView.aesTypeId;
switch (itemView.aesTypeId.underlying())
{
case AreaEffectSimulation::AesType_def::AtFunctionalArea:
{
///////////////////
/// \brief [GUEZE-2256] 3D Wirksim - Funktionsraum Nicht Kampffähig
/// Die Teilnehmer der Partei des Wirkfeldes werden nicht berücksichtig.
///
AreaEffectSimulation::FunctionalArea functionalArea = m_ddsHandler->dtcAes()->functionalArea(itemView.aesItemId);
DEBUG_LOG(m_logger) << "functionalArea Typ=" << functionalArea.functionalAreaTypeId()
<< " itemView.partyId=" << itemView.partyId
<< " participantData.partyId=" << participantData.partyId()
<< " insideBuilding=" << participantData.insideBuilding();
{
if ( (itemView.partyId == participantData.partyId())
&& (functionalArea.functionalAreaTypeId() == 8)) // Funktionsraum Nicht Kampffaehig [GUEZE-2256]
{
DEBUG_LOG(m_logger) << "Position mit Funktionsraum Nicht Kampffähig hat die Partei des Wirkfeldes => nicht beruecksichtigen";
continue;
}
}
// Check whether the position appears in the building list of the effective field.
bool inForm = false;
for (int i = 0; i < m_aesPolygonEncloseBuilding.value(itemView.aesItemId).size(); i++)
{
if (m_aesPolygonEncloseBuilding.value(itemView.aesItemId).at(i) == participantData.buildingId())
{
inForm = true;
m_handlerParticipant->setNotfightMode(participantData.participantId(), true);
break;
}
}
///////////////////
sendEnterLeave(itemView, participantData.participantId(), inForm);
break;
}
default:
// nothing
break;
} // switch
} // for
}
void HandlerFunctionalAreas::onRestoreRadioReadinessChanged(const int participantId)
{
DEBUG_LOG(m_logger) << "HandlerArtillery::onRestoreRadioReadinessChanged participantId=" << participantId;
m_supplyTimers.remove(participantId);
removeParticipant(participantId);
}
// return true, if participant is inside of the bounding Box
bool HandlerFunctionalAreas::inBoundingBoxCheck(const CentralEffectSimulation::AesItemViewUtm &itemView,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData)
{
if (itemView.effectStateId != AreaEffectSimulation::AesEffectState_def::EsActivated)
return false;
// QRectF(topLeft, bottomRight) -> no need to mormalize, QRectF:contains() handles it correct
const QRectF boundingBoxImpact(itemView.boundingBoxBottomLeft,
itemView.boundingBoxTopRight);
const QPointF participantPosUtmPoint = CentralEffectSimulation::geographic2Utm(participantData.pos(), itemView.zone);
if (boundingBoxImpact.contains(participantPosUtmPoint))
{
DEBUG_LOG(m_logger) << "inBoundingBoxCheck Paricipant " << participantData.participantId()
<< " inside AesItemView:" << itemView.aesItemId;
return true;
}
TRACE_LOG(m_logger) << "inBoundingBoxCheck Paricipant " << participantData.participantId()
<< " outside AesItemView:" << itemView.aesItemId;
return false;
}
// return true, if participant is inside of the form of AesItemView
bool HandlerFunctionalAreas::inFormCheck(const CentralEffectSimulation::AesItemViewUtm &itemView,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData)
{
if (itemView.effectStateId != AreaEffectSimulation::AesEffectState_def::EsActivated)
return false;
const QRectF boundingBox(itemView.boundingBoxBottomLeft,
itemView.boundingBoxTopRight);
const QPointF participantPosUtmPoint = CentralEffectSimulation::geographic2Utm(participantData.pos(), itemView.zone);
const QString participantPosMgrs = CentralEffectSimulation::geographic2mgrs(participantData.pos(), itemView.zone);
DEBUG_LOG(m_logger) << "inFormCheck start, paricipantId: " << participantData.participantId()
<< ", aesItemId: " << itemView.aesItemId
<< ", aesTypeId: " << itemView.aesTypeId
<< ", form.size: " << itemView.form.size()
<< ", Mgrs:" << participantPosMgrs;
if (boundingBox.contains(participantPosUtmPoint) &&
itemView.form.containsPoint(participantPosUtmPoint, Qt::FillRule::OddEvenFill))
{
DEBUG_LOG(m_logger) << "inside AES form, paricipantId: " << participantData.participantId()
<< ", aesItemId: " << itemView.aesItemId;
return true;
} // if inside
// outside
#if 0
if (m_logger.isDebugEnabled())
{
DEBUG_LOG(m_logger) << "inFormCheck: Paricipant " << participantPosition.participantId << " outside AesItemView " << itemView.aesItemId;
DEBUG_LOG(m_logger) << "ParticipantPos = " << debug(participantPosUtmPoint);
for (const auto &itPos : itemView.form)
DEBUG_LOG(m_logger) << "itemView =" << debug(itPos);
}
#endif
return false;
}
// Send via TAB-Proxy to battlefield
void HandlerFunctionalAreas::sendCesHitRequest(const CentralEffectSimulation::AesItemViewUtm &itemView,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData,
ProjectDataManagement::EventType eventType)
{
qint64 effectTime = QDateTime::currentMSecsSinceEpoch();
// qint64 mineFieldBitIndex = 0;
int remaining = 0;
switch (eventType.underlying())
{
case ProjectDataManagement::EventType_def::EnterFunctionalArea:
DEBUG_LOG(m_logger) << "-------------- EnterFunctionalArea itemView =" << itemView.aesItemId;
remaining = 1;
break;
case ProjectDataManagement::EventType_def::LeaveFunctionalArea:
remaining = 0;
DEBUG_LOG(m_logger) << "-------------- LeaveFunctionalArea itemView =" << itemView.aesItemId;
break;
default:
return;
}
if (remaining < 0)
return;
DEBUG_LOG(m_logger) << "sendCesHitRequest Settings::calculateCentralAes="
<< " insideWlsArea=" << std::boolalpha << participantData.insideWlsArea()
<< " isSmartChargeType=" << std::boolalpha << m_ddsHandler->isSmartChargeType(itemView.chargeStruct)
<< " participantId=" << participantData.participantId();
const int equipNo = m_ddsHandler->participantId2EquipNo(participantData.participantId());
DEBUG_LOG(m_logger) << " ftc sendCESHit to Participant participantId = " << participantData.participantId()
<< " equipNo = " << equipNo
<< " aesItemId =" << itemView.aesItemId;
// participantPosition.participantPosition == 0 -> send to all
if (participantData.participantId() != 0 && equipNo <= 0)
{
DEBUG_LOG(m_logger) << "participantPosition.participantId != 0 && equipNo <= 0";
return;
}
if (participantData.participantId() != 0 &&
participantData.vulnerabilityState == ProjectDataManagement::VulnerabilityState_def::CatastrophicKill)
{
DEBUG_LOG(m_logger) << "participantPosition.participantId != 0 CatastrophicKill)";
return;
}
const AreaEffectSimulation::FunctionalArea &fa = m_ddsHandler->dtcAes()->functionalArea(itemView.aesItemId);
const TrainingAreaBase::TabPosition pos(participantData.pos(),
Core::PositionReportingSource_def::Gps, // irrelevant
participantData.buildingId(),
participantData.roomId());
const int medicTime = fa.medicTime() / 600000; //reserve 2 = medical treatment
const int maintanceTime = fa.maintTime() / 600000; //reserve 1 = maintance time
const int decontaminatonTime = fa.deconTime() / 600000; //reserve Munitionsart = decontaminaton time
const int operationModeDecontamination = fa.deconMode().underlying();
const int operationModeMaintenance = fa.maintMode().underlying();
const int operationModeMedical = fa.medicMode().underlying();
//const int originatorEquipNo = fa.medicTime()/60000; //reserve 2 = medical treatment
//const int mineId = fa.maintTime()/60000; //reserve 1 = maintance time
//const int chargeType = fa.deconTime()/1000; //reserve Munitionsart = decontaminaton time
const int originatorEquipNo = (operationModeMedical << 8) + medicTime; //reserve 2 = medical treatment
const int mineId = (operationModeMaintenance << 8) + maintanceTime; //reserve 1 = maintance time
const int chargeType = (operationModeDecontamination << 8) + decontaminatonTime; //reserve Munitionsart = decontaminaton time
TrainingAreaBase::SendCesHitRequest requestTab(
equipNo, // equipmentNumber
participantData.participantId(), // participantId
chargeType, // chargeTypeId
itemView.aesItemId, // aesId
originatorEquipNo, // originatorEquipmentNumber
remaining, // remainEffectPercent ( no protection outside Building )
pos,
effectTime, // effectTime
eventType,
itemView.partyId, // originPartyId
mineId
);
DEBUG_LOG(m_logger) << " participantId=" << participantData.participantId()
<< " chargeTypeId=" << itemView.chargeStruct.chargeTypeId();
m_sendCesHitRequestQueue.enqueue(requestTab);
if (m_sendCesHitRequestQueue.size() == 1)
{
DEBUG_LOG(m_logger) << "SendCesHitRequest: " << requestTab;
m_ddsHandler->ftcTab()->sendCesHitRequest(requestTab, this);
}
}
void HandlerFunctionalAreas::sendParticipantEvent(const CentralEffectSimulation::AesItemViewUtm &itemView,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData,
const ProjectDataManagement::EventType eventType)
{
ParticipantManagement::TypeClass typeClass = m_handlerParticipant->typeClassFromTypeId(participantData.participantTypeId());
// can happen since the positions are collected for all participants (no check if it is a SupportEntity or similar)
if (typeClass == ParticipantManagement::TypeClass_def::Unit ||
typeClass == ParticipantManagement::TypeClass_def::SupportUnit ||
typeClass == ParticipantManagement::TypeClass_def::SupportEntity ||
typeClass == ParticipantManagement::TypeClass_def::Aircraft ||
typeClass == ParticipantManagement::TypeClass_def::Vessel ||
typeClass == ParticipantManagement::TypeClass_def::Unknown)
{
DEBUG_LOG(m_logger) << "Participant with id " << participantData.participantId()
<< " has invalid typeClass: " << typeClass
<< " eventType: " << eventType;
return;
}
int equipmentNumber = m_ddsHandler->participantId2EquipNo(participantData.participantId());
if (equipmentNumber <= 0)
{
WARNING_LOG(m_logger) << "Not sending Event " << eventType << " for participant " << participantData.participantId()
<< " - participant has no equipment number";
return;
}
DEBUG_LOG(m_logger) << "sendParticipantEvent" << eventType
<< " participantId=" << participantData.participantId()
<< " AesItemId=" << itemView.aesItemId;
const AreaEffectSimulation::FunctionalArea &fa = m_ddsHandler->dtcAes()->functionalArea(itemView.aesItemId);
CentralEffectSimulation::ParticipantEvent pe;
pe.id(m_ddsHandler->getParticipantEventId());
pe.eventTypeId(eventType.underlying());
pe.participantId(participantData.participantId());
pe.eventTime(participantData.sampleTime());
pe.aesItemId(itemView.aesItemId);
pe.partyId(participantData.partyId());
pe.aesName(fa.name());
pe.equipmentNumber(equipmentNumber);
pe.vulnerability(participantData.vulnerabilityState.underlying());
pe.position(participantData.pos());
pe.friendlyFire(false);
INFO_LOG(m_logger) << "sendParticipantEvent: " << pe
<< ", currentMSecsSinceEpoch = " << QDateTime::currentMSecsSinceEpoch()
<< ", time difference = " << QDateTime::currentMSecsSinceEpoch() - pe.eventTime();
m_ddsHandler->dtsCes()->publish(pe);
const auto id = pe.id();
QTimer::singleShot(1 * 60 * 1000, this, [id, this]() { m_ddsHandler->dtsCes()->removeParticipantEventByKey(id); });
}
void HandlerFunctionalAreas::aesItemViewRemoved(int aesItemId)
{
DEBUG_LOG(m_logger) << "aesItemViewRemoved aesItemId=" << aesItemId
<< " m_cesEnterLeaveFunctionalArea.size=" << m_cesEnterLeaveFunctionalArea.size()
<< " m_aesItemViews.size=" << m_aesItemViews.size();
QHashIterator<QPair<int, int>, EnterLeaveType> i(m_cesEnterLeaveFunctionalArea);
while (i.hasNext()) {
i.next();
DEBUG_LOG(m_logger) << "Key: itemId=" << i.key().first << " participantId=" << i.key().second
<< " EnterLeaveType=" << i.value().eventType;
if (i.key().first == aesItemId )
{
DEBUG_LOG(m_logger) << " EnterLeaveType=" << i.value().eventType;
CentralEffectSimulation::AesItemViewUtm itemView = m_aesItemViews.value(i.key().first);
sendEnterLeave(itemView, i.key().second, false);
m_cesEnterLeaveFunctionalArea.remove(i.key());
}
}
m_aesItemViews.remove(aesItemId);
}
void HandlerFunctionalAreas::removeParticipant(int participantId)
{
DEBUG_LOG(m_logger) << "removeParticipant participantId=" << participantId
<< " m_cesEnterLeaveFunctionalArea.size=" << m_cesEnterLeaveFunctionalArea.size();
QHashIterator<QPair<int, int>, EnterLeaveType> i(m_cesEnterLeaveFunctionalArea);
while (i.hasNext()) {
i.next();
DEBUG_LOG(m_logger) << "Key: itemId=" << i.key().first << " participantId=" << i.key().second
<< " EnterLeaveType=" << i.value().eventType;
if (i.key().second == participantId )
{
DEBUG_LOG(m_logger) << " EnterLeaveType=" << i.value().eventType;
CentralEffectSimulation::AesItemViewUtm itemView = m_aesItemViews.value(i.key().first);
//sendEnterLeave(itemView, i.key().second, false);
m_cesEnterLeaveFunctionalArea.remove(i.key());
}
}
}
void HandlerFunctionalAreas::sendEnterLeave(const CentralEffectSimulation::AesItemViewUtm &itemView, int participantId, bool inForm)
{
QPair<int, int> key = QPair<int, int>(itemView.aesItemId, participantId);
EnterLeaveType enterLeaveType;
EnterLeaveType lastEnterLeaveType;
if (m_cesEnterLeaveFunctionalArea.contains(key))
lastEnterLeaveType = m_cesEnterLeaveFunctionalArea.value(key);
DEBUG_LOG(m_logger) << "HandlerFunctionalAreas::sendEnterLeave "
<< " aesItemId=" << itemView.aesItemId
<< " participantId=" << participantId
<< " inForm=" << inForm;
if (inForm)
{
enterLeaveType.eventType = ProjectDataManagement::EventType_def::EnterFunctionalArea;
if (itemView.isSupplyTruck)
{
enterLeaveType.isAlreadySupplied = true;
const AreaEffectSimulation::FunctionalArea &fa = m_ddsHandler->dtcAes()->functionalArea(itemView.aesItemId);
if (!lastEnterLeaveType.isAlreadySupplied)
{
DEBUG_LOG(m_logger) << "sendEnterLeave.startSupplyTimer"
" m_cesEnterLeaveFunctionalArea.insert"
<< " aesItemId=" << key.first
<< " participantId=" << key.second
<< " enterLeaveType=" << enterLeaveType.eventType;
startSupplyTimer(participantId, itemView.aesItemId, fa.supplyTime());
m_cesEnterLeaveFunctionalArea.insert(key, enterLeaveType);
}
}
}
else
{
enterLeaveType.eventType = ProjectDataManagement::EventType_def::LeaveFunctionalArea;
if (itemView.isSupplyTruck && lastEnterLeaveType.eventType == ProjectDataManagement::EventType_def::EnterFunctionalArea)
{
DEBUG_LOG(m_logger) << "sendEnterLeave.stopSupplyTimer";
enterLeaveType.isAlreadySupplied = false;
stopSupplyTimer(participantId);
DEBUG_LOG(m_logger) << "sendEnterLeave.startSupplyTimer"
" m_cesEnterLeaveFunctionalArea.insert"
<< " aesItemId=" << key.first
<< " participantId=" << key.second
<< " enterLeaveType=" << enterLeaveType.eventType;
m_cesEnterLeaveFunctionalArea.insert(key, enterLeaveType);
}
}
if ((inForm && lastEnterLeaveType.eventType != ProjectDataManagement::EventType_def::EnterFunctionalArea)
|| (!inForm && lastEnterLeaveType.eventType == ProjectDataManagement::EventType_def::EnterFunctionalArea))
{
CentralEffectSimulation::HandlerParticipant::CesParticipantData cesParticipantData = m_handlerParticipant.get()->getParticipantPosition(participantId);
sendParticipantEvent(itemView, cesParticipantData, enterLeaveType.eventType);
const AreaEffectSimulation::FunctionalArea &fa = m_ddsHandler->dtcAes()->functionalArea(itemView.aesItemId);
DEBUG_LOG(m_logger) << "fa.isCentral()=" << fa.isCentral()
<< " isSupplyTruck=" << itemView.isSupplyTruck
<< " eventType=" << m_cesEnterLeaveFunctionalArea.value(key).eventType
<< " isAlreadySupplied=" << enterLeaveType.isAlreadySupplied;
if (fa.isCentral() && !itemView.isSupplyTruck)
{
DEBUG_LOG(m_logger) << "sendCesHitRequest";
sendCesHitRequest(itemView, cesParticipantData, enterLeaveType.eventType);
}
DEBUG_LOG(m_logger) << " m_cesEnterLeaveFunctionalArea.insert"
<< " aesItemId=" << key.first
<< " participantId=" << key.second
<< " enterLeaveType=" << enterLeaveType.eventType;
m_cesEnterLeaveFunctionalArea.insert(key, enterLeaveType);
}
} // sendEnterLeave
void HandlerFunctionalAreas::startSupplyTimer(int participantId, int aesId, long time)
{
DEBUG_LOG(m_logger) << "startSupplyTimer="
<< " participantId=" << participantId
<< " aesId=" << aesId
<< " time=" << time
<< " ST participant" << m_aesItemViews[aesId].participantId;
if (participantId == m_aesItemViews[aesId].participantId)
{
DEBUG_LOG(m_logger) << "No supply for SupplyTruck";
return;
}
if (m_supplyTimers.contains(participantId))
{
if (m_supplyTimers[participantId]->isActive())
{
DEBUG_LOG(m_logger) << "SupplyTimer isActive";
return;
}
else
m_supplyTimers.remove(participantId);
}
SupplyTimer *supplyTimer = new SupplyTimer(participantId,
aesId, time);
DEBUG_LOG(m_logger) << "supplyTimer->startTimer();";
QObject::connect(supplyTimer, &SupplyTimer::timeToEffectTimeout,
this, &HandlerFunctionalAreas::on_supplyFinished);
m_supplyTimers.insert(participantId, supplyTimer);
supplyTimer->startTimer();
} // startSupplyTimer
void HandlerFunctionalAreas::stopSupplyTimer(int participantId)
{
DEBUG_LOG(m_logger) << "stopSupplyTimer="
<< "participantId=" << participantId;
if (m_supplyTimers.contains(participantId))
{
if (m_supplyTimers[participantId]->isActive())
return;
}
} // startSupplyTimer
void HandlerFunctionalAreas::on_supplyFinished(int participantId, int aesId)
{
DEBUG_LOG(m_logger) << "HandlerFunctionalAreas::on_supplyFinished participantId=" << participantId
<< " aesId =" << aesId;
sendInitSupplyToTab(participantId,
aesId);
}
void HandlerFunctionalAreas::sendInitSupplyToTab(int participantId, int aesId)
{
const int equipmentNumber = m_ddsHandler->participantId2EquipNo(participantId);
if (equipmentNumber <= 0)
return;
int requestId = m_requestId++;
int workstationId = 0;
std::vector<int32_t> equipmentNumbers;
equipmentNumbers.push_back(equipmentNumber);
bool restockCharges = true;
bool resetManipulation = false;
bool resetVulnerabilityState = false;
bool restockSanitationMaterial = false;
DEBUG_LOG(m_logger) << "sendInitSupplyToTab"
<< " participantId=" << participantId
<< " aesId=" << aesId;
TrainingAreaBase::DemandInitRequest demandInitRequest(
requestId,
workstationId,
equipmentNumbers,
restockCharges,
resetManipulation,
resetVulnerabilityState,
restockSanitationMaterial
);
m_sendInitRequestQueue.enqueue(demandInitRequest);
if (m_sendInitRequestQueue.size() == 1)
{
DEBUG_LOG(m_logger) << "sendInitSupply: " << demandInitRequest;
m_ddsHandler->ftcTab()->demandInitRequest(demandInitRequest, this);
}
}
} // namespace CES_FUNCTIONAL_AREA