1459 lines
58 KiB
C++
Executable File
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;
|
|
}
|
|
|