/** * 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_def::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 + 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 + 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