Files
qt5-legatus-legacy/Lts/Services/CentralEffectSimulation/handler_participant.cpp
T
2026-08-13 18:33:10 +02:00

604 lines
22 KiB
C++
Executable File

/**
* Handler for player data
* $Id$
* $HeadURL$
* $Author$
* Created by gr, SLSE, 2017-02-20
*/
#include "handler_participant.h"
#include "handler_building_data.h"
#include <ParticipantManagement/ppm_common.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <QLineF>
namespace CentralEffectSimulation
{
HandlerParticipant::HandlerParticipant(const std::shared_ptr<DdsHandler> &ddsHandler,
const std::shared_ptr<HandlerBuildingData> &handlerBuildingData,
int cheatingDistanceVehicle,
int cheatingDistanceSoldier,
QObject *parent)
: QObject(parent)
, m_ddsHandler(ddsHandler)
, m_handlerBuildingData(handlerBuildingData)
, m_cheatingDistanceVehicle(cheatingDistanceVehicle)
, m_cheatingDistanceSoldier(cheatingDistanceSoldier)
, m_logger(CentralEffectSimulation::getLogger("HandlerParticipant"))
{
} // end of ctor()
//-----------------------------------------------------------------------------
HandlerParticipant::~HandlerParticipant()
{
} // end of dtor()
//-----------------------------------------------------------------------------
bool HandlerParticipant::init()
{
auto dtcPpm = m_ddsHandler->dtcPpm();
INFO_LOG(m_logger) << "m_cheatingDistanceVehicle=" << m_cheatingDistanceVehicle
<< " m_cheatingDistanceSoldier=" << m_cheatingDistanceSoldier;
// waitForHistorical...
dtcPpm->waitForHistoricalDataType(1000);
dtcPpm->waitForHistoricalDataParticipant(1000);
dtcPpm->waitForHistoricalDataDynamicParticipantData(1000);
dtcPpm->waitForHistoricalDataParticipantPosition(1000);
// connect:
connect(dtcPpm.get(), &ParticipantManagement::Interface::Dtc::participantPositionChanged,
this, &HandlerParticipant::onParticipantPositionChanged);
connect(dtcPpm.get(), &ParticipantManagement::Interface::Dtc::dynamicParticipantDataChanged,
this, &HandlerParticipant::onDynamicParticipantDataChanged);
connect(dtcPpm.get(), &ParticipantManagement::Interface::Dtc::participantChanged,
this, &HandlerParticipant::onParticipantChanged);
connect(dtcPpm.get(), &ParticipantManagement::Interface::Dtc::typeChanged,
this, &HandlerParticipant::onTypeChanged);
// init:
{
auto cb = [this](const ParticipantManagement::Type & data)
{
onTypeChanged(data, DataModification::eAdded);
};
dtcPpm->types(cb);
}
{
auto cb = [this](const ParticipantManagement::Participant & data)
{
onParticipantChanged(data, DataModification::eAdded);
};
dtcPpm->participants(cb);
}
{
auto cb = [this](const ParticipantManagement::DynamicParticipantData & data)
{
onDynamicParticipantDataChanged(data, DataModification::eAdded);
};
dtcPpm->dynamicParticipantDatas(cb);
}
{
auto cb = [this](const ParticipantManagement::ParticipantPosition & data)
{
onParticipantPositionChanged(data, DataModification::eAdded);
};
dtcPpm->participantPositions(cb);
}
auto dtcTab = m_ddsHandler->dtcTab();
dtcTab->enableRestoreRadioReadiness();
connect(dtcTab.get(), &TrainingAreaBase::Interface::Dtc::restoreRadioReadinessChanged,
this, &HandlerParticipant::onRestoreRadioReadinessChanged);
INFO_LOG(m_logger) << "HandlerParticipant::init() finished. "
<< " m_positionsMap.size(): " << m_positionsMap.size();
return true;
} // end of init()
//-----------------------------------------------------------------------------
void HandlerParticipant::onParticipantPositionChanged(const ParticipantManagement::ParticipantPosition &data, DataModification modType)
{
DEBUG_LOG(m_logger) << "onParticipantPositionChanged: " << data;
if (modType == DataModification::eRemoved)
{
DEBUG_LOG(m_logger) << "m_participantsOutsideMap.remove participantId: " << data.participantId();
//m_participantsOutsideMap.remove(data.participantId());
}
else
{
// [GUEZE-3102] Aufgesessene Teilnehmer bekommen den Schaden vom Fahrzeug, auf dem sie aufgesessen sind.
if ( data.mountedOn().is_set())
{
return;
}
int floorId = m_handlerBuildingData->getFloorIdFromRoomId(data.roomId());
int lastFloorId;
CesParticipantData partPos(data);
// update LtsPosition/LtsCoordinate: (created as new master, with Z, geo and utm)
LtsCoordTrans::LtsCoordinate &ltsCoordRef = partPos.ltsCoordinate();
ltsCoordRef = LtsCoordTrans::LtsCoordinate(data.pos());
// ltsPosRef.setGeoPosition(data.pos(), 0.0); // hier wird 0.0 zu NaN umgewandelt ...
// ltsPosRef.setZValueAccordingElevation(0.0); // hier wird implizit der LtsElevationManager genutzt
// DEBUG_LOG(m_logger) << "- ltsPosRef: " << ltsPosRef;
ltsCoordRef.replaceZValueByElevationIfValue(0.0);
DEBUG_LOG(m_logger) << "- ltsCoordRef: " << ltsCoordRef;
bool lastGeoPositionValid = false;
auto it = m_positionsMap.find(partPos.participantId());
if (it != m_positionsMap.end())
{
const CesParticipantData &partPosOld = *it;
lastGeoPositionValid = partPosOld.lastPositionValid;
lastFloorId = m_handlerBuildingData->getFloorIdFromRoomId(partPosOld.roomId());
partPos.vulnerabilityState = partPosOld.vulnerabilityState;
partPos.lastGeoPosition = partPosOld.pos(); // save previous position
partPos.lastPositionValid = true;
if (floorId < 0 )
partPos.insideBuildingValue = false;
else
partPos.insideBuildingValue = true;
// replace
*it = partPos;
}
else
{
INFO_LOG(m_logger) << "m_positionsMap.insert="
<< partPos;
m_positionsMap.insert(data.participantId(), partPos);
}
//
if (lastGeoPositionValid)
{
if (floorId < 0)
{
partPos.buildingId(0);
partPos.roomId(0);
DEBUG_LOG(m_logger) << "emit and insert newOutdoorPosition:"
<< partPos;
m_positionsMap.insert(data.participantId(), partPos);
emit newOutdoorPosition(partPos);
if (lastFloorId > 0)
emit participantLeavesBuilding(partPos.participantId());
}
else
{
emit newIndoorPosition(partPos);
}
}
DEBUG_LOG(m_logger) << "checkCheating m_positionsCheatingMap.size=" << m_positionsCheatingMap.size();
QHashIterator<int, CesParticipantData> i(m_positionsCheatingMap);
while (i.hasNext())
{
i.next();
DEBUG_LOG(m_logger) << i.key() << ": " << i.value().participantId();
}
if (m_positionsCheatingMap.contains(data.participantId()))
{
DEBUG_LOG(m_logger) << "checkCheatingPosition participantId=" << data.participantId();
checkCheatingPosition(data.participantId());
}
INFO_LOG(m_logger) << "onParticipantPositionChanged()"
<< " participantId; " << data.participantId()
<< " participantTypeId: " << data.participantTypeId()
<< " partyId: " << data.partyId()
<< " vulnerabilityState: " << partPos.vulnerabilityState
<< " insideBuilding: " << partPos.insideBuilding();
INFO_LOG(m_logger) << partPos;
}
} // end of onParticipantPositionChanged()
//-----------------------------------------------------------------------------
void HandlerParticipant::onDynamicParticipantDataChanged(const ParticipantManagement::DynamicParticipantData &data, DataModification modType)
{
DEBUG_LOG(m_logger) << "onDynamicParticipantDataChanged";
if (modType == DataModification::eRemoved)
return;
CesParticipantData &participantPosition = m_positionsMap[data.participantId()]; // reference!
// save vulnerabilityState in participantHandler
ProjectDataManagement::VulnerabilityState newVulnerabilityState = ProjectDataManagement::VulnerabilityState_def::CombatReady;
if (data.stateHistory().size() > 0)
{
const ParticipantManagement::StateInformation &vul = ParticipantManagement::youngestStateInformation(data.stateHistory());
newVulnerabilityState = vul.vulnerabilityState();
DEBUG_LOG(m_logger) << "newVulnerabilityState" << vul.vulnerabilityState();
if (newVulnerabilityState == ProjectDataManagement::VulnerabilityState_def::CombatReady)
{
emit participantDecontaminated(participantPosition.participantId());
DEBUG_LOG(m_logger) << "emit participantDecontaminated id=" << participantPosition.participantId();
}
}
if (participantPosition.vulnerabilityState != newVulnerabilityState)
{
checkCheating(data.participantId(), participantPosition, newVulnerabilityState);
participantPosition.vulnerabilityState = newVulnerabilityState;
emit newParticipantState(participantPosition);
}
}
void HandlerParticipant::onParticipantChanged(const ParticipantManagement::Participant &data, DataModification modType)
{
// Remove Participant:
if (modType == DataModification::eRemoved || data.isDeleted())
{
DEBUG_LOG(m_logger) << "onParticipantChanged m_positionsMap.remove id=" << data.id();
m_participantData.remove(data.id());
m_positionsMap.remove(data.id());
return;
}
// No OC in CES
ParticipantManagement::TypeClass typeClass = typeClassFromTypeId(data.typeId());
if (typeClass == ParticipantManagement::TypeClass_def::SupportEntity
|| typeClass == ParticipantManagement::TypeClass_def::SupportUnit
|| typeClass == ParticipantManagement::TypeClass_def::Unit
|| typeClass == ParticipantManagement::TypeClass_def::Unknown)
return;
m_participantData[data.id()] = data;
CesParticipantData &pos = m_positionsMap[data.id()];
pos.partyId(data.partyId());
pos.participantId(data.id());
pos.participantTypeId(data.typeId());
DEBUG_LOG(m_logger) << "onParticipantChanged"
<< " id=" << data.id()
<< " typeId=" << data.typeId()
<< " designator=" << data.designator();
}
void HandlerParticipant::onTypeChanged(const ParticipantManagement::Type &data, DataModification modType)
{
if (modType == DataModification::eRemoved)
return;
m_typeMap.insert(data.id(), data.typeClass());
DEBUG_LOG(m_logger) << "m_typeMap.size()" << m_typeMap.size()
<< " equipmentTypeId=" << data.id()
<< " typeClass=" << data.typeClass();
}
void HandlerParticipant::onRestoreRadioReadinessChanged(const TrainingAreaBase::RestoreRadioReadiness &data, DataModification modType)
{
// Remove Participant:
if (modType == DataModification::eRemoved)
{
return;
}
auto dtcPpm = m_ddsHandler->dtcPpm();
int participantId = dtcPpm->participantIdByEquipmentNumber(data.equipmentNumber());
DEBUG_LOG(m_logger) << "onRestoreRadioReadinessChanged"
<< " data.equipmentNumber=" << data.equipmentNumber()
<< " participantId=" << participantId;
emit restoreRadioReadinessChanged(participantId);
auto partPos = m_positionsMap.value(participantId);
if ( partPos.insideBuilding())
emit newIndoorPosition(partPos);
else
{
partPos.buildingId(0);
partPos.roomId(0);
m_positionsMap.insert(participantId, partPos);
emit newOutdoorPosition(partPos);
}
}
QPolygonF HandlerParticipant::getParticipantStep(int participantId, int zone) const
{
QPolygonF result;
auto it = m_positionsMap.find(participantId);
if (it == m_positionsMap.end())
return {};
const CesParticipantData &partPos = it.value();
QPointF p1 = CentralEffectSimulation::geographic2Utm(partPos.lastGeoPosition, &zone);
QPointF p2 = CentralEffectSimulation::geographic2Utm(partPos.pos(), &zone);
//return {CentralEffectSimulation::geographic2Utm(partPos.lastGeoPosition, &zone), CentralEffectSimulation::geographic2Utm(partPos.pos(), &zone)};
result << p1 << p2 ;
return result;
}
QPointF HandlerParticipant::getParticipantPositionUtm(int participantId, int zone) const
{
QPointF result = QPointF();
if (m_positionsMap.contains(participantId))
{
const CesParticipantData &partPos = m_positionsMap.value(participantId);
result = CentralEffectSimulation::geographic2Utm(partPos.pos(), &zone);
}
return result;
}
HandlerParticipant::CesParticipantData HandlerParticipant::getParticipantPosition(int participantId) const
{
return m_positionsMap.value(participantId);
}
QHash<int, HandlerParticipant::CesParticipantData> HandlerParticipant::positionsAircraft() const
{
QHash<int, HandlerParticipant::CesParticipantData> result;
for (const HandlerParticipant::CesParticipantData &pos : m_positionsMap)
{
ParticipantManagement::TypeClass typeClass = typeClassFromTypeId(pos.participantTypeId());
if (typeClass != ParticipantManagement::TypeClass_def::Aircraft)
continue;
if (!m_participantData.contains(pos.participantId()))
continue;
result.insert(pos.participantId(), pos);
}
return result;
}
QVector<int32_t> HandlerParticipant::getParticipantsBuilding(const int32_t buildingId) const
{
QVector<int32_t> result;
DEBUG_LOG(m_logger) << "getParticipantsBuilding:" << buildingId;
for (const HandlerParticipant::CesParticipantData &pos : m_positionsMap)
{
if (buildingId == pos.buildingId())
{
DEBUG_LOG(m_logger) << "result.append " << pos.participantId();
result.append(pos.participantId());
}
}
return result;
}
bool HandlerParticipant::handleCheating(const ParticipantManagement::TypeClass typeClass,
const ProjectDataManagement::VulnerabilityState newVulnerabilityState)
{
DEBUG_LOG(m_logger) << "handleCheating typeClass=" << typeClass
<< " newVulnerabilityState=" << newVulnerabilityState;
// unknown is necessary for the initialization phase
if (typeClass == ParticipantManagement::TypeClass::Unknown)
{
DEBUG_LOG(m_logger) << "handle Cheating for Unknown";
return true;
}
if (typeClass == ParticipantManagement::TypeClass::Human)
{
DEBUG_LOG(m_logger) << "handle Cheating for Human";
if (newVulnerabilityState >= ProjectDataManagement::VulnerabilityState::MediumDamage)
return true;
}
if (typeClass == ParticipantManagement::TypeClass::GroundVehicle
|| typeClass == ParticipantManagement::TypeClass::WeaponSystem
|| typeClass == ParticipantManagement::TypeClass::VehicleWithGear)
{
DEBUG_LOG(m_logger) << "handle Cheating for Vehicle";
if (newVulnerabilityState == ProjectDataManagement::VulnerabilityState::MobilityKill
|| newVulnerabilityState == ProjectDataManagement::VulnerabilityState::VisibleMobilityKill)
return true;
}
return false;
}
// if no participantPosition has yet arrived, the participantId in participantPosition is 0
void HandlerParticipant::checkCheating(const int participantId,
const CesParticipantData &participantPosition,
const ProjectDataManagement::VulnerabilityState newVulnerabilityState)
{
DEBUG_LOG(m_logger) << "checkCheating state =" << newVulnerabilityState
<< " participantId=" << participantId;
if (!m_typeMap.contains(participantPosition.participantTypeId()))
WARNING_LOG(m_logger) << "!m_typeMap.contains(" << participantPosition.participantTypeId() << ")";
ParticipantManagement::TypeClass typeClass = m_typeMap[participantPosition.participantTypeId()];
if (handleCheating(typeClass, newVulnerabilityState))
{
if (!m_positionsCheatingMap.contains(participantId))
{
DEBUG_LOG(m_logger) << "checkCheating insert id= " << participantId;
m_positionsCheatingMap.insert(participantId, participantPosition);
}
}
else
{
if (newVulnerabilityState == ProjectDataManagement::VulnerabilityState::CombatReady)
{
DEBUG_LOG(m_logger) << "checkCheating remove id= " << participantId;
m_positionsCheatingMap.remove(participantId);
}
}
}
void HandlerParticipant::checkCheatingPosition(const int participantId)
{
DEBUG_LOG(m_logger) << "checkCheatingPosition id= " << participantId;
CesParticipantData posMobilityKill = m_positionsCheatingMap[participantId];
CesParticipantData posActual = m_positionsMap[participantId];
ParticipantManagement::TypeClass typeClass = m_typeMap[participantId];
if (!posActual.insideWlsArea())
{
DEBUG_LOG(m_logger) << "position participantId=" << participantId << " not insideWlsArea";
return;
}
// Check, if valid position is available
if (posMobilityKill.participantId() == 0)
{
DEBUG_LOG(m_logger) << "position participantId=" << participantId << " not valid";
m_positionsCheatingMap.insert(participantId, posActual);
return;
}
QPointF posUtmMobilityKill = CentralEffectSimulation::geographic2Utm(posMobilityKill.pos());
QPointF posUtmActual = CentralEffectSimulation::geographic2Utm(posActual.pos());
DEBUG_LOG(m_logger) << "posUtmMobilityKill=" << posUtmMobilityKill.rx() << "/" << posUtmMobilityKill.ry();
DEBUG_LOG(m_logger) << "posUtmActual=" << posUtmActual.rx() << "/" << posUtmActual.ry();
qreal distance = QLineF(posUtmMobilityKill, posUtmActual).length();
int cheatingDistance;
if (typeClass == ParticipantManagement::TypeClass::Human)
cheatingDistance = m_cheatingDistanceSoldier;
else
cheatingDistance = m_cheatingDistanceVehicle;
DEBUG_LOG(m_logger) << "distance=" << distance;
if (distance > cheatingDistance)
{
DEBUG_LOG(m_logger) << " Send Manipulation to id= and save new Cheating Position" << participantId;
m_positionsCheatingMap.insert(participantId, posActual);
sendBeStillWarning(participantId);
}
}
void HandlerParticipant::onSendParticipantBeStillWarningReply(const Core::FunctionReplyObject &replyObject)
{
//if (replyObject.error())
// WARNING_LOG(m_logger) << "Can not send hit on participant to training area: " << replyObject();
//else
DEBUG_LOG(m_logger) << "onSendParticipantBeStillWarningReply for id " << replyObject.id() << " success";
}
void HandlerParticipant::sendBeStillWarning(const int32_t participantId)
{
TrainingAreaBase::SendParticipantBeStillWarningRequest pba;
pba.equipmentNumber(m_ddsHandler->participantId2EquipNo(participantId));
pba.participantId(participantId);
pba.data(0);
m_ddsHandler->ftcTab()->sendParticipantBeStillWarningRequest(pba, this);
}
void HandlerParticipant::onModifyStateReply(const Core::FunctionReplyObject &reply)
{
if (reply.error())
ERROR_LOG(m_logger) << "onModifyStateReply for id " << reply.id() << " failure";
else
DEBUG_LOG(m_logger) << "onModifyStateReply for id " << reply.id() << " success";
}
void HandlerParticipant::modifyStateRequest(
const int &participantId, const ProjectDataManagement::VulnerabilityState &state, const int &kind, const int &vitality
)
{
std::vector<int32_t> participantIds;
participantIds.push_back(participantId);
ParticipantManagement::ModifyStateRequest msr;
msr.participantIds(participantIds);
msr.vulnerabilityState(state);
msr.vulnerabilityKind(kind);
msr.vitality(vitality);
m_ddsHandler->ftcPpm()->modifyStateRequest(msr, this);
}
long HandlerParticipant::getDirection(int originatorParticipantId, int targetParticipantId)
{
CesParticipantData originatorPos = m_positionsMap[originatorParticipantId];
CesParticipantData targetPos = m_positionsMap[targetParticipantId];
const Core::GeoPosition2D originatorGeoPos = originatorPos.pos();
const Core::GeoPosition2D targetGeoPos = targetPos.pos();
int zone = -1;
const QPointF originatorPosUtm = CentralEffectSimulation::geographic2Utm(originatorGeoPos, &zone);
const QPointF targetPosUtm = CentralEffectSimulation::geographic2Utm(targetGeoPos, zone);
const QLineF line(originatorPosUtm, targetPosUtm);
DEBUG_LOG(m_logger) << "originatorPosUtm=" << originatorPosUtm.x() << " / " << originatorPosUtm.y();
DEBUG_LOG(m_logger) << "targetPosUtm=" << targetPosUtm.x() << " / " << targetPosUtm.y();
DEBUG_LOG(m_logger) << "getDirection=" << (static_cast<int>(line.angle()) + 270) % 360 * 100;
return (static_cast<long>(line.angle()) + 270) % 360 * 100;
}
long HandlerParticipant::getDistance(int originatorParticipantId, int targetParticipantId)
{
CesParticipantData originatorPos = m_positionsMap[originatorParticipantId];
CesParticipantData targetPos = m_positionsMap[targetParticipantId];
const Core::GeoPosition2D originatorGeoPos = originatorPos.pos();
const Core::GeoPosition2D targetGeoPos = targetPos.pos();
int zone = -1;
const QPointF originatorPosUtm = CentralEffectSimulation::geographic2Utm(originatorGeoPos, &zone);
const QPointF targetPosUtm = CentralEffectSimulation::geographic2Utm(targetGeoPos, zone);
const QLineF line(originatorPosUtm, targetPosUtm);
DEBUG_LOG(m_logger) << "getDistance=" << line.length();
return static_cast<int>(line.length());
}
int HandlerParticipant::getParticipantId(int equipentNumber)
{
// QHash<int, ParticipantManagement::Participant> m_participantData;
QHashIterator<int, ParticipantManagement::Participant> i(m_participantData);
while (i.hasNext())
{
i.next();
if (i.value().equipmentNumber() == equipentNumber)
return i.value().id();
}
return 0;
}
int HandlerParticipant::getEquipmentNumber(int participantId) const
{
return m_ddsHandler->participantId2EquipNo(participantId);
}
void HandlerParticipant::setNotfightMode ( const int participantId, const bool notfightMode)
{
CesParticipantData participantData = m_positionsMap.value(participantId);
participantData.notfightMode = notfightMode;
INFO_LOG(m_logger) << "setNotfightMode m_positionsMap.insert="
<< participantData;
m_positionsMap.insert ( participantId,participantData );
emit newNotfightMode(participantData);
}
std::ostream &operator<<(std::ostream &stream,
const HandlerParticipant::CesParticipantData &value)
{
stream << "CesParticipantData("
<< ", lastGeoPosition = " << value.lastGeoPosition
<< ", lastPositionValid = " << value.lastPositionValid
<< ", ltsCoordinate = " << value.ltsCoordinate()
<< ", insideWlsArea = " << value.insideWlsArea()
<< ", insideBuilding = " << value.insideBuilding()
<< ", buildingId = " << value.buildingId()
<< ", notfightMode = " << value.notfightMode
<< ", partyId = " << value.partyId()
<< ", vulnerabilityState= " << value.vulnerabilityState
<< ", participantTypeId = " << value.participantTypeId()
<< ", participantId = " << value.participantId()
<< ")";
return stream;
}
} // namespace CentralEffectSimulation