827 lines
34 KiB
C++
Executable File
827 lines
34 KiB
C++
Executable File
/**
|
|
* 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
|