/** * Handler for all exercise objects * $Id$ * $HeadURL$ * $Author$ * Created by Hanna E. Rathje, SLSE, 2015-09-03 */ #include "handler_bccontamination.h" #include "handler_danger_area.h" #include "Utils/polygons.h" namespace AreaEffectSimulation { HandlerBCContamination::HandlerBCContamination(MainHandler *mainHandler) : HandlerBaseTmpl(mainHandler, QStringLiteral("BCContamination"), s_areaCount[AesType::AtBCContamination], s_areaCountCentral[AesType::AtBCContamination]) , Interface::Fts::BCContaminationModifyRequestHandler(mainHandler->dds()->fts()) , Interface::Fts::BCContaminationRemoveRequestHandler(mainHandler->dds()->fts()) {} bool HandlerBCContamination::init() { bool bRet = true; auto cb = [this, &bRet] (const Database::AesBCContamination &data) { ERROR_LOG(m_logger) << "TotalC: " << totalAreasCentral() << " Total: " << totalAreas(); ObjectBCContamination *ifs(new ObjectBCContamination(m_mainHandler, this)); connect(ifs, &ObjectBCContamination::effectStateChanged, this, &HandlerBCContamination::onEffectStateChanged); connect(ifs, &ObjectBCContamination::changedToCentral, this, &HandlerBCContamination::onChangedToCentral); Core::FunctionReplyObject ret = ifs->createObject(data); if (ret.error()) { delete ifs; ERROR_LOG(m_logger) << ret(); bRet = false; return; } if(!ifs->data().isCentral) { if (totalAreas() >= (s_maxActiveAreas[AesType::AtBCContamination] + s_maxActiveAreas[AesType::AtNContamination])) { ERROR_LOG(m_logger) << "More active bc contaminationsin database than allowed - ignoring the rest!"; ifs->removeObject(); delete ifs; return; } } else { if (totalAreasCentral() >= (s_maxActiveAreasCentral[AesType::AtBCContamination] + s_maxActiveAreasCentral[AesType::AtNContamination])) { ERROR_LOG(m_logger) << "More active bc contaminationsin database than allowed - ignoring the rest!"; ifs->removeObject(); delete ifs; return; } } m_objectMap.insert(ifs->id(), ifs); connect(ifs, &ObjectBCContamination::newAiv, this, &HandlerBCContamination::newAiv); connect(ifs, &ObjectBCContamination::removeAiv, this, &HandlerBCContamination::removeAiv); if (ifs->isObjectInTrainingArea()) { if (ifs->data().isCentral) ++m_areaCountCentral; else ++m_areaCount; } }; if (!m_mainHandler->db()->select(cb) || !bRet) { ERROR_LOG(m_logger) << "Error reading data from database!"; return true; } DEBUG_LOG(m_logger) << "m_exeObjMap.size() = " << m_objectMap.size(); DEBUG_LOG(m_logger) << "m_areaCount = " << m_areaCount; DEBUG_LOG(m_logger) << "m_areaCountCentral = " << m_areaCountCentral; return true; } int HandlerBCContamination::totalAreas() const { return s_areaCount[AesType::AtBCContamination] + s_areaCount[AesType::AtNContamination]; } int HandlerBCContamination::totalAreasCentral() const { return s_areaCountCentral[AesType::AtBCContamination] + s_areaCountCentral[AesType::AtNContamination]; } void HandlerBCContamination::onChangedToCentral() { s_areaCount[AesType::AtBCContamination]--; s_areaCountCentral[AesType::AtBCContamination]++; DEBUG_LOG(m_logger) << "m_areaCount after Recount = " << m_areaCount; DEBUG_LOG(m_logger) << "m_areaCountCentral after Recount = " << m_areaCountCentral; } static void fillData(const BCContaminationModifyRequest &src, Database::AesBCContamination &dst) { if (src.id() < 0) // is the id given as negative? set id -> used by OC-laptop dst.id = src.id(); dst.name = QString::fromStdString(src.name()); dst.effectStart = src.effectStart().is_set() && src.effectStart().get() > 0 ? QDateTime::fromMSecsSinceEpoch(src.effectStart().get()) : QDateTime(); dst.effectDuration = src.effectDuration(); dst.impactPosition.rx() = src.impactPosition().lon(); dst.impactPosition.ry() = src.impactPosition().lat(); dst.impactRadius = src.impactRadius(); dst.partyId = src.partyId().is_set() ? src.partyId().get() : 0; dst.chargeTypeId = src.chargeTypeId(); dst.participantId = src.participantId().is_set() ? src.participantId().get() : 0; dst.weatherSourceId = src.weatherSource(); dst.externalId = src.externalId().is_set() ? src.externalId().get() : 0; dst.upperOffset = src.upperOffset(); dst.lowerOffset = src.lowerOffset(); // weather parameter are delivered, when adding in OC-laptop if (src.weatherPosition().is_set()) { dst.weatherPosition.rx() = src.weatherPosition().get().lon(); dst.weatherPosition.ry() = src.weatherPosition().get().lat(); } else dst.weatherPosition = dst.impactPosition; // initial, is not used during update therefore it's ok here if(src.windSpeed().is_set()) dst.windSpeed = src.windSpeed().get(); if(src.propagationDirection().is_set()) dst.propagationDirection = src.propagationDirection().get(); if(src.weatherTimestamp().is_set()) dst.weatherTimestamp = QDateTime::fromMSecsSinceEpoch(src.weatherTimestamp().get()); else if(src.effectStart().is_set()) dst.weatherTimestamp = QDateTime::fromMSecsSinceEpoch(src.effectStart().get()); } void HandlerBCContamination::onBCContaminationModifyRequest(const rti::core::SampleIdentity &cookie, const BCContaminationModifyRequest &request) { DEBUG_LOG(m_logger) << "onBCContaminationModifyRequest: " << request; const Core::FunctionReplyObject ret = bCContaminationModifyRequest(request); if (ret.error()) WARNING_LOG(m_logger) << ret(); m_mainHandler->dds()->fts()->bCContaminationModifyReply(cookie, ret); } Core::FunctionReplyObject HandlerBCContamination::bCContaminationCreateRequest(const BCContaminationModifyRequest &request) { Database::AesBCContamination newData; fillData(request, newData); ObjectBCContamination *ifs(new ObjectBCContamination(m_mainHandler, this)); connect(ifs, &ObjectBCContamination::effectStateChanged, this, &HandlerBCContamination::onEffectStateChanged); Core::FunctionReplyObject ret = ifs->createObject(newData); if (ret.error()) { delete ifs; return ret; } ERROR_LOG(m_logger) << "Is Central: " << ifs->data().isCentral << " upperOffset=" << ifs->data().upperOffset << " lowerOffset=" << ifs->data().lowerOffset; if (ifs->data().isCentral) { if (totalAreasCentral() >= (s_maxActiveAreasCentral[AesType::AtBCContamination] + s_maxActiveAreasCentral[AesType::AtNContamination]) && request.effectStart().is_set()) { ifs->removeObject(); //Not finally deleted from db after this,Fallback if DB deletion is not working correct ifs->removeObjectFromDb(); delete ifs; return Core::FunctionReplyObject(1, tr_lts("dds", "Too many active central B/C or N contamination areas.")); } } else { if (totalAreas() >= (s_maxActiveAreas[AesType::AtBCContamination] + s_maxActiveAreas[AesType::AtNContamination]) && request.effectStart().is_set()) { ifs->removeObject(); //Not finally deleted from db after this,Fallback if DB deletion is not working correct ifs->removeObjectFromDb(); delete ifs; return Core::FunctionReplyObject(1, tr_lts("dds", "Too many active B/C or N contamination areas.")); } } connect(ifs, &ObjectBCContamination::newAiv, this, &HandlerBCContamination::newAiv); connect(ifs, &ObjectBCContamination::removeAiv, this, &HandlerBCContamination::removeAiv); if (ifs->data().isCentral) { ++m_areaCountCentral; DEBUG_LOG(m_logger) << "s_areaCountCentral[AesType::AtBCContamination] = " << m_areaCountCentral; } else if (ifs->isObjectInTrainingArea()) { ++m_areaCount; DEBUG_LOG(m_logger) << "s_areaCount[AesType::AtBCContamination] = " << m_areaCount; } else { DEBUG_LOG(m_logger) << "Counting of [AesType::AtBCContamination] not affected"; } m_objectMap.insert(ifs->id(), ifs); if (request.withDangerArea().is_set() && request.withDangerArea().get()) { DangerAreaModifyRequest req; req.id(0); #ifdef GUEZ_MODE const QString name = QString::fromStdString(tr_lts("dds","%1 - Gefahrenbereich")).arg(ifs->data().name); #else const QString name = QString::fromStdString(tr_lts("dds","%1 - Danger Area")).arg(ifs->data().name); #endif req.name(name.toStdString()); req.partyId(ifs->data().partyId); req.effectDuration(ifs->data().effectDuration); req.chargeTypeId(ifs->data().chargeTypeId); req.segments(Polygons::dangerAreaDefaultSegments(ifs->data().impactPosition, ifs->data().impactRadius + 50)); req.associatedAesId(ifs->data().id); if(ifs->data().effectStart.isValid()) req.effectStart(ifs->data().effectStart.toMSecsSinceEpoch()); Core::FunctionReplyObject bretDangerArea= m_mainHandler->dangerAreaHandler()->dangerAreaCreateRequest(req); if (bretDangerArea.error()) ERROR_LOG(m_logger)<<"Couldn't create associated dangerArea to bcContamination: "<data().name; } return ret; } Core::FunctionReplyObject HandlerBCContamination::bCContaminationModifyRequest(const BCContaminationModifyRequest &request) { Core::FunctionReplyObject ret; ObjectBCContamination *ifs = nullptr; if (request.externalId().is_set() && request.externalId().get() > 0) ifs = getObjectFromMapByExternalId(m_objectMap, request.externalId().get(), ret); if (!ifs) { if (request.id() == 0 || ((request.id() < 0) && !getObjectFromMap(m_objectMap, std::abs(request.id()), ret))) return bCContaminationCreateRequest(request); ifs = getObjectFromMap(m_objectMap, std::abs(request.id()), ret); if (!ifs) return ret; } if (request.effectStart().is_set() && (request.effectStart().get() + request.effectDuration() < m_mainHandler->dds()->currentPartitionTime().toMSecsSinceEpoch())) return removeObject(ifs); Database::AesBCContamination aea(ifs->data()); fillData(request, aea); DEBUG_LOG(m_logger) << "request.upperOffset=" << request.upperOffset() << " request.lowerOffset=" << request.lowerOffset() << " aea.upperOffset=" << aea.upperOffset << " aea.lowerOffset=" << aea.lowerOffset; // Calculate new polygon here. Not nice, though auto poly = Polygons::bcContamination(aea, m_mainHandler->dds()->pdmDtc()->volatilityTypeId(aea.chargeTypeId, aea.igniterTypeId, aea.igniterFunctionId), m_mainHandler->dds()->pdmDtc()->expansionFactor(aea.chargeTypeId, aea.igniterTypeId, aea.igniterFunctionId), m_mainHandler->dds()->currentPartitionTime()); std::vector _form; ObjectBase::ddsVecFromPoly(poly, _form); bool isCentral = ifs->checkIsCentral(_form); bool wasCentral = ifs->data().isCentral; /*! * If the effect start added after creation, the max amount need to be checked */ if(!ifs->isActivationTimeSet() && request.effectStart().is_set()) { if (isCentral) { if (totalAreasCentral() >= (s_maxActiveAreasCentral[AesType::AtBCContamination] + s_maxActiveAreasCentral[AesType::AtNContamination]) /*&& request.effectStart().is_set()*/) { return Core::FunctionReplyObject(1, tr_lts("dds", "Too many active central B/C or N contamination areas.")); } } else { if (totalAreas() >= (s_maxActiveAreas[AesType::AtBCContamination] + s_maxActiveAreas[AesType::AtNContamination]) /*&& request.effectStart().is_set()*/) { return Core::FunctionReplyObject(1, tr_lts("dds", "Too many active B/C or N contamination areas.")); } } } // For counting, only Elements being at least prepared are important: if (request.effectStart().is_set() && ifs->isObjectModifiable()) { DEBUG_LOG(m_logger) << "isCentral: " << isCentral; DEBUG_LOG(m_logger) << "wasCentral: " << wasCentral; // only change if element changed from central to training area or vice versa if ((isCentral != wasCentral)) { // Change from central to training area if (wasCentral) { if (totalAreas() >= (s_maxActiveAreas[AesType::AtBCContamination] + s_maxActiveAreas[AesType::AtNContamination])) return Core::FunctionReplyObject(request.id(), tr_lts("dds", "Too many active B/C or N contamination areas.")); m_areaCount++; m_areaCountCentral--; DEBUG_LOG(m_logger) << "s_areaCount[AesType::AtBCContamination] = " << m_areaCount; DEBUG_LOG(m_logger) << "s_areaCountCentral[AesType::AtBCContamination] = " << m_areaCountCentral; } else // Change from training area to central { if (totalAreasCentral() >= (s_maxActiveAreasCentral[AesType::AtBCContamination] + s_maxActiveAreasCentral[AesType::AtNContamination])) return Core::FunctionReplyObject(request.id(), tr_lts("dds", "Too many active central B/C or N contamination areas.")); m_areaCount--; m_areaCountCentral++; DEBUG_LOG(m_logger) << "s_areaCount[AesType::AtBCContamination] = " << m_areaCount; DEBUG_LOG(m_logger) << "s_areaCountCentral[AesType::AtBCContamination] = " << m_areaCountCentral; } } } if (request.id() < 0 && checkStateForSfm(ifs)) { DEBUG_LOG(m_logger) << "Overwrite bc contamination Effect State for OC"; aea.effectStateId = AesEffectState::EsPrepared; } ret = ifs->updateObject(aea); // check / update danger area if(!ret.error()) { Database::AesDangerArea dangerArea; if (m_mainHandler->dangerAreaHandler()->getDangerAreaByAssociatedAesId(ifs->id(), &dangerArea)) { DEBUG_LOG(m_logger)<<"[bCContaminationModifyRequest] modify danger area associated to bcId: " <id() <<" dangerAreaId: "<data().impactPosition, ifs->data().impactRadius + 50)); dangerRequest.associatedAesId(ifs->data().id); if(ifs->data().effectStart.isValid()) dangerRequest.effectStart(ifs->data().effectStart.toMSecsSinceEpoch()); Core::FunctionReplyObject bretDangerArea= m_mainHandler->dangerAreaHandler()->dangerAreaModifyRequest(dangerRequest); if (bretDangerArea.error()) ERROR_LOG(m_logger)<<"[bCContaminationModifyRequest] couldn't update danger area: bccontamination.id: "<id() <<" dangerArea.name: "<id(); DangerAreaModifyRequest newDangerRequest; newDangerRequest.id(0); #ifdef GUEZ_MODE const QString name = QString::fromStdString(tr_lts("dds","%1 - Gefahrenbereich")).arg(ifs->data().name); #else const QString name = QString::fromStdString(tr_lts("dds","%1 - Danger Area")).arg(ifs->data().name); #endif newDangerRequest.name(name.toStdString()); newDangerRequest.partyId(ifs->data().partyId); newDangerRequest.effectDuration(ifs->data().effectDuration); newDangerRequest.chargeTypeId(ifs->data().chargeTypeId); newDangerRequest.segments(Polygons::dangerAreaDefaultSegments(ifs->data().impactPosition, ifs->data().impactRadius + 50)); newDangerRequest.associatedAesId(ifs->data().id); if(ifs->data().effectStart.isValid()) newDangerRequest.effectStart(ifs->data().effectStart.toMSecsSinceEpoch()); Core::FunctionReplyObject bretDangerArea = m_mainHandler->dangerAreaHandler()->dangerAreaCreateRequest(newDangerRequest); if (bretDangerArea.error()) ERROR_LOG(m_logger)<<"[bCContaminationModifyRequest] couldn't add danger area: bccontamination.id: "<id() <<" dangerArea.name: "<dds()->fts()->bCContaminationRemoveReply(cookie, removeReply(&DatabaseInterface::removeAesBCContamination, request)); // remove if dangerarea is associated if (ret) { Database::AesDangerArea dangerArea; if (m_mainHandler->dangerAreaHandler()->getDangerAreaByAssociatedAesId(request.id(), &dangerArea)) { bool bret = m_mainHandler->dangerAreaHandler()->dangerAreaRemoveRequest(Core::RemoveElementRequest(dangerArea.id)); if (!bret) ERROR_LOG(m_logger)<<"[onBCContaminationRemoveRequest] couldn't remove danger area: "<