mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-01 21:56:43 +08:00
478 lines
16 KiB
C++
478 lines
16 KiB
C++
#include "avatcstation.h"
|
|
#include "aviocomsystem.h"
|
|
#include "voiceroom.h"
|
|
#include "blackmiscfreefunctions.h"
|
|
|
|
using namespace BlackMisc::PhysicalQuantities;
|
|
using namespace BlackMisc::Geo;
|
|
using namespace BlackMisc::Network;
|
|
using namespace BlackMisc::Audio;
|
|
|
|
namespace BlackMisc
|
|
{
|
|
namespace Aviation
|
|
{
|
|
|
|
/*
|
|
* Constructor
|
|
*/
|
|
CAtcStation::CAtcStation() :
|
|
m_distanceToPlane(0, CLengthUnit::nullUnit()), m_isOnline(false), m_atis(CInformationMessage::ATIS), m_metar(CInformationMessage::METAR)
|
|
{
|
|
// void
|
|
}
|
|
|
|
/*
|
|
* Constructor
|
|
*/
|
|
CAtcStation::CAtcStation(const QString &callsign) :
|
|
m_callsign(callsign), m_distanceToPlane(0, CLengthUnit::nullUnit()), m_isOnline(false), m_atis(CInformationMessage::ATIS), m_metar(CInformationMessage::METAR)
|
|
{
|
|
// void
|
|
}
|
|
|
|
/*
|
|
* Constructor
|
|
*/
|
|
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_distanceToPlane(0, CLengthUnit::nullUnit()), m_isOnline(isOnline),
|
|
m_bookedFromUtc(bookedFromUtc), m_bookedUntilUtc(bookedUntilUtc), m_atis(atis), m_metar(metar)
|
|
{
|
|
// sync callsigns
|
|
if (!this->m_controller.hasValidCallsign() && !callsign.isEmpty())
|
|
this->m_controller.setCallsign(callsign);
|
|
}
|
|
|
|
/*
|
|
* Convert to string
|
|
*/
|
|
QString CAtcStation::convertToQString(bool i18n) const
|
|
{
|
|
QString s = i18n ?
|
|
QCoreApplication::translate("Aviation", "ATC station") :
|
|
"ATC station";
|
|
s.append(' ').append(this->m_callsign.toQString(i18n));
|
|
|
|
// position
|
|
s.append(' ').append(this->m_position.toQString(i18n));
|
|
|
|
// Online?
|
|
s.append(' ');
|
|
if (this->m_isOnline)
|
|
{
|
|
i18n ? s.append(QCoreApplication::translate("Aviation", "online")) : s.append("online");
|
|
}
|
|
else
|
|
{
|
|
i18n ? s.append(QCoreApplication::translate("Aviation", "offline")) : s.append("offline");
|
|
}
|
|
|
|
// controller name
|
|
if (!this->m_controller.isValid())
|
|
{
|
|
s.append(' ');
|
|
s.append(this->m_controller.toQString(i18n));
|
|
}
|
|
|
|
// frequency
|
|
s.append(' ');
|
|
s.append(this->m_frequency.toQString(i18n));
|
|
|
|
// ATIS
|
|
if (this->hasAtis())
|
|
{
|
|
s.append(' ');
|
|
s.append(this->m_atis.toQString(i18n));
|
|
}
|
|
|
|
// METAR
|
|
if (this->hasMetar())
|
|
{
|
|
s.append(' ');
|
|
s.append(this->m_metar.toQString(i18n));
|
|
}
|
|
|
|
// range
|
|
s.append(' ');
|
|
i18n ? s.append(s.append(QCoreApplication::translate("Aviation", "range"))) : s.append("range");
|
|
s.append(": ");
|
|
s.append(this->m_range.toQString(i18n));
|
|
|
|
// distance to plane
|
|
if (this->m_distanceToPlane.isPositiveWithEpsilonConsidered())
|
|
{
|
|
i18n ? s.append(QCoreApplication::translate("Aviation", "distance")) : s.append("distance");
|
|
s.append(' ');
|
|
s.append(this->m_distanceToPlane.toQString(i18n));
|
|
}
|
|
|
|
// from / to
|
|
if (!this->hasBookingTimes()) return s;
|
|
|
|
// append from
|
|
s.append(' ');
|
|
i18n ? s.append(s.append(QCoreApplication::translate("Aviation", "from(UTC)"))) : s.append("from(UTC)");
|
|
s.append(": ");
|
|
if (this->m_bookedFromUtc.isNull())
|
|
{
|
|
s.append('-');
|
|
}
|
|
else
|
|
{
|
|
s.append(this->m_bookedFromUtc.toString("yy-MM-dd HH:mm"));
|
|
}
|
|
|
|
// append to
|
|
s.append(' ');
|
|
i18n ? s.append(s.append(QCoreApplication::translate("Aviation", "until(UTC)"))) : s.append("to(UTC)");
|
|
s.append(": ");
|
|
if (this->m_bookedFromUtc.isNull())
|
|
{
|
|
s.append('-');
|
|
}
|
|
else
|
|
{
|
|
s.append(this->m_bookedUntilUtc.toString("yy-MM-dd HH:mm"));
|
|
}
|
|
return s;
|
|
|
|
// force strings for translation in resource files
|
|
(void)QT_TRANSLATE_NOOP("Aviation", "ATC station");
|
|
(void)QT_TRANSLATE_NOOP("Aviation", "online");
|
|
(void)QT_TRANSLATE_NOOP("Aviation", "offline");
|
|
(void)QT_TRANSLATE_NOOP("Aviation", "from(UTC)");
|
|
(void)QT_TRANSLATE_NOOP("Aviation", "until(UTC)");
|
|
(void)QT_TRANSLATE_NOOP("Aviation", "range");
|
|
(void)QT_TRANSLATE_NOOP("Aviation", "distance");
|
|
(void)QT_TRANSLATE_NOOP("Network", "voiceroom");
|
|
}
|
|
|
|
/*
|
|
* Register metadata
|
|
*/
|
|
void CAtcStation::registerMetadata()
|
|
{
|
|
qRegisterMetaType<CAtcStation>();
|
|
qDBusRegisterMetaType<CAtcStation>();
|
|
}
|
|
|
|
/*
|
|
* Members
|
|
*/
|
|
const QStringList &CAtcStation::jsonMembers()
|
|
{
|
|
return TupleConverter<CAtcStation>::jsonMembers();
|
|
}
|
|
|
|
/*
|
|
* To JSON
|
|
*/
|
|
QJsonObject CAtcStation::toJson() const
|
|
{
|
|
return BlackMisc::serializeJson(CAtcStation::jsonMembers(), TupleConverter<CAtcStation>::toTuple(*this));
|
|
}
|
|
|
|
/*
|
|
* From Json
|
|
*/
|
|
void CAtcStation::fromJson(const QJsonObject &json)
|
|
{
|
|
BlackMisc::deserializeJson(json, CAtcStation::jsonMembers(), TupleConverter<CAtcStation>::toTuple(*this));
|
|
}
|
|
|
|
/*
|
|
* Compare
|
|
*/
|
|
int CAtcStation::compareImpl(const CValueObject &otherBase) const
|
|
{
|
|
const auto &other = static_cast<const CAtcStation &>(otherBase);
|
|
return compare(TupleConverter<CAtcStation>::toTuple(*this), TupleConverter<CAtcStation>::toTuple(other));
|
|
}
|
|
|
|
/*
|
|
* Marshall to DBus
|
|
*/
|
|
void CAtcStation::marshallToDbus(QDBusArgument &argument) const
|
|
{
|
|
argument << TupleConverter<CAtcStation>::toTuple(*this);
|
|
}
|
|
|
|
/*
|
|
* Unmarshall from DBus
|
|
*/
|
|
void CAtcStation::unmarshallFromDbus(const QDBusArgument &argument)
|
|
{
|
|
argument >> TupleConverter<CAtcStation>::toTuple(*this);
|
|
}
|
|
|
|
/*
|
|
* Equal?
|
|
*/
|
|
bool CAtcStation::operator ==(const CAtcStation &other) const
|
|
{
|
|
if (this == &other) return true;
|
|
return TupleConverter<CAtcStation>::toTuple(*this) == TupleConverter<CAtcStation>::toTuple(other);
|
|
}
|
|
|
|
/*
|
|
* Hash
|
|
*/
|
|
uint CAtcStation::getValueHash() const
|
|
{
|
|
return qHash(TupleConverter<CAtcStation>::toTuple(*this));
|
|
}
|
|
|
|
/*
|
|
* Unequal?
|
|
*/
|
|
bool CAtcStation::operator !=(const CAtcStation &other) const
|
|
{
|
|
return !((*this) == other);
|
|
}
|
|
|
|
/*
|
|
* SyncronizeControllerData
|
|
*/
|
|
void CAtcStation::syncronizeControllerData(CAtcStation &otherStation)
|
|
{
|
|
if (this->m_controller == otherStation.getController()) return;
|
|
CUser otherController = otherStation.getController();
|
|
this->m_controller.syncronizeData(otherController);
|
|
otherStation.setController(otherController);
|
|
}
|
|
|
|
/*
|
|
* Distance to planne
|
|
*/
|
|
const CLength &CAtcStation::calculcateDistanceToPlane(const CCoordinateGeodetic &position)
|
|
{
|
|
this->m_distanceToPlane = greatCircleDistance(this->m_position, position);
|
|
return this->m_distanceToPlane;
|
|
}
|
|
|
|
/*
|
|
* Booked now
|
|
*/
|
|
bool CAtcStation::isBookedNow() const
|
|
{
|
|
if (!this->hasValidBookingTimes()) return false;
|
|
QDateTime now = QDateTime::currentDateTimeUtc();
|
|
if (this->m_bookedFromUtc > now) return false;
|
|
if (now > this->m_bookedUntilUtc) return false;
|
|
return true;
|
|
}
|
|
|
|
/*!
|
|
* \brief When booked?
|
|
* \return
|
|
*/
|
|
CTime CAtcStation::bookedWhen() const
|
|
{
|
|
if (!this->hasValidBookingTimes()) return CTime(-365.0, CTimeUnit::d());
|
|
QDateTime now = QDateTime::currentDateTimeUtc();
|
|
qint64 diffMs;
|
|
if (this->m_bookedFromUtc > now)
|
|
{
|
|
// future
|
|
diffMs = now.msecsTo(this->m_bookedFromUtc);
|
|
return CTime(diffMs / 1000.0, CTimeUnit::s());
|
|
}
|
|
else if (this->m_bookedUntilUtc > now)
|
|
{
|
|
// now
|
|
return CTime(0.0, CTimeUnit::s());
|
|
}
|
|
else
|
|
{
|
|
// past
|
|
diffMs = m_bookedUntilUtc.msecsTo(now);
|
|
return CTime(-diffMs / 1000.0, CTimeUnit::s());
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Property by index
|
|
*/
|
|
QVariant CAtcStation::propertyByIndex(int index) const
|
|
{
|
|
switch (index)
|
|
{
|
|
case IndexBookedFrom:
|
|
return QVariant(this->m_bookedFromUtc);
|
|
case IndexBookedUntil:
|
|
return QVariant(this->m_bookedUntilUtc);
|
|
case IndexCallsign:
|
|
return this->m_callsign.toQVariant();
|
|
case IndexCallsignAsString:
|
|
return QVariant(this->m_callsign.asString());
|
|
case IndexCallsignAsStringAsSet:
|
|
return QVariant(this->m_callsign.getStringAsSet());
|
|
case IndexController:
|
|
return this->m_controller.toQVariant();
|
|
case IndexControllerRealName:
|
|
return QVariant(this->getControllerRealName());
|
|
case IndexControllerId:
|
|
return QVariant(this->getControllerId());
|
|
case IndexFrequency:
|
|
return this->m_frequency.toQVariant();
|
|
case IndexIsOnline:
|
|
return QVariant(this->m_isOnline);
|
|
case IndexLatitude:
|
|
return this->latitude().toQVariant();
|
|
case IndexDistance:
|
|
return this->m_distanceToPlane.toQVariant();
|
|
case IndexLongitude:
|
|
return this->longitude().toQVariant();
|
|
case IndexPosition:
|
|
return this->m_position.toQVariant();
|
|
case IndexRange:
|
|
return this->m_range.toQVariant();
|
|
case IndexAtis:
|
|
return this->m_atis.toQVariant();
|
|
case IndexAtisMessage:
|
|
return QVariant(this->m_atis.getMessage());
|
|
case IndexMetar:
|
|
return this->m_metar.toQVariant();
|
|
case IndexMetarMessage:
|
|
return QVariant(this->m_metar.getMessage());
|
|
case IndexVoiceRoom:
|
|
return QVariant(this->m_voiceRoom.toQVariant());
|
|
case IndexVoiceRoomUrl:
|
|
return QVariant(this->m_voiceRoom.getVoiceRoomUrl());
|
|
default:
|
|
break;
|
|
}
|
|
|
|
Q_ASSERT_X(false, "CAtcStation", "index unknown");
|
|
QString m = QString("no property, index ").append(QString::number(index));
|
|
return QVariant::fromValue(m);
|
|
}
|
|
|
|
/*
|
|
* Set property as index
|
|
*/
|
|
void CAtcStation::setPropertyByIndex(const QVariant &variant, int index)
|
|
{
|
|
switch (index)
|
|
{
|
|
case IndexBookedFrom:
|
|
this->setBookedFromUtc(variant.value<QDateTime>());
|
|
break;
|
|
case IndexBookedUntil:
|
|
this->setBookedUntilUtc(variant.value<QDateTime>());
|
|
break;
|
|
case IndexCallsign:
|
|
this->setCallsign(variant.value<CCallsign>());
|
|
break;
|
|
case IndexCallsignAsString:
|
|
this->setCallsign(CCallsign(variant.value<QString>()));
|
|
break;
|
|
case IndexController:
|
|
this->setController(variant.value<CUser>());
|
|
break;
|
|
case IndexControllerRealName:
|
|
this->setControllerRealName(variant.value<QString>());
|
|
break;
|
|
case IndexControllerId:
|
|
this->setControllerId(variant.value<QString>());
|
|
break;
|
|
case IndexFrequency:
|
|
this->setFrequency(variant.value<CFrequency>());
|
|
break;
|
|
case IndexIsOnline:
|
|
this->setOnline(variant.value<bool>());
|
|
break;
|
|
case IndexPosition:
|
|
this->setPosition(variant.value<CCoordinateGeodetic>());
|
|
break;
|
|
case IndexRange:
|
|
this->setRange(variant.value<CLength>());
|
|
break;
|
|
case IndexDistance:
|
|
this->setDistanceToPlane(variant.value<CLength>());
|
|
break;
|
|
case IndexAtis:
|
|
this->setAtis(variant.value<CInformationMessage>());
|
|
break;
|
|
case IndexAtisMessage:
|
|
this->setAtisMessage(variant.value<QString>());
|
|
break;
|
|
case IndexMetar:
|
|
this->setMetar(variant.value<CInformationMessage>());
|
|
break;
|
|
case IndexMetarMessage:
|
|
this->setMetarMessage(variant.value<QString>());
|
|
break;
|
|
case IndexVoiceRoom:
|
|
this->setVoiceRoom(variant.value<CVoiceRoom>());
|
|
break;
|
|
case IndexVoiceRoomUrl:
|
|
this->setVoiceRoom(CVoiceRoom(variant.toString()));
|
|
break;
|
|
default:
|
|
Q_ASSERT_X(false, "CAtcStation", "index unknown (setter)");
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* metaTypeId
|
|
*/
|
|
int CAtcStation::getMetaTypeId() const
|
|
{
|
|
return qMetaTypeId<CAtcStation>();
|
|
}
|
|
|
|
/*
|
|
* is a
|
|
*/
|
|
bool CAtcStation::isA(int metaTypeId) const
|
|
{
|
|
if (metaTypeId == qMetaTypeId<CAtcStation>()) { return true; }
|
|
|
|
return this->CValueObject::isA(metaTypeId);
|
|
}
|
|
|
|
/*
|
|
* Property as string by index
|
|
*/
|
|
QString CAtcStation::propertyByIndexAsString(int index, bool i18n) const
|
|
{
|
|
QVariant qv = this->propertyByIndex(index);
|
|
// special treatment
|
|
// this is required as it is possible an ATC station is not containing all
|
|
// properties
|
|
switch (index)
|
|
{
|
|
case IndexFrequency:
|
|
if (!CComSystem::isValidCivilAviationFrequency(qv.value<CFrequency>()))
|
|
return "";
|
|
else
|
|
return qv.value<CFrequency>().valueRoundedWithUnit(3, i18n);
|
|
break;
|
|
case IndexDistance:
|
|
{
|
|
CLength distance = qv.value<CLength>();
|
|
if (distance.isNegativeWithEpsilonConsidered()) return "";
|
|
return distance.toQString(i18n);
|
|
}
|
|
|
|
case IndexBookedFrom:
|
|
case IndexBookedUntil:
|
|
{
|
|
QDateTime dt = qv.value<QDateTime>();
|
|
if (dt.isNull() || !dt.isValid()) return "";
|
|
return dt.toString("yyyy-MM-dd HH:mm");
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return BlackMisc::qVariantToString(qv, i18n);
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace
|