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"
This commit is contained in:
Klaus Basan
2018-06-13 23:19:58 +02:00
parent d49831abc4
commit 3467bef45c
8 changed files with 196 additions and 105 deletions

View File

@@ -943,7 +943,7 @@ namespace BlackCore
CAircraftSituation correctedSituation(this->testAddAltitudeOffsetToSituation(situation)); CAircraftSituation correctedSituation(this->testAddAltitudeOffsetToSituation(situation));
if (!correctedSituation.hasGroundElevation() && !correctedSituation.canLikelySkipNearGroundInterpolation()) 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); const CElevationPlane ep = this->findClosestElevationWithinRangeOrRequest(correctedSituation, distance, callsign);
Q_ASSERT_X(ep.isNull() || !ep.getRadius().isNull(), Q_FUNC_INFO, "null radius"); Q_ASSERT_X(ep.isNull() || !ep.getRadius().isNull(), Q_FUNC_INFO, "null radius");
correctedSituation.setGroundElevation(ep, CAircraftSituation::FromCache); correctedSituation.setGroundElevation(ep, CAircraftSituation::FromCache);
@@ -965,26 +965,15 @@ namespace BlackCore
} }
} }
this->guessOnGroundAndUpdateModelCG(correctedSituation); // does nothing if situation is not appropriate for guessing // CG from provider
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);
const CLength cg = this->getCG(callsign); // always x-check against simulator to override guessed values and reflect changed CGs 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); correctedSituation.setCG(cg);
this->updateCG(callsign, cg); // model's CG in remote provider
} }
if (!cg.isNull()) { situation.setCG(cg); } // store change object
const CAircraftSituationChange change = this->remoteAircraftSituationChange(callsign); CRemoteAircraftProvider::storeAircraftSituation(correctedSituation, false); // we already added offset if any
if (!situation.shouldGuessOnGround()) { return false; }
return situation.guessOnGround(change, aircraftModel);
} }
void CAirspaceMonitor::sendInitialAtcQueries(const CCallsign &callsign) void CAirspaceMonitor::sendInitialAtcQueries(const CCallsign &callsign)

View File

@@ -174,10 +174,6 @@ namespace BlackCore
CAirspaceAnalyzer *m_analyzer = nullptr; //!< owned analyzer 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 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 //! Remove ATC online stations
void removeAllOnlineAtcStations(); void removeAllOnlineAtcStations();

View File

