From 48188dd28df6d2004df7aedca30c3b38e7ae4d77 Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Tue, 21 Apr 2015 04:01:09 +0200 Subject: [PATCH] refs #395, moved thread safe aircraft parts / situations (from interpolator) to airspace * access via provider, access now possible also beyond the scope of interpolator * will be used in (to be written airpace analyzer) * renamed some member functions as required * fixed some asserts / Doxygen comments * adjusted unit tests * added vtolAircraft flag for interpolator, not fully used everywhere remarks: update signals for parts / situation still only needed in XP driver --- src/blackcore/airspace_monitor.cpp | 127 ++++++++++----- src/blackcore/airspace_monitor.h | 57 ++++--- src/blackcore/context_network_impl.cpp | 31 ++-- src/blackcore/context_network_impl.h | 26 +-- src/blackcore/interpolator.cpp | 150 +----------------- src/blackcore/interpolator.h | 69 +------- src/blackcore/interpolator_linear.cpp | 37 ++--- src/blackcore/interpolator_linear.h | 2 +- src/blackcore/simulator.cpp | 6 +- .../simulation/remoteaircraftprovider.cpp | 70 +++++--- .../simulation/remoteaircraftprovider.h | 82 ++++++---- .../remoteaircraftproviderdummy.cpp | 26 +-- .../simulation/remoteaircraftproviderdummy.h | 17 +- src/plugins/simulator/fs9/fs9_client.cpp | 6 +- src/plugins/simulator/fsx/simulator_fsx.cpp | 25 ++- .../simulator/xplane/simulator_xplane.cpp | 3 + tests/blackcore/testinterpolator.cpp | 128 +++------------ 17 files changed, 356 insertions(+), 506 deletions(-) diff --git a/src/blackcore/airspace_monitor.cpp b/src/blackcore/airspace_monitor.cpp index c92145db3..d6bd923a4 100644 --- a/src/blackcore/airspace_monitor.cpp +++ b/src/blackcore/airspace_monitor.cpp @@ -77,53 +77,53 @@ namespace BlackCore return m_aircraftInRange; } - const CAircraftSituationList &CAirspaceMonitor::remoteAircraftSituations() const + CAircraftSituationList CAirspaceMonitor::remoteAircraftSituations(const CCallsign &callsign) const { - // not thread safe, check - Q_ASSERT(this->thread() == QThread::currentThread()); - return m_aircraftSituations; + QReadLocker l(&m_lockSituations); + static const CAircraftSituationList empty; + if (!m_situationsByCallsign.contains(callsign)) { return empty; } + return m_situationsByCallsign[callsign]; } - CAircraftSituationList &CAirspaceMonitor::remoteAircraftSituations() + int CAirspaceMonitor::remoteAircraftSituationsCount(const CCallsign &callsign) const { - // not thread safe, check - Q_ASSERT(this->thread() == QThread::currentThread()); - return m_aircraftSituations; + QReadLocker l(&m_lockSituations); + if (!m_situationsByCallsign.contains(callsign)) { return -1; } + return m_situationsByCallsign[callsign].size(); } - CAircraftSituationList CAirspaceMonitor::getRenderedAircraftSituations() const + CAircraftPartsList CAirspaceMonitor::remoteAircraftParts(const CCallsign &callsign, qint64 cutoffTimeValuesBefore) const { - Q_ASSERT(this->thread() == QThread::currentThread()); - return this->m_aircraftSituations; + QReadLocker l(&m_lockParts); + static const CAircraftPartsList empty; + if (!m_partsByCallsign.contains(callsign)) { return empty; } + if (cutoffTimeValuesBefore < 0) + { + return m_partsByCallsign[callsign]; + } + else + { + return m_partsByCallsign[callsign].findBefore(cutoffTimeValuesBefore); + } } - const CAircraftPartsList &CAirspaceMonitor::remoteAircraftParts() const + bool CAirspaceMonitor::isRemoteAircraftSupportingParts(const CCallsign &callsign) const { - // not thread safe, check - Q_ASSERT(this->thread() == QThread::currentThread()); - return m_aircraftParts; + QReadLocker l(&m_lockParts); + return m_aircraftSupportingParts.contains(callsign); } - CAircraftPartsList &CAirspaceMonitor::remoteAircraftParts() + CCallsignSet CAirspaceMonitor::remoteAircraftSupportingParts() const { - // not thread safe, check - Q_ASSERT(this->thread() == QThread::currentThread()); - return m_aircraftParts; - } - - CAircraftPartsList CAirspaceMonitor::getRenderedAircraftParts() const - { - Q_ASSERT(this->thread() == QThread::currentThread()); - return this->m_aircraftParts; + QReadLocker l(&m_lockParts); + return m_aircraftSupportingParts; } bool CAirspaceMonitor::connectRemoteAircraftProviderSignals( std::function situationSlot, std::function partsSlot, - std::function removedAircraftSlot - ) + std::function removedAircraftSlot) { - // bool s1 = connect(this, &CAirspaceMonitor::addedRemoteAircraftSituation, situationSlot); bool s1 = connect(this->m_network, &INetwork::aircraftPositionUpdate, situationSlot); Q_ASSERT(s1); bool s2 = connect(this, &CAirspaceMonitor::addedRemoteAircraftParts, partsSlot); @@ -516,8 +516,16 @@ namespace BlackCore const CCallsign cs(aircraft.getCallsign()); emit removedRemoteAircraft(cs); } - m_aircraftSituations.clear(); - m_aircraftParts.clear(); + + // block for lock scope + { + QWriteLocker l1(&m_lockParts); + QWriteLocker l2(&m_lockSituations); + m_situationsByCallsign.clear(); + m_partsByCallsign.clear(); + m_aircraftSupportingParts.clear(); + } + m_aircraftInRange.clear(); m_flightPlanCache.clear(); m_icaoCodeCache.clear(); @@ -769,8 +777,7 @@ namespace BlackCore Q_ASSERT_X(!callsign.isEmpty(), "ps_aircraftUpdateReceived", "Empty callsign"); // store situation history - this->m_aircraftSituations.push_front(situation); - this->m_aircraftSituations.removeOlderThanNowMinusOffset(AircraftSituationsRemovedOffsetMs); + this->storeAircraftSituation(situation); emit this->addedRemoteAircraftSituation(situation); bool exists = this->m_aircraftInRange.containsCallsign(callsign); @@ -892,15 +899,22 @@ namespace BlackCore void CAirspaceMonitor::ps_pilotDisconnected(const CCallsign &callsign) { Q_ASSERT(BlackCore::isCurrentThreadCreatingThread(this)); - bool contains = this->m_aircraftInRange.containsCallsign(callsign); - // if with contains false remove here, in case of inconsistencies + // in case of inconsistencies I always remove here this->m_aircraftWatchdog.removeCallsign(callsign); this->m_otherClients.removeByCallsign(callsign); - this->m_aircraftSituations.removeByCallsign(callsign); - this->m_aircraftParts.removeByCallsign(callsign); this->removeFromAircraftCaches(callsign); + // block for lock scope + { + QWriteLocker l1(&m_lockParts); + QWriteLocker l2(&m_lockSituations); + m_situationsByCallsign.remove(callsign); + m_partsByCallsign.remove(callsign); + m_aircraftSupportingParts.remove(callsign); + } + + bool contains = this->m_aircraftInRange.containsCallsign(callsign); if (contains) { this->m_aircraftInRange.removeByCallsign(callsign); @@ -938,7 +952,7 @@ namespace BlackCore else { // incremental update - parts = m_aircraftParts.findFirstByCallsign(callsign); + parts = this->remoteAircraftParts(callsign).findFirstByCallsign(callsign); QJsonObject config = applyIncrementalObject(parts.toJson(), jsonObject); parts.convertFromJson(config); } @@ -947,9 +961,8 @@ namespace BlackCore parts.setCurrentUtcTime(); parts.setCallsign(callsign); - // store part history - this->m_aircraftParts.push_front(parts); - this->m_aircraftParts.removeOlderThanNowMinusOffset(AircraftPartsRemoveOffsetMs); + // store part history (parts always absolute) + this->storeAircraftParts(parts); emit this->addedRemoteAircraftParts(parts); // here I expect always a changed value @@ -963,6 +976,40 @@ namespace BlackCore if (!this->m_connected || !m_sendInterimPositions) { return; } CSimulatedAircraftList aircrafts = m_aircraftInRange.findBy(&CSimulatedAircraft::fastPositionUpdates, true); m_network->sendInterimPosition(aircrafts.getCallsigns()); + + void CAirspaceMonitor::storeAircraftSituation(const CAircraftSituation &situation) + { + QWriteLocker lock(&m_lockSituations); + const CCallsign callsign(situation.getCallsign()); + Q_ASSERT_X(!callsign.isEmpty(), "storeAircraftSituation", "empty callsign"); + if (callsign.isEmpty()) { return; } + + // list from new to old + CAircraftSituationList &l = this->m_situationsByCallsign[callsign]; + l.push_frontMaxElements(situation, MaxSituationsPerCallsign); + + // check sort order + Q_ASSERT_X(l.size() < 2 || l[0].getMSecsSinceEpoch() >= l[1].getMSecsSinceEpoch(), "storeAircraftSituation", "wrong sort order"); + } + + void CAirspaceMonitor::storeAircraftParts(const CAircraftParts &parts) + { + QWriteLocker lock(&m_lockParts); + const CCallsign callsign(parts.getCallsign()); + Q_ASSERT_X(!callsign.isEmpty(), "storeAircraftParts", "empty callsign"); + if (callsign.isEmpty()) { return; } + + // list sorted from new to old + CAircraftPartsList &l = this->m_partsByCallsign[callsign]; + l.push_frontMaxElements(parts, MaxPartsPerCallsign); + + if (!m_aircraftSupportingParts.contains(callsign)) + { + m_aircraftSupportingParts.push_back(callsign); // mark as callsign which supports parts + } + + // check sort order + Q_ASSERT_X(l.size() < 2 || l[0].getMSecsSinceEpoch() >= l[1].getMSecsSinceEpoch(), "storeAircraftParts", "wrong sort order"); } } // namespace diff --git a/src/blackcore/airspace_monitor.h b/src/blackcore/airspace_monitor.h index 70259981c..ddd86a7f9 100644 --- a/src/blackcore/airspace_monitor.h +++ b/src/blackcore/airspace_monitor.h @@ -43,25 +43,28 @@ namespace BlackCore //! Constructor CAirspaceMonitor(QObject *parent, const BlackMisc::Simulation::IOwnAircraftProviderReadOnly *ownAircraft, INetwork *network, CVatsimBookingReader *bookings, CVatsimDataFileReader *dataFile); - //! \copydoc IRemoteAircraftProviderReadOnly::renderedAircraft + //! \copydoc IRemoteAircraftProviderReadOnly::remoteAircraft virtual const BlackMisc::Simulation::CSimulatedAircraftList &remoteAircraft() const override; - //! \copydoc IRemoteAircraftProvider::renderedAircraft + //! \copydoc IRemoteAircraftProvider::remoteAircraft virtual BlackMisc::Simulation::CSimulatedAircraftList &remoteAircraft() override; //! \copydoc IRemoteAircraftProvider::remoteAircraftSituations - virtual const BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations() const override; + virtual BlackMisc::Aviation::CAircraftSituationList remoteAircraftSituations(const BlackMisc::Aviation::CCallsign &callsign) const override; - //! \copydoc IRemoteAircraftProvider::remoteAircraftSituations - virtual BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations() override; + //! \copydoc IRemoteAircraftProvider::remoteAircraftSituationsCount + virtual int remoteAircraftSituationsCount(const BlackMisc::Aviation::CCallsign &callsign) const override; //! \copydoc IRemoteAircraftProvider::remoteAircraftParts - virtual const BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts() const override; + virtual BlackMisc::Aviation::CAircraftPartsList remoteAircraftParts(const BlackMisc::Aviation::CCallsign &callsign, qint64 cutoffTimeValuesBefore = -1) const override; - //! \copydoc IRemoteAircraftProvider::remoteAircraftParts - virtual BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts() override; + //! \copydoc IRemoteAircraftProviderReadOnly::isRemoteAircraftSupportingParts + virtual bool isRemoteAircraftSupportingParts(const BlackMisc::Aviation::CCallsign &callsign) const override; - //! \copydoc IRemoteAircraftProvider::remoteAircraftParts + //! \copydoc IRemoteAircraftProviderReadOnly::remoteAircraftSupportingParts + virtual BlackMisc::Aviation::CCallsignSet remoteAircraftSupportingParts() const override; + + //! \copydoc IRemoteAircraftProvider::updateAircraftEnabled virtual bool updateAircraftEnabled(const BlackMisc::Aviation::CCallsign &callsign, bool enabledForRedering, const QString &originator) override; //! \copydoc IRemoteAircraftProvider::updateAircraftModel @@ -116,12 +119,6 @@ namespace BlackCore //! Test injected aircraft parts void testAddAircraftParts(const BlackMisc::Aviation::CAircraftParts &parts, bool incremental); - //! Aircraft situations - virtual BlackMisc::Aviation::CAircraftSituationList getRenderedAircraftSituations() const; - - //! Aircraft parts - virtual BlackMisc::Aviation::CAircraftPartsList getRenderedAircraftParts() const; - //! \copydoc IRemoteAircraftProviderReadOnly::connectSignals //! \copydoc IRemoteAircraftProviderReadOnly::connectSignals virtual bool connectRemoteAircraftProviderSignals( @@ -143,7 +140,7 @@ namespace BlackCore //--- signals for the provider, work locally only (not in DBus) - //! \copydoc IRemoteAircraftProviderReadOnly::addedRemoteAircraftSituation + //! \copydoc IRemoteAircraftProviderReadOnly::addedRemoteAircraftPart void addedRemoteAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation); //! \copydoc IRemoteAircraftProviderReadOnly::addedRemoteAircraftPart @@ -152,6 +149,8 @@ namespace BlackCore //! \copydoc IRemoteAircraftProviderReadOnly::removedAircraft void removedRemoteAircraft(const BlackMisc::Aviation::CCallsign &callsign); + //--- DBus / local signals + //! Online ATC stations were changed void changedAtcStationsOnline(); @@ -175,8 +174,11 @@ namespace BlackCore BlackMisc::Aviation::CAtcStationList m_atcStationsBooked; BlackMisc::Network::CClientList m_otherClients; BlackMisc::Simulation::CSimulatedAircraftList m_aircraftInRange; - BlackMisc::Aviation::CAircraftSituationList m_aircraftSituations; - BlackMisc::Aviation::CAircraftPartsList m_aircraftParts; + + // hashs, because not sorted by key but keeping order + CSituationsPerCallsign m_situationsByCallsign; //!< situations, for performance reasons per callsign + CPartsPerCallsign m_partsByCallsign; //!< parts, for performance reasons per callsign + BlackMisc::Aviation::CCallsignSet m_aircraftSupportingParts; //!< aircraft supporting parts QMap m_metarCache; QMap m_flightPlanCache; @@ -190,8 +192,17 @@ namespace BlackCore bool m_serverSupportsNameQuery = false; //!< not all servers support name query bool m_connected = false; //!< retrieve data bool m_sendInterimPositions = false; + QTimer m_interimPositionUpdateTimer; - QTimer m_interimPositionUpdateTimer; + // locks + mutable QReadWriteLock m_lockSituations; //!< lock for situations + mutable QReadWriteLock m_lockParts; //!< lock for parts + + + // TODO FIXME (MS) should be in INetwork + void sendFsipiCustomPacket(const BlackMisc::Aviation::CCallsign &recipientCallsign) const; + void sendFsipirCustomPacket(const BlackMisc::Aviation::CCallsign &recipientCallsign) const; + QStringList createFsipiCustomPacketData() const; //! Remove ATC online stations void removeAllOnlineAtcStations(); @@ -208,6 +219,14 @@ namespace BlackCore //! Schedule a ready for model matching void fireDelayedReadyForModelMatching(const BlackMisc::Aviation::CCallsign &callsign, int trial = 1, int delayMs = 2500); + //! Store an aircraft situation + //! \threadsafe + void storeAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation); + + //! Store an aircraft part + //! \threadsafe + void storeAircraftParts(const BlackMisc::Aviation::CAircraftParts &parts); + private slots: //! Create aircraft in range, this is the only place where a new aircraft should be added void ps_aircraftUpdateReceived(const BlackMisc::Aviation::CAircraftSituation &situation, const BlackMisc::Aviation::CTransponder &transponder); diff --git a/src/blackcore/context_network_impl.cpp b/src/blackcore/context_network_impl.cpp index 75d74ff3b..f8e56a658 100644 --- a/src/blackcore/context_network_impl.cpp +++ b/src/blackcore/context_network_impl.cpp @@ -78,12 +78,13 @@ namespace BlackCore connect(this->m_airspace, &CAirspaceMonitor::changedAtcStationsBooked, this, &CContextNetwork::changedAtcStationsBooked); connect(this->m_airspace, &CAirspaceMonitor::changedAtcStationOnlineConnectionStatus, this, &CContextNetwork::changedAtcStationOnlineConnectionStatus); connect(this->m_airspace, &CAirspaceMonitor::changedAircraftInRange, this, &CContextNetwork::changedAircraftInRange); - connect(this->m_airspace, &CAirspaceMonitor::removedRemoteAircraft, this, &IContextNetwork::removedAircraft); - connect(this->m_airspace, &CAirspaceMonitor::removedRemoteAircraft, this, &CContextNetwork::removedRemoteAircraft); + connect(this->m_airspace, &CAirspaceMonitor::removedRemoteAircraft, this, &IContextNetwork::removedAircraft); // DBus connect(this->m_airspace, &CAirspaceMonitor::readyForModelMatching, this, &CContextNetwork::readyForModelMatching); - connect(this->m_airspace, &CAirspaceMonitor::addedRemoteAircraftParts, this, &CContextNetwork::addedRemoteAircraftParts); - connect(this->m_airspace, &CAirspaceMonitor::addedRemoteAircraftSituation, this, &CContextNetwork::addedRemoteAircraftSituation); connect(this->m_airspace, &CAirspaceMonitor::addedAircraft, this, &CContextNetwork::addedAircraft); + + // remote provider, local only + connect(this->m_airspace, &CAirspaceMonitor::removedRemoteAircraft, this, &CContextNetwork::removedRemoteAircraft); // Local + connect(this->m_airspace, &CAirspaceMonitor::addedRemoteAircraftParts, this, &CContextNetwork::addedRemoteAircraftParts); } CContextNetwork::~CContextNetwork() @@ -103,28 +104,34 @@ namespace BlackCore return m_airspace->remoteAircraft(); } - CAircraftSituationList &CContextNetwork::remoteAircraftSituations() + CAircraftSituationList CContextNetwork::remoteAircraftSituations(const CCallsign &callsign) const { Q_ASSERT(this->m_airspace); - return m_airspace->remoteAircraftSituations(); + return m_airspace->remoteAircraftSituations(callsign); } - const CAircraftSituationList &CContextNetwork::remoteAircraftSituations() const + CAircraftPartsList CContextNetwork::remoteAircraftParts(const CCallsign &callsign, qint64 cutoffTimeBefore) const { Q_ASSERT(this->m_airspace); - return m_airspace->remoteAircraftSituations(); + return m_airspace->remoteAircraftParts(callsign, cutoffTimeBefore); } - const CAircraftPartsList &CContextNetwork::remoteAircraftParts() const + int CContextNetwork::remoteAircraftSituationsCount(const CCallsign &callsign) const { Q_ASSERT(this->m_airspace); - return m_airspace->remoteAircraftParts(); + return m_airspace->remoteAircraftSituationsCount(callsign); } - CAircraftPartsList &CContextNetwork::remoteAircraftParts() + bool CContextNetwork::isRemoteAircraftSupportingParts(const CCallsign &callsign) const { Q_ASSERT(this->m_airspace); - return m_airspace->remoteAircraftParts(); + return m_airspace->isRemoteAircraftSupportingParts(callsign); + } + + CCallsignSet CContextNetwork::remoteAircraftSupportingParts() const + { + Q_ASSERT(this->m_airspace); + return m_airspace->remoteAircraftSupportingParts(); } bool CContextNetwork::connectRemoteAircraftProviderSignals( diff --git a/src/blackcore/context_network_impl.h b/src/blackcore/context_network_impl.h index 6d9d530b5..9cb062297 100644 --- a/src/blackcore/context_network_impl.h +++ b/src/blackcore/context_network_impl.h @@ -51,23 +51,26 @@ namespace BlackCore //! Destructor virtual ~CContextNetwork(); - //! \copydoc IRemoteAircraftProviderReadOnly::renderedAircraft + //! \copydoc IRemoteAircraftProviderReadOnly::remoteAircraft virtual const BlackMisc::Simulation::CSimulatedAircraftList &remoteAircraft() const override; - //! \copydoc IRenderedAircraftProvider::renderedAircraft + //! \copydoc IRenderedAircraftProvider::remoteAircraft virtual BlackMisc::Simulation::CSimulatedAircraftList &remoteAircraft() override; - //! \copydoc IRemoteAircraftProviderReadOnly::renderedAircraftSituations - virtual const BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations() const override; + //! \copydoc IRemoteAircraftProviderReadOnly::remoteAircraftSituations + virtual BlackMisc::Aviation::CAircraftSituationList remoteAircraftSituations(const BlackMisc::Aviation::CCallsign &callsign) const override; - //! \copydoc IRemoteAircraftProviderReadOnly::renderedAircraftSituations - virtual BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations() override; + //! \copydoc IRemoteAircraftProvider::remoteAircraftSituationsCount + virtual int remoteAircraftSituationsCount(const BlackMisc::Aviation::CCallsign &callsign) const override; - //! \copydoc IRemoteAircraftProviderReadOnly::renderedAircraftParts - virtual const BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts() const override; + //! \copydoc IRemoteAircraftProviderReadOnly::remoteAircraftParts + virtual BlackMisc::Aviation::CAircraftPartsList remoteAircraftParts(const BlackMisc::Aviation::CCallsign &callsign, qint64 cutoffTimeBefore = -1) const override; - //! \copydoc IRenderedAircraftProvider::renderedAircraftParts - virtual BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts() override; + //! \copydoc IRemoteAircraftProviderReadOnly::isRemoteAircraftSupportingParts + virtual bool isRemoteAircraftSupportingParts(const BlackMisc::Aviation::CCallsign &callsign) const; + + //! \copydoc IRemoteAircraftProviderReadOnly::remoteAircraftSupportingParts + virtual BlackMisc::Aviation::CCallsignSet remoteAircraftSupportingParts() const override; //! \copydoc IRemoteAircraftProviderReadOnly::connectSignals virtual bool connectRemoteAircraftProviderSignals( @@ -77,9 +80,6 @@ namespace BlackCore ) override; signals: - //! \copydoc IRemoteAircraftProviderReadOnly::addedRemoteAircraftSituation - void addedRemoteAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation); - //! \copydoc IRemoteAircraftProviderReadOnly::addedRemoteAircraftPart void addedRemoteAircraftParts(const BlackMisc::Aviation::CAircraftParts &parts); diff --git a/src/blackcore/interpolator.cpp b/src/blackcore/interpolator.cpp index bfb18db61..7f3ea6d63 100644 --- a/src/blackcore/interpolator.cpp +++ b/src/blackcore/interpolator.cpp @@ -23,101 +23,18 @@ namespace BlackCore CContinuousWorker(parent, workerName), CRemoteAircraftAwareReadOnly(provider) { - Q_ASSERT(provider); - this->m_situationsByCallsign = this->remoteAircraftSituations().splitPerCallsign(); - this->m_partsByCallsign = this->remoteAircraftParts().splitPerCallsign(); - bool c = provider->connectRemoteAircraftProviderSignals( - std::bind(&IInterpolator::ps_onAddedAircraftSituation, this, std::placeholders::_1), - std::bind(&IInterpolator::ps_onAddedAircraftParts, this, std::placeholders::_1), - std::bind(&IInterpolator::ps_onRemovedAircraft, this, std::placeholders::_1) - ); - Q_ASSERT(c); - Q_UNUSED(c); + Q_ASSERT_X(provider, Q_FUNC_INFO, "missing provider"); } - CAircraftSituationList IInterpolator::getInterpolatedSituations(qint64 currentTimeMsSinceEpoch) - { - QReadLocker l(&m_lockSituations); - const CSituationsPerCallsign situationsCopy(m_situationsByCallsign); - l.unlock(); - - CAircraftSituationList latestInterpolations; - if (currentTimeMsSinceEpoch < 0) { currentTimeMsSinceEpoch = QDateTime::currentMSecsSinceEpoch(); } - for (const CCallsign &cs : situationsCopy.keys()) - { - InterpolationStatus status; - CAircraftSituation situation = getInterpolatedSituation(cs, currentTimeMsSinceEpoch, status, &situationsCopy); - if (status.allTrue()) - { - latestInterpolations.push_back(situation); - } - else - { - // not OK can mean not enough situations - // further logging could go here - } - } - return latestInterpolations; - } - - IInterpolator::CSituationsPerCallsign IInterpolator::getSituationsByCallsign() const - { - QReadLocker l(&m_lockSituations); - return m_situationsByCallsign; - } - - CAircraftPartsList IInterpolator::getAndRemovePartsBeforeTime(const CCallsign &callsign, qint64 cutoffTime, BlackCore::IInterpolator::PartsStatus &partsStatus) + CAircraftPartsList IInterpolator::getPartsBeforeTime(const CCallsign &callsign, qint64 cutoffTime, BlackCore::IInterpolator::PartsStatus &partsStatus) { static const CAircraftPartsList empty; - Q_ASSERT_X(!callsign.isEmpty(), "getAndRemovePartsBeforeTime", "empty callsign"); + Q_ASSERT_X(!callsign.isEmpty(), Q_FUNC_INFO, "empty callsign"); partsStatus.reset(); - QWriteLocker l(&m_lockParts); - if (this->m_partsByCallsign.contains(callsign)) - { - partsStatus.supportsParts = true; - if (cutoffTime < 0) { return this->m_partsByCallsign[callsign]; } - return this->m_partsByCallsign[callsign].findBeforeAndRemove(cutoffTime); - } - else - { - // did we ever have parts for this callsign - partsStatus.supportsParts = m_aircraftSupportingParts.contains(callsign); - return empty; - } - } - void IInterpolator::clear() - { - QWriteLocker s(&m_lockSituations); - QWriteLocker p(&m_lockParts); - m_situationsByCallsign.clear(); - m_partsByCallsign.clear(); - } - - bool IInterpolator::hasDataForCallsign(const CCallsign &callsign) const - { - if (callsign.isEmpty()) { return false; } - QReadLocker s(&m_lockSituations); - if (m_situationsByCallsign.contains(callsign)) { return true; } - - QReadLocker p(&m_lockParts); - return m_partsByCallsign.contains(callsign); - } - - CAircraftSituationList IInterpolator::getSituationsForCallsign(const CCallsign &callsign) const - { - QReadLocker l(&m_lockSituations); - static const CAircraftSituationList empty; - if (!m_situationsByCallsign.contains(callsign)) { return empty; } - return m_situationsByCallsign[callsign]; - } - - CAircraftPartsList IInterpolator::getPartsForCallsign(const CCallsign &callsign) const - { - QReadLocker l(&m_lockParts); - static const CAircraftPartsList empty; - if (!m_partsByCallsign.contains(callsign)) { return empty; } - return m_partsByCallsign[callsign]; + partsStatus.supportsParts = this->isRemoteAircraftSupportingParts(callsign); + if (!partsStatus.supportsParts) { return empty; } + return this->remoteAircraftParts(callsign, cutoffTime); } void IInterpolator::enableDebugMessages(bool enabled) @@ -125,61 +42,6 @@ namespace BlackCore this->m_withDebugMsg = enabled; } - void IInterpolator::forceSortingOfAddedValues(bool sort) - { - this->m_forceSortWhenAddingValues = sort; - } - - void IInterpolator::ps_onAddedAircraftSituation(const CAircraftSituation &situation) - { - QWriteLocker lock(&m_lockSituations); - const CCallsign callsign(situation.getCallsign()); - Q_ASSERT_X(!callsign.isEmpty(), "ps_onAddedAircraftSituation", "empty callsign"); - if (callsign.isEmpty()) { return; } - if (this->m_withDebugMsg) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO << situation.getCallsign() << situation.getMSecsSinceEpoch(); } - - // list from new to old - CAircraftSituationList &l = this->m_situationsByCallsign[callsign]; - l.push_frontMaxElements(situation, MaxSituationsPerCallsign); - if (this->m_forceSortWhenAddingValues) { l.sortLatestFirst(); } - - // check sort order - Q_ASSERT(l.size() < 2 || l[0].getMSecsSinceEpoch() >= l[1].getMSecsSinceEpoch()); - } - - void IInterpolator::ps_onAddedAircraftParts(const CAircraftParts &parts) - { - QWriteLocker lock(&m_lockParts); - const CCallsign callsign(parts.getCallsign()); - Q_ASSERT_X(!callsign.isEmpty(), "ps_onAddedAircraftParts", "empty callsign"); - if (callsign.isEmpty()) { return; } - if (this->m_withDebugMsg) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO << parts.getCallsign() << parts.getMSecsSinceEpoch(); } - - // list sorted from new to old - CAircraftPartsList &l = this->m_partsByCallsign[callsign]; - l.push_frontMaxElements(parts, MaxPartsPerCallsign); - if (this->m_forceSortWhenAddingValues) { l.sortLatestFirst(); } - - if (m_aircraftSupportingParts.contains(callsign)) { return; } - m_aircraftSupportingParts.push_back(callsign); // mark as callsign which supports parts - - // check sort order - Q_ASSERT(l.size() < 2 || l[0].getMSecsSinceEpoch() >= l[1].getMSecsSinceEpoch()); - } - - void IInterpolator::ps_onRemovedAircraft(const CCallsign &callsign) - { - QWriteLocker ls(&m_lockSituations); - QWriteLocker lp(&m_lockParts); - Q_ASSERT(!callsign.isEmpty()); - if (callsign.isEmpty()) { return; } - if (this->m_withDebugMsg) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO << callsign; } - - this->m_partsByCallsign.remove(callsign); - this->m_situationsByCallsign.remove(callsign); - this->m_aircraftSupportingParts.remove(callsign); - } - bool IInterpolator::InterpolationStatus::allTrue() const { return interpolationSucceeded && changedPosition; diff --git a/src/blackcore/interpolator.h b/src/blackcore/interpolator.h index 54ae038ef..c31e289fb 100644 --- a/src/blackcore/interpolator.h +++ b/src/blackcore/interpolator.h @@ -29,12 +29,6 @@ namespace BlackCore Q_OBJECT public: - //! Situations per callsign - typedef QHash CSituationsPerCallsign; - - //! Parts per callsign - typedef QHash CPartsPerCallsign; - //! Virtual destructor virtual ~IInterpolator() {} @@ -70,79 +64,22 @@ namespace BlackCore //! Current interpolated situation //! \threadsafe virtual BlackMisc::Aviation::CAircraftSituation getInterpolatedSituation( - const BlackMisc::Aviation::CCallsign &callsign, qint64 currentTimeSinceEpoc, - InterpolationStatus &status, const CSituationsPerCallsign *situationsPerCallsign = nullptr) const = 0; - - //! Do a complete calculation for all know callsigns. - //! \param currentTimeMsSinceEpoch if no value is passed current time is used - //! \threadsafe - //! - virtual BlackMisc::Aviation::CAircraftSituationList getInterpolatedSituations(qint64 currentTimeMsSinceEpoch = -1); - - //! All situations for all callsigns (in map as per callsign) - //! \threadsafe - CSituationsPerCallsign getSituationsByCallsign() const; + const BlackMisc::Aviation::CCallsign &callsign, qint64 currentTimeSinceEpoc, bool isVtolAircraft, InterpolationStatus &status) const = 0; //! Parts before given offset time (aka pending parts) //! \threadsafe - virtual BlackMisc::Aviation::CAircraftPartsList getAndRemovePartsBeforeTime(const BlackMisc::Aviation::CCallsign &callsign, qint64 cutoffTime, PartsStatus &partsStatus); - - //! Clear all data - //! \threadsafe - virtual void clear(); - - //! Does know callsign? - //! \threadsafe - virtual bool hasDataForCallsign(const BlackMisc::Aviation::CCallsign &callsign) const; - - //! All situations for given callsign - //! \threadsafe - BlackMisc::Aviation::CAircraftSituationList getSituationsForCallsign(const BlackMisc::Aviation::CCallsign &callsign) const; - - //! All parts for given callsign - //! \threadsafe - BlackMisc::Aviation::CAircraftPartsList getPartsForCallsign(const BlackMisc::Aviation::CCallsign &callsign) const; + virtual BlackMisc::Aviation::CAircraftPartsList getPartsBeforeTime(const BlackMisc::Aviation::CCallsign &callsign, qint64 cutoffTime, PartsStatus &partsStatus); //! Enable debug messages void enableDebugMessages(bool enabled); - //! Force sorting (latest first), not required if order can be guaranteed - void forceSortingOfAddedValues(bool sort); - static const qint64 TimeOffsetMs = 6000; //!< offset for interpolation - static const int MaxSituationsPerCallsign = 6; //!< How many situations per callsign - static const int MaxPartsPerCallsign = 3; //!< How many parts per callsign - static const int MaxKeptInterpolationRequests = 3; //!< How many requests are stored - - private slots: - //! New situation got added - //! \threadsafe - void ps_onAddedAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation); - - //! Added aircraft parts - //! \threadsafe - void ps_onAddedAircraftParts(const BlackMisc::Aviation::CAircraftParts &parts); - - //! Removed aircraft - //! \threadsafe - void ps_onRemovedAircraft(const BlackMisc::Aviation::CCallsign &callsign); protected: //! Constructor IInterpolator(BlackMisc::Simulation::IRemoteAircraftProviderReadOnly *provider, const QString &workerName, QObject *parent = nullptr); - bool m_withDebugMsg = false; //!< allows to disable debug messages - bool m_forceSortWhenAddingValues = false; //!< force sorting (latest first) when adding values - BlackMisc::Aviation::CCallsignSet m_aircraftSupportingParts; //!< aircraft supporting parts - - // hashs, because not sorted by key but keeping order - CSituationsPerCallsign m_situationsByCallsign; //!< situations - CPartsPerCallsign m_partsByCallsign; //!< parts - - // locks - mutable QReadWriteLock m_lockSituations; //!< lock for situations - mutable QReadWriteLock m_lockParts; //!< lock for parts - + bool m_withDebugMsg = false; //!< allows to disable debug messages }; } // namespace diff --git a/src/blackcore/interpolator_linear.cpp b/src/blackcore/interpolator_linear.cpp index fc65e217c..3b86adb5e 100644 --- a/src/blackcore/interpolator_linear.cpp +++ b/src/blackcore/interpolator_linear.cpp @@ -20,30 +20,20 @@ using namespace BlackMisc::Aviation; namespace BlackCore { - CAircraftSituation CInterpolatorLinear::getInterpolatedSituation(const CCallsign &callsign, qint64 currentTimeMsSinceEpoc, InterpolationStatus &status, const CSituationsPerCallsign *situationsPerCallsign) const + CAircraftSituation CInterpolatorLinear::getInterpolatedSituation(const CCallsign &callsign, qint64 currentTimeMsSinceEpoc, bool vtolAiracraft, InterpolationStatus &status) const { - const static CAircraftSituation empty; + static const CAircraftSituation empty; status.reset(); - QList splitSituations; + + // any data at all? + Q_ASSERT_X(!callsign.isEmpty(), Q_FUNC_INFO, "empty callsign"); + if (this->remoteAircraftSituationsCount(callsign) < 1) { return empty; } + + // data, split situations by time if (currentTimeMsSinceEpoc < 0) { currentTimeMsSinceEpoc = QDateTime::currentMSecsSinceEpoch(); } qint64 splitTimeMsSinceEpoch = currentTimeMsSinceEpoc - TimeOffsetMs; - if (situationsPerCallsign) - { - // lock free, expected that situationsPerCallsign is a copy - if (!situationsPerCallsign->contains(callsign)) { return empty; } - if ((*situationsPerCallsign)[callsign].isEmpty()) { return empty; } - splitSituations = (*situationsPerCallsign)[callsign].splitByTime(splitTimeMsSinceEpoch); - } - else - { - // only part where it is locked - QReadLocker lock(&m_lockSituations); - if (!m_situationsByCallsign.contains(callsign)) { return empty; } - if (m_situationsByCallsign[callsign].isEmpty()) { return empty; } - splitSituations = m_situationsByCallsign[callsign].splitByTime(splitTimeMsSinceEpoch, true); - } - + QList splitSituations(remoteAircraftSituations(callsign).splitByTime(splitTimeMsSinceEpoch, true)); CAircraftSituationList &situationsNewer = splitSituations[0]; // newer part CAircraftSituationList &situationsOlder = splitSituations[1]; // older part @@ -123,16 +113,15 @@ namespace BlackCore // Interpolate altitude: Alt = (AltB - AltA) * t + AltA const CAltitude oldAlt(oldSituation.getAltitude()); const CAltitude newAlt(newSituation.getAltitude()); - Q_ASSERT(oldAlt.getReferenceDatum() == newAlt.getReferenceDatum()); // otherwise no calculation is possible + Q_ASSERT_X(oldAlt.getReferenceDatum() == newAlt.getReferenceDatum(), Q_FUNC_INFO, "mismatch in reference"); // otherwise no calculation is possible currentSituation.setAltitude(CAltitude((newAlt - oldAlt) * simulationTimeFraction + oldAlt, oldAlt.getReferenceDatum())); - if (newLat == oldLat && newLng == oldLng && oldAlt == newAlt) + if (!vtolAiracraft && newLat == oldLat && newLng == oldLng && oldAlt == newAlt) { - // stop interpolation here - //! \todo Does not work for VTOL aircraft. We need a flag for VTOL aircraft + // stop interpolation here, does not work for VTOL aircraft. We need a flag for VTOL aircraft return currentSituation; } @@ -179,7 +168,7 @@ namespace BlackCore * simulationTimeFraction + oldSituation.getGroundSpeed()); status.changedPosition = true; - Q_ASSERT(currentSituation.getCallsign() == callsign); + Q_ASSERT_X(currentSituation.getCallsign() == callsign, Q_FUNC_INFO, "mismatching callsigns"); return currentSituation; } diff --git a/src/blackcore/interpolator_linear.h b/src/blackcore/interpolator_linear.h index 70fc8db28..223915793 100644 --- a/src/blackcore/interpolator_linear.h +++ b/src/blackcore/interpolator_linear.h @@ -31,7 +31,7 @@ namespace BlackCore {} //! \copydoc IInterpolator::getCurrentInterpolatedSituation - virtual BlackMisc::Aviation::CAircraftSituation getInterpolatedSituation(const BlackMisc::Aviation::CCallsign &callsign, qint64 currentTimeSinceEpoc, InterpolationStatus &status, const CSituationsPerCallsign *situationsPerCallsign = nullptr) const override; + virtual BlackMisc::Aviation::CAircraftSituation getInterpolatedSituation(const BlackMisc::Aviation::CCallsign &callsign, qint64 currentTimeSinceEpoc, bool vtolAiracraft, InterpolationStatus &status) const override; //! Log category static QString getMessageCategory() { return "swift.interpolatorlinear"; } diff --git a/src/blackcore/simulator.cpp b/src/blackcore/simulator.cpp index bc1ec7a74..3590c0af8 100644 --- a/src/blackcore/simulator.cpp +++ b/src/blackcore/simulator.cpp @@ -42,7 +42,7 @@ namespace BlackCore CRemoteAircraftAware(remoteAircraftProvider), m_simulatorPluginInfo(info) { - this->setObjectName("CSimulatorCommon"); + this->setObjectName(info.getIdentifier()); m_oneSecondTimer = new QTimer(this); m_oneSecondTimer->setObjectName(this->objectName().append(":OneSecondTimer")); connect(this->m_oneSecondTimer, &QTimer::timeout, this, &CSimulatorCommon::ps_oneSecondTimer); @@ -129,13 +129,13 @@ namespace BlackCore if (!this->m_interpolator) { return; } const CCallsign callsign(aircraft.getCallsign()); - if (!this->m_interpolator->hasDataForCallsign(callsign)) { return; } + if (!(this->remoteAircraftSituationsCount(callsign) < 1)) { return; } // with an interpolator the interpolated situation is used // to avoid position jittering qint64 time = QDateTime::currentMSecsSinceEpoch(); IInterpolator::InterpolationStatus is; - CAircraftSituation as(m_interpolator->getInterpolatedSituation(callsign, time, is)); + CAircraftSituation as(m_interpolator->getInterpolatedSituation(callsign, time, aircraft.isVtol(), is)); if (is.interpolationSucceeded) { aircraft.setSituation(as); } } diff --git a/src/blackmisc/simulation/remoteaircraftprovider.cpp b/src/blackmisc/simulation/remoteaircraftprovider.cpp index e680e4419..5e7e3d172 100644 --- a/src/blackmisc/simulation/remoteaircraftprovider.cpp +++ b/src/blackmisc/simulation/remoteaircraftprovider.cpp @@ -18,67 +18,91 @@ namespace BlackMisc const CSimulatedAircraftList &CRemoteAircraftAwareReadOnly::remoteAircraft() const { - Q_ASSERT_X(this->m_remoteAircraftProvider, "renderedAircraft", "No object available"); + Q_ASSERT_X(this->m_remoteAircraftProvider, Q_FUNC_INFO, "No object available"); return this->m_remoteAircraftProvider->remoteAircraft(); } - const Aviation::CAircraftSituationList &CRemoteAircraftAwareReadOnly::remoteAircraftSituations() const + Aviation::CAircraftSituationList CRemoteAircraftAwareReadOnly::remoteAircraftSituations(const BlackMisc::Aviation::CCallsign &callsign) const { - Q_ASSERT_X(this->m_remoteAircraftProvider, "renderedAircraftSituations", "No object available"); - return this->m_remoteAircraftProvider->remoteAircraftSituations(); + Q_ASSERT_X(this->m_remoteAircraftProvider, Q_FUNC_INFO, "No object available"); + return this->m_remoteAircraftProvider->remoteAircraftSituations(callsign); } - const Aviation::CAircraftPartsList &CRemoteAircraftAwareReadOnly::remoteAircraftParts() const + int CRemoteAircraftAwareReadOnly::remoteAircraftSituationsCount(const CCallsign &callsign) const { - Q_ASSERT_X(this->m_remoteAircraftProvider, "renderedAircraftParts", "No object available"); - return this->m_remoteAircraftProvider->remoteAircraftParts(); + Q_ASSERT_X(this->m_remoteAircraftProvider, Q_FUNC_INFO, "No object available"); + return this->m_remoteAircraftProvider->remoteAircraftSituationsCount(callsign); + } + + CAircraftPartsList CRemoteAircraftAwareReadOnly::remoteAircraftParts(const BlackMisc::Aviation::CCallsign &callsign, qint64 cutoffTimeBefore) const + { + Q_ASSERT_X(this->m_remoteAircraftProvider, Q_FUNC_INFO, "No object available"); + return this->m_remoteAircraftProvider->remoteAircraftParts(callsign, cutoffTimeBefore); + } + + CCallsignSet CRemoteAircraftAwareReadOnly::remoteAircraftSupportingParts() const + { + Q_ASSERT_X(this->m_remoteAircraftProvider, Q_FUNC_INFO, "No object available"); + return this->m_remoteAircraftProvider->remoteAircraftSupportingParts(); + } + + bool CRemoteAircraftAwareReadOnly::isRemoteAircraftSupportingParts(const CCallsign &callsign) const + { + Q_ASSERT_X(this->m_remoteAircraftProvider, Q_FUNC_INFO, "No object available"); + return this->m_remoteAircraftProvider->isRemoteAircraftSupportingParts(callsign); } const CSimulatedAircraftList &CRemoteAircraftAware::remoteAircraft() const { - Q_ASSERT_X(this->m_remoteAircraftProvider, "renderedAircraft", "No object available"); + Q_ASSERT_X(this->m_remoteAircraftProvider, Q_FUNC_INFO, "No object available"); return this->m_remoteAircraftProvider->remoteAircraft(); } CSimulatedAircraftList &CRemoteAircraftAware::remoteAircraft() { - Q_ASSERT_X(this->m_remoteAircraftProvider, "renderedAircraft", "No object available"); + Q_ASSERT_X(this->m_remoteAircraftProvider, Q_FUNC_INFO, "No object available"); return this->m_remoteAircraftProvider->remoteAircraft(); } - const CAircraftSituationList &CRemoteAircraftAware::remoteAircraftSituations() const + CAircraftSituationList CRemoteAircraftAware::remoteAircraftSituations(const BlackMisc::Aviation::CCallsign &callsign) const { - Q_ASSERT_X(this->m_remoteAircraftProvider, "renderedAircraftSituations", "No object available"); - return this->m_remoteAircraftProvider->remoteAircraftSituations(); + Q_ASSERT_X(this->m_remoteAircraftProvider, Q_FUNC_INFO, "No object available"); + return this->m_remoteAircraftProvider->remoteAircraftSituations(callsign); } - CAircraftSituationList &CRemoteAircraftAware::remoteAircraftSituations() + CAircraftPartsList CRemoteAircraftAware::remoteAircraftParts(const BlackMisc::Aviation::CCallsign &callsign) const { - Q_ASSERT_X(this->m_remoteAircraftProvider, "renderedAircraftSituations", "No object available"); - return this->m_remoteAircraftProvider->remoteAircraftSituations(); + Q_ASSERT_X(this->m_remoteAircraftProvider, Q_FUNC_INFO, "No object available"); + return this->m_remoteAircraftProvider->remoteAircraftParts(callsign); } - const CAircraftPartsList &CRemoteAircraftAware::remoteAircraftParts() const + CCallsignSet CRemoteAircraftAware::remoteAircraftSupportingParts() const { - Q_ASSERT_X(this->m_remoteAircraftProvider, "renderedAircraftParts", "No object available"); - return this->m_remoteAircraftProvider->remoteAircraftParts(); + Q_ASSERT_X(this->m_remoteAircraftProvider, Q_FUNC_INFO, "No object available"); + return this->m_remoteAircraftProvider->remoteAircraftSupportingParts(); } - CAircraftPartsList &CRemoteAircraftAware::remoteAircraftParts() + int CRemoteAircraftAware::remoteAircraftSituationsCount(const CCallsign &callsign) const { - Q_ASSERT_X(this->m_remoteAircraftProvider, "renderedAircraftParts", "No object available"); - return this->m_remoteAircraftProvider->remoteAircraftParts(); + Q_ASSERT_X(this->m_remoteAircraftProvider, Q_FUNC_INFO, "No object available"); + return this->m_remoteAircraftProvider->remoteAircraftSituationsCount(callsign); } bool CRemoteAircraftAware::providerUpdateAircraftModel(const Aviation::CCallsign &callsign, const CAircraftModel &model, const QString &originator) { - Q_ASSERT_X(this->m_remoteAircraftProvider, "providerUpdateAircraftModel", "No object available"); + Q_ASSERT_X(this->m_remoteAircraftProvider, Q_FUNC_INFO, "No object available"); return this->m_remoteAircraftProvider->updateAircraftModel(callsign, model, originator); } + bool CRemoteAircraftAware::isRemoteAircraftSupportingParts(const CCallsign &callsign) const + { + Q_ASSERT_X(this->m_remoteAircraftProvider, Q_FUNC_INFO, "No object available"); + return this->m_remoteAircraftProvider->isRemoteAircraftSupportingParts(callsign); + } + bool CRemoteAircraftAware::providerUpdateAircraftEnabled(const Aviation::CCallsign &callsign, bool enabledForRedering, const QString &originator) { - Q_ASSERT_X(this->m_remoteAircraftProvider, "providerUpdateAircraftEnabled", "No object available"); + Q_ASSERT_X(this->m_remoteAircraftProvider, Q_FUNC_INFO, "No object available"); return this->m_remoteAircraftProvider->updateAircraftEnabled(callsign, enabledForRedering, originator); } diff --git a/src/blackmisc/simulation/remoteaircraftprovider.h b/src/blackmisc/simulation/remoteaircraftprovider.h index 1494b04dc..6a1357fe3 100644 --- a/src/blackmisc/simulation/remoteaircraftprovider.h +++ b/src/blackmisc/simulation/remoteaircraftprovider.h @@ -28,14 +28,34 @@ namespace BlackMisc class BLACKMISC_EXPORT IRemoteAircraftProviderReadOnly { public: + //! Situations per callsign + typedef QHash CSituationsPerCallsign; + + //! Parts per callsign + typedef QHash CPartsPerCallsign; + //! All rendered aircraft virtual const CSimulatedAircraftList &remoteAircraft() const = 0; - //! All situation (per callsign, time history) - virtual const BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations() const = 0; + //! Rendered aircraft situations (per callsign, time history) + //! \threadsafe + virtual BlackMisc::Aviation::CAircraftSituationList remoteAircraftSituations(const BlackMisc::Aviation::CCallsign &callsign) const = 0; + + //! Number of remote aircraft situations for callsign + //! \threadsafe + virtual int remoteAircraftSituationsCount(const BlackMisc::Aviation::CCallsign &callsign) const = 0; //! All parts (per callsign, time history) - virtual const BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts() const = 0; + //! \threadsafe + virtual BlackMisc::Aviation::CAircraftPartsList remoteAircraftParts(const BlackMisc::Aviation::CCallsign &callsign, qint64 cutoffTimeBefore = -1) const = 0; + + //! Is remote aircraft supporting parts? + //! \threadsafe + virtual bool isRemoteAircraftSupportingParts(const BlackMisc::Aviation::CCallsign &callsign) const = 0; + + //! Remote aircraft supporting parts. + //! \threadsafe + virtual BlackMisc::Aviation::CCallsignSet remoteAircraftSupportingParts() const = 0; //! Destructor virtual ~IRemoteAircraftProviderReadOnly() {} @@ -47,11 +67,11 @@ namespace BlackMisc std::function removedAircraftSlot ) = 0; + static const int MaxSituationsPerCallsign = 6; //!< How many situations per callsign + static const int MaxPartsPerCallsign = 3; //!< How many parts per callsign + // those signals have to be implemented by classes using the interface. signals: - //! A new situation got added - void addedRemoteAircraftSituation(const BlackMisc::Aviation::CAircraftSituation &situation); - //! New parts got added void addedRemoteAircraftParts(const BlackMisc::Aviation::CAircraftParts &parts); @@ -65,21 +85,13 @@ namespace BlackMisc { public: + //! The read only /sa IRemoteAircraftProviderReadOnly::remoteAircraft using IRemoteAircraftProviderReadOnly::remoteAircraft; - using IRemoteAircraftProviderReadOnly::remoteAircraftParts; - using IRemoteAircraftProviderReadOnly::remoteAircraftSituations; //! All rendered aircraft //! \note in memory reference, not thread safe virtual CSimulatedAircraftList &remoteAircraft() = 0; - //! Rendered aircraft situations (history) - virtual BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations() = 0; - - //! All parts (per callsign, time history) - //! \note in memory reference, not thread safe - virtual BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts() = 0; - //! Enable/disable rendering virtual bool updateAircraftEnabled(const BlackMisc::Aviation::CCallsign &callsign, bool enabledForRendering, const QString &originator) = 0; @@ -97,11 +109,20 @@ namespace BlackMisc //! \copydoc IRemoteAircraftProviderReadOnly::renderedAircraft virtual const CSimulatedAircraftList &remoteAircraft() const; - //!\copydoc IRemoteAircraftProviderReadOnly::renderedAircraftSituations - virtual const BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations() const; + //! \copydoc IRemoteAircraftProviderReadOnly::remoteAircraftSituations + virtual BlackMisc::Aviation::CAircraftSituationList remoteAircraftSituations(const BlackMisc::Aviation::CCallsign &callsign) const; - //!\copydoc IRemoteAircraftProviderReadOnly::renderedAircraftParts - virtual const BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts() const; + //! \copydoc IRemoteAircraftProviderReadOnly::remoteAircraftSituationsCount + virtual int remoteAircraftSituationsCount(const BlackMisc::Aviation::CCallsign &callsign) const; + + //! \copydoc IRemoteAircraftProviderReadOnly::remoteAircraftParts + virtual BlackMisc::Aviation::CAircraftPartsList remoteAircraftParts(const BlackMisc::Aviation::CCallsign &callsign, qint64 cutoffTimeBefore = -1) const; + + //! \copydoc IRemoteAircraftProviderReadOnly::remoteAircraftSupportingParts + virtual BlackMisc::Aviation::CCallsignSet remoteAircraftSupportingParts() const; + + //! \copydoc IRemoteAircraftProviderReadOnly::isRemoteAircraftSupportingParts + virtual bool isRemoteAircraftSupportingParts(const BlackMisc::Aviation::CCallsign &callsign) const; //! Destructor virtual ~CRemoteAircraftAwareReadOnly() {} @@ -116,23 +137,23 @@ namespace BlackMisc class BLACKMISC_EXPORT CRemoteAircraftAware { public: - //! \copydoc IRemoteAircraftProviderReadOnly::renderedAircraft + //! \copydoc IRemoteAircraftProviderReadOnly::remoteAircraft virtual const CSimulatedAircraftList &remoteAircraft() const; - //! \copydoc IRemoteAircraftProvider::renderedAircraft + //! \copydoc IRemoteAircraftProvider::remoteAircraft virtual CSimulatedAircraftList &remoteAircraft(); - //!\copydoc IRemoteAircraftProviderReadOnly::renderedAircraftSituations - virtual const BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations() const; + //! \copydoc IRemoteAircraftProviderReadOnly::remoteAircraftSituations + virtual BlackMisc::Aviation::CAircraftSituationList remoteAircraftSituations(const BlackMisc::Aviation::CCallsign &callsign) const; - //!\copydoc IRemoteAircraftProvider::remoteAircraftSituations - virtual BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations(); + //! \copydoc IRemoteAircraftProviderReadOnly::remoteAircraftParts + virtual BlackMisc::Aviation::CAircraftPartsList remoteAircraftParts(const BlackMisc::Aviation::CCallsign &callsign) const; - //!\copydoc IRemoteAircraftProviderReadOnly::renderedAircraftParts - virtual const BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts() const; + //! \copydoc IRemoteAircraftProviderReadOnly::remoteAircraftSupportingParts + virtual BlackMisc::Aviation::CCallsignSet remoteAircraftSupportingParts() const; - //!\copydoc IRemoteAircraftProvider::remoteAircraftParts - virtual BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts(); + //! \copydoc IRemoteAircraftProviderReadOnly::remoteAircraftSituationsCount + virtual int remoteAircraftSituationsCount(const BlackMisc::Aviation::CCallsign &callsign) const; //! \copydoc IRemoteAircraftProvider::updateAircraftEnabled virtual bool providerUpdateAircraftEnabled(const BlackMisc::Aviation::CCallsign &callsign, bool enabledForRedering, const QString &originator); @@ -140,6 +161,9 @@ namespace BlackMisc //! \copydoc IRemoteAircraftProvider::updateAircraftModel virtual bool providerUpdateAircraftModel(const BlackMisc::Aviation::CCallsign &callsign, const BlackMisc::Simulation::CAircraftModel &model, const QString &originator); + //! \copydoc IRemoteAircraftProviderReadOnly::isRemoteAircraftSupportingParts + virtual bool isRemoteAircraftSupportingParts(const BlackMisc::Aviation::CCallsign &callsign) const; + //! Destructor virtual ~CRemoteAircraftAware() {} diff --git a/src/blackmisc/simulation/remoteaircraftproviderdummy.cpp b/src/blackmisc/simulation/remoteaircraftproviderdummy.cpp index e68d10318..25638ed49 100644 --- a/src/blackmisc/simulation/remoteaircraftproviderdummy.cpp +++ b/src/blackmisc/simulation/remoteaircraftproviderdummy.cpp @@ -29,24 +29,30 @@ namespace BlackMisc return m_aircraft; } - const CAircraftPartsList &CRemoteAircraftProviderDummy::remoteAircraftParts() const + CAircraftPartsList CRemoteAircraftProviderDummy::remoteAircraftParts(const BlackMisc::Aviation::CCallsign &callsign, qint64 cutoffTimeBefore) const { - return m_parts; + if (cutoffTimeBefore < 0) { return m_parts.findByCallsign(callsign); } + return m_parts.findByCallsign(callsign).findBefore(cutoffTimeBefore); } - CAircraftPartsList &CRemoteAircraftProviderDummy::remoteAircraftParts() + CAircraftSituationList CRemoteAircraftProviderDummy::remoteAircraftSituations(const BlackMisc::Aviation::CCallsign &callsign) const { - return m_parts; + return m_situations.findByCallsign(callsign); } - const CAircraftSituationList &CRemoteAircraftProviderDummy::remoteAircraftSituations() const + int CRemoteAircraftProviderDummy::remoteAircraftSituationsCount(const CCallsign &callsign) const { - return m_situations; + return remoteAircraftSituations(callsign).size(); } - CAircraftSituationList &CRemoteAircraftProviderDummy::remoteAircraftSituations() + CCallsignSet CRemoteAircraftProviderDummy::remoteAircraftSupportingParts() const { - return m_situations; + return m_parts.getCallsigns(); + } + + bool CRemoteAircraftProviderDummy::isRemoteAircraftSupportingParts(const CCallsign &callsign) const + { + return remoteAircraftParts(callsign).size() > 0; } bool CRemoteAircraftProviderDummy::connectRemoteAircraftProviderSignals(std::function situationSlot, std::function partsSlot, std::function removedAircraftSlot) @@ -83,14 +89,14 @@ namespace BlackMisc void CRemoteAircraftProviderDummy::insertNewSituation(const CAircraftSituation &situation) { - this->m_situations.push_frontMaxElements(situation, 20); + this->m_situations.push_front(situation); this->m_situations.sortLatestFirst(); // like in real world, latest should be first emit addedRemoteAircraftSituation(situation); } void CRemoteAircraftProviderDummy::insertNewAircraftParts(const CAircraftParts &parts) { - this->m_parts.push_frontMaxElements(parts, 20); + this->m_parts.push_front(parts); this->m_parts.sortLatestFirst(); // like in real world, latest should be first emit addedRemoteAircraftParts(parts); } diff --git a/src/blackmisc/simulation/remoteaircraftproviderdummy.h b/src/blackmisc/simulation/remoteaircraftproviderdummy.h index b1b1c522b..3a8113c43 100644 --- a/src/blackmisc/simulation/remoteaircraftproviderdummy.h +++ b/src/blackmisc/simulation/remoteaircraftproviderdummy.h @@ -39,16 +39,19 @@ namespace BlackMisc virtual CSimulatedAircraftList &remoteAircraft() override; //! \copydoc IRemoteAircraftProviderReadOnly::remoteAircraftParts - virtual const BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts() const override; - - //! \copydoc IRemoteAircraftProvider::remoteAircraftParts - virtual BlackMisc::Aviation::CAircraftPartsList &remoteAircraftParts() override; + virtual BlackMisc::Aviation::CAircraftPartsList remoteAircraftParts(const Aviation::CCallsign &callsign, qint64 cutoffTimeBefore = -1) const override; //! \copydoc IRemoteAircraftProviderReadOnly::remoteAircraftSituations - virtual const BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations() const override; + virtual BlackMisc::Aviation::CAircraftSituationList remoteAircraftSituations(const Aviation::CCallsign &callsign) const override; - //! \copydoc IRemoteAircraftProvider::remoteAircraftSituations - virtual BlackMisc::Aviation::CAircraftSituationList &remoteAircraftSituations() override; + //! \copydoc IRemoteAircraftProviderReadOnly::remoteAircraftSituationsCount + virtual int remoteAircraftSituationsCount(const Aviation::CCallsign &callsign) const override; + + //! \copydoc IRemoteAircraftProviderReadOnly::remoteAircraftSupportingParts + virtual BlackMisc::Aviation::CCallsignSet remoteAircraftSupportingParts() const override; + + //! \copydoc IRemoteAircraftProviderReadOnly::isRemoteAircraftSupportingParts + virtual bool isRemoteAircraftSupportingParts(const Aviation::CCallsign &callsign) const override; //! \copydoc IRemoteAircraftProviderReadOnly::connectRemoteAircraftProviderSignals virtual bool connectRemoteAircraftProviderSignals( diff --git a/src/plugins/simulator/fs9/fs9_client.cpp b/src/plugins/simulator/fs9/fs9_client.cpp index 9b0041029..26423d5f6 100644 --- a/src/plugins/simulator/fs9/fs9_client.cpp +++ b/src/plugins/simulator/fs9/fs9_client.cpp @@ -76,13 +76,13 @@ namespace BlackSimPlugin void CFs9Client::timerEvent(QTimerEvent *event) { Q_UNUSED(event); - Q_ASSERT(m_interpolator); + Q_ASSERT_X(m_interpolator, Q_FUNC_INFO, "Missing interpolator"); if (m_clientStatus == Disconnected) { return; } - IInterpolator::InterpolationStatus status; - CAircraftSituation situation = this->m_interpolator->getInterpolatedSituation(m_callsign, -1, status); + bool vtolAircraft(false); + CAircraftSituation situation = this->m_interpolator->getInterpolatedSituation(m_callsign, -1, vtolAircraft, status); // Test only for successful interpolation. FS9 requires constant positions if (!status.interpolationSucceeded) { return; } diff --git a/src/plugins/simulator/fsx/simulator_fsx.cpp b/src/plugins/simulator/fsx/simulator_fsx.cpp index a5a5a22d8..9ae63adb2 100644 --- a/src/plugins/simulator/fsx/simulator_fsx.cpp +++ b/src/plugins/simulator/fsx/simulator_fsx.cpp @@ -151,8 +151,8 @@ namespace BlackSimPlugin CLogMessage(this).warning("Have to remove aircraft %1 before I can add it") << callsign; } - CSimulatedAircraft newRemoteAircraftCopy(newRemoteAircraft); - this->setInitialAircraftSituationAndParts(newRemoteAircraftCopy); + CSimulatedAircraft newRemoteAircraftCopy(newRemoteAircraft); // copy which can be modified + this->setInitialAircraftSituationAndParts(newRemoteAircraftCopy); // set interpolated data/parts if available SIMCONNECT_DATA_INITPOSITION initialPosition = aircraftSituationToFsxInitPosition(newRemoteAircraftCopy.getSituation()); CSimConnectObject simObj; @@ -611,7 +611,7 @@ namespace BlackSimPlugin { static_assert(sizeof(DataDefinitionRemoteAircraftParts) == 120, "DataDefinitionRemoteAircraftParts has an incorrect size."); Q_ASSERT(this->m_interpolator); - Q_ASSERT_X(this->m_interpolator->thread() != this->thread(), "updateOtherAircraft", "interpolator should run in its own thread"); + Q_ASSERT_X(this->m_interpolator->thread() != this->thread(), Q_FUNC_INFO, "interpolator should run in its own thread"); // nothing to do, reset request id and exit if (this->isPaused()) { return; } // no interpolation while paused @@ -623,19 +623,29 @@ namespace BlackSimPlugin // values used for position and parts bool isOnGround = false; + bool isVtolAircraft = false; //! \todo determine VTOL aircraft in interpolator qint64 currentTimestamp = QDateTime::currentMSecsSinceEpoch(); + CCallsignSet aircraftWithParts(this->remoteAircraftSupportingParts()); // optimization, fetch all parts supporting aircraft in one step (one lock) + for (const CSimConnectObject &simObj : m_simConnectObjects) { + if (simObj.getObjectId() < 1) { continue; } + const CCallsign callsign(simObj.getCallsign()); + Q_ASSERT_X(!callsign.isEmpty(), Q_FUNC_INFO, "missing callsign"); IInterpolator::InterpolationStatus interpolatorStatus; - if (simObj.getObjectId() == 0) { continue; } - CAircraftSituation interpolatedSituation = this->m_interpolator->getInterpolatedSituation(callsign, currentTimestamp, interpolatorStatus); + CAircraftSituation interpolatedSituation = this->m_interpolator->getInterpolatedSituation(callsign, currentTimestamp, isVtolAircraft, interpolatorStatus); // having the onGround flag in parts forces me to obtain parts here // which is not the smartest thing regarding performance IInterpolator::PartsStatus partsStatus; - CAircraftPartsList parts = this->m_interpolator->getAndRemovePartsBeforeTime(callsign, currentTimestamp - IInterpolator::TimeOffsetMs, partsStatus); + partsStatus.supportsParts = aircraftWithParts.contains(callsign); + CAircraftPartsList parts; + if (partsStatus.supportsParts) + { + this->m_interpolator->getPartsBeforeTime(callsign, currentTimestamp - IInterpolator::TimeOffsetMs, partsStatus); + } if (interpolatorStatus.allTrue()) { @@ -643,6 +653,7 @@ namespace BlackSimPlugin SIMCONNECT_DATA_INITPOSITION position = aircraftSituationToFsxInitPosition(interpolatedSituation); //! \todo The onGround in parts is nuts, as already mentioned in the discussion + // Currently ignored here, only guessing which is faster as aircraft without parts can just be // a) I am forced to read parts even if i just want to update position // b) Unlike the other values it is not a fire and forget value, as I need it again in the next cycle if (partsStatus.supportsParts && !parts.isEmpty()) @@ -662,8 +673,6 @@ namespace BlackSimPlugin sizeof(SIMCONNECT_DATA_INITPOSITION), &position); if (hr != S_OK) { CLogMessage(this).warning("Failed so set position on SimObject %1 callsign: %2") << simObj.getObjectId() << callsign; } - - } // interpolation data if (interpolatorStatus.interpolationSucceeded) diff --git a/src/plugins/simulator/xplane/simulator_xplane.cpp b/src/plugins/simulator/xplane/simulator_xplane.cpp index 4a3416bf9..648b1ec09 100644 --- a/src/plugins/simulator/xplane/simulator_xplane.cpp +++ b/src/plugins/simulator/xplane/simulator_xplane.cpp @@ -47,10 +47,13 @@ namespace BlackSimPlugin m_watcher = new QDBusServiceWatcher(this); m_watcher->setWatchMode(QDBusServiceWatcher::WatchForUnregistration); m_watcher->addWatchedService(xbusServiceName()); + m_watcher->setObjectName("QDBusServiceWatcher"); connect(m_watcher, &QDBusServiceWatcher::serviceUnregistered, this, &CSimulatorXPlane::ps_serviceUnregistered); m_fastTimer = new QTimer(this); m_slowTimer = new QTimer(this); + m_fastTimer->setObjectName(this->objectName().append(":m_fastTimer")); + m_slowTimer->setObjectName(this->objectName().append(":m_slowTimer")); connect(m_fastTimer, &QTimer::timeout, this, &CSimulatorXPlane::ps_fastTimerTimeout); connect(m_slowTimer, &QTimer::timeout, this, &CSimulatorXPlane::ps_slowTimerTimeout); m_fastTimer->start(100); diff --git a/tests/blackcore/testinterpolator.cpp b/tests/blackcore/testinterpolator.cpp index d1d5a9ba5..c347d8a04 100644 --- a/tests/blackcore/testinterpolator.cpp +++ b/tests/blackcore/testinterpolator.cpp @@ -25,13 +25,12 @@ namespace BlackCoreTest { QScopedPointer provider(new CRemoteAircraftProviderDummy()); CInterpolatorLinear interpolator(provider.data()); - interpolator.forceSortingOfAddedValues(true); // fixed time so everything can be debugged const qint64 ts = 1425000000000; // QDateTime::currentMSecsSinceEpoch(); const qint64 deltaT = 5000; // ms CCallsign cs("SWIFT"); - for (int i = 0; i < IInterpolator::MaxSituationsPerCallsign; i++) + for (int i = 0; i < IRemoteAircraftProviderReadOnly::MaxSituationsPerCallsign; i++) { CAircraftSituation s(getTestSituation(cs, i, ts, deltaT)); @@ -41,30 +40,30 @@ namespace BlackCoreTest provider->insertNewSituation(s); } - for (int i = 0; i < IInterpolator::MaxPartsPerCallsign; i++) + for (int i = 0; i < IRemoteAircraftProviderReadOnly::MaxPartsPerCallsign; i++) { CAircraftParts p(getTestParts(cs, i, ts, deltaT)); provider->insertNewAircraftParts(p); } - // make sure signals are processed + // make sure signals are processed, if the interpolator depends on those signals QCoreApplication::processEvents(QEventLoop::AllEvents, 1000); // check if all situations / parts have been received - QVERIFY2(interpolator.getSituationsForCallsign(cs).size() == IInterpolator::MaxSituationsPerCallsign, "Missing situations"); - QVERIFY2(interpolator.getPartsForCallsign(cs).size() == IInterpolator::MaxPartsPerCallsign, "Missing parts"); + QVERIFY2(provider->remoteAircraftSituations(cs).size() == IRemoteAircraftProviderReadOnly::MaxSituationsPerCallsign, "Missing situations"); + QVERIFY2(provider->remoteAircraftParts(cs).size() == IRemoteAircraftProviderReadOnly::MaxPartsPerCallsign, "Missing parts"); - // interpolation + // interpolation functional check IInterpolator::InterpolationStatus status; double latOld = 360.0; double lngOld = 360.0; - for (qint64 currentTime = ts - 2 * deltaT; currentTime < ts; currentTime += 250) + for (qint64 currentTime = ts - 2 * deltaT; currentTime < ts; currentTime += (deltaT / 20)) { // This will use time range // from: ts - 2* deltaT - IInterpolator::TimeOffsetMs // to: ts - IInterpolator::TimeOffsetMs CAircraftSituation currentSituation(interpolator.getInterpolatedSituation - (cs, currentTime, status) + (cs, currentTime, false, status) ); QVERIFY2(status.interpolationSucceeded, "Interpolation was not succesful"); QVERIFY2(status.changedPosition, "Interpolation did not changed"); @@ -80,15 +79,21 @@ namespace BlackCoreTest int interpolationNo = 0; qint64 startTimeMsSinceEpoch = ts - 2 * deltaT; - for (int callsigns = 0; callsigns < 20; callsigns++) + + // Pseudo performance test: + // Those make not completely sense, as the performance depends on the implementation of + // the dummy provider, which is different from the real provider + // With one callsign in the lists (of dummy provider) it is somehow expected to be roughly the same performance + + for (int loops = 0; loops < 20; loops++) { - for (qint64 currentTime = startTimeMsSinceEpoch; currentTime < ts; currentTime += 250) + for (qint64 currentTime = startTimeMsSinceEpoch; currentTime < ts; currentTime += (deltaT / 20)) { // This will use range // from: ts - 2* deltaT - IInterpolator::TimeOffsetMs // to: ts - IInterpolator::TimeOffsetMs CAircraftSituation currentSituation(interpolator.getInterpolatedSituation - (cs, currentTime, status) + (cs, currentTime, false, status) ); QVERIFY2(status.allTrue(), "Failed interpolation"); QVERIFY2(currentSituation.getCallsign() == cs, "Wrong callsign"); @@ -101,105 +106,20 @@ namespace BlackCoreTest } int timeMs = timer.elapsed(); QVERIFY2(timeMs < interpolationNo, "Interpolation > 1ms"); - qDebug() << timeMs << "ms" << "for" << interpolationNo; - - CAircraftSituationList interpolations(interpolator.getInterpolatedSituations(startTimeMsSinceEpoch)); - QVERIFY(interpolations.size() == 1); - QVERIFY(interpolations.containsCallsign(cs)); - - // - // Single interpolation vs. all interpolations at once - // - - // Create data in provider - provider->clear(); - interpolator.clear(); - QVERIFY(interpolator.getSituationsByCallsign().size() == 0); - const int callsignsInProvider = 20; - for (int callsignNo = 0; callsignNo < callsignsInProvider; callsignNo++) - { - cs = CCallsign("SWIFT" + QString::number(callsignNo)); - int i = 0; - for (int t = 0; t < IInterpolator::MaxSituationsPerCallsign; t++) - { - qint64 currentTime = ts - t * deltaT; - CAircraftSituation s(getTestSituation(cs, i, currentTime, 0)); - provider->insertNewSituation(s); - - CAircraftParts p(getTestParts(cs, i, currentTime, 0)); - provider->insertNewAircraftParts(p); - i++; - } - } - - QList csKeys = interpolator.getSituationsByCallsign().keys(); - CCallsignSet callsigns(csKeys); - QVERIFY(callsigns.size() == callsignsInProvider); - QVERIFY(interpolator.getSituationsForCallsign("SWIFT0").size() == IInterpolator::MaxSituationsPerCallsign); - QVERIFY(interpolator.getPartsForCallsign("SWIFT0").size() == IInterpolator::MaxPartsPerCallsign); - - // interpolation for time, then for each callsign - int doneInterpolations = 0; - timer.start(); - for (qint64 currentTime = ts - 2 * deltaT; currentTime < ts; currentTime += 250) - { - // This will use range - // from: ts - 2* deltaT - IInterpolator::TimeOffsetMs - // to: ts - IInterpolator::TimeOffsetMs - - for (const CCallsign &cs : callsigns) - { - CAircraftSituation currentSituation(interpolator.getInterpolatedSituation - (cs, currentTime, status) - ); - QVERIFY2(status.interpolationSucceeded, "Interpolation was not succesful"); - QVERIFY2(status.changedPosition, "Interpolation did not changed"); - double latDeg = currentSituation.getPosition().latitude().valueRounded(CAngleUnit::deg(), 5); - double lngDeg = currentSituation.getPosition().longitude().valueRounded(CAngleUnit::deg(), 5); - Q_UNUSED(latDeg); - Q_UNUSED(lngDeg); - doneInterpolations++; - } - } - timeMs = timer.elapsed(); - qDebug() << "Per callsign" << doneInterpolations << "interpolations in" << timeMs << "ms"; - - doneInterpolations = 0; - timer.start(); - for (qint64 currentTime = ts - 2 * deltaT; currentTime < ts; currentTime += 250) - { - // This will use range - // from: ts - 2* deltaT - IInterpolator::TimeOffsetMs - // to: ts - IInterpolator::TimeOffsetMs - - CAircraftSituationList currentSituations(interpolator.getInterpolatedSituations(currentTime)); - QVERIFY2(currentSituations.size() == callsignsInProvider, "Interpolation was not succesful"); - for (const CAircraftSituation ¤tSituation : currentSituations) - { - double latDeg = currentSituation.getPosition().latitude().valueRounded(CAngleUnit::deg(), 5); - double lngDeg = currentSituation.getPosition().longitude().valueRounded(CAngleUnit::deg(), 5); - doneInterpolations++; - Q_UNUSED(latDeg); - Q_UNUSED(lngDeg); - } - } - timeMs = timer.elapsed(); - qDebug() << "All callsigns" << doneInterpolations << "interpolations in" << timeMs << "ms"; + qDebug() << timeMs << "ms" << "for" << interpolationNo << "interpolations"; int fetchedParts = 0; timer.start(); for (qint64 currentTime = ts - 2 * deltaT; currentTime < ts; currentTime += 250) { - for (const CCallsign &callsign : callsigns) - { - IInterpolator::PartsStatus status; - CAircraftPartsList pl = interpolator.getAndRemovePartsBeforeTime(callsign, ts, status); - fetchedParts++; - Q_UNUSED(pl); - } + IInterpolator::PartsStatus status; + CAircraftPartsList pl(interpolator.getPartsBeforeTime(cs, ts, status)); + fetchedParts++; + QVERIFY2(status.supportsParts, "Parts not supported"); + QVERIFY2(!pl.isEmpty(), "Parts empty"); } timeMs = timer.elapsed(); - qDebug() << "Per callsign" << fetchedParts << "fetched parts in" << timeMs << "ms"; + qDebug() << timeMs << "ms" << "for" << fetchedParts << "fetched parts"; } CAircraftSituation CTestInterpolator::getTestSituation(const CCallsign &callsign, int number, qint64 ts, qint64 deltaT)