mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-23 05:45:35 +08:00
Ref T243, adjust offset for timestamp based objects when keeping the order
This commit is contained in:
@@ -1288,7 +1288,7 @@ namespace BlackCore
|
|||||||
// list from new to old
|
// list from new to old
|
||||||
QWriteLocker lock(&m_lockSituations);
|
QWriteLocker lock(&m_lockSituations);
|
||||||
CAircraftSituationList &situationList = m_situationsByCallsign[callsign];
|
CAircraftSituationList &situationList = m_situationsByCallsign[callsign];
|
||||||
situationList.push_frontMaxElements(situation, IRemoteAircraftProvider::MaxSituationsPerCallsign);
|
situationList.push_frontKeepLatestFirstAdjustOffset(situation, IRemoteAircraftProvider::MaxSituationsPerCallsign);
|
||||||
|
|
||||||
// check sort order
|
// check sort order
|
||||||
Q_ASSERT_X(situationList.isSortedAdjustedLatestFirst(), Q_FUNC_INFO, "wrong sort order");
|
Q_ASSERT_X(situationList.isSortedAdjustedLatestFirst(), Q_FUNC_INFO, "wrong sort order");
|
||||||
@@ -1303,7 +1303,7 @@ namespace BlackCore
|
|||||||
// list sorted from new to old
|
// list sorted from new to old
|
||||||
QWriteLocker lock(&m_lockParts);
|
QWriteLocker lock(&m_lockParts);
|
||||||
CAircraftPartsList &partsList = m_partsByCallsign[callsign];
|
CAircraftPartsList &partsList = m_partsByCallsign[callsign];
|
||||||
partsList.push_frontKeepLatestAdjustedFirst(parts, IRemoteAircraftProvider::MaxPartsPerCallsign);
|
partsList.push_frontKeepLatestFirstAdjustOffset(parts, IRemoteAircraftProvider::MaxPartsPerCallsign);
|
||||||
|
|
||||||
// remove outdated parts (but never remove the most recent one)
|
// remove outdated parts (but never remove the most recent one)
|
||||||
IRemoteAircraftProvider::removeOutdatedParts(partsList);
|
IRemoteAircraftProvider::removeOutdatedParts(partsList);
|
||||||
|
|||||||
@@ -238,11 +238,7 @@ namespace BlackMisc
|
|||||||
return emptyParts;
|
return emptyParts;
|
||||||
}
|
}
|
||||||
|
|
||||||
// with the latest updates of T243 the order and the offsets are supposed to be correct
|
// Ref T243, KB 2018-02, can be removed in future, we verify parts when we add parts
|
||||||
// so even mixing fast/slow updates shall work
|
|
||||||
Q_ASSERT_X(m_aircraftParts.isSortedAdjustedLatestFirst(), Q_FUNC_INFO, "Wrong sort order");
|
|
||||||
|
|
||||||
// Ref T243, KB 2018-02, can be removed in future, we verify parts above
|
|
||||||
// Parts are supposed to be in correct order
|
// Parts are supposed to be in correct order
|
||||||
// const auto end = std::is_sorted_until(m_aircraftParts.begin(), m_aircraftParts.end(), [](auto && a, auto && b) { return b.getAdjustedMSecsSinceEpoch() < a.getAdjustedMSecsSinceEpoch(); });
|
// const auto end = std::is_sorted_until(m_aircraftParts.begin(), m_aircraftParts.end(), [](auto && a, auto && b) { return b.getAdjustedMSecsSinceEpoch() < a.getAdjustedMSecsSinceEpoch(); });
|
||||||
// const auto validParts = makeRange(m_aircraftParts.begin(), end);
|
// const auto validParts = makeRange(m_aircraftParts.begin(), end);
|
||||||
@@ -328,36 +324,54 @@ namespace BlackMisc
|
|||||||
}
|
}
|
||||||
|
|
||||||
// we add new situations at front and keep the latest values (real time) first
|
// we add new situations at front and keep the latest values (real time) first
|
||||||
m_aircraftSituations.push_frontKeepLatestFirst(situation, IRemoteAircraftProvider::MaxSituationsPerCallsign);
|
m_aircraftSituations.push_frontKeepLatestFirstAdjustOffset(situation, IRemoteAircraftProvider::MaxSituationsPerCallsign);
|
||||||
|
|
||||||
|
|
||||||
|
// with the latest updates of T243 the order and the offsets are supposed to be correct
|
||||||
|
// so even mixing fast/slow updates shall work
|
||||||
|
Q_ASSERT_X(!m_aircraftSituations.containsZeroOrNegativeOffsetTime(), Q_FUNC_INFO, "Missing offset time");
|
||||||
|
Q_ASSERT_X(m_aircraftSituations.isSortedAdjustedLatestFirst(), Q_FUNC_INFO, "Wrong sort order");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Derived>
|
template <typename Derived>
|
||||||
void CInterpolator<Derived>::addAircraftParts(const CAircraftParts &parts)
|
void CInterpolator<Derived>::addAircraftParts(const CAircraftParts &parts)
|
||||||
{
|
{
|
||||||
const bool hasOffset = parts.hasOffsetTime();
|
const bool hasOffset = parts.hasOffsetTime();
|
||||||
const qint64 offset =
|
if (!hasOffset)
|
||||||
hasOffset ?
|
{
|
||||||
parts.getTimeOffsetMs() :
|
const qint64 offset =
|
||||||
m_aircraftSituations.isEmpty() ? IRemoteAircraftProvider::DefaultOffsetTimeMs : m_aircraftSituations.front().getTimeOffsetMs();
|
hasOffset ?
|
||||||
|
parts.getTimeOffsetMs() :
|
||||||
|
m_aircraftSituations.isEmpty() ? IRemoteAircraftProvider::DefaultOffsetTimeMs : m_aircraftSituations.front().getTimeOffsetMs();
|
||||||
|
CAircraftParts copy(parts);
|
||||||
|
copy.setTimeOffsetMs(offset);
|
||||||
|
CInterpolator<Derived>::addAircraftParts(copy);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// here we have an offset
|
||||||
|
Q_ASSERT_X(parts.hasOffsetTime(), Q_FUNC_INFO, "Missing parts offset");
|
||||||
if (m_aircraftParts.isEmpty())
|
if (m_aircraftParts.isEmpty())
|
||||||
{
|
{
|
||||||
// make sure we have enough parts to do start interpolating immediately without waiting for more updates
|
// make sure we have enough parts to do start interpolating immediately without waiting for more updates
|
||||||
// the offsets here (addMSecs) do not really matter
|
// the offsets here (addMSecs) do not really matter
|
||||||
CAircraftParts copy(parts);
|
CAircraftParts copy(parts);
|
||||||
copy.setTimeOffsetMs(offset);
|
copy.addMsecs(-2 * parts.getTimeOffsetMs());
|
||||||
copy.addMsecs(-2 * offset);
|
|
||||||
m_aircraftParts.push_frontKeepLatestFirst(copy);
|
m_aircraftParts.push_frontKeepLatestFirst(copy);
|
||||||
copy.addMsecs(offset);
|
copy.addMsecs(parts.getTimeOffsetMs());
|
||||||
m_aircraftParts.push_frontKeepLatestFirst(copy);
|
m_aircraftParts.push_frontKeepLatestFirst(copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we add new situations at front and keep the latest values (real time) first
|
// we add new situations at front and keep the latest values (real time) first
|
||||||
m_aircraftParts.push_frontKeepLatestFirst(parts, IRemoteAircraftProvider::MaxSituationsPerCallsign);
|
m_aircraftParts.push_frontKeepLatestFirstAdjustOffset(parts, IRemoteAircraftProvider::MaxSituationsPerCallsign);
|
||||||
if (!hasOffset) { m_aircraftParts.front().setTimeOffsetMs(offset); }
|
|
||||||
|
|
||||||
// force remote provider to cleanup
|
// force remote provider to cleanup
|
||||||
IRemoteAircraftProvider::removeOutdatedParts(m_aircraftParts);
|
IRemoteAircraftProvider::removeOutdatedParts(m_aircraftParts);
|
||||||
|
|
||||||
|
// with the latest updates of T243 the order and the offsets are supposed to be correct
|
||||||
|
// so even mixing fast/slow updates shall work
|
||||||
|
Q_ASSERT_X(!m_aircraftParts.containsZeroOrNegativeOffsetTime(), Q_FUNC_INFO, "Missing offset time");
|
||||||
|
Q_ASSERT_X(m_aircraftParts.isSortedAdjustedLatestFirst(), Q_FUNC_INFO, "Wrong sort order");
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
|
|||||||
@@ -232,17 +232,18 @@ namespace BlackMisc
|
|||||||
{
|
{
|
||||||
c.truncate(maxElements - 1);
|
c.truncate(maxElements - 1);
|
||||||
}
|
}
|
||||||
if (!c.isEmpty() && value.isOlderThan(c.front()))
|
const bool needSort = !c.isEmpty() && value.isOlderThan(c.front());
|
||||||
|
c.push_front(value);
|
||||||
|
if (needSort)
|
||||||
{
|
{
|
||||||
ITimestampObjectList::sortLatestFirst();
|
ITimestampObjectList::sortLatestFirst();
|
||||||
}
|
}
|
||||||
c.push_front(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class OBJ, class CONTAINER>
|
template<class OBJ, class CONTAINER>
|
||||||
bool ITimestampObjectList<OBJ, CONTAINER>::isSortedLatestLast() const
|
bool ITimestampObjectList<OBJ, CONTAINER>::isSortedLatestLast() const
|
||||||
{
|
{
|
||||||
if (this->container().isEmpty()) { return true; }
|
if (this->container().size() < 2) { return true; }
|
||||||
qint64 max = -1;
|
qint64 max = -1;
|
||||||
for (const ITimestampBased &obj : this->container())
|
for (const ITimestampBased &obj : this->container())
|
||||||
{
|
{
|
||||||
@@ -257,7 +258,7 @@ namespace BlackMisc
|
|||||||
template<class OBJ, class CONTAINER>
|
template<class OBJ, class CONTAINER>
|
||||||
bool ITimestampObjectList<OBJ, CONTAINER>::isSortedLatestFirst() const
|
bool ITimestampObjectList<OBJ, CONTAINER>::isSortedLatestFirst() const
|
||||||
{
|
{
|
||||||
if (this->container().isEmpty()) { return true; }
|
if (this->container().size() < 2) { return true; }
|
||||||
qint64 min = std::numeric_limits <qint64>::max();
|
qint64 min = std::numeric_limits <qint64>::max();
|
||||||
for (const ITimestampBased &obj : this->container())
|
for (const ITimestampBased &obj : this->container())
|
||||||
{
|
{
|
||||||
@@ -282,6 +283,16 @@ namespace BlackMisc
|
|||||||
this->container().sort(Predicates::MemberLess(&OBJ::getAdjustedMSecsSinceEpoch));
|
this->container().sort(Predicates::MemberLess(&OBJ::getAdjustedMSecsSinceEpoch));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class OBJ, class CONTAINER>
|
||||||
|
bool ITimestampWithOffsetObjectList<OBJ, CONTAINER>::containsZeroOrNegativeOffsetTime() const
|
||||||
|
{
|
||||||
|
for (const ITimestampWithOffsetBased &obj : this->container())
|
||||||
|
{
|
||||||
|
if (obj.getTimeOffsetMs() <= 0) { return true; }
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
template<class OBJ, class CONTAINER>
|
template<class OBJ, class CONTAINER>
|
||||||
ITimestampWithOffsetObjectList<OBJ, CONTAINER>::ITimestampWithOffsetObjectList() : ITimestampObjectList<OBJ, CONTAINER>()
|
ITimestampWithOffsetObjectList<OBJ, CONTAINER>::ITimestampWithOffsetObjectList() : ITimestampObjectList<OBJ, CONTAINER>()
|
||||||
{
|
{
|
||||||
@@ -297,17 +308,41 @@ namespace BlackMisc
|
|||||||
{
|
{
|
||||||
c.truncate(maxElements - 1);
|
c.truncate(maxElements - 1);
|
||||||
}
|
}
|
||||||
if (!c.isEmpty() && value.isOlderThanAdjusted(c.front()))
|
const bool needSort = !c.isEmpty() && value.isOlderThanAdjusted(c.front());
|
||||||
|
c.push_front(value);
|
||||||
|
if (needSort)
|
||||||
{
|
{
|
||||||
ITimestampWithOffsetObjectList::sortAdjustedLatestFirst();
|
ITimestampWithOffsetObjectList::sortAdjustedLatestFirst();
|
||||||
}
|
}
|
||||||
c.push_front(value);
|
}
|
||||||
|
|
||||||
|
template<class OBJ, class CONTAINER>
|
||||||
|
void ITimestampWithOffsetObjectList<OBJ, CONTAINER>::push_frontKeepLatestFirstAdjustOffset(const OBJ &value, int maxElements)
|
||||||
|
{
|
||||||
|
ITimestampObjectList<OBJ, CONTAINER>::push_frontKeepLatestFirst(value, maxElements);
|
||||||
|
|
||||||
|
// now sorted by timestamp
|
||||||
|
// this reflects normally the incoming order
|
||||||
|
CONTAINER &c = this->container();
|
||||||
|
if (c.size() < 2) { return; }
|
||||||
|
const ITimestampWithOffsetBased &front = c.front();
|
||||||
|
ITimestampWithOffsetBased &second = c[1];
|
||||||
|
if (!front.isOlderThanAdjusted(second)) { return; }
|
||||||
|
const qint64 maxOs = front.getAdjustedMSecsSinceEpoch() - second.getMSecsSinceEpoch();
|
||||||
|
const qint64 avgOs = (maxOs + qMax(front.getTimeOffsetMs(), maxOs)) / 2;
|
||||||
|
second.setTimeOffsetMs(avgOs);
|
||||||
|
|
||||||
|
// ts
|
||||||
|
// 8: os 2 adj 10
|
||||||
|
// 6: os 2 adj 8
|
||||||
|
// 5: os 5 adj 10 => max os 3
|
||||||
|
// 0: os 5 adj 5
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class OBJ, class CONTAINER>
|
template<class OBJ, class CONTAINER>
|
||||||
bool ITimestampWithOffsetObjectList<OBJ, CONTAINER>::isSortedAdjustedLatestLast() const
|
bool ITimestampWithOffsetObjectList<OBJ, CONTAINER>::isSortedAdjustedLatestLast() const
|
||||||
{
|
{
|
||||||
if (this->container().isEmpty()) { return true; }
|
if (this->container().size() < 2) { return true; }
|
||||||
qint64 max = -1;
|
qint64 max = -1;
|
||||||
for (const ITimestampWithOffsetBased &obj : this->container())
|
for (const ITimestampWithOffsetBased &obj : this->container())
|
||||||
{
|
{
|
||||||
@@ -321,14 +356,13 @@ namespace BlackMisc
|
|||||||
template<class OBJ, class CONTAINER>
|
template<class OBJ, class CONTAINER>
|
||||||
bool ITimestampWithOffsetObjectList<OBJ, CONTAINER>::isSortedAdjustedLatestFirst() const
|
bool ITimestampWithOffsetObjectList<OBJ, CONTAINER>::isSortedAdjustedLatestFirst() const
|
||||||
{
|
{
|
||||||
if (this->container().isEmpty()) { return true; }
|
if (this->container().size() < 2) { return true; }
|
||||||
qint64 min = std::numeric_limits <qint64>::max();
|
qint64 min = std::numeric_limits <qint64>::max();
|
||||||
for (const ITimestampWithOffsetBased &obj : this->container())
|
for (const ITimestampWithOffsetBased &obj : this->container())
|
||||||
{
|
{
|
||||||
if (!obj.hasValidTimestamp()) { return false; }
|
if (!obj.hasValidTimestamp()) { return false; }
|
||||||
if (obj.getAdjustedMSecsSinceEpoch() > min) { return false; }
|
if (obj.getAdjustedMSecsSinceEpoch() > min) { return false; }
|
||||||
min = obj.getAdjustedMSecsSinceEpoch();
|
min = obj.getAdjustedMSecsSinceEpoch();
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,9 +125,16 @@ namespace BlackMisc
|
|||||||
//! Sort by adjusted timestamp
|
//! Sort by adjusted timestamp
|
||||||
void sortAdjustedOldestFirst();
|
void sortAdjustedOldestFirst();
|
||||||
|
|
||||||
|
//! Any negative or zero offset time?
|
||||||
|
bool containsZeroOrNegativeOffsetTime() const;
|
||||||
|
|
||||||
//! Insert as first element by keeping maxElements and the latest first
|
//! Insert as first element by keeping maxElements and the latest first
|
||||||
void push_frontKeepLatestAdjustedFirst(const OBJ &value, int maxElements = -1);
|
void push_frontKeepLatestAdjustedFirst(const OBJ &value, int maxElements = -1);
|
||||||
|
|
||||||
|
//! Insert as first element by keeping maxElements and the latest first
|
||||||
|
//! \remark adjust offset so adjusted values are sorted
|
||||||
|
void push_frontKeepLatestFirstAdjustOffset(const OBJ &value, int maxElements = -1);
|
||||||
|
|
||||||
//! Is completely sorted: latest last
|
//! Is completely sorted: latest last
|
||||||
//! \remark all object must have a valid timestamp
|
//! \remark all object must have a valid timestamp
|
||||||
bool isSortedAdjustedLatestLast() const;
|
bool isSortedAdjustedLatestLast() const;
|
||||||
|
|||||||
Reference in New Issue
Block a user