From 3467bef45c153adeade6532417c5ee6a83e0ffa6 Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Wed, 13 Jun 2018 23:19:58 +0200 Subject: [PATCH] Ref T280, provider improvements * store the changes per callsign * aircraft stored per callsign * moved "guessOnGroundAndUpdateModelCG" down to IRemoteAircraftProvider (from airspace monitor, "one level deeper in base class" --- src/blackcore/airspacemonitor.cpp | 23 +-- src/blackcore/airspacemonitor.h | 4 - src/blackcore/context/contextnetworkimpl.cpp | 16 +- src/blackcore/context/contextnetworkimpl.h | 2 + .../aviation/aircraftsituationlist.cpp | 16 +- .../aviation/aircraftsituationlist.h | 2 +- .../simulation/remoteaircraftprovider.cpp | 193 ++++++++++++------ .../simulation/remoteaircraftprovider.h | 45 ++-- 8 files changed, 196 insertions(+), 105 deletions(-) diff --git a/src/blackcore/airspacemonitor.cpp b/src/blackcore/airspacemonitor.cpp index 3f1c3918d..1d1903472 100644 --- a/src/blackcore/airspacemonitor.cpp +++ b/src/blackcore/airspacemonitor.cpp @@ -943,7 +943,7 @@ namespace BlackCore CAircraftSituation correctedSituation(this->testAddAltitudeOffsetToSituation(situation)); if (!correctedSituation.hasGroundElevation() && !correctedSituation.canLikelySkipNearGroundInterpolation()) { - const CLength distance(correctedSituation.getDistancePerTime(250)); + const CLength distance(correctedSituation.getDistancePerTime(250)); // distnacee per ms const CElevationPlane ep = this->findClosestElevationWithinRangeOrRequest(correctedSituation, distance, callsign); Q_ASSERT_X(ep.isNull() || !ep.getRadius().isNull(), Q_FUNC_INFO, "null radius"); correctedSituation.setGroundElevation(ep, CAircraftSituation::FromCache); @@ -965,26 +965,15 @@ namespace BlackCore } } - this->guessOnGroundAndUpdateModelCG(correctedSituation); // does nothing if situation is not appropriate for guessing - CRemoteAircraftProvider::storeAircraftSituation(correctedSituation, false); // we already added offset if any - } - - bool CAirspaceMonitor::guessOnGroundAndUpdateModelCG(CAircraftSituation &situation) - { - const CCallsign callsign(situation.getCallsign()); - CAircraftModel aircraftModel = this->getAircraftInRangeModelForCallsign(callsign); + // CG from provider const CLength cg = this->getCG(callsign); // always x-check against simulator to override guessed values and reflect changed CGs - if (!cg.isNull() && aircraftModel.getCG() != cg) + if (!cg.isNull()) { - aircraftModel.setCG(cg); - this->updateCG(callsign, cg); // model's CG in remote provider + correctedSituation.setCG(cg); } - if (!cg.isNull()) { situation.setCG(cg); } - const CAircraftSituationChange change = this->remoteAircraftSituationChange(callsign); - - if (!situation.shouldGuessOnGround()) { return false; } - return situation.guessOnGround(change, aircraftModel); + // store change object + CRemoteAircraftProvider::storeAircraftSituation(correctedSituation, false); // we already added offset if any } void CAirspaceMonitor::sendInitialAtcQueries(const CCallsign &callsign) diff --git a/src/blackcore/airspacemonitor.h b/src/blackcore/airspacemonitor.h index 1864314e0..79aef0209 100644 --- a/src/blackcore/airspacemonitor.h +++ b/src/blackcore/airspacemonitor.h @@ -174,10 +174,6 @@ namespace BlackCore CAirspaceAnalyzer *m_analyzer = nullptr; //!< owned analyzer bool m_bookingsRequested = false; //!< bookings have been requested, it can happen we receive an BlackCore::Vatsim::CVatsimBookingReader::atcBookingsReadUnchanged signal - //! Guess situation "on ground" and update model's CG if applicable - //! \remark updates CG and ground flag in situation - bool guessOnGroundAndUpdateModelCG(BlackMisc::Aviation::CAircraftSituation &situation); - //! Remove ATC online stations void removeAllOnlineAtcStations(); diff --git a/src/blackcore/context/contextnetworkimpl.cpp b/src/blackcore/context/contextnetworkimpl.cpp index d456f3bbf..5ea2d5cdd 100644 --- a/src/blackcore/context/contextnetworkimpl.cpp +++ b/src/blackcore/context/contextnetworkimpl.cpp @@ -145,12 +145,24 @@ namespace BlackCore return m_airspace->remoteAircraftSupportingParts(); } + Aviation::CAircraftSituationChangeList CContextNetwork::remoteAircraftSituationChanges(const CCallsign &callsign) const + { + Q_ASSERT(m_airspace); + return m_airspace->remoteAircraftSituationChanges(callsign); + } + + int CContextNetwork::remoteAircraftSituationChangesCount(const CCallsign &callsign) const + { + Q_ASSERT(m_airspace); + return m_airspace->remoteAircraftSituationChangesCount(callsign); + } + QList CContextNetwork::connectRemoteAircraftProviderSignals( QObject *receiver, std::function situationSlot, std::function partsSlot, std::function removedAircraftSlot, - std::function aircraftSnapshotSlot) + std::function aircraftSnapshotSlot) { Q_ASSERT_X(m_airspace, Q_FUNC_INFO, "Missing airspace"); return m_airspace->connectRemoteAircraftProviderSignals(receiver, situationSlot, partsSlot, removedAircraftSlot, aircraftSnapshotSlot); @@ -166,7 +178,7 @@ namespace BlackCore CStatusMessage CContextNetwork::connectToNetwork(const CServer &server, INetwork::LoginMode mode) { - if (this->isDebugEnabled()) {CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; } + if (this->isDebugEnabled()) { CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO; } QString msg; if (!server.getUser().hasCredentials()) { return CStatusMessage({ CLogCategory::validation() }, CStatusMessage::SeverityError, "Invalid user credentials"); } if (!this->ownAircraft().getAircraftIcaoCode().hasDesignator()) { return CStatusMessage({ CLogCategory::validation() }, CStatusMessage::SeverityError, "Invalid ICAO data for own aircraft"); } diff --git a/src/blackcore/context/contextnetworkimpl.h b/src/blackcore/context/contextnetworkimpl.h index 4ae4ba50f..0fa1281de 100644 --- a/src/blackcore/context/contextnetworkimpl.h +++ b/src/blackcore/context/contextnetworkimpl.h @@ -97,6 +97,8 @@ namespace BlackCore virtual int remoteAircraftPartsCount(const BlackMisc::Aviation::CCallsign &callsign) const override; virtual bool isRemoteAircraftSupportingParts(const BlackMisc::Aviation::CCallsign &callsign) const override; virtual BlackMisc::Aviation::CCallsignSet remoteAircraftSupportingParts() const override; + virtual BlackMisc::Aviation::CAircraftSituationChangeList remoteAircraftSituationChanges(const BlackMisc::Aviation::CCallsign &callsign) const override; + virtual int remoteAircraftSituationChangesCount(const BlackMisc::Aviation::CCallsign &callsign) const override; virtual QList connectRemoteAircraftProviderSignals( QObject *receiver, std::function addedSituationSlot, diff --git a/src/blackmisc/aviation/aircraftsituationlist.cpp b/src/blackmisc/aviation/aircraftsituationlist.cpp index 0f4495c31..013273ca0 100644 --- a/src/blackmisc/aviation/aircraftsituationlist.cpp +++ b/src/blackmisc/aviation/aircraftsituationlist.cpp @@ -51,19 +51,16 @@ namespace BlackMisc return c; } - int CAircraftSituationList::setGroundElevationCheckedAndGuessGround(const CElevationPlane &elevationPlane, CAircraftSituation::GndElevationInfo info, const CAircraftModel &model) + int CAircraftSituationList::setGroundElevationCheckedAndGuessGround(const CElevationPlane &elevationPlane, CAircraftSituation::GndElevationInfo info, const CAircraftModel &model, CAircraftSituationChange *changeOut) { if (elevationPlane.isNull()) { return 0; } if (this->isEmpty()) { return 0; } - Q_ASSERT_X(this->isSortedAdjustedLatestFirstWithoutNullPositions(), Q_FUNC_INFO, "Need sorted situations without NULL positions"); + Q_ASSERT_X(m_tsAdjustedSortHint == CAircraftSituationList::AdjustedTimestampLatestFirst || this->isSortedAdjustedLatestFirstWithoutNullPositions(), Q_FUNC_INFO, "Need sorted situations without NULL positions"); const CAircraftSituationChange change(*this, model.getCG(), model.isVtol(), true, true); + if (changeOut) { *changeOut = change; } // copy over int c = 0; - bool first = true; - if (this->front().getCallsign().equalsString("AFL2353")) - { - c = 0; - } + bool latest = true; for (CAircraftSituation &s : *this) { @@ -71,10 +68,11 @@ namespace BlackMisc if (set) { // change is only valid for the latest situation - s.guessOnGround(first ? change : CAircraftSituationChange::null(), model); + // this will do nothing if not appropriate + s.guessOnGround(latest ? change : CAircraftSituationChange::null(), model); c++; } - first = false; + latest = false; } return c; } diff --git a/src/blackmisc/aviation/aircraftsituationlist.h b/src/blackmisc/aviation/aircraftsituationlist.h index d9138fff1..2a65a04b7 100644 --- a/src/blackmisc/aviation/aircraftsituationlist.h +++ b/src/blackmisc/aviation/aircraftsituationlist.h @@ -60,7 +60,7 @@ namespace BlackMisc //! Set ground elevation from elevation plane and guess ground //! \note requires a sorted list latest first - int setGroundElevationCheckedAndGuessGround(const Geo::CElevationPlane &elevationPlane, CAircraftSituation::GndElevationInfo info, const Simulation::CAircraftModel &model); + int setGroundElevationCheckedAndGuessGround(const Geo::CElevationPlane &elevationPlane, CAircraftSituation::GndElevationInfo info, const Simulation::CAircraftModel &model, CAircraftSituationChange *changeOut); //! Adjust flag from parts by using CAircraftSituation::adjustGroundFlag int adjustGroundFlag(const CAircraftParts &parts, double timeDeviationFactor = 0.1); diff --git a/src/blackmisc/simulation/remoteaircraftprovider.cpp b/src/blackmisc/simulation/remoteaircraftprovider.cpp index 9f395bec1..7fc8d513c 100644 --- a/src/blackmisc/simulation/remoteaircraftprovider.cpp +++ b/src/blackmisc/simulation/remoteaircraftprovider.cpp @@ -24,19 +24,6 @@ namespace BlackMisc { namespace Simulation { - CAircraftSituationChange IRemoteAircraftProvider::remoteAircraftSituationChange(const CCallsign &callsign) const - { - const CAircraftSituationList situations(this->remoteAircraftSituations(callsign)); - if (situations.isEmpty()) { return CAircraftSituationChange::null(); } - if (CBuildConfig::isLocalDeveloperDebugBuild()) - { - Q_ASSERT_X(situations.isSortedAdjustedLatestFirstWithoutNullPositions(), Q_FUNC_INFO, "Expect latest first"); - } - const CAircraftModel model = this->getAircraftInRangeModelForCallsign(callsign); - const CAircraftSituationChange change = CAircraftSituationChange(situations, model.getCG(), model.isVtol(), true, true); - return change; - } - const CLogCategoryList &CRemoteAircraftProvider::getLogCategories() { static const CLogCategoryList cats { CLogCategory::matching(), CLogCategory::network() }; @@ -48,13 +35,20 @@ namespace BlackMisc CSimulatedAircraftList CRemoteAircraftProvider::getAircraftInRange() const { - QReadLocker l(&m_lockAircraft); - return m_aircraftInRange; + QList aircraft; + { + QReadLocker l(&m_lockAircraft); + aircraft = m_aircraftInRange.values(); + } + return aircraft; } CCallsignSet CRemoteAircraftProvider::getAircraftInRangeCallsigns() const { - return this->getAircraftInRange().getCallsigns(); + QReadLocker l(&m_lockAircraft); + const QList callsigns = m_aircraftInRange.keys(); + l.unlock(); + return CCallsignSet(callsigns); } CSimulatedAircraft CRemoteAircraftProvider::getAircraftInRangeForCallsign(const CCallsign &callsign) const @@ -65,14 +59,14 @@ namespace BlackMisc CAircraftModel CRemoteAircraftProvider::getAircraftInRangeModelForCallsign(const CCallsign &callsign) const { - const CSimulatedAircraft aircraft(getAircraftInRangeForCallsign(callsign)); // threadsafe + const CSimulatedAircraft aircraft(this->getAircraftInRangeForCallsign(callsign)); // threadsafe return aircraft.getModel(); } CAircraftSituationList CRemoteAircraftProvider::remoteAircraftSituations(const CCallsign &callsign) const { - QReadLocker l(&m_lockSituations); static const CAircraftSituationList empty; + QReadLocker l(&m_lockSituations); if (!m_situationsByCallsign.contains(callsign)) { return empty; } return m_situationsByCallsign[callsign]; } @@ -94,8 +88,9 @@ namespace BlackMisc int CRemoteAircraftProvider::remoteAircraftPartsCount(const CCallsign &callsign) const { - const int s = this->remoteAircraftParts(callsign).size(); - return s; + QReadLocker l(&m_lockParts); + if (!m_partsByCallsign.contains(callsign)) { return -1; } + return m_partsByCallsign[callsign].size(); } bool CRemoteAircraftProvider::isRemoteAircraftSupportingParts(const CCallsign &callsign) const @@ -116,16 +111,28 @@ namespace BlackMisc return m_aircraftWithParts; } + CAircraftSituationChangeList CRemoteAircraftProvider::remoteAircraftSituationChanges(const CCallsign &callsign) const + { + QReadLocker l(&m_lockChanges); + return m_changesByCallsign[callsign]; + } + + int CRemoteAircraftProvider::remoteAircraftSituationChangesCount(const CCallsign &callsign) const + { + QReadLocker l(&m_lockChanges); + return m_changesByCallsign[callsign].size(); + } + int CRemoteAircraftProvider::getAircraftInRangeCount() const { - return this->getAircraftInRange().size(); + QReadLocker l(&m_lockAircraft); + return m_aircraftInRange.size(); } void CRemoteAircraftProvider::removeAllAircraft() { - for (const CSimulatedAircraft &aircraft : getAircraftInRange()) + for (const CCallsign &cs : this->getAircraftInRangeCallsigns()) { - const CCallsign cs(aircraft.getCallsign()); emit this->removedAircraft(cs); } @@ -144,7 +151,12 @@ namespace BlackMisc m_situationsLastModified.clear(); m_testOffset.clear(); } - { QWriteLocker l(&m_lockPartsHistory); m_aircraftPartsHistory.clear(); } + { + QWriteLocker l(&m_lockChanges); + m_changesByCallsign.clear(); + } + + { QWriteLocker l(&m_lockPartsHistory); m_aircraftPartsMessages.clear(); } { QWriteLocker l(&m_lockMessages); m_reverseLookupMessages.clear(); } { QWriteLocker l(&m_lockAircraft); m_aircraftInRange.clear(); } } @@ -158,10 +170,11 @@ namespace BlackMisc bool CRemoteAircraftProvider::addNewAircraftInRange(const CSimulatedAircraft &aircraft) { if (this->isAircraftInRange(aircraft.getCallsign())) { return false; } + // store { QWriteLocker l(&m_lockAircraft); - m_aircraftInRange.push_back(aircraft); + m_aircraftInRange.insert(aircraft.getCallsign(), aircraft); } emit this->addedAircraft(aircraft); emit this->changedAircraftInRange(); @@ -174,7 +187,8 @@ namespace BlackMisc int c = 0; { QWriteLocker l(&m_lockAircraft); - c = m_aircraftInRange.applyIfCallsign(callsign, vm, skipEqualValues); + if (!m_aircraftInRange.contains(callsign)) { return 0; } + c = m_aircraftInRange[callsign].apply(vm, skipEqualValues).size(); } if (c > 0) { @@ -197,39 +211,69 @@ namespace BlackMisc // add offset (for testing only) CAircraftSituation situationCorrected(allowTestOffset ? this->testAddAltitudeOffsetToSituation(situation) : situation); - // list from new to old - const qint64 ts = QDateTime::currentMSecsSinceEpoch(); + // CG, model + const CAircraftModel aircraftModel = this->getAircraftInRangeModelForCallsign(cs); + if (situation.hasCG() && aircraftModel.getCG() != situation.getCG()) { + this->updateCG(cs, situation.getCG()); + } + + // list from new to old + { + const qint64 ts = QDateTime::currentMSecsSinceEpoch(); QWriteLocker lock(&m_lockSituations); m_situationsAdded++; m_situationsLastModified[cs] = ts; - CAircraftSituationList &situationList = m_situationsByCallsign[cs]; - const int situations = situationList.size(); + CAircraftSituationList &newSituationsList = m_situationsByCallsign[cs]; + const int situations = newSituationsList.size(); if (situations < 1) { - situationList.prefillLatestAdjustedFirst(situationCorrected, IRemoteAircraftProvider::MaxSituationsPerCallsign); + newSituationsList.prefillLatestAdjustedFirst(situationCorrected, IRemoteAircraftProvider::MaxSituationsPerCallsign); } else { - situationList.front().transferGroundElevation(situationCorrected); // transfer last situation if possible - situationList.push_frontKeepLatestFirstAdjustOffset(situationCorrected, true, IRemoteAircraftProvider::MaxSituationsPerCallsign); - situationList.setAdjustedSortHint(CAircraftSituationList::AdjustedTimestampLatestFirst); + newSituationsList.front().transferGroundElevation(situationCorrected); // transfer last situation elevation if possible + newSituationsList.push_frontKeepLatestFirstAdjustOffset(situationCorrected, true, IRemoteAircraftProvider::MaxSituationsPerCallsign); + newSituationsList.setAdjustedSortHint(CAircraftSituationList::AdjustedTimestampLatestFirst); // unify all inbound ground information if (situation.hasInboundGroundDetails()) { - situationList.setOnGroundDetails(situation.getOnGroundDetails()); + newSituationsList.setOnGroundDetails(situation.getOnGroundDetails()); } } // check sort order if (CBuildConfig::isLocalDeveloperDebugBuild()) { - BLACK_VERIFY_X(situationList.isSortedAdjustedLatestFirstWithoutNullPositions(), Q_FUNC_INFO, "wrong sort order"); - BLACK_VERIFY_X(situationList.size() <= IRemoteAircraftProvider::MaxSituationsPerCallsign, Q_FUNC_INFO, "Wrong size"); + BLACK_VERIFY_X(newSituationsList.isSortedAdjustedLatestFirstWithoutNullPositions(), Q_FUNC_INFO, "wrong sort order"); + BLACK_VERIFY_X(newSituationsList.size() <= IRemoteAircraftProvider::MaxSituationsPerCallsign, Q_FUNC_INFO, "Wrong size"); } } // lock + CAircraftSituationList updatedSituations; // copy of updated situations + if (situation.hasInboundGroundDetails()) + { + QReadLocker lock(&m_lockSituations); + updatedSituations = m_situationsByCallsign[cs]; + } + else + { + // first use a version without standard deviations to guess "on ground + const CAircraftSituationChange simpleChange(updatedSituations, situationCorrected.getCG(), aircraftModel.isVtol(), true, false); + + // guess GND + QWriteLocker lock(&m_lockSituations); + CAircraftSituationList &fixedSituationList = m_situationsByCallsign[cs]; + fixedSituationList.front().guessOnGround(simpleChange, aircraftModel); + updatedSituations = fixedSituationList; + } + + // calculate change AFTER gnd. was guessed + Q_ASSERT_X(!updatedSituations.isEmpty(), Q_FUNC_INFO, "Missing situations"); + const CAircraftSituationChange change(updatedSituations, situationCorrected.getCG(), aircraftModel.isVtol(), true, true); + this->storeChange(change); + emit this->addedAircraftSituation(situationCorrected); } @@ -270,8 +314,12 @@ namespace BlackMisc // update aircraft { QWriteLocker l(&m_lockAircraft); - const int c = m_aircraftInRange.setAircraftPartsSynchronized(callsign, parts); - Q_UNUSED(c); + if (m_aircraftInRange.contains(callsign)) + { + CSimulatedAircraft &aircraft = m_aircraftInRange[callsign]; + aircraft.setParts(parts); + aircraft.setPartsSynchronized(true); + } } // update parts @@ -331,18 +379,33 @@ namespace BlackMisc const CStatusMessage message(getLogCategories(), CStatusMessage::SeverityInfo, callsign.isEmpty() ? callsign.toQString() + ": " + partsAsString.trimmed() : partsAsString.trimmed()); QReadLocker l(&m_lockPartsHistory); - if (m_aircraftPartsHistory.contains(callsign)) + if (m_aircraftPartsMessages.contains(callsign)) { - CStatusMessageList &msgs = m_aircraftPartsHistory[callsign]; + CStatusMessageList &msgs = m_aircraftPartsMessages[callsign]; msgs.push_back(message); } else { - m_aircraftPartsHistory.insert(callsign, message); + m_aircraftPartsMessages.insert(callsign, message); } } } + void CRemoteAircraftProvider::storeChange(const CAircraftSituationChange &change) + { + QWriteLocker lock(&m_lockChanges); + const CCallsign cs(change.getCallsign()); + CAircraftSituationChangeList &changeList = m_changesByCallsign[cs]; + changeList.push_frontKeepLatestAdjustedFirst(change, true, IRemoteAircraftProvider::MaxSituationsPerCallsign); + } + + bool CRemoteAircraftProvider::guessOnGroundAndUpdateModelCG(CAircraftSituation &situation, const CAircraftSituationChange &change, const CAircraftModel &aircraftModel) + { + if (aircraftModel.hasCG() && !situation.hasCG()) { situation.setCG(aircraftModel.getCG()); } + if (!situation.shouldGuessOnGround()) { return false; } + return situation.guessOnGround(change, aircraftModel); + } + bool CRemoteAircraftProvider::updateAircraftEnabled(const CCallsign &callsign, bool enabledForRendering) { const CPropertyIndexVariantMap vm(CSimulatedAircraft::IndexEnabled, CVariant::fromValue(enabledForRendering)); @@ -369,15 +432,15 @@ namespace BlackMisc bool CRemoteAircraftProvider::updateFastPositionEnabled(const CCallsign &callsign, bool enableFastPositonUpdates) { QWriteLocker l(&m_lockAircraft); - const int c = m_aircraftInRange.setFastPositionUpdates(callsign, enableFastPositonUpdates); - return c > 0; + if (!m_aircraftInRange.contains(callsign)) { return false; } + return m_aircraftInRange[callsign].setFastPositionUpdates(enableFastPositonUpdates); } bool CRemoteAircraftProvider::updateAircraftRendered(const CCallsign &callsign, bool rendered) { QWriteLocker l(&m_lockAircraft); - const int c = m_aircraftInRange.setRendered(callsign, rendered); - return c > 0; + if (!m_aircraftInRange.contains(callsign)) { return false; } + return m_aircraftInRange[callsign].setRendered(rendered); } int CRemoteAircraftProvider::updateAircraftGroundElevation(const CCallsign &callsign, const CElevationPlane &elevation, CAircraftSituation::GndElevationInfo info) @@ -387,19 +450,28 @@ namespace BlackMisc // update aircraft situation const qint64 ts = QDateTime::currentMSecsSinceEpoch(); const CAircraftModel model = this->getAircraftInRangeModelForCallsign(callsign); + CAircraftSituationChange change; int updated = 0; { QWriteLocker l(&m_lockSituations); CAircraftSituationList &situations = m_situationsByCallsign[callsign]; - updated = situations.setGroundElevationCheckedAndGuessGround(elevation, info, model); + updated = situations.setGroundElevationCheckedAndGuessGround(elevation, info, model, &change); if (updated < 1) { return 0; } m_situationsLastModified[callsign] = ts; } + // update change + if (!change.isNull()) + { + this->storeChange(change); + } + // aircraft updates QWriteLocker l(&m_lockAircraft); - const int c = m_aircraftInRange.setGroundElevationChecked(callsign, elevation, info); - Q_UNUSED(c); // just for info, expect 1 + if (m_aircraftInRange.contains(callsign)) + { + m_aircraftInRange[callsign].setGroundElevationChecked(elevation, info); + } return updated; // updated situations } @@ -407,14 +479,19 @@ namespace BlackMisc bool CRemoteAircraftProvider::updateCG(const CCallsign &callsign, const CLength &cg) { QWriteLocker l(&m_lockAircraft); - const int c = m_aircraftInRange.setCG(callsign, cg); - return c > 0; + if (!m_aircraftInRange.contains(callsign)) { return false; } + m_aircraftInRange[callsign].setCG(cg); + return true; } void CRemoteAircraftProvider::updateMarkAllAsNotRendered() { + const CCallsignSet callsigns = this->getAircraftInRangeCallsigns(); QWriteLocker l(&m_lockAircraft); - m_aircraftInRange.markAllAsNotRendered(); + for (const CCallsign &cs : callsigns) + { + m_aircraftInRange[cs].setRendered(false); + } } void CRemoteAircraftProvider::enableReverseLookupMessages(bool enabled) @@ -506,7 +583,7 @@ namespace BlackMisc CStatusMessageList CRemoteAircraftProvider::getAircraftPartsHistory(const CCallsign &callsign) const { QReadLocker l(&m_lockPartsHistory); - return m_aircraftPartsHistory.value(callsign); + return m_aircraftPartsMessages.value(callsign); } bool CRemoteAircraftProvider::isAircraftPartsHistoryEnabled() const @@ -563,7 +640,7 @@ namespace BlackMisc { if (callsign.isEmpty()) { return false; } QReadLocker l(&m_lockAircraft); - return m_aircraftInRange.containsCallsign(callsign); + return m_aircraftInRange.contains(callsign); } bool CRemoteAircraftProvider::isVtolAircraft(const CCallsign &callsign) const @@ -599,11 +676,11 @@ namespace BlackMisc { { QWriteLocker l1(&m_lockParts); m_partsByCallsign.remove(callsign); m_aircraftWithParts.remove(callsign); m_partsLastModified.remove(callsign); } { QWriteLocker l2(&m_lockSituations); m_situationsByCallsign.remove(callsign); m_situationsLastModified.remove(callsign); } - { QWriteLocker l4(&m_lockPartsHistory); m_aircraftPartsHistory.remove(callsign); } + { QWriteLocker l4(&m_lockPartsHistory); m_aircraftPartsMessages.remove(callsign); } bool removedCallsign = false; { QWriteLocker l(&m_lockAircraft); - const int c = m_aircraftInRange.removeByCallsign(callsign); + const int c = m_aircraftInRange.remove(callsign); removedCallsign = c > 0; } return removedCallsign; @@ -663,10 +740,10 @@ namespace BlackMisc return this->provider()->remoteAircraftSituations(callsign); } - CAircraftSituationChange CRemoteAircraftAware::remoteAircraftSituationChange(const CCallsign &callsign) const + CAircraftSituationChangeList CRemoteAircraftAware::remoteAircraftSituationChanges(const CCallsign &callsign) const { Q_ASSERT_X(this->provider(), Q_FUNC_INFO, "No object available"); - return this->provider()->remoteAircraftSituationChange(callsign); + return this->provider()->remoteAircraftSituationChanges(callsign); } CAircraftPartsList CRemoteAircraftAware::remoteAircraftParts(const CCallsign &callsign) const diff --git a/src/blackmisc/simulation/remoteaircraftprovider.h b/src/blackmisc/simulation/remoteaircraftprovider.h index b3208f6d2..4eeacb82b 100644 --- a/src/blackmisc/simulation/remoteaircraftprovider.h +++ b/src/blackmisc/simulation/remoteaircraftprovider.h @@ -18,7 +18,7 @@ #include "blackmisc/simulation/simulatedaircraftlist.h" #include "blackmisc/aviation/aircraftpartslist.h" #include "blackmisc/aviation/aircraftsituationlist.h" -#include "blackmisc/aviation/aircraftsituationchange.h" +#include "blackmisc/aviation/aircraftsituationchangelist.h" #include "blackmisc/aviation/percallsign.h" #include "blackmisc/aviation/callsignset.h" #include "blackmisc/provider.h" @@ -101,10 +101,6 @@ namespace BlackMisc //! \threadsafe virtual int remoteAircraftPartsCount(const Aviation::CCallsign &callsign) const = 0; - //! Get the change object for callsign - //! \threadsafe - Aviation::CAircraftSituationChange remoteAircraftSituationChange(const Aviation::CCallsign &callsign) const; - //! Is remote aircraft supporting parts? //! \threadsafe virtual bool isRemoteAircraftSupportingParts(const Aviation::CCallsign &callsign) const = 0; @@ -121,6 +117,14 @@ namespace BlackMisc //! \threadsafe virtual Aviation::CCallsignSet remoteAircraftSupportingParts() const = 0; + //! Aircraft changes. + //! \threadsafe + virtual Aviation::CAircraftSituationChangeList remoteAircraftSituationChanges(const Aviation::CCallsign &callsign) const = 0; + + //! Aircraft changes count. + //! \threadsafe + virtual int remoteAircraftSituationChangesCount(const Aviation::CCallsign &callsign) const = 0; + //! Enable/disable enabled aircraft //! \threadsafe virtual bool updateAircraftEnabled(const Aviation::CCallsign &callsign, bool enabledForRendering) = 0; @@ -251,6 +255,8 @@ namespace BlackMisc virtual bool isRemoteAircraftSupportingParts(const Aviation::CCallsign &callsign) const override; virtual int getRemoteAircraftSupportingPartsCount() const override; virtual Aviation::CCallsignSet remoteAircraftSupportingParts() const override; + virtual Aviation::CAircraftSituationChangeList remoteAircraftSituationChanges(const Aviation::CCallsign &callsign) const override; + virtual int remoteAircraftSituationChangesCount(const Aviation::CCallsign &callsign) const override; virtual bool updateAircraftEnabled(const Aviation::CCallsign &callsign, bool enabledForRendering) override; virtual bool updateAircraftModel(const Aviation::CCallsign &callsign, const CAircraftModel &model, const CIdentifier &originator) override; virtual bool updateAircraftNetworkModel(const Aviation::CCallsign &callsign, const CAircraftModel &model, const CIdentifier &originator) override; @@ -369,22 +375,32 @@ namespace BlackMisc void storeAircraftParts(const Aviation::CCallsign &callsign, const QJsonObject &jsonObject, int currentOffset); //! @} + //! Guess situation "on ground" and update model's CG if applicable + //! \remark updates CG and ground flag in situation + bool guessOnGroundAndUpdateModelCG(Aviation::CAircraftSituation &situation, const Aviation::CAircraftSituationChange &change, const CAircraftModel &aircraftModel); + //! Add an offset for testing Aviation::CAircraftSituation testAddAltitudeOffsetToSituation(const Aviation::CAircraftSituation &situation) const; private: - Aviation::CAircraftSituationListPerCallsign m_situationsByCallsign; //!< situations, for performance reasons per callsign, thread safe access required - Aviation::CAircraftPartsListPerCallsign m_partsByCallsign; //!< parts, for performance reasons per callsign, thread safe access required - Aviation::CCallsignSet m_aircraftWithParts; //!< aircraft supporting parts, thread safe access required + //! Store the latest changes + //! \remark latest first + //! \threadsafe + void storeChange(const Aviation::CAircraftSituationChange &change); + + Aviation::CAircraftSituationListPerCallsign m_situationsByCallsign; //!< situations, for performance reasons per callsign, thread safe access required + Aviation::CAircraftPartsListPerCallsign m_partsByCallsign; //!< parts, for performance reasons per callsign, thread safe access required + Aviation::CAircraftSituationChangeListPerCallsign m_changesByCallsign; //!< changes, for performance reasons per callsign, thread safe access required + Aviation::CCallsignSet m_aircraftWithParts; //!< aircraft supporting parts, thread safe access required int m_situationsAdded = 0; //!< total number of situations added, thread safe access required int m_partsAdded = 0; //!< total number of parts added, thread safe access required - CSimulatedAircraftList m_aircraftInRange; //!< aircraft, thread safe access required + Simulation::CSimulatedAircraftPerCallsign m_aircraftInRange; //!< aircraft, thread safe access required Aviation::CStatusMessageListPerCallsign m_reverseLookupMessages; //!< reverse lookup messages Aviation::CStatusMessageListPerCallsign m_aircraftPartsMessages; //!< status messages for parts history - Aviation::CTimestampPerCallsign m_situationsLastModified; //!< when situations last modified - Aviation::CTimestampPerCallsign m_partsLastModified; //!< when parts last modified - QHash m_testOffset; + Aviation::CTimestampPerCallsign m_situationsLastModified; //!< when situations last modified + Aviation::CTimestampPerCallsign m_partsLastModified; //!< when parts last modified + Aviation::CLengthPerCallsign m_testOffset; //!< offsets bool m_enableReverseLookupMsgs = false; //!< shall we log. information about the matching process bool m_enableAircraftPartsHistory = true; //!< shall we keep a history of aircraft parts @@ -392,6 +408,7 @@ namespace BlackMisc // locks mutable QReadWriteLock m_lockSituations; //!< lock for situations: m_situationsByCallsign mutable QReadWriteLock m_lockParts; //!< lock for parts: m_partsByCallsign, m_aircraftSupportingParts + mutable QReadWriteLock m_lockChanges; //!< lock for changes: m_changesByCallsign mutable QReadWriteLock m_lockAircraft; //!< lock aircraft: m_aircraftInRange mutable QReadWriteLock m_lockMessages; //!< lock for messages mutable QReadWriteLock m_lockPartsHistory; //!< lock for aircraft parts @@ -437,8 +454,8 @@ namespace BlackMisc //! \copydoc IRemoteAircraftProvider::remoteAircraftPartsCount int remoteAircraftPartsCount(const Aviation::CCallsign &callsign) const; - //! \copydoc IRemoteAircraftProvider::remoteAircraftSituationChange - Aviation::CAircraftSituationChange remoteAircraftSituationChange(const Aviation::CCallsign &callsign) const; + //! \copydoc IRemoteAircraftProvider::remoteAircraftSituationChanges + Aviation::CAircraftSituationChangeList remoteAircraftSituationChanges(const Aviation::CCallsign &callsign) const; //! \copydoc IRemoteAircraftProvider::remoteAircraftSupportingParts Aviation::CCallsignSet remoteAircraftSupportingParts() const;