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,830 @@
/**
* Handler for all oc situation data at the server per client
* $Id: handler_oc_situation_data.cpp 57938 2022-08-26 09:56:44Z diers $
* $HeadURL: svn://192.168.133.21/TDS/branches/product/features/3dws_devel/Lts/Services/OcSituationServer/handler_oc_situation_data.cpp $
* $Author: diers $
* Created by Philipp Dassow, NLST, 27-02-2018
*/
#include "handler_oc_central_aes_data.h"
#include <LtsCoordTrans/lts_coord_trans.h>
#include <LtsUtilsCore/qbytearray_byteaccess.h>
#include <LtsUtilsCore/dds_vector.h>
#include <LtsUtilsCore/outdated_position.h>
#include <ParticipantManagement/ppm_common.h>
#include "settings.h"
#include <QLineF>
#include "central_aes_data_queue.h"
#include <QMultiMap>
namespace OcSituationServer
{
////
//// ThreadOcSituationData
////
ThreadOcCentralAesData::ThreadOcCentralAesData(MainHandler *mainHandler,
int equipmentId,
int centerEquipmentId,
int radius)
: m_baseCoordinate(mainHandler->positionConverter()->baseCoordinate())
, m_equipmentId(equipmentId)
, m_centerEquipmentId(centerEquipmentId)
, m_radius(radius)
, m_mainHandler(mainHandler)
, m_logger(getLogger(QStringLiteral("ThreadOcCentralAesData.") + QString::number(equipmentId)))
{}
void ThreadOcCentralAesData::requestOcCentralAesData(OcSituation::SituationCenterType centerType,
int centerEquipmentId,
const Core::GeoPosition2D &position,
int radius,
bool initial)
{
INFO_LOG(m_logger) << "OC-Situation Request for centerEquipmentId: " << centerEquipmentId
<< " from O/C-laptop-Id: " << m_equipmentId
<< " with radius of " << radius
<< "m, initial: " << initial;
QMutexLocker l(&m_accessMutex);
m_centerType = centerType;
m_centerEquipmentId = centerEquipmentId;
m_radius = radius;
m_position = position;
if (m_handler)
m_handler->setRequestCentralAesData(centerType, centerEquipmentId, position, radius, initial);
else
DEBUG_LOG(m_logger) << "Thread doesn't exist up to now! Do nothing.";
}
void ThreadOcCentralAesData::run()
{
static QMutex s_ddsAccesMutex;
{
QMutexLocker l(&m_accessMutex);
QMutexLocker m(&s_ddsAccesMutex);
DEBUG_LOG(m_logger) << "Instance new OC-Thread for O/C-Laptop-Id: " << m_equipmentId;
m_handler = new HandlerOcCentralAesData(m_mainHandler->dds(),
m_baseCoordinate,
m_equipmentId);
connect(m_handler, &HandlerOcCentralAesData::sendOcData, this, &ThreadOcCentralAesData::sendOcData, Qt::QueuedConnection);
m_handler->setRequestCentralAesData(m_centerType, m_centerEquipmentId, m_position, m_radius, true);
}
INFO_LOG(m_logger) << "OC-Thread started for O/C-Laptop-Id: " << m_equipmentId;
exec();
{
QMutexLocker l(&m_accessMutex);
QMutexLocker m(&s_ddsAccesMutex);
delete m_handler;
m_handler = nullptr;
}
}
//
// HandlerOcSituationData
//
HandlerOcCentralAesData::HandlerOcCentralAesData(const std::shared_ptr<DdsHandler> &dds,
const LtsCoordTrans::UtmCoordinate &baseCoordinate,
int equipmentId)
: m_baseCoordinate(baseCoordinate)
, m_aesDtc(AreaEffectSimulation::Interface::Dtc::create(dds->dds()))
, m_ppmDtc(ParticipantManagement::Interface::Dtc::create(dds->dds()))
, m_equipmentId(equipmentId)
, m_partitionTime(QDateTime::currentMSecsSinceEpoch())
, m_aliveTimer(new QTimer(this))
, m_txTimer(new QTimer(this))
, m_dataQueue(new CentralAesDataQueue(this))
, m_logger(getLogger(QStringLiteral("HandlerOcCentralAesData.") + QString::number(equipmentId)))
{
INFO_LOG(m_logger) << "Create O/C-CentralAesHandler for O/C-Laptop-Id: " << equipmentId
<< " aliveTimeout: " << Settings::aliveTimeout() << " sec"
<< " txCyleTime: " << Settings::txCycleTime() << " sec"
<< " maxTransferBytes: " << Settings::maxNumOfBytePerTxCycle();
connect(dds.get(), &DdsHandler::partitionTimeChanged, this, &HandlerOcCentralAesData::onPartitionTimeChanged);
connect(m_aliveTimer, &QTimer::timeout, this, &HandlerOcCentralAesData::aliveTimeout);
m_aliveTimer->setSingleShot(true);
m_aliveTimer->start(Settings::aliveTimeout());
connect(m_txTimer, &QTimer::timeout, this, &HandlerOcCentralAesData::handleSituation);
m_txTimer->start(Settings::txCycleTime());
connect(this, &HandlerOcCentralAesData::resetInternalData,
this, &HandlerOcCentralAesData::onResetInternalData, Qt::QueuedConnection);
connect(m_ppmDtc.get(), &ParticipantManagement::Interface::Dtc::participantPositionChanged,
this, &HandlerOcCentralAesData::onParticipantPositionChanged);
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::effectClusterChanged,
this, &HandlerOcCentralAesData::onEffectClusterChanged);
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::nContaminationChanged,
this, &HandlerOcCentralAesData::onNContaminationChanged);
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::bCContaminationChanged,
this, &HandlerOcCentralAesData::onBCContaminationChanged);
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::explosionAreaChanged,
this, &HandlerOcCentralAesData::onExplosionAreaChanged);
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::explosionSingleChanged,
this, &HandlerOcCentralAesData::onExplosionSingleChanged);
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::mineAreaChanged,
this, &HandlerOcCentralAesData::onMineAreaChanged);
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::functionalAreaChanged,
this, &HandlerOcCentralAesData::onFunctionalAreaChanged);
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::boobyTrapChanged,
this, &HandlerOcCentralAesData::onBoobyTrapChanged);
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::offRouteMineChanged,
this, &HandlerOcCentralAesData::onOffRouteMineChanged);
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::explosionClusterChanged,
this, &HandlerOcCentralAesData::onExplosionClusterChanged);
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::aesItemViewChanged,
this, &HandlerOcCentralAesData::onAesItemViewChanged);
// fetch aes items
m_aesDtc->effectClusters([this](const AreaEffectSimulation::EffectCluster & data)
{
if (data.isCentral())
m_allCentralEffectClusters.insert(data.id(), data);
});
TRACE_LOG(m_logger) << "Got " << m_allCentralEffectClusters.size() << " central EffectClusters on startup.";
m_aesDtc->nContaminations([this](const AreaEffectSimulation::NContamination & data)
{
if (data.isCentral())
m_allCentralNContaminations.insert(data.id(), data);
});
TRACE_LOG(m_logger) << "Got " << m_allCentralNContaminations.size() << " central NContaminations on startup.";
m_aesDtc->bCContaminations([this](const AreaEffectSimulation::BCContamination & data)
{
if (data.isCentral())
m_allCentralBCContaminations.insert(data.id(), data);
});
TRACE_LOG(m_logger) << "Got " << m_allCentralBCContaminations.size() << " central BCContaminations on startup.";
m_aesDtc->explosionAreas([this](const AreaEffectSimulation::ExplosionArea & data)
{
if (data.isCentral())
m_allCentralExplosionsArea.insert(data.id(), data);
});
TRACE_LOG(m_logger) << "Got " << m_allCentralExplosionsArea.size() << " central ExplosionsAreas on startup.";
m_aesDtc->explosionSingles([this](const AreaEffectSimulation::ExplosionSingle & data)
{
if (data.isCentral())
m_allCentralExplosionsSingle.insert(data.id(), data);
});
TRACE_LOG(m_logger) << "Got " << m_allCentralExplosionsSingle.size() << " central ExplosionsSingles on startup.";
m_aesDtc->mineAreas([this](const AreaEffectSimulation::MineArea & data)
{
if (data.isCentral())
m_allCentralMineAreas.insert(data.id(), data);
});
TRACE_LOG(m_logger) << "Got " << m_allCentralMineAreas.size() << " central MineAreas on startup.";
m_aesDtc->functionalAreas([this](const AreaEffectSimulation::FunctionalArea & data)
{
if (data.isCentral())
m_allCentralFunctionalAreas.insert(data.id(), data);
});
TRACE_LOG(m_logger) << "Got " << m_allCentralFunctionalAreas.size() << " central FunctionalAreas on startup.";
m_aesDtc->boobyTraps([this](const AreaEffectSimulation::BoobyTrap & data)
{
if (data.isCentral())
m_allCentralBoobyTraps.insert(data.id(), data);
});
TRACE_LOG(m_logger) << "Got " << m_allCentralBoobyTraps.size() << " central BoobyTraps on startup.";
m_aesDtc->offRouteMines([this](const AreaEffectSimulation::OffRouteMine & data)
{
if (data.isCentral())
m_allCentralOffRouteMines.insert(data.id(), data);
});
TRACE_LOG(m_logger) << "Got " << m_allCentralOffRouteMines.size() << " central OffRouteMines on startup.";
m_aesDtc->explosionClusters([this](const AreaEffectSimulation::ExplosionCluster &data)
{
if (data.isCentral())
m_allCentralExplosionClusters.insert(data.id(), data);
});
TRACE_LOG(m_logger) << "Got " << m_allCentralExplosionClusters.size() << " central ExplosionClusters on startup.";
//fetch aes itemviews
QList<qint32> aesItemIds = allInternalAesItemIds();
m_aesDtc->aesItemViews([this, aesItemIds](const AreaEffectSimulation::AesItemView & data)
{
if (aesItemIds.contains(data.aesItemId()))
m_allCentralAesItemViews.insert(data.aesItemId(), data);
});
TRACE_LOG(m_logger) << "Got " << allInternalAesItemIds().size() << " central AesItems in total on startup. And " << m_allCentralAesItemViews.size() << " AesItemViews.";
m_aesDtc->enableEffectCluster();
m_aesDtc->enableNContamination();
m_aesDtc->enableBCContamination();
m_aesDtc->enableExplosionArea();
m_aesDtc->enableExplosionSingle();
m_aesDtc->enableMineArea();
m_aesDtc->enableFunctionalArea();
m_aesDtc->enableBoobyTrap();
m_aesDtc->enableOffRouteMine();
m_aesDtc->enableExplosionCluster();
m_aesDtc->enableAesItemView();
m_ppmDtc->enableParticipant();
}
void HandlerOcCentralAesData::setRequestCentralAesData(OcSituation::SituationCenterType centerType,
int centerEquipmentId,
const Core::GeoPosition2D &centerPosition,
int radius,
bool initial)
{
TRACE_LOG(m_logger) << "Thread " << QThread::currentThreadId() << " function: " << LOGFUNCTION;
QMutexLocker l(&m_accessMutex);
DEBUG_LOG(m_logger) << "Requested CenterEquipmentId: " << centerEquipmentId << " radius: " << radius;
bool endThread = false;
if (initial)
onResetInternalData();
m_centerType = centerType;
m_centerEquipmentId = centerEquipmentId;
m_centerPosition = centerPosition;
m_centerParticipantId = 0;
m_radius = radius;
if (centerType == OcSituation::SituationCenterType::Equipment)
{
if (m_centerEquipmentId > 0)
{
ParticipantManagement::Participant centerParticipant = m_ppmDtc->participant(m_ppmDtc->participantIdByEquipmentNumber(m_centerEquipmentId));
if (centerParticipant.id() <= 0)
{
ERROR_LOG(m_logger) << "Participant with EqId " << m_centerEquipmentId
<< " as center of the oc situation request does not exist!";
endThread = true;
}
else
{
const ParticipantManagement::ParticipantPosition &partPosition = m_ppmDtc->participantPosition(m_ppmDtc->participantIdByEquipmentNumber(m_centerEquipmentId));
if (partPosition.participantId() == 0)
{
ERROR_LOG(m_logger) << "Participant with EqId " << m_centerEquipmentId
<< " as center of the oc situation request has no position!";
endThread = true;
}
else
{
m_centerPosition = partPosition.pos();
m_centerParticipantId = centerParticipant.id();
}
}
if (endThread && ++m_retryCount < 5)
{
INFO_LOG(m_logger) << "Retry setting data - maybe participant is not yet available... " << m_retryCount;
QTimer::singleShot(1000 * m_retryCount, this, [this]()
{
// must be initial here
setRequestCentralAesData(m_centerType, m_centerEquipmentId, m_centerPosition, m_radius, true);
});
return;
}
}
else
{
INFO_LOG(m_logger) << "Situation is not requested anymore -> end thread";
endThread = true;
}
}
if (!endThread)
{
if (centerType == OcSituation::SituationCenterType::Equipment)
{
if (m_centerParticipantId == 0)
{
DEBUG_LOG(m_logger) << "m_centerParticipantId == 0";
endThread = true;
}
}
else if ((centerPosition.lon() == std::nan("")) || (centerPosition.lat() == std::nan("")))
{
DEBUG_LOG(m_logger) << "m_centerParticipantId == 0";
endThread = true;
}
}
m_retryCount = 0;
if (endThread)
m_radius = 0; // ==> no data transfer on handleSituation() and quit
buildSituationCircle();
QTimer::singleShot(0, this, &HandlerOcCentralAesData::resetAliveTimer);
if (endThread && !initial)
{
DEBUG_LOG(m_logger) << "Ending Thread --> stopping txTimer and resetting internal data.";
QTimer::singleShot(0, this, &HandlerOcCentralAesData::handleSituation);
emit resetInternalData();
}
}
void HandlerOcCentralAesData::onParticipantPositionChanged(const ParticipantManagement::ParticipantPosition &data, DataModification modType)
{
if (modType != DataModification::eModified
|| m_centerType != OcSituation::SituationCenterType::Equipment
|| data.participantId() != m_centerParticipantId)
return;
m_centerPosition = data.pos();
buildSituationCircle();
}
void HandlerOcCentralAesData::onEffectClusterChanged(const AreaEffectSimulation::EffectCluster &data, DataModification modType)
{
onAesItemChanged(m_allCentralEffectClusters, data, modType);
}
void HandlerOcCentralAesData::onNContaminationChanged(const AreaEffectSimulation::NContamination &data, DataModification modType)
{
onAesItemChanged(m_allCentralNContaminations, data, modType);
}
void HandlerOcCentralAesData::onBCContaminationChanged(const AreaEffectSimulation::BCContamination &data, DataModification modType)
{
onAesItemChanged(m_allCentralBCContaminations, data, modType);
}
void HandlerOcCentralAesData::onExplosionAreaChanged(const AreaEffectSimulation::ExplosionArea &data, DataModification modType)
{
onAesItemChanged(m_allCentralExplosionsArea, data, modType);
}
void HandlerOcCentralAesData::onExplosionSingleChanged(const AreaEffectSimulation::ExplosionSingle &data, DataModification modType)
{
onAesItemChanged(m_allCentralExplosionsSingle, data, modType);
}
void HandlerOcCentralAesData::onMineAreaChanged(const AreaEffectSimulation::MineArea &data, DataModification modType)
{
onAesItemChanged(m_allCentralMineAreas, data, modType);
}
void HandlerOcCentralAesData::onFunctionalAreaChanged(const AreaEffectSimulation::FunctionalArea &data, DataModification modType)
{
onAesItemChanged(m_allCentralFunctionalAreas, data, modType);
}
void HandlerOcCentralAesData::onBoobyTrapChanged(const AreaEffectSimulation::BoobyTrap &data, DataModification modType)
{
onAesItemChanged(m_allCentralBoobyTraps, data, modType);
}
void HandlerOcCentralAesData::onOffRouteMineChanged(const AreaEffectSimulation::OffRouteMine &data, DataModification modType)
{
onAesItemChanged(m_allCentralOffRouteMines, data, modType);
}
void HandlerOcCentralAesData::onExplosionClusterChanged(const AreaEffectSimulation::ExplosionCluster &data, DataModification modType)
{
onAesItemChanged(m_allCentralExplosionClusters, data, modType);
}
void HandlerOcCentralAesData::onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType)
{
const QVector<AreaEffectSimulation::AesType> validTypes = {AreaEffectSimulation::AesType::inner_enum::AtEffectCluster,
AreaEffectSimulation::AesType::inner_enum::AtNContamination,
AreaEffectSimulation::AesType::inner_enum::AtBCContamination ,
AreaEffectSimulation::AesType::inner_enum::AtExplosionArea,
AreaEffectSimulation::AesType::inner_enum::AtExplosionSingle,
AreaEffectSimulation::AesType::inner_enum::AtMineArea,
AreaEffectSimulation::AesType::inner_enum::AtFunctionalArea,
AreaEffectSimulation::AesType::inner_enum::AtBoobyTrap,
AreaEffectSimulation::AesType::inner_enum::AtOffRouteMine,
AreaEffectSimulation::AesType::inner_enum::AtExplosionCluster};
if (!validTypes.contains(data.aesTypeId()))
return;
switch (modType)
{
case DataModification::eAdded:
if (!allInternalAesItemIds().contains(data.aesItemId()))
return;
m_allCentralAesItemViews.insert(data.aesItemId(), data);
break;
case DataModification::eModified:
{
if (!m_allCentralAesItemViews.contains(data.aesItemId()))
return;
m_allCentralAesItemViews[data.aesItemId()] = data;
break;
}
case DataModification::eRemoved:
// AesItemViews are removed from m_allCentralAesItemViews in HandlerOcCentralAesData::onAesItemChanged
break;
}
}
void HandlerOcCentralAesData::handleSituation()
{
TRACE_LOG(m_logger) << "Thread " << QThread::currentThreadId() << " function: " << LOGFUNCTION;
QMutexLocker l(&m_accessMutex);
if (m_radius == 0)
{
INFO_LOG(m_logger) << "Do not send Situation as radius is 0, centerEquipmentId " << m_centerEquipmentId
<< ", m_position " << m_centerPosition;
QTimer::singleShot(0, this, &HandlerOcCentralAesData::aliveTimeout); // ending thread
return;
}
QSet<qint32> oldAesItemsInRange = m_aesItemsInRange;
fetchAesItemsInRange();
// 50 is the max number of AesItems which are allowed to be handled on the ABT.
// So we have to just take the 50 nearest items.
bool hasOverload = m_aesItemsInRange.size() > 50;
if (hasOverload)
{
DEBUG_LOG(m_logger) << "Got more than 50 AesItems in range. " << m_aesItemsInRange.size() << " in total --> Sorting out.";
QMultiMap<qreal, qint32> distances;
for (qint32 currentAesItemId : qAsConst(m_aesItemsInRange))
{
qreal distance = calculateDistanceToCircleCenter(currentAesItemId);
if (distance >= 0.0)
distances.insert(distance, currentAesItemId);
}
DEBUG_LOG(m_logger) << "We have " << distances.size() << " valid distances.";
m_aesItemsInRange.clear();
qint32 counter = 0;
for (auto it = distances.constBegin(); (it != distances.constEnd()) && (counter < 50); ++it, ++counter)
m_aesItemsInRange.insert(it.value());
DEBUG_LOG(m_logger) << "We now have " << m_aesItemsInRange.size() << " AES Items to send.";
}
QSet<qint32> validIds = m_aesItemsInRange - oldAesItemsInRange;
DEBUG_LOG(m_logger) << "After sorting out old items, we have " << validIds.size() << " items left.";
removeKickedOutAesItems(oldAesItemsInRange);
addAesItemsToBuilder(m_allCentralEffectClusters, validIds);
addAesItemsToBuilder(m_allCentralNContaminations, validIds);
addAesItemsToBuilder(m_allCentralBCContaminations, validIds);
addAesItemsToBuilder(m_allCentralExplosionsArea, validIds);
addAesItemsToBuilder(m_allCentralExplosionsSingle, validIds);
addAesItemsToBuilder(m_allCentralMineAreas, validIds);
addAesItemsToBuilder(m_allCentralFunctionalAreas, validIds);
addAesItemsToBuilder(m_allCentralBoobyTraps, validIds);
addAesItemsToBuilder(m_allCentralOffRouteMines, validIds);
addAesItemsToBuilder(m_allCentralExplosionClusters, validIds);
if (m_dataQueue->hasMessages())
{
QByteArray payload;
LtsUtils::set1Byte(m_bInitialDataTransfer ? OcSituation::TelegramId::CentralAesDataInitial : OcSituation::TelegramId::CentralAesData, payload);
LtsUtils::set1Byte(hasOverload, payload); // info, if there are more than 50 aes items in range
m_bInitialDataTransfer = false;
QByteArray sendingData = m_dataQueue->getSendingData(Settings::maxNumOfBytePerTxCycle());
payload += m_bWithCompression ? qCompress(sendingData) : sendingData;
TrainingAreaBase::SendOcDataRequest req;
req.equipmentNumber(m_equipmentId);
req.payload(LtsUtils::convert<std::vector<uint8_t>>(payload));
DEBUG_LOG(m_logger) << "Sending " << req.payload().size() << " Bytes payload.";
emit sendOcData(req);
}
else
DEBUG_LOG(m_logger) << "Sending timeout, but nothing to send.";
}
void HandlerOcCentralAesData::resetAliveTimer()
{
m_aliveTimer->start();
}
void HandlerOcCentralAesData::aliveTimeout()
{
INFO_LOG(m_logger) << "O/C-Thread keep alive timeout for O/C-Laptop-Id: " << m_equipmentId
<< " - Thread will be finished id: " << QThread::currentThreadId();
QThread::currentThread()->quit();
}
void HandlerOcCentralAesData::onResetInternalData()
{
TRACE_LOG(m_logger) << "Thread " << QThread::currentThreadId() << " function: " << LOGFUNCTION;
DEBUG_LOG(m_logger) << "Resetting internal data!";
m_aesItemsInRange.clear();
m_dataQueue->clear();
m_bInitialDataTransfer = true;
}
void HandlerOcCentralAesData::fetchAesItemsInRange()
{
TRACE_LOG(m_logger) << "Thread " << QThread::currentThreadId() << " function: " << LOGFUNCTION;
if (m_radius == 0)
return;
const QPointF relCenterPos = PositionConverter::relativeFromGeographic(m_centerPosition, m_baseCoordinate);
if (m_centerType == OcSituation::SituationCenterType::Equipment)
INFO_LOG(m_logger) << "Fetching AesItems in radius around equipment " << m_centerEquipmentId
<< " with position " << relCenterPos.x() << "/" << relCenterPos.y() << " and radius: " << m_radius << ", " << m_baseCoordinate.mgrs()
<< ", " << m_centerPosition.lon() << ", " << m_centerPosition.lat();
else
INFO_LOG(m_logger) << "Fetching AesItems in radius of position " << relCenterPos.x() << "/" << relCenterPos.y() << " radius: " << m_radius;
m_aesItemsInRange.clear();
qint32 effectClustersInRange = fetchAesItemsInCircle(m_allCentralEffectClusters);
qint32 nContaminationsInRange = fetchAesItemsInCircle(m_allCentralNContaminations);
qint32 bCContaminationsInRange = fetchAesItemsInCircle(m_allCentralBCContaminations);
qint32 explosionsAreaInRange = fetchAesItemsInCircle(m_allCentralExplosionsArea);
qint32 explosionsSingleInRange = fetchAesItemsInCircle(m_allCentralExplosionsSingle);
qint32 mineAreasInRange = fetchAesItemsInCircle(m_allCentralMineAreas);
qint32 functionalAreasInRange = fetchAesItemsInCircle(m_allCentralFunctionalAreas);
qint32 boobyTrapsInRange = fetchAesItemsInCircle(m_allCentralBoobyTraps);
qint32 offRouteMinesInRange = fetchAesItemsInCircle(m_allCentralOffRouteMines);
qint32 explosionClustersInRage = fetchAesItemsInCircle(m_allCentralExplosionClusters);
TRACE_LOG(m_logger) << "Got " << effectClustersInRange << " EffectClusters in range.";
TRACE_LOG(m_logger) << "Got " << nContaminationsInRange << " NContaminations in range.";
TRACE_LOG(m_logger) << "Got " << bCContaminationsInRange << " BCContaminations in range.";
TRACE_LOG(m_logger) << "Got " << explosionsAreaInRange << " ExplosionsArea in range.";
TRACE_LOG(m_logger) << "Got " << explosionsSingleInRange << " ExplosionsSingle in range.";
TRACE_LOG(m_logger) << "Got " << mineAreasInRange << " MineAreas in range.";
TRACE_LOG(m_logger) << "Got " << functionalAreasInRange << " FunctionalAreas in range.";
TRACE_LOG(m_logger) << "Got " << boobyTrapsInRange << " BoobyTraps in range.";
TRACE_LOG(m_logger) << "Got " << offRouteMinesInRange << " OffRouteMines in range.";
TRACE_LOG(m_logger) << "Got " << explosionClustersInRage << " ExplosionClusters in range.";
}
template<typename T>
qint32 HandlerOcCentralAesData::fetchAesItemsInCircle(const QHash<qint32, T> &aesItems)
{
qint32 aesItemsInRangeCount = 0;
for (auto it = aesItems.constBegin(); it != aesItems.constEnd(); ++it)
{
if (!m_allCentralAesItemViews.contains(it.key()))
{
WARNING_LOG(m_logger) << "Got AesItem::id " << it.key() << " but there is no corresponding AesItemView.";
continue;
}
AreaEffectSimulation::AesItemView aesItemView = m_allCentralAesItemViews.value(it.key());
if (it.value().effectStateId() == AreaEffectSimulation::AesEffectState::inner_enum::EsExpired ||
it.value().effectStateId() == AreaEffectSimulation::AesEffectState::inner_enum::EsRemoved)
{
TRACE_LOG(m_logger) << "AesItem of type " << aesItemView.aesTypeId() << ", with id " << it.key() << " is removed or expired --> skipping.";
continue;
}
#if QT_VERSION < QT_VERSION_CHECK(5,10,0)
if (polygonFromForm(aesItemView.form()).intersected(m_situationCircle).size() > 0)
#else
if (polygonFromForm(aesItemView.form()).intersects(m_situationCircle))
#endif
{
m_aesItemsInRange.insert(it.key());
++aesItemsInRangeCount;
}
}
return aesItemsInRangeCount;
}
QPolygonF HandlerOcCentralAesData::polygonFromForm(const std::vector<Core::GeoPosition> &form) const
{
QPolygonF result;
result.reserve(form.size());
for (const Core::GeoPosition &currentPosition : qAsConst(form))
result.append(PositionConverter::relativeFromGeographic({currentPosition.lon(), currentPosition.lat()}, m_baseCoordinate));
return result;
}
QList<qint32> HandlerOcCentralAesData::allInternalAesItemIds() const
{
QList<qint32> result;
result.reserve(m_allCentralEffectClusters.size() +
m_allCentralNContaminations.size() +
m_allCentralBCContaminations.size() +
m_allCentralExplosionsArea.size() +
m_allCentralExplosionsSingle.size() +
m_allCentralMineAreas.size() +
m_allCentralFunctionalAreas.size() +
m_allCentralBoobyTraps.size() +
m_allCentralOffRouteMines.size() +
m_allCentralExplosionClusters.size());
for (auto it = m_allCentralEffectClusters.constBegin(); it != m_allCentralEffectClusters.constEnd(); ++it)
result.append(it.key());
for (auto it = m_allCentralNContaminations.constBegin(); it != m_allCentralNContaminations.constEnd(); ++it)
result.append(it.key());
for (auto it = m_allCentralBCContaminations.constBegin(); it != m_allCentralBCContaminations.constEnd(); ++it)
result.append(it.key());
for (auto it = m_allCentralExplosionsArea.constBegin(); it != m_allCentralExplosionsArea.constEnd(); ++it)
result.append(it.key());
for (auto it = m_allCentralExplosionsSingle.constBegin(); it != m_allCentralExplosionsSingle.constEnd(); ++it)
result.append(it.key());
for (auto it = m_allCentralMineAreas.constBegin(); it != m_allCentralMineAreas.constEnd(); ++it)
result.append(it.key());
for (auto it = m_allCentralFunctionalAreas.constBegin(); it != m_allCentralFunctionalAreas.constEnd(); ++it)
result.append(it.key());
for (auto it = m_allCentralBoobyTraps.constBegin(); it != m_allCentralBoobyTraps.constEnd(); ++it)
result.append(it.key());
for (auto it = m_allCentralOffRouteMines.constBegin(); it != m_allCentralOffRouteMines.constEnd(); ++it)
result.append(it.key());
for (auto it = m_allCentralExplosionClusters.constBegin(); it != m_allCentralExplosionClusters.constEnd(); ++it)
result.append(it.key());
return result;
}
void HandlerOcCentralAesData::removeKickedOutAesItems(const QSet<qint32> &aesItemsSentBefore)
{
QSet<qint32> kickedOutAesItems = aesItemsSentBefore - m_aesItemsInRange;
DEBUG_LOG(m_logger) << "Found " << kickedOutAesItems.size() << " AesItems to kick out.";
AreaEffectSimulation::AesType aesType = AreaEffectSimulation::AesType::inner_enum::AtUnknown;
for (qint32 currentAesItemId : qAsConst(kickedOutAesItems))
{
if (m_allCentralAesItemViews.contains(currentAesItemId))
aesType = m_allCentralAesItemViews.value(currentAesItemId).aesTypeId();
else if (m_allCentralEffectClusters.contains(currentAesItemId))
aesType = AreaEffectSimulation::AesType::inner_enum::AtEffectCluster;
else if (m_allCentralNContaminations.contains(currentAesItemId))
aesType = AreaEffectSimulation::AesType::inner_enum::AtNContamination;
else if (m_allCentralBCContaminations.contains(currentAesItemId))
aesType = AreaEffectSimulation::AesType::inner_enum::AtBCContamination;
else if (m_allCentralExplosionsArea.contains(currentAesItemId))
aesType = AreaEffectSimulation::AesType::inner_enum::AtExplosionArea;
else if (m_allCentralExplosionsSingle.contains(currentAesItemId))
aesType = AreaEffectSimulation::AesType::inner_enum::AtExplosionSingle;
else if (m_allCentralMineAreas.contains(currentAesItemId))
aesType = AreaEffectSimulation::AesType::inner_enum::AtMineArea;
else if (m_allCentralFunctionalAreas.contains(currentAesItemId))
aesType = AreaEffectSimulation::AesType::inner_enum::AtFunctionalArea;
else if (m_allCentralBoobyTraps.contains(currentAesItemId))
aesType = AreaEffectSimulation::AesType::inner_enum::AtBoobyTrap;
else if (m_allCentralOffRouteMines.contains(currentAesItemId))
aesType = AreaEffectSimulation::AesType::inner_enum::AtOffRouteMine;
else if (m_allCentralExplosionClusters.contains(currentAesItemId))
aesType = AreaEffectSimulation::AesType::inner_enum::AtExplosionCluster;
else
{
WARNING_LOG(m_logger) << "Could not remove AesItem with id " << currentAesItemId << ". There is no way to find out its AesType";
continue;
}
m_dataQueue->addRemoveMessage(currentAesItemId, aesType);
}
}
void HandlerOcCentralAesData::buildSituationCircle()
{
TRACE_LOG(m_logger) << "Thread " << QThread::currentThreadId() << " function: " << LOGFUNCTION;
// building the situation "circle" --> we use a regular polygon with 8 edges
m_situationCircle.clear();
QLineF tempLine;
const qint32 edges = 8;
const qreal angle = 360.0 / edges;
tempLine.setP1(PositionConverter::relativeFromGeographic(m_centerPosition, m_baseCoordinate));
tempLine.setLength(m_radius);
tempLine.setAngle(angle);
m_situationCircle << tempLine.p2();
for (qint32 counter = 1; counter < edges; ++counter)
{
tempLine.setAngle(tempLine.angle() + angle);
m_situationCircle << tempLine.p2();
}
}
qreal HandlerOcCentralAesData::calculateDistanceToCircleCenter(qint32 aesItemId) const
{
if (!m_allCentralAesItemViews.contains(aesItemId))
{
WARNING_LOG(m_logger) << "Could not calculate distance to circle center, because there is no AesItemView for AesItem::id " << aesItemId;
return -1.0;
}
QPolygonF aesItemForm = polygonFromForm(m_allCentralAesItemViews.value(aesItemId).form());
QLineF distanceLine(aesItemForm.boundingRect().center(), m_situationCircle.boundingRect().center());
return distanceLine.length();
}
template<typename T>
void HandlerOcCentralAesData::onAesItemChanged(QHash<qint32, T> &container, const T &data, DataModification modType)
{
switch (modType)
{
case DataModification::eAdded:
if (!data.isCentral())
return;
container.insert(data.id(), data);
return;
case DataModification::eModified:
container[data.id()] = data;
if (m_aesItemsInRange.contains(data.id()))
{
if (data.effectStateId() == AreaEffectSimulation::AesEffectState::inner_enum::EsExpired
|| data.effectStateId() == AreaEffectSimulation::AesEffectState::inner_enum::EsRemoved)
{
m_aesItemsInRange.remove(data.id());
m_dataQueue->addRemoveMessage(data);
}
else
m_dataQueue->addAesItem(data);
}
return;
case DataModification::eRemoved:
container.remove(data.id());
if (m_allCentralAesItemViews.contains(data.id()))
{
AreaEffectSimulation::AesItemView aesItemView = m_allCentralAesItemViews.take(data.id());
if (m_aesItemsInRange.contains(data.id()))
{
m_aesItemsInRange.remove(data.id());
m_dataQueue->addRemoveMessage(data.id(), aesItemView.aesTypeId());
}
}
return;
}
}
template<typename T>
void HandlerOcCentralAesData::addAesItemsToBuilder(const QHash<qint32, T> &aesItems, const QSet<qint32> &validIds)
{
for (auto it = aesItems.constBegin(); it != aesItems.constEnd(); ++it)
{
if (validIds.contains(it.key()))
m_dataQueue->addAesItem(it.value());
}
}
} // namespace OcSituationServer