/** * Borderline object * $Id$ * $HeadURL$ * $Author$ * Created by hjl, SLSE, 2017-06-14 */ #include "object_borderline.h" #include "special_area_provider.h" #include #include namespace AreaEffectSimulation { ObjectBorderline::ObjectBorderline(MainHandler *mainHandler, QObject *parent) : ObjectBaseTmpl(mainHandler, QStringLiteral("Borderline"), parent) { DEBUG_LOG(m_logger) << " Start AreaEffectSimulation ObjectBorderline."; } // end of ctor() //----------------------------------------------------------------------------- ObjectBorderline::~ObjectBorderline() { removeTopics(); } // end of dtor() //----------------------------------------------------------------------------- Core::FunctionReplyObject ObjectBorderline::createObject(const Database::AesBorderline &dbData, const std::vector &ddsSegments, const QVector &dbSegments) { DEBUG_LOG(m_logger) << "createObjectBorderline."; m_data = dbData; m_data.effectStart = partitionTime(); m_data.effectStateId = AreaEffectSimulation::AesEffectState::EsCreated; m_data.effectDuration = 0; m_data.chargeTypeId = 312; // see GearClass 1 -> 'pdm.pdm_charge_type' und 'pdm.pdm_gear_type_charge_type' in insert_pdm_values_xxx.sql if (m_data.id <= 0) // new borderline { DBTransaction trans(m_mainHandler->db()->database()); // Only commit if >nothing< fails if (ddsSegments.size() == 0) return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "Could not create borderline without segments.")); // AesBorderline in db eintragen ) if (!m_mainHandler->db()->insert(m_data)) // incl. insert new id in m_data return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "Error inserting AesBorderline-data into database.")); // AesBorderlineSegment in db eintragen m_dbSegments.reserve(ddsSegments.size()); Database::AesBorderlineSegment dbSegment; for (size_t i = 0; i < ddsSegments.size(); ++i) { dbSegment.id = 0; // Reset for insert. Otherwise second segment cannot be inserted! dbSegment.borderlineId = m_data.privBorderlineId; // db dbSegment.position = QPointF(ddsSegments[i].lon, ddsSegments[i].lat); dbSegment.positionIndex = i; if (!m_mainHandler->db()->insert(dbSegment)) return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "Error inserting AesBorderlineSegment-data into database.")); m_dbSegments.append(dbSegment); } trans.commit(); } else m_dbSegments = dbSegments; // Publish Data via DTS m_publishDataTimer->start(); return Core::FunctionReplyObject(m_data.id); } // end of createObject() //----------------------------------------------------------------------------- Core::FunctionReplyObject ObjectBorderline::updateObject(const Database::AesBorderline &dbData, const std::vector &ddsSegments) { if (ddsSegments.size() == 0) return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "Could not modify AesBorderline without segments.")); DBTransaction trans(m_mainHandler->db()->database()); auto tmpDbData = m_data; // Todo noch weitere noetig ? tmpDbData.name = dbData.name; tmpDbData.operatorId = dbData.operatorId; tmpDbData.partyId = dbData.partyId; auto tmpDbSegments = m_dbSegments; const int newSegmentSize = ddsSegments.size(); // segment count increased for (int i = m_dbSegments.size(); i < newSegmentSize; ++i) { Database::AesBorderlineSegment dbSegment; dbSegment.borderlineId = m_data.privBorderlineId; // db // will update segment.id if (!m_mainHandler->db()->insert(dbSegment)) return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "Error inserting AesBorderlineSegment-data into database.")); tmpDbSegments.append(dbSegment); } // segment count decreased for (int i = newSegmentSize; i < m_dbSegments.size(); ++i) { if (!m_mainHandler->db()->removeAesBorderlineSegment(m_dbSegments.at(i).id)) return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "Error removing AesBorderlineSegment-data into database.")); } tmpDbSegments.resize(newSegmentSize); // if count is decreased // update all segments in tmpDbSegments for (size_t i = 0; i < ddsSegments.size(); ++i) { tmpDbSegments[i].position = QPointF(ddsSegments[i].lon, ddsSegments[i].lat); tmpDbSegments[i].positionIndex = i; } // update all AesBorderlineSegments in database for (const Database::AesBorderlineSegment &segment : qAsConst(tmpDbSegments)) { if (!m_mainHandler->db()->update(segment)) return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "Error updating AesBorderlineSegment-data in database.")); } // update AesBorderline in database if (!m_mainHandler->db()->update(tmpDbData)) return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "Error updating AesBorderline-data id %1 in database.")).arg(m_data.id); trans.commit(); m_data = tmpDbData; m_dbSegments = tmpDbSegments; // Publish Data via DTS m_publishDataTimer->start(); return Core::FunctionReplyObject(m_data.id); } // end of updateObject() //----------------------------------------------------------------------------- Core::FunctionReplyObject ObjectBorderline::removeObject() { Core::FunctionReplyObject ret = ObjectBaseTmpl::removeObject(); if (ret.error()) return ret; // nur wegen db noetig um sie dort als geloescht zu hinterlegen onPublishData(); // DDS topics entfernen, wird zwar auch im dtor gemacht aber so ist es offensichtlicher removeTopics(); return ret; } // end of removeObject() //----------------------------------------------------------------------------- void ObjectBorderline::onPublishData() { INFO_LOG(m_logger) << "Publish Borderline-data to dds for id: " << m_data.id << " effectStateId: " << effectState(); ObjectBaseTmpl::onPublishData(); // Update Sample Time if (!m_mainHandler->db()->update(m_data)) ERROR_LOG(m_logger) << "Error updating AesBorderline-data in database"; AreaEffectSimulation::Borderline ddsData; ddsData.id = m_data.id; ddsData.name = m_data.name.toStdString(); ddsData.operatorId = m_data.operatorId.isNull() ? 0 : m_data.operatorId.toInt(); ddsData.isDeleted = effectState() == AesEffectState::EsRemoved; ddsData.isUsed = false; ddsData.sampleTime = m_mainHandler->dds()->currentPartitionTimeMSec(); ddsData.chargeStruct.chargeTypeId = m_data.chargeTypeId; ddsData.effectDuration = m_data.effectDuration; ddsData.effectStart = toOptional(toMSec(m_data.effectStart)); ddsData.effectStateId = effectState(); ddsData.partyId = toOptional(m_data.partyId); ddsData.participantId = toOptional(m_data.participantId); dbSegment2DdsSegment(m_dbSegments, ddsData.segments); if (!m_mainHandler->dds()->dts()->publish(ddsData)) ERROR_LOG(m_logger) << "Error publishing AesBorderline-data to dds"; publishAiv(); } // end of onPublishData() //----------------------------------------------------------------------------- void ObjectBorderline::publishAiv() { QPolygonF poly(m_dbSegments.size()); qreal y_topRight, y_bottmLeft; for (int i = 0; i < m_dbSegments.size(); ++i) poly[i] = m_dbSegments.at(i).position; AesItemView aiv(m_aiv); aiv.aesItemId = m_data.id; aiv.chargeStruct.chargeTypeId = m_data.chargeTypeId; aiv.effectStart = partitionTimeMSec(); ddsVecFromPoly(poly, aiv.form); const QRectF bounds(poly.boundingRect()); // Hack if (bounds.bottomLeft().y() > bounds.topRight().y() ) { y_bottmLeft = bounds.topRight().y(); y_topRight = bounds.bottomLeft().y(); } else { y_topRight = bounds.topRight().y(); y_bottmLeft = bounds.bottomLeft().y(); } aiv.boundingBoxBottomLeft = Core::GeoPosition2D(bounds.bottomLeft().x(), y_bottmLeft); aiv.boundingBoxTopRight = Core::GeoPosition2D(bounds.topRight().x(), y_topRight); aiv.aesTypeId = AesType::AtBorderline; aiv.effectStateId = effectState(); aiv.id = 1000 * m_data.id + static_cast(AesType::AtBorderline); aiv.partyId = m_data.partyId; checkIsCentralAndPublish(aiv.form, m_aiv.form, m_data.isCentral); if (aiv != m_aiv) { aiv.sampleTime = partitionTimeMSec(); m_aiv = aiv; m_mainHandler->dds()->dts()->publish(aiv); emit newAiv(aiv); } } // end of publishAiv() //----------------------------------------------------------------------------- void ObjectBorderline::removeTopics() { auto dts = m_mainHandler->dds()->dts(); dts->removeBorderlineByKey(m_data.id); dts->removeAesItemViewByKey(1000 * m_data.id + static_cast(AesType::AtBorderline)); } QPolygonF ObjectBorderline::generateForm() { QPolygonF poly(m_dbSegments.size()); for (int i = 0; i < m_dbSegments.size(); ++i) poly[i] = m_dbSegments.at(i).position; return poly; } } // Namespace AreaEffectSimulation