Ref T442, utility functions for logically sorting by suffix

This commit is contained in:
Klaus Basan
2018-11-29 03:19:45 +01:00
parent 391327b3a7
commit 0da8d85999
10 changed files with 141 additions and 53 deletions

View File

@@ -70,6 +70,11 @@ namespace BlackMisc
return m_callsign.getSuffix();
}
int CAtcStation::getSuffixSortOrder() const
{
return m_callsign.getSuffixSortOrder();
}
void CAtcStation::setCallsign(const CCallsign &callsign)
{
m_callsign = callsign;

View File

@@ -95,6 +95,9 @@ namespace BlackMisc
//! Callsign suffix (e.g. TWR)
QString getCallsignSuffix() const;
//! Callsign suffix sort order
int getSuffixSortOrder() const;
//! Set callsign
void setCallsign(const CCallsign &callsign);

View File

@@ -126,5 +126,17 @@ namespace BlackMisc
Q_ASSERT_X(c == 0 || c == 1, Q_FUNC_INFO, "Found >1 matching station");
return c;
}
void CAtcStationList::sortByAtcSuffixSortOrderAndDistance()
{
this->sortBy(&CAtcStation::getSuffixSortOrder, &CAtcStation::getRelativeDistance);
}
CAtcStationList CAtcStationList::sortedByAtcSuffixSortOrderAndDistance() const
{
CAtcStationList stations = *this;
stations.sortByAtcSuffixSortOrderAndDistance();
return stations;
}
} // namespace
} // namespace

View File

@@ -66,7 +66,7 @@ namespace BlackMisc
CAtcStationList stationsWithValidFrequency() const;
//! All controllers (with valid data)
BlackMisc::Network::CUserList getControllers() const;
Network::CUserList getControllers() const;
//! Remove if marked outside of range
int removeIfOutsideRange();
@@ -75,8 +75,13 @@ namespace BlackMisc
//! Both sides (booking, online station) will be updated.
//! \pre Can be used only if the stored data in this list are online ATC stations
int synchronizeWithBookedStation(CAtcStation &bookedAtcStation);
};
//! Sort by ATC suffix sort order and distance
void sortByAtcSuffixSortOrderAndDistance();
//! Sorted by ATC suffix sort order and distance
CAtcStationList sortedByAtcSuffixSortOrderAndDistance() const;
};
} //namespace
} // namespace

View File

