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,27 @@
#
# monitoring of the target areas
# $Id$
# $HeadURL$
# $Author$
#
SET(SRCS
plugin.cpp
plugin.h
handler_participant_booby_trap.cpp
handler_participant_booby_trap.h
handler_participant_off_route_mine.cpp
handler_participant_off_route_mine.h
)
NGL_ADD_LIBRARY(AAR SV cesPluginVirtualMines MODULE ${SRCS})
NGL_TARGET_LINK_LIBRARIES(cesPluginVirtualMines
Qt5::Network
Qt5::Widgets
cesPluginInterface
ngldb
svcCesDDSCommon
# ProjectConfig
)
NGL_INSTALL_TARGET(cesPluginVirtualMines)
@@ -0,0 +1,685 @@
/**
* Handler for player data
* $Id$
* $HeadURL$
* $Author$
* Created by gr, SLSE, 2017-02-20
*/
#include "handler_participant_booby_trap.h"
#include <LtsCoordTrans/lts_coord_trans.h>
#include <QLineF>
#include <QTimer>
namespace CesVirtualMines
{
HandlerParticipantBoobyTrap::HandlerParticipantBoobyTrap(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &participantHandler,
QObject *parent)
: QObject(parent)
, m_ddsHandler(ddsHandler)
, m_handlerParticipant(participantHandler)
, m_boobyTrapItems()
, m_requestMap()
, m_timer(new QTimer(this))
, m_logger(CentralEffectSimulation::getLogger("Plugin.VirtualMines.HandlerParticipantBoobyTrap"))
{
INFO_LOG(m_logger) << "HandlerParticipantBoobyTrap::HandlerParticipantBoobyTrap";
m_timer->setSingleShot(true);
connect(m_timer, &QTimer::timeout, this, &HandlerParticipantBoobyTrap::sendFtcCesHitRequestTimeout);
} // end of ctor()
//-----------------------------------------------------------------------------
HandlerParticipantBoobyTrap::~HandlerParticipantBoobyTrap()
{
INFO_LOG(m_logger) << "HandlerParticipantBoobyTrap::~HandlerParticipantBoobyTrap";
} // end of dtor()
//-----------------------------------------------------------------------------
bool HandlerParticipantBoobyTrap::init()
{
INFO_LOG(m_logger) << "HandlerParticipantBoobyTrap::init";
auto dtcAes = m_ddsHandler->dtcAes();
auto ftcAes = m_ddsHandler->ftcAes();
auto dtcCes = m_ddsHandler->dtsCes();
dtcAes->waitForHistoricalDataBoobyTrap(2000);
dtcAes->waitForHistoricalDataAesItemView(2000);
dtcAes->enableBoobyTrap();
ftcAes->enableBoobyTrapTrigger();
dtcCes->enableParticipantEvent();
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::boobyTrapChanged,
this, &HandlerParticipantBoobyTrap::onBoobyTrapChanged);
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::aesItemViewChanged,
this, &HandlerParticipantBoobyTrap::onAesItemViewChanged);
connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::newOutdoorPosition,
this, &HandlerParticipantBoobyTrap::onParticipantPositionChanged);
// 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) << "HandlerParticipantBoobyTrap::init() finished. ";
return true;
} // end of init()
//-----------------------------------------------------------------------------
// ///////////////////////////////////
// A E S (AreaEffectSimulation)
// ///////////////////////////////////
void HandlerParticipantBoobyTrap::onBoobyTrapChanged(const AreaEffectSimulation::BoobyTrap &data, DataModification modType)
{
if (data.isDeleted()
|| data.effectStateId() == AreaEffectSimulation::AesEffectState::EsRemoved
|| (data.effectStateId() == AreaEffectSimulation::AesEffectState::EsExpired && !data.triggered())
|| !data.isCentral()
|| modType == DataModification::eRemoved)
{
m_boobyTraps.remove(data.id());
m_boobyTrapItems.remove(data.id());
m_boobyTrapItemsSecondary.remove(data.id());
return;
}
INFO_LOG(m_logger) << "HandlerParticipantBoobyTrap::onBoobyTrapChanged"
<< " data.sampleTime=" << data.sampleTime()
<< " m_ddsHandler->currentPartitionTime=" << m_ddsHandler->currentPartitionTime()
<< " diff=" << m_ddsHandler->currentPartitionTime() - data.sampleTime();
if ((m_ddsHandler->currentPartitionTime() - data.sampleTime()) > 2000)
{
INFO_LOG(m_logger) << "onBoobyTrap outdated";
return;
}
m_boobyTraps.insert(data.id(), data);
if (!data.triggered())
return;
// CentralEffectSimulation::AesItemViewUtm prevData;
// const double impactRadius = 0;
// prevData.aesItemId = 0;
// const CentralEffectSimulation::AesItemViewUtm boobyTrapUtm = CentralEffectSimulation::AesItemViewUtm::create(data, prevData, impactRadius);
// if (data.aesTypeId() == AreaEffectSimulation::AesType_def::AtBoobyTrap)
// m_boobyTrapItems.insert(data.aesItemId(), boobyTrapUtm);
// if (data.aesTypeId() == AreaEffectSimulation::AesType_def::AtBoobyTrapSecondary)
// m_boobyTrapItemsSecondary.insert(data.aesItemId(), boobyTrapUtm);
// DEBUG_LOG(m_logger) << "Check each participant"
// << " aesTypeId=" << data.aesTypeId();
// Check each participant
const auto partPosMap = m_handlerParticipant->positions();
for (const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPos : partPosMap)
{
if (m_handlerParticipant->isOutdated(participantPos))
{
TRACE_LOG(m_logger) << "isOutdated participantId=" << participantPos.participantId() << " continue";
continue;
}
DEBUG_LOG(m_logger) << "Check each actuell participant participantId=" << participantPos.participantId();
if (participantPos.insideBuilding())
{
DEBUG_LOG(m_logger) << "inside Building participantId=" << participantPos.participantId() << " continue";
continue;
}
if (participantPos.vulnerabilityState == ProjectDataManagement::VulnerabilityState::inner_enum::CatastrophicKill)
{
DEBUG_LOG(m_logger) << "CatastrophicKill participantId=" << participantPos.participantId() << " continue";
continue;
}
DEBUG_LOG(m_logger) << "pos participantId=" << participantPos.participantId()
<< " buildingId=" << participantPos.buildingId()
<< " insideBuilding=" << participantPos.insideBuilding()
<< " positionValid=" << participantPos.positionValid;
const CentralEffectSimulation::AesItemViewUtm aesItemView = m_boobyTrapItemsSecondary.value(data.id());
calculateBoobyTrapParticipant(aesItemView, participantPos);
}
m_boobyTraps.remove(data.id());
m_boobyTrapItems.remove(data.id());
m_boobyTrapItemsSecondary.remove(data.id());
}
void HandlerParticipantBoobyTrap::onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType)
{
INFO_LOG(m_logger) << "---------------------------------------------------------------------------";
INFO_LOG(m_logger) << "HandlerParticipantBoobyTrap::onAesItemViewChanged"
<< " aesTypeId=" << data.aesTypeId()
<< " data.effectStateId()=" << data.effectStateId();
if (data.effectStateId() == AreaEffectSimulation::AesEffectState::EsExpired
|| data.effectStateId() == AreaEffectSimulation::AesEffectState::EsRemoved
|| modType == DataModification::eRemoved)
{
if (data.aesTypeId() == AreaEffectSimulation::AesType_def::AtBoobyTrapSecondary)
{
m_boobyTraps.remove(data.id());
m_boobyTrapItems.remove(data.id());
m_boobyTrapItemsSecondary.remove(data.id());
m_triggeredMineParticipant.remove(data.id());
DEBUG_LOG(m_logger) << "onBoobyTrapChanged remove aesId=" << data.id()
<< " m_triggeredMineParticipant.remove(" << data.id() ;
}
return;
}
//
if (data.aesTypeId() != AreaEffectSimulation::AesType_def::AtBoobyTrap
&& data.aesTypeId() != AreaEffectSimulation::AesType_def::AtBoobyTrapSecondary)
return;
const int aesItemId = data.aesItemId();
DEBUG_LOG(m_logger) << "Got AesItemView id: " << aesItemId
<< ", type: " << data.aesTypeId()
<< ", effectState: " << data.effectStateId()
<< ", modType: " << modType;
if (modType == DataModification::eAdded
|| modType == DataModification::eModified)
{
const AreaEffectSimulation::AesEffectState &effectState = data.effectStateId();
switch (effectState.underlying())
{
case AreaEffectSimulation::AesEffectState_def::EsActivated:
{
CentralEffectSimulation::AesItemViewUtm prevData;
const double impactRadius = 0;
prevData.aesItemId = 0;
const CentralEffectSimulation::AesItemViewUtm boobyTrapUtm = CentralEffectSimulation::AesItemViewUtm::create(data, prevData, impactRadius);
if (data.aesTypeId() == AreaEffectSimulation::AesType_def::AtBoobyTrap)
m_boobyTrapItems.insert(data.aesItemId(), boobyTrapUtm);
if (data.aesTypeId() == AreaEffectSimulation::AesType_def::AtBoobyTrapSecondary)
m_boobyTrapItemsSecondary.insert(data.aesItemId(), boobyTrapUtm);
DEBUG_LOG(m_logger) << "Check each participant"
<< " aesTypeId=" << data.aesTypeId();
// Check each participant
// const auto partPosMap = m_handlerParticipant->positions();
// for (const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPos : partPosMap)
// {
// if (m_handlerParticipant->isOutdated(participantPos))
// {
// TRACE_LOG(m_logger) << "isOutdated participantId=" << participantPos.participantId() << " continue";
// continue;
// }
// DEBUG_LOG(m_logger) << "Check each actuell participant participantId=" << participantPos.participantId();
// if (participantPos.insideBuilding())
// {
// DEBUG_LOG(m_logger) << "inside Building participantId=" << participantPos.participantId() << " continue";
// continue;
// }
// if (participantPos.vulnerabilityState == ProjectDataManagement::VulnerabilityState::inner_enum::CatastrophicKill)
// {
// DEBUG_LOG(m_logger) << "CatastrophicKill participantId=" << participantPos.participantId() << " continue";
// continue;
// }
// // Nur Positionsmeldungen, die neuer sind als die Mine koennen sie ausloesen!
// if ((participantPos.sampleTime() < data.sampleTime())
// && (data.aesTypeId() == AreaEffectSimulation::AesType_def::AtBoobyTrap))
// {
// DEBUG_LOG(m_logger) << " the time of the participant is older than the BoobyTrap participantId=" << participantPos.participantId()
// << " participantPos.sampleTime()=" << participantPos.sampleTime()
// << " data.sampleTime()=" << data.sampleTime()
// << " diff =" << participantPos.sampleTime() - data.sampleTime();
// continue;
// }
// DEBUG_LOG(m_logger) << "pos participantId=" << participantPos.participantId()
// << " buildingId=" << participantPos.buildingId()
// << " insideBuilding=" << participantPos.insideBuilding()
// << " positionValid=" << participantPos.positionValid
// << " aesTypeId=" << data.aesTypeId();
// const CentralEffectSimulation::AesItemViewUtm aesItemView = m_boobyTrapItems.value(data.aesItemId());
// calculateBoobyTrapParticipant(aesItemView, participantPos);
// }
break;
}
default:
{
DEBUG_LOG(m_logger) << "default";
}
}
return;
}
} // onAesItemViewChanged
void HandlerParticipantBoobyTrap::calculateBoobyTrapParticipantsSecondary(int aesItemId, int participantId)
{
DEBUG_LOG(m_logger) << "calculateBoobyTrapParticipantsSecondary : aesItemId=" << aesItemId;
const auto partPosMap = m_handlerParticipant->positions();
for (const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPos : partPosMap)
{
if (participantPos.participantId() == participantId)
{
DEBUG_LOG(m_logger) << "is already handled participantId=" << participantId;
continue;
}
if (m_handlerParticipant->isOutdated(participantPos))
{
// DEBUG_LOG(m_logger) << "isOutdated participantId=" << participantPos.participantId();
continue;
}
if (participantPos.insideBuilding())
{
DEBUG_LOG(m_logger) << "inside Building participantId=" << participantPos.participantId() << " continue";
continue;
}
if (participantPos.vulnerabilityState == ProjectDataManagement::VulnerabilityState::inner_enum::CatastrophicKill)
{
DEBUG_LOG(m_logger) << "CatastrophicKill participantId=" << participantPos.participantId() << " continue";
continue;
}
const CentralEffectSimulation::AesItemViewUtm aesItemView = m_boobyTrapItemsSecondary.value(aesItemId);
calculateBoobyTrapParticipantSecondary(aesItemView, participantPos);
}
}
bool HandlerParticipantBoobyTrap::insideSecondaryArea(const QPolygonF &polygonf, const QPointF &participantPos) const
{
DEBUG_LOG(m_logger) << "pos to check: " << CentralEffectSimulation::debug(participantPos) ;
return polygonf.containsPoint(participantPos, Qt::OddEvenFill);
}
bool HandlerParticipantBoobyTrap::enteredOrCrossedArea(const QPolygonF &polygonf, const QPolygonF &participantStep) const
{
#if QT_VERSION < QT_VERSION_CHECK(5,10,0)
bool result = polygonf.intersected(participantStep).size() > 0;
#else
bool result = polygonf.intersects(participantStep);
#endif
DEBUG_LOG(m_logger) << "enteredOrCrossedArea : " << CentralEffectSimulation::debug(participantStep[0])
<< " to " << CentralEffectSimulation::debug(participantStep[1])
<< " result = " << result;
for (int i = 0; i < polygonf.size(); i++)
{
const QPointF point = polygonf[i];
DEBUG_LOG(m_logger) << "polygonf[" << i << "]="
<< point.x() << "/" << point.y();
}
for (int i = 0; i < participantStep.size(); i++)
{
const QPointF point = participantStep[i];
DEBUG_LOG(m_logger) << "participantStep[" << i << "]="
<< point.x() << "/" << point.y();
}
//return polygonf.containsPoint(participantStep, Qt::OddEvenFill);
return result;
}
void HandlerParticipantBoobyTrap::calculateBoobyTrapParticipantSecondary(const CentralEffectSimulation::AesItemViewUtm &aesItemView,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPos)
{
bool result;
const AreaEffectSimulation::BoobyTrap boobyTrap = m_ddsHandler->dtcAes()->boobyTrap(aesItemView.aesItemId);
const QPointF partPosGeo = QPointF(participantPos.pos().lon(), participantPos.pos().lat());
const QPointF impactPosGeo = QPointF(boobyTrap.impactPosition().lon(), boobyTrap.impactPosition().lat());
DEBUG_LOG(m_logger) << "calculateBoobyTrapParticipantSecondary itemView.id=" << aesItemView.aesItemId
<< " participantId=" << participantPos.participantId();
DEBUG_LOG(m_logger) << "BoobyTrap id = " << aesItemView.aesItemId
<< ", Box bottomLeft = " << CentralEffectSimulation::debug(aesItemView.boundingBoxBottomLeft)
<< ", topRight = " << CentralEffectSimulation::debug(aesItemView.boundingBoxTopRight);
bool completeEnclosed = false;
bool isGroundLevel = true;
int exerciseId = m_ddsHandler->getExerciseId();
QPolygonF polygonGeo;
polygonGeo.append(partPosGeo);
polygonGeo.append(impactPosGeo);
const QVector<int> &buildingIds = m_ddsHandler->dtcIsm()->getBuildingByPolygon(exerciseId, polygonGeo, completeEnclosed, isGroundLevel);
//dtcIsm.get()->getBuildingByPolygon(exerciseId, polygonGeo, completeEnclosed, isGroundLevel);
if ( buildingIds.size() > 0)
{
DEBUG_LOG(m_logger) << "Gebaeude verdeckt den Minentreffer participantId=" << participantPos.participantId();
return;
}
if (!aesItemView.boundingBox.containsPoint(partPosGeo, Qt::OddEvenFill))
DEBUG_LOG(m_logger) << "not in boundingBox " << participantPos.participantId();
else
DEBUG_LOG(m_logger) << "in boundingBox" << participantPos.participantId();
// const QPolygonF utmStepPoly = m_handlerParticipant->getParticipantStep(participantPos.participantId(), aesItemView.zone);
result = insideSecondaryArea(aesItemView.form, partPosGeo);
DEBUG_LOG(m_logger) << "insideSecondaryArea : "
<< " participantId=" << participantPos.participantId()
<< " aesItemId=" << aesItemView.aesItemId
<< " result=" << result;
// const bool result = enteredOrCrossedArea(aesItemView.form, partPosGeo);
DEBUG_LOG(m_logger) << "result BoobyTrap Explosion = " << result;
if (result)
{
DEBUG_LOG(m_logger) << "sendParticipantEvent";
sendParticipantEvent(aesItemView, participantPos, ProjectDataManagement::EventType_def::HitMine);
DEBUG_LOG(m_logger) << "sendParticipantHit";
sendParticipantHit(aesItemView, participantPos, ProjectDataManagement::EventType_def::HitMine);
}
} // calculateBoobyTrapParticipantSecondary
// return true, if participant is inside of the bounding Box
bool HandlerParticipantBoobyTrap::intersectsBoundingBoxCheck(const CentralEffectSimulation::AesItemViewUtm &itemView,
const int participantId)
{
bool result = false;
DEBUG_LOG(m_logger) << "intersectsBoundingBoxCheck participantId=" << participantId
<< " itemViewId=" << itemView.aesItemId
<< " m_zone=" << itemView.zone;
const QPolygonF stepPoly = m_handlerParticipant->getParticipantStep(participantId, itemView.zone);
if (stepPoly.size() < 2)
return false;
DEBUG_LOG(m_logger) << "stepPoly von=" << stepPoly.at(0).x() << "/" << stepPoly.at(0).y()
<< " bis=" << stepPoly.at(1).x() << "/" << stepPoly.at(1).y()
<< " m_zone=" << itemView.zone;
DEBUG_LOG(m_logger) << "ItemView Bounding Box BottomLeft=" << itemView.boundingBoxBottomLeft.x() << "/" << itemView.boundingBoxBottomLeft.y()
<< " boundingBoxTopRight=" << itemView.boundingBoxTopRight.x() << "/" << itemView.boundingBoxTopRight.y();
#if QT_VERSION < QT_VERSION_CHECK(5,10,0)
result = itemView.boundingBox.intersected(stepPoly).size() > 0;
#else
result = itemView.boundingBox.intersects(stepPoly);
#endif
DEBUG_LOG(m_logger) << "HandlerMineAreas::intersectsBoundingBoxCheck result =" << result;
return result;
}
bool HandlerParticipantBoobyTrap::calculateBoobyTrapParticipant(const CentralEffectSimulation::AesItemViewUtm &aesItemView,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPos)
{
DEBUG_LOG(m_logger) << "calculateBoobyTrapParticipant itemView.id=" << aesItemView.aesItemId
<< " participantId=" << participantPos.participantId();
// Check coverage by a building
const AreaEffectSimulation::BoobyTrap boobyTrap = m_ddsHandler->dtcAes()->boobyTrap(aesItemView.aesItemId);
//const QPointF partPosGeo = CentralEffectSimulation::geographic2Utm(participantPos.pos(), aesItemView.zone);
//const QPointF impactPosGeo = CentralEffectSimulation::geographic2Utm(boobyTrap.impactPosition(), aesItemView.zone);
const QPointF partPosGeo = QPointF(participantPos.pos().lon(), participantPos.pos().lat());
const QPointF impactPosGeo = QPointF(boobyTrap.impactPosition().lon(), boobyTrap.impactPosition().lat());
bool completeEnclosed = false;
bool isGroundLevel = true;
int exerciseId = m_ddsHandler->getExerciseId();
QPolygonF polygonGeo;
polygonGeo.append(partPosGeo);
polygonGeo.append(impactPosGeo);
const QVector<int> &buildingIds = m_ddsHandler->dtcIsm()->getBuildingByPolygon(exerciseId, polygonGeo, completeEnclosed, isGroundLevel);
if (buildingIds.size() > 0)
{
DEBUG_LOG(m_logger) << "coverage by building id =" << buildingIds[0];
return false;
}
const QPointF partPosUtm = CentralEffectSimulation::geographic2Utm(participantPos.pos(), -1);
DEBUG_LOG(m_logger) << "BoobyTrap id = " << aesItemView.aesItemId
<< ", Box bottomLeft = " << CentralEffectSimulation::debug(aesItemView.boundingBoxBottomLeft)
<< ", topRight = " << CentralEffectSimulation::debug(aesItemView.boundingBoxTopRight)
<< " participantPos=" << partPosUtm.x() << "/" << partPosUtm.y();
if (!aesItemView.boundingBox.containsPoint(partPosUtm, Qt::OddEvenFill))
{
DEBUG_LOG(m_logger) << "not in boundingBox " << participantPos.participantId();
bool intersectsBoundingBox = intersectsBoundingBoxCheck(aesItemView, participantPos.participantId());
if (!intersectsBoundingBox)
{
DEBUG_LOG(m_logger) << "Continue nach Bounding BoxCheck itemView: " << aesItemView.aesItemId << ", "
<< " paricipantId=" << participantPos.participantId();
return false;
}
}
else
DEBUG_LOG(m_logger) << "in boundingBox participantId=" << participantPos.participantId();
const QPolygonF posStepPoly = m_handlerParticipant->getParticipantStep(participantPos.participantId(), aesItemView.zone);
if (posStepPoly.size() < 2)
return false;
const bool result = enteredOrCrossedArea(aesItemView.form, posStepPoly);
DEBUG_LOG(m_logger) << "enteredOrCrossedArea : "
<< " participantId=" << participantPos.participantId()
<< " aesItemId=" << aesItemView.aesItemId
<< " result=" << result;
// const bool result = enteredOrCrossedArea(aesItemView.form, partPosGeo);
DEBUG_LOG(m_logger) << "result BoobyTrap Explosion = " << result;
if (result)
{
DEBUG_LOG(m_logger) << "sendFtcBoobyTrapTrigger id=" << aesItemView.aesItemId;
sendFtcBoobyTrapTrigger(aesItemView.aesItemId);
DEBUG_LOG(m_logger) << "sendParticipantEvent";
sendParticipantEvent(aesItemView, participantPos, ProjectDataManagement::EventType_def::HitMine);
DEBUG_LOG(m_logger) << "sendParticipantHit";
sendParticipantHit(aesItemView, participantPos, ProjectDataManagement::EventType_def::HitMine);
//calculateBoobyTrapParticipantsSecondary(aesItemView.aesItemId, participantPos.participantId() );
}
return true;
} // calculateBoobyTrapParticipant
void HandlerParticipantBoobyTrap::onParticipantPositionChanged(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &partPos)
{
// Bounding Box von der Linie
DEBUG_LOG(m_logger) << "ParicipantPos "
<< " participantId=" << partPos.participantId()
<< " participantTypeId=" << partPos.participantTypeId()
<< " participantPos: lat=" << partPos.pos().lat()
<< " lon=" << partPos.pos().lon()
<< " Anzahl BoobyTraps=" << m_boobyTrapItems.size();
if (partPos.vulnerabilityState == ProjectDataManagement::VulnerabilityState::inner_enum::CatastrophicKill)
{
DEBUG_LOG(m_logger) << "Not handle position: participant has vulnerability state CatastrophicKill";
return;
}
if (m_handlerParticipant->getEquipmentNumber(partPos.participantId()) == 0)
{
DEBUG_LOG(m_logger) << "Not handle position: participant has no equipment number";
return;
}
for (const CentralEffectSimulation::AesItemViewUtm &boobyTrap : qAsConst(m_boobyTrapItems))
{
if (!calculateBoobyTrapParticipant(boobyTrap, partPos))
continue;
DEBUG_LOG(m_logger) << "boobyTrap id = " << boobyTrap.aesItemId
<< ", Box bottomLeft = " << CentralEffectSimulation::debug(boobyTrap.boundingBoxBottomLeft)
<< ", topRight = " << CentralEffectSimulation::debug(boobyTrap.boundingBoxTopRight);
const QPolygonF posStepPoly = m_handlerParticipant->getParticipantStep(partPos.participantId(), boobyTrap.zone);
if (posStepPoly.size() < 2)
return;
const bool result = enteredOrCrossedArea(boobyTrap.form, posStepPoly);
DEBUG_LOG(m_logger) << "result BoobyTrap Explosion = " << result;
if (result)
sendParticipantEvent(boobyTrap, partPos, ProjectDataManagement::EventType_def::HitMine);
}
} // end of onParticipantPositionChanged()
//-----------------------------------------------------------------------------
// ///////////////////////////////////
// P D M (ProjectDataManagement)
// ///////////////////////////////////
// Search for corresponding aesItemView
// Check for all participants wheter he is in the explosion area
void HandlerParticipantBoobyTrap::sendParticipantEvent(const CentralEffectSimulation::AesItemViewUtm &boobyTrapItem,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
const ProjectDataManagement::EventType eventType)
{
DEBUG_LOG(m_logger) << "sendParticipantEvent aesItemId=" << boobyTrapItem.aesItemId
<< " participantId=" << participantPosition.participantId();
if ((m_triggeredMineParticipant.contains(boobyTrapItem.aesItemId))
&& (m_triggeredMineParticipant.value(boobyTrapItem.aesItemId) == participantPosition.participantId()))
{
DEBUG_LOG(m_logger) << "m_triggeredMineParticipant already sent "
<< " aesItemId=" << boobyTrapItem.aesItemId
<< " participantId=" << participantPosition.participantId();
return;
}
m_triggeredMineParticipant.insert(boobyTrapItem.aesItemId, participantPosition.participantId());
ParticipantManagement::TypeClass typeClass = m_handlerParticipant->typeClassFromTypeId(participantPosition.participantTypeId());
if (typeClass == ParticipantManagement::TypeClass_def::Unit ||
typeClass == ParticipantManagement::TypeClass_def::SupportUnit ||
typeClass == ParticipantManagement::TypeClass_def::SupportEntity ||
typeClass == ParticipantManagement::TypeClass_def::Unknown)
return;
int equipmentNumber = m_ddsHandler->participantId2EquipNo(participantPosition.participantId());
if (equipmentNumber <= 0)
return;
CentralEffectSimulation::ParticipantEvent pe;
if (m_boobyTraps.contains(boobyTrapItem.aesItemId))
{
INFO_LOG(m_logger) << "BoobyTrap Position found";
AreaEffectSimulation::BoobyTrap boobyTrap = m_boobyTraps.value(boobyTrapItem.aesItemId);
pe.position().lat(boobyTrap.impactPosition().lat());
pe.position().lon(boobyTrap.impactPosition().lon());
}
else
{
INFO_LOG(m_logger) << "No BoobyTrap Position found";
pe.position(participantPosition.pos());
}
const AreaEffectSimulation::BoobyTrap &bt = m_ddsHandler->dtcAes()->boobyTrap(boobyTrapItem.aesItemId);
DEBUG_LOG(m_logger) << "sendParticipantEvent participantId=" << participantPosition.participantId()
<< " lat= " << participantPosition.pos().lat()
<< " lon= " << participantPosition.pos().lon()
<< " equipmentNumber=" << equipmentNumber
<< " eventType=" << eventType;
pe.id(m_ddsHandler->getParticipantEventId());
pe.eventTypeId(eventType);
pe.participantId(participantPosition.participantId());
pe.eventTime(participantPosition.sampleTime());
pe.aesItemId(boobyTrapItem.aesItemId);
pe.partyId(participantPosition.partyId());
pe.aesName(bt.name());
pe.equipmentNumber(equipmentNumber);
pe.friendlyFire(boobyTrapItem.partyId == participantPosition.partyId());
m_ddsHandler->dtsCes()->publish(pe);
qint64 id = pe.id();
QTimer::singleShot(1 * 60 * 1000, this, [id, this]() { m_ddsHandler->dtsCes()->removeParticipantEventByKey(id); });
}
void HandlerParticipantBoobyTrap::sendParticipantHit(const CentralEffectSimulation::AesItemViewUtm &boobyTrap,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
const ProjectDataManagement::EventType eventType)
{
// Q_UNUSED(eventType); // not used - no alarm for this
const int equipNo = m_ddsHandler->participantId2EquipNo(participantPosition.participantId());
const int participantId = participantPosition.participantId();
const int originatorEquipNo = 0;
if ( equipNo == 0)
return;
Core::GeoPosition position;
// TODO: Hier wird die Mitte der Bounding-Box genommen und nicht die Position vom Participant
position.lat(participantPosition.pos().lat());
position.lon(participantPosition.pos().lon());
const TrainingAreaBase::TabPosition pos(position, participantPosition.reportingSource(), 0, 0);
int remainTasCodeIndirect = m_ddsHandler->remainingTasCode(boobyTrap.chargeStruct);
//pos.position(position);
//pos.reportingSource(participantPosition.reportingSource());
DEBUG_LOG(m_logger) << "sendParticipantHit participantId=" << participantId
<< " equipmentNumber=" << equipNo
<< " chargeTypeId=" << boobyTrap.chargeStruct.chargeTypeId()
<< " eventType=" << eventType
<< " remainTasCodeIndirect=" << remainTasCodeIndirect;
TrainingAreaBase::SendCesHitRequest requestTab(
equipNo, // equipmentNumber
participantId, // participantId
boobyTrap.chargeStruct.chargeTypeId(), // chargeTypeId
boobyTrap.aesItemId, // aesId
originatorEquipNo, // originatorEquipmentNumber
remainTasCodeIndirect, // IED heavy
pos,
boobyTrap.effectStart, // effectTime
eventType,
boobyTrap.partyId, // originPartyId
0
);
m_requestMap.insert(equipNo, requestTab);
if (!m_timer->isActive() && !m_requestMap.isEmpty())
m_timer->start(1000);
}
void HandlerParticipantBoobyTrap::onSendCesHitReply(const Core::FunctionReplyObject &replyObject)
{
//if (replyObject.error())
// WARNING_LOG(m_logger) << "Can not send hit on participant to training area: " << replyObject();
//else
DEBUG_LOG(m_logger) << "onSendCesHitReply for id " << replyObject.id() << " success";
}
void HandlerParticipantBoobyTrap::onBoobyTrapTriggerReply(const Core::FunctionReplyObject &replyObject)
{
if (replyObject.error())
ERROR_LOG(m_logger) << "Can not send BoobyTrapTriggerReply: " << replyObject();
else
DEBUG_LOG(m_logger) << "onBoobyTrapTriggerReply for id " << replyObject.id() << " success";
}
void HandlerParticipantBoobyTrap::sendFtcBoobyTrapTrigger(int aesItemId)
{
auto ftcAes = m_ddsHandler->ftcAes();
AreaEffectSimulation::BoobyTrapTriggerRequest hr;
hr.id(aesItemId);
hr.triggered(true);
DEBUG_LOG(m_logger) << "sendFtcAesRemoveBoobyTrap: id=" << hr;
ftcAes->boobyTrapTriggerRequest(hr, this);
}
void HandlerParticipantBoobyTrap::sendFtcCesHitRequestTimeout()
{
auto ftcTab = m_ddsHandler->ftcTab();
for (const TrainingAreaBase::SendCesHitRequest &hr : qAsConst(m_requestMap))
{
DEBUG_LOG(m_logger) << "sendFtcCesHitRequestTimeout: " << hr;
ftcTab->sendCesHitRequest(hr, this);
}
m_requestMap.clear();
}
} // namespace CesVirtualMines
@@ -0,0 +1,100 @@
/**
* Handler for player data
* $Id$
* $HeadURL$
* $Author$
* Created by gr, SLSE, 2017-02-20
*/
#pragma once
#include <CentralEffectSimulation/logger.h>
#include <AreaEffectSimulation/aes_dtc.h>
#include <CentralEffectSimulation/aes_item_view_utm.h>
#include <CentralEffectSimulation/dds_handler.h>
#include <CentralEffectSimulation/handler_participant.h>
#include <QTimer>
#include <QObject>
#include <QHash>
#include <QRectF>
#include <QPolygonF>
// AES-Handling for participants
namespace CesVirtualMines
{
class HandlerParticipantBoobyTrap final : public QObject
, protected TrainingAreaBase::Interface::Ftc::SendCesHitReplyHandler
, protected AreaEffectSimulation::Interface::Ftc::BoobyTrapTriggerReplyHandler
{
Q_OBJECT
public:
HandlerParticipantBoobyTrap(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &participantHandler,
QObject *parent = nullptr);
~HandlerParticipantBoobyTrap();
/**
* Initialize the handler to manage information from player management
*/
bool init();
protected:
void onSendCesHitReply(const Core::FunctionReplyObject &replyObject) override final;
void onBoobyTrapTriggerReply(const Core::FunctionReplyObject &replyObject) override final;
private Q_SLOTS:
/**
* Handle the signals from 'ParticipantHandler'
*/
void onParticipantPositionChanged(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &partPos);
/**
* Handle the signals from 'AES'
*/
void onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType);
void onBoobyTrapChanged(const AreaEffectSimulation::BoobyTrap &data, DataModification modType);
void sendFtcBoobyTrapTrigger(int aesItemId);
/**
* Send Hit to participant
*/
void sendFtcCesHitRequestTimeout();
private: // methoden
void sendParticipantEvent(const CentralEffectSimulation::AesItemViewUtm &boobyTrapItem,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
const ProjectDataManagement::EventType eventType);
void sendParticipantHit(const CentralEffectSimulation::AesItemViewUtm &boobyTrap,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
const ProjectDataManagement::EventType eventType);
bool insideSecondaryArea(const QPolygonF &polygonf, const QPointF &participantPos) const;
bool enteredOrCrossedArea(const QPolygonF &polygonf, const QPolygonF &participantStep) const;
bool calculateBoobyTrapParticipant(const CentralEffectSimulation::AesItemViewUtm &aesItemView, const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPos);
void calculateBoobyTrapParticipantSecondary(const CentralEffectSimulation::AesItemViewUtm &aesItemView, const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPos);
void calculateBoobyTrapParticipantsSecondary(int aesItemId, int participantId);
bool intersectsBoundingBoxCheck(const CentralEffectSimulation::AesItemViewUtm &itemView, const int participantId);
private: // attributes
std::shared_ptr<CentralEffectSimulation::DdsHandler> m_ddsHandler; ///< Pointer to VOM DDS handler
std::shared_ptr<CentralEffectSimulation::HandlerParticipant> m_handlerParticipant;
// AES-Values
QHash<int, AreaEffectSimulation::BoobyTrap> m_boobyTraps;
QHash<int, CentralEffectSimulation::AesItemViewUtm> m_boobyTrapItems; // key = aesItemId
QHash<int, CentralEffectSimulation::AesItemViewUtm> m_boobyTrapItemsSecondary; // key = aesItemId
QHash<int, int> m_triggeredMineParticipant; // key = aesItemId, value = participantId
QHash<int, TrainingAreaBase::SendCesHitRequest> m_requestMap; // Key = equipmentNumber
QTimer *m_timer;
CentralEffectSimulation::LOGGER_T &m_logger; ///< Interface to the Logging-Facility
};
} // namespace CesVirtualMines
@@ -0,0 +1,528 @@
/**
* Handler for player data
* $Id$
* $HeadURL$
* $Author$
* Created by gr, SLSE, 2017-02-20
*/
#include "handler_participant_off_route_mine.h"
#include <LtsCoordTrans/lts_coord_trans.h>
#include <QLineF>
#include <QTimer>
namespace CesVirtualMines
{
HandlerParticipantOffRouteMine::HandlerParticipantOffRouteMine(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &participantHandler,
QObject *parent)
: QObject(parent)
, m_ddsHandler(ddsHandler)
, m_handlerParticipant(participantHandler)
, m_offRouteMineItems()
, m_requestMap()
, m_timer(new QTimer(this))
, m_logger(CentralEffectSimulation::getLogger("Plugin.VirtualMines.HandlerParticipantOffRouteMine"))
{
INFO_LOG(m_logger) << "HandlerParticipantOffRouteMine::HandlerParticipantOffRouteMine";
m_timer->setSingleShot(true);
connect(m_timer, &QTimer::timeout, this, &HandlerParticipantOffRouteMine::sendFtcCesHitRequestTimeout);
} // end of ctor()
//-----------------------------------------------------------------------------
HandlerParticipantOffRouteMine::~HandlerParticipantOffRouteMine()
{
INFO_LOG(m_logger) << "HandlerParticipantOffRouteMine::~HandlerParticipantOffRouteMine";
} // end of dtor()
//-----------------------------------------------------------------------------
bool HandlerParticipantOffRouteMine::init()
{
INFO_LOG(m_logger) << "HandlerParticipantOffRouteMine::init";
auto dtcAes = m_ddsHandler->dtcAes();
auto ftcAes = m_ddsHandler->ftcAes();
auto dtcCes = m_ddsHandler->dtsCes();
dtcAes->waitForHistoricalDataOffRouteMine(2000);
dtcAes->waitForHistoricalDataAesItemView(2000);
ftcAes->enableOffRouteMineTrigger();
dtcCes->enableParticipantEvent();
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::offRouteMineChanged,
this, &HandlerParticipantOffRouteMine::onOffRouteMineChanged);
connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::aesItemViewChanged,
this, &HandlerParticipantOffRouteMine::onAesItemViewChanged);
connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::newOutdoorPosition,
this, &HandlerParticipantOffRouteMine::onParticipantPositionChanged);
// 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) << "HandlerParticipantOffRouteMine::init() finished. ";
return true;
} // end of init()
//-----------------------------------------------------------------------------
// ///////////////////////////////////
// A E S (AreaEffectSimulation)
// ///////////////////////////////////
void HandlerParticipantOffRouteMine::onOffRouteMineChanged(const AreaEffectSimulation::OffRouteMine &data, DataModification modType)
{
if (data.isDeleted()
|| data.effectStateId() == AreaEffectSimulation::AesEffectState::EsExpired
|| data.effectStateId() == AreaEffectSimulation::AesEffectState::EsRemoved
|| modType == DataModification::eRemoved)
{
m_offRouteMines.remove(data.id());
m_offRouteMineItems.remove(data.id());
m_offRouteMineItemsSecondary.remove(data.id());
return;
}
INFO_LOG(m_logger) << "HandlerParticipantOffRouteMine::onOffRouteMineChanged";
m_offRouteMines.insert(data.id(), data);
}
void HandlerParticipantOffRouteMine::onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType)
{
INFO_LOG(m_logger) << "HandlerParticipantOffRouteMine::onAesItemViewChanged";
if ( data.effectStateId() == AreaEffectSimulation::AesEffectState::EsExpired
|| data.effectStateId() == AreaEffectSimulation::AesEffectState::EsRemoved
|| modType == DataModification::eRemoved)
{
return;
}
//
if (data.aesTypeId() != AreaEffectSimulation::AesType_def::AtOffRouteMine
&& data.aesTypeId() != AreaEffectSimulation::AesType_def::AtOffRouteMineSecondary)
return;
const int aesItemId = data.aesItemId();
DEBUG_LOG(m_logger) << "Got AesItemView id: " << aesItemId
<< ", type: " << data.aesTypeId()
<< ", effectState: " << data.effectStateId()
<< ", modType: " << modType;
if (modType == DataModification::eAdded
|| modType == DataModification::eModified)
{
const AreaEffectSimulation::AesEffectState &effectState = data.effectStateId();
switch (effectState.underlying())
{
case AreaEffectSimulation::AesEffectState_def::EsActivated:
{
CentralEffectSimulation::AesItemViewUtm prevData;
const double impactRadius = 0;
prevData.aesItemId = 0;
const CentralEffectSimulation::AesItemViewUtm aesItemViewUtm = CentralEffectSimulation::AesItemViewUtm::create(data, prevData, impactRadius);
if (data.aesTypeId() == AreaEffectSimulation::AesType_def::AtOffRouteMine)
m_offRouteMineItems.insert(data.aesItemId(), aesItemViewUtm);
if (data.aesTypeId() == AreaEffectSimulation::AesType_def::AtOffRouteMineSecondary)
m_offRouteMineItemsSecondary.insert(data.aesItemId(), aesItemViewUtm);
// DEBUG_LOG(m_logger) << "Check each participant";
// // Check each participant
// const auto partPosMap = m_handlerParticipant->positions();
// for (const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPos : partPosMap)
// {
// if (m_handlerParticipant->isOutdated(participantPos))
// {
// DEBUG_LOG(m_logger) << "isOutdated participantId=" << participantPos.participantId() << " continue";
// continue;
// }
// if (participantPos.insideBuilding())
// {
// DEBUG_LOG(m_logger) << "inside Building participantId=" << participantPos.participantId() << " continue";
// continue;
// }
// if (participantPos.vulnerabilityState == ProjectDataManagement::VulnerabilityState::inner_enum::CatastrophicKill)
// {
// DEBUG_LOG(m_logger) << "CatastrophicKill participantId=" << participantPos.participantId() << " continue";
// continue;
// }
//// if (participantPos.sampleTime() < data.sampleTime())
//// {
//// DEBUG_LOG(m_logger) << " the time of the participant is older than the OffRouteMine participantId=" << participantPos.participantId();
//// continue;
//// }
// DEBUG_LOG(m_logger) << "pos participantId=" << participantPos.participantId()
// << " buildingId=" << participantPos.buildingId()
// << " insideBuilding=" << participantPos.insideBuilding()
// << " positionValid=" << participantPos.positionValid;
// const CentralEffectSimulation::AesItemViewUtm aesItemView = m_offRouteMineItems.value(data.aesItemId());
// calculateOffRouteMineParticipant(aesItemView, participantPos);
// }
break;
}
default:
{
DEBUG_LOG(m_logger) << "remove OffRouteMine";
m_offRouteMineItems.remove(aesItemId);
}
}
return;
}
} // onAesItemViewChanged
void HandlerParticipantOffRouteMine::calculateOffRouteMineParticipantsSecondary(int aesItemId)
{
DEBUG_LOG(m_logger) << "calculateOffRouteMineParticipantsSecondary : aesItemId=" << aesItemId;
const auto partPosMap = m_handlerParticipant->positions();
for (const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPos : partPosMap)
{
if (m_handlerParticipant->isOutdated(participantPos))
{
// DEBUG_LOG(m_logger) << "isOutdated participantId=" << participantPos.participantId();
continue;
}
const CentralEffectSimulation::AesItemViewUtm aesItemView = m_offRouteMineItemsSecondary.value(aesItemId);
calculateOffRouteMineParticipantSecondary(aesItemView, participantPos);
}
}
bool HandlerParticipantOffRouteMine::insideSecondaryArea(const QPolygonF &polygonf, const QPointF &participantPos) const
{
DEBUG_LOG(m_logger) << "pos to check: " << CentralEffectSimulation::debug(participantPos) ;
return polygonf.containsPoint(participantPos, Qt::OddEvenFill);
}
bool HandlerParticipantOffRouteMine::enteredOrCrossedArea(const QPolygonF &polygonf, const QPolygonF &participantStep) const
{
#if QT_VERSION < QT_VERSION_CHECK(5,10,0)
bool result = polygonf.intersected(participantStep).size() > 0;
#else
bool result = polygonf.intersects(participantStep);
#endif
DEBUG_LOG(m_logger) << "enteredOrCrossedArea : " << CentralEffectSimulation::debug(participantStep[0])
<< " to " << CentralEffectSimulation::debug(participantStep[1])
<< " result = " << result;
for (int i = 0; i < polygonf.size(); i++)
{
const QPointF point = polygonf[i];
DEBUG_LOG(m_logger) << "polygonf[" << i << "]="
<< point.x() << "/" << point.y();
}
for (int i = 0; i < participantStep.size(); i++)
{
const QPointF point = participantStep[i];
DEBUG_LOG(m_logger) << "participantStep[" << i << "]="
<< point.x() << "/" << point.y();
}
//return polygonf.containsPoint(participantStep, Qt::OddEvenFill);
return result;
}
void HandlerParticipantOffRouteMine::calculateOffRouteMineParticipantSecondary(const CentralEffectSimulation::AesItemViewUtm &aesItemView,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPos)
{
bool result;
const QPointF partPosGeo = CentralEffectSimulation::geographic2Utm(participantPos.pos(), aesItemView.zone);
DEBUG_LOG(m_logger) << "calculateOffRouteMineParticipantSecondary itemView.id=" << aesItemView.aesItemId
<< " participantId=" << participantPos.participantId();
DEBUG_LOG(m_logger) << "OffRouteMine id = " << aesItemView.aesItemId
<< ", Box bottomLeft = " << CentralEffectSimulation::debug(aesItemView.boundingBoxBottomLeft)
<< ", topRight = " << CentralEffectSimulation::debug(aesItemView.boundingBoxTopRight);
const QPolygonF boundingBoxAesItemView({QPointF(aesItemView.boundingBoxBottomLeft.x(),
aesItemView.boundingBoxBottomLeft.y()),
QPointF(aesItemView.boundingBoxTopRight.x(),
aesItemView.boundingBoxBottomLeft.y()),
QPointF(aesItemView.boundingBoxTopRight.x(),
aesItemView.boundingBoxTopRight.y()),
QPointF(aesItemView.boundingBoxBottomLeft.x(),
aesItemView.boundingBoxTopRight.y())
});
// if (!boundingBoxAesItemView.containsPoint(partPosGeo, Qt::OddEvenFill))
// {
// DEBUG_LOG(m_logger) << "not in boundingBox";
// return;
// }
result = insideSecondaryArea(aesItemView.form, partPosGeo);
DEBUG_LOG(m_logger) << "insideSecondaryArea : "
<< " participantId=" << participantPos.participantId()
<< " aesItemId=" << aesItemView.aesItemId
<< " result=" << result;
// const bool result = enteredOrCrossedArea(aesItemView.form, partPosGeo);
DEBUG_LOG(m_logger) << "result OffRouteMine Explosion = " << result;
if (result)
{
DEBUG_LOG(m_logger) << "sendParticipantEvent";
sendParticipantEvent(aesItemView, participantPos, ProjectDataManagement::EventType_def::HitMine); //69
DEBUG_LOG(m_logger) << "sendParticipantHit";
sendParticipantHit(aesItemView, participantPos, ProjectDataManagement::EventType_def::HitMine); // 49
}
} // calculateOffRouteMineParticipantSecondary
void HandlerParticipantOffRouteMine::calculateOffRouteMineParticipant(const CentralEffectSimulation::AesItemViewUtm &aesItemView,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPos)
{
DEBUG_LOG(m_logger) << "calculateOffRouteMineParticipant itemView.id=" << aesItemView.aesItemId
<< " participantId=" << participantPos.participantId();
DEBUG_LOG(m_logger) << "OffRouteMine id = " << aesItemView.aesItemId
<< ", Box bottomLeft = " << CentralEffectSimulation::debug(aesItemView.boundingBoxBottomLeft)
<< ", topRight = " << CentralEffectSimulation::debug(aesItemView.boundingBoxTopRight);
const QPolygonF posStepPoly = m_handlerParticipant->getParticipantStep(participantPos.participantId(), m_zone);
if (posStepPoly.size() < 2)
return;
const bool result = enteredOrCrossedArea(aesItemView.form, posStepPoly);
DEBUG_LOG(m_logger) << "enteredOrCrossedArea : "
<< " participantId=" << participantPos.participantId()
<< " aesItemId=" << aesItemView.aesItemId
<< " result=" << result;
// const bool result = enteredOrCrossedArea(aesItemView.form, partPosGeo);
DEBUG_LOG(m_logger) << "result OffRouteMine Explosion = " << result;
if (result)
{
DEBUG_LOG(m_logger) << "sendFtcOffRouteMineTrigger id=" << aesItemView.aesItemId;
sendFtcOffRouteMineTrigger(aesItemView.aesItemId);
DEBUG_LOG(m_logger) << "sendParticipantEvent";
sendParticipantEvent(aesItemView, participantPos, ProjectDataManagement::EventType_def::HitMine);
DEBUG_LOG(m_logger) << "sendParticipantHit";
sendParticipantHit(aesItemView, participantPos, ProjectDataManagement::EventType_def::HitMine);
calculateOffRouteMineParticipantsSecondary(aesItemView.aesItemId);
}
} // calculateOffRouteMineParticipant
void HandlerParticipantOffRouteMine::onParticipantPositionChanged(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &partPos)
{
ParticipantManagement::TypeClass typeClass = m_handlerParticipant->typeClassFromTypeId(partPos.participantTypeId());
// Bounding Box von der Linie
DEBUG_LOG(m_logger) << "ParicipantPos "
<< " participantId=" << partPos.participantId()
<< " participantTypeId=" << partPos.participantTypeId()
<< " typeClass=" << typeClass
<< " participantPos: lat=" << partPos.pos().lat()
<< " lon=" << partPos.pos().lon()
<< " Anzahl OffRouteMines=" << m_offRouteMineItems.size();
if (partPos.vulnerabilityState == ProjectDataManagement::VulnerabilityState::inner_enum::CatastrophicKill)
{
DEBUG_LOG(m_logger) << "Not handle position: participant has vulnerability state CatastrophicKill";
return;
}
if (typeClass != ParticipantManagement::TypeClass_def::GroundVehicle
&& typeClass != ParticipantManagement::TypeClass_def::WeaponSystem
&& typeClass != ParticipantManagement::TypeClass_def::VehicleWithGear)
{
INFO_LOG(m_logger) << "Not handle position: No type vehicle ";
return;
}
if (m_handlerParticipant->getEquipmentNumber(partPos.participantId()) == 0)
{
DEBUG_LOG(m_logger) << "Not handle position: participant has no equipment number";
return;
}
for (const CentralEffectSimulation::AesItemViewUtm &offRouteMine : qAsConst(m_offRouteMineItems))
{
calculateOffRouteMineParticipant(offRouteMine, partPos);
DEBUG_LOG(m_logger) << "offRouteMine id = " << offRouteMine.aesItemId
<< ", Box bottomLeft = " << CentralEffectSimulation::debug(offRouteMine.boundingBoxBottomLeft)
<< ", topRight = " << CentralEffectSimulation::debug(offRouteMine.boundingBoxTopRight);
const QPolygonF boundingBoxOffRouteMine({QPointF(offRouteMine.boundingBoxBottomLeft.x(),
offRouteMine.boundingBoxBottomLeft.y()),
QPointF(offRouteMine.boundingBoxTopRight.x(),
offRouteMine.boundingBoxBottomLeft.y()),
QPointF(offRouteMine.boundingBoxTopRight.x(),
offRouteMine.boundingBoxTopRight.y()),
QPointF(offRouteMine.boundingBoxBottomLeft.x(),
offRouteMine.boundingBoxTopRight.y())
});
// if (!boundingBoxOffRouteMine.containsPoint(partPosGeo, Qt::OddEvenFill))
// continue;
const QVector<QPointF> utmStepPoly = m_handlerParticipant->getParticipantStep(partPos.participantId(), m_zone);
QPolygonF posStepPoly;
if (utmStepPoly.size() < 2)
return;
posStepPoly.append(utmStepPoly[0]);
posStepPoly.append(utmStepPoly[1]);
const bool result = enteredOrCrossedArea(offRouteMine.form, posStepPoly);
DEBUG_LOG(m_logger) << "result offRouteMine Explosion = " << result;
if (result)
sendParticipantEvent(offRouteMine, partPos, ProjectDataManagement::EventType_def::HitMine);
}
} // end of onParticipantPositionChanged()
//-----------------------------------------------------------------------------
// ///////////////////////////////////
// P D M (ProjectDataManagement)
// ///////////////////////////////////
// Search for corresponding aesItemView
// Check for all participants wheter he is in the explosion area
void HandlerParticipantOffRouteMine::sendParticipantEvent(const CentralEffectSimulation::AesItemViewUtm &offRouteItem,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
const ProjectDataManagement::EventType eventType)
{
ParticipantManagement::TypeClass typeClass = m_handlerParticipant->typeClassFromTypeId(participantPosition.participantTypeId());
if (typeClass == ParticipantManagement::TypeClass_def::Unit ||
typeClass == ParticipantManagement::TypeClass_def::SupportUnit ||
typeClass == ParticipantManagement::TypeClass_def::SupportEntity ||
typeClass == ParticipantManagement::TypeClass_def::Unknown)
return;
int equipmentNumber = m_ddsHandler->participantId2EquipNo(participantPosition.participantId());
if (equipmentNumber <= 0)
return;
CentralEffectSimulation::ParticipantEvent pe;
if (m_offRouteMines.contains(offRouteItem.aesItemId))
{
INFO_LOG(m_logger) << "OffRouteMine Position found";
AreaEffectSimulation::OffRouteMine offRouteMine = m_offRouteMines.value(offRouteItem.aesItemId);
pe.position().lat(offRouteMine.area().cornerBottomLeft().lat());
pe.position().lon(offRouteMine.area().cornerBottomLeft().lon());
}
else
{
INFO_LOG(m_logger) << "No OffRouteMine Position found";
pe.position(participantPosition.pos());
}
const AreaEffectSimulation::OffRouteMine &of = m_ddsHandler->dtcAes()->offRouteMine(offRouteItem.aesItemId);
DEBUG_LOG(m_logger) << "sendParticipantEvent participantId=" << participantPosition.participantId()
<< " lat= " << participantPosition.pos().lat()
<< " lon= " << participantPosition.pos().lon()
<< " equipmentNumber=" << equipmentNumber
<< " eventType=" << eventType
<< " Name=" << of.name();
pe.id(m_ddsHandler->getParticipantEventId());
pe.eventTypeId(eventType);
pe.participantId(participantPosition.participantId());
pe.eventTime(participantPosition.sampleTime());
pe.aesItemId(offRouteItem.aesItemId);
pe.partyId(participantPosition.partyId());
pe.aesName(of.name());
pe.equipmentNumber(equipmentNumber);
pe.friendlyFire(offRouteItem.partyId == participantPosition.partyId());
m_ddsHandler->dtsCes()->publish(pe);
qint64 id = pe.id();
QTimer::singleShot(1 * 60 * 1000, this, [id, this]() { m_ddsHandler->dtsCes()->removeParticipantEventByKey(id); });
}
void HandlerParticipantOffRouteMine::sendParticipantHit(const CentralEffectSimulation::AesItemViewUtm &offRouteMine,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
const ProjectDataManagement::EventType eventType)
{
const int equipNo = m_ddsHandler->participantId2EquipNo(participantPosition.participantId());
const int participantId = participantPosition.participantId();
const int originatorEquipNo = 0;
DEBUG_LOG(m_logger) << "sendParticipantHit participantId=" << participantId
<< " equipmentNumber=" << equipNo;
Core::GeoPosition position;
// TODO: Hier wird die Mitte der Bounding-Box genommen und nicht die Position vom Participant
position.lat(participantPosition.pos().lat());
position.lon(participantPosition.pos().lon());
const TrainingAreaBase::TabPosition pos(position, participantPosition.reportingSource(), 0, 0);
//pos.position(position);
//pos.reportingSource(participantPosition.reportingSource());
int remainTasCodeIndirect = m_ddsHandler->remainingTasCode(offRouteMine.chargeStruct); // 69
// [GUEZE-3033] Kundenwunsch bei RiMi2 zur Wirkung: Huaprtwirkung im Sekundaerbereich
// if (offRouteMine.aesTypeId == AreaEffectSimulation::AesType::AtOffRouteMineSecondary)
// remainTasCodeIndirect = m_ddsHandler->secondaryRemainingTasCode(offRouteMine.chargeTypeId); // 49
TrainingAreaBase::SendCesHitRequest requestTab(
equipNo, // equipmentNumber
participantId, // participantId
offRouteMine.chargeStruct.chargeTypeId(), // chargeTypeId
offRouteMine.aesItemId, // aesId
originatorEquipNo, // originatorEquipmentNumber
remainTasCodeIndirect, // IED heavy
pos,
offRouteMine.effectStart, // effectTime
eventType,
offRouteMine.partyId, // originPartyId
0
);
m_requestMap.insert(equipNo, requestTab);
if (!m_timer->isActive() && !m_requestMap.isEmpty())
m_timer->start(1000);
}
void HandlerParticipantOffRouteMine::onSendCesHitReply(const Core::FunctionReplyObject &replyObject)
{
//if (replyObject.error())
// WARNING_LOG(m_logger) << "Can not send hit on participant to training area: " << replyObject();
//else
DEBUG_LOG(m_logger) << "onSendCesHitReply for id " << replyObject.id() << " success";
}
void HandlerParticipantOffRouteMine::onOffRouteMineTriggerReply(const Core::FunctionReplyObject &replyObject)
{
if (replyObject.error())
ERROR_LOG(m_logger) << "Can not send OffRouteMineTriggerReply: " << replyObject();
else
DEBUG_LOG(m_logger) << "onOffRouteMineTriggerReply for id " << replyObject.id() << " success";
}
void HandlerParticipantOffRouteMine::sendFtcOffRouteMineTrigger(int aesItemId)
{
auto ftcAes = m_ddsHandler->ftcAes();
AreaEffectSimulation::OffRouteMineTriggerRequest hr;
hr.id(aesItemId);
hr.triggered(true);
DEBUG_LOG(m_logger) << "send OffRouteMineTriggerRequest: id=" << hr;
ftcAes->offRouteMineTriggerRequest(hr, this);
}
void HandlerParticipantOffRouteMine::sendFtcCesHitRequestTimeout()
{
auto ftcTab = m_ddsHandler->ftcTab();
for (const TrainingAreaBase::SendCesHitRequest &hr : qAsConst(m_requestMap))
{
DEBUG_LOG(m_logger) << "sendFtcCesHitRequestTimeout: " << hr;
ftcTab->sendCesHitRequest(hr, this);
}
m_requestMap.clear();
}
} // namespace CesVirtualMines
@@ -0,0 +1,97 @@
/**
* Handler for player data
* $Id$
* $HeadURL$
* $Author$
* Created by gr, SLSE, 2017-02-20
*/
#pragma once
#include <AreaEffectSimulation/aes_dtc.h>
#include <CentralEffectSimulation/dds_handler.h>
#include <CentralEffectSimulation/aes_item_view_utm.h>
#include <CentralEffectSimulation/handler_participant.h>
#include <QTimer>
#include <QObject>
#include <QHash>
#include <QRectF>
#include <QPolygonF>
// AES-Handling for participants
namespace CesVirtualMines
{
class HandlerParticipantOffRouteMine final : public QObject
, protected TrainingAreaBase::Interface::Ftc::SendCesHitReplyHandler
, protected AreaEffectSimulation::Interface::Ftc::OffRouteMineTriggerReplyHandler
{
Q_OBJECT
public:
HandlerParticipantOffRouteMine(const std::shared_ptr<CentralEffectSimulation::DdsHandler> &ddsHandler,
const std::shared_ptr<CentralEffectSimulation::HandlerParticipant> &participantHandler,
QObject *parent = nullptr);
~HandlerParticipantOffRouteMine();
/**
* Initialize the handler to manage information from player management
*/
bool init();
protected:
void onSendCesHitReply(const Core::FunctionReplyObject &replyObject) override final;
void onOffRouteMineTriggerReply(const Core::FunctionReplyObject &replyObject) override final;
private Q_SLOTS:
/**
* Handle the signals from 'ParticipantHandler'
*/
void onParticipantPositionChanged(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &partPos);
/**
* Handle the signals from 'AES'
*/
void onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType);
void onOffRouteMineChanged(const AreaEffectSimulation::OffRouteMine &data, DataModification modType);
void sendFtcOffRouteMineTrigger(int aesItemId);
/**
* Send Hit to participant
*/
void sendFtcCesHitRequestTimeout();
private: // methoden
void sendParticipantEvent(const CentralEffectSimulation::AesItemViewUtm &offRouteItem,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
const ProjectDataManagement::EventType eventType);
void sendParticipantHit(const CentralEffectSimulation::AesItemViewUtm &offRouteMine,
const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPosition,
const ProjectDataManagement::EventType eventType);
bool insideSecondaryArea(const QPolygonF &polygonf, const QPointF &participantPos) const;
bool enteredOrCrossedArea(const QPolygonF &polygonf, const QPolygonF &participantStep) const;
void calculateOffRouteMineParticipant(const CentralEffectSimulation::AesItemViewUtm &aesItemView, const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPos);
void calculateOffRouteMineParticipantSecondary(const CentralEffectSimulation::AesItemViewUtm &aesItemView, const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPos);
void calculateOffRouteMineParticipantsSecondary(int aesItemId);
private: // attributes
std::shared_ptr<CentralEffectSimulation::DdsHandler> m_ddsHandler; ///< Pointer to VOM DDS handler
std::shared_ptr<CentralEffectSimulation::HandlerParticipant> m_handlerParticipant;
// AES-Values
QHash<int, AreaEffectSimulation::OffRouteMine> m_offRouteMines;
QHash<int, CentralEffectSimulation::AesItemViewUtm> m_offRouteMineItems; // key = aesItemId
QHash<int, CentralEffectSimulation::AesItemViewUtm> m_offRouteMineItemsSecondary; // key = aesItemId
QHash<int, TrainingAreaBase::SendCesHitRequest> m_requestMap; // Key = equipmentNumber
QTimer *m_timer;
int m_zone = -1;
CentralEffectSimulation::LOGGER_T &m_logger; ///< Interface to the Logging-Facility
};
} // namespace CesVirtualMines
@@ -0,0 +1,93 @@
/**
* Plugin Ces Virtual Mines
* $Id$
* $HeadURL$
* $Author$
* Created by Gerlinde Rudolphus, SLTE, 2016-04-14
*/
#include "plugin.h"
#include <ngldb/db_service_handler.h>
namespace CesVirtualMines
{
std::shared_ptr<CentralEffectSimulation::Plugin::Interface> CesVirtualMinesPlugin::createInterface(CentralEffectSimulation::Plugin::DataProvider *pdp,
const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
NGL::Settings *settings,
CentralEffectSimulation::MainHandler *mainHandler)
{
return std::make_shared<CesVirtualMinesInterfaceImpl>(pdp, dDSConnector, settings, mainHandler);
}
CesVirtualMinesInterfaceImpl::CesVirtualMinesInterfaceImpl(CentralEffectSimulation::Plugin::DataProvider *pdp,
const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
NGL::Settings *settings,
CentralEffectSimulation::MainHandler *mainHandler)
: m_pdp(pdp)
, m_ddsConnector(dDSConnector)
, m_mainHandler(mainHandler)
, m_ddsHandler(m_mainHandler->dds())
, m_db(m_mainHandler->db())
, m_handlerParticipant(m_mainHandler->handlerParticipant())
, m_logger(CentralEffectSimulation::getLogger("Plugin.VirtualMines.CesMinesInterfaceImpl"))
{
Q_UNUSED(settings)
}
CesVirtualMinesInterfaceImpl::~CesVirtualMinesInterfaceImpl()
{
m_handlerParticipantBoobyTrap.reset();
m_handlerParticipantOffRouteMine.reset();
}
bool CesVirtualMinesInterfaceImpl::init(int domainId, int exerciseId)
{
m_domainId = domainId;
m_exerciseId = exerciseId;
INFO_LOG(m_logger) << "CesVirtualMinesInterfaceImpl::init()"
<< " m_domainId=" << m_domainId
<< " m_exerciseId=" << m_exerciseId;
// initialize handlerBoobyTrap
m_handlerParticipantBoobyTrap = std::make_shared<HandlerParticipantBoobyTrap>(m_ddsHandler,
m_handlerParticipant,
this);
if (!m_handlerParticipantBoobyTrap->init())
{
ERROR_LOG(m_logger) << "Initialisation m_handlerParticipantBoobyTrap failed.";
return false;
}
// initialize offRouteMine
m_handlerParticipantOffRouteMine = std::make_shared<HandlerParticipantOffRouteMine>(m_ddsHandler,
m_handlerParticipant,
this);
if (!m_handlerParticipantOffRouteMine->init())
{
ERROR_LOG(m_logger) << "Initialisation m_handlerParticipantOffRouteMine failed.";
return false;
}
return true;
}
QString CesVirtualMinesInterfaceImpl::echo(const QString &message)
{
QString ret(QStringLiteral("<<<< %1 >>>> CesVirtualMinesInterfaceImpl::echo").arg(message));
INFO_LOG(m_logger) << "CesVirtualMinesInterfaceImpl::echo return:" << ret;
DEBUG_LOG(m_logger) << "DEBUG: CesVirtualMinesInterfaceImpl::echo return:" << ret;
return ret;
}
} //namespace CesVirtualMines
@@ -0,0 +1,76 @@
/**
* Plugin Ces Virtual Mines
* $Id$
* $HeadURL$
* $Author$
* Created by Gerlinde Rudolphus, SLTE, 2016-04-14
*/
#pragma once
#include <CentralEffectSimulation/logger.h>
#include "handler_participant_booby_trap.h"
#include "handler_participant_off_route_mine.h"
#include <CentralEffectSimulation/ces_plugin_interface.h>
#include <CentralEffectSimulation/main_handler.h>
#include <CentralEffectSimulation/dds_handler.h>
#include <DDS/DDSConnector/dds_connector.h>
#include <QObject>
namespace CesVirtualMines
{
class CesVirtualMinesPlugin : public QObject, public CentralEffectSimulation::Plugin::Plugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "special:3:ces.CesVirtualMinesPlugin")
Q_INTERFACES(CentralEffectSimulation::Plugin::Plugin)
public:
CesVirtualMinesPlugin() = default;
~CesVirtualMinesPlugin() = default;
std::shared_ptr<CentralEffectSimulation::Plugin::Interface> createInterface(CentralEffectSimulation::Plugin::DataProvider *pdp,
const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
NGL::Settings *settings,
CentralEffectSimulation::MainHandler *mainHandler) override;
};
class CesVirtualMinesInterfaceImpl final : public CentralEffectSimulation::Plugin::Interface
{
Q_OBJECT
public:
CesVirtualMinesInterfaceImpl(CentralEffectSimulation::Plugin::DataProvider *pdp,
const std::shared_ptr<DDSConnector::DdsConnector> &dDSConnector,
NGL::Settings *settings,
CentralEffectSimulation::MainHandler *mainHandler);
~CesVirtualMinesInterfaceImpl();
//bool init();
const char *name() const override { return "CentralEffectVirtualMines"; }
QString echo(const QString &message) override;
private Q_SLOTS:
bool init(int domainId, int exerciseId) override;
private:
private:
CentralEffectSimulation::Plugin::DataProvider *m_pdp;
std::shared_ptr<DDSConnector::DdsConnector> m_ddsConnector;
CentralEffectSimulation::MainHandler *m_mainHandler{nullptr};
std::shared_ptr<CentralEffectSimulation::DdsHandler> m_ddsHandler;
std::shared_ptr<CentralEffectSimulation::DatabaseInterface> m_db;
std::shared_ptr<CentralEffectSimulation::HandlerParticipant> m_handlerParticipant; ///< Pointer to handler for all participants
std::shared_ptr<HandlerParticipantBoobyTrap> m_handlerParticipantBoobyTrap; ///< Pointer to handler for BoobyTrap
std::shared_ptr<HandlerParticipantOffRouteMine> m_handlerParticipantOffRouteMine; ///< Pointer to handler for OffRouteMine
CentralEffectSimulation::LOGGER_T &m_logger; ///< Interface to the Logging-Facility
int m_domainId = 0;
int m_exerciseId = 0;
};
} // namespace CesVirtualMines