@@ -145,12 +145,24 @@ namespace BlackCore
return m_airspace->remoteAircraftSupportingParts(); 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<QMetaObject::Connection> CContextNetwork::connectRemoteAircraftProviderSignals( QList<QMetaObject::Connection> CContextNetwork::connectRemoteAircraftProviderSignals(
QObject *receiver, QObject *receiver,
std::function<void (const CAircraftSituation &)> situationSlot, std::function<void (const CAircraftSituation &)> situationSlot,
std::function<void (const CCallsign &, const CAircraftParts &)> partsSlot, std::function<void (const CCallsign &, const CAircraftParts &)> partsSlot,
std::function<void (const CCallsign &)> removedAircraftSlot, std::function<void (const CCallsign &)> removedAircraftSlot,
std::function<void (const BlackMisc::Simulation::CAirspaceAircraftSnapshot &)> aircraftSnapshotSlot) std::function<void (const CAirspaceAircraftSnapshot &)> aircraftSnapshotSlot)
{ {
Q_ASSERT_X(m_airspace, Q_FUNC_INFO, "Missing airspace"); Q_ASSERT_X(m_airspace, Q_FUNC_INFO, "Missing airspace");
return m_airspace->connectRemoteAircraftProviderSignals(receiver, situationSlot, partsSlot, removedAircraftSlot, aircraftSnapshotSlot); return m_airspace->connectRemoteAircraftProviderSignals(receiver, situationSlot, partsSlot, removedAircraftSlot, aircraftSnapshotSlot);
@@ -166,7 +178,7 @@ namespace BlackCore
CStatusMessage CContextNetwork::connectToNetwork(const CServer &server, INetwork::LoginMode mode) 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; QString msg;
if (!server.getUser().hasCredentials()) { return CStatusMessage({ CLogCategory::validation() }, CStatusMessage::SeverityError, "Invalid user credentials"); } 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"); } if (!this->ownAircraft().getAircraftIcaoCode().hasDesignator()) { return CStatusMessage({ CLogCategory::validation() }, CStatusMessage::SeverityError, "Invalid ICAO data for own aircraft"); }

View File

@@ -97,6 +97,8 @@ namespace BlackCore
virtual int remoteAircraftPartsCount(const BlackMisc::Aviation::CCallsign &callsign) const override; virtual int remoteAircraftPartsCount(const BlackMisc::Aviation::CCallsign &callsign) const override;
virtual bool isRemoteAircraftSupportingParts(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::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<QMetaObject::Connection> connectRemoteAircraftProviderSignals( virtual QList<QMetaObject::Connection> connectRemoteAircraftProviderSignals(
QObject *receiver, QObject *receiver,
std::function<void(const BlackMisc::Aviation::CAircraftSituation &)> addedSituationSlot, std::function<void(const BlackMisc::Aviation::CAircraftSituation &)> addedSituationSlot,

View File

@@ -51,19 +51,16 @@ namespace BlackMisc
return c; 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 (elevationPlane.isNull()) { return 0; }
if (this->isEmpty()) { 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); const CAircraftSituationChange change(*this, model.getCG(), model.isVtol(), true, true);
if (changeOut) { *changeOut = change; } // copy over
int c = 0; int c = 0;
bool first = true; bool latest = true;
if (this->front().getCallsign().equalsString("AFL2353"))
{
c = 0;
}
for (CAircraftSituation &s : *this) for (CAircraftSituation &s : *this)
{ {
@@ -71,10 +68,11 @@ namespace BlackMisc
if (set) if (set)
{ {
// change is only valid for the latest situation // 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++; c++;
} }
first = false; latest = false;
} }
return c; return c;
} }

View File

@@ -60,7 +60,7 @@ namespace BlackMisc
//! Set ground elevation from elevation plane and guess ground //! Set ground elevation from elevation plane and guess ground
//! \note requires a sorted list latest first //! \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 //! Adjust flag from parts by using CAircraftSituation::adjustGroundFlag
int adjustGroundFlag(const CAircraftParts &parts, double timeDeviationFactor = 0.1); int adjustGroundFlag(const CAircraftParts &parts, double timeDeviationFactor = 0.1);

View File

@@ -24,19 +24,6 @@ namespace BlackMisc
{ {
namespace Simulation 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() const CLogCategoryList &CRemoteAircraftProvider::getLogCategories()
{ {
static const CLogCategoryList cats { CLogCategory::matching(), CLogCategory::network() }; static const CLogCategoryList cats { CLogCategory::matching(), CLogCategory::network() };
@@ -48,13 +35,20 @@ namespace BlackMisc
CSimulatedAircraftList CRemoteAircraftProvider::getAircraftInRange() const CSimulatedAircraftList CRemoteAircraftProvider::getAircraftInRange() const
{ {
QReadLocker l(&m_lockAircraft); QList<CSimulatedAircraft> aircraft;
return m_aircraftInRange; {
QReadLocker l(&m_lockAircraft);
aircraft = m_aircraftInRange.values();
}
return aircraft;
} }
CCallsignSet CRemoteAircraftProvider::getAircraftInRangeCallsigns() const CCallsignSet CRemoteAircraftProvider::getAircraftInRangeCallsigns() const
{ {
return this->getAircraftInRange().getCallsigns(); QReadLocker l(&m_lockAircraft);
const QList<CCallsign> callsigns = m_aircraftInRange.keys();
l.unlock();
return CCallsignSet(callsigns);
} }
CSimulatedAircraft CRemoteAircraftProvider::getAircraftInRangeForCallsign(const CCallsign &callsign) const CSimulatedAircraft CRemoteAircraftProvider::getAircraftInRangeForCallsign(const CCallsign &callsign) const
@@ -65,14 +59,14 @@ namespace BlackMisc
CAircraftModel CRemoteAircraftProvider::getAircraftInRangeModelForCallsign(const CCallsign &callsign) const CAircraftModel CRemoteAircraftProvider::getAircraftInRangeModelForCallsign(const CCallsign &callsign) const
{ {
const CSimulatedAircraft aircraft(getAircraftInRangeForCallsign(callsign)); // threadsafe const CSimulatedAircraft aircraft(this->getAircraftInRangeForCallsign(callsign)); // threadsafe
return aircraft.getModel(); return aircraft.getModel();
} }
CAircraftSituationList CRemoteAircraftProvider::remoteAircraftSituations(const CCallsign &callsign) const CAircraftSituationList CRemoteAircraftProvider::remoteAircraftSituations(const CCallsign &callsign) const
{ {
QReadLocker l(&m_lockSituations);
static const CAircraftSituationList empty; static const CAircraftSituationList empty;
QReadLocker l(&m_lockSituations);
if (!m_situationsByCallsign.contains(callsign)) { return empty; } if (!m_situationsByCallsign.contains(callsign)) { return empty; }
return m_situationsByCallsign[callsign]; return m_situationsByCallsign[callsign];
} }
@@ -94,8 +88,9 @@ namespace BlackMisc
int CRemoteAircraftProvider::remoteAircraftPartsCount(const CCallsign &callsign) const int CRemoteAircraftProvider::remoteAircraftPartsCount(const CCallsign &callsign) const
{ {
const int s = this->remoteAircraftParts(callsign).size(); QReadLocker l(&m_lockParts);
return s; if (!m_partsByCallsign.contains(callsign)) { return -1; }
return m_partsByCallsign[callsign].size();
} }
bool CRemoteAircraftProvider::isRemoteAircraftSupportingParts(const CCallsign &callsign) const bool CRemoteAircraftProvider::isRemoteAircraftSupportingParts(const CCallsign &callsign) const
@@ -116,16 +111,28 @@ namespace BlackMisc
return m_aircraftWithParts; 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 int CRemoteAircraftProvider::getAircraftInRangeCount() const
{ {
return this->getAircraftInRange().size(); QReadLocker l(&m_lockAircraft);
return m_aircraftInRange.size();
} }
void CRemoteAircraftProvider::removeAllAircraft() void CRemoteAircraftProvider::removeAllAircraft()
{ {
for (const CSimulatedAircraft &aircraft : getAircraftInRange()) for (const CCallsign &cs : this->getAircraftInRangeCallsigns())
{ {
const CCallsign cs(aircraft.getCallsign());
emit this->removedAircraft(cs); emit this->removedAircraft(cs);
} }
@@ -144,7 +151,12 @@ namespace BlackMisc
m_situationsLastModified.clear(); m_situationsLastModified.clear();
m_testOffset.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_lockMessages); m_reverseLookupMessages.clear(); }
{ QWriteLocker l(&m_lockAircraft); m_aircraftInRange.clear(); } { QWriteLocker l(&m_lockAircraft); m_aircraftInRange.clear(); }
} }
@@ -158,10 +170,11 @@ namespace BlackMisc
bool CRemoteAircraftProvider::addNewAircraftInRange(const CSimulatedAircraft &aircraft) bool CRemoteAircraftProvider::addNewAircraftInRange(const CSimulatedAircraft &aircraft)
{ {
if (this->isAircraftInRange(aircraft.getCallsign())) { return false; } if (this->isAircraftInRange(aircraft.getCallsign())) { return false; }
// store // store
{ {
QWriteLocker l(&m_lockAircraft); QWriteLocker l(&m_lockAircraft);
m_aircraftInRange.push_back(aircraft); m_aircraftInRange.insert(aircraft.getCallsign(), aircraft);
} }
emit this->addedAircraft(aircraft); emit this->addedAircraft(aircraft);
emit this->changedAircraftInRange(); emit this->changedAircraftInRange();
@@ -174,7 +187,8 @@ namespace BlackMisc
int c = 0; int c = 0;
{ {
QWriteLocker l(&m_lockAircraft); 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) if (c > 0)
{ {
@@ -197,39 +211,69 @@ namespace BlackMisc
// add offset (for testing only) // add offset (for testing only)
CAircraftSituation situationCorrected(allowTestOffset ? this->testAddAltitudeOffsetToSituation(situation) : situation); CAircraftSituation situationCorrected(allowTestOffset ? this->testAddAltitudeOffsetToSituation(situation) : situation);
// list from new to old // CG, model
const qint64 ts = QDateTime::currentMSecsSinceEpoch(); 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); QWriteLocker lock(&m_lockSituations);
m_situationsAdded++; m_situationsAdded++;
m_situationsLastModified[cs] = ts; m_situationsLastModified[cs] = ts;
CAircraftSituationList &situationList = m_situationsByCallsign[cs]; CAircraftSituationList &newSituationsList = m_situationsByCallsign[cs];
const int situations = situationList.size(); const int situations = newSituationsList.size();
if (situations < 1) if (situations < 1)
{ {
situationList.prefillLatestAdjustedFirst(situationCorrected, IRemoteAircraftProvider::MaxSituationsPerCallsign); newSituationsList.prefillLatestAdjustedFirst(situationCorrected, IRemoteAircraftProvider::MaxSituationsPerCallsign);
} }
else else
{ {
situationList.front().transferGroundElevation(situationCorrected); // transfer last situation if possible newSituationsList.front().transferGroundElevation(situationCorrected); // transfer last situation elevation if possible
situationList.push_frontKeepLatestFirstAdjustOffset(situationCorrected, true, IRemoteAircraftProvider::MaxSituationsPerCallsign); newSituationsList.push_frontKeepLatestFirstAdjustOffset(situationCorrected, true, IRemoteAircraftProvider::MaxSituationsPerCallsign);
situationList.setAdjustedSortHint(CAircraftSituationList::AdjustedTimestampLatestFirst); newSituationsList.setAdjustedSortHint(CAircraftSituationList::AdjustedTimestampLatestFirst);
// unify all inbound ground information // unify all inbound ground information
if (situation.hasInboundGroundDetails()) if (situation.hasInboundGroundDetails())
{ {
situationList.setOnGroundDetails(situation.getOnGroundDetails()); newSituationsList.setOnGroundDetails(situation.getOnGroundDetails());
} }
} }
// check sort order // check sort order
if (CBuildConfig::isLocalDeveloperDebugBuild()) if (CBuildConfig::isLocalDeveloperDebugBuild())
{ {
BLACK_VERIFY_X(situationList.isSortedAdjustedLatestFirstWithoutNullPositions(), Q_FUNC_INFO, "wrong sort order"); BLACK_VERIFY_X(newSituationsList.isSortedAdjustedLatestFirstWithoutNullPositions(), Q_FUNC_INFO, "wrong sort order");
BLACK_VERIFY_X(situationList.size() <= IRemoteAircraftProvider::MaxSituationsPerCallsign, Q_FUNC_INFO, "Wrong size"); BLACK_VERIFY_X(newSituationsList.size() <= IRemoteAircraftProvider::MaxSituationsPerCallsign, Q_FUNC_INFO, "Wrong size");
} }
} // lock } // 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); emit this->addedAircraftSituation(situationCorrected);
} }
@@ -270,8 +314,12 @@ namespace BlackMisc
// update aircraft // update aircraft
{ {
QWriteLocker l(&m_lockAircraft); QWriteLocker l(&m_lockAircraft);
const int c = m_aircraftInRange.setAircraftPartsSynchronized(callsign, parts); if (m_aircraftInRange.contains(callsign))
Q_UNUSED(c); {
CSimulatedAircraft &aircraft = m_aircraftInRange[callsign];
aircraft.setParts(parts);
aircraft.setPartsSynchronized(true);
}
} }
// update parts // update parts
@@ -331,18 +379,33 @@ namespace BlackMisc
const CStatusMessage message(getLogCategories(), CStatusMessage::SeverityInfo, callsign.isEmpty() ? callsign.toQString() + ": " + partsAsString.trimmed() : partsAsString.trimmed()); const CStatusMessage message(getLogCategories(), CStatusMessage::SeverityInfo, callsign.isEmpty() ? callsign.toQString() + ": " + partsAsString.trimmed() : partsAsString.trimmed());
QReadLocker l(&m_lockPartsHistory); 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); msgs.push_back(message);
} }
else 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) bool CRemoteAircraftProvider::updateAircraftEnabled(const CCallsign &callsign, bool enabledForRendering)
{ {
const CPropertyIndexVariantMap vm(CSimulatedAircraft::IndexEnabled, CVariant::fromValue(enabledForRendering)); const CPropertyIndexVariantMap vm(CSimulatedAircraft::IndexEnabled, CVariant::fromValue(enabledForRendering));
@@ -369,15 +432,15 @@ namespace BlackMisc
bool CRemoteAircraftProvider::updateFastPositionEnabled(const CCallsign &callsign, bool enableFastPositonUpdates) bool CRemoteAircraftProvider::updateFastPositionEnabled(const CCallsign &callsign, bool enableFastPositonUpdates)
{ {
QWriteLocker l(&m_lockAircraft); QWriteLocker l(&m_lockAircraft);
const int c = m_aircraftInRange.setFastPositionUpdates(callsign, enableFastPositonUpdates); if (!m_aircraftInRange.contains(callsign)) { return false; }
return c > 0; return m_aircraftInRange[callsign].setFastPositionUpdates(enableFastPositonUpdates);
} }
bool CRemoteAircraftProvider::updateAircraftRendered(const CCallsign &callsign, bool rendered) bool CRemoteAircraftProvider::updateAircraftRendered(const CCallsign &callsign, bool rendered)
{ {
QWriteLocker l(&m_lockAircraft); QWriteLocker l(&m_lockAircraft);
const int c = m_aircraftInRange.setRendered(callsign, rendered); if (!m_aircraftInRange.contains(callsign)) { return false; }
return c > 0; return m_aircraftInRange[callsign].setRendered(rendered);
} }
int CRemoteAircraftProvider::updateAircraftGroundElevation(const CCallsign &callsign, const CElevationPlane &elevation, CAircraftSituation::GndElevationInfo info) int CRemoteAircraftProvider::updateAircraftGroundElevation(const CCallsign &callsign, const CElevationPlane &elevation, CAircraftSituation::GndElevationInfo info)
@@ -387,19 +450,28 @@ namespace BlackMisc
// update aircraft situation // update aircraft situation
const qint64 ts = QDateTime::currentMSecsSinceEpoch(); const qint64 ts = QDateTime::currentMSecsSinceEpoch();
const CAircraftModel model = this->getAircraftInRangeModelForCallsign(callsign); const CAircraftModel model = this->getAircraftInRangeModelForCallsign(callsign);
CAircraftSituationChange change;
int updated = 0; int updated = 0;
{ {
QWriteLocker l(&m_lockSituations); QWriteLocker l(&m_lockSituations);
CAircraftSituationList &situations = m_situationsByCallsign[callsign]; CAircraftSituationList &situations = m_situationsByCallsign[callsign];
updated = situations.setGroundElevationCheckedAndGuessGround(elevation, info, model); updated = situations.setGroundElevationCheckedAndGuessGround(elevation, info, model, &change);
if (updated < 1) { return 0; } if (updated < 1) { return 0; }
m_situationsLastModified[callsign] = ts; m_situationsLastModified[callsign] = ts;
} }
// update change
if (!change.isNull())
{
this->storeChange(change);
}
// aircraft updates // aircraft updates
QWriteLocker l(&m_lockAircraft); QWriteLocker l(&m_lockAircraft);
const int c = m_aircraftInRange.setGroundElevationChecked(callsign, elevation, info); if (m_aircraftInRange.contains(callsign))
Q_UNUSED(c); // just for info, expect 1 {
m_aircraftInRange[callsign].setGroundElevationChecked(elevation, info);
}
return updated; // updated situations return updated; // updated situations
} }
@@ -407,14 +479,19 @@ namespace BlackMisc
bool CRemoteAircraftProvider::updateCG(const CCallsign &callsign, const CLength &cg) bool CRemoteAircraftProvider::updateCG(const CCallsign &callsign, const CLength &cg)
{ {
QWriteLocker l(&m_lockAircraft); QWriteLocker l(&m_lockAircraft);
const int c = m_aircraftInRange.setCG(callsign, cg); if (!m_aircraftInRange.contains(callsign)) { return false; }
return c > 0; m_aircraftInRange[callsign].setCG(cg);
return true;
} }
void CRemoteAircraftProvider::updateMarkAllAsNotRendered() void CRemoteAircraftProvider::updateMarkAllAsNotRendered()
{ {
const CCallsignSet callsigns = this->getAircraftInRangeCallsigns();
QWriteLocker l(&m_lockAircraft); QWriteLocker l(&m_lockAircraft);
m_aircraftInRange.markAllAsNotRendered(); for (const CCallsign &cs : callsigns)
{
m_aircraftInRange[cs].setRendered(false);
}
} }
void CRemoteAircraftProvider::enableReverseLookupMessages(bool enabled) void CRemoteAircraftProvider::enableReverseLookupMessages(bool enabled)
@@ -506,7 +583,7 @@ namespace BlackMisc
CStatusMessageList CRemoteAircraftProvider::getAircraftPartsHistory(const CCallsign &callsign) const CStatusMessageList CRemoteAircraftProvider::getAircraftPartsHistory(const CCallsign &callsign) const
{ {
QReadLocker l(&m_lockPartsHistory); QReadLocker l(&m_lockPartsHistory);
return m_aircraftPartsHistory.value(callsign); return m_aircraftPartsMessages.value(callsign);
} }
bool CRemoteAircraftProvider::isAircraftPartsHistoryEnabled() const bool CRemoteAircraftProvider::isAircraftPartsHistoryEnabled() const
@@ -563,7 +640,7 @@ namespace BlackMisc
{ {
if (callsign.isEmpty()) { return false; } if (callsign.isEmpty()) { return false; }
QReadLocker l(&m_lockAircraft); QReadLocker l(&m_lockAircraft);
return m_aircraftInRange.containsCallsign(callsign); return m_aircraftInRange.contains(callsign);
} }
bool CRemoteAircraftProvider::isVtolAircraft(const CCallsign &callsign) const 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 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 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; bool removedCallsign = false;
{ {
QWriteLocker l(&m_lockAircraft); QWriteLocker l(&m_lockAircraft);
const int c = m_aircraftInRange.removeByCallsign(callsign); const int c = m_aircraftInRange.remove(callsign);
removedCallsign = c > 0; removedCallsign = c > 0;
} }
return removedCallsign; return removedCallsign;
@@ -663,10 +740,10 @@ namespace BlackMisc
return this->provider()->remoteAircraftSituations(callsign); 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"); 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 CAircraftPartsList CRemoteAircraftAware::remoteAircraftParts(const CCallsign &callsign) const

View File

@@ -18,7 +18,7 @@
#include "blackmisc/simulation/simulatedaircraftlist.h" #include "blackmisc/simulation/simulatedaircraftlist.h"
#include "blackmisc/aviation/aircraftpartslist.h" #include "blackmisc/aviation/aircraftpartslist.h"
#include "blackmisc/aviation/aircraftsituationlist.h" #include "blackmisc/aviation/aircraftsituationlist.h"
#include "blackmisc/aviation/aircraftsituationchange.h" #include "blackmisc/aviation/aircraftsituationchangelist.h"
#include "blackmisc/aviation/percallsign.h" #include "blackmisc/aviation/percallsign.h"
#include "blackmisc/aviation/callsignset.h" #include "blackmisc/aviation/callsignset.h"
#include "blackmisc/provider.h" #include "blackmisc/provider.h"
@@ -101,10 +101,6 @@ namespace BlackMisc
//! \threadsafe //! \threadsafe
virtual int remoteAircraftPartsCount(const Aviation::CCallsign &callsign) const = 0; 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? //! Is remote aircraft supporting parts?
//! \threadsafe //! \threadsafe
virtual bool isRemoteAircraftSupportingParts(const Aviation::CCallsign &callsign) const = 0; virtual bool isRemoteAircraftSupportingParts(const Aviation::CCallsign &callsign) const = 0;
@@ -121,6 +117,14 @@ namespace BlackMisc
//! \threadsafe //! \threadsafe
virtual Aviation::CCallsignSet remoteAircraftSupportingParts() const = 0; 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 //! Enable/disable enabled aircraft
//! \threadsafe //! \threadsafe
virtual bool updateAircraftEnabled(const Aviation::CCallsign &callsign, bool enabledForRendering) = 0; 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 bool isRemoteAircraftSupportingParts(const Aviation::CCallsign &callsign) const override;
virtual int getRemoteAircraftSupportingPartsCount() const override; virtual int getRemoteAircraftSupportingPartsCount() const override;
virtual Aviation::CCallsignSet remoteAircraftSupportingParts() 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 updateAircraftEnabled(const Aviation::CCallsign &callsign, bool enabledForRendering) override;
virtual bool updateAircraftModel(const Aviation::CCallsign &callsign, const CAircraftModel &model, const CIdentifier &originator) 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; 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); 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 //! Add an offset for testing
Aviation::CAircraftSituation testAddAltitudeOffsetToSituation(const Aviation::CAircraftSituation &situation) const; Aviation::CAircraftSituation testAddAltitudeOffsetToSituation(const Aviation::CAircraftSituation &situation) const;
private: private:
Aviation::CAircraftSituationListPerCallsign m_situationsByCallsign; //!< situations, for performance reasons per callsign, thread safe access required //! Store the latest changes
Aviation::CAircraftPartsListPerCallsign m_partsByCallsign; //!< parts, for performance reasons per callsign, thread safe access required //! \remark latest first
Aviation::CCallsignSet m_aircraftWithParts; //!< aircraft supporting parts, thread safe access required //! \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_situationsAdded = 0; //!< total number of situations added, thread safe access required
int m_partsAdded = 0; //!< total number of parts 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_reverseLookupMessages; //!< reverse lookup messages
Aviation::CStatusMessageListPerCallsign m_aircraftPartsMessages; //!< status messages for parts history Aviation::CStatusMessageListPerCallsign m_aircraftPartsMessages; //!< status messages for parts history
Aviation::CTimestampPerCallsign m_situationsLastModified; //!< when situations last modified Aviation::CTimestampPerCallsign m_situationsLastModified; //!< when situations last modified
Aviation::CTimestampPerCallsign m_partsLastModified; //!< when parts last modified Aviation::CTimestampPerCallsign m_partsLastModified; //!< when parts last modified
QHash<Aviation::CCallsign, PhysicalQuantities::CLength> m_testOffset; Aviation::CLengthPerCallsign m_testOffset; //!< offsets
bool m_enableReverseLookupMsgs = false; //!< shall we log. information about the matching process bool m_enableReverseLookupMsgs = false; //!< shall we log. information about the matching process
bool m_enableAircraftPartsHistory = true; //!< shall we keep a history of aircraft parts bool m_enableAircraftPartsHistory = true; //!< shall we keep a history of aircraft parts
@@ -392,6 +408,7 @@ namespace BlackMisc
// locks // locks
mutable QReadWriteLock m_lockSituations; //!< lock for situations: m_situationsByCallsign mutable QReadWriteLock m_lockSituations; //!< lock for situations: m_situationsByCallsign
mutable QReadWriteLock m_lockParts; //!< lock for parts: m_partsByCallsign, m_aircraftSupportingParts 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_lockAircraft; //!< lock aircraft: m_aircraftInRange
mutable QReadWriteLock m_lockMessages; //!< lock for messages mutable QReadWriteLock m_lockMessages; //!< lock for messages
mutable QReadWriteLock m_lockPartsHistory; //!< lock for aircraft parts mutable QReadWriteLock m_lockPartsHistory; //!< lock for aircraft parts
@@ -437,8 +454,8 @@ namespace BlackMisc
//! \copydoc IRemoteAircraftProvider::remoteAircraftPartsCount //! \copydoc IRemoteAircraftProvider::remoteAircraftPartsCount
int remoteAircraftPartsCount(const Aviation::CCallsign &callsign) const; int remoteAircraftPartsCount(const Aviation::CCallsign &callsign) const;
//! \copydoc IRemoteAircraftProvider::remoteAircraftSituationChange //! \copydoc IRemoteAircraftProvider::remoteAircraftSituationChanges
Aviation::CAircraftSituationChange remoteAircraftSituationChange(const Aviation::CCallsign &callsign) const; Aviation::CAircraftSituationChangeList remoteAircraftSituationChanges(const Aviation::CCallsign &callsign) const;
//! \copydoc IRemoteAircraftProvider::remoteAircraftSupportingParts //! \copydoc IRemoteAircraftProvider::remoteAircraftSupportingParts
Aviation::CCallsignSet remoteAircraftSupportingParts() const; Aviation::CCallsignSet remoteAircraftSupportingParts() const;