diff --git a/include/Common/Numeric.h b/include/Common/Numeric.h index b74e2a2..9170def 100644 --- a/include/Common/Numeric.h +++ b/include/Common/Numeric.h @@ -1,8 +1,12 @@ +#ifndef NUMERIC_H +#define NUMERIC_H #include #include #include #include +namespace SciQLop::numeric { + /* taken from here https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon */ @@ -16,3 +20,7 @@ typename std::enable_if::is_integer, bool>::type // unless the result is subnormal || std::abs(x-y) < std::numeric_limits::min(); } + +} + +#endif diff --git a/include/Data/DateTimeRange.h b/include/Data/DateTimeRange.h index ff9f528..8e6f03a 100644 --- a/include/Data/DateTimeRange.h +++ b/include/Data/DateTimeRange.h @@ -1,15 +1,15 @@ #ifndef SCIQLOP_SQPRANGE_H #define SCIQLOP_SQPRANGE_H +#include #include #include +#include #include #include -#include - -#include +#include template @@ -22,6 +22,7 @@ struct Seconds : opaque::numeric_typedef> , { using base = opaque::numeric_typedef>; using base::base; + operator T () const {return this->value;} }; /** @@ -36,6 +37,12 @@ struct DateTimeRange { DateUtils::secondsSinceEpoch(QDateTime{endDate, endTime, Qt::UTC})}; } + static DateTimeRange fromDateTime(const QDateTime &start, const QDateTime &end) + { + return {DateUtils::secondsSinceEpoch(start), + DateUtils::secondsSinceEpoch(end)}; + } + /// Start time (UTC) double m_TStart; /// End time (UTC) @@ -55,12 +62,10 @@ struct DateTimeRange { bool operator==(const DateTimeRange &other) const { - auto equals = [](const auto &v1, const auto &v2) { - return (std::isnan(v1) && std::isnan(v2)) || v1 == v2; - }; - - return equals(m_TStart, other.m_TStart) && equals(m_TEnd, other.m_TEnd); + return SciQLop::numeric::almost_equal(m_TStart, other.m_TStart, 1.) && + SciQLop::numeric::almost_equal(m_TEnd, other.m_TEnd, 1.); } + bool operator!=(const DateTimeRange &other) const { return !(*this == other); } void grow(double factor) diff --git a/src/Variable/VariableController.cpp b/src/Variable/VariableController.cpp index 2f7356f..cee7442 100644 --- a/src/Variable/VariableController.cpp +++ b/src/Variable/VariableController.cpp @@ -659,7 +659,7 @@ bool VariableController::hasPendingDownloads() AcquisitionZoomType VariableController::getZoomType(const DateTimeRange &range, const DateTimeRange &oldRange) { - if (almost_equal(static_cast(range.delta()), static_cast(oldRange.delta()), 1)) // same delta -> must be a pan or nothing + if (SciQLop::numeric::almost_equal(range.delta(), oldRange.delta(), 1)) // same delta -> must be a pan or nothing { if(range.m_TStart > oldRange.m_TStart) return AcquisitionZoomType::PanRight; diff --git a/src/Variable/VariableController2.cpp b/src/Variable/VariableController2.cpp index 10f5c8a..db13c1a 100644 --- a/src/Variable/VariableController2.cpp +++ b/src/Variable/VariableController2.cpp @@ -1,4 +1,5 @@ #include "Variable/VariableController2.h" +#include "Variable/VariableSynchronizationGroup2.h" #include #include #include @@ -7,6 +8,7 @@ class VariableController2::VariableController2Private { std::set> _variables; QMap> _providers; + QMap> _synchronizationGroups; public: VariableController2Private(QObject* parent=Q_NULLPTR) { @@ -20,6 +22,7 @@ public: auto newVar = std::make_shared(name,metadata); this->_variables.insert(newVar); this->_providers[newVar->ID()] = provider; + this->_synchronizationGroups[newVar->ID()] = std::make_shared(newVar->ID()); return newVar; } diff --git a/src/pybind11_wrappers/CoreWrappers.cpp b/src/pybind11_wrappers/CoreWrappers.cpp index 861967c..748be66 100644 --- a/src/pybind11_wrappers/CoreWrappers.cpp +++ b/src/pybind11_wrappers/CoreWrappers.cpp @@ -107,7 +107,7 @@ PYBIND11_MODULE(pysciqlopcore,m){ py::class_(m,"SqpRange") - .def("fromDateTime", &DateTimeRange::fromDateTime, py::return_value_policy::move) + //.def("fromDateTime", &DateTimeRange::fromDateTime, py::return_value_policy::move) .def(py::init([](double start, double stop){return DateTimeRange{start, stop};})) .def(py::init([](system_clock::time_point start, system_clock::time_point stop) { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0283d14..b5f7ffe 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -13,6 +13,8 @@ declare_test(TestStringUtils TestStringUtils Common/TestStringUtils.cpp "sciqlop declare_test(TestContainers TestContainers Common/TestContainers.cpp "sciqlopcore;Qt5::Test") declare_test(TestSyncGroup TestSyncGroup Variable/TestSyncGroup.cpp "sciqlopcore;Qt5::Test") +declare_test(TestDateTimeRange TestDateTimeRange Data/TestDateTimeRange.cpp "sciqlopcore;Qt5::Test") + declare_test(TestDataSeriesUtils TestDataSeriesUtils Data/TestDataSeriesUtils.cpp "sciqlopcore;Qt5::Test") declare_test(TestOptionalAxis TestOptionalAxis Data/TestOptionalAxis.cpp "sciqlopcore;Qt5::Test") diff --git a/tests/Data/TestDateTimeRange.cpp b/tests/Data/TestDateTimeRange.cpp new file mode 100644 index 0000000..02a30f6 --- /dev/null +++ b/tests/Data/TestDateTimeRange.cpp @@ -0,0 +1,106 @@ +#include +#include +#include +#include + + +#include +#include + +Q_DECLARE_METATYPE(Seconds); + +DateTimeRange computeZoom(QDateTime start, QDateTime stop, double zoom) +{ + double start_epoch = start.toMSecsSinceEpoch(); + double stop_epoch = stop.toMSecsSinceEpoch(); + auto delta = stop_epoch - start_epoch; + auto dt_ms = (zoom-1.)*(double(delta))/2.; + return DateTimeRange{(start_epoch - dt_ms)/1000., (stop_epoch + dt_ms)/1000.}; +} + +class TestDateTimeRange: public QObject { + Q_OBJECT + +private slots: + void testRangeDelta_data() + { + QTest::addColumn("tstart"); + QTest::addColumn("tend"); + QTest::addColumn("expected"); + auto now = QDateTime::currentDateTime(); + auto yesterday = QDateTime::currentDateTime().addDays(-1); + QTest::newRow("No delta") << now << now << 0.; + QTest::newRow("One day delta") << yesterday << now << 60.*60.*24.; + QTest::newRow("Minus one day delta") << now << yesterday << -60.*60.*24.; + } + + void testRangeDelta() + { + QFETCH(QDateTime,tstart); + QFETCH(QDateTime,tend); + QFETCH(double,expected); + auto range = DateTimeRange::fromDateTime(tstart, tend); + double delta = range.delta(); + // Since it is built from QDateTime don't expect better resolution + QVERIFY((delta-expected) <= 0.002); + } + + void testRangeShift_data() + { + QTest::addColumn("initial"); + QTest::addColumn>("shift"); + QTest::addColumn("expected"); + auto now = QDateTime::currentDateTime(); + auto yestd = QDateTime::currentDateTime().addDays(-1); + auto range = DateTimeRange::fromDateTime(yestd, now); + QTest::newRow("No shift") << range << Seconds{0.} << range; + + QTest::newRow("One milisecond left") << range << Seconds{-.001} << + DateTimeRange::fromDateTime(yestd.addMSecs(-1.), now.addMSecs(-1.)); + QTest::newRow("One milisecond right") << range << Seconds{.001} << + DateTimeRange::fromDateTime(yestd.addMSecs(1.), now.addMSecs(1.)); + QTest::newRow("One second left") << range << Seconds{-1.} << + DateTimeRange::fromDateTime(yestd.addSecs(-1.), now.addSecs(-1.)); + QTest::newRow("One second right") << range << Seconds{1.} << + DateTimeRange::fromDateTime(yestd.addSecs(1.), now.addSecs(1.)); + QTest::newRow("One year left") << range << Seconds{-365.*24.*60.*60.} << + DateTimeRange::fromDateTime(yestd.addYears(-1.), now.addYears(-1.)); + QTest::newRow("One year right") << range << Seconds{365.*24.*60.*60.} << + DateTimeRange::fromDateTime(yestd.addYears(1.), now.addYears(1.)); + } + void testRangeShift() + { + QFETCH(DateTimeRange,initial); + QFETCH(Seconds,shift); + QFETCH(DateTimeRange,expected); + QCOMPARE(initial+shift, expected); + } + + void testRangeZoom_data() + { + QTest::addColumn("initial"); + QTest::addColumn("zoom"); + QTest::addColumn("expected"); + auto now = QDateTime::currentDateTime(); + auto yestd = QDateTime::currentDateTime().addDays(-1); + auto range = DateTimeRange::fromDateTime(yestd, now); + QTest::newRow("No zoom") << range << 1. << range; + + QTest::newRow("Zoom IN 0.001") << range << 1.001 << + computeZoom(yestd, now, 1.001); + QTest::newRow("Zoom OUT 0.001") << range << 0.999 << + computeZoom(yestd, now, 0.999); + } + void testRangeZoom() + { + QFETCH(DateTimeRange,initial); + QFETCH(double,zoom); + QFETCH(DateTimeRange,expected); + QCOMPARE(initial*zoom, expected); + } + +}; +QTEST_MAIN(TestDateTimeRange) + + +#include "TestDateTimeRange.moc"