/** * Handler for the HMI language * $Id$ * $HeadURL$ * $Author$ */ #include "object_off_route_mine.h" #include "meteo_data_provider.h" #include "Utils/polygons.h" #include #include #include namespace AreaEffectSimulation { ObjectOffRouteMine::ObjectOffRouteMine(MainHandler *mainHandler, QObject *parent) : ObjectBaseTmpl(mainHandler, QStringLiteral("OffRouteMine"), parent) , m_aivUpdateTimer(new QTimer(this)) { m_aivUpdateTimer->setInterval(1 * 1000); // every second - really needed? m_aivUpdateTimer->setTimerType(Qt::VeryCoarseTimer); connect(m_aivUpdateTimer, &QTimer::timeout, this, &ObjectOffRouteMine::onUpdateAiv); } ObjectOffRouteMine::~ObjectOffRouteMine() { removeTopics(); } Core::FunctionReplyObject ObjectOffRouteMine::createObject(const Database::AesOffRouteMine &data) { return ObjectBaseTmpl::createObject(data); } Core::FunctionReplyObject ObjectOffRouteMine::updateObject(const Database::AesOffRouteMine &data) { Core::FunctionReplyObject ret = ObjectBaseTmpl::updateObject(data); Database::AesOffRouteMine tmpData(m_data); if (ret.error()) return ret; if (data.triggered && !m_data.triggered) { tmpData.triggered = data.triggered; tmpData.effectStateId = data.effectStateId; tmpData.effectDuration = data.effectDuration; tmpData.properties = data.properties; } else if (isOnlyObjectNameModifiable() && (data.id > 0)) // data.id > 0 -> negative values from oc always get a full update) return ret; else { // only allow some fields tmpData.id = std::abs(data.id); tmpData.name = data.name; tmpData.effectStart = data.effectStart; tmpData.effectDuration = data.effectDuration; tmpData.impactPosition = data.impactPosition; tmpData.impactRadius = data.impactRadius; // 2023/08, N. Thoden: add width,length tmpData.width = data.width; tmpData.length = data.length; // effectMarkingInTa, externalId, isCentral, ... ?? tmpData.rotationAngle = data.rotationAngle; tmpData.participantId = data.participantId; tmpData.partyId = data.partyId; tmpData.chargeTypeId = data.chargeTypeId; tmpData.effectStateId = data.effectStateId; // overwrite for oc tmpData.triggered = data.triggered; tmpData.properties = data.properties; } if (!m_mainHandler->db()->update(tmpData)) return Core::FunctionReplyObject(data.id, tr_lts("dds", "Error updating off route mine with id %1 in database.")).arg(m_data.id); m_data = std::move(tmpData); m_publishDataTimer->start(); checkEnterNewState(); return Core::FunctionReplyObject(data.id); // data not m_data for the possible negative id in the oc-laptop } bool ObjectOffRouteMine::removeObjectFromDb() { return m_mainHandler->db()->removeAesOffRouteMine(m_data.id); } void ObjectOffRouteMine::setEffectState(AesEffectState newState) { if (newState == AesEffectState::EsActivated) { m_aivUpdateTimer->start(); } else m_aivUpdateTimer->stop(); ObjectBaseTmpl::setEffectState(newState); } ProjectDataManagement::VolatilityType ObjectOffRouteMine::volatilityType() const { return m_mainHandler->dds()->pdmDtc()->volatilityTypeId(m_data.chargeTypeId, m_data.igniterTypeId, m_data.igniterFunctionId); } void ObjectOffRouteMine::onUpdateAiv() { if (effectState() != AesEffectState::EsActivated) { m_aivUpdateTimer->stop(); return; } publishAiv(); } void ObjectOffRouteMine::onPublishData() { ObjectBaseTmpl::onPublishData(); if (!m_mainHandler->db()->update(m_data)) ERROR_LOG(m_logger) << "Error updating AesOffRouteMine-data in database"; OffRouteMine ddsData(m_data.id, m_data.name.toStdString(), effectState() == AesEffectState::EsRemoved, false, partitionTimeMSec(), {m_data.chargeTypeId,0,0}, m_data.effectDuration, toOptional(toMSec(m_data.effectStart)), m_data.effectStateId, m_data.effectSourceId, toOptional(m_data.partyId), toOptional(m_data.participantId), m_data.effectMarkingInTa, m_data.externalId, m_data.isCentral, m_data.properties.toStdString(), Area(Core::GeoPosition2D(m_data.impactPosition.x(), m_data.impactPosition.y()), m_data.width, m_data.length, m_data.rotationAngle), toOptional(m_data.impactRadius), m_data.triggered); m_mainHandler->dds()->dts()->publish(ddsData); publishAiv(); } void ObjectOffRouteMine::publishAiv() { // OffRouteMine Trigger { const QPolygonF poly = Polygons::offRouteMineArea(m_data); const QRectF bounds(poly.boundingRect()); AesItemView aiv(m_aiv); aiv.aesItemId(m_data.id); aiv.effectStart(toMSec(m_data.effectStart)); aiv.chargeStruct().chargeTypeId(m_data.chargeTypeId); ddsVecFromPoly(poly, aiv.form()); aiv.boundingBoxBottomLeft(Core::GeoPosition2D(bounds.bottomLeft().x(), bounds.bottomLeft().y())); aiv.boundingBoxTopRight(Core::GeoPosition2D(bounds.topRight().x(), bounds.topRight().y())); aiv.aesTypeId(AesType::AtOffRouteMine); aiv.effectStateId(data().effectStateId); aiv.id(1000 * m_data.id + AesType::AtOffRouteMine); if (m_data.partyId != 0) aiv.partyId(m_data.partyId); if (aiv != m_aiv) { aiv.sampleTime(partitionTimeMSec()); m_aiv = aiv; m_mainHandler->dds()->dts()->publish(aiv); emit newAiv(m_aiv); } } // OffRouteMine Impact if (m_data.impactRadius > 0.0f) { QPolygonF poly = Polygons::offRouteMineAreaImpact(m_data); const QRectF bounds(poly.boundingRect()); AesItemView aiv2(m_aiv2); aiv2.aesItemId(m_data.id); aiv2.effectStart(toMSec(m_data.effectStart)); aiv2.chargeStruct().chargeTypeId(m_data.chargeTypeId); ddsVecFromPoly(poly, aiv2.form()); aiv2.boundingBoxBottomLeft(Core::GeoPosition2D(bounds.bottomLeft().x(), bounds.bottomLeft().y())); aiv2.boundingBoxTopRight(Core::GeoPosition2D(bounds.topRight().x(), bounds.topRight().y())); aiv2.aesTypeId(AesType::AtOffRouteMineSecondary); aiv2.effectStateId(data().effectStateId); aiv2.id(1000 * m_data.id + AesType::AtOffRouteMineSecondary); if (m_data.partyId != 0) aiv2.partyId(m_data.partyId); if (aiv2 != m_aiv2) { aiv2.sampleTime(partitionTimeMSec()); m_aiv2 = aiv2; m_mainHandler->dds()->dts()->publish(aiv2); emit newAiv(aiv2); } } } void ObjectOffRouteMine::removeTopics() { auto dts = m_mainHandler->dds()->dts(); dts->removeOffRouteMineByKey(m_data.id); dts->removeAesItemViewByKey(1000 * m_data.id + AesType::AtOffRouteMine); emit removeAiv(m_data.id); } QPolygonF ObjectOffRouteMine::generateForm() { return QPolygonF(); } } // Namespace AreaEffectSimulation