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

1024 lines
36 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_dtcTab.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_dtcTab = TrainingAreaBase::Interface::Dtc::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);
connect(m_dtcPpm.get(), &ParticipantManagement::Interface::Dtc::participantGearEventChanged,
this, &PpmHandler::onParticipantGearEventChanged);
m_dtcPpm->enableType();
m_dtcPpm->enableDynamicParticipantData();
m_dtcPpm->enableParticipant();
m_dtcPpm->enableParticipantPosition();
m_dtcPpm->enableParty();
m_dtcPpm->enableParticipantGearEvent();
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->enableEquipmentBite())
)
{
ERROR_LOG(m_logger) << "Enabling TAB DTS Data-Topics failed.";
return false;
}
// TAB TDC
connect(m_dtcTab.get(), &TrainingAreaBase::Interface::Dtc::equipmentBiteChanged,
this, &PpmHandler::onEquipmentBiteChanged);
m_dtcTab->enableEquipmentBite();
// TAB FTC
m_ftcTab->enableDemandInit();
m_ftcTab->enableDemandParticipantMode();
m_ftcTab->enableDemandBite();
// 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::guezHit, this, &PpmHandler::onParticipantHit);
connect(conn, &NgsConnector::participantReceivedInit, this, &PpmHandler::onParticipantReceivedInit);
connect(conn, &NgsConnector::guezInit, this, &PpmHandler::onParticipantInit);
connect(conn, &NgsConnector::biteReport, this, &PpmHandler::onBiteReport);
connect(conn, &NgsConnector::biteRequest, this, &PpmHandler::onBiteRequest);
connect(conn, &NgsConnector::weaponFire, this, &PpmHandler::onWeaponFire);
connect(conn, &NgsConnector::isPartOfChanged, this, &PpmHandler::onIsPartOfChanged);
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());
}
}
const std::vector<ParticipantManagement::GearInformation> oldGear = m_dynPartData.value(data.participantId()).gear();
const std::vector<ParticipantManagement::GearInformation> &newGear = data.gear();
// check if sth. changed
if (oldGear != newGear)
{
// Something to do? Gear not necessary on HLA...?
}
const std::vector<ParticipantManagement::ManipulationInformation> oldMani = m_dynPartData.value(data.participantId()).manipulation();
const std::vector<ParticipantManagement::ManipulationInformation> &newMani = data.manipulation();
// check if sth. changed
if (oldMani != newMani)
{
// Todo: Compare each to each? How to delete Manipulations?
// for (const auto x : newMani)
// conn->setManipulation(data.participantId(), x);
}
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()));
if (m_partData[data.id()].partyId() != data.partyId() && data.equipmentNumber().is_set())
m_ngsHandler->ngsConnector()->setParticipantForce(data.equipmentNumber().get(), forceIdentifierFromPartyId(data.partyId()));
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());
int mountedOnEqNo = data.mountedOn().is_set() ? getEquipmentNo(data.mountedOn().get()) : 0;
m_ngsHandler->ngsConnector()->setWorldLocation(eqNo, pos, mountedOnEqNo);
}
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);
}
// HLA -> DDS
void PpmHandler::onParticipantReceivedInit(int eqId, qint64 simTimeMSecs)
{
TrainingAreaBase::EquipmentState init;
init.equipmentNumber(eqId);
init.sampleTime(simTimeMSecs);
init.vulnerabilityBits(1);
init.vulnerabilityState(ProjectDataManagement::VulnerabilityState_def::CombatReady);
init.originatorType(ProjectDataManagement::StateChangeOriginator_def::ExerciseControl);
m_dtsTab->publish(init);
}
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;
}
}
void PpmHandler::onParticipantGearEventChanged(const ParticipantManagement::ParticipantGearEvent &data, DataModification modType)
{
if (modType != DataModification::eRemoved)
m_ngsHandler->ngsConnector()->setWeaponFire(getEquipmentNo(data.participantId()), data);
}
// 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::onEquipmentBiteChanged(const TrainingAreaBase::EquipmentBite &data, DataModification modType)
{
if (modType != DataModification::eRemoved)
m_ngsHandler->ngsConnector()->setEquipmentBite(data.equipmentNumber(), data);
}
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);
}
void PpmHandler::participantBiteRequest(const TrainingAreaBase::TetraIcd::DemandBite &request)
{
m_ngsHandler->ngsConnector()->sendParticipantBiteRequest(request.header.equipmentNumber, request.withSelfTest, request.header.timeStamp);
}
void PpmHandler::createParticipant(const ParticipantManagement::Participant &participant)
{
// Only create participants that have no external ID.
if (participant.externalId() > 0 || !participant.equipmentNumber().is_set() || participant.isDeleted() || participant.equipmentNumber().get() == 0)
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::SupportEntity:
bCreated = createObserverController(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::createHuman(const ParticipantManagement::Participant &participant)
{
const ParticipantInformation pi(participant, getTypestruct(participant.typeId()), getParticipantPosition(participant.id()));
return m_ngsHandler->ngsConnector()->addHuman(pi, currentTacticalStatus(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, currentTacticalStatus(participant.id()));
}
bool PpmHandler::createObserverController(const ParticipantManagement::Participant &participant)
{
const ParticipantInformation pi(participant, getTypestruct(participant.typeId()), getParticipantPosition(participant.id()));
return m_ngsHandler->ngsConnector()->addObserverController(pi);
}
TypeStruct PpmHandler::getTypestruct(int typeId)
{
std::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();
}
rpr2::TacticalStatusStruct PpmHandler::currentTacticalStatus(int participantId) const
{
rpr2::TacticalStatusStruct ts;
ts.VulnerabilityKind = rpr2::TacticalStatusEnum8::ET::CombatReady;
ts.TotalStatus = rpr2::TotalStatusEnum32::ET::CombatReady;
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.TacticalStatus = static_cast<rpr2::TacticalStatusEnum8::ET>(sh.at(idxCurrent).vulnerabilityState().underlying());
ts.VulnerabilityKind = sh.at(idxCurrent).vulnerabilityKindId();
ts.TotalStatus = static_cast<rpr2::TotalStatusEnum32::ET>(sh.at(idxCurrent).vulnerabilityBits());
return ts;
}
}
ts.TacticalStatus = rpr2::TacticalStatusEnum8::TemporaryFailure;
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);
}
std::vector<ParticipantManagement::GearInformation> PpmHandler::currentParticipantGearInformation(int participantId) const
{
auto itPartData = m_dynPartData.find(participantId);
if (itPartData != m_dynPartData.end())
return itPartData.value().gear();
return std::vector<ParticipantManagement::GearInformation>();
}
std::vector<ParticipantManagement::ManipulationInformation> PpmHandler::currentParticipantManipulationInformation(int participantId) const
{
auto itPartData = m_dynPartData.find(participantId);
if (itPartData != m_dynPartData.end())
return itPartData.value().manipulation();
return std::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);
m_dtcPdm = nullptr;
}
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();
m_dtcPdm = nullptr;
}
for (const auto &item : qAsConst(m_chargeTypes))
{
if (item.disEntity() == disEntity)
return item;
}
return ProjectDataManagement::ChargeType();
}
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::onDemandBiteReply(const Core::FunctionReplyObject &reply)
{
m_requestHelper->requestReply(reply);
}
void PpmHandler::onSendParticipantModeReply(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 & 0xffff) / 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::onManipulationChanged(int eqNo, bool playerIsManipulated, qint64 sampleTime)
{
// Set Manipulation:
TrainingAreaBase::EquipmentOperationalState eos;
eos.equipmentNumber(eqNo);
eos.isManipulation(playerIsManipulated);
eos.sampleTime(sampleTime);
m_dtsTab->publish(eos);
}
void PpmHandler::onWeaponFire(const TrainingAreaBase::EquipmentGearEvent &event)
{
m_dtsTab->publish(event);
}
void PpmHandler::onIsPartOfChanged(int eqNo, int eqNoHost, qint64 simTimeMSecs)
{
// Look up the old host - if any.
int eqNoOldHost = m_isMountedOn.value(eqNo, 0);
if (eqNoOldHost == eqNoHost)
return;
// Store the new host - to be the old host next time
if (eqNoHost == 0)
m_isMountedOn.remove(eqNo);
else
m_isMountedOn.insert(eqNo, eqNoHost);
// Has a (new) host now? (Aufgesessen?)
if (eqNoHost > 0)
{
// Get new Host
TrainingAreaBase::EquipmentPosition &newHost = m_observerPositions[eqNoHost];
// Add Participant to Host, no ref here
auto mountedParticipants = newHost.mountedParticipants().is_set() ? newHost.mountedParticipants().get() : std::vector<int32_t>();
// We assume, he wasn't mounted on the same before, so we simply add him to the party.
mountedParticipants.push_back(eqNo);
// Re-insert the mounted participants to new Host
newHost.mountedParticipants(mountedParticipants);
// Update Timestamp and fire
newHost.sampleTime(simTimeMSecs);
m_dtsTab->publish(newHost);
}
// Had an old host? (Abgesessen?)
if (eqNoOldHost > 0)
{
TrainingAreaBase::EquipmentPosition &oldHost = m_observerPositions[eqNoOldHost];
// Get old Host
if (!oldHost.mountedParticipants().is_set())
return;
// Remove Participant from host, ref here
auto &mountedParticipants = oldHost.mountedParticipants().get();
auto newEnd = std::remove(mountedParticipants.begin(), mountedParticipants.end(), eqNo);
auto distance = std::distance(newEnd, mountedParticipants.end());
// If nothing is removed, skip further processing
if (distance == 0)
return;
// Crop to actual length
mountedParticipants.resize(mountedParticipants.size() - distance);
// No re-inserting necessary. We work on references!
// Update Timestamp and fire
oldHost.sampleTime(simTimeMSecs);
m_dtsTab->publish(oldHost);
}
}
bool PpmHandler::onExconInit(int eqNo, rpr2::ResetPlayerEnum8::ET rp, rpr2::ActivateHelmetObservationEnum8::ET aho )
{
TrainingAreaBase::DemandInitRequest req;
req.equipmentNumbers().push_back(eqNo);
req.resetVulnerabilityState(true);
req.restockCharges(rp == rpr2::ResetPlayerEnum8::CombatReadyWithReammunition);
if (rp != rpr2::ResetPlayerEnum8::NoChange)
{
m_requestHelper->addRequest([this, req]()
{
return m_ftcTab->demandInitRequest(req, this);
});
}
ProjectDataManagement::WphMode helmet = ProjectDataManagement::WphMode_def::NoChange;;
ProjectDataManagement::WphMode vest = ProjectDataManagement::WphMode_def::NoChange;
bool bNoChange = false;
switch (aho) {
case rpr2::ActivateHelmetObservationEnum8::WithoutHelmetWithoutVest:
helmet = ProjectDataManagement::WphMode_def::Without;
vest = ProjectDataManagement::WphMode_def::Without;
break;
case rpr2::ActivateHelmetObservationEnum8::HelmetWithoutVest:
helmet = ProjectDataManagement::WphMode_def::With;
vest = ProjectDataManagement::WphMode_def::Without;
break;
case rpr2::ActivateHelmetObservationEnum8::HelmetAndVest:
helmet = ProjectDataManagement::WphMode_def::With;
vest = ProjectDataManagement::WphMode_def::With;
break;
case rpr2::ActivateHelmetObservationEnum8::NoChange:
helmet = ProjectDataManagement::WphMode_def::NoChange;
vest = ProjectDataManagement::WphMode_def::NoChange;
bNoChange = true;
break;
}
if (!bNoChange)
{
TrainingAreaBase::SendParticipantModeRequest mreq;
mreq.protectionModeHelmet(helmet);
mreq.protectionModeVest(vest);
mreq.equipmentNumber(eqNo);
m_requestHelper->addRequest([this, mreq]()
{
return m_ftcTab->sendParticipantModeRequest(mreq, this);
});
}
return m_requestHelper->startRequests();
}
bool PpmHandler::onBiteReport(const TrainingAreaBase::EquipmentBite &report)
{
DEBUG_LOG(m_logger) << "Attempting to Forward Bite Report to DDS. dtsTab: " << m_dtsTab << ", report for EqId: " << report.equipmentNumber();
if (!m_dtsTab)
return false;
return m_dtsTab->publish(report);
}
bool PpmHandler::onBiteRequest(const TrainingAreaBase::DemandBiteRequest &request)
{
if (!m_ftcTab)
return false;
return m_ftcTab->demandBiteRequest(request, this);
}
} // namespace HighLevelArchitecture