703 lines
28 KiB
C++
Executable File
703 lines
28 KiB
C++
Executable File
/**
|
|
* @RDE_HEADER@
|
|
* Handler for all exercise objects
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
* Created by Norbert Thoden, SLSE, 2023-10
|
|
*/
|
|
|
|
#include "handler_explosion_cluster.h"
|
|
#include "handler_charge_administration.h"
|
|
#include <AreaEffectSimulation/Utils/polygons.h>
|
|
#include <ProjectDataManagement/pdm_translation.h>
|
|
#include <QtGui/QPolygonF>
|
|
#include <QJsonDocument>
|
|
#include <QJsonObject>
|
|
|
|
// for TrajectoryGenerator
|
|
#include <LtsCoordTrans/lts_coord_trans.h>
|
|
|
|
|
|
namespace AreaEffectSimulation
|
|
{
|
|
|
|
HandlerExplosionCluster::HandlerExplosionCluster(MainHandler *mainHandler)
|
|
: HandlerBaseTmpl<ObjectExplosionCluster>(mainHandler, QStringLiteral("HandlerExplosionCluster"), s_areaCount[static_cast<int>(AesType::AtExplosionCluster)], s_areaCountCentral[static_cast<int>(AesType::AtExplosionCluster)])
|
|
, Interface::Fts::ExplosionClusterModifyRequestHandler(mainHandler->dds()->fts())
|
|
, Interface::Fts::ExplosionClusterSingleEffectOnlyModifyRequestHandler(mainHandler->dds()->fts())
|
|
, Interface::Fts::ExplosionClusterOcModifyRequestHandler(mainHandler->dds()->fts())
|
|
, Interface::Fts::ExplosionClusterRemoveRequestHandler(mainHandler->dds()->fts())
|
|
, Interface::Fts::ExplosionClusterPauseResumeRequestHandler(mainHandler->dds()->fts())
|
|
, Interface::Fts::TargetPositionsModifyRequestHandler(mainHandler->dds()->fts())
|
|
, Interface::Fts::ExplosionClusterReleaseReceivedRequestHandler(mainHandler->dds()->fts())
|
|
{
|
|
}
|
|
|
|
bool HandlerExplosionCluster::init()
|
|
{
|
|
// create explosion cluster objects
|
|
bool bRet = true;
|
|
auto cb = [this, &bRet] (const Database::AesExplosionCluster &data)
|
|
{
|
|
ObjectExplosionCluster *ifs(new ObjectExplosionCluster(m_mainHandler, this));
|
|
connect(ifs, &ObjectExplosionCluster::effectStateChanged, this, &HandlerExplosionCluster::onEffectStateChanged);
|
|
Core::FunctionReplyObject ret = ifs->createObject(data);
|
|
if (ret.error())
|
|
{
|
|
delete ifs;
|
|
ERROR_LOG(m_logger) << ret();
|
|
bRet = false;
|
|
return true;
|
|
}
|
|
|
|
// Context NASAT: check via chargeTypeId:
|
|
const bool bChargeIsAirSupport = m_mainHandler->dds()->pdmDtc()->gearClassFromChargeTypeId(ifs->data().chargeTypeId) == ProjectDataManagement::GearClass::GearClass_AirSupport;
|
|
ifs->setAirSupportSource(bChargeIsAirSupport);
|
|
|
|
if(!ifs->data().isCentral)
|
|
{
|
|
if (bChargeIsAirSupport)
|
|
{
|
|
// Note: s_currentAirSupportCount is updated via overloaded recountActiveAreas
|
|
if(s_currentAirSupportCount >= s_maxAirSupportCount)
|
|
{
|
|
ERROR_LOG(m_logger) << "More active air supports in database than allowed - ignoring the rest!";
|
|
ifs->removeObject();
|
|
delete ifs;
|
|
return true;
|
|
}
|
|
}
|
|
else if (totalAreas() >= s_maxActiveAreas[static_cast<int>(AesType::AtExplosionCluster)])
|
|
{
|
|
ERROR_LOG(m_logger) << "More active explosion areas in database than allowed - ignoring the rest!";
|
|
ifs->removeObject();
|
|
delete ifs;
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (totalAreasCentral() >= (s_maxActiveAreasCentral[static_cast<int>(AesType::AtExplosionCluster)]))
|
|
{
|
|
ERROR_LOG(m_logger) << "More active explosion areas in database than allowed - ignoring the rest!";
|
|
ifs->removeObject();
|
|
delete ifs;
|
|
return true;
|
|
}
|
|
}
|
|
if (ifs->isObjectInTrainingArea())
|
|
{
|
|
if (ifs->data().isCentral)
|
|
++m_areaCountCentral;
|
|
else
|
|
++m_areaCount;
|
|
}
|
|
m_objectMap.insert(ifs->id(), ifs);
|
|
connect(ifs, &ObjectExplosionCluster::newAiv, this, &HandlerExplosionCluster::newAiv);
|
|
connect(ifs, &ObjectExplosionCluster::removeAiv, this, &HandlerExplosionCluster::removeAiv);
|
|
|
|
return true;
|
|
};
|
|
|
|
if (!m_mainHandler->db()->select(cb) || !bRet)
|
|
{
|
|
ERROR_LOG(m_logger) << "Error reading data from database!";
|
|
return false;
|
|
}
|
|
|
|
DEBUG_LOG(m_logger) << "m_exeObjMap.size() = " << m_objectMap.size();
|
|
DEBUG_LOG(m_logger) << "m_areaCount = " << m_areaCount;
|
|
DEBUG_LOG(m_logger) << "m_areaCountCentral = " << m_areaCountCentral;
|
|
return true;
|
|
}
|
|
|
|
int HandlerExplosionCluster::totalAreas() const
|
|
{
|
|
return s_areaCount[static_cast<int>(AesType::AtExplosionCluster)];
|
|
}
|
|
|
|
int HandlerExplosionCluster::totalAreasCentral() const
|
|
{
|
|
return s_areaCountCentral[static_cast<int>(AesType::AtExplosionCluster)] ;
|
|
}
|
|
|
|
|
|
static void fillData(const ExplosionClusterModifyRequest &src, Database::AesExplosionCluster &dst, MainHandler *mainHandler)
|
|
{
|
|
if (src.id < 0) // is the id given as negative? set id -> used by OC-Laptop
|
|
dst.id = src.id;
|
|
|
|
dst.name = QString::fromStdString(src.name);
|
|
dst.element = QString::fromStdString(src.element);
|
|
|
|
|
|
dst.impactPosition.rx() = src.area.cornerBottomLeft.lon;
|
|
dst.impactPosition.ry() = src.area.cornerBottomLeft.lat;
|
|
dst.impactLength = src.area.height;
|
|
dst.impactWidth = src.area.width;
|
|
dst.rotationAngle = src.area.rotation;
|
|
|
|
const bool bIsPointSimilar = (src.explosionGeometry == AreaEffectSimulation::AesExplosionGeometry::EgAimPoint) ||
|
|
(src.explosionGeometry == AreaEffectSimulation::AesExplosionGeometry::EgPoint);
|
|
|
|
if (bIsPointSimilar && ((src.area.width <= 0) || (src.area.height <= 0)))
|
|
{
|
|
const Core::GeoPosition2D &cornerBottomLeft = src.area.cornerBottomLeft;
|
|
const double impactDiameter = mainHandler->dds()->pdmDtc()->impactRadius(src.chargeStruct.chargeTypeId,
|
|
src.chargeStruct.igniterTypeId,
|
|
src.chargeStruct.igniterFunctionId) * 2.0; // GUEZE-2634
|
|
|
|
const QPointF bottomLeft(Polygons::centerPoint2BottomLeft(QPointF(cornerBottomLeft.lon, cornerBottomLeft.lat),
|
|
impactDiameter, impactDiameter, 0));
|
|
|
|
dst.impactPosition.rx() = bottomLeft.x();
|
|
dst.impactPosition.ry() = bottomLeft.y();
|
|
dst.impactLength = impactDiameter;
|
|
dst.impactWidth = impactDiameter;
|
|
}
|
|
|
|
dst.explosionGeometryId = src.explosionGeometry;
|
|
dst.zog = src.tla;
|
|
|
|
dst.effectStart = src.effectStart.is_set() && src.effectStart.get() > 0 ? QDateTime::fromMSecsSinceEpoch(src.effectStart.get()) : QDateTime();
|
|
dst.effectDuration = src.effectDuration;
|
|
dst.effectSourceId = src.effectSourceId;
|
|
|
|
dst.chargeTypeId = src.chargeStruct.chargeTypeId;
|
|
dst.igniterTypeId = src.chargeStruct.igniterTypeId;
|
|
dst.igniterFunctionId = src.chargeStruct.igniterFunctionId;
|
|
dst.firePurposeId = src.firePurposeId;
|
|
|
|
dst.partyId = src.partyId.is_set() ? src.partyId.get() : 0;
|
|
dst.participantId = src.participantId.is_set() ? src.participantId.get() : -1; // -1 -> avoid trajectory
|
|
// dst.firingGeoPosition // not provided, has to be retrieved from dds
|
|
|
|
dst.impactCount = src.impactCount;
|
|
dst.mhpCountRequest = src.mhpCount;
|
|
if (src.mhpRotation.is_set())
|
|
dst.mhpRotationRequest = src.mhpRotation.get();
|
|
else
|
|
dst.mhpRotationRequest = ObjectExplosionCluster::s_invalid_rotation_angle;
|
|
|
|
dst.altitude = -1;
|
|
dst.peakHeight = src.peakHeight;
|
|
dst.flightDuration = src.flightDuration;
|
|
|
|
// dst.originatorId = src.o();
|
|
// dst.firePurpose = QString::fromStdString(src.purpose());
|
|
// dst.fireRequestTime = QDateTime::fromMSecsSinceEpoch(src.fireRequestTime());
|
|
dst.effectMarkingInTa = src.effectMarkingInTa;
|
|
dst.externalId = src.externalId.is_set() ? src.externalId.get() : 0;
|
|
|
|
dst.launchVelocity = src.launchVelocity;
|
|
dst.launchAngleDeg = src.launchAngleDeg;
|
|
dst.dropAngle = src.dropAngle;
|
|
|
|
dst.tapTimepoint = src.tapTime;
|
|
dst.lcPrf = src.lcAttack;
|
|
dst.lcTermination = src.lcTermination;
|
|
dst.cloudBase = src.cloudBase;
|
|
dst.properties = QString::fromStdString(src.properties);
|
|
dst.esmParticipantIds = LtsUtils::IntArray(src.esmParticipantIds);
|
|
}
|
|
|
|
void HandlerExplosionCluster::onExplosionClusterModifyRequest(const rti::core::SampleIdentity &cookie,
|
|
const ExplosionClusterModifyRequest &request)
|
|
{
|
|
DEBUG_LOG(m_logger) << "************************************ onExplosionClusterModifyRequest: " << request;
|
|
Core::FunctionReplyObject ret = explosionClusterModifyRequest(cookie, request);
|
|
if (ret.error())
|
|
WARNING_LOG(m_logger) << ret()
|
|
<< ", effectStart :" << request.effectStart;
|
|
ret.setAdditionalInfo(request.properties.c_str());
|
|
m_mainHandler->dds()->fts()->explosionClusterModifyReply(cookie, ret);
|
|
}
|
|
|
|
void HandlerExplosionCluster::onExplosionClusterSingleEffectOnlyModifyRequest(const rti::core::SampleIdentity &cookie,
|
|
const ExplosionClusterSingleEffectOnlyRequest &request)
|
|
{
|
|
DEBUG_LOG(m_logger) << "************************************ onExplosionClusterSingleEffectModifyRequest: " << request;
|
|
|
|
// generalize the specific request to the common one. (similar an 'upcast')
|
|
// in other words: ExplosionClusterSingleEffectOnlyRequest -> ExplosionClusterModifyRequest:
|
|
|
|
ExplosionClusterModifyRequest ecCommonModifyRequest;
|
|
|
|
ecCommonModifyRequest.id = request.id;
|
|
ecCommonModifyRequest.externalId = request.externalId;
|
|
|
|
ecCommonModifyRequest.effectStart = request.effectStart;
|
|
ecCommonModifyRequest.effectDuration = 1000;
|
|
|
|
// charge and geometry:
|
|
ecCommonModifyRequest.explosionGeometry = AreaEffectSimulation::AesExplosionGeometry::EgPoint;
|
|
// ecCommonModifyRequest.zog(0);
|
|
|
|
int igniterTypeId = 102; // from pdm_igniter_type (Impact Default)
|
|
ecCommonModifyRequest.chargeStruct.igniterTypeId = igniterTypeId;
|
|
ecCommonModifyRequest.chargeStruct.chargeTypeId = request.chargeTypeId;
|
|
|
|
// height, width are <=0 -> area will be adjusted using impactRadius of charge:
|
|
ecCommonModifyRequest.area.cornerBottomLeft = request.impactPosition;
|
|
ecCommonModifyRequest.area.height = 0;
|
|
ecCommonModifyRequest.area.width = 0;
|
|
|
|
|
|
ecCommonModifyRequest.mhpCount = 1;
|
|
ecCommonModifyRequest.impactCount = 1;
|
|
|
|
ecCommonModifyRequest.name = request.name; // ZpNummer
|
|
ecCommonModifyRequest.element = request.element; // element
|
|
|
|
|
|
ecCommonModifyRequest.partyId = request.partyId;
|
|
ecCommonModifyRequest.participantId = -1; // -1 -> avoid trajectory
|
|
|
|
|
|
|
|
Core::FunctionReplyObject ret = explosionClusterModifyRequest(cookie, ecCommonModifyRequest);
|
|
if (ret.error())
|
|
WARNING_LOG(m_logger) << ret();
|
|
|
|
m_mainHandler->dds()->fts()->explosionClusterSingleEffectOnlyModifyReply(cookie, ret);
|
|
}
|
|
|
|
void HandlerExplosionCluster::onExplosionClusterOcModifyRequest(const rti::core::SampleIdentity &cookie,
|
|
const ExplosionClusterOcModifyRequest &request)
|
|
{
|
|
DEBUG_LOG(m_logger) << "************************************ onExplosionClusterOcModifyRequest: " << request;
|
|
|
|
// generalize the specific request to the common one. (similar an 'upcast')
|
|
// in other words: ExplosionClusterSingleEffectOnlyRequest -> ExplosionClusterModifyRequest:
|
|
|
|
ExplosionClusterModifyRequest ecCommonModifyRequest;
|
|
|
|
ecCommonModifyRequest.id = request.id;
|
|
//ecCommonModifyRequest.externalId(request.externalId());
|
|
|
|
ecCommonModifyRequest.effectStart = request.effectStart;
|
|
ecCommonModifyRequest.effectDuration = request.effectDuration;
|
|
|
|
// charge and geometry:
|
|
ecCommonModifyRequest.area = request.area;
|
|
|
|
if (request.impactCount == 1)
|
|
ecCommonModifyRequest.explosionGeometry = AreaEffectSimulation::AesExplosionGeometry::EgPoint;
|
|
else
|
|
ecCommonModifyRequest.explosionGeometry = AreaEffectSimulation::AesExplosionGeometry::EgArea;
|
|
// ecCommonModifyRequest.zog(0);
|
|
|
|
ecCommonModifyRequest.mhpCount = request.mhpCount;
|
|
ecCommonModifyRequest.impactCount = request.impactCount;
|
|
ecCommonModifyRequest.mhpRotation = request.mhpRotation;
|
|
|
|
// was FtImpact
|
|
ecCommonModifyRequest.chargeStruct.igniterTypeId = request.chargeStruct.igniterTypeId;
|
|
ecCommonModifyRequest.chargeStruct.chargeTypeId = request.chargeStruct.chargeTypeId;
|
|
|
|
ecCommonModifyRequest.name = request.name; // ZpNummer
|
|
ecCommonModifyRequest.element = ecCommonModifyRequest.element; // element
|
|
|
|
ecCommonModifyRequest.partyId = request.partyId;
|
|
// ecCommonModifyRequest.participantId(-1); // -1 -> avoid trajectory
|
|
|
|
// ToDo: no trajectory needed, but how can we transfer the rotation of MhpAreas?
|
|
// ToDo: no trajectory needed, but how can we transfer the rotation of MhpAreas?
|
|
// ToDo: no trajectory needed, but how can we transfer the rotation of MhpAreas?
|
|
|
|
// ToDo: how to transfer request.mhpRotation??
|
|
|
|
Core::FunctionReplyObject ret = explosionClusterModifyRequest(cookie, ecCommonModifyRequest);
|
|
if (ret.error())
|
|
WARNING_LOG(m_logger) << ret();
|
|
m_mainHandler->dds()->fts()->explosionClusterOcModifyReply(cookie, ret);
|
|
|
|
}
|
|
|
|
Core::FunctionReplyObject HandlerExplosionCluster::explosionClusterCreateRequest(const ExplosionClusterModifyRequest &request)
|
|
{
|
|
// HLA Interface is using externalId...
|
|
// external (externalId>0) -> no partyId required
|
|
// external (externalId==0) -> partyId required
|
|
const int externalIdValue = request.externalId.is_set() ? request.externalId.get() : 0;
|
|
const ProjectDataManagement::GearClass gearClass = m_mainHandler->gearClassOfChargeTypeId(request.chargeStruct.chargeTypeId);
|
|
|
|
const bool bDoClaimPlannedCharge = (request.id == 0) &&
|
|
(externalIdValue==0) &&
|
|
(gearClass != ProjectDataManagement::GearClass::GearClass_AirSupport);
|
|
if (bDoClaimPlannedCharge)
|
|
{
|
|
int chargeNeeded = request.impactCount;
|
|
if (chargeNeeded <= 0)
|
|
return Core::FunctionReplyObject(tr_lts("dds", "Invalid impact count (<= 0)."));
|
|
|
|
if (request.id == 0)
|
|
{
|
|
int chargeLeft = m_mainHandler->chargeAdministrationHandler()->availableCharge(request.chargeStruct.chargeTypeId, request.partyId.get());
|
|
|
|
QString chargeName= QString::fromStdString(m_mainHandler->dds()->pdmDtc()->chargeType(request.chargeStruct.chargeTypeId).name);
|
|
QString fireUnitName;
|
|
if (request.participantId.is_set())
|
|
fireUnitName = QString::fromStdString(m_mainHandler->dds()->ppmDtc()->participant(request.participantId.get()).designator);
|
|
|
|
if (chargeNeeded > chargeLeft)
|
|
return Core::FunctionReplyObject(tr_lts("dds", "Invalid impact count. Fire Unit '%1' has %2 charges (%3), but for this cluster %4 are needed."))
|
|
.arg(fireUnitName)
|
|
.arg((chargeLeft))
|
|
.arg(chargeName)
|
|
.arg(chargeNeeded);
|
|
}
|
|
}
|
|
|
|
Database::AesExplosionCluster newData;
|
|
fillData(request, newData, m_mainHandler);
|
|
|
|
if (!request.properties.empty() &&
|
|
(!request.effectStart.is_set() ||
|
|
request.effectStart.get() == 0))
|
|
{
|
|
QJsonObject propertiesObject = QJsonDocument::fromJson(QByteArray::fromStdString(request.properties)).object();
|
|
|
|
newData.isUsingEffectStateReceived = propertiesObject.value(QStringLiteral("useReceived")).toBool();
|
|
}
|
|
// check: effectStart > time(NULL) ?
|
|
|
|
|
|
ObjectExplosionCluster *ifs(new ObjectExplosionCluster(m_mainHandler, this));
|
|
connect(ifs, &ObjectExplosionCluster::effectStateChanged, this, &HandlerExplosionCluster::onEffectStateChanged);
|
|
|
|
// Context NASAT: check via chargeTypeId:
|
|
const ProjectDataManagement::GearClass gc = m_mainHandler->dds()->pdmDtc()->gearClassFromChargeTypeId(request.chargeStruct.chargeTypeId);
|
|
const bool bChargeIsAirSupport = gc == ProjectDataManagement::GearClass::GearClass_AirSupport;
|
|
ifs->setAirSupportSource(bChargeIsAirSupport);
|
|
|
|
const Core::FunctionReplyObject ret = ifs->createObject(newData);
|
|
|
|
if (ret.error())
|
|
{
|
|
delete ifs;
|
|
return ret;
|
|
}
|
|
INFO_LOG(m_logger) << "IS Central: " << ifs->data().isCentral;
|
|
|
|
|
|
if (ifs->data().isCentral)
|
|
{
|
|
DEBUG_LOG(m_logger) << "New cen ExplosionCluster";
|
|
if(gearClass == ProjectDataManagement::GearClass::GearClass_AirSupport)
|
|
{
|
|
if (s_currentAirSupportCount >= s_maxAirSupportCount)
|
|
{
|
|
ifs->removeObject(); //Not finally deleted from db after this,Fallback if DB deletion is not working correct
|
|
ifs->removeObjectFromDb();
|
|
delete ifs;
|
|
return Core::FunctionReplyObject(1, tr_lts("dds", "Too many active air supports."));
|
|
}
|
|
}
|
|
else if (totalAreasCentral() >= (s_maxActiveAreasCentral[static_cast<int>(AesType::AtExplosionCluster)]) + (s_currentAirSupportCount) && request.effectStart.is_set())
|
|
{
|
|
ifs->removeObject(); //Not finally deleted from db after this,Fallback if DB deletion is not working correct
|
|
ifs->removeObjectFromDb();
|
|
delete ifs;
|
|
return Core::FunctionReplyObject(1, tr_lts("dds", "Too many active central explosion areas."));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DEBUG_LOG(m_logger) << "New dec ExplosionCluster: " << totalAreas() << " Max: " << s_maxActiveAreas[static_cast<int>(AesType::AtExplosionCluster)] << " Is Set: " << request.effectStart.is_set();
|
|
|
|
if (totalAreas() >= (s_maxActiveAreas[static_cast<int>(AesType::AtExplosionCluster)]) && request.effectStart.is_set())
|
|
{
|
|
ifs->removeObject(); //Not finally deleted from db after this,Fallback if DB deletion is not working correct
|
|
ifs->removeObjectFromDb();
|
|
delete ifs;
|
|
return Core::FunctionReplyObject(1, tr_lts("dds", "Too many active explosion areas."));
|
|
}
|
|
}
|
|
|
|
if (ifs->data().isCentral)
|
|
{
|
|
++m_areaCountCentral;
|
|
DEBUG_LOG(m_logger) << "m_areaCountCentral " << m_areaCountCentral;
|
|
}
|
|
else if (ifs->isObjectInTrainingArea())
|
|
{
|
|
++m_areaCount;
|
|
DEBUG_LOG(m_logger) << "m_areaCount = " << m_areaCount;
|
|
}
|
|
else
|
|
{
|
|
DEBUG_LOG(m_logger) << "Counting of [AesType::AtExplosionCluster] not affected";
|
|
}
|
|
|
|
m_objectMap.insert(ifs->id(), ifs);
|
|
|
|
connect(ifs, &ObjectExplosionCluster::newAiv, this, &HandlerExplosionCluster::newAiv);
|
|
connect(ifs, &ObjectExplosionCluster::removeAiv, this, &HandlerExplosionCluster::removeAiv);
|
|
return ret;
|
|
}
|
|
|
|
Core::FunctionReplyObject HandlerExplosionCluster::explosionClusterModifyRequest(const rti::core::SampleIdentity &cookie,
|
|
const ExplosionClusterModifyRequest &request )
|
|
{
|
|
|
|
|
|
// // externalId maybe set be HLA interface:
|
|
// // from external (externalIdValue>0) -> no partyId required
|
|
// // from internal (externalIdValue==0) -> partyId required
|
|
// const int externalIdValue = request.externalId.is_set() ? request.externalId.get() : 0;
|
|
// if (externalIdValue == 0 && !request.partyId.is_set())
|
|
// return Core::FunctionReplyObject(tr_lts("dds", "Explosion areas need a party id."));
|
|
|
|
DEBUG_LOG(m_logger) << "request.effectStart :" << request.effectStart
|
|
<< ", effectDuration :" << request.effectDuration
|
|
<< ", flightDuration :" << request.flightDuration
|
|
<< ", tapTime :" << request.tapTime
|
|
<< ", properties: " << request.properties;
|
|
|
|
Core::FunctionReplyObject ret;
|
|
if (request.id == 0 || ((request.id < 0) && !getObjectFromMap(m_objectMap, std::abs(request.id), ret)))
|
|
return explosionClusterCreateRequest(request);
|
|
|
|
ObjectExplosionCluster *ifs = getObjectFromMap(m_objectMap, std::abs(request.id), ret);
|
|
if (!ifs)
|
|
return ret;
|
|
|
|
ifs->setCookie(cookie);
|
|
|
|
AreaEffectSimulation::Database::AesExplosionCluster aea(ifs->data());
|
|
fillData(request, aea, m_mainHandler);
|
|
|
|
// Context NASAT: check via chargeTypeId:
|
|
const ProjectDataManagement::GearClass gc = m_mainHandler->dds()->pdmDtc()->gearClassFromChargeTypeId(request.chargeStruct.chargeTypeId);
|
|
const bool bChargeIsAirSupport = (gc == ProjectDataManagement::GearClass::GearClass_AirSupport);
|
|
ifs->setAirSupportSource(bChargeIsAirSupport);
|
|
|
|
// For counting, only Elements being at least prepared are important:
|
|
if (request.effectStart.is_set() && ifs->isObjectModifiable()) // ToDo: check
|
|
{
|
|
// Calculate new polygon here. Not nice, though
|
|
auto poly = Polygons::explosionClusterArea(aea);
|
|
|
|
std::vector<Core::GeoPosition> _form;
|
|
ObjectBase::ddsVecFromPoly(poly, _form);
|
|
bool isCentral = ifs->checkIsCentral(_form);
|
|
bool wasCentral = ifs->data().isCentral;
|
|
|
|
DEBUG_LOG(m_logger) << "isCentral: " << isCentral;
|
|
DEBUG_LOG(m_logger) << "wasCentral: " << wasCentral;
|
|
|
|
|
|
if (isCentral)
|
|
{
|
|
if (bChargeIsAirSupport)
|
|
{
|
|
if (s_currentAirSupportCount >= s_maxAirSupportCount)
|
|
{
|
|
return Core::FunctionReplyObject(1, tr_lts("dds", "Too many active air supports."));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// case 1: war zentral && effectStart war nicht gesetzt
|
|
// case 2: war dezentral && effectStart ist gesetzt.
|
|
if (totalAreasCentral() >= (s_maxActiveAreasCentral[static_cast<int>(AesType::AtExplosionCluster)] + (s_currentAirSupportCount)) && request.effectStart.is_set()
|
|
&& ((wasCentral && !ifs->isActivationTimeSet()) || !wasCentral))
|
|
{
|
|
return Core::FunctionReplyObject(1, tr_lts("dds", "Too many active central explosion clusters."));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// case 1: war dezentral && effectStart war nicht gesetzt
|
|
// case 2: war zentral && effectStart ist gesetzt.
|
|
if (totalAreas() >= (s_maxActiveAreas[static_cast<int>(AesType::AtExplosionCluster)]) && request.effectStart.is_set()
|
|
&& (( !wasCentral && !ifs->isActivationTimeSet()) || wasCentral))
|
|
{
|
|
return Core::FunctionReplyObject(1, tr_lts("dds", "Too many active explosion clusters."));
|
|
}
|
|
}
|
|
|
|
|
|
// For counting, only Elements being at least prepared are important:
|
|
if (request.effectStart.is_set() && ifs->isObjectModifiable())
|
|
{
|
|
|
|
DEBUG_LOG(m_logger) << "isCentral: " << isCentral;
|
|
DEBUG_LOG(m_logger) << "wasCentral: " << wasCentral;
|
|
|
|
// only change if element changed from central to training area or vice versa
|
|
if ((isCentral != wasCentral))
|
|
{
|
|
// Change from central to training area
|
|
if (wasCentral)
|
|
{
|
|
if (totalAreas() >= (s_maxActiveAreas[static_cast<int>(AesType::AtExplosionCluster)]))
|
|
return Core::FunctionReplyObject(request.id, tr_lts("dds", "Too many active explosion clusters."));
|
|
|
|
m_areaCount++;
|
|
m_areaCountCentral--;
|
|
DEBUG_LOG(m_logger) << "s_areaCount[AesType::AtExplosionCluster] = " << m_areaCount;
|
|
DEBUG_LOG(m_logger) << "s_areaCountCentral[AesType::AtExplosionCluster] = " << m_areaCountCentral;
|
|
}
|
|
else // Change from training area to central
|
|
{
|
|
if (totalAreasCentral() >= (s_maxActiveAreasCentral[static_cast<int>(AesType::AtExplosionCluster)]))
|
|
return Core::FunctionReplyObject(request.id, tr_lts("dds", "Too many active central explosion clusters."));
|
|
m_areaCount--;
|
|
m_areaCountCentral++;
|
|
DEBUG_LOG(m_logger) << "s_areaCount[AesType::AtExplosionCluster] = " << m_areaCount;
|
|
DEBUG_LOG(m_logger) << "s_areaCountCentral[AesType::AtExplosionCluster] = " << m_areaCountCentral;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (request.id < 0 && checkStateForSfm(ifs))
|
|
{
|
|
DEBUG_LOG(m_logger) << "Overwrite Effect State for OC";
|
|
aea.effectStateId = AesEffectState::EsPrepared;
|
|
}
|
|
|
|
DEBUG_LOG(m_logger) << "request.properties()" << request.properties
|
|
<< " aea.properties=" << aea.properties;
|
|
return ifs->updateObject(aea);
|
|
}
|
|
|
|
// unused
|
|
/*
|
|
Core::FunctionReplyObject HandlerExplosionCluster::explosionClusterModifyGeometryRequest(const ExplosionClusterModifyRequest &request)
|
|
{
|
|
// WARNING: request.area.cornerBottomLeft() contains center point!
|
|
Core::FunctionReplyObject ret;
|
|
ObjectExplosionCluster *ifs = getObjectFromMap(m_objectMap, request.id(), ret);
|
|
if (!ifs)
|
|
return ret;
|
|
|
|
// Anzahl aktiver Areas ist erreicht, der Wirkbeginn ist (soll) gesetzt sein, aber die Area war
|
|
// vorher noch ohne Wirkbeginn
|
|
if (totalAreas() >= (s_maxActiveAreas[AesType::AtExplosionArea] + s_maxActiveAreas[AesType::AtExplosionSingle]) && request.effectStart.is_set() && !ifs->isObjectModifiable())
|
|
return Core::FunctionReplyObject(request.id(), tr_lts("dds", "Too many active explosion areas."));
|
|
|
|
// Todo: IsObjectModifiable() ?!?
|
|
AreaEffectSimulation::Database::AesExplosionCluster aea(ifs->data());
|
|
|
|
aea.impactPosition = Polygons::centerPoint2BottomLeft(QPointF(request.area().cornerBottomLeft().lon(),
|
|
request.area().cornerBottomLeft().lat()),
|
|
ifs->data().impactWidth,
|
|
ifs->data().impactLength,
|
|
request.area().rotation());
|
|
aea.rotationAngle = request.area().rotation();
|
|
return ifs->updateObject(aea);
|
|
}
|
|
*/
|
|
|
|
/*
|
|
Core::FunctionReplyObject HandlerExplosionCluster::modifyPartyParticipant(qint32 itemId, qint32 partyId, qint32 participantId)
|
|
{
|
|
ObjectExplosionCluster *ifs = m_objectMap.value(itemId);
|
|
if (!ifs)
|
|
return Core::FunctionReplyObject(itemId, tr_lts("dds", "Explosion Cluster with id %1 not found.")).arg(itemId);
|
|
AreaEffectSimulation::Database::AesExplosionCluster aea(ifs->data());
|
|
aea.partyId = partyId;
|
|
aea.participantId= participantId;
|
|
return ifs->updateObject(aea);
|
|
}
|
|
*/
|
|
|
|
void HandlerExplosionCluster::recountActiveAreas()
|
|
{
|
|
s_currentAirSupportCount = 0;
|
|
for (const auto *area : qAsConst(m_objectMap))
|
|
{
|
|
if (area->isObjectInTrainingArea()) // meanwhile an ugly name, means EsPrepared, EsActivated, EsPaused
|
|
{
|
|
if (m_mainHandler->gearClassOfChargeTypeId(area->data().chargeTypeId) == ProjectDataManagement::GearClass::GearClass_AirSupport)
|
|
++s_currentAirSupportCount;
|
|
}
|
|
}
|
|
HandlerBaseTmpl::recountActiveAreas();
|
|
|
|
DEBUG_LOG(m_logger) << "m_areaCount after Recount = " << m_areaCount;
|
|
DEBUG_LOG(m_logger) << "m_areaCountCentral after Recount = " << m_areaCountCentral;
|
|
DEBUG_LOG(m_logger) << "m_areaCount s_currentAirSupportCount after Recount = " << s_currentAirSupportCount;
|
|
}
|
|
|
|
void HandlerExplosionCluster::onExplosionClusterRemoveRequest(const rti::core::SampleIdentity &cookie,
|
|
const Core::RemoveElementRequest &request)
|
|
{
|
|
DEBUG_LOG(m_logger) << "************************************ onExplosionClusterRemoveRequest: " << request;
|
|
m_mainHandler->dds()->fts()->explosionClusterRemoveReply(cookie, removeReply(&DatabaseInterface::removeAesExplosionCluster, request));
|
|
}
|
|
|
|
void HandlerExplosionCluster::onExplosionClusterPauseResumeRequest(const rti::core::SampleIdentity &cookie,
|
|
const ExplosionClusterPauseResumeRequest &request)
|
|
{
|
|
DEBUG_LOG(m_logger) << "onExplosionClusterPauseResumeRequest" << request;
|
|
Core::FunctionReplyObject ret;
|
|
ObjectExplosionCluster *ifs = getObjectFromMap(m_objectMap, request.id, ret);
|
|
if (!ifs)
|
|
{
|
|
m_mainHandler->dds()->fts()->explosionClusterPauseResumeReply(cookie, ret);
|
|
return;
|
|
}
|
|
|
|
ret = ifs->resumePause(request);
|
|
|
|
if (ret.error())
|
|
ERROR_LOG(m_logger) << ret();
|
|
m_mainHandler->dds()->fts()->explosionClusterPauseResumeReply(cookie, ret);
|
|
}
|
|
|
|
void HandlerExplosionCluster::onExplosionClusterReleaseReceivedRequest(const rti::core::SampleIdentity &cookie, const ExplosionClusterReleaseReceivedRequest &request)
|
|
{
|
|
DEBUG_LOG(m_logger) << "onExplosionClusterReleaseReceivedRequest" << request;
|
|
Core::FunctionReplyObject ret(request.id);
|
|
ObjectExplosionCluster *ifs = getObjectFromMap(m_objectMap, request.id, ret);
|
|
if (!ifs)
|
|
{
|
|
ERROR_LOG(m_logger) << ret();
|
|
m_mainHandler->dds()->fts()->explosionClusterReleaseReceivedReply(cookie, ret);
|
|
return;
|
|
}
|
|
|
|
if (!ifs->isUsingEffectStateReceived())
|
|
{
|
|
ret = ret.setStr(tr_lts("dds", "ExplosionCluster with id %1 is not using EffectState Received")).arg(request.id);
|
|
ERROR_LOG(m_logger) << ret();
|
|
m_mainHandler->dds()->fts()->explosionClusterReleaseReceivedReply(cookie, ret);
|
|
return;
|
|
}
|
|
|
|
ifs->setUseEffectStateReceived(false);
|
|
ifs->checkEnterNewState();
|
|
|
|
if (ret.error())
|
|
ERROR_LOG(m_logger) << ret();
|
|
m_mainHandler->dds()->fts()->explosionClusterReleaseReceivedReply(cookie, ret);
|
|
}
|
|
|
|
void HandlerExplosionCluster::onTargetPositionsModifyRequest(const rti::core::SampleIdentity &cookie, const TargetPositionsModifyRequest &request)
|
|
{
|
|
DEBUG_LOG(m_logger) << "onTargetPositionsModifyRequest" << request;
|
|
Core::FunctionReplyObject ret;
|
|
ObjectExplosionCluster *ifs = getObjectFromMap(m_objectMap, request.aesItemId, ret);
|
|
if (!ifs)
|
|
{
|
|
m_mainHandler->dds()->fts()->targetPositionsModifyReply(cookie, ret);
|
|
return;
|
|
}
|
|
|
|
ret = ifs->targetPositionsModify(request);
|
|
|
|
if (ret.error())
|
|
ERROR_LOG(m_logger) << ret();
|
|
m_mainHandler->dds()->fts()->targetPositionsModifyReply(cookie, ret);
|
|
}
|
|
|
|
} // Namespace AreaEffectSimulation
|
|
|