mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-03-22 14:55:36 +08:00
Ref T275, Ref T280 hint for timestamp based list if they are already sorted
This commit is contained in:
@@ -219,7 +219,8 @@ namespace BlackMisc
|
||||
else
|
||||
{
|
||||
situationList.front().transferGroundElevation(situationCorrected); // transfer last situation if possible
|
||||
situationList.push_frontKeepLatestFirstAdjustOffset(situationCorrected, IRemoteAircraftProvider::MaxSituationsPerCallsign);
|
||||
situationList.push_frontKeepLatestFirstAdjustOffset(situationCorrected, true, IRemoteAircraftProvider::MaxSituationsPerCallsign);
|
||||
situationList.setAdjustedSortHint(CAircraftSituationList::AdjustedTimestampLatestFirst);
|
||||
|
||||
// unify all inbound ground information
|
||||
if (situation.hasInboundGroundDetails())
|
||||
@@ -252,7 +253,8 @@ namespace BlackMisc
|
||||
m_partsAdded++;
|
||||
m_partsLastModified[callsign] = ts;
|
||||
CAircraftPartsList &partsList = m_partsByCallsign[callsign];
|
||||
partsList.push_frontKeepLatestFirstAdjustOffset(parts, IRemoteAircraftProvider::MaxPartsPerCallsign);
|
||||
partsList.push_frontKeepLatestFirstAdjustOffset(parts, true, IRemoteAircraftProvider::MaxPartsPerCallsign);
|
||||
partsList.setAdjustedSortHint(CAircraftPartsList::AdjustedTimestampLatestFirst);
|
||||
|
||||
// remove outdated parts (but never remove the most recent one)
|
||||
if (removeOutdated) { IRemoteAircraftProvider::removeOutdatedParts(partsList); }
|
||||
|
||||
@@ -253,14 +253,21 @@ namespace BlackMisc
|
||||
template <class OBJ, class CONTAINER>
|
||||
void ITimestampObjectList<OBJ, CONTAINER>::sortOldestFirst()
|
||||
{
|
||||
this->container().sort(BlackMisc::Predicates::MemberLess(&OBJ::getMSecsSinceEpoch));
|
||||
this->container().sort(Predicates::MemberLess(&OBJ::getMSecsSinceEpoch));
|
||||
}
|
||||
|
||||
template<class OBJ, class CONTAINER>
|
||||
void ITimestampObjectList<OBJ, CONTAINER>::push_frontKeepLatestFirst(const OBJ &value, int maxElements)
|
||||
void ITimestampObjectList<OBJ, CONTAINER>::push_frontKeepLatestFirst(const OBJ &value, bool replaceSameTimestamp, int maxElements)
|
||||
{
|
||||
Q_ASSERT_X(maxElements < 0 || maxElements > 1, Q_FUNC_INFO, "Max.value wrong range");
|
||||
CONTAINER &c = this->container();
|
||||
if (replaceSameTimestamp && !c.isEmpty() && c[0].getMSecsSinceEpoch() == value.getMSecsSinceEpoch())
|
||||
{
|
||||
c[0] = value;
|
||||
if (maxElements > 0) { c.truncate(maxElements); }
|
||||
return;
|
||||
}
|
||||
|
||||
if (maxElements > 0) { c.truncate(maxElements - 1); }
|
||||
const bool needSort = !c.isEmpty() && value.isOlderThan(c.front());
|
||||
c.push_front(value);
|
||||
@@ -270,6 +277,21 @@ namespace BlackMisc
|
||||
}
|
||||
}
|
||||
|
||||
template<class OBJ, class CONTAINER>
|
||||
int ITimestampObjectList<OBJ, CONTAINER>::replaceIfSameTimestamp(const OBJ &newObject)
|
||||
{
|
||||
int c = 0;
|
||||
for (OBJ &obj : this->container())
|
||||
{
|
||||
if (obj.getMSecsSinceEpoch() == newObject.getMSecsSinceEpoch())
|
||||
{
|
||||
obj = newObject;
|
||||
c++;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
template<class OBJ, class CONTAINER>
|
||||
bool ITimestampObjectList<OBJ, CONTAINER>::isSortedLatestLast() const
|
||||
{
|
||||
@@ -374,10 +396,17 @@ namespace BlackMisc
|
||||
}
|
||||
|
||||
template<class OBJ, class CONTAINER>
|
||||
void ITimestampWithOffsetObjectList<OBJ, CONTAINER>::push_frontKeepLatestAdjustedFirst(const OBJ &value, int maxElements)
|
||||
void ITimestampWithOffsetObjectList<OBJ, CONTAINER>::push_frontKeepLatestAdjustedFirst(const OBJ &value, bool replaceSameTimestamp, int maxElements)
|
||||
{
|
||||
Q_ASSERT_X(maxElements < 0 || maxElements > 1, Q_FUNC_INFO, "Max.value wrong range");
|
||||
CONTAINER &c = this->container();
|
||||
if (replaceSameTimestamp && !c.isEmpty() && c[0].getMSecsSinceEpoch() == value.getMSecsSinceEpoch())
|
||||
{
|
||||
c[0] = value;
|
||||
if (maxElements > 0) { c.truncate(maxElements); }
|
||||
return;
|
||||
}
|
||||
|
||||
if (maxElements > 0) { c.truncate(maxElements - 1); }
|
||||
const bool needSort = !c.isEmpty() && value.isOlderThanAdjusted(c.front());
|
||||
c.push_front(value);
|
||||
@@ -388,9 +417,9 @@ namespace BlackMisc
|
||||
}
|
||||
|
||||
template<class OBJ, class CONTAINER>
|
||||
void ITimestampWithOffsetObjectList<OBJ, CONTAINER>::push_frontKeepLatestFirstAdjustOffset(const OBJ &value, int maxElements)
|
||||
void ITimestampWithOffsetObjectList<OBJ, CONTAINER>::push_frontKeepLatestFirstAdjustOffset(const OBJ &value, bool replaceSameTimestamp, int maxElements)
|
||||
{
|
||||
ITimestampObjectList<OBJ, CONTAINER>::push_frontKeepLatestFirst(value, maxElements);
|
||||
ITimestampWithOffsetObjectList<OBJ, CONTAINER>::push_frontKeepLatestAdjustedFirst(value, replaceSameTimestamp, maxElements);
|
||||
|
||||
// now sorted by timestamp
|
||||
// this reflects normally the incoming order
|
||||
@@ -432,6 +461,7 @@ namespace BlackMisc
|
||||
copy.addMsecs(os * i);
|
||||
this->container().push_back(copy);
|
||||
}
|
||||
this->setAdjustedSortHint(ITimestampWithOffsetObjectList::AdjustedTimestampLatestFirst);
|
||||
}
|
||||
|
||||
template<class OBJ, class CONTAINER>
|
||||
@@ -513,6 +543,10 @@ namespace BlackMisc
|
||||
OBJ ITimestampWithOffsetObjectList<OBJ, CONTAINER>::latestAdjustedObject() const
|
||||
{
|
||||
if (this->container().isEmpty()) { return OBJ(); }
|
||||
if (m_tsAdjustedSortHint == AdjustedTimestampLatestFirst)
|
||||
{
|
||||
return this->container().front();
|
||||
}
|
||||
const auto latest = std::max_element(this->container().begin(), this->container().end(), [](const OBJ & a, const OBJ & b) { return a.getAdjustedMSecsSinceEpoch() < b.getAdjustedMSecsSinceEpoch(); });
|
||||
return *latest;
|
||||
}
|
||||
@@ -521,6 +555,10 @@ namespace BlackMisc
|
||||
OBJ ITimestampWithOffsetObjectList<OBJ, CONTAINER>::oldestAdjustedObject() const
|
||||
{
|
||||
if (this->container().isEmpty()) { return OBJ(); }
|
||||
if (m_tsAdjustedSortHint == AdjustedTimestampLatestFirst)
|
||||
{
|
||||
return this->container().back();
|
||||
}
|
||||
const auto oldest = std::min_element(this->container().begin(), this->container().end(), [](const OBJ & a, const OBJ & b) { return a.getAdjustedMSecsSinceEpoch() < b.getAdjustedMSecsSinceEpoch(); });
|
||||
return *oldest;
|
||||
}
|
||||
@@ -535,7 +573,8 @@ namespace BlackMisc
|
||||
template <class OBJ, class CONTAINER>
|
||||
qint64 ITimestampWithOffsetObjectList<OBJ, CONTAINER>::latestAdjustedTimestampMsecsSinceEpoch() const
|
||||
{
|
||||
const QDateTime dt(this->latestTimestamp());
|
||||
if (this->container().isEmpty()) { return -1; }
|
||||
const QDateTime dt(this->latestAdjustedTimestamp());
|
||||
return dt.isValid() ? dt.toMSecsSinceEpoch() : -1;
|
||||
}
|
||||
|
||||
@@ -549,6 +588,7 @@ namespace BlackMisc
|
||||
template <class OBJ, class CONTAINER>
|
||||
qint64 ITimestampWithOffsetObjectList<OBJ, CONTAINER>::oldestAdjustedTimestampMsecsSinceEpoch() const
|
||||
{
|
||||
if (this->container().isEmpty()) { return -1; }
|
||||
const QDateTime dt(oldestAdjustedTimestamp());
|
||||
return dt.isValid() ? dt.toMSecsSinceEpoch() : -1;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,13 @@ namespace BlackMisc
|
||||
template<class OBJ, class CONTAINER> class ITimestampObjectList
|
||||
{
|
||||
public:
|
||||
//! Hint if the list is sorted
|
||||
enum HintTimestampSort
|
||||
{
|
||||
NoTimestampSortHint,
|
||||
TimestampLatestFirst
|
||||
};
|
||||
|
||||
//! List of objects before dateTime (older)
|
||||
CONTAINER findBefore(const QDateTime &dateTime) const;
|
||||
|
||||
@@ -102,7 +109,10 @@ namespace BlackMisc
|
||||
void sortOldestFirst();
|
||||
|
||||
//! Insert as first element by keeping maxElements and the latest first
|
||||
void push_frontKeepLatestFirst(const OBJ &value, int maxElements = -1);
|
||||
void push_frontKeepLatestFirst(const OBJ &value, bool replaceSameTimestamp = true, int maxElements = -1);
|
||||
|
||||
//! Replace if an object has the same timestamp
|
||||
int replaceIfSameTimestamp(const OBJ &newObject);
|
||||
|
||||
//! Is completely sorted: latest last
|
||||
//! \remark all object must have a valid timestamp
|
||||
@@ -115,6 +125,9 @@ namespace BlackMisc
|
||||
//! Adds a time to all values
|
||||
void addMsecs(qint64 msToAdd);
|
||||
|
||||
//! Set the hint
|
||||
void setSortHint(HintTimestampSort hint) { m_tsSortHint = hint; }
|
||||
|
||||
protected:
|
||||
//! Constructor
|
||||
ITimestampObjectList();
|
||||
@@ -124,6 +137,8 @@ namespace BlackMisc
|
||||
|
||||
//! Container
|
||||
CONTAINER &container();
|
||||
|
||||
HintTimestampSort m_tsSortHint = NoTimestampSortHint; //!< sort hint
|
||||
};
|
||||
|
||||
//! List of objects with timestamp and offset.
|
||||
@@ -131,6 +146,13 @@ namespace BlackMisc
|
||||
template<class OBJ, class CONTAINER> class ITimestampWithOffsetObjectList : public ITimestampObjectList<OBJ, CONTAINER>
|
||||
{
|
||||
public:
|
||||
//! Hint if the list is sorted
|
||||
enum HintAdjustedTimestampSort
|
||||
{
|
||||
NoAdjustedTimestampSortHint,
|
||||
AdjustedTimestampLatestFirst
|
||||
};
|
||||
|
||||
//! Sort by adjusted timestamp
|
||||
void sortAdjustedLatestFirst();
|
||||
|
||||
@@ -153,11 +175,11 @@ namespace BlackMisc
|
||||
void addMsecsToOffset(qint64 msToAdd);
|
||||
|
||||
//! 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, bool replaceSameTimestamp = true, int maxElements = -1);
|
||||
|
||||
//! Insert as first element by keeping maxElements and the latest first
|
||||
//! \remark adjust offset to average offset of two adjacent elements so adjusted values are sorted
|
||||
void push_frontKeepLatestFirstAdjustOffset(const OBJ &value, int maxElements = -1);
|
||||
void push_frontKeepLatestFirstAdjustOffset(const OBJ &value, bool replaceSameTimestamp = true, int maxElements = -1);
|
||||
|
||||
//! Prefill with elements
|
||||
void prefillLatestAdjustedFirst(const OBJ &value, int elements, qint64 deltaTimeMs = -1);
|
||||
@@ -203,9 +225,14 @@ namespace BlackMisc
|
||||
//! Oldest adjusted timestamp
|
||||
qint64 oldestAdjustedTimestampMsecsSinceEpoch() const;
|
||||
|
||||
//! Set the hint
|
||||
void setAdjustedSortHint(HintAdjustedTimestampSort hint) { m_tsAdjustedSortHint = hint; }
|
||||
|
||||
protected:
|
||||
//! Constructor
|
||||
ITimestampWithOffsetObjectList();
|
||||
|
||||
HintAdjustedTimestampSort m_tsAdjustedSortHint = NoAdjustedTimestampSortHint; //!< sort hint
|
||||
};
|
||||
|
||||
//! \cond PRIVATE
|
||||
|
||||
@@ -20,7 +20,9 @@
|
||||
#include "blackmisc/math/mathutils.h"
|
||||
|
||||
#include <QTest>
|
||||
#include <QTimer>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
|
||||
using namespace BlackMisc::Aviation;
|
||||
using namespace BlackMisc::PhysicalQuantities;
|
||||
@@ -184,6 +186,36 @@ namespace BlackMiscTest
|
||||
QVERIFY2(corAlt == (ep.getAltitude() + cg), "Expect correction by CG");
|
||||
}
|
||||
|
||||
void CTestAircraftSituation::sortHint()
|
||||
{
|
||||
CAircraftSituationList situations = testSituations();
|
||||
situations.sortAdjustedLatestFirst();
|
||||
|
||||
constexpr int Max = 500000;
|
||||
QTime time;
|
||||
time.start();
|
||||
for (int i = 0; i < Max; ++i)
|
||||
{
|
||||
CAircraftSituation s1 = situations.oldestAdjustedObject();
|
||||
CAircraftSituation s2 = situations.latestAdjustedObject();
|
||||
QVERIFY(s1.getAdjustedMSecsSinceEpoch() < s2.getAdjustedMSecsSinceEpoch());
|
||||
}
|
||||
const int noHint = time.elapsed();
|
||||
situations.setAdjustedSortHint(CAircraftSituationList::AdjustedTimestampLatestFirst);
|
||||
|
||||
time.start();
|
||||
for (int i = 0; i < Max; ++i)
|
||||
{
|
||||
CAircraftSituation s1 = situations.oldestAdjustedObject();
|
||||
CAircraftSituation s2 = situations.latestAdjustedObject();
|
||||
QVERIFY(s1.getAdjustedMSecsSinceEpoch() < s2.getAdjustedMSecsSinceEpoch());
|
||||
}
|
||||
const int hint = time.elapsed();
|
||||
qDebug() << "Access without hint" << noHint << "ms";
|
||||
qDebug() << "Access with hint" << hint << "ms";
|
||||
QVERIFY2(hint < noHint, "Expected hinted sort being faster");
|
||||
}
|
||||
|
||||
CAircraftSituationList CTestAircraftSituation::testSituations()
|
||||
{
|
||||
// "Kugaaruk Airport","Pelly Bay","Canada","YBB","CYBB",68.534401,-89.808098,56,-7,"A","America/Edmonton","airport","OurAirports"
|
||||
|
||||
@@ -55,6 +55,9 @@ namespace BlackMiscTest
|
||||
//! Altitude correction
|
||||
void altitudeCorrection();
|
||||
|
||||
//! Using sort hint
|
||||
void sortHint();
|
||||
|
||||
private:
|
||||
//! Test situations (ascending)
|
||||
static BlackMisc::Aviation::CAircraftSituationList testSituations();
|
||||
|
||||
@@ -329,7 +329,7 @@ namespace BlackMiscTest
|
||||
}
|
||||
|
||||
ts += dt;
|
||||
situations.push_frontKeepLatestFirstAdjustOffset(s, max);
|
||||
situations.push_frontKeepLatestFirstAdjustOffset(s, true, max);
|
||||
|
||||
QVERIFY2(situations.size() <= max, "Wrong size");
|
||||
QVERIFY2(situations.isSortedAdjustedLatestFirstWithoutNullPositions(), "Wrong sort order");
|
||||
|
||||
Reference in New Issue
Block a user