/** * 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 #include #include #include using namespace ReportManagement; //----------------------------------------------------------------------------- HandlerDynamicParticipantData::HandlerDynamicParticipantData(const std::shared_ptr &ddsHandler, const std::shared_ptr &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, int> gearMap = m_chargeGearInfo.value(crData.participantId); QMap 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 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 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 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 &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 &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; }