Ref T243, adjust offset for timestamp based objects when keeping the order

This commit is contained in:
Klaus Basan
2018-02-06 00:42:28 +01:00
parent 23cd247bd8
commit 5d155fb59c
4 changed files with 81 additions and 26 deletions

View File

@@ -238,11 +238,7 @@ namespace BlackMisc
return emptyParts;
}
// 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.isSortedAdjustedLatestFirst(), Q_FUNC_INFO, "Wrong sort order");
// Ref T243, KB 2018-02, can be removed in future, we verify parts above
// Ref T243, KB 2018-02, can be removed in future, we verify parts when we add parts
// 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 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
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>
void CInterpolator<Derived>::addAircraftParts(const CAircraftParts &parts)
{
const bool hasOffset = parts.hasOffsetTime();
const qint64 offset =
hasOffset ?
parts.getTimeOffsetMs() :
m_aircraftSituations.isEmpty() ? IRemoteAircraftProvider::DefaultOffsetTimeMs : m_aircraftSituations.front().getTimeOffsetMs();
if (!hasOffset)
{
const qint64 offset =
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())
{
// make sure we have enough parts to do start interpolating immediately without waiting for more updates
// the offsets here (addMSecs) do not really matter
CAircraftParts copy(parts);
copy.setTimeOffsetMs(offset);
copy.addMsecs(-2 * offset);
copy.addMsecs(-2 * parts.getTimeOffsetMs());
m_aircraftParts.push_frontKeepLatestFirst(copy);
copy.addMsecs(offset);
copy.addMsecs(parts.getTimeOffsetMs());
m_aircraftParts.push_frontKeepLatestFirst(copy);
}
// we add new situations at front and keep the latest values (real time) first
m_aircraftParts.push_frontKeepLatestFirst(parts, IRemoteAircraftProvider::MaxSituationsPerCallsign);
if (!hasOffset) { m_aircraftParts.front().setTimeOffsetMs(offset); }
m_aircraftParts.push_frontKeepLatestFirstAdjustOffset(parts, IRemoteAircraftProvider::MaxSituationsPerCallsign);
// force remote provider to cleanup
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>

View File

@@ -232,17 +232,18 @@ namespace BlackMisc
{
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();
}
c.push_front(value);
}
template<class OBJ, class CONTAINER>
bool ITimestampObjectList<OBJ, CONTAINER>::isSortedLatestLast() const
{
if (this->container().isEmpty()) { return true; }
if (this->container().size() < 2) { return true; }
qint64 max = -1;
for (const ITimestampBased &obj : this->container())
{
@@ -257,7 +258,7 @@ namespace BlackMisc
template<class OBJ, class CONTAINER>
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();
for (const ITimestampBased &obj : this->container())
{
@@ -282,6 +283,16 @@ namespace BlackMisc
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>
ITimestampWithOffsetObjectList<OBJ, CONTAINER>::ITimestampWithOffsetObjectList() : ITimestampObjectList<OBJ, CONTAINER>()
{
@@ -297,17 +308,41 @@ namespace BlackMisc
{
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();
}
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>
bool ITimestampWithOffsetObjectList<OBJ, CONTAINER>::isSortedAdjustedLatestLast() const
{
if (this->container().isEmpty()) { return true; }
if (this->container().size() < 2) { return true; }
qint64 max = -1;
for (const ITimestampWithOffsetBased &obj : this->container())
{
@@ -321,14 +356,13 @@ namespace BlackMisc
template<class OBJ, class CONTAINER>
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();
for (const ITimestampWithOffsetBased &obj : this->container())
{
if (!obj.hasValidTimestamp()) { return false; }
if (obj.getAdjustedMSecsSinceEpoch() > min) { return false; }
min = obj.getAdjustedMSecsSinceEpoch();
continue;
}
return true;
}

View File

@@ -125,9 +125,16 @@ namespace BlackMisc
//! Sort by adjusted timestamp
void sortAdjustedOldestFirst();
//! Any negative or zero offset time?
bool containsZeroOrNegativeOffsetTime() const;
//! Insert as first element by keeping maxElements and the latest first
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
//! \remark all object must have a valid timestamp
bool isSortedAdjustedLatestLast() const;