refs #789, improvements when addressing FSX driver issue

* added new utility funtion is model list / aircraft list
* added setters/getters for CSimConnectObject
* added setters/getters for InterpolationStatus / PartsStatus
* added CSimConnectObjects (better encapsulation)
This commit is contained in:
Klaus Basan
2016-11-07 01:47:28 +01:00
parent 3de052494f
commit 9deedf1e10
13 changed files with 200 additions and 28 deletions

View File

@@ -162,7 +162,7 @@ namespace BlackCore
const qint64 time = QDateTime::currentMSecsSinceEpoch(); const qint64 time = QDateTime::currentMSecsSinceEpoch();
IInterpolator::InterpolationStatus interpolationStatus; IInterpolator::InterpolationStatus interpolationStatus;
const CAircraftSituation as(m_interpolator->getInterpolatedSituation(callsign, time, aircraft.isVtol(), interpolationStatus)); const CAircraftSituation as(m_interpolator->getInterpolatedSituation(callsign, time, aircraft.isVtol(), interpolationStatus));
if (interpolationStatus.interpolationSucceeded) if (interpolationStatus.didInterpolationSucceed())
{ {
aircraft.setSituation(as); aircraft.setSituation(as);
return true; return true;

View File

@@ -40,7 +40,7 @@ namespace BlackMisc
CAircraftPartsList IInterpolator::getPartsBeforeTime(const CAircraftPartsList &parts, qint64 cutoffTime, BlackMisc::IInterpolator::PartsStatus &partsStatus) const CAircraftPartsList IInterpolator::getPartsBeforeTime(const CAircraftPartsList &parts, qint64 cutoffTime, BlackMisc::IInterpolator::PartsStatus &partsStatus) const
{ {
partsStatus.reset(); partsStatus.reset();
partsStatus.supportsParts = true; partsStatus.setSupportsParts(true);
if (cutoffTime < 0) { return parts; } if (cutoffTime < 0) { return parts; }
return parts.findBefore(cutoffTime); return parts.findBefore(cutoffTime);
@@ -51,8 +51,8 @@ namespace BlackMisc
Q_ASSERT_X(!callsign.isEmpty(), Q_FUNC_INFO, "empty callsign"); Q_ASSERT_X(!callsign.isEmpty(), Q_FUNC_INFO, "empty callsign");
partsStatus.reset(); partsStatus.reset();
partsStatus.supportsParts = this->isRemoteAircraftSupportingParts(callsign); partsStatus.setSupportsParts(this->isRemoteAircraftSupportingParts(callsign));
if (!partsStatus.supportsParts) { return {}; } if (!partsStatus.isSupportingParts()) { return {}; }
return this->remoteAircraftParts(callsign, cutoffTime); return this->remoteAircraftParts(callsign, cutoffTime);
} }
@@ -70,22 +70,22 @@ namespace BlackMisc
bool IInterpolator::InterpolationStatus::allTrue() const bool IInterpolator::InterpolationStatus::allTrue() const
{ {
return interpolationSucceeded && changedPosition; return m_interpolationSucceeded && m_changedPosition;
} }
void IInterpolator::InterpolationStatus::reset() void IInterpolator::InterpolationStatus::reset()
{ {
changedPosition = false; m_changedPosition = false;
interpolationSucceeded = false; m_interpolationSucceeded = false;
} }
bool IInterpolator::PartsStatus::allTrue() const bool IInterpolator::PartsStatus::allTrue() const
{ {
return supportsParts; return m_supportsParts;
} }
void IInterpolator::PartsStatus::reset() void IInterpolator::PartsStatus::reset()
{ {
supportsParts = false; m_supportsParts = false;
} }
} // namespace } // namespace

View File

@@ -43,9 +43,22 @@ namespace BlackMisc
//! Status of interpolation //! Status of interpolation
struct BLACKMISC_EXPORT InterpolationStatus struct BLACKMISC_EXPORT InterpolationStatus
{ {
private:
bool m_changedPosition = false; //!< position was changed
bool m_interpolationSucceeded = false; //!< interpolation succeeded (means enough values, etc.)
public: public:
bool changedPosition = false; //!< position was changed //! Did interpolation succeed?
bool interpolationSucceeded = false; //!< interpolation succeeded (means enough values, etc.) bool didInterpolationSucceed() const { return m_interpolationSucceeded; }
//! Set succeeded
void setInterpolationSucceeded(bool succeeded) { m_interpolationSucceeded = succeeded; }
//! Changed position?
bool hasChangedPosition() const { return m_changedPosition; }
//! Set as changed
void setChangedPosition(bool changed) { m_changedPosition = changed; }
//! all OK //! all OK
bool allTrue() const; bool allTrue() const;
@@ -57,11 +70,19 @@ namespace BlackMisc
//! Status regarding parts //! Status regarding parts
struct BLACKMISC_EXPORT PartsStatus struct BLACKMISC_EXPORT PartsStatus
{ {
bool supportsParts = false; //!< supports parts for given callsign private:
bool m_supportsParts = false; //!< supports parts for given callsign
public:
//! all OK //! all OK
bool allTrue() const; bool allTrue() const;
//! Supporting parts
bool isSupportingParts() const { return m_supportsParts; }
//! Set support flag
void setSupportsParts(bool supports) { m_supportsParts = supports; }
//! Reset to default values //! Reset to default values
void reset(); void reset();
}; };

View File

@@ -60,8 +60,8 @@ namespace BlackMisc
// interpolation situations // interpolation situations
CAircraftSituation oldSituation; CAircraftSituation oldSituation;
CAircraftSituation newSituation; CAircraftSituation newSituation;
status.interpolationSucceeded = true; status.setInterpolationSucceeded(true);
status.changedPosition = true; //! \todo efficiently determine whether the position has changed status.setChangedPosition(true); //! \todo efficiently determine whether the position has changed
// latest first, now 00:20 split time // latest first, now 00:20 split time
// time pos // time pos

View File

@@ -54,6 +54,16 @@ namespace BlackMisc
return false; return false;
} }
bool CAircraftModelList::containsCallsign(const CCallsign &callsign) const
{
return this->contains(&CAircraftModel::getCallsign, callsign);
}
bool CAircraftModelList::containsModelsWithAircraftAndAirlineDesignator(const QString &aircraftDesignator, const QString &airlineDesignator) const
{
return this->contains(&CAircraftModel::getAircraftIcaoCodeDesignator, aircraftDesignator, &CAircraftModel::getAirlineIcaoCodeDesignator, airlineDesignator);
}
CAircraftModelList CAircraftModelList::findByModelString(const QString &modelString, Qt::CaseSensitivity sensitivity) const CAircraftModelList CAircraftModelList::findByModelString(const QString &modelString, Qt::CaseSensitivity sensitivity) const
{ {
return this->findBy([ & ](const CAircraftModel & model) return this->findBy([ & ](const CAircraftModel & model)

View File

@@ -65,6 +65,12 @@ namespace BlackMisc
//! Contains model with model string or id //! Contains model with model string or id
bool containsModelStringOrDbKey(const BlackMisc::Simulation::CAircraftModel &model, Qt::CaseSensitivity sensitivity = Qt::CaseInsensitive) const; bool containsModelStringOrDbKey(const BlackMisc::Simulation::CAircraftModel &model, Qt::CaseSensitivity sensitivity = Qt::CaseInsensitive) const;
//! Contains model for callsign
bool containsCallsign(const BlackMisc::Aviation::CCallsign &callsign) const;
//! Contains any model with aircraft and airline designator
bool containsModelsWithAircraftAndAirlineDesignator(const QString &aircraftDesignator, const QString &airlineDesignator) const;
//! Find by model string //! Find by model string
//! \remark normally CAircraftModelList::findFirstByModelStringOrDefault would be used //! \remark normally CAircraftModelList::findFirstByModelStringOrDefault would be used
CAircraftModelList findByModelString(const QString &modelString, Qt::CaseSensitivity sensitivity = Qt::CaseInsensitive) const; CAircraftModelList findByModelString(const QString &modelString, Qt::CaseSensitivity sensitivity = Qt::CaseInsensitive) const;

View File

@@ -153,5 +153,18 @@ namespace BlackMisc
return false; return false;
} }
bool CSimulatedAircraftList::replaceOrAddByCallsign(const CSimulatedAircraft &aircraft)
{
const CCallsign cs(aircraft.getCallsign());
if (cs.isEmpty()) { return false; }
if (this->containsCallsign(cs))
{
int c = this->replaceIf(&CSimulatedAircraft::getCallsign, cs, aircraft);
return c > 0;
}
this->push_back(aircraft);
return true;
}
} // namespace } // namespace
} // namespace } // namespace

View File

@@ -92,8 +92,9 @@ namespace BlackMisc
//! Rendered? //! Rendered?
bool isRendered(const BlackMisc::Aviation::CCallsign &callsign) const; bool isRendered(const BlackMisc::Aviation::CCallsign &callsign) const;
//! Replace or add by callsign
bool replaceOrAddByCallsign(const CSimulatedAircraft &aircraft);
}; };
} //namespace } //namespace
} // namespace } // namespace

