/** * Handler for all exercise objects * $Id$ * $HeadURL$ * $Author$ * Created by Hanna E. Rathje, SLSE, 2015-09-03 */ #include "handler_booby_trap.h" #include "Utils/polygons.h" #include namespace AreaEffectSimulation { HandlerBoobyTrap::HandlerBoobyTrap(MainHandler *mainHandler) : HandlerBaseTmpl(mainHandler, QStringLiteral("BoobyTrap"), s_areaCount[AesType::AtBoobyTrap], s_areaCountCentral[AesType::AtBoobyTrap]) , Interface::Fts::BoobyTrapModifyRequestHandler(mainHandler->dds()->fts()) , Interface::Fts::BoobyTrapRemoveRequestHandler(mainHandler->dds()->fts()) , Interface::Fts::BoobyTrapTriggerRequestHandler(mainHandler->dds()->fts()) {} bool HandlerBoobyTrap::init() { bool bRet = true; auto cb = [this, &bRet] (const Database::AesBoobyTrap &data) { ObjectBoobyTrap *ifs(new ObjectBoobyTrap(m_mainHandler, this)); connect(ifs, &ObjectBoobyTrap::effectStateChanged, this, &HandlerBoobyTrap::onEffectStateChanged); Core::FunctionReplyObject ret = ifs->createObject(data); if (ret.error()) { delete ifs; ERROR_LOG(m_logger) << ret(); bRet = false; return; } if (totalAreasCentral() >= s_maxActiveAreasCentral[AesType::AtBoobyTrap] ) { ERROR_LOG(m_logger) << "More active booby traps in database than allowed - ignoring the rest!"; ifs->removeObject(); delete ifs; return; } m_objectMap.insert(ifs->id(), ifs); connect(ifs, &ObjectBoobyTrap::newAiv, this, &HandlerBoobyTrap::newAiv); connect(ifs, &ObjectBoobyTrap::removeAiv, this, &HandlerBoobyTrap::removeAiv); if (ifs->isObjectInTrainingArea()) { ++m_areaCountCentral; DEBUG_LOG(m_logger) << "s_areaCount[AesType::AtBCContamination] = " << 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(); return true; } int HandlerBoobyTrap::totalAreas() const { return s_areaCount[AesType::AtBoobyTrap]; } int HandlerBoobyTrap::totalAreasCentral() const { return s_areaCountCentral[AesType::AtBoobyTrap]; } static void fillData(const BoobyTrapModifyRequest &src, Database::AesBoobyTrap &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.externalId = src.externalId().is_set() ? src.externalId().get() : 0; dst.triggerRadius = src.triggerRadius(); dst.rotationAngle = src.rotationAngle().is_set() ? src.rotationAngle().get() : 0; dst.centralAngle = src.centralAngle().is_set() ? src.centralAngle().get() : 0; dst.isCentral = true; dst.triggered = false; } void HandlerBoobyTrap::onBoobyTrapModifyRequest(const rti::core::SampleIdentity &cookie, const BoobyTrapModifyRequest &request) { DEBUG_LOG(m_logger) << "onBoobyTrapModifyRequest: " << request; const Core::FunctionReplyObject ret = boobyTrapModifyRequest(request); if (ret.error()) WARNING_LOG(m_logger) << ret(); m_mainHandler->dds()->fts()->boobyTrapModifyReply(cookie, ret); } Core::FunctionReplyObject HandlerBoobyTrap::boobyTrapCreateRequest(const BoobyTrapModifyRequest &request) { if (totalAreasCentral() >= (s_maxActiveAreasCentral[AesType::AtBoobyTrap]) && request.effectStart().is_set()) return Core::FunctionReplyObject(1, tr_lts("dds", "Too many active booby traps.")); Database::AesBoobyTrap newData; fillData(request, newData); ObjectBoobyTrap *ifs(new ObjectBoobyTrap(m_mainHandler, this)); connect(ifs, &ObjectBoobyTrap::effectStateChanged, this, &HandlerBoobyTrap::onEffectStateChanged); Core::FunctionReplyObject ret = ifs->createObject(newData); if (ret.error()) { delete ifs; return ret; } connect(ifs, &ObjectBoobyTrap::newAiv, this, &HandlerBoobyTrap::newAiv); connect(ifs, &ObjectBoobyTrap::removeAiv, this, &HandlerBoobyTrap::removeAiv); if (ifs->isObjectInTrainingArea()) { ++m_areaCountCentral; DEBUG_LOG(m_logger) << "s_areaCount[AesType::AtBoobyTrap] = " << m_areaCount; } m_objectMap.insert(ifs->id(), ifs); return ret; } Core::FunctionReplyObject HandlerBoobyTrap::boobyTrapModifyRequest(const BoobyTrapModifyRequest &request) { Core::FunctionReplyObject ret; const QPointF &impactPos = QPointF(request.impactPosition().lon(),request.impactPosition().lat()); // Convert Form to UTM bool isGroundLevel = true; const int exId = m_mainHandler->dds()->exerciseId(); int zone = -1; const auto ¢erPosUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(impactPos,zone); if (m_mainHandler->dds()->ismDtc()->getBuildingIdAtPosition(exId, QPointF(centerPosUtm.x, centerPosUtm.y), isGroundLevel) > 0) { return Core::FunctionReplyObject(1, tr_lts("dds", "The Booby Trap is within a building")); } if (request.id() == 0 || ((request.id() < 0) && !getObjectFromMap(m_objectMap, std::abs(request.id()), ret))) return boobyTrapCreateRequest(request); ObjectBoobyTrap *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); // Anzahl aktiver Areas ist erreicht, der Wirkbeginn ist (soll) gesetzt sein, aber die Area war // vorher noch ohne Wirkbeginn if (totalAreasCentral() >= (s_maxActiveAreasCentral[AesType::AtBoobyTrap]) && request.effectStart().is_set() && !ifs->isActivationTimeSet() /* && !ifs->isObjectModifiable()*/) return Core::FunctionReplyObject(request.id(), tr_lts("dds", "Too many active booby traps.")); Database::AesBoobyTrap aea(ifs->data()); fillData(request, aea); if (request.id() < 0 && checkStateForSfm(ifs)) { DEBUG_LOG(m_logger) << "Overwrite booby trap Effect State for OC"; aea.effectStateId = AesEffectState::EsPrepared; } return ifs->updateObject(aea); } void HandlerBoobyTrap::onBoobyTrapRemoveRequest(const rti::core::SampleIdentity &cookie, const Core::RemoveElementRequest &request) { m_mainHandler->dds()->fts()->boobyTrapRemoveReply(cookie, removeReply(&DatabaseInterface::removeAesBoobyTrap, request)); } void HandlerBoobyTrap::onBoobyTrapTriggerRequest(const rti::core::SampleIdentity &cookie, const BoobyTrapTriggerRequest &request) { DEBUG_LOG(m_logger) << "onBoobyTrapTriggerRequest: " << request; const Core::FunctionReplyObject ret = boobyTrapTriggerRequest(request); if (ret.error()) WARNING_LOG(m_logger) << ret(); m_mainHandler->dds()->fts()->boobyTrapTriggerReply(cookie, ret); } Core::FunctionReplyObject HandlerBoobyTrap::boobyTrapTriggerRequest(const BoobyTrapTriggerRequest &request) { Core::FunctionReplyObject ret; ObjectBoobyTrap *ifs = getObjectFromMap(m_objectMap, request.id(), ret); if (!ifs) return ret; Database::AesBoobyTrap aea(ifs->data()); DEBUG_LOG(m_logger) << "Overwrite booby trap Effect State to expired"; aea.effectStateId = AesEffectState::EsExpired; aea.triggered = request.triggered(); aea.effectDuration = aea.effectStart.msecsTo(QDateTime::currentDateTimeUtc()); if (aea.effectDuration < 0) aea.effectDuration = 1; return ifs->updateObject(aea); } } // Namespace AreaEffectSimulation