Files
qt5-legatus-legacy/Lts/Proxies/HighLevelArchitecture/Apache/ppm_handler.cpp
T
2026-08-13 18:33:10 +02:00

1003 lines
35 KiB
C++
Executable File

/**
* Send Participant data to NGS
* $Id$
* $HeadURL$
* $Author$
* Created by Christian Ehrlicher, SLSE, 2017-04-07
*/
#include "ppm_handler.h"
#include "ngs_handler.h"
#include <Common/participantinformation.h>
#include <LtsUtilsGuiDds/request_helper.h>
#include <EntityTypeStruct.h>
#include <Proxies/TrainingAreaBase/tab.hpp>
namespace HighLevelArchitecture
{
PpmHandler::PpmHandler(NgsHandler *ngsHandler)
: m_ngsHandler(ngsHandler)
, m_requestHelper(new LtsUtils::RequestHelper(this))
, m_logger(getLogger("PpmHandler"))
{}
PpmHandler::~PpmHandler()
{
m_dtcPpm.reset();
m_ftcPpm.reset();
m_dtcPdm.reset();
m_dtsTab.reset();
m_ftcTab.reset();
m_dtcAes.reset();
}
bool PpmHandler::init()
{
m_dtcPpm = ParticipantManagement::Interface::Dtc::create(m_ngsHandler->ddsHandler()->ddsConnector());
m_ftcPpm = ParticipantManagement::Interface::Ftc::create(m_ngsHandler->ddsHandler()->ddsConnector());
m_dtcPdm = ProjectDataManagement::Interface::Dtc::create(m_ngsHandler->ddsHandler()->ddsConnector());
m_dtsTab = TrainingAreaBase::Interface::Dts::create(m_ngsHandler->ddsHandler()->ddsConnector());
m_ftcTab = TrainingAreaBase::Interface::Ftc::create(m_ngsHandler->ddsHandler()->ddsConnector());
m_dtcAes = AreaEffectSimulation::Interface::Dtc::create(m_ngsHandler->ddsHandler()->ddsConnector());
// PPM DTC
connect(m_dtcPpm.get(), &ParticipantManagement::Interface::Dtc::typeChanged,
this, &PpmHandler::onTypeChanged);
connect(m_dtcPpm.get(), &ParticipantManagement::Interface::Dtc::dynamicParticipantDataChanged,
this, &PpmHandler::onDynamicParticipantDataChanged);
connect(m_dtcPpm.get(), &ParticipantManagement::Interface::Dtc::participantChanged,
this, &PpmHandler::onParticipantChanged);
connect(m_dtcPpm.get(), &ParticipantManagement::Interface::Dtc::participantPositionChanged,
this, &PpmHandler::onParticipantPositionChanged);
connect(m_dtcPpm.get(), &ParticipantManagement::Interface::Dtc::partyChanged,
this, &PpmHandler::onPartyChanged);
m_dtcPpm->enableType();
m_dtcPpm->enableDynamicParticipantData();
m_dtcPpm->enableParticipant();
m_dtcPpm->enableParticipantPosition();
m_dtcPpm->enableParty();
m_dtcPpm->enableParticipantGearEvent();
m_dtcPdm->enableGearTypeChargeType();
m_dtcPpm->waitForHistoricalDataParticipant();
// PPM FTC
m_ftcPpm->enableModifyParticipantData();
// PDM DTC
connect(m_dtcPdm.get(), &ProjectDataManagement::Interface::Dtc::chargeTypeChanged,
this, &PpmHandler::onChargeTypeChanged);
m_dtcPdm->enableChargeType();
// TAB DTS
if (!(m_dtsTab->enableEquipmentPosition() &&
m_dtsTab->enableEquipmentGearEvent() &&
m_dtsTab->enableEquipmentState() &&
m_dtsTab->enableLaserDesignation() &&
m_dtsTab->enableSpecialSensorData() &&
m_dtsTab->enableGearCharge() &&
m_dtsTab->enableEquipmentGearChargeState() &&
m_dtsTab->enableEquipmentGearAssignment())
)
{
ERROR_LOG(m_logger) << "Enabling TAB DTS Data-Topics failed.";
return false;
}
// TAB FTC
m_ftcTab->enableDemandInit();
m_ftcTab->enableDemandVulnerabilityStateChange();
m_ftcTab->enableSendCesHitInformation();
// AES DTC
// Nothing to do as only aesItemIdFromExternalId is called.
// Connect Connector signals to slots here.
NgsConnector *conn = m_ngsHandler->ngsConnector().get();
connect(conn, &NgsConnector::firstTickFinished, this, &PpmHandler::startPublishToNgs);
connect(conn, &NgsConnector::spatialChanged, this, &PpmHandler::onSpatialChanged);
connect(conn, &NgsConnector::markingChanged, this, &PpmHandler::onMarkingChanged);
connect(conn, &NgsConnector::exconEngagement, this, &PpmHandler::onExconEngagement);
connect(conn, &NgsConnector::weaponFire, this, &PpmHandler::onWeaponFire);
connect(conn, &NgsConnector::gearChargeState, this, &PpmHandler::onGearChargeState);
connect(conn, &NgsConnector::cesHitInformation, this, &PpmHandler::onParticipantCesHit);
connect(conn, &NgsConnector::equipmentState, this, &PpmHandler::onEquipmentState);
connect(conn, &NgsConnector::laserDesignation, this, &PpmHandler::onLaserDesignation);
connect(conn, &NgsConnector::sensorChanged, this, &PpmHandler::onSensorDataChanged);
return true;
}
ParticipantManagement::Role PpmHandler::roleForPartyId(int partyId)
{
if (partyId <= 0)
return ParticipantManagement::Role_def::Unknown;
auto it = m_partyData.constFind(partyId);
if (it == m_partyData.constEnd())
{
m_dtcPpm->waitForHistoricalDataParty();
m_partyData = m_dtcPpm->partys();
it = m_partyData.constFind(partyId);
if (it == m_partyData.constEnd())
return ParticipantManagement::Role_def::Unknown;
}
return it.value().role();
}
// DDS -> own memory
void PpmHandler::onTypeChanged(const ParticipantManagement::Type &data, DataModification modType)
{
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
m_types[data.id()] = data;
break;
case DataModification::eRemoved:
m_types.remove(data.id());
break;
}
}
int PpmHandler::getEquipmentNo(int participantId) const
{
if (!m_partData.contains(participantId))
return 0;
const ParticipantManagement::Participant &p = m_partData[participantId];
if (!p.equipmentNumber().is_set())
return 0;
return p.equipmentNumber().get();
}
int PpmHandler::getParticipantIdByExternalId(int externalId) const
{
for(const auto &part : qAsConst(m_partData))
{
if (part.externalId() == externalId)
return part.id();
}
return 0;
}
// DDS -> HLA
void PpmHandler::onDynamicParticipantDataChanged(const ParticipantManagement::DynamicParticipantData &data, DataModification modType)
{
int equipmentNo = getEquipmentNo(data.participantId());
if (equipmentNo == 0)
{
ERROR_LOG(m_logger) << "Could not find EquipmentNo for Participant " << data.participantId() << ". Cannot send Dynamic Participant Data Modification to HLA.";
return;
}
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
{
if (!m_ngsHandler->ngsConnector()->canPublishData())
break;
std::shared_ptr<NgsConnector> conn = m_ngsHandler->ngsConnector();
const ParticipantManagement::StateInformation oldStateInfo = currentParticipantStateInformation(m_dynPartData.value(data.participantId()));
const ParticipantManagement::StateInformation newStateInfo = currentParticipantStateInformation(data);
// Improvement: Pass Originator to Connector, so the source can also be AES.
if (oldStateInfo != newStateInfo)
{
m_dynPartData[data.participantId()] = data;
if (newStateInfo.originatorType() == ProjectDataManagement::StateChangeOriginator::AreaEffectSimulation)
{
// Aes hit
conn->setParticipantHit(equipmentNo,
newStateInfo,
getParticipantPosition(data.participantId()),
newStateInfo.originatorChargeTypeId(),
newStateInfo.originatorType(),
newStateInfo.originatorId());
}
else if (newStateInfo.originatorType() == ProjectDataManagement::StateChangeOriginator::Participant)
{
// direct hit
conn->setParticipantHit(equipmentNo,
newStateInfo,
getParticipantPosition(data.participantId()),
newStateInfo.originatorChargeTypeId(),
newStateInfo.originatorType(),
getEquipmentNo(newStateInfo.originatorId()));
}
else
{
// TODO: ProjectDataManagement::StateChangeOriginator::OperatorController, ExerciseControl, WoundTreatmentDevice, MaintainanceDevice
// reactivation or something similar
conn->setParticipantHit(equipmentNo,
newStateInfo,
getParticipantPosition(data.participantId()),
newStateInfo.originatorChargeTypeId(),
newStateInfo.originatorType(),
newStateInfo.originatorId());
}
}
break;
}
case DataModification::eRemoved:
m_dynPartData.remove(data.participantId());
break;
}
}
// DDS -> HLA
void PpmHandler::onParticipantChanged(const ParticipantManagement::Participant &data, DataModification modType)
{
DEBUG_LOG(m_logger) << "onParticipantChanged: " << data;
switch (modType)
{
case DataModification::eAdded:
createParticipant(data);
m_partData[data.id()] = data;
break;
case DataModification::eModified:
{
// Participant has been deleted
if (data.isDeleted() && !m_partData[data.id()].isDeleted())
{
removeParticipant(m_partData[data.id()]); // Remove the old Equipment No
removeParticipant(data); // If it has a new Equipment No, kill it also.
m_partData[data.id()] = data;
break;
}
// Participant is new // Shouldn't happen, as it is the Added case
if (!m_partData.contains(data.id()))
{
createParticipant(data);
m_partData[data.id()] = data;
break;
}
// Only create/remove if Equipment Number changed...
int oldEqNo = m_partData[data.id()].equipmentNumber().is_set() ? m_partData[data.id()].equipmentNumber().get() : 0;
int newEqNo = data.equipmentNumber().is_set() ? data.equipmentNumber().get() : 0;
if (oldEqNo != newEqNo)
{
removeParticipant(m_partData[data.id()]);
createParticipant(data);
}
if (m_partData[data.id()].designator() != data.designator() && data.equipmentNumber().is_set())
m_ngsHandler->ngsConnector()->setParticipantName(data.equipmentNumber().get(), QString::fromStdString(data.designator()));
m_partData[data.id()] = data;
break;
}
case DataModification::eRemoved:
removeParticipant(data);
m_partData.remove(data.id());
break;
}
auto it = m_externalEquipmentNumbers.find(data.id());
if (it == m_externalEquipmentNumbers.end())
{
// not found
if (modType == DataModification::eRemoved || !data.equipmentNumber().is_set() || data.externalId() <= 0)
return;
int equipNo = data.equipmentNumber().get();
m_externalEquipmentNumbers.insert(data.id(), equipNo);
emit externalEquipmentNumberAdded(equipNo);
}
else
{
// found
int oldEquipNo = it.value();
if (modType == DataModification::eRemoved || !data.equipmentNumber().is_set() || data.externalId() <= 0)
{
m_externalEquipmentNumbers.erase(it);
emit externalEquipmentNumberRemoved(oldEquipNo);
return;
}
if (oldEquipNo != data.equipmentNumber().get())
{
emit externalEquipmentNumberRemoved(oldEquipNo);
emit externalEquipmentNumberAdded(data.equipmentNumber().get());
it.value() = data.equipmentNumber().get();
}
}
}
// DDS -> HLA
void PpmHandler::onParticipantPositionChanged(const ParticipantManagement::ParticipantPosition &data, DataModification modType)
{
DEBUG_LOG(m_logger) << "onParticipantPositionChanged: " << data;
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
{
if (m_ngsHandler->ngsConnector()->canPublishData())
{
int eqNo = getEquipmentNo(data.participantId());
if (eqNo == 0)
return;
ParticipantPosition pos(data.pos(), data.sampleTime());
m_ngsHandler->ngsConnector()->setWorldLocation(eqNo, pos);
}
m_partPosData[data.participantId()] = data;
break;
}
case DataModification::eRemoved:
m_partPosData.remove(data.participantId());
break;
}
}
// HLA -> DDS
void PpmHandler::onSpatialChanged(int eqId, const ParticipantPosition &pos, qint64 simTimeMSecs)
{
// NGSConnector already checked that the position changed significantly
TrainingAreaBase::EquipmentPosition &position = m_observerPositions[eqId];
position.position().position() = pos.toGeoPosition();
position.equipmentNumber(eqId); // With SAAB, ExternalId and EqId are the same!
position.sampleTime(simTimeMSecs);
m_dtsTab->publish(position);
}
void PpmHandler::onSensorDataChanged(const TrainingAreaBase::SpecialSensorData &event)
{
m_dtsTab->publish(event);
}
bool PpmHandler::onMarkingChanged(int eqId, const QString &marking, qint64 simTimeMSecs)
{
Q_UNUSED(simTimeMSecs);
// According to Ulli, the external (fixed) designation shall be the tactIdentifier. The designator thus is freely changeable.
ParticipantManagement::ParticipantData p = m_dtcPpm->convertParticipantToParticipantData(m_dtcPpm->participant(m_dtcPpm->participantIdByEquipmentNumber(eqId)));
if (p.tacticalIdentifier() == marking.toStdString())
return true;
p.tacticalIdentifier(marking.toStdString());
ParticipantManagement::ModifyParticipantDataRequest req;
req.data().push_back(std::move(p));
return m_requestHelper->startSingleRequest([this, req]()
{
return m_ftcPpm->modifyParticipantDataRequest(req, this);
});
}
// DDS -> own memory
void PpmHandler::onPartyChanged(const ParticipantManagement::Party &data, DataModification modType)
{
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
m_partyData[data.id()] = data;
break;
case DataModification::eRemoved:
m_partyData.remove(data.id());
break;
}
}
// DDS -> own memory
void PpmHandler::onChargeTypeChanged(const ProjectDataManagement::ChargeType &data, DataModification modType)
{
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
m_chargeTypes[data.id()] = data;
break;
case DataModification::eRemoved:
m_chargeTypes.remove(data.id());
break;
}
}
void PpmHandler::startPublishToNgs()
{
INFO_LOG(m_logger) << "Recreating all players from scratch due to structure / exercise change";
// 1. Cleanup
m_createdParticipantIds.clear();
// 2. Remove all virtual Players from database
// not yet supporteed
// 4. Recreate players
INFO_LOG(m_logger) << "(Re)Adding all players, size: " << m_partData.size();
for (const ParticipantManagement::Participant &participant : qAsConst(m_partData))
createParticipant(participant);
}
void PpmHandler::participantInitRequest(const TrainingAreaBase::TetraIcd::Init &request)
{
m_ngsHandler->ngsConnector()->sendParticipantInitRequest(request.header.equipmentNumber, request.resetManipulation, request.resetVulnerabilityState, request.restockCharges, request.header.timeStamp);
}
rpr2::DetonationResultCodeEnum8::ET PpmHandler::rpr2DetonationResultFromVulnerabilityState(TrainingAreaBase::TetraIcd::VulnerabilityState vulnerabilityState)
{
// ICE only cares about EntityImpact and EntotyProximateDetonation. Everything else will be discarded
rpr2::DetonationResultCodeEnum8::ET status = rpr2::DetonationResultCodeEnum8::None;
switch(vulnerabilityState)
{
case TrainingAreaBase::TetraIcd::VulnerabilityState::CombatReady:
status = rpr2::DetonationResultCodeEnum8::None;
break;
case TrainingAreaBase::TetraIcd::VulnerabilityState::LightDamage:
case TrainingAreaBase::TetraIcd::VulnerabilityState::MediumDamage:
case TrainingAreaBase::TetraIcd::VulnerabilityState::HeavyDamage:
case TrainingAreaBase::TetraIcd::VulnerabilityState::MobilityKill:
case TrainingAreaBase::TetraIcd::VulnerabilityState::VisibleMobilityKill:
case TrainingAreaBase::TetraIcd::VulnerabilityState::WeaponSystemDamage:
case TrainingAreaBase::TetraIcd::VulnerabilityState::VisibleWeaponSystemDamage:
status = rpr2::DetonationResultCodeEnum8::AirHit;
break;
case TrainingAreaBase::TetraIcd::VulnerabilityState::CatastrophicKill:
status = rpr2::DetonationResultCodeEnum8::EntityImpact;
break;
case TrainingAreaBase::TetraIcd::VulnerabilityState::TemporarySeverance:
case TrainingAreaBase::TetraIcd::VulnerabilityState::NearMiss:
case TrainingAreaBase::TetraIcd::VulnerabilityState::HitWithNoEffect:
status = rpr2::DetonationResultCodeEnum8::EntityProximateDetonation;
break;
case TrainingAreaBase::TetraIcd::VulnerabilityState::VulnerabilityBitsChanged:
case TrainingAreaBase::TetraIcd::VulnerabilityState::Reserved:
case TrainingAreaBase::TetraIcd::VulnerabilityState::NContamination:
case TrainingAreaBase::TetraIcd::VulnerabilityState::BContamination:
case TrainingAreaBase::TetraIcd::VulnerabilityState::CContamination:
status = rpr2::DetonationResultCodeEnum8::Other;
break;
}
return status;
}
rpr2::DetonationResultCodeEnum8::ET PpmHandler::rpr2DetonationResultFromPercentage(int percentage)
{
rpr2::DetonationResultCodeEnum8::ET status = rpr2::DetonationResultCodeEnum8::EntityProximateDetonation;
if (percentage > 0)
status = rpr2::DetonationResultCodeEnum8::AirHit;
if (percentage > 50)
status = rpr2::DetonationResultCodeEnum8::EntityImpact;
return status;
}
void PpmHandler::participantVulnerabilityStateRequest(const TrainingAreaBase::TetraIcd::DemandVulnerabilityStateChange &request)
{
DEBUG_LOG(m_logger) << "Participant Vulnerability State Request";
rpr2::DetonationResultCodeEnum8::ET resCode = rpr2DetonationResultFromVulnerabilityState(request.reqestedState);
m_ngsHandler->ngsConnector()->sendMunitionDetonation(request.header.equipmentNumber,
ProjectDataManagement::ChargeType(),
0,
resCode,
request.header.timeStamp);
}
void PpmHandler::participantCesHitInformationRequest(const TrainingAreaBase::TetraIcd::CesHitInformation &request)
{
rpr2::DetonationResultCodeEnum8::ET resCode = rpr2DetonationResultFromPercentage(request.effectPercent);
ProjectDataManagement::ChargeType ct = chargeTypeFromTasCodeDirect(request.chargeTasCodeDirect);
m_ngsHandler->ngsConnector()->sendMunitionDetonation(request.header.equipmentNumber,
ct,
request.originatorEquipmentNumber,
resCode,
request.header.timeStamp);
}
void PpmHandler::createParticipant(const ParticipantManagement::Participant &participant)
{
// Only create participants that have no external ID.
if (participant.externalId() > 0 || participant.equipmentNumber() == 0 || participant.isDeleted())
return;
if (!m_ngsHandler->ngsConnector()->canPublishData())
{
WARNING_LOG(m_logger) << "Can not publish data ... :(";
return;
}
if (m_createdParticipantIds.contains(participant.id()))
return;
const ParticipantManagement::Type partType = getParticipantType(participant.typeId());
bool bCreated;
switch (partType.typeClass().underlying())
{
case ParticipantManagement::TypeClass_def::Human:
bCreated = createHuman(participant);
break;
case ParticipantManagement::TypeClass_def::GroundVehicle:
case ParticipantManagement::TypeClass_def::VehicleWithGear:
case ParticipantManagement::TypeClass_def::WeaponSystem:
bCreated = createGroundVehicle(participant);
break;
case ParticipantManagement::TypeClass_def::Aircraft:
bCreated = createAircraft(participant);
break;
case ParticipantManagement::TypeClass_def::SupportEntity:
case ParticipantManagement::TypeClass_def::Unit:
// bCreated = createUnit(participant);
// break;
case ParticipantManagement::TypeClass_def::Vessel:
// bCreated = createVessel(participant);
// break;
default:
bCreated = false;
}
if (!bCreated)
return;
m_createdParticipantIds += participant.id();
}
bool PpmHandler::removeParticipant(const ParticipantManagement::Participant &participant)
{
if (!participant.equipmentNumber().is_set() || participant.equipmentNumber().get() == 0)
return false;
return m_ngsHandler->ngsConnector()->removeBaseEntity(participant.equipmentNumber().get());
}
//bool PpmHandler::createUnit(const ParticipantManagement::Participant &participant)
//{
// const ParticipantInformation pi(participant2ParticipantInformation(participant));
// return m_ngsHandler->ngsConnector()->addAggregateEntity(pi, participant.inferiorIds());
//}
bool PpmHandler::createHuman(const ParticipantManagement::Participant &participant)
{
const ParticipantInformation pi(participant, getTypestruct(participant.typeId()), getParticipantPosition(participant.id()));
return m_ngsHandler->ngsConnector()->addHuman(pi, currentVulnerabilityState(participant.id()));
}
bool PpmHandler::createGroundVehicle(const ParticipantManagement::Participant &participant)
{
const ParticipantInformation pi(participant, getTypestruct(participant.typeId()), getParticipantPosition(participant.id()));
return m_ngsHandler->ngsConnector()->addGroundVehicle(pi, currentVulnerabilityState(participant.id()));
}
bool PpmHandler::createAircraft(const ParticipantManagement::Participant &participant)
{
const ParticipantInformation pi(participant, getTypestruct(participant.typeId()), getParticipantPosition(participant.id()));
return m_ngsHandler->ngsConnector()->addLongBowApache(pi, currentVulnerabilityState(participant.id()));
}
TypeStruct PpmHandler::getTypestruct(int typeId)
{
dds::core::vector<rti::core::int64> disEntities = getParticipantType(typeId).disEntities();
if (disEntities.size())
return TypeStruct::fromDisInt(disEntities.at(0)); // First is relevant for sending
return TypeStruct();
}
ParticipantManagement::Type PpmHandler::getParticipantType(int typeId)
{
auto it = m_types.constFind(typeId);
if (it == m_types.constEnd())
{
m_dtcPpm->waitForHistoricalDataType();
m_types = m_dtcPpm->types();
it = m_types.constFind(typeId);
if (it == m_types.constEnd())
return ParticipantManagement::Type();
}
return it.value();
}
ProjectDataManagement::VulnerabilityState PpmHandler::currentVulnerabilityState(int participantId) const
{
ProjectDataManagement::VulnerabilityState ts;
auto itPartData = m_dynPartData.find(participantId);
if (itPartData != m_dynPartData.end())
{
const auto &sh = itPartData.value().stateHistory();
if (sh.size() != 0)
{
size_t idxCurrent = 0;
for (size_t i = 1; i < sh.size(); ++i)
{
if (sh.at(idxCurrent).stateTime() < sh.at(i).stateTime())
idxCurrent = i;
}
ts = sh.at(idxCurrent).vulnerabilityState();
return ts;
}
}
ts = ProjectDataManagement::VulnerabilityState_def::TemporarySeverance;
return ts;
}
ParticipantManagement::StateInformation PpmHandler::currentParticipantStateInformation(int participantId) const
{
auto itPartData = m_dynPartData.find(participantId);
if (itPartData != m_dynPartData.end())
return currentParticipantStateInformation(itPartData.value());
return ParticipantManagement::StateInformation();
}
ParticipantManagement::StateInformation PpmHandler::currentParticipantStateInformation(const ParticipantManagement::DynamicParticipantData &data)
{
const auto &sh = data.stateHistory();
if (sh.size() == 0)
return ParticipantManagement::StateInformation();
size_t idxCurrent = 0;
for (size_t i = 1; i < sh.size(); ++i)
{
if (sh.at(idxCurrent).stateTime() < sh.at(i).stateTime())
idxCurrent = i;
}
return sh.at(idxCurrent);
}
dds::core::vector<ParticipantManagement::GearInformation> PpmHandler::currentParticipantGearInformation(int participantId) const
{
auto itPartData = m_dynPartData.find(participantId);
if (itPartData != m_dynPartData.end())
return itPartData.value().gear();
return dds::core::vector<ParticipantManagement::GearInformation>();
}
dds::core::vector<ParticipantManagement::ManipulationInformation> PpmHandler::currentParticipantManipulationInformation(int participantId) const
{
auto itPartData = m_dynPartData.find(participantId);
if (itPartData != m_dynPartData.end())
return itPartData.value().manipulation();
return dds::core::vector<ParticipantManagement::ManipulationInformation>();
}
ProjectDataManagement::ChargeType PpmHandler::chargeTypeFromId(int chargeTypeId)
{
auto it = m_chargeTypes.constFind(chargeTypeId);
if (it == m_chargeTypes.constEnd() && m_dtcPdm)
{
m_dtcPdm->waitForHistoricalDataChargeType();
m_chargeTypes = m_dtcPdm->chargeTypes();
it = m_chargeTypes.constFind(chargeTypeId);
}
return (it == m_chargeTypes.constEnd()) ? ProjectDataManagement::ChargeType() : it.value();
}
ProjectDataManagement::ChargeType PpmHandler::chargeTypeFromDisEntity(const std::string &disEntity)
{
if (m_chargeTypes.isEmpty() && m_dtcPdm)
{
m_dtcPdm->waitForHistoricalDataChargeType();
m_chargeTypes = m_dtcPdm->chargeTypes();
}
for (const auto &item : qAsConst(m_chargeTypes))
{
if (item.disEntity() == disEntity)
return item;
}
return ProjectDataManagement::ChargeType();
}
ProjectDataManagement::ChargeType PpmHandler::chargeTypeFromTasCodeDirect(int32_t tasCode)
{
if (m_chargeTypes.isEmpty() && m_dtcPdm)
{
m_dtcPdm->waitForHistoricalDataChargeType();
m_chargeTypes = m_dtcPdm->chargeTypes();
}
for (const auto &item : qAsConst(m_chargeTypes))
{
if (item.legacyId() == tasCode)
return item;
}
return ProjectDataManagement::ChargeType();
}
int PpmHandler::gearTypeIdFromChargeTypeId(int chargeTypeId)
{
if (m_gearTypeChargeTypes.isEmpty() && m_dtcPdm)
{
m_dtcPdm->waitForHistoricalDataGearTypeChargeType();
m_gearTypeChargeTypes = m_dtcPdm->gearTypeChargeTypes();
}
int gearTypeId = 999999999;
for (const auto &item : qAsConst(m_gearTypeChargeTypes))
{
if (item.chargeTypeId() == chargeTypeId)
if (item.gearTypeId() < gearTypeId)
gearTypeId = item.gearTypeId();
}
if (gearTypeId == 999999999)
return 0;
return gearTypeId;
}
rpr2::ForceIdentifierEnum8::ET PpmHandler::getRprForceIdentifierFromPpmForceIdentifier(const ParticipantManagement::HlaForceIdentifierEnum& ppmForceIdentifier) const
{
rpr2::ForceIdentifierEnum8::ET eqfi = rpr2::ForceIdentifierEnum8::Other;
switch (ppmForceIdentifier.underlying()) {
case ParticipantManagement::HlaForceIdentifierEnum_def::Friendly_1:
eqfi = rpr2::ForceIdentifierEnum8::Friendly;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Friendly_2:
eqfi = rpr2::ForceIdentifierEnum8::Friendly_2;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Friendly_3:
eqfi = rpr2::ForceIdentifierEnum8::Friendly_3;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Friendly_4:
eqfi = rpr2::ForceIdentifierEnum8::Friendly_4;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Friendly_5:
eqfi = rpr2::ForceIdentifierEnum8::Friendly_5;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Friendly_6:
eqfi = rpr2::ForceIdentifierEnum8::Friendly_6;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Friendly_7:
eqfi = rpr2::ForceIdentifierEnum8::Friendly_7;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Friendly_8:
eqfi = rpr2::ForceIdentifierEnum8::Friendly_8;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Friendly_9:
eqfi = rpr2::ForceIdentifierEnum8::Friendly_9;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Friendly_10:
eqfi = rpr2::ForceIdentifierEnum8::Friendly_10;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Opposing_1:
eqfi = rpr2::ForceIdentifierEnum8::Opposing;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Opposing_2:
eqfi = rpr2::ForceIdentifierEnum8::Opposing_2;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Opposing_3:
eqfi = rpr2::ForceIdentifierEnum8::Opposing_3;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Opposing_4:
eqfi = rpr2::ForceIdentifierEnum8::Opposing_4;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Opposing_5:
eqfi = rpr2::ForceIdentifierEnum8::Opposing_5;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Opposing_6:
eqfi = rpr2::ForceIdentifierEnum8::Opposing_6;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Opposing_7:
eqfi = rpr2::ForceIdentifierEnum8::Opposing_7;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Opposing_8:
eqfi = rpr2::ForceIdentifierEnum8::Opposing_8;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Opposing_9:
eqfi = rpr2::ForceIdentifierEnum8::Opposing_9;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Opposing_10:
eqfi = rpr2::ForceIdentifierEnum8::Opposing_10;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Neutral_1:
eqfi = rpr2::ForceIdentifierEnum8::Neutral;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Neutral_2:
eqfi = rpr2::ForceIdentifierEnum8::Neutral_2;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Neutral_3:
eqfi = rpr2::ForceIdentifierEnum8::Neutral_3;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Neutral_4:
eqfi = rpr2::ForceIdentifierEnum8::Neutral_4;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Neutral_5:
eqfi = rpr2::ForceIdentifierEnum8::Neutral_5;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Neutral_6:
eqfi = rpr2::ForceIdentifierEnum8::Neutral_6;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Neutral_7:
eqfi = rpr2::ForceIdentifierEnum8::Neutral_7;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Neutral_8:
eqfi = rpr2::ForceIdentifierEnum8::Neutral_8;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Neutral_9:
eqfi = rpr2::ForceIdentifierEnum8::Neutral_9;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Neutral_10:
eqfi = rpr2::ForceIdentifierEnum8::Neutral_10;
break;
case ParticipantManagement::HlaForceIdentifierEnum_def::Other:
eqfi = rpr2::ForceIdentifierEnum8::Other;
break;
}
return eqfi;
}
int PpmHandler::partyIdFromForceIdentifier(rpr2::ForceIdentifierEnum8::ET fi)
{
if (m_partyData.isEmpty() && m_dtcPpm)
{
m_dtcPpm->waitForHistoricalDataParty();
m_partyData = m_dtcPpm->partys();
}
for (const ParticipantManagement::Party &item : qAsConst(m_partyData))
{
if (fi == getRprForceIdentifierFromPpmForceIdentifier(item.hlaForceIdentifier()))
return item.id();
}
return -1;
}
rpr2::ForceIdentifierEnum8::ET PpmHandler::forceIdentifierFromPartyId(int partyId)
{
if (m_partyData.isEmpty() && m_dtcPpm)
{
m_dtcPpm->waitForHistoricalDataParty();
m_partyData = m_dtcPpm->partys();
}
if (!m_partyData.contains(partyId))
return rpr2::ForceIdentifierEnum8::Other;
return getRprForceIdentifierFromPpmForceIdentifier(m_partyData[partyId].hlaForceIdentifier());
}
void PpmHandler::onModifyParticipantDataReply(const Core::FunctionReplyObject &replyObject)
{
m_requestHelper->requestReply(replyObject);
}
void PpmHandler::onDemandInitReply(const Core::FunctionReplyObject &reply)
{
m_requestHelper->requestReply(reply);
}
void PpmHandler::onDemandVulnerabilityStateChangeReply(const Core::FunctionReplyObject &reply)
{
m_requestHelper->requestReply(reply);
}
void PpmHandler::onSendCesHitInformationReply(const Core::FunctionReplyObject &reply)
{
m_requestHelper->requestReply(reply);
}
ParticipantPosition PpmHandler::getParticipantPosition(int participantId) const
{
auto itPartPos = m_partPosData.find(participantId);
if (itPartPos == m_partPosData.end())
return ParticipantPosition();
ParticipantPosition pp(itPartPos.value().pos());
pp.msec = itPartPos.value().sampleTime();
return pp;
}
void PpmHandler::onParticipantHit(const GuezHitStruct &hitStruct)
{
const auto ct = chargeTypeFromDisEntity(hitStruct.originatorChargeTypeEtsString.toStdString());
TrainingAreaBase::TabPosition pos;
pos.position(hitStruct.position);
pos.reportingSource(Core::PositionReportingSource_def::External);
TrainingAreaBase::EquipmentState es;
es.equipmentNumber(hitStruct.targetId);
es.originatorChargeTypeId(ct.id());
if (hitStruct.originatorType.underlying() == ProjectDataManagement::StateChangeOriginator_def::AreaEffectSimulation)
{
int aesItemId = 0;
if (m_dtcAes->aesItemIdFromExternalId(hitStruct.originatorId, aesItemId) == AreaEffectSimulation::AesType_def::AtUnknown)
es.originatorId(hitStruct.originatorId % 10); // Not found, therefore it is our AesItem that is sent with (AesItemId * 10)
else
es.originatorId(aesItemId);
}
else
{
es.originatorId(hitStruct.originatorId);
}
es.originatorType(hitStruct.originatorType);
es.sampleTime(hitStruct.sampleTime);
es.vulnerabilityBits(hitStruct.vulnerabilityBits);
es.vulnerabilityKindId(hitStruct.vulnerabilityKind);
es.vulnerabilityState(hitStruct.vulnerabilityState);
if (!qIsNull(hitStruct.position.lat()) || !qIsNull(hitStruct.position.lon()))
es.position(pos);
m_dtsTab->publish(es);
// Damage Model recognizes change of Manipulation for itself and calls the Slot all by itself.
// onManipulationChanged(hitStruct.targetId, hitStruct.vulnerabilityBits & rpr2::TotalStatusEnum32::Manipulation, es.sampleTime());
}
void PpmHandler::onParticipantInit(int eqNo, bool resetManipulation, bool resupplyAmmo, bool resetVulnerabilityState)
{
TrainingAreaBase::DemandInitRequest dir;
dir.equipmentNumbers().push_back(eqNo);
dir.requestId(1);
dir.resetManipulation(resetManipulation);
dir.restockCharges(resupplyAmmo);
dir.resetVulnerabilityState(resetVulnerabilityState);
m_requestHelper->startSingleRequest([this, dir]()
{
return m_ftcTab->demandInitRequest(dir, this);
});
}
void PpmHandler::onParticipantCesHit(const TrainingAreaBase::SendCesHitInformation &request)
{
m_ftcTab->sendCesHitInformationRequest(request, this);
}
void PpmHandler::onLaserDesignation(const TrainingAreaBase::LaserDesignation &request)
{
m_dtsTab->publish(request);
}
void PpmHandler::onWeaponFire(const TrainingAreaBase::EquipmentGearEvent &event)
{
m_dtsTab->publish(event);
}
void PpmHandler::onGearChargeState(const TrainingAreaBase::EquipmentGearChargeState &event)
{
m_dtsTab->publish(event);
}
void PpmHandler::onGearAssignment(const TrainingAreaBase::EquipmentGearAssignment &event)
{
m_dtsTab->publish(event);
}
void PpmHandler::onEquipmentState(const TrainingAreaBase::EquipmentState &event)
{
m_dtsTab->publish(event);
}
bool PpmHandler::onExconEngagement(int eqNo, const ProjectDataManagement::VulnerabilityState &state)
{
if (state != ProjectDataManagement::VulnerabilityState_def::CombatReady)
{
TrainingAreaBase::DemandVulnerabilityStateChangeRequest req;
req.equipmentNumbers().push_back(eqNo);
req.requestId(1); // irrelevant
req.vulnerabilityState(state);
return m_requestHelper->startSingleRequest([this, req]()
{
return m_ftcTab->demandVulnerabilityStateChangeRequest(req, this);
});
}
TrainingAreaBase::DemandInitRequest req;
req.equipmentNumbers().push_back(eqNo);
req.resetVulnerabilityState(true);
return m_requestHelper->startSingleRequest([this, req]()
{
return m_ftcTab->demandInitRequest(req, this);
});
}
} // namespace HighLevelArchitecture