From 7b1beaf02d3e7a0918f03b72c75b6455e68cc150 Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Sun, 19 Apr 2015 18:55:05 +0200 Subject: [PATCH] Introduced hint for callsign to specify callsign type (aircraft? ATC?) by context. Background: Pilots can login in with virtually any callsign like XXX_OBS, resulting in wrong interpretations (as OBS here is no ATC station). --- src/blackcore/airspace_monitor.cpp | 5 --- src/blackcore/airspace_monitor.h | 2 +- src/blackcore/network_vatlib.cpp | 43 ++++++++++++-------- src/blackcore/vatsimbookingreader.cpp | 2 +- src/blackgui/models/atcstationlistmodel.cpp | 2 +- src/blackmisc/aviation/aircraft.cpp | 8 ++-- src/blackmisc/aviation/aircraftsituation.cpp | 18 ++++++++ src/blackmisc/aviation/aircraftsituation.h | 12 ++---- src/blackmisc/aviation/atcstation.cpp | 18 +++++--- src/blackmisc/aviation/callsign.cpp | 28 ++++++++++--- src/blackmisc/aviation/callsign.h | 41 ++++++++++++++----- 11 files changed, 121 insertions(+), 58 deletions(-) diff --git a/src/blackcore/airspace_monitor.cpp b/src/blackcore/airspace_monitor.cpp index 1b2e288a8..c92145db3 100644 --- a/src/blackcore/airspace_monitor.cpp +++ b/src/blackcore/airspace_monitor.cpp @@ -768,11 +768,6 @@ namespace BlackCore CCallsign callsign(situation.getCallsign()); Q_ASSERT_X(!callsign.isEmpty(), "ps_aircraftUpdateReceived", "Empty callsign"); - if (callsign.isObserverCallsign()) - { - return; // just ignore - } - // store situation history this->m_aircraftSituations.push_front(situation); this->m_aircraftSituations.removeOlderThanNowMinusOffset(AircraftSituationsRemovedOffsetMs); diff --git a/src/blackcore/airspace_monitor.h b/src/blackcore/airspace_monitor.h index d7d63ebff..70259981c 100644 --- a/src/blackcore/airspace_monitor.h +++ b/src/blackcore/airspace_monitor.h @@ -137,7 +137,7 @@ namespace BlackCore void enableFastPositionSending(bool enable); static const qint64 AircraftSituationsRemovedOffsetMs = 30 * 1000; //!< situations older than now - offset will be removed - static const qint64 AircraftPartsRemoveOffsetMs = 30* 1000; //!< parts older than now - offset will be removed + static const qint64 AircraftPartsRemoveOffsetMs = 30 * 1000; //!< parts older than now - offset will be removed signals: diff --git a/src/blackcore/network_vatlib.cpp b/src/blackcore/network_vatlib.cpp index 6571e2f20..8ccb4594d 100644 --- a/src/blackcore/network_vatlib.cpp +++ b/src/blackcore/network_vatlib.cpp @@ -261,11 +261,16 @@ namespace BlackCore VatSimType CNetworkVatlib::convertToSimType(CSimulatorPluginInfo &simInfo) { /* TODO Define recognized simulators somewhere */ - if (simInfo.getSimulator() == "fs9" || simInfo.getSimulator() == "fsx") { + if (simInfo.getSimulator() == "fs9" || simInfo.getSimulator() == "fsx") + { return vatSimTypeMSCFS; - } else if (simInfo.getSimulator() == "xplane") { + } + else if (simInfo.getSimulator() == "xplane") + { return vatSimTypeXPLANE; - } else { + } + else + { return vatSimTypeUnknown; } } @@ -685,17 +690,17 @@ namespace BlackCore void CNetworkVatlib::onPilotDisconnected(VatSessionID, const char *callsign, void *cbvar) { - emit cbvar_cast(cbvar)->pilotDisconnected(cbvar_cast(cbvar)->fromFSD(callsign)); + emit cbvar_cast(cbvar)->pilotDisconnected(CCallsign(cbvar_cast(cbvar)->fromFSD(callsign), CCallsign::Aircraft)); } void CNetworkVatlib::onControllerDisconnected(VatSessionID, const char *callsign, void *cbvar) { - emit cbvar_cast(cbvar)->atcDisconnected(cbvar_cast(cbvar)->fromFSD(callsign)); + emit cbvar_cast(cbvar)->atcDisconnected(CCallsign(cbvar_cast(cbvar)->fromFSD(callsign), CCallsign::Atc)); } void CNetworkVatlib::onPilotPositionUpdate(VatSessionID, const char *callsignChar , const VatPilotPosition *position, void *cbvar) { - const CCallsign callsign(callsignChar); + const CCallsign callsign(callsignChar, CCallsign::Aircraft); const CAircraftSituation situation( callsign, CCoordinateGeodetic(position->latitude, position->longitude, 0.0), @@ -747,9 +752,12 @@ namespace BlackCore QByteArray json = cbvar_cast(cbvar)->fromFSD(aircraftConfig).toUtf8(); QJsonParseError parserError; QJsonDocument doc = QJsonDocument::fromJson(json, &parserError); + CCallsign cs(callsign, CCallsign::Aircraft); if (parserError.error != QJsonParseError::NoError) + { CLogMessage(static_cast(nullptr)).warning("Failed to parse aircraft config packet: %1") << parserError.errorString(); + } QJsonObject packet = doc.object(); @@ -763,7 +771,7 @@ namespace BlackCore if (config.empty()) return; bool isFull = config.take("is_full_data").toBool(false); - emit cbvar_cast(cbvar)->aircraftConfigPacketReceived(cbvar_cast(cbvar)->fromFSD(callsign), config, isFull); + emit cbvar_cast(cbvar)->aircraftConfigPacketReceived(cs, config, isFull); } void CNetworkVatlib::onInterimPilotPositionUpdate(VatSessionID, const char *sender, const VatInterimPilotPosition *position, void *cbvar) @@ -788,8 +796,10 @@ namespace BlackCore int frequencyKHz = pos->frequency; CFrequency freq(frequencyKHz, CFrequencyUnit::kHz()); freq.switchUnit(CFrequencyUnit::MHz()); // we would not need to bother, but this makes it easier to identify - emit cbvar_cast(cbvar)->atcPositionUpdate(cbvar_cast(cbvar)->fromFSD(callsign), freq, - CCoordinateGeodetic(pos->latitude, pos->longitude, 0), CLength(pos->visibleRange, CLengthUnit::NM())); + Q_ASSERT(CComSystem::isValidCivilAviationFrequency(freq)); + emit cbvar_cast(cbvar)->atcPositionUpdate( + CCallsign(cbvar_cast(cbvar)->fromFSD(callsign), CCallsign::Atc), freq, + CCoordinateGeodetic(pos->latitude, pos->longitude, 0), CLength(pos->visibleRange, CLengthUnit::NM())); } void CNetworkVatlib::onKicked(VatSessionID, const char *reason, void *cbvar) @@ -867,11 +877,11 @@ namespace BlackCore { switch (type) { - case vatClientQueryFreq: emit cbvar_cast(cbvar)->frequencyReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), CFrequency(cbvar_cast(cbvar)->fromFSD(data).toFloat(), CFrequencyUnit::MHz())); break; - case vatClientQueryServer: emit cbvar_cast(cbvar)->serverReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); break; - case vatClientQueryAtc: emit cbvar_cast(cbvar)->atcReplyReceived(cbvar_cast(cbvar)->fromFSD(data2), *data == 'Y'); break; - case vatClientQueryName: emit cbvar_cast(cbvar)->realNameReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); break; - case vatClientQueryIP: emit cbvar_cast(cbvar)->ipReplyReceived(cbvar_cast(cbvar)->fromFSD(data)); break; + case vatInfoQueryTypeFreq: emit cbvar_cast(cbvar)->frequencyReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), CFrequency(cbvar_cast(cbvar)->fromFSD(data).toFloat(), CFrequencyUnit::MHz())); break; + case vatInfoQueryTypeServer: emit cbvar_cast(cbvar)->serverReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); break; + case vatInfoQueryTypeAtc: emit cbvar_cast(cbvar)->atcReplyReceived(CCallsign(cbvar_cast(cbvar)->fromFSD(data2), CCallsign::Atc), *data == 'Y'); break; + case vatInfoQueryTypeName: emit cbvar_cast(cbvar)->realNameReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), cbvar_cast(cbvar)->fromFSD(data)); break; + case vatInfoQueryTypeIP: emit cbvar_cast(cbvar)->ipReplyReceived(cbvar_cast(cbvar)->fromFSD(data)); break; default: break; } } @@ -911,8 +921,7 @@ namespace BlackCore } } - emit cbvar_cast(cbvar)->atisReplyReceived(cbvar_cast(cbvar)->fromFSD(callsign), atisMessage); - + emit cbvar_cast(cbvar)->atisReplyReceived(CCallsign(cbvar_cast(cbvar)->fromFSD(callsign), CCallsign::Atc), atisMessage); } void CNetworkVatlib::onFlightPlanReceived(VatSessionID, const char *callsign, const VatFlightPlan *fp, void *cbvar) @@ -954,7 +963,7 @@ namespace BlackCore cbvar_cast(cbvar)->fromFSD(fp->remarks) ); - emit cbvar_cast(cbvar)->flightPlanReplyReceived(callsign, flightPlan); + emit cbvar_cast(cbvar)->flightPlanReplyReceived(CCallsign(callsign, CCallsign::Atc), flightPlan); } void CNetworkVatlib::onTemperatureDataReceived(VatSessionID, const VatTempLayer /** layer **/ [4], int /** pressure **/, void * /** cbvar **/) diff --git a/src/blackcore/vatsimbookingreader.cpp b/src/blackcore/vatsimbookingreader.cpp index fdc44393e..4a9bc3591 100644 --- a/src/blackcore/vatsimbookingreader.cpp +++ b/src/blackcore/vatsimbookingreader.cpp @@ -115,7 +115,7 @@ namespace BlackCore } else if (name == "callsign") { - bookedStation.setCallsign(CCallsign(value)); + bookedStation.setCallsign(CCallsign(value, CCallsign::Atc)); } else if (name == "name") { diff --git a/src/blackgui/models/atcstationlistmodel.cpp b/src/blackgui/models/atcstationlistmodel.cpp index c824f13d8..4a61f2324 100644 --- a/src/blackgui/models/atcstationlistmodel.cpp +++ b/src/blackgui/models/atcstationlistmodel.cpp @@ -100,7 +100,7 @@ namespace BlackGui for (const QString &type : types.keys()) { // ownership of QStandardItem is taken by model - QStandardItem *typeFolderFirstColumn = new QStandardItem(CCallsign::suffixToIcon(type).toQIcon(), type); + QStandardItem *typeFolderFirstColumn = new QStandardItem(CCallsign::atcSuffixToIcon(type).toQIcon(), type); QList typeFolderRow { typeFolderFirstColumn }; model->invisibleRootItem()->appendRow(typeFolderRow); CAtcStationList stations = this->getContainer().findBySuffix(type); diff --git a/src/blackmisc/aviation/aircraft.cpp b/src/blackmisc/aviation/aircraft.cpp index 3c12fbcdb..5274b848f 100644 --- a/src/blackmisc/aviation/aircraft.cpp +++ b/src/blackmisc/aviation/aircraft.cpp @@ -24,6 +24,7 @@ namespace BlackMisc : m_callsign(callsign), m_pilot(user), m_situation(situation) { // sync callsigns + this->m_callsign.setTypeHint(CCallsign::Aircraft); if (!callsign.isEmpty()) { this->setCallsign(callsign); @@ -37,9 +38,10 @@ namespace BlackMisc void CAircraft::setCallsign(const CCallsign &callsign) { this->m_callsign = callsign; - this->m_pilot.setCallsign(callsign); - this->m_situation.setCallsign(callsign); - this->m_parts.setCallsign(callsign); + this->m_callsign.setTypeHint(CCallsign::Aircraft); + this->m_pilot.setCallsign(this->m_callsign); + this->m_situation.setCallsign(this->m_callsign); + this->m_parts.setCallsign(this->m_callsign); } QString CAircraft::convertToQString(bool i18n) const diff --git a/src/blackmisc/aviation/aircraftsituation.cpp b/src/blackmisc/aviation/aircraftsituation.cpp index 50a36fc1c..cc9e115ac 100644 --- a/src/blackmisc/aviation/aircraftsituation.cpp +++ b/src/blackmisc/aviation/aircraftsituation.cpp @@ -21,6 +21,18 @@ namespace BlackMisc namespace Aviation { + CAircraftSituation::CAircraftSituation(const CCoordinateGeodetic &position, const CAltitude &altitude, const CHeading &heading, const CAngle &pitch, const CAngle &bank, const CSpeed &gs) + : m_position(position), m_altitude(altitude), m_heading(heading), m_pitch(pitch), + m_bank(bank), m_groundspeed(gs) {} + + CAircraftSituation::CAircraftSituation(const CCallsign &correspondingCallsign, const CCoordinateGeodetic &position, const CAltitude &altitude, const CHeading &heading, const CAngle &pitch, const CAngle &bank, const CSpeed &gs) + : m_correspondingCallsign(correspondingCallsign), + m_position(position), m_altitude(altitude), m_heading(heading), m_pitch(pitch), + m_bank(bank), m_groundspeed(gs) + { + m_correspondingCallsign.setTypeHint(CCallsign::Aircraft); + } + QString CAircraftSituation::convertToQString(bool i18n) const { QString s(this->m_position.toQString(i18n)); @@ -140,5 +152,11 @@ namespace BlackMisc return notAvialable; } + void CAircraftSituation::setCallsign(const CCallsign &callsign) + { + this->m_correspondingCallsign = callsign; + this->m_correspondingCallsign.setTypeHint(CCallsign::Aircraft); + } + } // namespace } // namespace diff --git a/src/blackmisc/aviation/aircraftsituation.h b/src/blackmisc/aviation/aircraftsituation.h index 0902fde3e..6860eb514 100644 --- a/src/blackmisc/aviation/aircraftsituation.h +++ b/src/blackmisc/aviation/aircraftsituation.h @@ -54,9 +54,7 @@ namespace BlackMisc const BlackMisc::Aviation::CHeading &heading = {}, const BlackMisc::PhysicalQuantities::CAngle &pitch = {}, const BlackMisc::PhysicalQuantities::CAngle &bank = {}, - const BlackMisc::PhysicalQuantities::CSpeed &gs = {}) - : m_position(position), m_altitude(altitude), m_heading(heading), m_pitch(pitch), - m_bank(bank), m_groundspeed(gs) {} + const BlackMisc::PhysicalQuantities::CSpeed &gs = {}); //! Comprehensive constructor CAircraftSituation(const BlackMisc::Aviation::CCallsign &correspondingCallsign, @@ -64,11 +62,7 @@ namespace BlackMisc const BlackMisc::Aviation::CHeading &heading = {}, const BlackMisc::PhysicalQuantities::CAngle &pitch = {}, const BlackMisc::PhysicalQuantities::CAngle &bank = {}, - const BlackMisc::PhysicalQuantities::CSpeed &gs = {}) - : m_correspondingCallsign(correspondingCallsign), - m_position(position), m_altitude(altitude), m_heading(heading), m_pitch(pitch), - m_bank(bank), m_groundspeed(gs) {} - + const BlackMisc::PhysicalQuantities::CSpeed &gs = {}); //! \copydoc CValueObject::propertyByIndex CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const; @@ -141,7 +135,7 @@ namespace BlackMisc const BlackMisc::Aviation::CCallsign &getCallsign() const { return this->m_correspondingCallsign; } //! Corresponding callsign - void setCallsign(const BlackMisc::Aviation::CCallsign &callsign) { this->m_correspondingCallsign = callsign; } + void setCallsign(const BlackMisc::Aviation::CCallsign &callsign); //! \copydoc CValueObject::convertToQString QString convertToQString(bool i18n = false) const; diff --git a/src/blackmisc/aviation/atcstation.cpp b/src/blackmisc/aviation/atcstation.cpp index cc187e3aa..99c65c109 100644 --- a/src/blackmisc/aviation/atcstation.cpp +++ b/src/blackmisc/aviation/atcstation.cpp @@ -29,16 +29,24 @@ namespace BlackMisc { } CAtcStation::CAtcStation(const QString &callsign) : m_callsign(callsign) - { } + { + this->m_callsign.setTypeHint(CCallsign::Atc); + } - CAtcStation::CAtcStation(const CCallsign &callsign, const CUser &controller, const CFrequency &frequency, const CCoordinateGeodetic &pos, const CLength &range, bool isOnline, - const QDateTime &bookedFromUtc, const QDateTime &bookedUntilUtc, const CInformationMessage &atis, const CInformationMessage &metar) : + CAtcStation::CAtcStation(const CCallsign &callsign, const CUser &controller, const CFrequency &frequency, + const CCoordinateGeodetic &pos, const CLength &range, bool isOnline, + const QDateTime &bookedFromUtc, const QDateTime &bookedUntilUtc, + const CInformationMessage &atis, const CInformationMessage &metar) : m_callsign(callsign), m_controller(controller), m_frequency(frequency), m_position(pos), - m_range(range), m_isOnline(isOnline), m_bookedFromUtc(bookedFromUtc), m_bookedUntilUtc(bookedUntilUtc), m_atis(atis), m_metar(metar) + m_range(range), m_isOnline(isOnline), m_bookedFromUtc(bookedFromUtc), m_bookedUntilUtc(bookedUntilUtc), + m_atis(atis), m_metar(metar) { // sync callsigns + this->m_callsign.setTypeHint(CCallsign::Atc); if (!this->m_controller.hasValidCallsign() && !callsign.isEmpty()) - this->m_controller.setCallsign(callsign); + { + this->m_controller.setCallsign(m_callsign); + } } bool CAtcStation::hasMetar() const diff --git a/src/blackmisc/aviation/callsign.cpp b/src/blackmisc/aviation/callsign.cpp index 6da97cfc2..067d4e58d 100644 --- a/src/blackmisc/aviation/callsign.cpp +++ b/src/blackmisc/aviation/callsign.cpp @@ -30,17 +30,17 @@ namespace BlackMisc const CIcon &CCallsign::convertToIcon(const CCallsign &callsign) { - if (callsign.hasSuffix()) - { - return suffixToIcon(callsign.getSuffix()); - } - else + if (callsign.getTypeHint() == CCallsign::Aircraft || !callsign.hasSuffix()) { return CIconList::iconByIndex(CIcons::NetworkRolePilot); } + else + { + return atcSuffixToIcon(callsign.getSuffix()); + } } - const CIcon &CCallsign::suffixToIcon(const QString &suffix) + const CIcon &CCallsign::atcSuffixToIcon(const QString &suffix) { if (suffix.length() < 3) { return CIconList::iconByIndex(CIcons::NetworkRoleUnknown); } QString sfx = suffix.toUpper(); @@ -60,23 +60,39 @@ namespace BlackMisc bool CCallsign::isAtcCallsign() const { + if (this->getTypeHint() == Atc) { return true; } if (!this->hasSuffix()) { return false; } return atcCallsignSuffixes().contains(this->getSuffix(), Qt::CaseInsensitive); } bool CCallsign::isSupervisorCallsign() const { + if (this->getTypeHint() == Aircraft) { return false; } return this->m_callsign.endsWith("SUP"); } + QString CCallsign::getIcaoCode() const + { + if (this->isAtcCallsign()) + { + if (m_callsign.length() >= 4) + { + return m_callsign.left(4).toUpper(); + } + } + return ""; + } + bool CCallsign::isAtcAlikeCallsign() const { + if (this->getTypeHint() == Aircraft) { return false; } if (!this->hasSuffix()) { return false; } return atcAlikeCallsignSuffixes().contains(this->getSuffix(), Qt::CaseInsensitive); } bool CCallsign::isObserverCallsign() const { + if (this->getTypeHint() == Aircraft) { return false; } return m_callsignAsSet.endsWith("_OBS", Qt::CaseInsensitive); } diff --git a/src/blackmisc/aviation/callsign.h b/src/blackmisc/aviation/callsign.h index 9173f772c..d167c957e 100644 --- a/src/blackmisc/aviation/callsign.h +++ b/src/blackmisc/aviation/callsign.h @@ -35,17 +35,30 @@ namespace BlackMisc IndexSuffix }; + //! Representing what + enum TypeHint + { + NoHint, + Aircraft, + Atc + }; + //! Default constructor. CCallsign() = default; //! Constructor - CCallsign(const QString &callsign, const QString &telephonyDesignator = "") - : m_callsignAsSet(callsign.trimmed()), m_callsign(CCallsign::unifyCallsign(callsign.trimmed())), m_telephonyDesignator(telephonyDesignator.trimmed()) + CCallsign(const QString &callsign, TypeHint hint = NoHint) + : m_callsignAsSet(callsign.trimmed()), m_callsign(CCallsign::unifyCallsign(callsign.trimmed())), m_typeHint(hint) + {} + + //! Constructor + CCallsign(const QString &callsign, const QString &telephonyDesignator, TypeHint hint = NoHint) + : m_callsignAsSet(callsign.trimmed()), m_callsign(CCallsign::unifyCallsign(callsign.trimmed())), m_telephonyDesignator(telephonyDesignator.trimmed()), m_typeHint(hint) {} //! Constructor, needed to disambiguate implicit conversion from string literal. - CCallsign(const char *callsign) - : m_callsignAsSet(callsign), m_callsign(CCallsign::unifyCallsign(callsign)) + CCallsign(const char *callsign, TypeHint hint = NoHint) + : m_callsignAsSet(callsign), m_callsign(CCallsign::unifyCallsign(callsign)), m_typeHint(hint) {} //! Is empty? @@ -74,8 +87,14 @@ namespace BlackMisc //! Get callsign telephony designator (how callsign is pronounced) const QString &getTelephonyDesignator() const { return this->m_telephonyDesignator; } + //! Type hint + TypeHint getTypeHint() const { return m_typeHint; } + + //! Type hint + void setTypeHint(TypeHint hint) { this->m_typeHint = hint; } + //! Get ICAO code, if this makes sense (EDDF_TWR -> EDDF) - QString getIcaoCode() const { return m_callsign.left(4).toUpper(); } + QString getIcaoCode() const; //! Makes this callsign looking like an observer callsign (DAMBZ -> DAMBZ_OBS) QString getAsObserverCallsignString() const; @@ -108,7 +127,7 @@ namespace BlackMisc static const QStringList &atcAlikeCallsignSuffixes(); //! Suffix to icon - static const BlackMisc::CIcon &suffixToIcon(const QString &suffix); + static const BlackMisc::CIcon &atcSuffixToIcon(const QString &suffix); //! Representing icon static const CIcon &convertToIcon(const CCallsign &callsign); @@ -122,9 +141,10 @@ namespace BlackMisc private: BLACK_ENABLE_TUPLE_CONVERSION(CCallsign) - QString m_callsignAsSet; - QString m_callsign; - QString m_telephonyDesignator; + QString m_callsignAsSet; + QString m_callsign; + QString m_telephonyDesignator; + TypeHint m_typeHint = NoHint; }; } // namespace } // namespace @@ -132,7 +152,8 @@ namespace BlackMisc BLACK_DECLARE_TUPLE_CONVERSION(BlackMisc::Aviation::CCallsign, ( attr(o.m_callsign, flags()), attr(o.m_callsignAsSet, flags()), - attr(o.m_telephonyDesignator, flags()) + attr(o.m_telephonyDesignator, flags()), + attr(o.m_typeHint, flags()) )) Q_DECLARE_METATYPE(BlackMisc::Aviation::CCallsign)