View File

@@ -39,7 +39,7 @@ namespace BlackSimPlugin
positionVelocity.lat_f = qAbs((latitude - positionVelocity.lat_i) * 65536); positionVelocity.lat_f = qAbs((latitude - positionVelocity.lat_i) * 65536);
// Longitude - integer and decimal places // Longitude - integer and decimal places
double longitude = newSituation.getPosition().longitude().value(CAngleUnit::deg()) * ( 65536.0 * 65536.0) / 360.0; double longitude = newSituation.getPosition().longitude().value(CAngleUnit::deg()) * (65536.0 * 65536.0) / 360.0;
positionVelocity.lon_hi = static_cast<qint32>(longitude); positionVelocity.lon_hi = static_cast<qint32>(longitude);
positionVelocity.lon_lo = qAbs((longitude - positionVelocity.lon_hi) * 65536); positionVelocity.lon_lo = qAbs((longitude - positionVelocity.lon_hi) * 65536);
@@ -96,7 +96,7 @@ namespace BlackSimPlugin
positionSlewMode.lat_f = qAbs((latitude - positionSlewMode.lat_i) * 65536); positionSlewMode.lat_f = qAbs((latitude - positionSlewMode.lat_i) * 65536);
// Longitude - integer and decimal places // Longitude - integer and decimal places
double longitude = situation.getPosition().longitude().value(CAngleUnit::deg()) * ( 65536.0 * 65536.0) / 360.0; double longitude = situation.getPosition().longitude().value(CAngleUnit::deg()) * (65536.0 * 65536.0) / 360.0;
positionSlewMode.lon_hi = static_cast<qint32>(longitude); positionSlewMode.lon_hi = static_cast<qint32>(longitude);
positionSlewMode.lon_lo = qAbs((longitude - positionSlewMode.lon_hi) * 65536); positionSlewMode.lon_lo = qAbs((longitude - positionSlewMode.lon_hi) * 65536);
@@ -119,7 +119,7 @@ namespace BlackSimPlugin
} }
CFs9Client::CFs9Client(const CCallsign &callsign, const QString &modelName, CFs9Client::CFs9Client(const CCallsign &callsign, const QString &modelName,
BlackMisc::IInterpolator *interpolator, const CTime &updateInterval, QObject *owner) : BlackMisc::IInterpolator *interpolator, const CTime &updateInterval, QObject *owner) :
CDirectPlayPeer(owner, callsign), CDirectPlayPeer(owner, callsign),
m_updateInterval(updateInterval), m_interpolator(interpolator), m_modelName(modelName) m_updateInterval(updateInterval), m_interpolator(interpolator), m_modelName(modelName)
{ {
@@ -174,7 +174,7 @@ namespace BlackSimPlugin
CAircraftSituation situation = this->m_interpolator->getInterpolatedSituation(m_callsign, -1, vtolAircraft, status); CAircraftSituation situation = this->m_interpolator->getInterpolatedSituation(m_callsign, -1, vtolAircraft, status);
// Test only for successful interpolation. FS9 requires constant positions // Test only for successful interpolation. FS9 requires constant positions
if (!status.interpolationSucceeded) { return; } if (!status.didInterpolationSucceed()) { return; }
sendMultiplayerPosition(situation); sendMultiplayerPosition(situation);
sendMultiplayerParamaters(); sendMultiplayerParamaters();

View File

@@ -9,6 +9,9 @@
#include "simconnectobject.h" #include "simconnectobject.h"
using namespace BlackMisc::Aviation;
using namespace BlackMisc::Simulation;
namespace BlackSimPlugin namespace BlackSimPlugin
{ {
namespace Fsx namespace Fsx
@@ -19,9 +22,83 @@ namespace BlackSimPlugin
m_aircraft(aircraft), m_requestId(requestId) m_aircraft(aircraft), m_requestId(requestId)
{ } { }
bool CSimConnectObject::hasValidRequestId() const
{
return this->m_requestId >= 0;
}
bool CSimConnectObject::hasValidobjectId() const
{
return this->m_objectId >= 0;
}
bool CSimConnectObject::isPendingAdded() const
{
return !this->hasValidRequestAndObjectId() || !this->m_confirmedAdded;
}
bool CSimConnectObject::isConfirmedAdded() const
{
Q_ASSERT_X(!m_confirmedAdded || this->hasValidRequestAndObjectId(), Q_FUNC_INFO, "confirmed but invalid ids");
return m_confirmedAdded;
}
void CSimConnectObject::setConfirmedAdded(bool confirm)
{
m_confirmedAdded = confirm;
m_aircraft.setRendered(true);
}
void CSimConnectObject::setPendingRemoved(bool pending)
{
m_pendingRemoved = pending;
m_aircraft.setRendered(false);
}
bool CSimConnectObject::hasValidRequestAndObjectId() const bool CSimConnectObject::hasValidRequestAndObjectId() const
{ {
return this->m_requestId >= 0 && this->m_objectId >= 0; return this->hasValidRequestId() && this->hasValidobjectId();
}
bool CSimConnectObjects::setSimConnectObjectId(int requestID, int objectId)
{
// First check, if this request id belongs to us
const int requestIntId = static_cast<int>(requestID);
auto it = std::find_if(this->begin(), this->end(), [requestIntId](const CSimConnectObject & obj) { return obj.getRequestId() == requestIntId; });
if (it == this->end()) { return false; }
// belongs to us
it->setObjectId(objectId);
return true;
}
CCallsign CSimConnectObjects::getCallsignForObjectId(int objectId) const
{
return getSimObjectForObjectId(objectId).getCallsign();
}
CSimConnectObject CSimConnectObjects::getSimObjectForObjectId(int objectId) const
{
for (const CSimConnectObject &simObject : this->values())
{
if (simObject.getObjectId() == objectId) { return simObject; }
}
return CSimConnectObject();
}
bool CSimConnectObjects::isKnownSimObjectId(int objectId) const
{
const CSimConnectObject simObject(getSimObjectForObjectId(objectId));
return simObject.hasValidRequestAndObjectId() && objectId == simObject.getObjectId();
}
bool CSimConnectObjects::containsPendingAdd() const
{
for (const CSimConnectObject &simObject : this->values())
{
if (simObject.isPendingAdded()) { return true; }
}
return false;
} }
} // namespace } // namespace
} // namespace } // namespace

View File

@@ -29,16 +29,16 @@ namespace BlackSimPlugin
CSimConnectObject(); CSimConnectObject();
//! Constructor //! Constructor
CSimConnectObject(const BlackMisc::Simulation::CSimulatedAircraft &aircraft,int requestId); CSimConnectObject(const BlackMisc::Simulation::CSimulatedAircraft &aircraft, int requestId);
//! Destructor //! Destructor
~CSimConnectObject() {} ~CSimConnectObject() {}
//! Get Callsign //! Get Callsign
BlackMisc::Aviation::CCallsign getCallsign() const { return m_aircraft.getCallsign(); } const BlackMisc::Aviation::CCallsign &getCallsign() const { return m_aircraft.getCallsign(); }
//! Simulated aircraft (as added) //! Simulated aircraft (as added)
BlackMisc::Simulation::CSimulatedAircraft getAircraft() const { return m_aircraft; } const BlackMisc::Simulation::CSimulatedAircraft &getAircraft() const { return m_aircraft; }
//! Set Simconnect request id //! Set Simconnect request id
void setRequestId(int id) { m_requestId = id; } void setRequestId(int id) { m_requestId = id; }
@@ -52,6 +52,27 @@ namespace BlackSimPlugin
//! Set Simconnect object id //! Set Simconnect object id
int getObjectId() const { return m_objectId; } int getObjectId() const { return m_objectId; }
//! Valid request id?
bool hasValidRequestId() const;
//! Valid object id?
bool hasValidobjectId() const;
//! Object is requested, not yet added
bool isPendingAdded() const;
//! Adding is confirmed
bool isConfirmedAdded() const;
//! Marked as confirmed
void setConfirmedAdded(bool confirm);
//! Removing is pending
bool isPendingRemoved() const { return m_pendingRemoved; }
//! Marked as confirmed
void setPendingRemoved(bool pending);
//! VTOL? //! VTOL?
bool isVtol() const { return m_aircraft.isVtol(); } bool isVtol() const { return m_aircraft.isVtol(); }
@@ -62,7 +83,30 @@ namespace BlackSimPlugin
BlackMisc::Simulation::CSimulatedAircraft m_aircraft; BlackMisc::Simulation::CSimulatedAircraft m_aircraft;
int m_requestId = -1; int m_requestId = -1;
int m_objectId = -1; int m_objectId = -1;
bool m_confirmedAdded = false;
bool m_pendingRemoved = false;
}; };
//! Simulator objects (aka AI aircraft
class CSimConnectObjects : public QHash<BlackMisc::Aviation::CCallsign, CSimConnectObject>
{
public:
//! Set ID of a SimConnect object, so far we only have an request id in the object
bool setSimConnectObjectId(int requestID, int objectId);
//! Find which callsign belongs to the object id
BlackMisc::Aviation::CCallsign getCallsignForObjectId(int objectId) const;
//! Find which callsign belongs to the object id
CSimConnectObject getSimObjectForObjectId(int objectId) const;
//! Is the object id one of our AI objects?
bool isKnownSimObjectId(int objectId) const;
//! Pending add condition
bool containsPendingAdd() const;
};
} // namespace } // namespace
} // namespace } // namespace

