Ref T215, FP value class

* split into prefix / aircraft ICAO / suffix
* suffix equipment code functions
* fixed FP remarks loading (JSON file)
* fixed missing sending of aircraft ICAO
This commit is contained in:
Klaus Basan
2018-01-02 03:05:33 +01:00
parent d127f98d60
commit 8c539fab0a
5 changed files with 258 additions and 43 deletions

View File

@@ -587,7 +587,7 @@ namespace BlackCore
alt = alt.remove('.').remove(','); // remove any separators
QByteArray acTypeTemp, altAptTemp, cruiseAltTemp, depAptTemp, destAptTemp, routeTemp, remarksTemp;
vatlibFP.aircraftType = acTypeTemp = toFSD(flightPlan.getEquipmentIcao());
vatlibFP.aircraftType = acTypeTemp = toFSD(flightPlan.getPrefixIcaoSuffix());
vatlibFP.alternateAirport = altAptTemp = toFSD(flightPlan.getAlternateAirportIcao().asString());
vatlibFP.cruiseAltitude = cruiseAltTemp = toFSD(alt);
vatlibFP.departAirport = depAptTemp = toFSD(flightPlan.getOriginAirportIcao().asString());

View File

@@ -302,7 +302,7 @@ namespace BlackCore
const QString equipmentCodeAndAircraft = clientPartsMap["planned_aircraft"].trimmed();
if (!equipmentCodeAndAircraft.isEmpty())
{
const QString aircraftIcaoCode = CFlightPlanRemarks::aircraftIcaoCodeFromEquipmentCode(equipmentCodeAndAircraft);
const QString aircraftIcaoCode = CFlightPlan::aircraftIcaoCodeFromEquipmentCode(equipmentCodeAndAircraft);
if (CAircraftIcaoCode::isValidDesignator(aircraftIcaoCode))
{
currentAircraft.setAircraftIcaoDesignator(aircraftIcaoCode);

View File

@@ -37,13 +37,13 @@ namespace BlackMisc
bool CFlightPlanRemarks::hasAnyParsedRemarks() const
{
if (!this->m_isParsed) { return false; }
if (!m_isParsed) { return false; }
return this->hasParsedAirlineRemarks() || m_selcalCode.isValid() || !m_voiceCapabilities.isUnknown();
}
bool CFlightPlanRemarks::hasParsedAirlineRemarks() const
{
if (!this->m_isParsed) { return false; }
if (!m_isParsed) { return false; }
return !m_radioTelephony.isEmpty() || !m_flightOperator.isEmpty() || m_airlineIcao.hasValidDesignator();
}
@@ -59,14 +59,34 @@ namespace BlackMisc
return s.simplified().trimmed();
}
void CFlightPlanRemarks::parseFlightPlanRemarks()
QString CFlightPlanRemarks::textToVoiceCapabilities(const QString &text)
{
if (text.contains("TEXT", Qt::CaseInsensitive)) { return QStringLiteral("/T/"); }
if (text.contains("RECEIVE", Qt::CaseInsensitive)) { return QStringLiteral("/R/"); }
if (text.contains("VOICE", Qt::CaseInsensitive)) { return QStringLiteral("/V/"); }
return QStringLiteral("");
}
QString CFlightPlanRemarks::replaceVoiceCapabilities(const QString &newCaps, const QString &oldRemarks)
{
if (newCaps.isEmpty()) { return oldRemarks; }
if (oldRemarks.isEmpty()) { return newCaps; }
QString r(oldRemarks);
if (r.contains("/V/", Qt::CaseInsensitive)) { r.replace("/V/", newCaps, Qt::CaseInsensitive); return r; }
if (r.contains("/R/", Qt::CaseInsensitive)) { r.replace("/R/", newCaps, Qt::CaseInsensitive); return r; }
if (r.contains("/T/", Qt::CaseInsensitive)) { r.replace("/T/", newCaps, Qt::CaseInsensitive); return r; }
return newCaps + " " + r;
}
void CFlightPlanRemarks::parseFlightPlanRemarks(bool force)
{
// examples: VFPS = VATSIM Flightplan Prefile System
// 1) RT/KESTREL OPR/MYTRAVEL REG/G-DAJC SEL/FP-ES PER/C NAV/RNP10
// 2) OPR/UAL CALLSIGN/UNITED
// 3) /v/FPL-VIR9-IS-A346/DEP/S-EGLL/ARR/KJFK/REG/G-VGAS/TCAS RVR/200 OPR/VIRGIN AIRLINES
if (m_isParsed) { return; }
if (!force && m_isParsed) { return; }
m_isParsed = true;
if (m_remarks.isEmpty()) { return; }
const QString remarks = m_remarks.toUpper();
@@ -85,15 +105,6 @@ namespace BlackMisc
}
}
QString CFlightPlanRemarks::aircraftIcaoCodeFromEquipmentCode(const QString &equipmentCodeAndAircraft)
{
// http://uk.flightaware.com/about/faq_aircraft_flight_plan_suffix.rvt
// we expect something like H/B772/F B773 B773/F
thread_local const QRegularExpression reg("/.");
QString aircraftIcaoCode(equipmentCodeAndAircraft);
aircraftIcaoCode = aircraftIcaoCode.replace(reg, "").trimmed().toUpper();
return aircraftIcaoCode;
}
QString CFlightPlanRemarks::cut(const QString &remarks, const QString &marker)
{
@@ -125,7 +136,7 @@ namespace BlackMisc
const PhysicalQuantities::CTime &fuelTime, const CAltitude &cruiseAltitude, const PhysicalQuantities::CSpeed &cruiseTrueAirspeed, CFlightPlan::FlightRules flightRules,
const QString &route, const QString &remarks)
: m_callsign(callsign),
m_equipmentIcao(equipmentIcao), m_originAirportIcao(originAirportIcao), m_destinationAirportIcao(destinationAirportIcao), m_alternateAirportIcao(alternateAirportIcao),
m_equipmentSuffix(equipmentIcao), m_originAirportIcao(originAirportIcao), m_destinationAirportIcao(destinationAirportIcao), m_alternateAirportIcao(alternateAirportIcao),
m_takeoffTimePlanned(takeoffTimePlanned), m_takeoffTimeActual(takeoffTimeActual), m_enrouteTime(enrouteTime), m_fuelTime(fuelTime),
m_cruiseAltitude(cruiseAltitude), m_cruiseTrueAirspeed(cruiseTrueAirspeed), m_flightRules(flightRules),
m_route(route.trimmed().left(MaxRouteLength).toUpper()),
@@ -144,9 +155,10 @@ namespace BlackMisc
void CFlightPlan::setEquipmentIcao(const QString &equipmentIcao)
{
m_equipmentIcao = equipmentIcao;
const QString aircraftIcao = CFlightPlanRemarks::aircraftIcaoCodeFromEquipmentCode(equipmentIcao);
m_aircraftIcao = CAircraftIcaoCode::isValidDesignator(aircraftIcao) ? aircraftIcao : "";
const QStringList parts = CFlightPlan::splitEquipmentCode(equipmentIcao);
m_aircraftIcao = CAircraftIcaoCode::isValidDesignator(parts[1]) ? parts[1] : "";
m_equipmentPrefix = parts[0];
m_equipmentSuffix = parts[2];
}
void CFlightPlan::setRemarks(const QString &remarks)
@@ -156,20 +168,21 @@ namespace BlackMisc
CFlightPlan::FlightRules CFlightPlan::getFlightRulesAsVFRorIFR() const
{
switch (getFlightRules())
switch (this->getFlightRules())
{
case IFR:
return IFR;
case IFR: return IFR;
case VFR:
case SVFR:
case DVFR:
return VFR;
case DVFR: return VFR;
case UNKNOWN:
default:
break;
default: break;
}
return UNKNOWN;
}
QString CFlightPlan::getPrefixIcaoSuffix() const
{
return CFlightPlan::concatPrefixIcaoSuffix(m_equipmentPrefix, m_aircraftIcao.getDesignator(), m_equipmentSuffix);
}
CVariant CFlightPlan::propertyByIndex(const CPropertyIndex &index) const
@@ -183,7 +196,7 @@ namespace BlackMisc
case IndexAlternateAirportIcao: return m_alternateAirportIcao.propertyByIndex(index.copyFrontRemoved());
case IndexDestinationAirportIcao: return m_destinationAirportIcao.propertyByIndex(index.copyFrontRemoved());
case IndexOriginAirportIcao: return m_originAirportIcao.propertyByIndex(index.copyFrontRemoved());
case IndexCallsign: return this->m_callsign.propertyByIndex(index.copyFrontRemoved());
case IndexCallsign: return m_callsign.propertyByIndex(index.copyFrontRemoved());
case IndexRemarks: return CVariant::from(m_remarks);
default: return CValueObject::propertyByIndex(index);
}
@@ -213,7 +226,7 @@ namespace BlackMisc
QString CFlightPlan::convertToQString(bool i18n) const
{
const QString s = m_callsign.toQString(i18n)
% QLatin1Char(' ') % m_equipmentIcao
% QLatin1Char(' ') % m_equipmentSuffix
% QLatin1Char(' ') % m_originAirportIcao.toQString(i18n)
% QLatin1Char(' ') % m_destinationAirportIcao.toQString(i18n)
% QLatin1Char(' ') % m_alternateAirportIcao.toQString(i18n)
@@ -241,6 +254,71 @@ namespace BlackMisc
}
}
QString CFlightPlan::aircraftIcaoCodeFromEquipmentCode(const QString &equipmentCodeAndAircraft)
{
// http://uk.flightaware.com/about/faq_aircraft_flight_plan_suffix.rvt
// we expect something like H/B772/F B773 B773/F
thread_local const QRegularExpression reg("/.");
QString aircraftIcaoCode(equipmentCodeAndAircraft);
aircraftIcaoCode = aircraftIcaoCode.replace(reg, "").trimmed().toUpper();
return aircraftIcaoCode;
}
QStringList CFlightPlan::splitEquipmentCode(const QString &equipmentCodeAndAircraft)
{
static const QStringList empty({"", "", ""});
if (empty.isEmpty()) { return empty; }
QStringList split = equipmentCodeAndAircraft.split('/');
if (split.length() == 3) { return split; } // "H/B738/F"
if (split.length() == 2)
{
if (split[0].length() == 1)
{
// we assume prefix + ICAO
// e.g. "H/B748"
split.push_back("");
}
else
{
// we assume ICAO + suffix
// e.g. "B748/F"
split.push_front("");
return split;
}
}
// one part only
if (split[0].length() > 1 && CAircraftIcaoCode::isValidDesignator(split[0]))
{
QStringList sl(empty);
sl[1] = split[0]; // only ICAO
return sl;
}
if (split[0].length() != 1) { return empty; } // something invalid
// one part, one char only. hard to tell
QStringList sl(empty);
if (faaEquipmentCodes().contains(split[0]))
{
sl[2] = split[0]; // return as equipment code
return sl;
}
sl[0] = split[0];
return sl;
}
QString CFlightPlan::concatPrefixIcaoSuffix(const QString &prefix, const QString &icao, const QString &suffix)
{
QString s = prefix;
if (!icao.isEmpty())
{
s += (s.isEmpty() ? QStringLiteral("") : QStringLiteral("/")) % icao;
}
if (suffix.isEmpty()) { return s; }
if (s.isEmpty()) { return suffix; }
return s % QStringLiteral("/") % suffix;
}
CFlightPlan::FlightRules CFlightPlan::stringToFlightRules(const QString &flightRules)
{
if (flightRules.length() < 3) { return UNKNOWN; }
@@ -252,6 +330,89 @@ namespace BlackMisc
return UNKNOWN;
}
const QStringList &CFlightPlan::faaEquipmentCodes()
{
// List of FAA Aircraft Equipment Codes For US Domestic Flights
static const QStringList e({"X", "T", "U", "D", "B", "A", "M", "N", "P", "Y", "C", "I", "L", "G", "Z", "I", "W", "L"});
return e;
}
const QStringList &CFlightPlan::faaEquipmentCodesInfo()
{
static const QStringList e(
{
"X No transponder",
"T Transponder with no Mode C",
"U Transponder with Mode C",
"D DME: No transponder",
"B DME: Transponder with no Mode C",
"A DME: Transponder with Mode C",
"M TACAN only: No transponder",
"N TACAN only: Transponder with no Mode C",
"P TACAN only: Transponder with Mode C",
"Y Basic RNAV: LORAN, VOR/DME, or INS with no transponder",
"C Basic RNAV: LORAN, VOR/DME, or INS, transponder with no Mode C",
"I Basic RNAV: LORAN, VOR/DME, or INS, transponder with Mode C",
"L Advanced RNAV: RNAV capability with Global Navigation Satellite System (GNSS)",
"G Advanced RNAV: RNAV capability with GNSS and without RVSM",
"Z Advanced RNAV: RNAV capability without GNSS and with RVSM",
"I Advanced RNAV: RNAV capability without GNSS and without RVSM",
"W RVSM",
"L RVSM and /G"
});
return e;
}
const QStringList &CFlightPlan::squawkBoxEquipmentCodes()
{
static const QStringList e({"E", "F", "G", "R", "J", "K", "L", "Q"});
return e;
}
const QStringList &CFlightPlan::squawkBoxEquipmentCodesInfo()
{
static const QStringList e(
{
"E Flight Management System (FMS) with DME/DME and IRU positioning updating",
"F Flight Management System (FMS) with DME/DME positioning updating",
"G Global Navigation Satellite System (GNSS), including GPS or Wide Area Augmentation System",
"R Required navigation performance, the aircraft meets the RNP type prescribed for the route segment(s), route(s) and or area concerned",
"J RVSM + E",
"L RVSM + F",
"L RVSM + G",
"Q RVSM + E"
});
return e;
}
const QStringList &CFlightPlan::equipmentCodes()
{
static const QStringList e = []
{
QSet<QString> el(CFlightPlan::faaEquipmentCodes().toSet());
el.unite(CFlightPlan::squawkBoxEquipmentCodes().toSet());
return el.toList();
}();
return e;
}
const QStringList &CFlightPlan::equipmentCodesInfo()
{
static const QStringList e = []
{
QStringList info(CFlightPlan::faaEquipmentCodesInfo());
info.append(CFlightPlan::squawkBoxEquipmentCodesInfo());
return info;
}();
return e;
}
const QStringList &CFlightPlan::prefixCodes()
{
static const QStringList p({"T", "H"});
return p;
}
CIcon CFlightPlan::toIcon() const
{
return CIcon::iconByIndex(CIcons::StandardIconAppFlightPlan16);

View File

@@ -83,7 +83,7 @@ namespace BlackMisc
bool hasParsedAirlineRemarks() const;
//! Parse remarks from a flight plan
void parseFlightPlanRemarks();
void parseFlightPlanRemarks(bool force = false);
//! Valid airline ICAO?
//! \remark valid here means valid syntax, no guarantee it really exists
@@ -98,15 +98,17 @@ namespace BlackMisc
//! \copydoc BlackMisc::Mixin::String::toQString()
QString convertToQString(bool i18n = false) const;
//! Get aircraft ICAO code from equipment code like
//! \remark we expect something like H/B772/F B773 B773/F
static QString aircraftIcaoCodeFromEquipmentCode(const QString &equipmentCodeAndAircraft);
//! Turn text into voice capabilities for remarks
static QString textToVoiceCapabilities(const QString &text);
//! Replace the voice capabilities remarks part
static QString replaceVoiceCapabilities(const QString &newCaps, const QString &oldRemarks);
private:
QString m_remarks; //!< the unparsed string
QString m_radioTelephony; //!< radio telephony designator
QString m_flightOperator; //!< operator, i.e. normally the airline name
CCallsign m_registration; //!< callsign of other pilot
CCallsign m_registration; //!< callsign of pilot
CSelcal m_selcalCode; //!< SELCAL code
CAirlineIcaoCode m_airlineIcao; //!< airline ICAO if provided in flight plan
Network::CVoiceCapabilities m_voiceCapabilities; //!< voice capabilities
@@ -114,6 +116,7 @@ namespace BlackMisc
BLACK_METACLASS(
CFlightPlanRemarks,
BLACK_METAMEMBER(remarks, 0, DisabledForComparison),
BLACK_METAMEMBER(radioTelephony),
BLACK_METAMEMBER(flightOperator),
BLACK_METAMEMBER(airlineIcao),
@@ -170,7 +173,8 @@ namespace BlackMisc
//! Callsign (of aircraft)
void setCallsign(const CCallsign &callsign);
//! Set ICAO aircraft equipment code string (e.g. "T/A320/F")
//! Set single char ICAO aircraft equipment code like used in "T/A320/F" (here "F")
//! \remark function can handle full codes like "T/A320/F" of just the "F"
void setEquipmentIcao(const QString &equipmentIcao);
//! Set origin airport ICAO code
@@ -236,9 +240,6 @@ namespace BlackMisc
//! Has callsign?
bool hasCallsign() const { return !m_callsign.isEmpty(); }
//! Get ICAO aircraft equipment code string
const QString &getEquipmentIcao() const { return m_equipmentIcao; }
//! Get origin airport ICAO code
const CAirportIcaoCode &getOriginAirportIcao() const { return m_originAirportIcao; }
@@ -273,7 +274,7 @@ namespace BlackMisc
QString getFuelTimeHourMin() const { return m_fuelTime.valueRoundedWithUnit(BlackMisc::PhysicalQuantities::CTimeUnit::hrmin()); }
//! Cruising altitudes
const BlackMisc::Aviation::CAltitude &getCruiseAltitude() const { return m_cruiseAltitude; }
const CAltitude &getCruiseAltitude() const { return m_cruiseAltitude; }
//! Get planned cruise TAS
const PhysicalQuantities::CSpeed &getCruiseTrueAirspeed() const { return m_cruiseTrueAirspeed; }
@@ -305,12 +306,30 @@ namespace BlackMisc
//! Get the parsable remarks
const CFlightPlanRemarks &getFlightPlanRemarks() const { return m_remarks; }
//! Get aircraft ICAO, derived from equipment ICAO as in getEquipmentIcao()
//! Get ICAO aircraft equipment prefix H/B737/F "H"
const QString &getEquipmentPrefix() const { return m_equipmentPrefix; }
//! Set ICAO aircraft equipment prefix H/B737/F "H"
void setEquipmentPrefix(const QString &prefix) { m_equipmentPrefix = prefix; }
//! Get ICAO aircraft equipment suffix H/B737/F "F"
const QString &getEquipmentSuffix() const { return m_equipmentSuffix; }
//! Set ICAO aircraft equipment suffix H/B737/F "F"
void setEquipmentSuffix(const QString &suffix) { m_equipmentSuffix = suffix; }
//! Get aircraft ICAO H/B737/F "B737"
const CAircraftIcaoCode &getAircraftIcao() const { return m_aircraftIcao; }
//! Set aircraft ICAO code H/B737/F "B737"
void setAircraftIcao(const CAircraftIcaoCode &icao) { m_aircraftIcao = icao; }
//! Has aircraft ICAO?
bool hasAircraftIcao() const { return m_aircraftIcao.hasDesignator(); }
//! Full string like "H/B737/F"
QString getPrefixIcaoSuffix() const;
//! \copydoc BlackMisc::Mixin::Index::propertyByIndex
CVariant propertyByIndex(const CPropertyIndex &index) const;
@@ -329,10 +348,42 @@ namespace BlackMisc
//! String to flight rules
static FlightRules stringToFlightRules(const QString &flightRules);
//! Get aircraft ICAO code from equipment code like
//! \remark we expect something like "H/B772/F" "B773" "B773/F"
static QString aircraftIcaoCodeFromEquipmentCode(const QString &equipmentCodeAndAircraft);
//! Get the 3 parts of "H/B772/F", returned as prefix, ICAO, suffix
static QStringList splitEquipmentCode(const QString &equipmentCodeAndAircraft);
//! Concat the 3 parts to "H/B772/F"
static QString concatPrefixIcaoSuffix(const QString &prefix, const QString &icao, const QString &suffix);
//! Equipment codes 1 character
static const QStringList &faaEquipmentCodes();
//! Codes plus info
static const QStringList &faaEquipmentCodesInfo();
//! SquawkBox equipment codes
static const QStringList &squawkBoxEquipmentCodes();
//! Codes plus info
static const QStringList &squawkBoxEquipmentCodesInfo();
//! All equipment codes
static const QStringList &equipmentCodes();
//! Equipment codes info
static const QStringList &equipmentCodesInfo();
//! Prefix codes "H" .. Heavy, "T" .. TCAS
static const QStringList &prefixCodes();
private:
CCallsign m_callsign; //!< aircraft callsign
QString m_equipmentIcao; //!< e.g. "T/A320/F"
CAircraftIcaoCode m_aircraftIcao; //!< Aircraft ICAO code derived from equipment ICAO
CAircraftIcaoCode m_aircraftIcao; //!< Aircraft ICAO code
QString m_equipmentPrefix; //!< e.g. "T/A320/F" -> the "T"
QString m_equipmentSuffix; //!< e.g. "T/A320/F" -> the "F"
CAirportIcaoCode m_originAirportIcao;
CAirportIcaoCode m_destinationAirportIcao;
CAirportIcaoCode m_alternateAirportIcao;
@@ -348,7 +399,10 @@ namespace BlackMisc
BLACK_METACLASS(
CFlightPlan,
BLACK_METAMEMBER(equipmentIcao),
// callsign will be current flight
BLACK_METAMEMBER(aircraftIcao),
BLACK_METAMEMBER(equipmentPrefix),
BLACK_METAMEMBER(equipmentSuffix),
BLACK_METAMEMBER(originAirportIcao),
BLACK_METAMEMBER(destinationAirportIcao),
BLACK_METAMEMBER(alternateAirportIcao),