@@ -0,0 +1,106 | |||||
|
1 | #include <QObject> | |||
|
2 | #include <QtTest> | |||
|
3 | #include <QUuid> | |||
|
4 | #include <limits> | |||
|
5 | ||||
|
6 | ||||
|
7 | #include <Data/DateTimeRange.h> | |||
|
8 | #include <Common/Numeric.h> | |||
|
9 | ||||
|
10 | Q_DECLARE_METATYPE(Seconds<double>); | |||
|
11 | ||||
|
12 | DateTimeRange computeZoom(QDateTime start, QDateTime stop, double zoom) | |||
|
13 | { | |||
|
14 | double start_epoch = start.toMSecsSinceEpoch(); | |||
|
15 | double stop_epoch = stop.toMSecsSinceEpoch(); | |||
|
16 | auto delta = stop_epoch - start_epoch; | |||
|
17 | auto dt_ms = (zoom-1.)*(double(delta))/2.; | |||
|
18 | return DateTimeRange{(start_epoch - dt_ms)/1000., (stop_epoch + dt_ms)/1000.}; | |||
|
19 | } | |||
|
20 | ||||
|
21 | class TestDateTimeRange: public QObject { | |||
|
22 | Q_OBJECT | |||
|
23 | ||||
|
24 | private slots: | |||
|
25 | void testRangeDelta_data() | |||
|
26 | { | |||
|
27 | QTest::addColumn<QDateTime>("tstart"); | |||
|
28 | QTest::addColumn<QDateTime>("tend"); | |||
|
29 | QTest::addColumn<double>("expected"); | |||
|
30 | auto now = QDateTime::currentDateTime(); | |||
|
31 | auto yesterday = QDateTime::currentDateTime().addDays(-1); | |||
|
32 | QTest::newRow("No delta") << now << now << 0.; | |||
|
33 | QTest::newRow("One day delta") << yesterday << now << 60.*60.*24.; | |||
|
34 | QTest::newRow("Minus one day delta") << now << yesterday << -60.*60.*24.; | |||
|
35 | } | |||
|
36 | ||||
|
37 | void testRangeDelta() | |||
|
38 | { | |||
|
39 | QFETCH(QDateTime,tstart); | |||
|
40 | QFETCH(QDateTime,tend); | |||
|
41 | QFETCH(double,expected); | |||
|
42 | auto range = DateTimeRange::fromDateTime(tstart, tend); | |||
|
43 | double delta = range.delta(); | |||
|
44 | // Since it is built from QDateTime don't expect better resolution | |||
|
45 | QVERIFY((delta-expected) <= 0.002); | |||
|
46 | } | |||
|
47 | ||||
|
48 | void testRangeShift_data() | |||
|
49 | { | |||
|
50 | QTest::addColumn<DateTimeRange>("initial"); | |||
|
51 | QTest::addColumn<Seconds<double>>("shift"); | |||
|
52 | QTest::addColumn<DateTimeRange>("expected"); | |||
|
53 | auto now = QDateTime::currentDateTime(); | |||
|
54 | auto yestd = QDateTime::currentDateTime().addDays(-1); | |||
|
55 | auto range = DateTimeRange::fromDateTime(yestd, now); | |||
|
56 | QTest::newRow("No shift") << range << Seconds<double>{0.} << range; | |||
|
57 | ||||
|
58 | QTest::newRow("One milisecond left") << range << Seconds<double>{-.001} << | |||
|
59 | DateTimeRange::fromDateTime(yestd.addMSecs(-1.), now.addMSecs(-1.)); | |||
|
60 | QTest::newRow("One milisecond right") << range << Seconds<double>{.001} << | |||
|
61 | DateTimeRange::fromDateTime(yestd.addMSecs(1.), now.addMSecs(1.)); | |||
|
62 | QTest::newRow("One second left") << range << Seconds<double>{-1.} << | |||
|
63 | DateTimeRange::fromDateTime(yestd.addSecs(-1.), now.addSecs(-1.)); | |||
|
64 | QTest::newRow("One second right") << range << Seconds<double>{1.} << | |||
|
65 | DateTimeRange::fromDateTime(yestd.addSecs(1.), now.addSecs(1.)); | |||
|
66 | QTest::newRow("One year left") << range << Seconds<double>{-365.*24.*60.*60.} << | |||
|
67 | DateTimeRange::fromDateTime(yestd.addYears(-1.), now.addYears(-1.)); | |||
|
68 | QTest::newRow("One year right") << range << Seconds<double>{365.*24.*60.*60.} << | |||
|
69 | DateTimeRange::fromDateTime(yestd.addYears(1.), now.addYears(1.)); | |||
|
70 | } | |||
|
71 | void testRangeShift() | |||
|
72 | { | |||
|
73 | QFETCH(DateTimeRange,initial); | |||
|
74 | QFETCH(Seconds<double>,shift); | |||
|
75 | QFETCH(DateTimeRange,expected); | |||
|
76 | QCOMPARE(initial+shift, expected); | |||
|
77 | } | |||
|
78 | ||||
|
79 | void testRangeZoom_data() | |||
|
80 | { | |||
|
81 | QTest::addColumn<DateTimeRange>("initial"); | |||
|
82 | QTest::addColumn<double>("zoom"); | |||
|
83 | QTest::addColumn<DateTimeRange>("expected"); | |||
|
84 | auto now = QDateTime::currentDateTime(); | |||
|
85 | auto yestd = QDateTime::currentDateTime().addDays(-1); | |||
|
86 | auto range = DateTimeRange::fromDateTime(yestd, now); | |||
|
87 | QTest::newRow("No zoom") << range << 1. << range; | |||
|
88 | ||||
|
89 | QTest::newRow("Zoom IN 0.001") << range << 1.001 << | |||
|
90 | computeZoom(yestd, now, 1.001); | |||
|
91 | QTest::newRow("Zoom OUT 0.001") << range << 0.999 << | |||
|
92 | computeZoom(yestd, now, 0.999); | |||
|
93 | } | |||
|
94 | void testRangeZoom() | |||
|
95 | { | |||
|
96 | QFETCH(DateTimeRange,initial); | |||
|
97 | QFETCH(double,zoom); | |||
|
98 | QFETCH(DateTimeRange,expected); | |||
|
99 | QCOMPARE(initial*zoom, expected); | |||
|
100 | } | |||
|
101 | ||||
|
102 | }; | |||
|
103 | QTEST_MAIN(TestDateTimeRange) | |||
|
104 | ||||
|
105 | ||||
|
106 | #include "TestDateTimeRange.moc" |
@@ -1,8 +1,12 | |||||
|
1 | #ifndef NUMERIC_H | |||
|
2 | #define NUMERIC_H | |||
1 | #include <cmath> |
|
3 | #include <cmath> | |
2 | #include <limits> |
|
4 | #include <limits> | |
3 | #include <type_traits> |
|
5 | #include <type_traits> | |
4 | #include <algorithm> |
|
6 | #include <algorithm> | |
5 |
|
7 | |||
|
8 | namespace SciQLop::numeric { | |||
|
9 | ||||
6 | /* |
|
10 | /* | |
7 | taken from here https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon |
|
11 | taken from here https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon | |
8 | */ |
|
12 | */ | |
@@ -16,3 +20,7 typename std::enable_if<!std::numeric_limits<T>::is_integer, bool>::type | |||||
16 | // unless the result is subnormal |
|
20 | // unless the result is subnormal | |
17 | || std::abs(x-y) < std::numeric_limits<T>::min(); |
|
21 | || std::abs(x-y) < std::numeric_limits<T>::min(); | |
18 | } |
|
22 | } | |
|
23 | ||||
|
24 | } | |||
|
25 | ||||
|
26 | #endif |
@@ -1,15 +1,15 | |||||
1 | #ifndef SCIQLOP_SQPRANGE_H |
|
1 | #ifndef SCIQLOP_SQPRANGE_H | |
2 | #define SCIQLOP_SQPRANGE_H |
|
2 | #define SCIQLOP_SQPRANGE_H | |
3 |
|
3 | |||
|
4 | #include <cmath> | |||
4 | #include <QObject> |
|
5 | #include <QObject> | |
5 |
|
6 | |||
6 | #include <QDebug> |
|
7 | #include <QDebug> | |
7 |
|
8 | |||
|
9 | #include <opaque/numeric_typedef.hpp> | |||
8 | #include <Common/DateUtils.h> |
|
10 | #include <Common/DateUtils.h> | |
9 | #include <Common/MetaTypes.h> |
|
11 | #include <Common/MetaTypes.h> | |
10 |
#include < |
|
12 | #include <Common/Numeric.h> | |
11 |
|
||||
12 | #include <cmath> |
|
|||
13 |
|
13 | |||
14 |
|
14 | |||
15 | template <typename T> |
|
15 | template <typename T> | |
@@ -22,6 +22,7 struct Seconds : opaque::numeric_typedef<T, Seconds<T>> , | |||||
22 | { |
|
22 | { | |
23 | using base = opaque::numeric_typedef<T, Seconds<T>>; |
|
23 | using base = opaque::numeric_typedef<T, Seconds<T>>; | |
24 | using base::base; |
|
24 | using base::base; | |
|
25 | operator T () const {return this->value;} | |||
25 | }; |
|
26 | }; | |
26 |
|
27 | |||
27 | /** |
|
28 | /** | |
@@ -36,6 +37,12 struct DateTimeRange { | |||||
36 | DateUtils::secondsSinceEpoch(QDateTime{endDate, endTime, Qt::UTC})}; |
|
37 | DateUtils::secondsSinceEpoch(QDateTime{endDate, endTime, Qt::UTC})}; | |
37 | } |
|
38 | } | |
38 |
|
39 | |||
|
40 | static DateTimeRange fromDateTime(const QDateTime &start, const QDateTime &end) | |||
|
41 | { | |||
|
42 | return {DateUtils::secondsSinceEpoch(start), | |||
|
43 | DateUtils::secondsSinceEpoch(end)}; | |||
|
44 | } | |||
|
45 | ||||
39 | /// Start time (UTC) |
|
46 | /// Start time (UTC) | |
40 | double m_TStart; |
|
47 | double m_TStart; | |
41 | /// End time (UTC) |
|
48 | /// End time (UTC) | |
@@ -55,12 +62,10 struct DateTimeRange { | |||||
55 |
|
62 | |||
56 | bool operator==(const DateTimeRange &other) const |
|
63 | bool operator==(const DateTimeRange &other) const | |
57 | { |
|
64 | { | |
58 | auto equals = [](const auto &v1, const auto &v2) { |
|
65 | return SciQLop::numeric::almost_equal(m_TStart, other.m_TStart, 1.) && | |
59 | return (std::isnan(v1) && std::isnan(v2)) || v1 == v2; |
|
66 | SciQLop::numeric::almost_equal(m_TEnd, other.m_TEnd, 1.); | |
60 | }; |
|
|||
61 |
|
||||
62 | return equals(m_TStart, other.m_TStart) && equals(m_TEnd, other.m_TEnd); |
|
|||
63 | } |
|
67 | } | |
|
68 | ||||
64 | bool operator!=(const DateTimeRange &other) const { return !(*this == other); } |
|
69 | bool operator!=(const DateTimeRange &other) const { return !(*this == other); } | |
65 |
|
70 | |||
66 | void grow(double factor) |
|
71 | void grow(double factor) |
@@ -659,7 +659,7 bool VariableController::hasPendingDownloads() | |||||
659 |
|
659 | |||
660 | AcquisitionZoomType VariableController::getZoomType(const DateTimeRange &range, const DateTimeRange &oldRange) |
|
660 | AcquisitionZoomType VariableController::getZoomType(const DateTimeRange &range, const DateTimeRange &oldRange) | |
661 | { |
|
661 | { | |
662 |
if (almost_equal |
|
662 | if (SciQLop::numeric::almost_equal<double>(range.delta(), oldRange.delta(), 1)) // same delta -> must be a pan or nothing | |
663 | { |
|
663 | { | |
664 | if(range.m_TStart > oldRange.m_TStart) |
|
664 | if(range.m_TStart > oldRange.m_TStart) | |
665 | return AcquisitionZoomType::PanRight; |
|
665 | return AcquisitionZoomType::PanRight; |
@@ -1,4 +1,5 | |||||
1 | #include "Variable/VariableController2.h" |
|
1 | #include "Variable/VariableController2.h" | |
|
2 | #include "Variable/VariableSynchronizationGroup2.h" | |||
2 | #include <Common/containers.h> |
|
3 | #include <Common/containers.h> | |
3 | #include <Common/debug.h> |
|
4 | #include <Common/debug.h> | |
4 | #include <Data/DataProviderParameters.h> |
|
5 | #include <Data/DataProviderParameters.h> | |
@@ -7,6 +8,7 class VariableController2::VariableController2Private | |||||
7 | { |
|
8 | { | |
8 | std::set<std::shared_ptr<Variable>> _variables; |
|
9 | std::set<std::shared_ptr<Variable>> _variables; | |
9 | QMap<QUuid,std::shared_ptr<IDataProvider>> _providers; |
|
10 | QMap<QUuid,std::shared_ptr<IDataProvider>> _providers; | |
|
11 | QMap<QUuid,std::shared_ptr<VariableSynchronizationGroup2>> _synchronizationGroups; | |||
10 | public: |
|
12 | public: | |
11 | VariableController2Private(QObject* parent=Q_NULLPTR) |
|
13 | VariableController2Private(QObject* parent=Q_NULLPTR) | |
12 | { |
|
14 | { | |
@@ -20,6 +22,7 public: | |||||
20 | auto newVar = std::make_shared<Variable>(name,metadata); |
|
22 | auto newVar = std::make_shared<Variable>(name,metadata); | |
21 | this->_variables.insert(newVar); |
|
23 | this->_variables.insert(newVar); | |
22 | this->_providers[newVar->ID()] = provider; |
|
24 | this->_providers[newVar->ID()] = provider; | |
|
25 | this->_synchronizationGroups[newVar->ID()] = std::make_shared<VariableSynchronizationGroup2>(newVar->ID()); | |||
23 | return newVar; |
|
26 | return newVar; | |
24 | } |
|
27 | } | |
25 |
|
28 |
@@ -107,7 +107,7 PYBIND11_MODULE(pysciqlopcore,m){ | |||||
107 |
|
107 | |||
108 |
|
108 | |||
109 | py::class_<DateTimeRange>(m,"SqpRange") |
|
109 | py::class_<DateTimeRange>(m,"SqpRange") | |
110 | .def("fromDateTime", &DateTimeRange::fromDateTime, py::return_value_policy::move) |
|
110 | //.def("fromDateTime", &DateTimeRange::fromDateTime, py::return_value_policy::move) | |
111 | .def(py::init([](double start, double stop){return DateTimeRange{start, stop};})) |
|
111 | .def(py::init([](double start, double stop){return DateTimeRange{start, stop};})) | |
112 | .def(py::init([](system_clock::time_point start, system_clock::time_point stop) |
|
112 | .def(py::init([](system_clock::time_point start, system_clock::time_point stop) | |
113 | { |
|
113 | { |
@@ -13,6 +13,8 declare_test(TestStringUtils TestStringUtils Common/TestStringUtils.cpp "sciqlop | |||||
13 | declare_test(TestContainers TestContainers Common/TestContainers.cpp "sciqlopcore;Qt5::Test") |
|
13 | declare_test(TestContainers TestContainers Common/TestContainers.cpp "sciqlopcore;Qt5::Test") | |
14 | declare_test(TestSyncGroup TestSyncGroup Variable/TestSyncGroup.cpp "sciqlopcore;Qt5::Test") |
|
14 | declare_test(TestSyncGroup TestSyncGroup Variable/TestSyncGroup.cpp "sciqlopcore;Qt5::Test") | |
15 |
|
15 | |||
|
16 | declare_test(TestDateTimeRange TestDateTimeRange Data/TestDateTimeRange.cpp "sciqlopcore;Qt5::Test") | |||
|
17 | ||||
16 |
|
18 | |||
17 | declare_test(TestDataSeriesUtils TestDataSeriesUtils Data/TestDataSeriesUtils.cpp "sciqlopcore;Qt5::Test") |
|
19 | declare_test(TestDataSeriesUtils TestDataSeriesUtils Data/TestDataSeriesUtils.cpp "sciqlopcore;Qt5::Test") | |
18 | declare_test(TestOptionalAxis TestOptionalAxis Data/TestOptionalAxis.cpp "sciqlopcore;Qt5::Test") |
|
20 | declare_test(TestOptionalAxis TestOptionalAxis Data/TestOptionalAxis.cpp "sciqlopcore;Qt5::Test") |
General Comments 0
You need to be logged in to leave comments.
Login now