/** * Handler for all exercise objects * $Id$ * $HeadURL$ * $Author$ * Created by Hanna E. Rathje, SLSE, 2015-09-03 */ #include "handler_ncontamination.h" #include "Utils/polygons.h" #include namespace AreaEffectSimulation { HandlerNContamination::HandlerNContamination(MainHandler *mainHandler) : HandlerBaseTmpl(mainHandler, QStringLiteral("NContamination"), s_areaCount[AesType::AtNContamination], s_areaCountCentral[AesType::AtNContamination]) , Interface::Fts::NContaminationModifyRequestHandler(mainHandler->dds()->fts()) , Interface::Fts::NContaminationRemoveRequestHandler(mainHandler->dds()->fts()) {} bool HandlerNContamination::init() { QVector dataVec; // read all NContaminations from database if (!m_mainHandler->db()->select(dataVec)) { ERROR_LOG(m_logger) << "Error reading data from database!"; return true; } DEBUG_LOG(m_logger) << "TotalC: " << totalAreasCentral() << " Total: " << totalAreas(); for (const Database::AesNContamination &dbData : qAsConst(dataVec)) { ObjectNContamination *ifs(new ObjectNContamination(m_mainHandler, this)); connect(ifs, &ObjectNContamination::effectStateChanged, this, &HandlerNContamination::onEffectStateChanged); connect(ifs, &ObjectNContamination::changedToCentral, this, &HandlerNContamination::onChangedToCentral); Core::FunctionReplyObject ret = ifs->createObject(dbData); if (ret.error()) { delete ifs; ERROR_LOG(m_logger) << ret(); return false; } if(!ifs->data().isCentral) { if (totalAreas() >= (s_maxActiveAreas[AesType::AtBCContamination] + s_maxActiveAreas[AesType::AtNContamination])) { ERROR_LOG(m_logger) << "More active n contaminations in database than allowed - ignoring the rest!"; ifs->removeObject(); delete ifs; continue; } } else { if (totalAreasCentral() >= (s_maxActiveAreasCentral[AesType::AtBCContamination] + s_maxActiveAreasCentral[AesType::AtNContamination])) { ERROR_LOG(m_logger) << "More active n contaminations in database than allowed - ignoring the rest!"; ifs->removeObject(); delete ifs; continue; } } if (ifs->isObjectInTrainingArea()) { if (ifs->data().isCentral) ++m_areaCountCentral; else ++m_areaCount; } m_objectMap.insert(ifs->id(), ifs); connect(ifs, &ObjectNContamination::newAiv, this, &HandlerNContamination::newAiv); connect(ifs, &ObjectNContamination::removeAiv, this, &HandlerNContamination::removeAiv); } DEBUG_LOG(m_logger) << "m_exeObjMap.size() = " << m_objectMap.size(); return true; } int HandlerNContamination::totalAreas() const { return s_areaCount[AesType::AtBCContamination] + s_areaCount[AesType::AtNContamination]; } int HandlerNContamination::totalAreasCentral() const { return s_areaCountCentral[AesType::AtBCContamination] + s_areaCountCentral[AesType::AtNContamination]; } void HandlerNContamination::onChangedToCentral() { s_areaCount[AesType::AtNContamination]--; s_areaCountCentral[AesType::AtNContamination]++; DEBUG_LOG(m_logger) << "m_areaCount after Recount = " << m_areaCount; DEBUG_LOG(m_logger) << "m_areaCountCentral after Recount = " << m_areaCountCentral; } static void fillData(const NContaminationModifyRequest &src, Database::AesNContamination &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.borderLengthInner = src.borderLengthInner(); dst.borderLengthOuter = src.borderLengthOuter(); dst.spanAngle = src.spanAngle(); dst.rotationAngle = src.rotationAngle(); dst.detonationValue = src.detonationValue(); 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.externalId = src.externalId().is_set() ? src.externalId().get() : 0; dst.weatherSourceId = src.weatherSource(); } void HandlerNContamination::onNContaminationModifyRequest(const rti::core::SampleIdentity &cookie, const NContaminationModifyRequest &request) { DEBUG_LOG(m_logger) << "onNContaminationModifyRequest: " << request; const Core::FunctionReplyObject ret = nContaminationModifyRequest(request); if (ret.error()) WARNING_LOG(m_logger) << ret(); m_mainHandler->dds()->fts()->nContaminationModifyReply(cookie, ret); } Core::FunctionReplyObject HandlerNContamination::nContaminationCreateRequest(const NContaminationModifyRequest &request) { Database::AesNContamination newData; fillData(request, newData); // check: effectStart > time(NULL) ? ObjectNContamination *ifs(new ObjectNContamination(m_mainHandler, this)); connect(ifs, &ObjectNContamination::effectStateChanged, this, &HandlerNContamination::onEffectStateChanged); Core::FunctionReplyObject ret = ifs->createObject(newData); if (ret.error()) { delete ifs; return ret; } if (ifs->data().isCentral) { if (totalAreasCentral() >= (s_maxActiveAreasCentral[AesType::AtNContamination] + s_maxActiveAreasCentral[AesType::AtBCContamination]) && 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 N or B/C contamination areas.")); } } else { if (totalAreas() >= (s_maxActiveAreas[AesType::AtNContamination] + s_maxActiveAreas[AesType::AtBCContamination]) && 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 N or B/C contamination areas.")); } } 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::AtNContamination] = " << m_areaCount; } m_objectMap.insert(ifs->id(), ifs); connect(ifs, &ObjectNContamination::newAiv, this, &HandlerNContamination::newAiv); connect(ifs, &ObjectNContamination::removeAiv, this, &HandlerNContamination::removeAiv); return ret; } Core::FunctionReplyObject HandlerNContamination::nContaminationModifyRequest(const NContaminationModifyRequest &request) { Core::FunctionReplyObject ret; if (request.id() == 0 || ((request.id() < 0) && !getObjectFromMap(m_objectMap, std::abs(request.id()), ret))) return nContaminationCreateRequest(request); ObjectNContamination *ifs = getObjectFromMap(m_objectMap, std::abs(request.id()), ret); if (!ifs) return ret; // Anzahl aktiver Areas ist erreicht, der Wirkbeginn ist (soll) gesetzt sein, aber die Area war // vorher noch ohne Wirkbeginn // if (totalAreas() >= (s_maxActiveAreas[AesType::AtBCContamination] + s_maxActiveAreas[AesType::AtNContamination]) && request.effectStart().is_set() && !ifs->isObjectModifiable()) // return Core::FunctionReplyObject(request.id(), tr_lts("dds", "Too many active N contamination areas.")); Database::AesNContamination aea(ifs->data()); fillData(request, aea); // Calculate new polygon here. Not nice, though auto poly = Polygons::nContamination(aea); 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::AtNContamination] + s_maxActiveAreasCentral[AesType::AtBCContamination]) /*&& request.effectStart().is_set()*/) { return Core::FunctionReplyObject(1, tr_lts("dds", "Too many active central N or B/C contamination areas.")); } } else { if (totalAreas() >= (s_maxActiveAreas[AesType::AtNContamination] + s_maxActiveAreas[AesType::AtBCContamination]) /*&& request.effectStart().is_set()*/) // upper if-condition handle start-time { return Core::FunctionReplyObject(1, tr_lts("dds", "Too many active N or B/C 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 N or B/C 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 N or B/C 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 n contamination Effect State for OC"; aea.effectStateId = AesEffectState::EsPrepared; } return ifs->updateObject(aea); } void HandlerNContamination::onNContaminationRemoveRequest(const rti::core::SampleIdentity &cookie, const Core::RemoveElementRequest &request) { m_mainHandler->dds()->fts()->nContaminationRemoveReply(cookie, removeReply(&DatabaseInterface::removeAesNContamination, request)); } } // Namespace AreaEffectSimulation