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

1459 lines
58 KiB
C++
Executable File

/**
* Handler for dynamic participant data
* $Id$
* $HeadURL$
* $Author:
* Created by Iuliana Ojog, SLSE, 2016-09-21
*/
#include "handler_dynamic_participant_data.h"
#include "rep_db.h"
#include "settings.h"
#include <ngldb/nsqlquery.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <QJsonDocument>
#include <ProjectDataManagement/pdm_translation.h>
using namespace ReportManagement;
//-----------------------------------------------------------------------------
HandlerDynamicParticipantData::HandlerDynamicParticipantData(const std::shared_ptr<DdsHandler> &ddsHandler,
const std::shared_ptr<DatabaseInterface> &db)
: m_ddsHandler(ddsHandler)
, m_db(db)
, m_logger(getLogger("HandlerDynamicParticipantData"))
{
} // end of ctor()
//-----------------------------------------------------------------------------
HandlerDynamicParticipantData::~HandlerDynamicParticipantData()
{
} // end of dtor()
//-----------------------------------------------------------------------------
bool HandlerDynamicParticipantData::init()
{
DEBUG_LOG(m_logger) << "Creating and initializing PPM DTC, AES DTC, PDM DTC ...";
m_ppmDtc = ParticipantManagement::Interface::Dtc::create(m_ddsHandler->ddsConnector());
if (m_ppmDtc == nullptr)
{
ERROR_LOG(m_logger) << "Could not create PPM DTC";
return false;
}
m_ppmDtc->enableType();
m_aesDtc = AreaEffectSimulation::Interface::Dtc::create(m_ddsHandler->ddsConnector());
if (m_aesDtc == nullptr)
{
ERROR_LOG(m_logger) << "Could not create AES DTC";
return false;
}
#ifdef GUEZ_MODE
m_gimDtc = GuezIedManagement::Interface::Dtc::create(m_ddsHandler->ddsConnector());
if (m_gimDtc == nullptr)
{
ERROR_LOG(m_logger) << "Could not create GIM DTC";
return false;
}
#endif
m_pdmDtc = ProjectDataManagement::Interface::Dtc::create(m_ddsHandler->ddsConnector());
if (m_pdmDtc == nullptr)
{
ERROR_LOG(m_logger) << "Could not create PDM DTC";
return false;
}
m_pdmDtc->enableChargeType();
m_pdmDtc->waitForHistoricalDataChargeType();
// fill in AES data
// before enable - we'll get a changed signal for every entity
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::aesItemViewChanged,
this, &HandlerDynamicParticipantData::onAesItemViewChanged);
connect(m_aesDtc.get(), &AreaEffectSimulation::Interface::Dtc::effectsChanged,
this, &HandlerDynamicParticipantData::onAesEffectsChanged);
m_aesDtc->enableAesItemView();
m_aesDtc->enableAirSupportImpact();
m_aesDtc->enableExplosionCluster();
m_aesDtc->enableEffects();
m_aesDtc->waitForHistoricalDataEffects();
bool ww = m_aesDtc->waitForHistoricalDataAesItemView();
DEBUG_LOG(m_logger) << "waitForHistoricalDataAesItemView = " << ww;
// read all aesItemViewData
m_aesDtc->aesItemViews([this](const AreaEffectSimulation::AesItemView &aiv) { onAesItemViewChanged(aiv, DataModification::eAdded); });
// fill in PPM data
// before enable - we'll get a changed signal for every entity
connect(m_ppmDtc.get(), &ParticipantManagement::Interface::Dtc::participantChanged,
this, &HandlerDynamicParticipantData::onParticipantChanged);
m_ppmDtc->enableParticipant();
m_ppmDtc->waitForHistoricalDataParticipant();
m_ppmDtc->participants([this](const ParticipantManagement::Participant &pp) { onParticipantChanged(pp, DataModification::eAdded); });
connect(m_ppmDtc.get(), &ParticipantManagement::Interface::Dtc::participantPositionChanged,
this, &HandlerDynamicParticipantData::onParticipantPositionChanged);
m_ppmDtc->enableParticipantPosition();
m_ppmDtc->waitForHistoricalDataParticipantPosition();
m_ppmDtc->participantPositions([this](const ParticipantManagement::ParticipantPosition &pp) { onParticipantPositionChanged(pp, DataModification::eAdded); });
#ifdef GUEZ_MODE
// fill in GIM data, only for GUEZ!!!
// before enable - we'll get a changed signal for every entity
connect(m_gimDtc.get(), &GuezIedManagement::Interface::Dtc::iedChanged,
this, &HandlerDynamicParticipantData::onIedChanged);
m_gimDtc->enableIed();
bool gg = m_gimDtc->waitForHistoricalDataIed();
DEBUG_LOG(m_logger) << "waitForHistoricalDataIed = " << gg;
// read all aesItemViewData
m_gimDtc->ieds([this](const GuezIedManagement::Ied &ied) { onIedChanged(ied, DataModification::eAdded); });
#endif
m_bldDtc = Buildings::Interface::Dtc::create(m_ddsHandler->ddsConnector());
if (!m_bldDtc)
{
ERROR_LOG(m_logger) << "Could not create DTC Buildings";
return false;
}
connect(m_bldDtc.get(), &Buildings::Interface::Dtc::buildingStateChanged,
this, &HandlerDynamicParticipantData::onBuildingStateChanged);
m_bldDtc->enableBuildingState();
// Subscribe for DynamicParticipantData (for analyzing data)
// before enable - we'll get a changed signal for every entity
connect(m_ppmDtc.get(), &ParticipantManagement::Interface::Dtc::dynamicParticipantDataChanged,
this, &HandlerDynamicParticipantData::onDynamicParticipantDataChanged);
if (!m_ppmDtc->enableDynamicParticipantData())
{
ERROR_LOG(m_logger) << "init() PPM failed";
return false;
}
#ifndef GUEZ_MODE
//AHTC - capture fires without hit too. Here the participantId is the originatorId
connect(m_ppmDtc.get(), &ParticipantManagement::Interface::Dtc::participantGearEventChanged,
this, &HandlerDynamicParticipantData::onParticipantGearEventChanged);
if (!m_ppmDtc->enableParticipantGearEvent())
{
ERROR_LOG(m_logger) << "init() PPM failed";
return false;
}
#endif
DEBUG_LOG(m_logger) << "... done";
return true;
} // end of init()
//-----------------------------------------------------------------------------
void HandlerDynamicParticipantData::onParticipantChanged(const ParticipantManagement::Participant &data, DataModification modType)
{
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
m_partMap[data.id()] = data;
DEBUG_LOG(m_logger) << "added/modified - data.participantId: " << data.id()
<< ", data.partyId: " << data.partyId()
<< ", data.equipmentNumber: " << data.equipmentNumber();
break;
case DataModification::eRemoved:
m_partMap.remove(data.id());
break;
}
}
//-----------------------------------------------------------------------------
void HandlerDynamicParticipantData::onParticipantPositionChanged(const ParticipantManagement::ParticipantPosition &data, DataModification modType)
{
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
{
m_partPositionMap[data.participantId()] = data;
DEBUG_LOG(m_logger) << "added/modified Participant Position - data.participantId: " << data.participantId()
<< ", data.pos: " << data.pos();
//TransportInitiated (mounted on vehicle)
if (data.mountedOn().is_set())
{
DEBUG_LOG(m_logger) << "Mounted on : " << data.mountedOn().get();
if (m_isMounted.contains(data.participantId()))
break;
m_isMounted.append(data.participantId());
DEBUG_LOG(m_logger) << "Added mounted participant id " << data.participantId();
qint64 timeMounted = getLastSignificantPositionMountedChanged(data.participantId(), data.sampleTime(), data.pos());
if (timeMounted <= 0)
timeMounted = data.sampleTime();
// Report Treatment Timeline
Database::RepTreatmentTimelineData ttData;
ttData.participantId = data.participantId();
ttData.participantTypeId = data.participantTypeId();
ttData.partyId = data.partyId();
ttData.vitality = lastVitality(data.participantId(), data.sampleTime());
ttData.vulnerability = lastVulnerabilityKind(data.participantId(), data.sampleTime());
ttData.vulnerabilityState = m_vulnStateMap[data.participantId()].underlying();
ttData.eventTime = timeMounted;
ttData.eventTypeId = ReportManagement::EventType::TransportInitiated;
ttData.id = 0; // force insert
if (!m_db->insert(ttData))
WARNING_LOG(m_logger) << "Error while inserting Event TransportInitiated for participantId: " << ttData.participantId;
}
else
{
if (m_isMounted.contains(data.participantId()))
{
DEBUG_LOG(m_logger) << "Removed mounted participant id " << data.participantId();
m_isMounted.remove(m_isMounted.indexOf(data.participantId()));
}
}
break;
}
case DataModification::eRemoved:
{
DEBUG_LOG(m_logger) << "Removed participant id " << data.participantId();
if (m_isMounted.contains(data.participantId()))
m_isMounted.remove(m_isMounted.indexOf(data.participantId()));
m_partPositionMap.remove(data.participantId());
break;
}
}
}
//-----------------------------------------------------------------------------
void HandlerDynamicParticipantData::onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType)
{
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
DEBUG_LOG(m_logger) << "added/modified data.aesItemId(): " << data.aesItemId();
m_aesItemViewMap[data.aesItemId()] = data;
break;
case DataModification::eRemoved:
// ExplosionCluster will be removed from dds too soon (Data still needed),
// therefore do not delete from map (15.10.2024)
//m_aesItemViewMap.remove(data.aesItemId());
break;
}
}
#ifdef GUEZ_MODE
//-----------------------------------------------------------------------------
void HandlerDynamicParticipantData::onIedChanged(const GuezIedManagement::Ied &data, DataModification modType)
{
switch (modType)
{
case DataModification::eAdded:
case DataModification::eModified:
DEBUG_LOG(m_logger) << "added/modified data.id(): " << data.id();
m_iedMap[data.id()] = data;
break;
case DataModification::eRemoved:
m_iedMap.remove(data.id());
break;
}
}
#endif
//-----------------------------------------------------------------------------
void HandlerDynamicParticipantData::onDynamicParticipantDataChanged(const ParticipantManagement::DynamicParticipantData &data, DataModification modType)
{
if (modType == DataModification::eRemoved)
return;
DEBUG_LOG(m_logger) << "onDynamicParticipantDataChanged(): "
<< " participantId: " << data.participantId()
<< ", size stateHistory: " << data.stateHistory().size()
<< ", size sanMatStock: " << data.sanitationMaterialStock().size();
auto itLastDynData = m_lastDynData.find(data.participantId());
// the first insert does not trigger any updates, as in EEM
if (itLastDynData == m_lastDynData.end())
{
itLastDynData = m_lastDynData.insert(data.participantId(), data);
//return;
}
ParticipantManagement::DynamicParticipantData &lastDynData = itLastDynData.value();
// get corresponding participant data
auto itParticipant = m_partMap.constFind(data.participantId());
if (itParticipant == m_partMap.constEnd())
{
// we have to wait for historical participant data
m_ppmDtc->waitForHistoricalDataParticipant(2000);
itParticipant = m_partMap.constFind(data.participantId());
if (itParticipant == m_partMap.constEnd())
{
WARNING_LOG(m_logger) << "Participant does not exist: participantId: " << data.participantId();
return;
}
}
const ParticipantManagement::Participant &pData = itParticipant.value();
// Report Unit Power
Database::RepUnitPowerData upData;
if (pData.equipmentNumber().is_set())
upData.equipmentNumber = pData.equipmentNumber().get();
else
upData.equipmentNumber = -1;
upData.eventTime = data.sampleTime();
upData.participantId = data.participantId();
upData.partyId = pData.partyId();
upData.participantTypeId = pData.typeId();
// Report Vehicle Repair & Decontamination & Sanitation
Database::RepMaintenanceData vrData;
vrData.partyId = pData.partyId();
vrData.participantTypeId = pData.typeId();
vrData.participantId = data.participantId();
vrData.timeEvent = data.sampleTime();
// Report Mine Area
Database::RepMineAreaData mbData;
mbData.eventTime = data.sampleTime();
mbData.participantId = data.participantId();
mbData.participantTypeId = pData.typeId();
mbData.partyId = pData.partyId();
// Report NBC
Database::RepNbcData nbcData;
nbcData.eventTime = data.sampleTime();
nbcData.participantId = data.participantId();
nbcData.participantTypeId = pData.typeId();
nbcData.partyId = pData.partyId();
// Report Firings
Database::RepFiringsData fData;
fData.eventTime = data.sampleTime();
fData.participantId = data.participantId();
fData.participantTypeId = pData.typeId();
fData.partyId = pData.partyId();
// Report AirSupport
Database::RepAirSupportData airSupData;
airSupData.eventTime = data.sampleTime();
airSupData.participantId = data.participantId();
airSupData.participantTypeId = pData.typeId();
airSupData.partyId = pData.partyId();
// Report Treatment + Priority + Chain
Database::RepTreatmentData tData;
tData.participantId = data.participantId();
tData.participantTypeId = pData.typeId();
tData.partyId = pData.partyId();
tData.qualification = data.qualification().underlying();
// Report Treatment Timeline
Database::RepTreatmentTimelineData ttData;
ttData.participantId = data.participantId();
ttData.participantTypeId = pData.typeId();
ttData.partyId = pData.partyId();
if (data.stateHistory().size() > 0 && data.stateHistory() != lastDynData.stateHistory())
{
INFO_LOG(m_logger) << "PROCESSING: stateHistory.size() = " << data.stateHistory().size() << " for participant id = " << data.participantId();
const ParticipantManagement::StateInformation &stateInfo = data.stateHistory().at(data.stateHistory().size()-1);
//const ParticipantManagement::StateInformation &stateInfo = m_ppmDtc->youngestStateInformation(data.stateHistory());
const ProjectDataManagement::VulnerabilityState &vulnState = stateInfo.vulnerabilityState();
DEBUG_LOG(m_logger) << "vulnerabilityState: " << vulnState;
if (stateInfo.originatorChargeTypeId() > 0)
DEBUG_LOG(m_logger) << "originatorChargeTypeId: " << stateInfo.originatorChargeTypeId();
DEBUG_LOG(m_logger) << "originatorType: " << stateInfo.originatorType();
DEBUG_LOG(m_logger) << "vulnerabilityBits: " << stateInfo.vulnerabilityBits();
//counting NearMiss and HitWithNoEffect as CombatReady, after discussion with Ulli 08.2021
bool isCombatReady = (vulnState == ProjectDataManagement::VulnerabilityState::CombatReady ||
vulnState == ProjectDataManagement::VulnerabilityState::NearMiss ||
vulnState == ProjectDataManagement::VulnerabilityState::HitWithNoEffect);
// Report Unit Power
upData.ready = isCombatReady;
upData.vulnerabilityState = vulnState.underlying();
// Report Treatment (add vulnerabiltyState without treatment )
tData.vulnerabilityState = vulnState.underlying();
tData.timeVulnerability = stateInfo.stateTime();
tData.timeTreatment = 0;
if (stateInfo.originatorType() != ProjectDataManagement::StateChangeOriginator_def::Sanitation
&& vulnState > ProjectDataManagement::VulnerabilityState_def::CombatReady
&& vulnState <= ProjectDataManagement::VulnerabilityState_def::CatastrophicKill )
{
// Save Treatment Data
if (!m_db->insert(tData))
ERROR_LOG(m_logger) << "Error while inserting treatment data - participantId: " << tData.participantId;
}
// Report Firings
fData.vulnerabilityState = vulnState.underlying();
fData.chargeTypeId = stateInfo.originatorChargeTypeId(); // here we keep the original chargeId
// Report AirSupport
airSupData.vulnerabilityState = vulnState.underlying();
airSupData.chargeTypeId = stateInfo.originatorChargeTypeId();
// get the corresponding originator participant, it should be already in the map
const ParticipantManagement::Participant originatorParticipantData = m_partMap.value(stateInfo.originatorId());
#ifndef GUEZ_MODE
// AHTC: we save the originator participant instead of hit participant
fData.participantId = stateInfo.originatorId();
fData.participantTypeId = originatorParticipantData.typeId();
fData.partyId = originatorParticipantData.partyId();
#endif
// Save UnitPower Data
if (!m_db->insert(upData))
ERROR_LOG(m_logger) << "Error while inserting unit power data - participantId: " << upData.participantId;
// Report Mine Area / Report Firings / Report AirSupport
if (vulnState != ProjectDataManagement::VulnerabilityState::CombatReady)
{
mbData.hit = 1;
fData.hit = 1;
airSupData.hit = 1;
}
else
{
mbData.hit = 0;
fData.hit = 0;
airSupData.hit = 0;
}
// Report Firings: direct fires
if (stateInfo.originatorType() == ProjectDataManagement::StateChangeOriginator::Participant && stateInfo.originatorChargeTypeId() != 0)
{
if (originatorParticipantData.partyId() == pData.partyId() && vulnState != ProjectDataManagement::VulnerabilityState::CombatReady)
{
fData.hit = 0;
fData.hitFriendlyFire = 1;
}
// Save direct firings data
if (!m_db->insert(fData))
ERROR_LOG(m_logger) << "Error while inserting direct firings data into db for event_time = " << fData.eventTime;
//save TreatmentTimeline events too
{
ttData.vulnerabilityState = stateInfo.vulnerabilityState().underlying();
ttData.vulnerability = stateInfo.vulnerabilityKindId();
ttData.vitality = stateInfo.vitality();
// VBGChanged
qint32 lastVuln = lastVulnerabilityKind(ttData.participantId, stateInfo.stateTime());
if (lastVuln >= 0 && lastVuln != ttData.vulnerability)
{
ttData.eventTime = stateInfo.stateTime();
ttData.eventTypeId = ReportManagement::EventType::VBGChanged;
ttData.id = 0; // force insert
if (!m_db->insert(ttData))
ERROR_LOG(m_logger) << "Error while inserting Event VBGChanged for participantId: " << ttData.participantId;
}
// VitalityChanged
qint32 lastVit = lastVitality(ttData.participantId, stateInfo.stateTime());
if (lastVit >= 0 && lastVit <= 100 && lastVit != ttData.vitality)
{
ttData.eventTime = stateInfo.stateTime();
ttData.eventTypeId = ReportManagement::EventType::VitalityChanged;
ttData.id = 0; // force insert
if (!m_db->insert(ttData))
ERROR_LOG(m_logger) << "Error while inserting Event VitalityChanged for participantId: " << ttData.participantId;
}
}
}
// Report Firings / AirSupport: indirect fires
if (stateInfo.originatorType() == ProjectDataManagement::StateChangeOriginator::AreaEffectSimulation && stateInfo.originatorChargeTypeId() != 0)
{
const AreaEffectSimulation::AesItemView aesItemView = getAesItemView(stateInfo.originatorId());
DEBUG_LOG(m_logger) << "Found indirect fire from AES id = " << stateInfo.originatorId() << ", charge type = " << stateInfo.originatorChargeTypeId();
if (aesItemView.id() > 0)
{
if (aesItemView.partyId().is_set())
airSupData.aesPartyId = aesItemView.partyId().get();
if (aesItemView.partyId().is_set() && aesItemView.partyId().get() == pData.partyId() && vulnState != ProjectDataManagement::VulnerabilityState::CombatReady)
{
fData.hit = 0;
fData.hitFriendlyFire = 1;
airSupData.hit = 0;
airSupData.hitFriendlyFire = 1;
}
}
// Save indirect firings data
if (!m_db->insert(fData))
ERROR_LOG(m_logger) << "Error while inserting indirect firings data into db for event_time = " << fData.eventTime;
// Save indirect firings - Report AirSupport data
if (!m_db->insert(airSupData))
ERROR_LOG(m_logger) << "Error while inserting indirect firings (for airSupport report) into db for event_time = " << airSupData.eventTime;
//save TreatmentTimeline events too
{
ttData.vulnerabilityState = stateInfo.vulnerabilityState().underlying();
ttData.vulnerability = stateInfo.vulnerabilityKindId();
ttData.vitality = stateInfo.vitality();
// VBGChanged
qint32 lastVuln = lastVulnerabilityKind(ttData.participantId, stateInfo.stateTime());
if (lastVuln >= 0 && lastVuln != ttData.vulnerability)
{
ttData.eventTime = stateInfo.stateTime();
ttData.eventTypeId = ReportManagement::EventType::VBGChanged;
ttData.id = 0; // force insert
if (!m_db->insert(ttData))
ERROR_LOG(m_logger) << "Error while inserting Event VBGChanged for participantId: " << ttData.participantId;
}
// VitalityChanged
qint32 lastVit = lastVitality(ttData.participantId, stateInfo.stateTime());
if (lastVit >= 0 && lastVit <= 100 && lastVit != ttData.vitality)
{
ttData.eventTime = stateInfo.stateTime();
ttData.eventTypeId = ReportManagement::EventType::VitalityChanged;
ttData.id = 0; // force insert
if (!m_db->insert(ttData))
ERROR_LOG(m_logger) << "Error while inserting Event VitalityChanged for participantId: " << ttData.participantId;
}
}
}
#ifdef GUEZ_MODE
// Report explosive device
if (stateInfo.originatorType() == ProjectDataManagement::StateChangeOriginator::ImprovisedExplosiveDevice && stateInfo.originatorChargeTypeId() != 0)
{
const GuezIedManagement::Ied &gIed = m_gimDtc->iedForEquipmentNumber(stateInfo.originatorId());
if (gIed.id() > 0 && gIed.partyId() == pData.partyId() && vulnState != ProjectDataManagement::VulnerabilityState::CombatReady)
{
fData.hit = 0;
fData.hitFriendlyFire = 1;
}
// Save explosive device data
if (!m_db->insert(fData))
ERROR_LOG(m_logger) << "Error while inserting explosive device data into db for event_time = " << fData.eventTime;
}
#endif
// Report NBC
if (vulnState != ProjectDataManagement::VulnerabilityState::CombatReady)
{
if (data.hasNbcProtectionActive())
{
nbcData.hit = 0;
nbcData.protection = 1;
}
else
nbcData.hit = 1;
}
else
nbcData.hit = 0;
DEBUG_LOG(m_logger) << "nbcData.hit: " << nbcData.hit;
// Check, if effectSimulation is mine area or NBC or Functional Area
if (stateInfo.originatorType() == ProjectDataManagement::StateChangeOriginator::AreaEffectSimulation ||
stateInfo.originatorType() == ProjectDataManagement::StateChangeOriginator::FunctionalArea)
{
INFO_LOG(m_logger) << "Originator = AreaEffectSimulation or FunctionalArea";
mbData.mineAreaId = stateInfo.originatorId();
nbcData.nbcId = stateInfo.originatorId();
DEBUG_LOG(m_logger) << "aesItemViewMap.size(): " << m_aesItemViewMap.size();
const AreaEffectSimulation::AesItemView aesItemView = getAesItemView(nbcData.nbcId);
DEBUG_LOG(m_logger) << "aesItemView.id() = " << aesItemView.id();
if (aesItemView.id() > 0)
{
AreaEffectSimulation::AesType aesType = aesItemView.aesTypeId();
DEBUG_LOG(m_logger) << "AesType: " << aesType;
if (aesItemView.partyId().is_set())
mbData.mineAreaPartyId = aesItemView.partyId().get();
if (mbData.mineAreaPartyId == mbData.partyId)
mbData.hitFriendlyFire = 1;
// Save only, if vulnerabilityState changed
if (checkVulnerabilityStateChange(vulnState, data.participantId())) // TODO: can this check moved out of if (data.stateHistory().at(data.stateHistory().size()-1).originEffectSimulationId().is_set()) ?
{
if (aesType == AreaEffectSimulation::AesType::AtMineArea ||
aesType == AreaEffectSimulation::AesType::AtMineAreaSingleMines)
{
if (mbData.mineAreaId == 0) // get the id from AES Item View ?
mbData.mineAreaId = aesItemView.aesItemId();
if (mbData.mineAreaId > 0)
{
DEBUG_LOG(m_logger) << "Inserting Mine Area Data";
if (!m_db->insert(mbData))
ERROR_LOG(m_logger) << "Error while inserting mine area data participantId: " << mbData.participantId;
}
}
if (aesType == AreaEffectSimulation::AesType::AtBCContamination ||
aesType == AreaEffectSimulation::AesType::AtNContamination)
{
if (nbcData.nbcId == 0) // get the id from AES Item View ?
nbcData.nbcId = aesItemView.aesItemId();
nbcData.aesType = aesType.underlying();
nbcData.chargeTypeId = aesItemView.chargeStruct().chargeTypeId();
if (nbcData.nbcId > 0 && nbcData.chargeTypeId > 0)
{
DEBUG_LOG(m_logger) << "Inserting NBC Data";
if (!m_db->insert(nbcData))
ERROR_LOG(m_logger) << "Error while inserting nbc data participant: " << nbcData.participantId;
}
}
// enter functional area as trigger event for vehicle repair / decontamination reports and treatment timeline
if (aesType == AreaEffectSimulation::AesType::AtFunctionalArea)
{
//const ParticipantManagement::StateInformation &lastState = m_ppmDtc->youngestStateInformation(data.stateHistory());
vrData.timeVulnerability = stateInfo.stateTime();
vrData.timePositionChanged = getLastSignificantParticipantPositionChanged(vrData.participantId, vrData.timeEvent, getLastPosition(vrData.participantId));
if (!m_db->insert(vrData))
ERROR_LOG(m_logger) << "Error while inserting maintenance data for participantId: " << vrData.participantId;
// treatment timeline event EnterFunctionalArea
ttData.vulnerabilityState = stateInfo.vulnerabilityState().underlying();
ttData.vulnerability = stateInfo.vulnerabilityKindId();
ttData.vitality = stateInfo.vitality();
ttData.eventTime = stateInfo.stateTime();
ttData.eventTypeId = ReportManagement::EventType::EnterFunctionalArea;
QString areaName;
if (m_aesDtc)
{
AreaEffectSimulation::AesItem aesItem;
m_aesDtc->aesItemFromId(stateInfo.originatorId(), aesItem);
if (aesItem.id() > 0)
areaName = QString::fromStdString(aesItem.name());
}
QJsonObject obj = areaToJson(stateInfo.originatorId(), areaName);
ttData.properties = QString::fromStdString(QJsonDocument(obj).toJson(QJsonDocument::Compact).toStdString());
ttData.id = 0; // force insert
if (!m_db->insert(ttData))
ERROR_LOG(m_logger) << "Error while inserting Event EnterFunctionalArea for participantId: " << ttData.participantId;
}
}
}
}
// Treatment reports
if (stateInfo.originatorType() == ProjectDataManagement::StateChangeOriginator::Sanitation)
{
DEBUG_LOG(m_logger) << "Sanitation";
// Sanitation info only for Human type class
ParticipantManagement::TypeClass typeClass = m_ppmDtc->type(pData.typeId()).typeClass();
if (typeClass == ParticipantManagement::TypeClass::Human)
{
//const ParticipantManagement::StateInformation &lastState = m_ppmDtc->youngestStateInformation(data.stateHistory());
tData.vulnerabilityState = stateInfo.vulnerabilityState().underlying();
tData.vulnerability = stateInfo.vulnerabilityKindId();
tData.vitality = stateInfo.vitality();
// recalculating now as in Generator
tData.timeVulnerability = sinceWhenVulnerability(tData.participantId, tData.vulnerability, stateInfo.stateTime());
tData.timeVitality = sinceWhenVitality(tData.participantId,tData.vitality,stateInfo.stateTime());
switch(stateInfo.vulnerabilityState().underlying())
{
case ProjectDataManagement::VulnerabilityState::LightDamage:
tData.priority = 3;
break;
case ProjectDataManagement::VulnerabilityState::MediumDamage:
tData.priority = 2;
break;
case ProjectDataManagement::VulnerabilityState::HeavyDamage:
tData.priority = 1;
break;
default:
tData.priority = 0;
break;
}
tData.timeTreatment = data.sampleTime();
tData.sanitationResult = stateInfo.sanitationResult().underlying();
tData.sanitationEvaluation = stateInfo.sanitationEvaluation().underlying();
tData.sanitationProceduresTaken = stateInfo.sanitationProceduresTaken();
tData.timePositionChanged = getLastSignificantParticipantPositionChanged(tData.participantId, tData.timeTreatment, getLastPosition(tData.participantId));
//these 2 will be calculated in Generator
//tData.timeNineLiner = -1;
//tData.timeEnterArea = -1;
Core::GeoPosition geoPos = getLastPosition(tData.participantId);
QPointF position(geoPos.lon(), geoPos.lat());
tData.position = position;
LtsCoordTrans::UtmCoordinate coord(LtsCoordTrans::UtmCoordinate::fromGeographic(geoPos.lon(),
geoPos.lat()));
tData.positionXM = coord.x;
tData.positionYM = coord.y;
bool toAdd = true;
if (stateInfo.sanitationProceduresTaken() == 0 && stateInfo.originatorChargeTypeId() == 0) //qualification
toAdd = false;
if (toAdd && !m_db->insert(tData))
ERROR_LOG(m_logger) << "Error while inserting treatment data for participantId: " << tData.participantId;
// now treatment timeline events
{
ttData.vulnerabilityState = stateInfo.vulnerabilityState().underlying();
ttData.vulnerability = stateInfo.vulnerabilityKindId();
ttData.vitality = stateInfo.vitality();
// VBGChanged
qint32 lastVuln = lastVulnerabilityKind(ttData.participantId, stateInfo.stateTime());
if (lastVuln >= 0 && lastVuln != ttData.vulnerability)
{
ttData.eventTime = stateInfo.stateTime();
ttData.eventTypeId = ReportManagement::EventType::VBGChanged;
ttData.id = 0; // force insert
if (!m_db->insert(ttData))
ERROR_LOG(m_logger) << "Error while inserting Event VBGChanged for participantId: " << ttData.participantId;
}
// VitalityChanged
qint32 lastVit = lastVitality(ttData.participantId, stateInfo.stateTime());
if (lastVit >= 0 && lastVit <= 100 && lastVit != ttData.vitality)
{
ttData.eventTime = stateInfo.stateTime();
ttData.eventTypeId = ReportManagement::EventType::VitalityChanged;
ttData.id = 0; // force insert
if (!m_db->insert(ttData))
ERROR_LOG(m_logger) << "Error while inserting Event VitalityChanged for participantId: " << ttData.participantId;
}
// Treatment
ttData.eventTime = data.sampleTime();
ttData.eventTypeId = ReportManagement::EventType::Treatment;
// save san procs in properties as json
QJsonObject obj = sanToJson(stateInfo.sanitationProceduresTaken());
ttData.properties = QString::fromStdString(QJsonDocument(obj).toJson(QJsonDocument::Compact).toStdString());
ttData.id = 0; // force insert
if (!m_db->insert(ttData))
ERROR_LOG(m_logger) << "Error while inserting Event Treatment for participantId: " << ttData.participantId;
/*
//TransportInitiated (mounted on vehicle)
qint64 timeMounted = getLastSignificantPositionMountedChanged(tData.participantId, tData.timeTreatment, getLastPosition(tData.participantId));
if (timeMounted > 0)
{
ttData.eventTime = timeMounted;
ttData.eventTypeId = ReportManagement::EventType::TransportInitiated;
ttData.id = 0; // force insert
if (!m_db->insert(ttData))
ERROR_LOG(m_logger) << "Error while inserting Event TransportInitiated for participantId: " << ttData.participantId;
}
*/
}
}
}
// treatment timeline events NineLinerSet and TransportRequested
if (stateInfo.originatorType() == ProjectDataManagement::StateChangeOriginator::ObserverController)
{
ttData.vulnerabilityState = stateInfo.vulnerabilityState().underlying();
ttData.vulnerability = stateInfo.vulnerabilityKindId();
ttData.vitality = stateInfo.vitality();
if (stateInfo.originatorChargeTypeId() == 1) // 9Liner created
{
// NineLinerSet
ttData.eventTime = stateInfo.stateTime();
ttData.eventTypeId = ReportManagement::EventType::NineLinerSet;
ttData.id = 0; //force insert
if (!m_db->insert(ttData))
ERROR_LOG(m_logger) << "Error while inserting Event NineLinerSet for participantId: " << ttData.participantId;
}
else if (stateInfo.originatorChargeTypeId() == 2) // Transport Requested
{
// TransportInitiated
ttData.eventTime = stateInfo.stateTime();
ttData.eventTypeId = ReportManagement::EventType::TransportRequested;
ttData.id = 0; //force insert
if (!m_db->insert(ttData))
ERROR_LOG(m_logger) << "Error while inserting Event TransportRequested for participantId: " << ttData.participantId;
}
}
// DemandVulnerabilityStateChange TAB -> StateChange -> SetInjury
if (stateInfo.originatorType() == ProjectDataManagement::StateChangeOriginator::ExerciseControl)
{
ttData.vulnerabilityState = stateInfo.vulnerabilityState().underlying();
ttData.vulnerability = stateInfo.vulnerabilityKindId();
ttData.vitality = stateInfo.vitality();
ttData.eventTime = stateInfo.stateTime();
if (ttData.vitality == 100 && ttData.vulnerabilityState == 0) // CombatReady = Reactivation = VitalityReset
ttData.eventTypeId = ReportManagement::EventType::VitalityReset;
else
ttData.eventTypeId = ReportManagement::EventType::SetInjury;
ttData.id = 0; // force insert
if (!m_db->insert(ttData))
ERROR_LOG(m_logger) << "Error while inserting Event SetInjury for participantId: " << ttData.participantId;
}
// Vitality and Vulnerability reset manually
if (stateInfo.originatorType() == ProjectDataManagement::StateChangeOriginator::Initialization)
// && stateInfo.vulnerabilityState() == ProjectDataManagement::VulnerabilityState::CombatReady)
{
ttData.vulnerabilityState = stateInfo.vulnerabilityState().underlying();
ttData.vulnerability = stateInfo.vulnerabilityKindId();
ttData.vitality = stateInfo.vitality();
ttData.eventTime = stateInfo.stateTime();
ttData.eventTypeId = ReportManagement::EventType::VitalityReset;
ttData.id = 0; // force insert
if (!m_db->insert(ttData))
ERROR_LOG(m_logger) << "Error while inserting Event VitalityReset for participantId: " << ttData.participantId;
}
#ifdef GUEZ_MODE
// StateChange -> VBGSet
if (stateInfo.originatorType() == ProjectDataManagement::StateChangeOriginator::MedicalTimeout)
{
ttData.vulnerabilityState = stateInfo.vulnerabilityState().underlying();
ttData.vulnerability = stateInfo.vulnerabilityKindId();
ttData.vitality = stateInfo.vitality();
ttData.eventTime = stateInfo.stateTime();
ttData.eventTypeId = ReportManagement::EventType::VBGSet;
ttData.id = 0; // force insert
if (!m_db->insert(ttData))
ERROR_LOG(m_logger) << "Error while inserting Event VBGSet for participantId: " << ttData.participantId;
}
#endif
// Saving the new vulnerability state only at the end
m_vulnStateMap[mbData.participantId] = vulnState;
}
else
DEBUG_LOG(m_logger) << "No new state history for participant id = " << data.participantId();
// Report Charge Resupply
Database::RepChargeResupplyData crData;
crData.participantId = data.participantId();
crData.participantTypeId = pData.typeId();
crData.partyId = pData.partyId();
crData.eventTime = data.sampleTime();
QMap<QPair<int, int>, int> gearMap = m_chargeGearInfo.value(crData.participantId);
QMap<int, Database::RepChargeResupplyData> turmWanneMap;
for (auto it = data.gear().begin(); it != data.gear().end(); ++it)
{
ParticipantManagement::GearInformation gi = *it;
if (gi.chargeTypeId() <= 0) continue; // skip garbage
if (gi.gearId() == 0) continue; // ignore Feuerereignis hier
// Turm/ Wanne Data
// 1 = Wanne, 2 = Turm, see TAB::send_to_dds.cpp
if (gi.gearId() > 0 && gi.gearId() < 3)
{
auto turmWanneCrData = crData;
turmWanneCrData.gearId = -1; // hard-coded -1
turmWanneCrData.gearTypeId = gi.gearTypeId(); // always 0 ?
turmWanneCrData.chargeTypeId = m_pdmDtc->getAvailableChargeTypeId(gi.chargeTypeId()); // here we change the original chargeId to a valid DB value (Uleis)
turmWanneCrData.chargeRemain = turmWanneMap[turmWanneCrData.chargeTypeId].chargeRemain + gi.remain();
turmWanneMap[turmWanneCrData.chargeTypeId] = turmWanneCrData;
continue;
}
crData.gearId = gi.gearId(); // SerialNo of gear
crData.gearTypeId = gi.gearTypeId();
crData.chargeTypeId = m_pdmDtc->getAvailableChargeTypeId(gi.chargeTypeId()); // here we change the original chargeId to a valid DB value (Uleis)
crData.chargeRemain = gi.remain();
if (crData.chargeTypeId != gi.chargeTypeId())
WARNING_LOG(m_logger) << "OLD charge id " << gi.chargeTypeId() << " changed in NEW id " << crData.chargeTypeId;
QPair<int, int> pair;
pair.first = gi.gearTypeId();
pair.second = crData.chargeTypeId;
if (gearMap.contains(pair))
{
crData.chargeFired = gearMap.value(pair) - gi.remain();
if (crData.chargeFired < 0)
crData.chargeFired = 0; // resupplied;
}
gearMap.insert(pair, gi.remain());
DEBUG_LOG(m_logger) << "gearTypeId: " << crData.gearTypeId << ", chargeTypeId: " << crData.chargeTypeId;
crData.id = 0; // to force insert without id
if (!m_db->insert(crData))
ERROR_LOG(m_logger) << "Error while inserting charge resupply data for participant: " << data.participantId();
}
// Has Turm/Wanne Map been filled?
for (Database::RepChargeResupplyData turmWanneCrData : qAsConst(turmWanneMap))
{
QPair<int, int> pair;
pair.first = turmWanneCrData.gearTypeId;
pair.second = turmWanneCrData.chargeTypeId;
if (gearMap.contains(pair))
{
turmWanneCrData.chargeFired = gearMap.value(pair) - turmWanneCrData.chargeRemain;
if (turmWanneCrData.chargeFired < 0)
turmWanneCrData.chargeFired = 0; // resupplied;
}
gearMap.insert(pair, turmWanneCrData.chargeRemain);
INFO_LOG(m_logger) << "Inserting TurmWanne data gearTypeId: " << turmWanneCrData.gearTypeId
<< ", chargeTypeId: " << turmWanneCrData.chargeTypeId
<< ", remain: " << turmWanneCrData.chargeRemain
<< ", fired: " << turmWanneCrData.chargeFired ;
turmWanneCrData.id = 0; // to force insert without id
if (!m_db->insert(turmWanneCrData))
ERROR_LOG(m_logger) << "Error while inserting (turm/wanne) charge resupply data for participant: " << data.participantId();
}
m_chargeGearInfo.insert(crData.participantId, gearMap);
// Check, if gear has disappeared
for (auto it = gearMap.begin(); it != gearMap.end(); ++it)
{
QPair<int, int> pair = it.key();
DEBUG_LOG(m_logger) << "gearTypeId: " << pair.first << ", chargeTypeId: " << pair.second;
if (!containsGearTypeId(data.gear(), pair.first, pair.second))
{
crData.chargeTypeId = -2;
crData.chargeRemain = -1;
crData.id = 0; // to force insert without id
if (!m_db->insert(crData))
ERROR_LOG(m_logger) << "Error while inserting charge resupply data for participant: " << data.participantId();
}
}
// Report Sanitation Material
if (data.sanitationMaterialStock().size() > 0)
{
INFO_LOG(m_logger) << "sanitationMaterialStock.size() = " << data.sanitationMaterialStock().size() << " for participant id = " << data.participantId();
Database::RepSanitationMaterialData sanData;
sanData.participantId = data.participantId();
sanData.partyId = pData.partyId();
sanData.participantTypeId = pData.typeId();
sanData.eventTime = data.sampleTime();
sanData.sanitationUniqueId = data.sanitationUniqueId();
sanData.qualification = data.qualification().underlying();
DEBUG_LOG(m_logger) << "Qualification = " << sanData.qualification;
for ( ParticipantManagement::SanitationMaterial sanMat : qAsConst(data.sanitationMaterialStock()))
{
sanData.materialId = sanMat.materialId();
sanData.materialAmount = sanMat.materialCount();
sanData.id = 0; // to force insert
DEBUG_LOG(m_logger) << "Inserting SanMat data for participant id = " << data.participantId() << " , materialId = " << sanData.materialId << ", stock = " << sanData.materialAmount;
if (!m_db->insert(sanData))
ERROR_LOG(m_logger) << "Error while inserting sanitation material data for participant: " << data.participantId();
}
}
lastDynData = data;
} // end of onDynamicParticipantDataChanged()
//------------------------------------------------------------------------------------------------------------------
void HandlerDynamicParticipantData::onBuildingStateChanged(const Buildings::BuildingState &data, DataModification modType)
{
if (modType == DataModification::eRemoved)
return;
// Report AirSupport
Database::RepAirSupportData airSupData;
auto aiv = getAesItemView(data.aesId());
if (aiv.partyId().is_set())
airSupData.aesPartyId = aiv.partyId().get();
airSupData.buildingId = data.structureElementId();
airSupData.chargeTypeId = data.chargeTypeId();
// Hits on Building will be stored as catastrophic kill
airSupData.vulnerabilityState = ProjectDataManagement::VulnerabilityState_def::CatastrophicKill;
airSupData.hitBuilding = 1;
airSupData.eventTime = data.sampleTime();
if (!m_db->insert(airSupData))
ERROR_LOG(m_logger) << "Error while inserting building state data into db for event_time = " << airSupData.eventTime;
} // end of onBuildingStateChanged
//------------------------------------------------------------------------------------------------------------------
void HandlerDynamicParticipantData::onAesEffectsChanged(const AreaEffectSimulation::Effects &data, DataModification modType)
{
if (modType == DataModification::eRemoved)
return;
Database::RepAirSupportImpactData impData;
impData.aesId = data.aesItemId();
AreaEffectSimulation::AesItemView aiv = getAesItemView(data.aesItemId());
impData.chargeTypeId = aiv.chargeStruct().chargeTypeId();
if (aiv.partyId().is_set())
impData.partyId = aiv.partyId().get();
//impData.aesName = getAesName(data.aesItemId());
impData.impacts = 0;
for (const AreaEffectSimulation::SingleEffect &singleEffect : data.singleEffects())
{
if (singleEffect.singleEffectState() == AreaEffectSimulation::AesSingleEffectState_def::SesTriggered)
{
impData.impacts++;
if (impData.eventTime < singleEffect.singleEffectTime())
impData.eventTime = singleEffect.singleEffectTime();
}
}
if (!m_db->insert(impData))
ERROR_LOG(m_logger) << "Error while inserting air support impact data into db for event_time = " << impData.eventTime;
} // end of onAesEffectsChanged
//------------------------------------------------------------------------------------------------------------------
bool HandlerDynamicParticipantData::containsGearTypeId(const std::vector<ParticipantManagement::GearInformation> &gi, int gearTypeId, int chargeTypeId)
{
for (const auto &g : gi)
{
if (g.gearTypeId() == gearTypeId && g.chargeTypeId() == chargeTypeId)
return true;
}
return false;
}
//-----------------------------------------------------------------------------
bool HandlerDynamicParticipantData::checkVulnerabilityStateChange(ProjectDataManagement::VulnerabilityState vulnState, int participantId)
{
// Report Mine Area / NBC
auto it = m_vulnStateMap.find(participantId);
// not yet in map -> state change
if (it == m_vulnStateMap.end())
return true;
// No change?
if (it.value() == vulnState)
{
INFO_LOG(m_logger) << "Same vulnerabilityState: " << vulnState;
return false;
}
return true;
}
//-----------------------------------------------------------------------------
AreaEffectSimulation::AesItemView HandlerDynamicParticipantData::getAesItemView(int effectSimulationId)
{
auto it = m_aesItemViewMap.constFind(effectSimulationId);
if (it == m_aesItemViewMap.constEnd())
{
// make sure we have all data
bool ww = m_aesDtc->waitForHistoricalDataAesItemView();
DEBUG_LOG(m_logger) << "waitForHistoricalDataAesItemView = " << ww;
auto ret = m_aesDtc->aesItemView(effectSimulationId);
DEBUG_LOG(m_logger) << "ret.id() = " << ret.id();
if (ret.id() == effectSimulationId)
{
m_aesItemViewMap[ret.id()] = ret;
return ret;
}
else
{
DEBUG_LOG(m_logger) << "Not found effectSimulationId = " << effectSimulationId;
return AreaEffectSimulation::AesItemView();
}
}
return it.value();
}
//-----------------------------------------------------------------------------
// only for ExplosionCluster and AirSupport
QString HandlerDynamicParticipantData::getAesName(int effectSimulationId)
{
auto it = m_aesNamesMap.constFind(effectSimulationId);
if (it == m_aesNamesMap.constEnd())
{
// make sure we have all data
bool ww = m_aesDtc->waitForHistoricalDataAesItemView();
DEBUG_LOG(m_logger) << "waitForHistoricalDataAesItemView = " << ww;
auto aesItemView = getAesItemView(effectSimulationId);
ERROR_LOG(m_logger) << "aesType: " << aesItemView.aesTypeId().underlying();
if (aesItemView.aesTypeId() == AreaEffectSimulation::AesType_def::AtExplosionCluster)
{
QString aesName = QString::fromStdString(m_aesDtc->explosionCluster(effectSimulationId).name());
ERROR_LOG(m_logger) << "ExplosionCluster aesName: " << aesName;
m_aesNamesMap.insert(effectSimulationId, aesName);
return aesName;
}
else
{
QString aesName = QString::fromStdString(m_aesDtc->airSupportImpact(effectSimulationId).name());
ERROR_LOG(m_logger) << "AirSupport aesName: " << aesName;
m_aesNamesMap.insert(effectSimulationId, aesName);
return aesName;
}
}
return it.value();
}
//-----------------------------------------------------------------------------
qint64 HandlerDynamicParticipantData::lastVulnerabilityChanged(const std::vector<ParticipantManagement::StateInformation> &stateHistory)
{
qint64 time_changed = 0;
for (const ParticipantManagement::StateInformation &si : stateHistory)
{
if (si.vulnerabilityState() != ProjectDataManagement::VulnerabilityState::CombatReady &&
si.vulnerabilityState() != ProjectDataManagement::VulnerabilityState::NotReady)
return si.stateTime();
}
return time_changed;
}
//-----------------------------------------------------------------------------
qint32 HandlerDynamicParticipantData::lastVitality(int participantId, qint64 currTime)
{
qint32 vit = 0;
NSqlQuery qSelect(m_db->database());
QString stmtSelect = QStringLiteral("SELECT vitality "
"FROM rep_treatment_timeline_data "
"WHERE participant_id = :participantId AND (event_time <= :currTime) "
"ORDER BY event_time DESC LIMIT 1");
DEBUG_LOG(m_logger) << "Statement: " << stmtSelect;
DEBUG_LOG(m_logger) << "Participant Id = " << participantId;
DEBUG_LOG(m_logger) << "Time = " << currTime;
qSelect.prepare(stmtSelect);
qSelect.bindValue(QStringLiteral(":currTime"), currTime);
qSelect.bindValue(QStringLiteral(":participantId"), participantId);
if (!qSelect.exec())
{
ERROR_LOG(m_logger) << "Error selecting data for participant id = " << participantId;
return vit;
}
qSelect.next();
vit = qSelect.value(0).toInt();
return vit;
}
//-----------------------------------------------------------------------------
qint32 HandlerDynamicParticipantData::lastVulnerabilityKind(int participantId, qint64 currTime)
{
qint32 vuln = 0;
NSqlQuery qSelect(m_db->database());
QString stmtSelect = QStringLiteral("SELECT vulnerability "
"FROM rep_treatment_timeline_data "
"WHERE participant_id = :participantId AND (event_time <= :currTime) "
"ORDER BY event_time DESC LIMIT 1");
DEBUG_LOG(m_logger) << "Statement: " << stmtSelect;
DEBUG_LOG(m_logger) << "Participant Id = " << participantId;
DEBUG_LOG(m_logger) << "Time = " << currTime;
qSelect.prepare(stmtSelect);
qSelect.bindValue(QStringLiteral(":currTime"), currTime);
qSelect.bindValue(QStringLiteral(":participantId"), participantId);
if (!qSelect.exec())
{
ERROR_LOG(m_logger) << "Error selecting data for participant id = " << participantId;
return vuln;
}
qSelect.next();
vuln = qSelect.value(0).toInt();
return vuln;
}
//-----------------------------------------------------------------------------
Core::GeoPosition HandlerDynamicParticipantData::getLastPosition(int participantId) const
{
Core::GeoPosition lastPosition;
auto itParticipant = m_partPositionMap.constFind(participantId);
if (itParticipant == m_partPositionMap.constEnd())
{
// we have to wait for historical participant data position
m_ppmDtc->waitForHistoricalDataParticipantPosition();
itParticipant = m_partPositionMap.constFind(participantId);
if (itParticipant == m_partPositionMap.constEnd())
WARNING_LOG(m_logger) << "Participant position not found for participantId: " << participantId;
}
else
return itParticipant.value().pos();
return lastPosition;
}
//-----------------------------------------------------------------------------
qint64 HandlerDynamicParticipantData::getLastSignificantParticipantPositionChanged(int participantId, qint64 currTime, const Core::GeoPosition &currPos)
{
qint64 time_changed = currTime;
NSqlQuery qSelect(m_db->database());
QString stmtSelect = QStringLiteral("SELECT sample_time, pos_lon, pos_lat "
"FROM rec_participant_position "
"WHERE participant_id = :participantId AND (sample_time <= :currTime) "
"ORDER by sample_time DESC");
DEBUG_LOG(m_logger) << "Statement: " << stmtSelect;
DEBUG_LOG(m_logger) << "Participant Id = " << participantId;
DEBUG_LOG(m_logger) << "Time = " << currTime;
qSelect.prepare(stmtSelect);
qSelect.bindValue(QStringLiteral(":currTime"), currTime);
qSelect.bindValue(QStringLiteral(":participantId"), participantId);
if (!qSelect.exec())
{
ERROR_LOG(m_logger) << "Error selecting data for participant id = " << participantId;
return time_changed;
}
while (qSelect.next())
{
if (qSelect.value(1).toDouble() != currPos.lon() || qSelect.value(2).toDouble() != currPos.lat())
{
time_changed = qSelect.value(0).toLongLong();
return time_changed;
}
}
return time_changed;
}
//-----------------------------------------------------------------------------
qint64 HandlerDynamicParticipantData::getLastSignificantPositionMountedChanged(int participantId, qint64 currTime, const Core::GeoPosition &currPos)
{
qint64 time_changed = 0;
NSqlQuery qSelect(m_db->database());
QString stmtSelect = QStringLiteral("SELECT sample_time, pos_lon, pos_lat "
"FROM rec_participant_position "
"WHERE participant_id = :participantId AND (sample_time <= :currTime) AND mounted_on > 0 "
"ORDER by sample_time DESC");
DEBUG_LOG(m_logger) << "Statement: " << stmtSelect;
DEBUG_LOG(m_logger) << "Participant Id = " << participantId;
DEBUG_LOG(m_logger) << "Time = " << currTime;
qSelect.prepare(stmtSelect);
qSelect.bindValue(QStringLiteral(":currTime"), currTime);
qSelect.bindValue(QStringLiteral(":participantId"), participantId);
if (!qSelect.exec())
{
ERROR_LOG(m_logger) << "Error selecting data for participant id = " << participantId;
return time_changed;
}
while (qSelect.next())
{
if (qSelect.value(1).toDouble() != currPos.lon() || qSelect.value(2).toDouble() != currPos.lat())
{
time_changed = qSelect.value(0).toLongLong();
return time_changed;
}
}
return time_changed;
}
// AHTC: we save the originator participant instead of hit participant
//-----------------------------------------------------------------------------
void HandlerDynamicParticipantData::onParticipantGearEventChanged(const ParticipantManagement::ParticipantGearEvent &data, DataModification modType)
{
if (modType == DataModification::eRemoved)
return;
DEBUG_LOG(m_logger) << "onParticipantGearEventChanged(): "
<< " participantId: " << data.participantId();
// Report Firings
Database::RepFiringsData fData;
fData.eventTime = data.sampleTime();
fData.participantId = data.participantId();
// get the corresponding originator participant
auto itOParticipant = m_partMap.constFind(fData.participantId);
if (itOParticipant == m_partMap.constEnd())
{
// we have to wait for historical participant data
m_ppmDtc->waitForHistoricalDataParticipant(2000);
itOParticipant = m_partMap.constFind(fData.participantId);
if (itOParticipant == m_partMap.constEnd())
{
WARNING_LOG(m_logger) << "Originator participant does not exist: Id = " << fData.participantId;
return;
}
}
const ParticipantManagement::Participant &oData = itOParticipant.value();
fData.participantTypeId = oData.typeId();
fData.partyId = oData.partyId();
fData.vulnerabilityState = 0;
fData.chargeTypeId = data.charge().chargeTypeId();
fData.hit = 0;
fData.hitFriendlyFire = 0;
// Save firings data
if (!m_db->insert(fData))
ERROR_LOG(m_logger) << "Error while inserting ParticipantGearEvent firings data into db for event_time = " << fData.eventTime;
}
// -----------------------------------------------------------------------------------
QJsonObject HandlerDynamicParticipantData::areaToJson(int id, const QString& name) const
{
QJsonObject obj;
obj[QStringLiteral("area_id")] = id;
obj[QStringLiteral("area_name")] = name;
return obj;
}
// -----------------------------------------------------------------------------------
QJsonObject HandlerDynamicParticipantData::sanToJson(qint64 procTaken) const
{
QJsonObject obj;
obj[QStringLiteral("san_procs")] = procTaken;
return obj;
}
//TODO: remove double code
//-----------------------------------------------------------------------------
qint64 HandlerDynamicParticipantData::sinceWhenVitality(int participantId, int vitality, qint64 currTime)
{
qint64 time = currTime;
NSqlQuery qSelect(m_db->database());
QString stmtSelect = QStringLiteral("SELECT event_time, vitality "
"FROM rep_treatment_timeline_data "
"WHERE participant_id = :participantId AND (event_time <= :currTime) "
"ORDER BY event_time DESC");
DEBUG_LOG(m_logger) << "!!! sinceWhenVitality";
DEBUG_LOG(m_logger) << "Statement: " << stmtSelect;
DEBUG_LOG(m_logger) << "Participant Id = " << participantId;
DEBUG_LOG(m_logger) << "Time = " << currTime;
DEBUG_LOG(m_logger) << "Vitality = " << vitality;
qSelect.prepare(stmtSelect);
qSelect.bindValue(QStringLiteral(":currTime"), currTime);
qSelect.bindValue(QStringLiteral(":participantId"), participantId);
if (!qSelect.exec())
{
ERROR_LOG(m_logger) << "Error selecting data for participant id = " << participantId;
return time;
}
while (qSelect.next())
{
int vit = qSelect.value(1).toInt();
if (vit == vitality)
{
time = qSelect.value(0).toLongLong();
continue;
}
else
break;
}
DEBUG_LOG(m_logger) << "### Recalculated time vitality = " << time;
return time;
}
//TODO: remove double code
//-----------------------------------------------------------------------------
qint64 HandlerDynamicParticipantData::sinceWhenVulnerability(int participantId, int vulnerability, qint64 currTime)
{
qint64 time = currTime;
NSqlQuery qSelect(m_db->database());
QString stmtSelect = QStringLiteral("SELECT event_time, vulnerability "
"FROM rep_treatment_timeline_data "
"WHERE participant_id = :participantId AND (event_time <= :currTime) "
"ORDER BY event_time DESC");
DEBUG_LOG(m_logger) << "!!! sinceWhenVulnerability";
DEBUG_LOG(m_logger) << "Statement: " << stmtSelect;
DEBUG_LOG(m_logger) << "Participant Id = " << participantId;
DEBUG_LOG(m_logger) << "Time = " << currTime;
DEBUG_LOG(m_logger) << "Vulnerability = " << vulnerability;
qSelect.prepare(stmtSelect);
qSelect.bindValue(QStringLiteral(":currTime"), currTime);
qSelect.bindValue(QStringLiteral(":participantId"), participantId);
if (!qSelect.exec())
{
ERROR_LOG(m_logger) << "Error selecting data for participant id = " << participantId;
return time;
}
while (qSelect.next())
{
int vuln = qSelect.value(1).toInt();
DEBUG_LOG(m_logger) << "Checking - time = " << qSelect.value(0).toLongLong() << ", vuln = " << vuln;
if (vuln == vulnerability)
{
time = qSelect.value(0).toLongLong();
continue;
}
else
break;
}
DEBUG_LOG(m_logger) << "### Recalculated time vulnerability = " << time;
return time;
}