/** * Handler for player data * $Id$ * $HeadURL$ * $Author$ * Created by gr, SLSE, 2017-02-20 */ #include "handler_functional_area.h" #include #include #include #include #include namespace dds { namespace core { inline uint qHash(ProjectDataManagement::EventType et) { return ::qHash(et.underlying()); } } } namespace CES_FUNCTIONAL_AREA { inline uint qHash(EffectType et) { return ::qHash(int(et)); } QString toString(EffectType et) { switch (et) { case EffectType::Unknown: return QStringLiteral("Unknown"); case EffectType::EffectiveMineRangeEnter: return QStringLiteral("EffectiveMineRangeEnter"); case EffectType::EffectiveMineRangeLeave: return QStringLiteral("EffectiveMineRangeLeave"); case EffectType::NContaminationLeave: return QStringLiteral("NContaminationLeave"); case EffectType::NContaminationEnterArea1: return QStringLiteral("NContaminationEnterArea1"); case EffectType::NContaminationEnterArea2: return QStringLiteral("NContaminationEnterArea2"); case EffectType::NContaminationDetonation: return QStringLiteral("NContaminationDetonation"); case EffectType::FunctionalAreaLeave: return QStringLiteral("FunctionalAreaLeave"); case EffectType::FunctionalAreaEnter: return QStringLiteral("FunctionalAreaEnter"); case EffectType::ExplosionArea: return QStringLiteral("ExplosionArea"); case EffectType::ExplosionSingle: return QStringLiteral("ExplosionSingle"); case EffectType::BCContaminationLeave: return QStringLiteral("BCContaminationLeave"); case EffectType::BCContaminationEnterFloating: return QStringLiteral("BCContaminationEnterFloating"); case EffectType::BCContaminationEnterResident: return QStringLiteral("BCContaminationEnterResident"); case EffectType::BCContaminationEnterFloatingArea: return QStringLiteral("BCContaminationEnterFloatingArea"); case EffectType::BeStillWarning: return QStringLiteral("BeStillWarning"); } return QStringLiteral("Unknown (%1)").arg(int(et)); } HandlerFunctionalAreas::HandlerFunctionalAreas(const std::shared_ptr &ddsHandler, const std::shared_ptr &participantHandler, const std::shared_ptr &handlerBuildingData, QObject *parent) : QObject(parent) , m_ddsHandler(ddsHandler) , m_handlerParticipant(participantHandler) , m_handlerBuildingData(handlerBuildingData) , m_logger(CentralEffectSimulation::getLogger("Plugin.FunctionalAreas.HandlerFunctionalAreas")) { } // end of ctor() //----------------------------------------------------------------------------- HandlerFunctionalAreas::~HandlerFunctionalAreas() { } // end of dtor() //----------------------------------------------------------------------------- bool HandlerFunctionalAreas::init() { auto dtcAes = m_ddsHandler->dtcAes(); dtcAes->waitForHistoricalDataFunctionalArea(2000); dtcAes->waitForHistoricalDataAesItemView(1000); connect(dtcAes.get(), &AreaEffectSimulation::Interface::Dtc::aesItemViewChanged, this, &HandlerFunctionalAreas::onAesItemViewChanged); // TAB FTC m_ddsHandler->ftcTab()->enableDemandInit(); connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::newOutdoorPosition, this, &HandlerFunctionalAreas::onNewParticipantPosition); connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::newIndoorPosition, this, &HandlerFunctionalAreas::onNewIndoorParticipantPosition); connect(m_handlerParticipant.get(), &CentralEffectSimulation::HandlerParticipant::restoreRadioReadinessChanged, this, &HandlerFunctionalAreas::onRestoreRadioReadinessChanged); // Get 'static' data for all onAesItemView { auto cb = [this](const AreaEffectSimulation::AesItemView & aiv) { onAesItemViewChanged(aiv, DataModification::eAdded); }; if (!dtcAes->aesItemViews(cb)) return false; } INFO_LOG(m_logger) << "HandlerParticipantArea::init() finished."; return true; } // end of init() //----------------------------------------------------------------------------- void HandlerFunctionalAreas::onSendCesHitReply(const Core::FunctionReplyObject &replyObject) { DEBUG_LOG(m_logger) << "onSendCesHitReply for id " << replyObject.id() << " success= " << replyObject.error(); if (replyObject.error()) WARNING_LOG(m_logger) << "Can not send enter/leave Area to participant in training area: " << replyObject(); // Send next Request, if available if (!m_sendCesHitRequestQueue.isEmpty()) { DEBUG_LOG(m_logger) << "m_sendCesAreaActionRequestQueue.size()=" << m_sendCesHitRequestQueue.size(); m_sendCesHitRequestQueue.dequeue(); // Send next Message if (!m_sendCesHitRequestQueue.isEmpty()) { const auto &hr = m_sendCesHitRequestQueue.head(); DEBUG_LOG(m_logger) << "sendCesHitRequest: " << hr; m_ddsHandler->ftcTab()->sendCesHitRequest(hr, this); } } } void HandlerFunctionalAreas::onDemandInitReply(const Core::FunctionReplyObject &replyObject) { DEBUG_LOG(m_logger) << "onDemandInitReply for id " << replyObject.id() << " success= " << replyObject.error(); if (replyObject.error()) WARNING_LOG(m_logger) << "Can not send Init to participant in training area: " << replyObject(); // Send next Request, if available if (!m_sendInitRequestQueue.isEmpty()) { DEBUG_LOG(m_logger) << "m_sendInitRequestQueue.size()=" << m_sendInitRequestQueue.size(); m_sendInitRequestQueue.dequeue(); // Send next Message if (!m_sendInitRequestQueue.isEmpty()) { const auto &hr = m_sendInitRequestQueue.head(); DEBUG_LOG(m_logger) << "demandInitRequest: " << hr; m_ddsHandler->ftcTab()->demandInitRequest(hr, this); } } } // /////////////////////////////////// // A E S (AreaEffectSimulation) // /////////////////////////////////// void HandlerFunctionalAreas::onAesItemViewChanged(const AreaEffectSimulation::AesItemView &data, DataModification modType) { const int aesItemId = data.aesItemId(); const AreaEffectSimulation::AesEffectState &effectState = data.effectStateId(); if (data.aesTypeId().underlying() != AreaEffectSimulation::AesType_def::AtFunctionalArea) return; const AreaEffectSimulation::FunctionalArea &fa = m_ddsHandler->dtcAes()->functionalArea(data.aesItemId()); if (!fa.isCentral()) { DEBUG_LOG(m_logger) << " !isCentral" " Got AesItemView id: " << aesItemId << ", type: " << data.aesTypeId() << ", effectState: " << data.effectStateId() << ", modType: " << modType; if (m_aesItemViews.contains(aesItemId)) m_aesItemViews.remove(aesItemId); return; } DEBUG_LOG(m_logger) << "Got AesItemView id: " << aesItemId << ", type: " << data.aesTypeId() << ", effectState: " << data.effectStateId() << ", modType: " << modType; switch (effectState.underlying()) { case AreaEffectSimulation::AesEffectState_def::EsPrepared: break; case AreaEffectSimulation::AesEffectState_def::EsActivated: { bool isSupplyTruck = false; if (fa.supplyMode() == AreaEffectSimulation::AesOperatingMode_def::OmWaitingTime) { DEBUG_LOG(m_logger) << "isSupplyTruck = true"; isSupplyTruck = true; } auto aesItemViewUtm(CentralEffectSimulation::AesItemViewUtm::create(data, m_aesItemViews[data.aesItemId()], 0, isSupplyTruck)); if (fa.participantId().is_set()) aesItemViewUtm.participantId = fa.participantId().get(); if (!m_aesPolygonEncloseBuilding.contains(data.aesItemId())) { QVector enclosedBuildings; QPolygonF polygon; polygon.reserve(data.form().size()); for (size_t i = 0; i < data.form().size(); i++) { //QPointF point(itemView.form[i].x(), itemView.form[i].y()); QPointF point(data.form().at(i).lon(), data.form().at(i).lat()); polygon.append(point); } enclosedBuildings = m_handlerBuildingData->polygonEncloseBuildings(polygon); DEBUG_LOG(m_logger) << "enclosedBuildings.size=" << enclosedBuildings.size(); // local memory for the results, so that the polygonEncloseBuildings method is only run once for each effective field // and not for each position report m_aesPolygonEncloseBuilding.insert(data.aesItemId(), enclosedBuildings); DEBUG_LOG(m_logger) << "insert enclosedBuildings.size=" << enclosedBuildings.size(); } calculateFunctionalArea(aesItemViewUtm); m_aesItemViews.insert(data.aesItemId(), aesItemViewUtm); DEBUG_LOG(m_logger) << "insert Functiona Area AesItemView id: " << aesItemId << ", type: " << data.aesTypeId(); break; } // case EsActivated case AreaEffectSimulation::AesEffectState_def::EsRemoved: case AreaEffectSimulation::AesEffectState_def::EsExpired: { aesItemViewRemoved(aesItemId); m_aesPolygonEncloseBuilding.remove(aesItemId); break; } default: // do nothing break; } // switch effectStateId } // onAesItemViewChanged void HandlerFunctionalAreas::calculateFunctionalArea(const CentralEffectSimulation::AesItemViewUtm &itemView) { bool inForm = false; DEBUG_LOG(m_logger) << "HandlerParticipantArea::calculateFunctionalArea aesItemId =" << itemView.aesItemId; const auto participantsMap = m_handlerParticipant->positions(); for (const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantPos : participantsMap) { if (m_handlerParticipant->isOutdated(participantPos)) continue; DEBUG_LOG(m_logger) << "participant id= " << participantPos.participantId() << " buildingId=" << participantPos.buildingId(); if ( participantPos.buildingId() ==0 ) inForm = inFormCheck(itemView, participantPos); else { for (int i = 0; i < m_aesPolygonEncloseBuilding.value(itemView.aesItemId).size(); i++) { inForm = false; if (m_aesPolygonEncloseBuilding.value(itemView.aesItemId).at(i) == participantPos.buildingId()) { inForm = true; m_handlerParticipant->setNotfightMode(participantPos.participantId(), true); DEBUG_LOG(m_logger) << "!m_aesPolygonEncloseBuilding buildingId=" << participantPos.buildingId() << " aesId=" << itemView.aesItemId << " in Form = true"; break; } else { DEBUG_LOG(m_logger) << "!m_aesPolygonEncloseBuilding buildingId=" << participantPos.buildingId() << " aesId=" << itemView.aesItemId << " in Form = false"; } } } sendEnterLeave(itemView, participantPos.participantId(), inForm); } // for } // calculateFunctionalArea void HandlerFunctionalAreas::onNewParticipantPosition(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData) { DEBUG_LOG(m_logger) << "++++++++ onNewParticipantPosition participantId=" << participantData.participantId(); if (m_handlerParticipant->isOutdated(participantData)) return; const int equipmentNumber = m_ddsHandler->participantId2EquipNo(participantData.participantId()); if (equipmentNumber <= 0) { DEBUG_LOG(m_logger) << "equipmentNumber <=0"; return; } DEBUG_LOG(m_logger) << "HandlerParticipantArea::calculateAesParticipant paricipantId: " << participantData.participantId(); for (const CentralEffectSimulation::AesItemViewUtm &itemView : qAsConst(m_aesItemViews)) { DEBUG_LOG(m_logger) << " itemView: " << itemView.aesItemId << ", " << itemView.aesTypeId; switch (itemView.aesTypeId.underlying()) { case AreaEffectSimulation::AesType_def::AtFunctionalArea: { /////////////////// /// \brief [GUEZE-2256] 3D Wirksim - Funktionsraum Nicht Kampffähig /// Die Teilnehmer der Partei des Wirkfeldes werden nicht berücksichtig. /// AreaEffectSimulation::FunctionalArea functionalArea = m_ddsHandler->dtcAes()->functionalArea(itemView.aesItemId); DEBUG_LOG(m_logger) << "functionalArea Typ=" << functionalArea.functionalAreaTypeId() << " itemView.partyId=" << itemView.partyId << " participantData.partyId=" << participantData.partyId() << " insideBuilding=" << participantData.insideBuilding(); /////////////////// bool inForm = inFormCheck(itemView, participantData); sendEnterLeave(itemView, participantData.participantId(), inForm); break; } default: // nothing break; } // switch } // for } // onNewParticipantPosition void HandlerFunctionalAreas::onNewIndoorParticipantPosition(const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData) { DEBUG_LOG(m_logger) << "New Indoor Position paticipantId=" << participantData.participantId(); if (m_handlerParticipant->isOutdated(participantData)) return; const int equipmentNumber = m_ddsHandler->participantId2EquipNo(participantData.participantId()); if (equipmentNumber <= 0) { DEBUG_LOG(m_logger) << "equipmentNumber <=0"; return; } DEBUG_LOG(m_logger) << "HandlerParticipantArea::calculateAesParticipant paricipantId: " << participantData.participantId(); for (const CentralEffectSimulation::AesItemViewUtm &itemView : qAsConst(m_aesItemViews)) { DEBUG_LOG(m_logger) << " itemView: " << itemView.aesItemId << ", " << itemView.aesTypeId; switch (itemView.aesTypeId.underlying()) { case AreaEffectSimulation::AesType_def::AtFunctionalArea: { /////////////////// /// \brief [GUEZE-2256] 3D Wirksim - Funktionsraum Nicht Kampffähig /// Die Teilnehmer der Partei des Wirkfeldes werden nicht berücksichtig. /// AreaEffectSimulation::FunctionalArea functionalArea = m_ddsHandler->dtcAes()->functionalArea(itemView.aesItemId); DEBUG_LOG(m_logger) << "functionalArea Typ=" << functionalArea.functionalAreaTypeId() << " itemView.partyId=" << itemView.partyId << " participantData.partyId=" << participantData.partyId() << " insideBuilding=" << participantData.insideBuilding(); { if ( (itemView.partyId == participantData.partyId()) && (functionalArea.functionalAreaTypeId() == 8)) // Funktionsraum Nicht Kampffaehig [GUEZE-2256] { DEBUG_LOG(m_logger) << "Position mit Funktionsraum Nicht Kampffähig hat die Partei des Wirkfeldes => nicht beruecksichtigen"; continue; } } // Check whether the position appears in the building list of the effective field. bool inForm = false; for (int i = 0; i < m_aesPolygonEncloseBuilding.value(itemView.aesItemId).size(); i++) { if (m_aesPolygonEncloseBuilding.value(itemView.aesItemId).at(i) == participantData.buildingId()) { inForm = true; m_handlerParticipant->setNotfightMode(participantData.participantId(), true); break; } } /////////////////// sendEnterLeave(itemView, participantData.participantId(), inForm); break; } default: // nothing break; } // switch } // for } void HandlerFunctionalAreas::onRestoreRadioReadinessChanged(const int participantId) { DEBUG_LOG(m_logger) << "HandlerArtillery::onRestoreRadioReadinessChanged participantId=" << participantId; m_supplyTimers.remove(participantId); removeParticipant(participantId); } // return true, if participant is inside of the bounding Box bool HandlerFunctionalAreas::inBoundingBoxCheck(const CentralEffectSimulation::AesItemViewUtm &itemView, const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData) { if (itemView.effectStateId != AreaEffectSimulation::AesEffectState_def::EsActivated) return false; // QRectF(topLeft, bottomRight) -> no need to mormalize, QRectF:contains() handles it correct const QRectF boundingBoxImpact(itemView.boundingBoxBottomLeft, itemView.boundingBoxTopRight); const QPointF participantPosUtmPoint = CentralEffectSimulation::geographic2Utm(participantData.pos(), itemView.zone); if (boundingBoxImpact.contains(participantPosUtmPoint)) { DEBUG_LOG(m_logger) << "inBoundingBoxCheck Paricipant " << participantData.participantId() << " inside AesItemView:" << itemView.aesItemId; return true; } TRACE_LOG(m_logger) << "inBoundingBoxCheck Paricipant " << participantData.participantId() << " outside AesItemView:" << itemView.aesItemId; return false; } // return true, if participant is inside of the form of AesItemView bool HandlerFunctionalAreas::inFormCheck(const CentralEffectSimulation::AesItemViewUtm &itemView, const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData) { if (itemView.effectStateId != AreaEffectSimulation::AesEffectState_def::EsActivated) return false; const QRectF boundingBox(itemView.boundingBoxBottomLeft, itemView.boundingBoxTopRight); const QPointF participantPosUtmPoint = CentralEffectSimulation::geographic2Utm(participantData.pos(), itemView.zone); const QString participantPosMgrs = CentralEffectSimulation::geographic2mgrs(participantData.pos(), itemView.zone); DEBUG_LOG(m_logger) << "inFormCheck start, paricipantId: " << participantData.participantId() << ", aesItemId: " << itemView.aesItemId << ", aesTypeId: " << itemView.aesTypeId << ", form.size: " << itemView.form.size() << ", Mgrs:" << participantPosMgrs; if (boundingBox.contains(participantPosUtmPoint) && itemView.form.containsPoint(participantPosUtmPoint, Qt::FillRule::OddEvenFill)) { DEBUG_LOG(m_logger) << "inside AES form, paricipantId: " << participantData.participantId() << ", aesItemId: " << itemView.aesItemId; return true; } // if inside // outside #if 0 if (m_logger.isDebugEnabled()) { DEBUG_LOG(m_logger) << "inFormCheck: Paricipant " << participantPosition.participantId << " outside AesItemView " << itemView.aesItemId; DEBUG_LOG(m_logger) << "ParticipantPos = " << debug(participantPosUtmPoint); for (const auto &itPos : itemView.form) DEBUG_LOG(m_logger) << "itemView =" << debug(itPos); } #endif return false; } // Send via TAB-Proxy to battlefield void HandlerFunctionalAreas::sendCesHitRequest(const CentralEffectSimulation::AesItemViewUtm &itemView, const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData, ProjectDataManagement::EventType eventType) { qint64 effectTime = QDateTime::currentMSecsSinceEpoch(); // qint64 mineFieldBitIndex = 0; int remaining = 0; switch (eventType.underlying()) { case ProjectDataManagement::EventType_def::EnterFunctionalArea: DEBUG_LOG(m_logger) << "-------------- EnterFunctionalArea itemView =" << itemView.aesItemId; remaining = 1; break; case ProjectDataManagement::EventType_def::LeaveFunctionalArea: remaining = 0; DEBUG_LOG(m_logger) << "-------------- LeaveFunctionalArea itemView =" << itemView.aesItemId; break; default: return; } if (remaining < 0) return; DEBUG_LOG(m_logger) << "sendCesHitRequest Settings::calculateCentralAes=" << " insideWlsArea=" << std::boolalpha << participantData.insideWlsArea() << " isSmartChargeType=" << std::boolalpha << m_ddsHandler->isSmartChargeType(itemView.chargeStruct) << " participantId=" << participantData.participantId(); const int equipNo = m_ddsHandler->participantId2EquipNo(participantData.participantId()); DEBUG_LOG(m_logger) << " ftc sendCESHit to Participant participantId = " << participantData.participantId() << " equipNo = " << equipNo << " aesItemId =" << itemView.aesItemId; // participantPosition.participantPosition == 0 -> send to all if (participantData.participantId() != 0 && equipNo <= 0) { DEBUG_LOG(m_logger) << "participantPosition.participantId != 0 && equipNo <= 0"; return; } if (participantData.participantId() != 0 && participantData.vulnerabilityState == ProjectDataManagement::VulnerabilityState_def::CatastrophicKill) { DEBUG_LOG(m_logger) << "participantPosition.participantId != 0 CatastrophicKill)"; return; } const AreaEffectSimulation::FunctionalArea &fa = m_ddsHandler->dtcAes()->functionalArea(itemView.aesItemId); const TrainingAreaBase::TabPosition pos(participantData.pos(), Core::PositionReportingSource_def::Gps, // irrelevant participantData.buildingId(), participantData.roomId()); const int medicTime = fa.medicTime() / 600000; //reserve 2 = medical treatment const int maintanceTime = fa.maintTime() / 600000; //reserve 1 = maintance time const int decontaminatonTime = fa.deconTime() / 600000; //reserve Munitionsart = decontaminaton time const int operationModeDecontamination = fa.deconMode().underlying(); const int operationModeMaintenance = fa.maintMode().underlying(); const int operationModeMedical = fa.medicMode().underlying(); //const int originatorEquipNo = fa.medicTime()/60000; //reserve 2 = medical treatment //const int mineId = fa.maintTime()/60000; //reserve 1 = maintance time //const int chargeType = fa.deconTime()/1000; //reserve Munitionsart = decontaminaton time const int originatorEquipNo = (operationModeMedical << 8) + medicTime; //reserve 2 = medical treatment const int mineId = (operationModeMaintenance << 8) + maintanceTime; //reserve 1 = maintance time const int chargeType = (operationModeDecontamination << 8) + decontaminatonTime; //reserve Munitionsart = decontaminaton time TrainingAreaBase::SendCesHitRequest requestTab( equipNo, // equipmentNumber participantData.participantId(), // participantId chargeType, // chargeTypeId itemView.aesItemId, // aesId originatorEquipNo, // originatorEquipmentNumber remaining, // remainEffectPercent ( no protection outside Building ) pos, effectTime, // effectTime eventType, itemView.partyId, // originPartyId mineId ); DEBUG_LOG(m_logger) << " participantId=" << participantData.participantId() << " chargeTypeId=" << itemView.chargeStruct.chargeTypeId(); m_sendCesHitRequestQueue.enqueue(requestTab); if (m_sendCesHitRequestQueue.size() == 1) { DEBUG_LOG(m_logger) << "SendCesHitRequest: " << requestTab; m_ddsHandler->ftcTab()->sendCesHitRequest(requestTab, this); } } void HandlerFunctionalAreas::sendParticipantEvent(const CentralEffectSimulation::AesItemViewUtm &itemView, const CentralEffectSimulation::HandlerParticipant::CesParticipantData &participantData, const ProjectDataManagement::EventType eventType) { ParticipantManagement::TypeClass typeClass = m_handlerParticipant->typeClassFromTypeId(participantData.participantTypeId()); // can happen since the positions are collected for all participants (no check if it is a SupportEntity or similar) if (typeClass == ParticipantManagement::TypeClass_def::Unit || typeClass == ParticipantManagement::TypeClass_def::SupportUnit || typeClass == ParticipantManagement::TypeClass_def::SupportEntity || typeClass == ParticipantManagement::TypeClass_def::Aircraft || typeClass == ParticipantManagement::TypeClass_def::Vessel || typeClass == ParticipantManagement::TypeClass_def::Unknown) { DEBUG_LOG(m_logger) << "Participant with id " << participantData.participantId() << " has invalid typeClass: " << typeClass << " eventType: " << eventType; return; } int equipmentNumber = m_ddsHandler->participantId2EquipNo(participantData.participantId()); if (equipmentNumber <= 0) { WARNING_LOG(m_logger) << "Not sending Event " << eventType << " for participant " << participantData.participantId() << " - participant has no equipment number"; return; } DEBUG_LOG(m_logger) << "sendParticipantEvent" << eventType << " participantId=" << participantData.participantId() << " AesItemId=" << itemView.aesItemId; const AreaEffectSimulation::FunctionalArea &fa = m_ddsHandler->dtcAes()->functionalArea(itemView.aesItemId); CentralEffectSimulation::ParticipantEvent pe; pe.id(m_ddsHandler->getParticipantEventId()); pe.eventTypeId(eventType.underlying()); pe.participantId(participantData.participantId()); pe.eventTime(participantData.sampleTime()); pe.aesItemId(itemView.aesItemId); pe.partyId(participantData.partyId()); pe.aesName(fa.name()); pe.equipmentNumber(equipmentNumber); pe.vulnerability(participantData.vulnerabilityState.underlying()); pe.position(participantData.pos()); pe.friendlyFire(false); INFO_LOG(m_logger) << "sendParticipantEvent: " << pe << ", currentMSecsSinceEpoch = " << QDateTime::currentMSecsSinceEpoch() << ", time difference = " << QDateTime::currentMSecsSinceEpoch() - pe.eventTime(); m_ddsHandler->dtsCes()->publish(pe); const auto id = pe.id(); QTimer::singleShot(1 * 60 * 1000, this, [id, this]() { m_ddsHandler->dtsCes()->removeParticipantEventByKey(id); }); } void HandlerFunctionalAreas::aesItemViewRemoved(int aesItemId) { DEBUG_LOG(m_logger) << "aesItemViewRemoved aesItemId=" << aesItemId << " m_cesEnterLeaveFunctionalArea.size=" << m_cesEnterLeaveFunctionalArea.size() << " m_aesItemViews.size=" << m_aesItemViews.size(); QHashIterator, EnterLeaveType> i(m_cesEnterLeaveFunctionalArea); while (i.hasNext()) { i.next(); DEBUG_LOG(m_logger) << "Key: itemId=" << i.key().first << " participantId=" << i.key().second << " EnterLeaveType=" << i.value().eventType; if (i.key().first == aesItemId ) { DEBUG_LOG(m_logger) << " EnterLeaveType=" << i.value().eventType; CentralEffectSimulation::AesItemViewUtm itemView = m_aesItemViews.value(i.key().first); sendEnterLeave(itemView, i.key().second, false); m_cesEnterLeaveFunctionalArea.remove(i.key()); } } m_aesItemViews.remove(aesItemId); } void HandlerFunctionalAreas::removeParticipant(int participantId) { DEBUG_LOG(m_logger) << "removeParticipant participantId=" << participantId << " m_cesEnterLeaveFunctionalArea.size=" << m_cesEnterLeaveFunctionalArea.size(); QHashIterator, EnterLeaveType> i(m_cesEnterLeaveFunctionalArea); while (i.hasNext()) { i.next(); DEBUG_LOG(m_logger) << "Key: itemId=" << i.key().first << " participantId=" << i.key().second << " EnterLeaveType=" << i.value().eventType; if (i.key().second == participantId ) { DEBUG_LOG(m_logger) << " EnterLeaveType=" << i.value().eventType; CentralEffectSimulation::AesItemViewUtm itemView = m_aesItemViews.value(i.key().first); //sendEnterLeave(itemView, i.key().second, false); m_cesEnterLeaveFunctionalArea.remove(i.key()); } } } void HandlerFunctionalAreas::sendEnterLeave(const CentralEffectSimulation::AesItemViewUtm &itemView, int participantId, bool inForm) { QPair key = QPair(itemView.aesItemId, participantId); EnterLeaveType enterLeaveType; EnterLeaveType lastEnterLeaveType; if (m_cesEnterLeaveFunctionalArea.contains(key)) lastEnterLeaveType = m_cesEnterLeaveFunctionalArea.value(key); DEBUG_LOG(m_logger) << "HandlerFunctionalAreas::sendEnterLeave " << " aesItemId=" << itemView.aesItemId << " participantId=" << participantId << " inForm=" << inForm; if (inForm) { enterLeaveType.eventType = ProjectDataManagement::EventType_def::EnterFunctionalArea; if (itemView.isSupplyTruck) { enterLeaveType.isAlreadySupplied = true; const AreaEffectSimulation::FunctionalArea &fa = m_ddsHandler->dtcAes()->functionalArea(itemView.aesItemId); if (!lastEnterLeaveType.isAlreadySupplied) { DEBUG_LOG(m_logger) << "sendEnterLeave.startSupplyTimer" " m_cesEnterLeaveFunctionalArea.insert" << " aesItemId=" << key.first << " participantId=" << key.second << " enterLeaveType=" << enterLeaveType.eventType; startSupplyTimer(participantId, itemView.aesItemId, fa.supplyTime()); m_cesEnterLeaveFunctionalArea.insert(key, enterLeaveType); } } } else { enterLeaveType.eventType = ProjectDataManagement::EventType_def::LeaveFunctionalArea; if (itemView.isSupplyTruck && lastEnterLeaveType.eventType == ProjectDataManagement::EventType_def::EnterFunctionalArea) { DEBUG_LOG(m_logger) << "sendEnterLeave.stopSupplyTimer"; enterLeaveType.isAlreadySupplied = false; stopSupplyTimer(participantId); DEBUG_LOG(m_logger) << "sendEnterLeave.startSupplyTimer" " m_cesEnterLeaveFunctionalArea.insert" << " aesItemId=" << key.first << " participantId=" << key.second << " enterLeaveType=" << enterLeaveType.eventType; m_cesEnterLeaveFunctionalArea.insert(key, enterLeaveType); } } if ((inForm && lastEnterLeaveType.eventType != ProjectDataManagement::EventType_def::EnterFunctionalArea) || (!inForm && lastEnterLeaveType.eventType == ProjectDataManagement::EventType_def::EnterFunctionalArea)) { CentralEffectSimulation::HandlerParticipant::CesParticipantData cesParticipantData = m_handlerParticipant.get()->getParticipantPosition(participantId); sendParticipantEvent(itemView, cesParticipantData, enterLeaveType.eventType); const AreaEffectSimulation::FunctionalArea &fa = m_ddsHandler->dtcAes()->functionalArea(itemView.aesItemId); DEBUG_LOG(m_logger) << "fa.isCentral()=" << fa.isCentral() << " isSupplyTruck=" << itemView.isSupplyTruck << " eventType=" << m_cesEnterLeaveFunctionalArea.value(key).eventType << " isAlreadySupplied=" << enterLeaveType.isAlreadySupplied; if (fa.isCentral() && !itemView.isSupplyTruck) { DEBUG_LOG(m_logger) << "sendCesHitRequest"; sendCesHitRequest(itemView, cesParticipantData, enterLeaveType.eventType); } DEBUG_LOG(m_logger) << " m_cesEnterLeaveFunctionalArea.insert" << " aesItemId=" << key.first << " participantId=" << key.second << " enterLeaveType=" << enterLeaveType.eventType; m_cesEnterLeaveFunctionalArea.insert(key, enterLeaveType); } } // sendEnterLeave void HandlerFunctionalAreas::startSupplyTimer(int participantId, int aesId, long time) { DEBUG_LOG(m_logger) << "startSupplyTimer=" << " participantId=" << participantId << " aesId=" << aesId << " time=" << time << " ST participant" << m_aesItemViews[aesId].participantId; if (participantId == m_aesItemViews[aesId].participantId) { DEBUG_LOG(m_logger) << "No supply for SupplyTruck"; return; } if (m_supplyTimers.contains(participantId)) { if (m_supplyTimers[participantId]->isActive()) { DEBUG_LOG(m_logger) << "SupplyTimer isActive"; return; } else m_supplyTimers.remove(participantId); } SupplyTimer *supplyTimer = new SupplyTimer(participantId, aesId, time); DEBUG_LOG(m_logger) << "supplyTimer->startTimer();"; QObject::connect(supplyTimer, &SupplyTimer::timeToEffectTimeout, this, &HandlerFunctionalAreas::on_supplyFinished); m_supplyTimers.insert(participantId, supplyTimer); supplyTimer->startTimer(); } // startSupplyTimer void HandlerFunctionalAreas::stopSupplyTimer(int participantId) { DEBUG_LOG(m_logger) << "stopSupplyTimer=" << "participantId=" << participantId; if (m_supplyTimers.contains(participantId)) { if (m_supplyTimers[participantId]->isActive()) return; } } // startSupplyTimer void HandlerFunctionalAreas::on_supplyFinished(int participantId, int aesId) { DEBUG_LOG(m_logger) << "HandlerFunctionalAreas::on_supplyFinished participantId=" << participantId << " aesId =" << aesId; sendInitSupplyToTab(participantId, aesId); } void HandlerFunctionalAreas::sendInitSupplyToTab(int participantId, int aesId) { const int equipmentNumber = m_ddsHandler->participantId2EquipNo(participantId); if (equipmentNumber <= 0) return; int requestId = m_requestId++; int workstationId = 0; std::vector equipmentNumbers; equipmentNumbers.push_back(equipmentNumber); bool restockCharges = true; bool resetManipulation = false; bool resetVulnerabilityState = false; bool restockSanitationMaterial = false; DEBUG_LOG(m_logger) << "sendInitSupplyToTab" << " participantId=" << participantId << " aesId=" << aesId; TrainingAreaBase::DemandInitRequest demandInitRequest( requestId, workstationId, equipmentNumbers, restockCharges, resetManipulation, resetVulnerabilityState, restockSanitationMaterial ); m_sendInitRequestQueue.enqueue(demandInitRequest); if (m_sendInitRequestQueue.size() == 1) { DEBUG_LOG(m_logger) << "sendInitSupply: " << demandInitRequest; m_ddsHandler->ftcTab()->demandInitRequest(demandInitRequest, this); } } } // namespace CES_FUNCTIONAL_AREA