@@ -21,6 +21,18 @@ namespace BlackMisc
{
namespace Aviation
{
CCallsign::CCallsign(const QString &callsign, CCallsign::TypeHint hint)
: m_callsignAsSet(callsign.trimmed()), m_callsign(CCallsign::unifyCallsign(callsign)), m_typeHint(hint)
{}
CCallsign::CCallsign(const QString &callsign, const QString &telephonyDesignator, CCallsign::TypeHint hint)
: m_callsignAsSet(callsign.trimmed()), m_callsign(CCallsign::unifyCallsign(callsign)), m_telephonyDesignator(telephonyDesignator.trimmed()), m_typeHint(hint)
{}
CCallsign::CCallsign(const char *callsign, CCallsign::TypeHint hint)
: m_callsignAsSet(callsign), m_callsign(CCallsign::unifyCallsign(callsign)), m_typeHint(hint)
{}
void CCallsign::registerMetadata()
{
CValueObject<CCallsign>::registerMetadata();
@@ -38,6 +50,23 @@ namespace BlackMisc
*this = CCallsign();
}
int CCallsign::suffixToSortOrder(const QString &suffix)
{
if ("CTR" == suffix) { return 1; }
if ("APP" == suffix) { return 2; }
if ("FSS" == suffix) { return 3; }
if ("TWR" == suffix) { return 5; }
if ("GND" == suffix) { return 6; }
if ("DEL" == suffix) { return 7; }
if ("ATIS" == suffix) { return 8; }
if ("SUP" == suffix) { return 10; }
if ("OBS" == suffix) { return 11; }
if ("INS" == suffix) { return 13; } // instructor/mentor
if ("EXAM" == suffix) { return 14; }
if ("VATSIM" == suffix) { return 14; }
return std::numeric_limits<int>::max();
}
QString CCallsign::unifyCallsign(const QString &callsign)
{
return removeChars(callsign.toUpper().trimmed(), [](QChar c) { return !c.isLetterOrNumber() && c != '_'; });
@@ -58,18 +87,18 @@ namespace BlackMisc
const CIcon &CCallsign::atcSuffixToIcon(const QString &suffix)
{
if (suffix.length() < 3) { return CIcon::iconByIndex(CIcons::NetworkRoleUnknown); }
QString sfx = suffix.toUpper();
if ("APP" == sfx) { return CIcon::iconByIndex(CIcons::NetworkRoleApproach); }
if ("GND" == sfx) { return CIcon::iconByIndex(CIcons::NetworkRoleGround); }
if ("TWR" == sfx) { return CIcon::iconByIndex(CIcons::NetworkRoleTower); }
if ("DEL" == sfx) { return CIcon::iconByIndex(CIcons::NetworkRoleDelivery); }
if ("CTR" == sfx) { return CIcon::iconByIndex(CIcons::NetworkRoleCenter); }
if ("SUP" == sfx) { return CIcon::iconByIndex(CIcons::NetworkRoleSup); }
if ("OBS" == sfx) { return CIcon::iconByIndex(CIcons::NetworkRoleObs); }
if ("INS" == sfx) { return CIcon::iconByIndex(CIcons::NetworkRoleMnt); }
if ("FSS" == sfx) { return CIcon::iconByIndex(CIcons::NetworkRoleFss); }
const QString sfx = suffix.toUpper();
if ("APP" == sfx) { return CIcon::iconByIndex(CIcons::NetworkRoleApproach); }
if ("GND" == sfx) { return CIcon::iconByIndex(CIcons::NetworkRoleGround); }
if ("TWR" == sfx) { return CIcon::iconByIndex(CIcons::NetworkRoleTower); }
if ("DEL" == sfx) { return CIcon::iconByIndex(CIcons::NetworkRoleDelivery); }
if ("CTR" == sfx) { return CIcon::iconByIndex(CIcons::NetworkRoleCenter); }
if ("SUP" == sfx) { return CIcon::iconByIndex(CIcons::NetworkRoleSup); }
if ("OBS" == sfx) { return CIcon::iconByIndex(CIcons::NetworkRoleObs); }
if ("INS" == sfx) { return CIcon::iconByIndex(CIcons::NetworkRoleMnt); }
if ("FSS" == sfx) { return CIcon::iconByIndex(CIcons::NetworkRoleFss); }
if ("ATIS" == sfx) { return CIcon::iconByIndex(CIcons::AviationAtis); }
if ("EXAM" == sfx) { return CIcon::iconByIndex(CIcons::NetworkRoleMnt); }
if ("EXAM" == sfx) { return CIcon::iconByIndex(CIcons::NetworkRoleMnt); }
if ("VATSIM" == sfx) { return CIcon::iconByIndex(CIcons::NetworkVatsimLogoWhite); }
return CIcon::iconByIndex(CIcons::NetworkRoleUnknown);
}
@@ -122,7 +151,7 @@ namespace BlackMisc
{
if (this->isEmpty()) { return ""; }
QString obs = this->getStringAsSet();
if (obs.endsWith("_OBS", Qt::CaseInsensitive)) { return obs; }
if (obs.endsWith("_OBS", Qt::CaseInsensitive)) { return obs; } // already OBS
if (obs.contains('_')) { obs = obs.left(obs.lastIndexOf('_')); }
return obs.append("_OBS").toUpper();
}
@@ -169,6 +198,11 @@ namespace BlackMisc
return !s.isEmpty() && atcCallsignSuffixes().contains(s);
}
int CCallsign::getSuffixSortOrder() const
{
return suffixToSortOrder(this->getSuffix());
}
bool CCallsign::equalsString(const QString &callsignString) const
{
CCallsign other(callsignString);
@@ -181,10 +215,10 @@ namespace BlackMisc
const ColumnIndex i = index.frontCasted<ColumnIndex>();
switch (i)
{
case IndexCallsignString: return CVariant(this->asString());
case IndexCallsignString: return CVariant(this->asString());
case IndexCallsignStringAsSet: return CVariant(this->getStringAsSet());
case IndexTelephonyDesignator: return CVariant(this->getTelephonyDesignator());
case IndexSuffix: return CVariant(this->getSuffix());
case IndexSuffix: return CVariant(this->getSuffix());
default: return CValueObject::propertyByIndex(index);
}
}
@@ -195,7 +229,7 @@ namespace BlackMisc
const ColumnIndex i = index.frontCasted<ColumnIndex>();
switch (i)
{
case IndexCallsignString: m_callsign = m_callsign = unifyCallsign(variant.toQString()); break;
case IndexCallsignString: m_callsign = unifyCallsign(variant.toQString()); break;
case IndexCallsignStringAsSet: m_callsignAsSet = variant.toQString(); break;
case IndexTelephonyDesignator: m_telephonyDesignator = variant.toQString(); break;
default:
@@ -210,10 +244,10 @@ namespace BlackMisc
const ColumnIndex i = index.frontCasted<ColumnIndex>();
switch (i)
{
case IndexCallsignString: return m_callsign.compare(compareValue.m_callsign, Qt::CaseInsensitive);
case IndexCallsignString: return m_callsign.compare(compareValue.m_callsign, Qt::CaseInsensitive);
case IndexCallsignStringAsSet: return m_callsignAsSet.compare(compareValue.m_callsignAsSet, Qt::CaseInsensitive);
case IndexTelephonyDesignator: return m_telephonyDesignator.compare(compareValue.m_telephonyDesignator, Qt::CaseInsensitive);
case IndexSuffix: return this->getSuffix().compare(compareValue.getSuffix(), Qt::CaseInsensitive);
case IndexSuffix: return this->getSuffix().compare(compareValue.getSuffix(), Qt::CaseInsensitive);
default:
return CValueObject::comparePropertyByIndex(index, compareValue);
}

View File

@@ -38,7 +38,8 @@ namespace BlackMisc
IndexCallsignString = CPropertyIndex::GlobalIndexCCallsign,
IndexCallsignStringAsSet,
IndexTelephonyDesignator,
IndexSuffix
IndexSuffix,
IndexSuffixSortOrder
};
//! Representing what
@@ -53,19 +54,13 @@ namespace BlackMisc
CCallsign() {}
//! Constructor
CCallsign(const QString &callsign, TypeHint hint = NoHint)
: m_callsignAsSet(callsign.trimmed()), m_callsign(CCallsign::unifyCallsign(callsign)), m_typeHint(hint)
{}
CCallsign(const QString &callsign, TypeHint hint = NoHint);
//! Constructor
CCallsign(const QString &callsign, const QString &telephonyDesignator, TypeHint hint = NoHint)
: m_callsignAsSet(callsign.trimmed()), m_callsign(CCallsign::unifyCallsign(callsign)), m_telephonyDesignator(telephonyDesignator.trimmed()), m_typeHint(hint)
{}
CCallsign(const QString &callsign, const QString &telephonyDesignator, TypeHint hint = NoHint);
//! Constructor, needed to disambiguate implicit conversion from string literal.
CCallsign(const char *callsign, TypeHint hint = NoHint)
: m_callsignAsSet(callsign), m_callsign(CCallsign::unifyCallsign(callsign)), m_typeHint(hint)
{}
CCallsign(const char *callsign, TypeHint hint = NoHint);
//! Is empty?
bool isEmpty() const { return m_callsignAsSet.isEmpty(); }
@@ -122,12 +117,36 @@ namespace BlackMisc
//! Has an ATC suffix?
bool hasAtcSuffix() const;
//! Sort order by suffix
int getSuffixSortOrder() const;
//! Equals callsign string?
bool equalsString(const QString &callsignString) const;
//! Valid callsign?
bool isValid() const;
//! \copydoc BlackMisc::Mixin::Icon::toIcon()
CIcon toIcon() const { return convertToIcon(*this); }
//! \copydoc BlackMisc::Mixin::Index::propertyByIndex
CVariant propertyByIndex(const CPropertyIndex &index) const;
//! \copydoc BlackMisc::Mixin::Index::setPropertyByIndex
void setPropertyByIndex(const CPropertyIndex &index, const CVariant &variant);
//! \copydoc BlackMisc::Mixin::Index::comparePropertyByIndex
int comparePropertyByIndex(const CPropertyIndex &index, const CCallsign &compareValue) const;
//! \copydoc BlackMisc::Mixin::String::toQString()
QString convertToQString(bool i18n = false) const;
//! Clear this callsign
void clear();
//! Index for ATC suffix, if unknown int max value
static int suffixToSortOrder(const QString &suffix);
//! Valid callsign?
static bool isValidAircraftCallsign(const QString &callsign);
@@ -155,24 +174,6 @@ namespace BlackMisc
//! Representing icon
static const CIcon &convertToIcon(const CCallsign &callsign);
//! \copydoc BlackMisc::Mixin::Icon::toIcon()
CIcon toIcon() const { return convertToIcon(*this); }
//! \copydoc BlackMisc::Mixin::Index::propertyByIndex
CVariant propertyByIndex(const CPropertyIndex &index) const;
//! \copydoc BlackMisc::Mixin::Index::setPropertyByIndex
void setPropertyByIndex(const CPropertyIndex &index, const CVariant &variant);
//! \copydoc BlackMisc::Mixin::Index::comparePropertyByIndex
int comparePropertyByIndex(const CPropertyIndex &index, const CCallsign &compareValue) const;
//! \copydoc BlackMisc::Mixin::String::toQString()
QString convertToQString(bool i18n = false) const;
//! Clear this callsign
void clear();
//! Register metadata
static void registerMetadata();

View File

@@ -133,9 +133,9 @@ namespace BlackMisc
}
template <class OBJ, class CONTAINER>
QMap<QString, int> ICallsignObjectList<OBJ, CONTAINER>::getSuffixes() const
QMap<QString, int> ICallsignObjectList<OBJ, CONTAINER>::getSuffixesAndCount() const
{
QMap<QString, int> r;
QMap<QString, int> r; // sorted by key
for (const OBJ &csObj : this->container())
{
const QString s = csObj.getCallsign().getSuffix();
@@ -152,6 +152,19 @@ namespace BlackMisc
return r;
}
template<class OBJ, class CONTAINER>
QStringList ICallsignObjectList<OBJ, CONTAINER>::getSuffixes() const
{
QStringList suffixes;
for (const OBJ &csObj : this->container())
{
const QString s = csObj.getCallsign().getSuffix();
if (s.isEmpty() || suffixes.contains(s, Qt::CaseInsensitive)) { continue; }
suffixes << s;
}
return suffixes;
}
template <class OBJ, class CONTAINER>
QHash<CCallsign, CONTAINER> ICallsignObjectList<OBJ, CONTAINER>::splitPerCallsign() const
{

View File

@@ -88,7 +88,12 @@ namespace BlackMisc
int removeByCallsigns(const CCallsignSet &callsigns);
//! All suffixes with their respective count
QMap<QString, int> getSuffixes() const;
//! \remark since using QMap sorted by suffix
QMap<QString, int> getSuffixesAndCount() const;
//! All suffixes, in the order of the list
//! \remark first found suffixes first
QStringList getSuffixes() const;
//! Split into 0..n containers as per callsign
QHash<CCallsign, CONTAINER> splitPerCallsign() const;

View File

@@ -77,7 +77,7 @@ namespace BlackMisc
NetworkRoleGround,
NetworkRoleI1,
NetworkRoleI3,
NetworkRoleMnt,
NetworkRoleMnt, //!< Mentor
NetworkRoleObs,
NetworkRolePilot,
NetworkRoleS1,