View File

@@ -308,8 +308,8 @@ namespace XBus
{ {
BlackMisc::IInterpolator::InterpolationStatus status; BlackMisc::IInterpolator::InterpolationStatus status;
auto situation = m_interpolator->getInterpolatedSituation(plane->situations, -1, false, status); auto situation = m_interpolator->getInterpolatedSituation(plane->situations, -1, false, status);
if (! status.interpolationSucceeded) { return xpmpData_Unavailable; } if (! status.didInterpolationSucceed()) { return xpmpData_Unavailable; }
if (! status.changedPosition) { return xpmpData_Unchanged; } if (! status.hasChangedPosition()) { return xpmpData_Unchanged; }
using namespace BlackMisc::PhysicalQuantities; using namespace BlackMisc::PhysicalQuantities;
using namespace BlackMisc::Aviation; using namespace BlackMisc::Aviation;

View File

@@ -99,8 +99,8 @@ namespace BlackCoreTest
CAircraftSituation currentSituation(interpolator.getInterpolatedSituation CAircraftSituation currentSituation(interpolator.getInterpolatedSituation
(cs, currentTime, false, status) (cs, currentTime, false, status)
); );
QVERIFY2(status.interpolationSucceeded, "Interpolation was not succesful"); QVERIFY2(status.didInterpolationSucceed(), "Interpolation was not succesful");
QVERIFY2(status.changedPosition, "Interpolation did not changed"); QVERIFY2(status.hasChangedPosition(), "Interpolation did not changed");
double latDeg = currentSituation.getPosition().latitude().valueRounded(CAngleUnit::deg(), 5); double latDeg = currentSituation.getPosition().latitude().valueRounded(CAngleUnit::deg(), 5);
double lngDeg = currentSituation.getPosition().longitude().valueRounded(CAngleUnit::deg(), 5); double lngDeg = currentSituation.getPosition().longitude().valueRounded(CAngleUnit::deg(), 5);
QVERIFY2(latDeg < latOld && lngDeg < lngOld, "Values shall decrease"); QVERIFY2(latDeg < latOld && lngDeg < lngOld, "Values shall decrease");
@@ -150,7 +150,7 @@ namespace BlackCoreTest
IInterpolator::PartsStatus status; IInterpolator::PartsStatus status;
CAircraftPartsList pl(interpolator.getPartsBeforeTime(cs, ts, status)); CAircraftPartsList pl(interpolator.getPartsBeforeTime(cs, ts, status));
fetchedParts++; fetchedParts++;
QVERIFY2(status.supportsParts, "Parts not supported"); QVERIFY2(status.isSupportingParts(), "Parts not supported");
QVERIFY2(!pl.isEmpty(), "Parts empty"); QVERIFY2(!pl.isEmpty(), "Parts empty");
} }
timeMs = timer.elapsed(); timeMs = timer.elapsed();