@@ -0,0 +1,3 | |||||
|
1 | [submodule "external/pybind11"] | |||
|
2 | path = external/pybind11 | |||
|
3 | url = https://github.com/pybind/pybind11 |
@@ -0,0 +1,187 | |||||
|
1 | cmake_minimum_required(VERSION 3.6) | |||
|
2 | project(SciQLOPCore CXX) | |||
|
3 | ||||
|
4 | OPTION (CPPCHECK "Analyzes the source code with cppcheck" OFF) | |||
|
5 | OPTION (CLANG_TIDY "Analyzes the source code with Clang Tidy" OFF) | |||
|
6 | OPTION (IWYU "Analyzes the source code with Include What You Use" OFF) | |||
|
7 | ||||
|
8 | OPTION (Catalog "builds catalog API" OFF) | |||
|
9 | ||||
|
10 | set(CMAKE_CXX_STANDARD 17) | |||
|
11 | ||||
|
12 | set(CMAKE_AUTOMOC ON) | |||
|
13 | #https://gitlab.kitware.com/cmake/cmake/issues/15227 | |||
|
14 | #set(CMAKE_AUTOUIC ON) | |||
|
15 | if(POLICY CMP0071) | |||
|
16 | cmake_policy(SET CMP0071 OLD) | |||
|
17 | endif() | |||
|
18 | set(CMAKE_AUTORCC ON) | |||
|
19 | set(CMAKE_INCLUDE_CURRENT_DIR ON) | |||
|
20 | ||||
|
21 | find_package(Qt5 COMPONENTS Core Widgets Network PrintSupport Svg Test REQUIRED) | |||
|
22 | ||||
|
23 | find_package(pybind11 CONFIG QUIET) | |||
|
24 | if (NOT pybind11_FOUND) | |||
|
25 | execute_process(COMMAND git submodule init external/pybind11 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) | |||
|
26 | execute_process(COMMAND git submodule update external/pybind11 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) | |||
|
27 | add_subdirectory(external/pybind11) | |||
|
28 | endif() | |||
|
29 | ||||
|
30 | macro(declare_test testname testexe sources libraries) | |||
|
31 | add_executable(${testexe} ${sources}) | |||
|
32 | target_link_libraries(${testexe} ${libraries}) | |||
|
33 | add_test(NAME ${testname} COMMAND ${testexe}) | |||
|
34 | endmacro(declare_test) | |||
|
35 | ||||
|
36 | enable_testing() | |||
|
37 | ||||
|
38 | FILE (GLOB_RECURSE core_SRCS | |||
|
39 | ./include/DataSource/DataSourceItemMergeHelper.h | |||
|
40 | ./include/DataSource/DataSourceItemAction.h | |||
|
41 | ./include/DataSource/DataSourceItem.h | |||
|
42 | ./include/DataSource/DataSourceController.h | |||
|
43 | ./include/Common/SortUtils.h | |||
|
44 | ./include/Common/spimpl.h | |||
|
45 | ./include/Common/MimeTypesDef.h | |||
|
46 | ./include/Common/MetaTypes.h | |||
|
47 | ./include/Common/StringUtils.h | |||
|
48 | ./include/Common/SignalWaiter.h | |||
|
49 | ./include/Common/DateUtils.h | |||
|
50 | ./include/Common/Numeric.h | |||
|
51 | ./include/Common/deprecate.h | |||
|
52 | ./include/Common/containers.h | |||
|
53 | ./include/Plugin/IPlugin.h | |||
|
54 | ./include/Data/ArrayDataIterator.h | |||
|
55 | ./include/Data/VariableRequest.h | |||
|
56 | ./include/Data/VectorSeries.h | |||
|
57 | ./include/Data/DateTimeRange.h | |||
|
58 | ./include/Data/ScalarSeries.h | |||
|
59 | ./include/Data/DataSeriesMergeHelper.h | |||
|
60 | ./include/Data/DataSeries.h | |||
|
61 | ./include/Data/AcquisitionDataPacket.h | |||
|
62 | ./include/Data/DataSeriesType.h | |||
|
63 | ./include/Data/AcquisitionRequest.h | |||
|
64 | ./include/Data/SqpIterator.h | |||
|
65 | ./include/Data/ArrayData.h | |||
|
66 | ./include/Data/DataSeriesIterator.h | |||
|
67 | ./include/Data/DataSeriesUtils.h | |||
|
68 | ./include/Data/SpectrogramSeries.h | |||
|
69 | ./include/Data/Unit.h | |||
|
70 | ./include/Data/DataProviderParameters.h | |||
|
71 | ./include/Data/OptionalAxis.h | |||
|
72 | ./include/Data/IDataProvider.h | |||
|
73 | ./include/Data/IDataSeries.h | |||
|
74 | ./include/Network/NetworkController.h | |||
|
75 | ./include/Network/Downloader.h | |||
|
76 | ./include/Version.h | |||
|
77 | ./include/CoreGlobal.h | |||
|
78 | ./include/Visualization/VisualizationController.h | |||
|
79 | ./include/PluginManager/PluginManager.h | |||
|
80 | ./include/Variable/VariableModel.h | |||
|
81 | ./include/Variable/VariableAcquisitionWorker.h | |||
|
82 | ./include/Variable/VariableCacheStrategy.h | |||
|
83 | ./include/Variable/VariableSynchronizationGroup.h | |||
|
84 | ./include/Variable/VariableSynchronizationGroup2.h | |||
|
85 | ./include/Variable/VariableSingleThresholdCacheStrategy.h | |||
|
86 | ./include/Variable/VariableCacheStrategyFactory.h | |||
|
87 | ./include/Variable/Variable.h | |||
|
88 | ./include/Variable/VariableCacheController.h | |||
|
89 | ./include/Variable/VariableController.h | |||
|
90 | ./include/Variable/VariableController2.h | |||
|
91 | ./include/Time/TimeController.h | |||
|
92 | ./include/Settings/ISqpSettingsBindable.h | |||
|
93 | ./include/Settings/SqpSettingsDefs.h | |||
|
94 | ||||
|
95 | ./src/DataSource/DataSourceItem.cpp | |||
|
96 | ./src/DataSource/DataSourceItemAction.cpp | |||
|
97 | ./src/DataSource/DataSourceItemMergeHelper.cpp | |||
|
98 | ./src/DataSource/DataSourceController.cpp | |||
|
99 | ./src/Common/DateUtils.cpp | |||
|
100 | ./src/Common/MimeTypesDef.cpp | |||
|
101 | ./src/Common/StringUtils.cpp | |||
|
102 | ./src/Common/SignalWaiter.cpp | |||
|
103 | ./src/Data/ScalarSeries.cpp | |||
|
104 | ./src/Data/DataSeriesIterator.cpp | |||
|
105 | ./src/Data/OptionalAxis.cpp | |||
|
106 | ./src/Data/ArrayDataIterator.cpp | |||
|
107 | ./src/Data/SpectrogramSeries.cpp | |||
|
108 | ./src/Data/DataSeriesUtils.cpp | |||
|
109 | ./src/Data/VectorSeries.cpp | |||
|
110 | ./src/Network/NetworkController.cpp | |||
|
111 | ./src/Network/Downloader.cpp | |||
|
112 | ./src/Visualization/VisualizationController.cpp | |||
|
113 | ./src/PluginManager/PluginManager.cpp | |||
|
114 | ./src/Variable/VariableController.cpp | |||
|
115 | ./src/Variable/VariableController2.cpp | |||
|
116 | ./src/Variable/VariableModel.cpp | |||
|
117 | ./src/Variable/VariableCacheController.cpp | |||
|
118 | ./src/Variable/VariableSynchronizationGroup.cpp | |||
|
119 | ./src/Variable/VariableSynchronizationGroup2.cpp | |||
|
120 | ./src/Variable/Variable.cpp | |||
|
121 | ./src/Variable/VariableAcquisitionWorker.cpp | |||
|
122 | ./src/Version.cpp | |||
|
123 | ./src/Time/TimeController.cpp | |||
|
124 | ./src/Settings/SqpSettingsDefs.cpp | |||
|
125 | ||||
|
126 | ) | |||
|
127 | ||||
|
128 | ||||
|
129 | IF(Catalog) | |||
|
130 | FILE (GLOB_RECURSE core_catalog_SRCS | |||
|
131 | ./src/Catalogue/CatalogueController.cpp | |||
|
132 | ./include/Catalogue/CatalogueController.h | |||
|
133 | ) | |||
|
134 | ELSE() | |||
|
135 | FILE (GLOB_RECURSE core_catalog_SRCS | |||
|
136 | ) | |||
|
137 | ENDIF(Catalog) | |||
|
138 | ||||
|
139 | add_definitions(-DCORE_STATIC) | |||
|
140 | #add_definitions(-DHIDE_DEPRECATED) | |||
|
141 | ||||
|
142 | add_library(sciqlopcore ${core_SRCS} ${core_catalog_SRCS}) | |||
|
143 | SET_TARGET_PROPERTIES(sciqlopcore PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS TRUE) | |||
|
144 | ||||
|
145 | target_include_directories(sciqlopcore PUBLIC | |||
|
146 | $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> | |||
|
147 | $<INSTALL_INTERFACE:include/SciQLOP> | |||
|
148 | ) | |||
|
149 | ||||
|
150 | target_link_libraries(sciqlopcore PUBLIC | |||
|
151 | Qt5::Core | |||
|
152 | Qt5::Network | |||
|
153 | ) | |||
|
154 | ||||
|
155 | if(Catalog) | |||
|
156 | target_link_libraries(sciqlopcore PUBLIC | |||
|
157 | catalogs | |||
|
158 | ) | |||
|
159 | endif() | |||
|
160 | ||||
|
161 | ||||
|
162 | pybind11_add_module(sciqlopqt src/pybind11_wrappers/QtWrappers.cpp) | |||
|
163 | target_link_libraries(sciqlopqt PUBLIC Qt5::Core) | |||
|
164 | ||||
|
165 | pybind11_add_module(pysciqlopcore src/pybind11_wrappers/CoreWrappers.cpp) | |||
|
166 | target_link_libraries(pysciqlopcore PUBLIC sciqlopcore) | |||
|
167 | ||||
|
168 | add_library(pysciqlop src/pybind11_wrappers/pywrappers_common.h) | |||
|
169 | target_link_libraries(pysciqlop PUBLIC Qt5::Core) | |||
|
170 | target_include_directories(pysciqlop PUBLIC | |||
|
171 | $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src/pybind11_wrappers/> | |||
|
172 | $<INSTALL_INTERFACE:include/SciQLOP/py_wrappers> | |||
|
173 | ) | |||
|
174 | ||||
|
175 | SET_PROPERTY(GLOBAL PROPERTY CORE_PYTHON_PATH ${CMAKE_CURRENT_BINARY_DIR}) | |||
|
176 | ||||
|
177 | ||||
|
178 | install(TARGETS sciqlopcore EXPORT SciQLOPCoreConfig | |||
|
179 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} | |||
|
180 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} | |||
|
181 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) | |||
|
182 | ||||
|
183 | install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/SciQLOP) | |||
|
184 | install(EXPORT SciQLOPCoreConfig DESTINATION share/SciQLOPCore/cmake) | |||
|
185 | export(TARGETS sciqlopcore FILE SciQLOPCoreConfig.cmake) | |||
|
186 | ||||
|
187 | add_subdirectory(tests) |
@@ -0,0 +1,1 | |||||
|
1 | Subproject commit f7bc18f528bb35cd06c93d0a58c17e6eea3fa68c |
@@ -0,0 +1,93 | |||||
|
1 | #ifndef SCIQLOP_CATALOGUECONTROLLER_H | |||
|
2 | #define SCIQLOP_CATALOGUECONTROLLER_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <Data/DateTimeRange.h> | |||
|
7 | ||||
|
8 | #include <QLoggingCategory> | |||
|
9 | #include <QObject> | |||
|
10 | #include <QUuid> | |||
|
11 | ||||
|
12 | #include <Common/spimpl.h> | |||
|
13 | ||||
|
14 | #include <memory> | |||
|
15 | ||||
|
16 | class DBCatalogue; | |||
|
17 | class DBEvent; | |||
|
18 | class DBEventProduct; | |||
|
19 | ||||
|
20 | Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueController) | |||
|
21 | ||||
|
22 | class DataSourceItem; | |||
|
23 | class Variable; | |||
|
24 | ||||
|
25 | /** | |||
|
26 | * @brief The CatalogueController class aims to handle catalogues and event using the CatalogueAPI | |||
|
27 | * library. | |||
|
28 | */ | |||
|
29 | class SCIQLOP_CORE_EXPORT CatalogueController : public QObject { | |||
|
30 | Q_OBJECT | |||
|
31 | public: | |||
|
32 | explicit CatalogueController(QObject *parent = 0); | |||
|
33 | virtual ~CatalogueController(); | |||
|
34 | ||||
|
35 | // DB | |||
|
36 | QStringList getRepositories() const; | |||
|
37 | void addDB(const QString &dbPath); | |||
|
38 | void saveDB(const QString &destinationPath, const QString &repository); | |||
|
39 | ||||
|
40 | // Event | |||
|
41 | /// retrieveEvents with empty repository retrieve them from the default repository | |||
|
42 | std::list<std::shared_ptr<DBEvent> > retrieveEvents(const QString &repository) const; | |||
|
43 | std::list<std::shared_ptr<DBEvent> > retrieveAllEvents() const; | |||
|
44 | ||||
|
45 | void addEvent(std::shared_ptr<DBEvent> event); | |||
|
46 | void updateEvent(std::shared_ptr<DBEvent> event); | |||
|
47 | void updateEventProduct(std::shared_ptr<DBEventProduct> eventProduct); | |||
|
48 | void removeEvent(std::shared_ptr<DBEvent> event); | |||
|
49 | // void trashEvent(std::shared_ptr<DBEvent> event); | |||
|
50 | // void restore(std::shared_ptr<DBEvent> event); | |||
|
51 | void saveEvent(std::shared_ptr<DBEvent> event); | |||
|
52 | void discardEvent(std::shared_ptr<DBEvent> event, bool &removed); | |||
|
53 | bool eventHasChanges(std::shared_ptr<DBEvent> event) const; | |||
|
54 | ||||
|
55 | // Catalogue | |||
|
56 | std::list<std::shared_ptr<DBEvent> > | |||
|
57 | retrieveEventsFromCatalogue(std::shared_ptr<DBCatalogue> catalogue) const; | |||
|
58 | ||||
|
59 | /// retrieveEvents with empty repository retrieve them from the default repository | |||
|
60 | std::list<std::shared_ptr<DBCatalogue> > retrieveCatalogues(const QString &repository | |||
|
61 | = QString()) const; | |||
|
62 | void addCatalogue(std::shared_ptr<DBCatalogue> catalogue); | |||
|
63 | void updateCatalogue(std::shared_ptr<DBCatalogue> catalogue); | |||
|
64 | void removeCatalogue(std::shared_ptr<DBCatalogue> catalogue); | |||
|
65 | void saveCatalogue(std::shared_ptr<DBCatalogue> catalogue); | |||
|
66 | void discardCatalogue(std::shared_ptr<DBCatalogue> catalogue, bool &removed); | |||
|
67 | ||||
|
68 | void saveAll(); | |||
|
69 | bool hasChanges() const; | |||
|
70 | ||||
|
71 | /// Returns the MIME data associated to a list of variables | |||
|
72 | QByteArray mimeDataForEvents(const QVector<std::shared_ptr<DBEvent> > &events) const; | |||
|
73 | ||||
|
74 | /// Returns the list of variables contained in a MIME data | |||
|
75 | QVector<std::shared_ptr<DBEvent> > eventsForMimeData(const QByteArray &mimeData) const; | |||
|
76 | ||||
|
77 | /// Returns the MIME data associated to a list of variables | |||
|
78 | QByteArray | |||
|
79 | mimeDataForCatalogues(const QVector<std::shared_ptr<DBCatalogue> > &catalogues) const; | |||
|
80 | ||||
|
81 | /// Returns the list of variables contained in a MIME data | |||
|
82 | QVector<std::shared_ptr<DBCatalogue> > cataloguesForMimeData(const QByteArray &mimeData) const; | |||
|
83 | ||||
|
84 | public slots: | |||
|
85 | /// Manage init/end of the controller | |||
|
86 | void initialize(); | |||
|
87 | ||||
|
88 | private: | |||
|
89 | class CatalogueControllerPrivate; | |||
|
90 | spimpl::unique_impl_ptr<CatalogueControllerPrivate> impl; | |||
|
91 | }; | |||
|
92 | ||||
|
93 | #endif // SCIQLOP_CATALOGUECONTROLLER_H |
@@ -0,0 +1,23 | |||||
|
1 | #ifndef SCIQLOP_DATEUTILS_H | |||
|
2 | #define SCIQLOP_DATEUTILS_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <QDateTime> | |||
|
7 | ||||
|
8 | /// Format for datetimes | |||
|
9 | const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz"); | |||
|
10 | const auto DATETIME_FORMAT_ONE_LINE = QStringLiteral("dd/MM/yyyy hh:mm:ss:zzz"); | |||
|
11 | ||||
|
12 | /** | |||
|
13 | * Utility class with methods for dates | |||
|
14 | */ | |||
|
15 | struct SCIQLOP_CORE_EXPORT DateUtils { | |||
|
16 | /// Converts seconds (since epoch) to datetime. By default, the datetime is in UTC | |||
|
17 | static QDateTime dateTime(double secs, Qt::TimeSpec timeSpec = Qt::UTC) noexcept; | |||
|
18 | ||||
|
19 | /// Converts datetime to seconds since epoch | |||
|
20 | static double secondsSinceEpoch(const QDateTime &dateTime) noexcept; | |||
|
21 | }; | |||
|
22 | ||||
|
23 | #endif // SCIQLOP_DATEUTILS_H |
@@ -0,0 +1,46 | |||||
|
1 | #ifndef SCIQLOP_METATYPES_H | |||
|
2 | #define SCIQLOP_METATYPES_H | |||
|
3 | ||||
|
4 | #include <QMetaType> | |||
|
5 | ||||
|
6 | /** | |||
|
7 | * Struct used to create an instance that registers a type in Qt for signals / slots mechanism | |||
|
8 | * @tparam T the type to register | |||
|
9 | */ | |||
|
10 | template <typename T> | |||
|
11 | struct MetaTypeRegistry { | |||
|
12 | explicit MetaTypeRegistry() { qRegisterMetaType<T>(); } | |||
|
13 | }; | |||
|
14 | ||||
|
15 | /** | |||
|
16 | * This macro can be used to : | |||
|
17 | * - declare a type as a Qt meta type | |||
|
18 | * - and register it (through a static instance) at the launch of SciQlop, so it can be passed in | |||
|
19 | * Qt signals/slots | |||
|
20 | * | |||
|
21 | * It can be used both in .h or in .cpp files | |||
|
22 | * | |||
|
23 | * @param NAME name of the instance under which the type will be registered (in uppercase) | |||
|
24 | * @param TYPE type to register | |||
|
25 | * | |||
|
26 | * Example: | |||
|
27 | * ~~~cpp | |||
|
28 | * // The following macro : | |||
|
29 | * // - declares std::shared_ptr<Variable> as a Qt meta type | |||
|
30 | * // - registers it through an instance named VAR_SHARED_PTR | |||
|
31 | * SCIQLOP_REGISTER_META_TYPE(VAR_SHARED_PTR, std::shared_ptr<Variable>) | |||
|
32 | * | |||
|
33 | * // The following macro : | |||
|
34 | * // - declares a raw pointer of Variable as a Qt meta type | |||
|
35 | * // - registers it through an instance named VAR_RAW_PTR | |||
|
36 | * SCIQLOP_REGISTER_META_TYPE(VAR_RAW_PTR, Variable*) | |||
|
37 | * ~~~ | |||
|
38 | * | |||
|
39 | */ | |||
|
40 | // clang-format off | |||
|
41 | #define SCIQLOP_REGISTER_META_TYPE(NAME, TYPE) \ | |||
|
42 | Q_DECLARE_METATYPE(TYPE) \ | |||
|
43 | const auto NAME = MetaTypeRegistry<TYPE>{}; \ | |||
|
44 | // clang-format on | |||
|
45 | ||||
|
46 | #endif // SCIQLOP_METATYPES_H |
@@ -0,0 +1,22 | |||||
|
1 | #ifndef SCIQLOP_MIMETYPESDEF_H | |||
|
2 | #define SCIQLOP_MIMETYPESDEF_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <QString> | |||
|
7 | ||||
|
8 | // ////////////////// // | |||
|
9 | // SciQlop Mime Types // | |||
|
10 | // ////////////////// // | |||
|
11 | ||||
|
12 | extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_GRAPH; | |||
|
13 | extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_ZONE; | |||
|
14 | extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_VARIABLE_LIST; | |||
|
15 | extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_PRODUCT_LIST; | |||
|
16 | extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_TIME_RANGE; | |||
|
17 | extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_SELECTION_ZONE; | |||
|
18 | extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_EVENT_LIST; | |||
|
19 | extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_SOURCE_CATALOGUE_LIST; | |||
|
20 | ||||
|
21 | ||||
|
22 | #endif // SCIQLOP_MIMETYPESDEF_H |
@@ -0,0 +1,18 | |||||
|
1 | #include <cmath> | |||
|
2 | #include <limits> | |||
|
3 | #include <type_traits> | |||
|
4 | #include <algorithm> | |||
|
5 | ||||
|
6 | /* | |||
|
7 | taken from here https://en.cppreference.com/w/cpp/types/numeric_limits/epsilon | |||
|
8 | */ | |||
|
9 | template<class T> | |||
|
10 | typename std::enable_if<!std::numeric_limits<T>::is_integer, bool>::type | |||
|
11 | almost_equal(T x, T y, int ulp) | |||
|
12 | { | |||
|
13 | // the machine epsilon has to be scaled to the magnitude of the values used | |||
|
14 | // and multiplied by the desired precision in ULPs (units in the last place) | |||
|
15 | return std::abs(x-y) <= std::numeric_limits<T>::epsilon() * std::abs(x+y) * ulp | |||
|
16 | // unless the result is subnormal | |||
|
17 | || std::abs(x-y) < std::numeric_limits<T>::min(); | |||
|
18 | } |
@@ -0,0 +1,38 | |||||
|
1 | #ifndef SCIQLOP_SIGNALWAITER_H | |||
|
2 | #define SCIQLOP_SIGNALWAITER_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <QEventLoop> | |||
|
7 | ||||
|
8 | /** | |||
|
9 | * Class for synchronously waiting for the reception of a signal. The signal to wait is passed to | |||
|
10 | * the construction of the object. When starting the wait, a timeout can be set to exit if the | |||
|
11 | * signal has not been sent | |||
|
12 | */ | |||
|
13 | class SCIQLOP_CORE_EXPORT SignalWaiter : public QObject { | |||
|
14 | Q_OBJECT | |||
|
15 | public: | |||
|
16 | /** | |||
|
17 | * Ctor | |||
|
18 | * @param object the sender of the signal | |||
|
19 | * @param signal the signal to listen | |||
|
20 | */ | |||
|
21 | explicit SignalWaiter(QObject &sender, const char *signal); | |||
|
22 | ||||
|
23 | /** | |||
|
24 | * Starts the signal and leaves after the signal has been received, or after the timeout | |||
|
25 | * @param timeout the timeout set (if 0, uses a default timeout) | |||
|
26 | * @return true if the signal was sent, false if the timeout occured | |||
|
27 | */ | |||
|
28 | bool wait(int timeout); | |||
|
29 | ||||
|
30 | private: | |||
|
31 | bool m_Timeout; | |||
|
32 | QEventLoop m_EventLoop; | |||
|
33 | ||||
|
34 | private slots: | |||
|
35 | void timeout(); | |||
|
36 | }; | |||
|
37 | ||||
|
38 | #endif // SCIQLOP_SIGNALWAITER_H |
@@ -0,0 +1,139 | |||||
|
1 | #ifndef SCIQLOP_SORTUTILS_H | |||
|
2 | #define SCIQLOP_SORTUTILS_H | |||
|
3 | ||||
|
4 | #include <algorithm> | |||
|
5 | #include <cmath> | |||
|
6 | #include <numeric> | |||
|
7 | #include <vector> | |||
|
8 | ||||
|
9 | /** | |||
|
10 | * Utility class with methods for sorting data | |||
|
11 | */ | |||
|
12 | struct SortUtils { | |||
|
13 | /** | |||
|
14 | * Generates a vector representing the index of insertion of each data of a container if this | |||
|
15 | * one had to be sorted according to a comparison function. | |||
|
16 | * | |||
|
17 | * For example: | |||
|
18 | * If the container is a vector {1; 4; 2; 5; 3} and the comparison function is std::less, the | |||
|
19 | * result would be : {0; 3; 1; 4; 2} | |||
|
20 | * | |||
|
21 | * @tparam Container the type of the container. | |||
|
22 | * @tparam Compare the type of the comparison function | |||
|
23 | * @param container the container from which to generate the result. The container must have a | |||
|
24 | * at() method that returns a value associated to an index | |||
|
25 | * @param compare the comparison function | |||
|
26 | */ | |||
|
27 | template <typename Container, typename Compare> | |||
|
28 | static std::vector<int> sortPermutation(const Container &container, const Compare &compare) | |||
|
29 | { | |||
|
30 | auto permutation = std::vector<int>{}; | |||
|
31 | permutation.resize(container.size()); | |||
|
32 | ||||
|
33 | std::iota(permutation.begin(), permutation.end(), 0); | |||
|
34 | std::sort(permutation.begin(), permutation.end(), | |||
|
35 | [&](int i, int j) { return compare(container.at(i), container.at(j)); }); | |||
|
36 | return permutation; | |||
|
37 | } | |||
|
38 | ||||
|
39 | /** | |||
|
40 | * Sorts a container according to indices passed in parameter. The number of data in the | |||
|
41 | * container must be a multiple of the number of indices used to sort the container. | |||
|
42 | * | |||
|
43 | * Example 1: | |||
|
44 | * container: {1, 2, 3, 4, 5, 6} | |||
|
45 | * sortPermutation: {1, 0} | |||
|
46 | * | |||
|
47 | * Values will be sorted three by three, and the result will be: | |||
|
48 | * {4, 5, 6, 1, 2, 3} | |||
|
49 | * | |||
|
50 | * Example 2: | |||
|
51 | * container: {1, 2, 3, 4, 5, 6} | |||
|
52 | * sortPermutation: {2, 0, 1} | |||
|
53 | * | |||
|
54 | * Values will be sorted two by two, and the result will be: | |||
|
55 | * {5, 6, 1, 2, 3, 4} | |||
|
56 | * | |||
|
57 | * @param container the container sorted | |||
|
58 | * @param sortPermutation the indices used to sort the container | |||
|
59 | * @return the container sorted | |||
|
60 | * @warning no verification is made on validity of sortPermutation (i.e. the vector has unique | |||
|
61 | * indices and its range is [0 ; vector.size()[ ) | |||
|
62 | */ | |||
|
63 | template <typename Container> | |||
|
64 | static Container sort(const Container &container, int nbValues, | |||
|
65 | const std::vector<int> &sortPermutation) | |||
|
66 | { | |||
|
67 | auto containerSize = container.size(); | |||
|
68 | if (containerSize % nbValues != 0 | |||
|
69 | || ((containerSize / nbValues) != sortPermutation.size())) { | |||
|
70 | return Container{}; | |||
|
71 | } | |||
|
72 | ||||
|
73 | // Inits result | |||
|
74 | auto sortedData = Container{}; | |||
|
75 | sortedData.reserve(containerSize); | |||
|
76 | ||||
|
77 | for (auto i = 0u, componentIndex = 0u, permutationIndex = 0u; i < containerSize; | |||
|
78 | ++i, componentIndex = i % nbValues, permutationIndex = i / nbValues) { | |||
|
79 | auto insertIndex = sortPermutation.at(permutationIndex) * nbValues + componentIndex; | |||
|
80 | sortedData.push_back(container.at(insertIndex)); | |||
|
81 | } | |||
|
82 | ||||
|
83 | return sortedData; | |||
|
84 | } | |||
|
85 | ||||
|
86 | /** | |||
|
87 | * Compares two values that can be NaN. This method is intended to be used as a compare function | |||
|
88 | * for searching min value by excluding NaN values. | |||
|
89 | * | |||
|
90 | * Examples of use: | |||
|
91 | * - f({1, 3, 2, 4, 5}) will return 1 | |||
|
92 | * - f({NaN, 3, 2, 4, 5}) will return 2 (NaN is excluded) | |||
|
93 | * - f({NaN, NaN, 3, NaN, NaN}) will return 3 (NaN are excluded) | |||
|
94 | * - f({NaN, NaN, NaN, NaN, NaN}) will return NaN (no existing value) | |||
|
95 | * | |||
|
96 | * @param v1 first value | |||
|
97 | * @param v2 second value | |||
|
98 | * @return true if v1 < v2, false otherwise | |||
|
99 | * @sa std::min_element | |||
|
100 | */ | |||
|
101 | template <typename T> | |||
|
102 | static bool minCompareWithNaN(const T &v1, const T &v2) | |||
|
103 | { | |||
|
104 | // Table used with NaN values: | |||
|
105 | // NaN < v2 -> false | |||
|
106 | // v1 < NaN -> true | |||
|
107 | // NaN < NaN -> false | |||
|
108 | // v1 < v2 -> v1 < v2 | |||
|
109 | return std::isnan(v1) ? false : std::isnan(v2) || (v1 < v2); | |||
|
110 | } | |||
|
111 | ||||
|
112 | /** | |||
|
113 | * Compares two values that can be NaN. This method is intended to be used as a compare function | |||
|
114 | * for searching max value by excluding NaN values. | |||
|
115 | * | |||
|
116 | * Examples of use: | |||
|
117 | * - f({1, 3, 2, 4, 5}) will return 5 | |||
|
118 | * - f({1, 3, 2, 4, NaN}) will return 4 (NaN is excluded) | |||
|
119 | * - f({NaN, NaN, 3, NaN, NaN}) will return 3 (NaN are excluded) | |||
|
120 | * - f({NaN, NaN, NaN, NaN, NaN}) will return NaN (no existing value) | |||
|
121 | * | |||
|
122 | * @param v1 first value | |||
|
123 | * @param v2 second value | |||
|
124 | * @return true if v1 < v2, false otherwise | |||
|
125 | * @sa std::max_element | |||
|
126 | */ | |||
|
127 | template <typename T> | |||
|
128 | static bool maxCompareWithNaN(const T &v1, const T &v2) | |||
|
129 | { | |||
|
130 | // Table used with NaN values: | |||
|
131 | // NaN < v2 -> true | |||
|
132 | // v1 < NaN -> false | |||
|
133 | // NaN < NaN -> false | |||
|
134 | // v1 < v2 -> v1 < v2 | |||
|
135 | return std::isnan(v1) ? true : !std::isnan(v2) && (v1 < v2); | |||
|
136 | } | |||
|
137 | }; | |||
|
138 | ||||
|
139 | #endif // SCIQLOP_SORTUTILS_H |
@@ -0,0 +1,35 | |||||
|
1 | #ifndef SCIQLOP_STRINGUTILS_H | |||
|
2 | #define SCIQLOP_STRINGUTILS_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <vector> | |||
|
7 | ||||
|
8 | class QString; | |||
|
9 | ||||
|
10 | /** | |||
|
11 | * Utility class with methods for strings | |||
|
12 | */ | |||
|
13 | struct SCIQLOP_CORE_EXPORT StringUtils { | |||
|
14 | /** | |||
|
15 | * Generates a unique name from a default name and a set of forbidden names. | |||
|
16 | * | |||
|
17 | * Generating the unique name is done by adding an index to the default name and stopping at the | |||
|
18 | * first index for which the generated name is not in the forbidden names. | |||
|
19 | * | |||
|
20 | * Examples (defaultName, forbiddenNames -> result): | |||
|
21 | * - "FGM", {"FGM"} -> "FGM1" | |||
|
22 | * - "FGM", {"ABC"} -> "FGM" | |||
|
23 | * - "FGM", {"FGM", "FGM1"} -> "FGM2" | |||
|
24 | * - "FGM", {"FGM", "FGM2"} -> "FGM1" | |||
|
25 | * - "", {"ABC"} -> "1" | |||
|
26 | * | |||
|
27 | * @param defaultName the default name | |||
|
28 | * @param forbiddenNames the set of forbidden names | |||
|
29 | * @return the unique name generated | |||
|
30 | */ | |||
|
31 | static QString uniqueName(const QString &defaultName, | |||
|
32 | const std::vector<QString> &forbiddenNames) noexcept; | |||
|
33 | }; | |||
|
34 | ||||
|
35 | #endif // SCIQLOP_STRINGUTILS_H |
@@ -0,0 +1,16 | |||||
|
1 | #ifndef CONTAINERS_H | |||
|
2 | #define CONTAINERS_H | |||
|
3 | #include <algorithm> | |||
|
4 | ||||
|
5 | namespace SciQLop::containers { | |||
|
6 | ||||
|
7 | template <class T1,class T2> | |||
|
8 | bool contains(const T1 &container, const T2 &value) | |||
|
9 | { | |||
|
10 | return std::find(container.begin(), container.end(), value) != container.end(); | |||
|
11 | } | |||
|
12 | ||||
|
13 | } | |||
|
14 | ||||
|
15 | ||||
|
16 | #endif // CONTAINERS_H |
@@ -0,0 +1,10 | |||||
|
1 | #ifndef DEPRECATE_H | |||
|
2 | #define DEPRECATE_H | |||
|
3 | ||||
|
4 | #ifdef HIDE_DEPRECATED | |||
|
5 | #define DEPRECATE(x) | |||
|
6 | #else | |||
|
7 | #define DEPRECATE(x) x | |||
|
8 | #endif | |||
|
9 | ||||
|
10 | #endif |
@@ -0,0 +1,460 | |||||
|
1 | /* | |||
|
2 | ==================================================================== | |||
|
3 | A Smart Pointer to IMPLementation (i.e. Smart PIMPL or just SPIMPL). | |||
|
4 | ==================================================================== | |||
|
5 | ||||
|
6 | Version: 1.1 | |||
|
7 | ||||
|
8 | Latest version: | |||
|
9 | https://github.com/oliora/samples/blob/master/spimpl.h | |||
|
10 | Rationale and description: | |||
|
11 | http://oliora.github.io/2015/12/29/pimpl-and-rule-of-zero.html | |||
|
12 | ||||
|
13 | Copyright (c) 2015 Andrey Upadyshev (oliora@gmail.com) | |||
|
14 | ||||
|
15 | Distributed under the Boost Software License, Version 1.0. | |||
|
16 | See http://www.boost.org/LICENSE_1_0.txt | |||
|
17 | ||||
|
18 | Changes history | |||
|
19 | --------------- | |||
|
20 | v1.1: | |||
|
21 | - auto_ptr support is disabled by default for C++17 compatibility | |||
|
22 | v1.0: | |||
|
23 | - Released | |||
|
24 | */ | |||
|
25 | ||||
|
26 | #ifndef SPIMPL_H_ | |||
|
27 | #define SPIMPL_H_ | |||
|
28 | ||||
|
29 | #include <cassert> | |||
|
30 | #include <memory> | |||
|
31 | #include <type_traits> | |||
|
32 | ||||
|
33 | #if defined _MSC_VER && _MSC_VER < 1900 // MS Visual Studio before VS2015 | |||
|
34 | #define SPIMPL_NO_CPP11_NOEXCEPT | |||
|
35 | #define SPIMPL_NO_CPP11_CONSTEXPR | |||
|
36 | #define SPIMPL_NO_CPP11_DEFAULT_MOVE_SPEC_FUNC | |||
|
37 | #endif | |||
|
38 | ||||
|
39 | #if !defined SPIMPL_NO_CPP11_NOEXCEPT | |||
|
40 | #define SPIMPL_NOEXCEPT noexcept | |||
|
41 | #else | |||
|
42 | #define SPIMPL_NOEXCEPT | |||
|
43 | #endif | |||
|
44 | ||||
|
45 | #if !defined SPIMPL_NO_CPP11_CONSTEXPR | |||
|
46 | #define SPIMPL_CONSTEXPR constexpr | |||
|
47 | #else | |||
|
48 | #define SPIMPL_CONSTEXPR | |||
|
49 | #endif | |||
|
50 | ||||
|
51 | // define SPIMPL_HAS_AUTO_PTR to enable constructor and assignment operator that accept | |||
|
52 | // std::auto_ptr | |||
|
53 | // TODO: auto detect std::auto_ptr support | |||
|
54 | ||||
|
55 | ||||
|
56 | namespace spimpl { | |||
|
57 | namespace details { | |||
|
58 | template <class T> | |||
|
59 | T *default_copy(T *src) | |||
|
60 | { | |||
|
61 | static_assert(sizeof(T) > 0, "default_copy cannot copy incomplete type"); | |||
|
62 | static_assert(!std::is_void<T>::value, "default_copy cannot copy incomplete type"); | |||
|
63 | return new T(*src); | |||
|
64 | } | |||
|
65 | ||||
|
66 | template <class T> | |||
|
67 | void default_delete(T *p) SPIMPL_NOEXCEPT | |||
|
68 | { | |||
|
69 | static_assert(sizeof(T) > 0, "default_delete cannot delete incomplete type"); | |||
|
70 | static_assert(!std::is_void<T>::value, "default_delete cannot delete incomplete type"); | |||
|
71 | delete p; | |||
|
72 | } | |||
|
73 | ||||
|
74 | template <class T> | |||
|
75 | struct default_deleter { | |||
|
76 | using type = void (*)(T *); | |||
|
77 | }; | |||
|
78 | ||||
|
79 | template <class T> | |||
|
80 | using default_deleter_t = typename default_deleter<T>::type; | |||
|
81 | ||||
|
82 | template <class T> | |||
|
83 | struct default_copier { | |||
|
84 | using type = T *(*)(T *); | |||
|
85 | }; | |||
|
86 | ||||
|
87 | template <class T> | |||
|
88 | using default_copier_t = typename default_copier<T>::type; | |||
|
89 | ||||
|
90 | template <class T, class D, class C> | |||
|
91 | struct is_default_manageable | |||
|
92 | : public std::integral_constant<bool, std::is_same<D, default_deleter_t<T> >::value | |||
|
93 | && std::is_same<C, default_copier_t<T> >::value> { | |||
|
94 | }; | |||
|
95 | } | |||
|
96 | ||||
|
97 | ||||
|
98 | template <class T, class Deleter = details::default_deleter_t<T>, | |||
|
99 | class Copier = details::default_copier_t<T> > | |||
|
100 | class impl_ptr { | |||
|
101 | private: | |||
|
102 | static_assert(!std::is_array<T>::value, | |||
|
103 | "impl_ptr specialization for arrays is not implemented"); | |||
|
104 | struct dummy_t_ { | |||
|
105 | int dummy__; | |||
|
106 | }; | |||
|
107 | ||||
|
108 | public: | |||
|
109 | using pointer = T *; | |||
|
110 | using element_type = T; | |||
|
111 | using copier_type = typename std::decay<Copier>::type; | |||
|
112 | using deleter_type = typename std::decay<Deleter>::type; | |||
|
113 | using unique_ptr_type = std::unique_ptr<T, deleter_type>; | |||
|
114 | using is_default_manageable = details::is_default_manageable<T, deleter_type, copier_type>; | |||
|
115 | ||||
|
116 | SPIMPL_CONSTEXPR impl_ptr() SPIMPL_NOEXCEPT : ptr_(nullptr, deleter_type{}), | |||
|
117 | copier_(copier_type{}) | |||
|
118 | { | |||
|
119 | } | |||
|
120 | ||||
|
121 | SPIMPL_CONSTEXPR impl_ptr(std::nullptr_t) SPIMPL_NOEXCEPT : impl_ptr() {} | |||
|
122 | ||||
|
123 | template <class D, class C> | |||
|
124 | impl_ptr(pointer p, D &&d, C &&c, | |||
|
125 | typename std::enable_if<std::is_convertible<D, deleter_type>::value | |||
|
126 | && std::is_convertible<C, copier_type>::value, | |||
|
127 | dummy_t_>::type | |||
|
128 | = dummy_t_()) SPIMPL_NOEXCEPT : ptr_(std::move(p), std::forward<D>(d)), | |||
|
129 | copier_(std::forward<C>(c)) | |||
|
130 | { | |||
|
131 | } | |||
|
132 | ||||
|
133 | template <class U> | |||
|
134 | impl_ptr(U *u, typename std::enable_if<std::is_convertible<U *, pointer>::value | |||
|
135 | && is_default_manageable::value, | |||
|
136 | dummy_t_>::type | |||
|
137 | = dummy_t_()) SPIMPL_NOEXCEPT | |||
|
138 | : impl_ptr(u, &details::default_delete<T>, &details::default_copy<T>) | |||
|
139 | { | |||
|
140 | } | |||
|
141 | ||||
|
142 | impl_ptr(const impl_ptr &r) : impl_ptr(r.clone()) {} | |||
|
143 | ||||
|
144 | #ifndef SPIMPL_NO_CPP11_DEFAULT_MOVE_SPEC_FUNC | |||
|
145 | impl_ptr(impl_ptr &&r) SPIMPL_NOEXCEPT = default; | |||
|
146 | #else | |||
|
147 | impl_ptr(impl_ptr &&r) SPIMPL_NOEXCEPT : ptr_(std::move(r.ptr_)), copier_(std::move(r.copier_)) | |||
|
148 | { | |||
|
149 | } | |||
|
150 | #endif | |||
|
151 | ||||
|
152 | #ifdef SPIMPL_HAS_AUTO_PTR | |||
|
153 | template <class U> | |||
|
154 | impl_ptr(std::auto_ptr<U> &&u, typename std::enable_if<std::is_convertible<U *, pointer>::value | |||
|
155 | && is_default_manageable::value, | |||
|
156 | dummy_t_>::type | |||
|
157 | = dummy_t_()) SPIMPL_NOEXCEPT | |||
|
158 | : ptr_(u.release(), &details::default_delete<T>), | |||
|
159 | copier_(&details::default_copy<T>) | |||
|
160 | { | |||
|
161 | } | |||
|
162 | #endif | |||
|
163 | ||||
|
164 | template <class U> | |||
|
165 | impl_ptr(std::unique_ptr<U> &&u, | |||
|
166 | typename std::enable_if<std::is_convertible<U *, pointer>::value | |||
|
167 | && is_default_manageable::value, | |||
|
168 | dummy_t_>::type | |||
|
169 | = dummy_t_()) SPIMPL_NOEXCEPT : ptr_(u.release(), &details::default_delete<T>), | |||
|
170 | copier_(&details::default_copy<T>) | |||
|
171 | { | |||
|
172 | } | |||
|
173 | ||||
|
174 | template <class U, class D, class C> | |||
|
175 | impl_ptr(std::unique_ptr<U, D> &&u, C &&c, | |||
|
176 | typename std::enable_if<std::is_convertible<U *, pointer>::value | |||
|
177 | && std::is_convertible<D, deleter_type>::value | |||
|
178 | && std::is_convertible<C, copier_type>::value, | |||
|
179 | dummy_t_>::type | |||
|
180 | = dummy_t_()) SPIMPL_NOEXCEPT : ptr_(std::move(u)), | |||
|
181 | copier_(std::forward<C>(c)) | |||
|
182 | { | |||
|
183 | } | |||
|
184 | ||||
|
185 | template <class U, class D, class C> | |||
|
186 | impl_ptr(impl_ptr<U, D, C> &&u, | |||
|
187 | typename std::enable_if<std::is_convertible<U *, pointer>::value | |||
|
188 | && std::is_convertible<D, deleter_type>::value | |||
|
189 | && std::is_convertible<C, copier_type>::value, | |||
|
190 | dummy_t_>::type | |||
|
191 | = dummy_t_()) SPIMPL_NOEXCEPT : ptr_(std::move(u.ptr_)), | |||
|
192 | copier_(std::move(u.copier_)) | |||
|
193 | { | |||
|
194 | } | |||
|
195 | ||||
|
196 | impl_ptr &operator=(const impl_ptr &r) | |||
|
197 | { | |||
|
198 | if (this == &r) | |||
|
199 | return *this; | |||
|
200 | ||||
|
201 | return operator=(r.clone()); | |||
|
202 | } | |||
|
203 | ||||
|
204 | #ifndef SPIMPL_NO_CPP11_DEFAULT_MOVE_SPEC_FUNC | |||
|
205 | impl_ptr &operator=(impl_ptr &&r) SPIMPL_NOEXCEPT = default; | |||
|
206 | #else | |||
|
207 | impl_ptr &operator=(impl_ptr &&r) SPIMPL_NOEXCEPT | |||
|
208 | { | |||
|
209 | ptr_ = std::move(r.ptr_); | |||
|
210 | copier_ = std::move(r.copier_); | |||
|
211 | return *this; | |||
|
212 | } | |||
|
213 | #endif | |||
|
214 | ||||
|
215 | template <class U, class D, class C> | |||
|
216 | typename std::enable_if<std::is_convertible<U *, pointer>::value | |||
|
217 | && std::is_convertible<D, deleter_type>::value | |||
|
218 | && std::is_convertible<C, copier_type>::value, | |||
|
219 | impl_ptr &>::type | |||
|
220 | operator=(impl_ptr<U, D, C> &&u) SPIMPL_NOEXCEPT | |||
|
221 | { | |||
|
222 | ptr_ = std::move(u.ptr_); | |||
|
223 | copier_ = std::move(u.copier_); | |||
|
224 | return *this; | |||
|
225 | } | |||
|
226 | ||||
|
227 | template <class U, class D, class C> | |||
|
228 | typename std::enable_if<std::is_convertible<U *, pointer>::value | |||
|
229 | && std::is_convertible<D, deleter_type>::value | |||
|
230 | && std::is_convertible<C, copier_type>::value, | |||
|
231 | impl_ptr &>::type | |||
|
232 | operator=(const impl_ptr<U, D, C> &u) | |||
|
233 | { | |||
|
234 | return operator=(u.clone()); | |||
|
235 | } | |||
|
236 | ||||
|
237 | // | |||
|
238 | ||||
|
239 | #ifdef SPIMPL_HAS_AUTO_PTR | |||
|
240 | template <class U> | |||
|
241 | typename std::enable_if<std::is_convertible<U *, pointer>::value | |||
|
242 | && is_default_manageable::value, | |||
|
243 | impl_ptr &>::type | |||
|
244 | operator=(std::auto_ptr<U> &&u) SPIMPL_NOEXCEPT | |||
|
245 | { | |||
|
246 | return operator=(impl_ptr(std::move(u))); | |||
|
247 | } | |||
|
248 | #endif | |||
|
249 | ||||
|
250 | template <class U> | |||
|
251 | typename std::enable_if<std::is_convertible<U *, pointer>::value | |||
|
252 | && is_default_manageable::value, | |||
|
253 | impl_ptr &>::type | |||
|
254 | operator=(std::unique_ptr<U> &&u) SPIMPL_NOEXCEPT | |||
|
255 | { | |||
|
256 | return operator=(impl_ptr(std::move(u))); | |||
|
257 | } | |||
|
258 | ||||
|
259 | impl_ptr clone() const | |||
|
260 | { | |||
|
261 | return impl_ptr(ptr_ ? copier_(ptr_.get()) : nullptr, ptr_.get_deleter(), copier_); | |||
|
262 | } | |||
|
263 | ||||
|
264 | typename std::remove_reference<T>::type &operator*() const { return *ptr_; } | |||
|
265 | pointer operator->() const SPIMPL_NOEXCEPT { return get(); } | |||
|
266 | pointer get() const SPIMPL_NOEXCEPT { return ptr_.get(); } | |||
|
267 | ||||
|
268 | void swap(impl_ptr &u) SPIMPL_NOEXCEPT | |||
|
269 | { | |||
|
270 | using std::swap; | |||
|
271 | ptr_.swap(u.ptr_); | |||
|
272 | swap(copier_, u.copier_); | |||
|
273 | } | |||
|
274 | ||||
|
275 | pointer release() SPIMPL_NOEXCEPT { return ptr_.release(); } | |||
|
276 | ||||
|
277 | unique_ptr_type release_unique() SPIMPL_NOEXCEPT { return std::move(ptr_); } | |||
|
278 | ||||
|
279 | explicit operator bool() const SPIMPL_NOEXCEPT { return static_cast<bool>(ptr_); } | |||
|
280 | ||||
|
281 | typename std::remove_reference<deleter_type>::type &get_deleter() SPIMPL_NOEXCEPT | |||
|
282 | { | |||
|
283 | return ptr_.get_deleter(); | |||
|
284 | } | |||
|
285 | const typename std::remove_reference<deleter_type>::type &get_deleter() const SPIMPL_NOEXCEPT | |||
|
286 | { | |||
|
287 | return ptr_.get_deleter(); | |||
|
288 | } | |||
|
289 | ||||
|
290 | typename std::remove_reference<copier_type>::type &get_copier() SPIMPL_NOEXCEPT | |||
|
291 | { | |||
|
292 | return copier_; | |||
|
293 | } | |||
|
294 | const typename std::remove_reference<copier_type>::type &get_copier() const SPIMPL_NOEXCEPT | |||
|
295 | { | |||
|
296 | return copier_; | |||
|
297 | } | |||
|
298 | ||||
|
299 | private: | |||
|
300 | unique_ptr_type ptr_; | |||
|
301 | copier_type copier_; | |||
|
302 | }; | |||
|
303 | ||||
|
304 | ||||
|
305 | template <class T, class D, class C> | |||
|
306 | inline void swap(impl_ptr<T, D, C> &l, impl_ptr<T, D, C> &r) SPIMPL_NOEXCEPT | |||
|
307 | { | |||
|
308 | l.swap(r); | |||
|
309 | } | |||
|
310 | ||||
|
311 | ||||
|
312 | template <class T1, class D1, class C1, class T2, class D2, class C2> | |||
|
313 | inline bool operator==(const impl_ptr<T1, D1, C1> &l, const impl_ptr<T2, D2, C2> &r) | |||
|
314 | { | |||
|
315 | return l.get() == r.get(); | |||
|
316 | } | |||
|
317 | ||||
|
318 | template <class T1, class D1, class C1, class T2, class D2, class C2> | |||
|
319 | inline bool operator!=(const impl_ptr<T1, D1, C1> &l, const impl_ptr<T2, D2, C2> &r) | |||
|
320 | { | |||
|
321 | return !(l == r); | |||
|
322 | } | |||
|
323 | ||||
|
324 | template <class T1, class D1, class C1, class T2, class D2, class C2> | |||
|
325 | inline bool operator<(const impl_ptr<T1, D1, C1> &l, const impl_ptr<T2, D2, C2> &r) | |||
|
326 | { | |||
|
327 | using P1 = typename impl_ptr<T1, D1, C1>::pointer; | |||
|
328 | using P2 = typename impl_ptr<T2, D2, C2>::pointer; | |||
|
329 | using CT = typename std::common_type<P1, P2>::type; | |||
|
330 | return std::less<CT>()(l.get(), r.get()); | |||
|
331 | } | |||
|
332 | ||||
|
333 | template <class T1, class D1, class C1, class T2, class D2, class C2> | |||
|
334 | inline bool operator>(const impl_ptr<T1, D1, C1> &l, const impl_ptr<T2, D2, C2> &r) | |||
|
335 | { | |||
|
336 | return r < l; | |||
|
337 | } | |||
|
338 | ||||
|
339 | template <class T1, class D1, class C1, class T2, class D2, class C2> | |||
|
340 | inline bool operator<=(const impl_ptr<T1, D1, C1> &l, const impl_ptr<T2, D2, C2> &r) | |||
|
341 | { | |||
|
342 | return !(r < l); | |||
|
343 | } | |||
|
344 | ||||
|
345 | template <class T1, class D1, class C1, class T2, class D2, class C2> | |||
|
346 | inline bool operator>=(const impl_ptr<T1, D1, C1> &l, const impl_ptr<T2, D2, C2> &r) | |||
|
347 | { | |||
|
348 | return !(l < r); | |||
|
349 | } | |||
|
350 | ||||
|
351 | template <class T, class D, class C> | |||
|
352 | inline bool operator==(const impl_ptr<T, D, C> &p, std::nullptr_t) SPIMPL_NOEXCEPT | |||
|
353 | { | |||
|
354 | return !p; | |||
|
355 | } | |||
|
356 | ||||
|
357 | template <class T, class D, class C> | |||
|
358 | inline bool operator==(std::nullptr_t, const impl_ptr<T, D, C> &p) SPIMPL_NOEXCEPT | |||
|
359 | { | |||
|
360 | return !p; | |||
|
361 | } | |||
|
362 | ||||
|
363 | template <class T, class D, class C> | |||
|
364 | inline bool operator!=(const impl_ptr<T, D, C> &p, std::nullptr_t) SPIMPL_NOEXCEPT | |||
|
365 | { | |||
|
366 | return static_cast<bool>(p); | |||
|
367 | } | |||
|
368 | ||||
|
369 | template <class T, class D, class C> | |||
|
370 | inline bool operator!=(std::nullptr_t, const impl_ptr<T, D, C> &p) SPIMPL_NOEXCEPT | |||
|
371 | { | |||
|
372 | return static_cast<bool>(p); | |||
|
373 | } | |||
|
374 | ||||
|
375 | template <class T, class D, class C> | |||
|
376 | inline bool operator<(const impl_ptr<T, D, C> &l, std::nullptr_t) | |||
|
377 | { | |||
|
378 | using P = typename impl_ptr<T, D, C>::pointer; | |||
|
379 | return std::less<P>()(l.get(), nullptr); | |||
|
380 | } | |||
|
381 | ||||
|
382 | template <class T, class D, class C> | |||
|
383 | inline bool operator<(std::nullptr_t, const impl_ptr<T, D, C> &p) | |||
|
384 | { | |||
|
385 | using P = typename impl_ptr<T, D, C>::pointer; | |||
|
386 | return std::less<P>()(nullptr, p.get()); | |||
|
387 | } | |||
|
388 | ||||
|
389 | template <class T, class D, class C> | |||
|
390 | inline bool operator>(const impl_ptr<T, D, C> &p, std::nullptr_t) | |||
|
391 | { | |||
|
392 | return nullptr < p; | |||
|
393 | } | |||
|
394 | ||||
|
395 | template <class T, class D, class C> | |||
|
396 | inline bool operator>(std::nullptr_t, const impl_ptr<T, D, C> &p) | |||
|
397 | { | |||
|
398 | return p < nullptr; | |||
|
399 | } | |||
|
400 | ||||
|
401 | template <class T, class D, class C> | |||
|
402 | inline bool operator<=(const impl_ptr<T, D, C> &p, std::nullptr_t) | |||
|
403 | { | |||
|
404 | return !(nullptr < p); | |||
|
405 | } | |||
|
406 | ||||
|
407 | template <class T, class D, class C> | |||
|
408 | inline bool operator<=(std::nullptr_t, const impl_ptr<T, D, C> &p) | |||
|
409 | { | |||
|
410 | return !(p < nullptr); | |||
|
411 | } | |||
|
412 | ||||
|
413 | template <class T, class D, class C> | |||
|
414 | inline bool operator>=(const impl_ptr<T, D, C> &p, std::nullptr_t) | |||
|
415 | { | |||
|
416 | return !(p < nullptr); | |||
|
417 | } | |||
|
418 | ||||
|
419 | template <class T, class D, class C> | |||
|
420 | inline bool operator>=(std::nullptr_t, const impl_ptr<T, D, C> &p) | |||
|
421 | { | |||
|
422 | return !(nullptr < p); | |||
|
423 | } | |||
|
424 | ||||
|
425 | ||||
|
426 | template <class T, class... Args> | |||
|
427 | inline impl_ptr<T> make_impl(Args &&... args) | |||
|
428 | { | |||
|
429 | return impl_ptr<T>(new T(std::forward<Args>(args)...), &details::default_delete<T>, | |||
|
430 | &details::default_copy<T>); | |||
|
431 | } | |||
|
432 | ||||
|
433 | ||||
|
434 | // Helpers to manage unique impl, stored in std::unique_ptr | |||
|
435 | ||||
|
436 | template <class T, class Deleter = void (*)(T *)> | |||
|
437 | using unique_impl_ptr = std::unique_ptr<T, Deleter>; | |||
|
438 | ||||
|
439 | template <class T, class... Args> | |||
|
440 | inline unique_impl_ptr<T> make_unique_impl(Args &&... args) | |||
|
441 | { | |||
|
442 | static_assert(!std::is_array<T>::value, "unique_impl_ptr does not support arrays"); | |||
|
443 | return unique_impl_ptr<T>(new T(std::forward<Args>(args)...), &details::default_delete<T>); | |||
|
444 | } | |||
|
445 | } | |||
|
446 | ||||
|
447 | namespace std { | |||
|
448 | template <class T, class D, class C> | |||
|
449 | struct hash<spimpl::impl_ptr<T, D, C> > { | |||
|
450 | using argument_type = spimpl::impl_ptr<T, D, C>; | |||
|
451 | using result_type = size_t; | |||
|
452 | ||||
|
453 | result_type operator()(const argument_type &p) const SPIMPL_NOEXCEPT | |||
|
454 | { | |||
|
455 | return hash<typename argument_type::pointer>()(p.get()); | |||
|
456 | } | |||
|
457 | }; | |||
|
458 | } | |||
|
459 | ||||
|
460 | #endif // SPIMPL_H_ |
@@ -0,0 +1,12 | |||||
|
1 | #ifndef SCIQLOP_COREGLOBAL_H | |||
|
2 | #define SCIQLOP_COREGLOBAL_H | |||
|
3 | ||||
|
4 | #include <QtCore/QtGlobal> | |||
|
5 | ||||
|
6 | #ifdef CORE_LIB | |||
|
7 | #define SCIQLOP_CORE_EXPORT Q_DECL_EXPORT | |||
|
8 | #else | |||
|
9 | #define SCIQLOP_CORE_EXPORT Q_DECL_IMPORT | |||
|
10 | #endif | |||
|
11 | ||||
|
12 | #endif // SCIQLOP_COREGLOBAL_H |
@@ -0,0 +1,25 | |||||
|
1 | #ifndef SCIQLOP_ACQUISITIONDATAPACKET_H | |||
|
2 | #define SCIQLOP_ACQUISITIONDATAPACKET_H | |||
|
3 | ||||
|
4 | #include <QObject> | |||
|
5 | ||||
|
6 | #include <Common/DateUtils.h> | |||
|
7 | #include <Common/MetaTypes.h> | |||
|
8 | #include <Data/IDataSeries.h> | |||
|
9 | #include <Data/DateTimeRange.h> | |||
|
10 | ||||
|
11 | #include <memory> | |||
|
12 | ||||
|
13 | /** | |||
|
14 | * @brief The AcquisitionDataPacket struct holds the information of an acquisition request result | |||
|
15 | * part. | |||
|
16 | */ | |||
|
17 | struct AcquisitionDataPacket { | |||
|
18 | std::shared_ptr<IDataSeries> m_DateSeries; | |||
|
19 | DateTimeRange m_Range; | |||
|
20 | }; | |||
|
21 | ||||
|
22 | SCIQLOP_REGISTER_META_TYPE(ACQUISITIONDATAPACKET_REGISTRY, AcquisitionDataPacket) | |||
|
23 | SCIQLOP_REGISTER_META_TYPE(ACQUISITIONDATAPACKETVECTOR_REGISTRY, QVector<AcquisitionDataPacket>) | |||
|
24 | ||||
|
25 | #endif // SCIQLOP_ACQUISITIONREQUEST_H |
@@ -0,0 +1,40 | |||||
|
1 | #ifndef SCIQLOP_ACQUISITIONREQUEST_H | |||
|
2 | #define SCIQLOP_ACQUISITIONREQUEST_H | |||
|
3 | ||||
|
4 | #include <QObject> | |||
|
5 | ||||
|
6 | #include <QUuid> | |||
|
7 | ||||
|
8 | #include <Common/DateUtils.h> | |||
|
9 | #include <Common/MetaTypes.h> | |||
|
10 | #include <Data/DataProviderParameters.h> | |||
|
11 | #include <Data/IDataProvider.h> | |||
|
12 | #include <Data/DateTimeRange.h> | |||
|
13 | ||||
|
14 | #include <memory> | |||
|
15 | ||||
|
16 | /** | |||
|
17 | * @brief The AcquisitionRequest struct holds the information of an variable request | |||
|
18 | */ | |||
|
19 | struct AcquisitionRequest { | |||
|
20 | AcquisitionRequest() | |||
|
21 | { | |||
|
22 | m_AcqIdentifier = QUuid::createUuid(); | |||
|
23 | m_Size = 0; | |||
|
24 | m_Progression = 0; | |||
|
25 | } | |||
|
26 | ||||
|
27 | QUuid m_VarRequestId; | |||
|
28 | QUuid m_AcqIdentifier; | |||
|
29 | QUuid m_vIdentifier; | |||
|
30 | DataProviderParameters m_DataProviderParameters; | |||
|
31 | DateTimeRange m_RangeRequested; | |||
|
32 | DateTimeRange m_CacheRangeRequested; | |||
|
33 | int m_Size; | |||
|
34 | int m_Progression; | |||
|
35 | std::shared_ptr<IDataProvider> m_Provider; | |||
|
36 | }; | |||
|
37 | ||||
|
38 | SCIQLOP_REGISTER_META_TYPE(ACQUISITIONREQUEST_REGISTRY, AcquisitionRequest) | |||
|
39 | ||||
|
40 | #endif // SCIQLOP_ACQUISITIONREQUEST_H |
@@ -0,0 +1,373 | |||||
|
1 | #ifndef SCIQLOP_ARRAYDATA_H | |||
|
2 | #define SCIQLOP_ARRAYDATA_H | |||
|
3 | ||||
|
4 | #include "Data/ArrayDataIterator.h" | |||
|
5 | #include <Common/SortUtils.h> | |||
|
6 | ||||
|
7 | #include <QReadLocker> | |||
|
8 | #include <QReadWriteLock> | |||
|
9 | #include <QVector> | |||
|
10 | ||||
|
11 | #include <memory> | |||
|
12 | ||||
|
13 | template <int Dim> | |||
|
14 | class ArrayData; | |||
|
15 | ||||
|
16 | using DataContainer = std::vector<double>; | |||
|
17 | ||||
|
18 | namespace arraydata_detail { | |||
|
19 | ||||
|
20 | /// Struct used to sort ArrayData | |||
|
21 | template <int Dim> | |||
|
22 | struct Sort { | |||
|
23 | static std::shared_ptr<ArrayData<Dim> > sort(const DataContainer &data, int nbComponents, | |||
|
24 | const std::vector<int> &sortPermutation) | |||
|
25 | { | |||
|
26 | return std::make_shared<ArrayData<Dim> >( | |||
|
27 | SortUtils::sort(data, nbComponents, sortPermutation), nbComponents); | |||
|
28 | } | |||
|
29 | }; | |||
|
30 | ||||
|
31 | /// Specialization for uni-dimensional ArrayData | |||
|
32 | template <> | |||
|
33 | struct Sort<1> { | |||
|
34 | static std::shared_ptr<ArrayData<1> > sort(const DataContainer &data, int nbComponents, | |||
|
35 | const std::vector<int> &sortPermutation) | |||
|
36 | { | |||
|
37 | Q_UNUSED(nbComponents) | |||
|
38 | return std::make_shared<ArrayData<1> >(SortUtils::sort(data, 1, sortPermutation)); | |||
|
39 | } | |||
|
40 | }; | |||
|
41 | ||||
|
42 | template <int Dim, bool IsConst> | |||
|
43 | class IteratorValue; | |||
|
44 | ||||
|
45 | template <int Dim, bool IsConst> | |||
|
46 | struct IteratorValueBuilder { | |||
|
47 | }; | |||
|
48 | ||||
|
49 | template <int Dim> | |||
|
50 | struct IteratorValueBuilder<Dim, true> { | |||
|
51 | using DataContainerIterator = DataContainer::const_iterator; | |||
|
52 | ||||
|
53 | static void swap(IteratorValue<Dim, true> &o1, IteratorValue<Dim, true> &o2) {} | |||
|
54 | }; | |||
|
55 | ||||
|
56 | template <int Dim> | |||
|
57 | struct IteratorValueBuilder<Dim, false> { | |||
|
58 | using DataContainerIterator = DataContainer::iterator; | |||
|
59 | ||||
|
60 | static void swap(IteratorValue<Dim, false> &o1, IteratorValue<Dim, false> &o2) | |||
|
61 | { | |||
|
62 | for (auto i = 0; i < o1.m_NbComponents; ++i) { | |||
|
63 | std::iter_swap(o1.m_It + i, o2.m_It + i); | |||
|
64 | } | |||
|
65 | } | |||
|
66 | }; | |||
|
67 | ||||
|
68 | template <int Dim, bool IsConst> | |||
|
69 | class IteratorValue : public ArrayDataIteratorValue::Impl { | |||
|
70 | public: | |||
|
71 | friend class ArrayData<Dim>; | |||
|
72 | friend class IteratorValueBuilder<Dim, IsConst>; | |||
|
73 | ||||
|
74 | using DataContainerIterator = | |||
|
75 | typename IteratorValueBuilder<Dim, IsConst>::DataContainerIterator; | |||
|
76 | ||||
|
77 | template <bool IC = IsConst, typename = std::enable_if_t<IC == true> > | |||
|
78 | explicit IteratorValue(const DataContainer &container, int nbComponents, bool begin) | |||
|
79 | : m_It{begin ? container.cbegin() : container.cend()}, m_NbComponents{nbComponents} | |||
|
80 | { | |||
|
81 | } | |||
|
82 | ||||
|
83 | template <bool IC = IsConst, typename = std::enable_if_t<IC == false> > | |||
|
84 | explicit IteratorValue(DataContainer &container, int nbComponents, bool begin) | |||
|
85 | : m_It{begin ? container.begin() : container.end()}, m_NbComponents{nbComponents} | |||
|
86 | { | |||
|
87 | } | |||
|
88 | ||||
|
89 | IteratorValue(const IteratorValue &other) = default; | |||
|
90 | ||||
|
91 | std::unique_ptr<ArrayDataIteratorValue::Impl> clone() const override | |||
|
92 | { | |||
|
93 | return std::make_unique<IteratorValue<Dim, IsConst> >(*this); | |||
|
94 | } | |||
|
95 | ||||
|
96 | int distance(const ArrayDataIteratorValue::Impl &other) const override try { | |||
|
97 | const auto &otherImpl = dynamic_cast<const IteratorValue &>(other); | |||
|
98 | return std::distance(otherImpl.m_It, m_It) / m_NbComponents; | |||
|
99 | } | |||
|
100 | catch (const std::bad_cast &) { | |||
|
101 | return 0; | |||
|
102 | } | |||
|
103 | ||||
|
104 | bool equals(const ArrayDataIteratorValue::Impl &other) const override try { | |||
|
105 | const auto &otherImpl = dynamic_cast<const IteratorValue &>(other); | |||
|
106 | return std::tie(m_It, m_NbComponents) == std::tie(otherImpl.m_It, otherImpl.m_NbComponents); | |||
|
107 | } | |||
|
108 | catch (const std::bad_cast &) { | |||
|
109 | return false; | |||
|
110 | } | |||
|
111 | ||||
|
112 | bool lowerThan(const ArrayDataIteratorValue::Impl &other) const override try { | |||
|
113 | const auto &otherImpl = dynamic_cast<const IteratorValue &>(other); | |||
|
114 | return m_It < otherImpl.m_It; | |||
|
115 | } | |||
|
116 | catch (const std::bad_cast &) { | |||
|
117 | return false; | |||
|
118 | } | |||
|
119 | ||||
|
120 | std::unique_ptr<ArrayDataIteratorValue::Impl> advance(int offset) const override | |||
|
121 | { | |||
|
122 | auto result = clone(); | |||
|
123 | result->next(offset); | |||
|
124 | return result; | |||
|
125 | } | |||
|
126 | ||||
|
127 | void next(int offset) override { std::advance(m_It, offset * m_NbComponents); } | |||
|
128 | void prev() override { std::advance(m_It, -m_NbComponents); } | |||
|
129 | ||||
|
130 | double at(int componentIndex) const override { return *(m_It + componentIndex); } | |||
|
131 | double first() const override { return *m_It; } | |||
|
132 | double min() const override | |||
|
133 | { | |||
|
134 | auto values = this->values(); | |||
|
135 | auto end = values.cend(); | |||
|
136 | auto it = std::min_element(values.cbegin(), end, [](const auto &v1, const auto &v2) { | |||
|
137 | return SortUtils::minCompareWithNaN(v1, v2); | |||
|
138 | }); | |||
|
139 | ||||
|
140 | return it != end ? *it : std::numeric_limits<double>::quiet_NaN(); | |||
|
141 | } | |||
|
142 | double max() const override | |||
|
143 | { | |||
|
144 | auto values = this->values(); | |||
|
145 | auto end = values.cend(); | |||
|
146 | auto it = std::max_element(values.cbegin(), end, [](const auto &v1, const auto &v2) { | |||
|
147 | return SortUtils::maxCompareWithNaN(v1, v2); | |||
|
148 | }); | |||
|
149 | return it != end ? *it : std::numeric_limits<double>::quiet_NaN(); | |||
|
150 | } | |||
|
151 | ||||
|
152 | QVector<double> values() const override | |||
|
153 | { | |||
|
154 | auto result = QVector<double>{}; | |||
|
155 | for (auto i = 0; i < m_NbComponents; ++i) { | |||
|
156 | result.push_back(*(m_It + i)); | |||
|
157 | } | |||
|
158 | ||||
|
159 | return result; | |||
|
160 | } | |||
|
161 | ||||
|
162 | void swap(ArrayDataIteratorValue::Impl &other) override | |||
|
163 | { | |||
|
164 | auto &otherImpl = dynamic_cast<IteratorValue &>(other); | |||
|
165 | IteratorValueBuilder<Dim, IsConst>::swap(*this, otherImpl); | |||
|
166 | } | |||
|
167 | ||||
|
168 | private: | |||
|
169 | DataContainerIterator m_It; | |||
|
170 | int m_NbComponents; | |||
|
171 | }; | |||
|
172 | ||||
|
173 | } // namespace arraydata_detail | |||
|
174 | ||||
|
175 | /** | |||
|
176 | * @brief The ArrayData class represents a dataset for a data series. | |||
|
177 | * | |||
|
178 | * A dataset can be unidimensional or two-dimensional. This property is determined by the Dim | |||
|
179 | * template-parameter. In a case of a two-dimensional dataset, each dataset component has the same | |||
|
180 | * number of values | |||
|
181 | * | |||
|
182 | * @tparam Dim the dimension of the ArrayData (one or two) | |||
|
183 | * @sa IDataSeries | |||
|
184 | */ | |||
|
185 | template <int Dim> | |||
|
186 | class ArrayData { | |||
|
187 | public: | |||
|
188 | // ///// // | |||
|
189 | // Ctors // | |||
|
190 | // ///// // | |||
|
191 | ||||
|
192 | /** | |||
|
193 | * Ctor for a unidimensional ArrayData | |||
|
194 | * @param data the data the ArrayData will hold | |||
|
195 | */ | |||
|
196 | template <int D = Dim, typename = std::enable_if_t<D == 1> > | |||
|
197 | explicit ArrayData(DataContainer data) : m_Data{std::move(data)}, m_NbComponents{1} | |||
|
198 | { | |||
|
199 | } | |||
|
200 | ||||
|
201 | /** | |||
|
202 | * Ctor for a two-dimensional ArrayData. The number of components (number of lines) must be | |||
|
203 | * greater than 2 and must be a divisor of the total number of data in the vector | |||
|
204 | * @param data the data the ArrayData will hold | |||
|
205 | * @param nbComponents the number of components | |||
|
206 | * @throws std::invalid_argument if the number of components is less than 2 or is not a divisor | |||
|
207 | * of the size of the data | |||
|
208 | */ | |||
|
209 | template <int D = Dim, typename = std::enable_if_t<D == 2> > | |||
|
210 | explicit ArrayData(DataContainer data, int nbComponents) | |||
|
211 | : m_Data{std::move(data)}, m_NbComponents{nbComponents} | |||
|
212 | { | |||
|
213 | if (nbComponents < 2) { | |||
|
214 | throw std::invalid_argument{ | |||
|
215 | QString{"A multidimensional ArrayData must have at least 2 components (found: %1)"} | |||
|
216 | .arg(nbComponents) | |||
|
217 | .toStdString()}; | |||
|
218 | } | |||
|
219 | ||||
|
220 | if (m_Data.size() % m_NbComponents != 0) { | |||
|
221 | throw std::invalid_argument{QString{ | |||
|
222 | "The number of components (%1) is inconsistent with the total number of data (%2)"} | |||
|
223 | .arg(m_Data.size(), nbComponents) | |||
|
224 | .toStdString()}; | |||
|
225 | } | |||
|
226 | } | |||
|
227 | ||||
|
228 | /// Copy ctor | |||
|
229 | explicit ArrayData(const ArrayData &other) | |||
|
230 | { | |||
|
231 | QReadLocker otherLocker{&other.m_Lock}; | |||
|
232 | m_Data = other.m_Data; | |||
|
233 | m_NbComponents = other.m_NbComponents; | |||
|
234 | } | |||
|
235 | ||||
|
236 | // /////////////// // | |||
|
237 | // General methods // | |||
|
238 | // /////////////// // | |||
|
239 | ||||
|
240 | /** | |||
|
241 | * Merges into the array data an other array data. The two array datas must have the same number | |||
|
242 | * of components so the merge can be done | |||
|
243 | * @param other the array data to merge with | |||
|
244 | * @param prepend if true, the other array data is inserted at the beginning, otherwise it is | |||
|
245 | * inserted at the end | |||
|
246 | */ | |||
|
247 | void add(const ArrayData<Dim> &other, bool prepend = false) | |||
|
248 | { | |||
|
249 | QWriteLocker locker{&m_Lock}; | |||
|
250 | QReadLocker otherLocker{&other.m_Lock}; | |||
|
251 | ||||
|
252 | if (m_NbComponents != other.componentCount()) { | |||
|
253 | return; | |||
|
254 | } | |||
|
255 | ||||
|
256 | insert(other.cbegin(), other.cend(), prepend); | |||
|
257 | } | |||
|
258 | ||||
|
259 | void clear() | |||
|
260 | { | |||
|
261 | QWriteLocker locker{&m_Lock}; | |||
|
262 | m_Data.clear(); | |||
|
263 | } | |||
|
264 | ||||
|
265 | int componentCount() const noexcept { return m_NbComponents; } | |||
|
266 | ||||
|
267 | /// @return the size (i.e. number of values) of a single component | |||
|
268 | /// @remarks in a case of a two-dimensional ArrayData, each component has the same size | |||
|
269 | int size() const | |||
|
270 | { | |||
|
271 | QReadLocker locker{&m_Lock}; | |||
|
272 | return m_Data.size() / m_NbComponents; | |||
|
273 | } | |||
|
274 | ||||
|
275 | /// @return the total size (i.e. number of values) of the array data | |||
|
276 | int totalSize() const | |||
|
277 | { | |||
|
278 | QReadLocker locker{&m_Lock}; | |||
|
279 | return m_Data.size(); | |||
|
280 | } | |||
|
281 | ||||
|
282 | std::shared_ptr<ArrayData<Dim> > sort(const std::vector<int> &sortPermutation) | |||
|
283 | { | |||
|
284 | QReadLocker locker{&m_Lock}; | |||
|
285 | return arraydata_detail::Sort<Dim>::sort(m_Data, m_NbComponents, sortPermutation); | |||
|
286 | } | |||
|
287 | ||||
|
288 | // ///////// // | |||
|
289 | // Iterators // | |||
|
290 | // ///////// // | |||
|
291 | ||||
|
292 | ArrayDataIterator begin() | |||
|
293 | { | |||
|
294 | return ArrayDataIterator{ | |||
|
295 | ArrayDataIteratorValue{std::make_unique<arraydata_detail::IteratorValue<Dim, false> >( | |||
|
296 | m_Data, m_NbComponents, true)}}; | |||
|
297 | } | |||
|
298 | ||||
|
299 | ArrayDataIterator end() | |||
|
300 | { | |||
|
301 | return ArrayDataIterator{ | |||
|
302 | ArrayDataIteratorValue{std::make_unique<arraydata_detail::IteratorValue<Dim, false> >( | |||
|
303 | m_Data, m_NbComponents, false)}}; | |||
|
304 | } | |||
|
305 | ||||
|
306 | ArrayDataIterator cbegin() const | |||
|
307 | { | |||
|
308 | return ArrayDataIterator{ | |||
|
309 | ArrayDataIteratorValue{std::make_unique<arraydata_detail::IteratorValue<Dim, true> >( | |||
|
310 | m_Data, m_NbComponents, true)}}; | |||
|
311 | } | |||
|
312 | ||||
|
313 | ArrayDataIterator cend() const | |||
|
314 | { | |||
|
315 | return ArrayDataIterator{ | |||
|
316 | ArrayDataIteratorValue{std::make_unique<arraydata_detail::IteratorValue<Dim, true> >( | |||
|
317 | m_Data, m_NbComponents, false)}}; | |||
|
318 | } | |||
|
319 | ||||
|
320 | void erase(ArrayDataIterator first, ArrayDataIterator last) | |||
|
321 | { | |||
|
322 | auto firstImpl = dynamic_cast<arraydata_detail::IteratorValue<Dim, false> *>(first->impl()); | |||
|
323 | auto lastImpl = dynamic_cast<arraydata_detail::IteratorValue<Dim, false> *>(last->impl()); | |||
|
324 | ||||
|
325 | if (firstImpl && lastImpl) { | |||
|
326 | m_Data.erase(firstImpl->m_It, lastImpl->m_It); | |||
|
327 | } | |||
|
328 | } | |||
|
329 | ||||
|
330 | void insert(ArrayDataIterator first, ArrayDataIterator last, bool prepend = false) | |||
|
331 | { | |||
|
332 | auto firstImpl = dynamic_cast<arraydata_detail::IteratorValue<Dim, true> *>(first->impl()); | |||
|
333 | auto lastImpl = dynamic_cast<arraydata_detail::IteratorValue<Dim, true> *>(last->impl()); | |||
|
334 | ||||
|
335 | if (firstImpl && lastImpl) { | |||
|
336 | auto insertIt = prepend ? m_Data.begin() : m_Data.end(); | |||
|
337 | ||||
|
338 | m_Data.insert(insertIt, firstImpl->m_It, lastImpl->m_It); | |||
|
339 | } | |||
|
340 | } | |||
|
341 | ||||
|
342 | /** | |||
|
343 | * @return the data at a specified index | |||
|
344 | * @remarks index must be a valid position | |||
|
345 | */ | |||
|
346 | double at(int index) const noexcept | |||
|
347 | { | |||
|
348 | QReadLocker locker{&m_Lock}; | |||
|
349 | return m_Data.at(index); | |||
|
350 | } | |||
|
351 | ||||
|
352 | // ///////////// // | |||
|
353 | // 1-dim methods // | |||
|
354 | // ///////////// // | |||
|
355 | ||||
|
356 | /** | |||
|
357 | * @return the data as a vector, as a const reference | |||
|
358 | * @remarks this method is only available for a unidimensional ArrayData | |||
|
359 | */ | |||
|
360 | template <int D = Dim, typename = std::enable_if_t<D == 1> > | |||
|
361 | DataContainer cdata() const noexcept | |||
|
362 | { | |||
|
363 | return m_Data; | |||
|
364 | } | |||
|
365 | ||||
|
366 | private: | |||
|
367 | DataContainer m_Data; | |||
|
368 | /// Number of components (lines). Is always 1 in a 1-dim ArrayData | |||
|
369 | int m_NbComponents; | |||
|
370 | mutable QReadWriteLock m_Lock; | |||
|
371 | }; | |||
|
372 | ||||
|
373 | #endif // SCIQLOP_ARRAYDATA_H |
@@ -0,0 +1,74 | |||||
|
1 | #ifndef SCIQLOP_ARRAYDATAITERATOR_H | |||
|
2 | #define SCIQLOP_ARRAYDATAITERATOR_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | #include "Data/SqpIterator.h" | |||
|
6 | ||||
|
7 | #include <QVector> | |||
|
8 | #include <memory> | |||
|
9 | ||||
|
10 | /** | |||
|
11 | * @brief The ArrayDataIteratorValue class represents the current value of an array data iterator. | |||
|
12 | * It offers standard access methods for the data in the series (at(), first()), but it is up to | |||
|
13 | * each array data to define its own implementation of how to retrieve this data (one-dim or two-dim | |||
|
14 | * array), by implementing the ArrayDataIteratorValue::Impl interface | |||
|
15 | * @sa ArrayDataIterator | |||
|
16 | */ | |||
|
17 | class SCIQLOP_CORE_EXPORT ArrayDataIteratorValue { | |||
|
18 | public: | |||
|
19 | struct Impl { | |||
|
20 | virtual ~Impl() noexcept = default; | |||
|
21 | virtual std::unique_ptr<Impl> clone() const = 0; | |||
|
22 | virtual int distance(const Impl &other) const = 0; | |||
|
23 | virtual bool equals(const Impl &other) const = 0; | |||
|
24 | virtual bool lowerThan(const Impl &other) const = 0; | |||
|
25 | virtual std::unique_ptr<Impl> advance(int offset) const = 0; | |||
|
26 | virtual void next(int offset) = 0; | |||
|
27 | virtual void prev() = 0; | |||
|
28 | virtual double at(int componentIndex) const = 0; | |||
|
29 | virtual double first() const = 0; | |||
|
30 | virtual double min() const = 0; | |||
|
31 | virtual double max() const = 0; | |||
|
32 | virtual QVector<double> values() const = 0; | |||
|
33 | ||||
|
34 | virtual void swap(Impl &other) = 0; | |||
|
35 | }; | |||
|
36 | ||||
|
37 | explicit ArrayDataIteratorValue(std::unique_ptr<Impl> impl); | |||
|
38 | ArrayDataIteratorValue(const ArrayDataIteratorValue &other); | |||
|
39 | ArrayDataIteratorValue &operator=(ArrayDataIteratorValue other); | |||
|
40 | ||||
|
41 | int distance(const ArrayDataIteratorValue &other) const; | |||
|
42 | bool equals(const ArrayDataIteratorValue &other) const; | |||
|
43 | bool lowerThan(const ArrayDataIteratorValue &other) const; | |||
|
44 | ||||
|
45 | ArrayDataIteratorValue advance(int offset) const; | |||
|
46 | /// Advances to the next value | |||
|
47 | void next(int offset = 1); | |||
|
48 | /// Moves back to the previous value | |||
|
49 | void prev(); | |||
|
50 | /// Gets value of a specified component | |||
|
51 | double at(int componentIndex) const; | |||
|
52 | /// Gets value of first component | |||
|
53 | double first() const; | |||
|
54 | /// Gets min value among all components | |||
|
55 | double min() const; | |||
|
56 | /// Gets max value among all components | |||
|
57 | double max() const; | |||
|
58 | /// Gets all values | |||
|
59 | QVector<double> values() const; | |||
|
60 | ||||
|
61 | Impl *impl(); | |||
|
62 | ||||
|
63 | friend void swap(ArrayDataIteratorValue &lhs, ArrayDataIteratorValue &rhs) | |||
|
64 | { | |||
|
65 | std::swap(lhs.m_Impl, rhs.m_Impl); | |||
|
66 | } | |||
|
67 | ||||
|
68 | private: | |||
|
69 | std::unique_ptr<Impl> m_Impl; | |||
|
70 | }; | |||
|
71 | ||||
|
72 | using ArrayDataIterator = SqpIterator<ArrayDataIteratorValue>; | |||
|
73 | ||||
|
74 | #endif // SCIQLOP_ARRAYDATAITERATOR_H |
@@ -0,0 +1,18 | |||||
|
1 | #ifndef SCIQLOP_DATAPROVIDERPARAMETERS_H | |||
|
2 | #define SCIQLOP_DATAPROVIDERPARAMETERS_H | |||
|
3 | ||||
|
4 | #include "DateTimeRange.h" | |||
|
5 | ||||
|
6 | /** | |||
|
7 | * @brief The DataProviderParameters struct holds the information needed to retrieve data from a | |||
|
8 | * data provider | |||
|
9 | * @sa IDataProvider | |||
|
10 | */ | |||
|
11 | struct DataProviderParameters { | |||
|
12 | /// Times for which retrieve data | |||
|
13 | QVector<DateTimeRange> m_Times; | |||
|
14 | /// Extra data that can be used by the provider to retrieve data | |||
|
15 | QVariantHash m_Data; | |||
|
16 | }; | |||
|
17 | ||||
|
18 | #endif // SCIQLOP_DATAPROVIDERPARAMETERS_H |
This diff has been collapsed as it changes many lines, (507 lines changed) Show them Hide them | |||||
@@ -0,0 +1,507 | |||||
|
1 | #ifndef SCIQLOP_DATASERIES_H | |||
|
2 | #define SCIQLOP_DATASERIES_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <Common/SortUtils.h> | |||
|
7 | ||||
|
8 | #include <Data/ArrayData.h> | |||
|
9 | #include <Data/DataSeriesMergeHelper.h> | |||
|
10 | #include <Data/IDataSeries.h> | |||
|
11 | #include <Data/OptionalAxis.h> | |||
|
12 | ||||
|
13 | #include <QLoggingCategory> | |||
|
14 | #include <QReadLocker> | |||
|
15 | #include <QReadWriteLock> | |||
|
16 | #include <memory> | |||
|
17 | ||||
|
18 | // We don't use the Qt macro since the log is used in the header file, which causes multiple log | |||
|
19 | // definitions with inheritance. Inline method is used instead | |||
|
20 | inline const QLoggingCategory &LOG_DataSeries() | |||
|
21 | { | |||
|
22 | static const QLoggingCategory category{"DataSeries"}; | |||
|
23 | return category; | |||
|
24 | } | |||
|
25 | ||||
|
26 | template <int Dim> | |||
|
27 | class DataSeries; | |||
|
28 | ||||
|
29 | namespace dataseries_detail { | |||
|
30 | ||||
|
31 | template <int Dim, bool IsConst> | |||
|
32 | class IteratorValue : public DataSeriesIteratorValue::Impl { | |||
|
33 | public: | |||
|
34 | friend class DataSeries<Dim>; | |||
|
35 | ||||
|
36 | template <bool IC = IsConst, typename = std::enable_if_t<IC == false> > | |||
|
37 | explicit IteratorValue(DataSeries<Dim> &dataSeries, bool begin) | |||
|
38 | : m_XIt(begin ? dataSeries.xAxisData()->begin() : dataSeries.xAxisData()->end()), | |||
|
39 | m_ValuesIt(begin ? dataSeries.valuesData()->begin() : dataSeries.valuesData()->end()), | |||
|
40 | m_YItBegin{dataSeries.yAxis().begin()}, | |||
|
41 | m_YItEnd{dataSeries.yAxis().end()} | |||
|
42 | { | |||
|
43 | } | |||
|
44 | ||||
|
45 | template <bool IC = IsConst, typename = std::enable_if_t<IC == true> > | |||
|
46 | explicit IteratorValue(const DataSeries<Dim> &dataSeries, bool begin) | |||
|
47 | : m_XIt(begin ? dataSeries.xAxisData()->cbegin() : dataSeries.xAxisData()->cend()), | |||
|
48 | m_ValuesIt(begin ? dataSeries.valuesData()->cbegin() | |||
|
49 | : dataSeries.valuesData()->cend()), | |||
|
50 | m_YItBegin{dataSeries.yAxis().cbegin()}, | |||
|
51 | m_YItEnd{dataSeries.yAxis().cend()} | |||
|
52 | { | |||
|
53 | } | |||
|
54 | ||||
|
55 | IteratorValue(const IteratorValue &other) = default; | |||
|
56 | ||||
|
57 | std::unique_ptr<DataSeriesIteratorValue::Impl> clone() const override | |||
|
58 | { | |||
|
59 | return std::make_unique<IteratorValue<Dim, IsConst> >(*this); | |||
|
60 | } | |||
|
61 | ||||
|
62 | int distance(const DataSeriesIteratorValue::Impl &other) const override try { | |||
|
63 | const auto &otherImpl = dynamic_cast<const IteratorValue &>(other); | |||
|
64 | return m_XIt->distance(*otherImpl.m_XIt); | |||
|
65 | } | |||
|
66 | catch (const std::bad_cast &) { | |||
|
67 | return 0; | |||
|
68 | } | |||
|
69 | ||||
|
70 | bool equals(const DataSeriesIteratorValue::Impl &other) const override try { | |||
|
71 | const auto &otherImpl = dynamic_cast<const IteratorValue &>(other); | |||
|
72 | return std::tie(m_XIt, m_ValuesIt, m_YItBegin, m_YItEnd) | |||
|
73 | == std::tie(otherImpl.m_XIt, otherImpl.m_ValuesIt, otherImpl.m_YItBegin, | |||
|
74 | otherImpl.m_YItEnd); | |||
|
75 | } | |||
|
76 | catch (const std::bad_cast &) { | |||
|
77 | return false; | |||
|
78 | } | |||
|
79 | ||||
|
80 | bool lowerThan(const DataSeriesIteratorValue::Impl &other) const override try { | |||
|
81 | const auto &otherImpl = dynamic_cast<const IteratorValue &>(other); | |||
|
82 | return m_XIt->lowerThan(*otherImpl.m_XIt); | |||
|
83 | } | |||
|
84 | catch (const std::bad_cast &) { | |||
|
85 | return false; | |||
|
86 | } | |||
|
87 | ||||
|
88 | std::unique_ptr<DataSeriesIteratorValue::Impl> advance(int offset) const override | |||
|
89 | { | |||
|
90 | auto result = clone(); | |||
|
91 | result->next(offset); | |||
|
92 | return result; | |||
|
93 | } | |||
|
94 | ||||
|
95 | void next(int offset) override | |||
|
96 | { | |||
|
97 | m_XIt->next(offset); | |||
|
98 | m_ValuesIt->next(offset); | |||
|
99 | } | |||
|
100 | ||||
|
101 | void prev() override | |||
|
102 | { | |||
|
103 | --m_XIt; | |||
|
104 | --m_ValuesIt; | |||
|
105 | } | |||
|
106 | ||||
|
107 | double x() const override { return m_XIt->at(0); } | |||
|
108 | std::vector<double> y() const override | |||
|
109 | { | |||
|
110 | std::vector<double> result{}; | |||
|
111 | std::transform(m_YItBegin, m_YItEnd, std::back_inserter(result), | |||
|
112 | [](const auto &it) { return it.first(); }); | |||
|
113 | ||||
|
114 | return result; | |||
|
115 | } | |||
|
116 | ||||
|
117 | double value() const override { return m_ValuesIt->at(0); } | |||
|
118 | double value(int componentIndex) const override { return m_ValuesIt->at(componentIndex); } | |||
|
119 | double minValue() const override { return m_ValuesIt->min(); } | |||
|
120 | double maxValue() const override { return m_ValuesIt->max(); } | |||
|
121 | QVector<double> values() const override { return m_ValuesIt->values(); } | |||
|
122 | ||||
|
123 | void swap(DataSeriesIteratorValue::Impl &other) override | |||
|
124 | { | |||
|
125 | auto &otherImpl = dynamic_cast<IteratorValue &>(other); | |||
|
126 | m_XIt->impl()->swap(*otherImpl.m_XIt->impl()); | |||
|
127 | m_ValuesIt->impl()->swap(*otherImpl.m_ValuesIt->impl()); | |||
|
128 | m_YItBegin->impl()->swap(*otherImpl.m_YItBegin->impl()); | |||
|
129 | m_YItEnd->impl()->swap(*otherImpl.m_YItEnd->impl()); | |||
|
130 | } | |||
|
131 | ||||
|
132 | private: | |||
|
133 | ArrayDataIterator m_XIt; | |||
|
134 | ArrayDataIterator m_ValuesIt; | |||
|
135 | ArrayDataIterator m_YItBegin; | |||
|
136 | ArrayDataIterator m_YItEnd; | |||
|
137 | }; | |||
|
138 | } // namespace dataseries_detail | |||
|
139 | ||||
|
140 | /** | |||
|
141 | * @brief The DataSeries class is the base (abstract) implementation of IDataSeries. | |||
|
142 | * | |||
|
143 | * The DataSeries represents values on one or two axes, according to these rules: | |||
|
144 | * - the x-axis is always defined | |||
|
145 | * - an y-axis can be defined or not. If set, additional consistency checks apply to the values (see | |||
|
146 | * below) | |||
|
147 | * - the values are defined on one or two dimensions. In the case of 2-dim values, the data is | |||
|
148 | * distributed into components (for example, a vector defines three components) | |||
|
149 | * - New values can be added to the series, on the x-axis. | |||
|
150 | * - Once initialized to the series creation, the y-axis (if defined) is no longer modifiable | |||
|
151 | * - Data representing values and axes are associated with a unit | |||
|
152 | * - The data series is always sorted in ascending order on the x-axis. | |||
|
153 | * | |||
|
154 | * Consistency checks are carried out between the axes and the values. These controls are provided | |||
|
155 | * throughout the DataSeries lifecycle: | |||
|
156 | * - the number of data on the x-axis must be equal to the number of values (in the case of | |||
|
157 | * 2-dim ArrayData for values, the test is performed on the number of values per component) | |||
|
158 | * - if the y-axis is defined, the number of components of the ArrayData for values must equal the | |||
|
159 | * number of data on the y-axis. | |||
|
160 | * | |||
|
161 | * Examples: | |||
|
162 | * 1) | |||
|
163 | * - x-axis: [1 ; 2 ; 3] | |||
|
164 | * - y-axis: not defined | |||
|
165 | * - values: [10 ; 20 ; 30] (1-dim ArrayData) | |||
|
166 | * => the DataSeries is valid, as x-axis and values have the same number of data | |||
|
167 | * | |||
|
168 | * 2) | |||
|
169 | * - x-axis: [1 ; 2 ; 3] | |||
|
170 | * - y-axis: not defined | |||
|
171 | * - values: [10 ; 20 ; 30 ; 40] (1-dim ArrayData) | |||
|
172 | * => the DataSeries is invalid, as x-axis and values haven't the same number of data | |||
|
173 | * | |||
|
174 | * 3) | |||
|
175 | * - x-axis: [1 ; 2 ; 3] | |||
|
176 | * - y-axis: not defined | |||
|
177 | * - values: [10 ; 20 ; 30 | |||
|
178 | * 40 ; 50 ; 60] (2-dim ArrayData) | |||
|
179 | * => the DataSeries is valid, as x-axis has 3 data and values contains 2 components with 3 | |||
|
180 | * data each | |||
|
181 | * | |||
|
182 | * 4) | |||
|
183 | * - x-axis: [1 ; 2 ; 3] | |||
|
184 | * - y-axis: [1 ; 2] | |||
|
185 | * - values: [10 ; 20 ; 30 | |||
|
186 | * 40 ; 50 ; 60] (2-dim ArrayData) | |||
|
187 | * => the DataSeries is valid, as: | |||
|
188 | * - x-axis has 3 data and values contains 2 components with 3 data each AND | |||
|
189 | * - y-axis has 2 data and values contains 2 components | |||
|
190 | * | |||
|
191 | * 5) | |||
|
192 | * - x-axis: [1 ; 2 ; 3] | |||
|
193 | * - y-axis: [1 ; 2 ; 3] | |||
|
194 | * - values: [10 ; 20 ; 30 | |||
|
195 | * 40 ; 50 ; 60] (2-dim ArrayData) | |||
|
196 | * => the DataSeries is invalid, as: | |||
|
197 | * - x-axis has 3 data and values contains 2 components with 3 data each BUT | |||
|
198 | * - y-axis has 3 data and values contains only 2 components | |||
|
199 | * | |||
|
200 | * @tparam Dim The dimension of the values data | |||
|
201 | * | |||
|
202 | */ | |||
|
203 | template <int Dim> | |||
|
204 | class SCIQLOP_CORE_EXPORT DataSeries : public IDataSeries { | |||
|
205 | friend class DataSeriesMergeHelper; | |||
|
206 | ||||
|
207 | public: | |||
|
208 | /// @sa IDataSeries::xAxisData() | |||
|
209 | std::shared_ptr<ArrayData<1> > xAxisData() override { return m_XAxisData; } | |||
|
210 | const std::shared_ptr<ArrayData<1> > xAxisData() const { return m_XAxisData; } | |||
|
211 | ||||
|
212 | /// @sa IDataSeries::xAxisUnit() | |||
|
213 | Unit xAxisUnit() const override { return m_XAxisUnit; } | |||
|
214 | ||||
|
215 | /// @sa IDataSeries::yAxisUnit() | |||
|
216 | Unit yAxisUnit() const override { return m_YAxis.unit(); } | |||
|
217 | ||||
|
218 | /// @return the values dataset | |||
|
219 | std::shared_ptr<ArrayData<Dim> > valuesData() { return m_ValuesData; } | |||
|
220 | const std::shared_ptr<ArrayData<Dim> > valuesData() const { return m_ValuesData; } | |||
|
221 | ||||
|
222 | /// @sa IDataSeries::valuesUnit() | |||
|
223 | Unit valuesUnit() const override { return m_ValuesUnit; } | |||
|
224 | ||||
|
225 | int nbPoints() const override { return m_ValuesData->totalSize(); } | |||
|
226 | ||||
|
227 | std::pair<double, double> yBounds() const override { return m_YAxis.bounds(); } | |||
|
228 | ||||
|
229 | void clear() | |||
|
230 | { | |||
|
231 | m_XAxisData->clear(); | |||
|
232 | m_ValuesData->clear(); | |||
|
233 | } | |||
|
234 | ||||
|
235 | bool isEmpty() const noexcept { return m_XAxisData->size() == 0; } | |||
|
236 | ||||
|
237 | /// Merges into the data series an other data series. | |||
|
238 | /// | |||
|
239 | /// The two dataseries: | |||
|
240 | /// - must be of the same dimension | |||
|
241 | /// - must have the same y-axis (if defined) | |||
|
242 | /// | |||
|
243 | /// If the prerequisites are not valid, the method does nothing | |||
|
244 | /// | |||
|
245 | /// @remarks the data series to merge with is cleared after the operation | |||
|
246 | void merge(IDataSeries *dataSeries) override | |||
|
247 | { | |||
|
248 | dataSeries->lockWrite(); | |||
|
249 | lockWrite(); | |||
|
250 | ||||
|
251 | if (auto other = dynamic_cast<DataSeries<Dim> *>(dataSeries)) { | |||
|
252 | if (m_YAxis == other->m_YAxis) { | |||
|
253 | DataSeriesMergeHelper::merge(*other, *this); | |||
|
254 | } | |||
|
255 | else { | |||
|
256 | qCWarning(LOG_DataSeries()) | |||
|
257 | << QObject::tr("Can't merge data series that have not the same y-axis"); | |||
|
258 | } | |||
|
259 | } | |||
|
260 | else { | |||
|
261 | qCWarning(LOG_DataSeries()) | |||
|
262 | << QObject::tr("Detection of a type of IDataSeries we cannot merge with !"); | |||
|
263 | } | |||
|
264 | unlock(); | |||
|
265 | dataSeries->unlock(); | |||
|
266 | } | |||
|
267 | ||||
|
268 | void purge(double min, double max) override | |||
|
269 | { | |||
|
270 | // Nothing to purge if series is empty | |||
|
271 | if (isEmpty()) { | |||
|
272 | return; | |||
|
273 | } | |||
|
274 | ||||
|
275 | if (min > max) { | |||
|
276 | std::swap(min, max); | |||
|
277 | } | |||
|
278 | ||||
|
279 | // Nothing to purge if series min/max are inside purge range | |||
|
280 | auto xMin = cbegin()->x(); | |||
|
281 | auto xMax = (--cend())->x(); | |||
|
282 | if (xMin >= min && xMax <= max) { | |||
|
283 | return; | |||
|
284 | } | |||
|
285 | ||||
|
286 | auto lowerIt = std::lower_bound( | |||
|
287 | begin(), end(), min, [](const auto &it, const auto &val) { return it.x() < val; }); | |||
|
288 | erase(begin(), lowerIt); | |||
|
289 | auto upperIt = std::upper_bound( | |||
|
290 | begin(), end(), max, [](const auto &val, const auto &it) { return val < it.x(); }); | |||
|
291 | erase(upperIt, end()); | |||
|
292 | } | |||
|
293 | ||||
|
294 | // ///////// // | |||
|
295 | // Iterators // | |||
|
296 | // ///////// // | |||
|
297 | ||||
|
298 | DataSeriesIterator begin() override | |||
|
299 | { | |||
|
300 | return DataSeriesIterator{DataSeriesIteratorValue{ | |||
|
301 | std::make_unique<dataseries_detail::IteratorValue<Dim, false> >(*this, true)}}; | |||
|
302 | } | |||
|
303 | ||||
|
304 | DataSeriesIterator end() override | |||
|
305 | { | |||
|
306 | return DataSeriesIterator{DataSeriesIteratorValue{ | |||
|
307 | std::make_unique<dataseries_detail::IteratorValue<Dim, false> >(*this, false)}}; | |||
|
308 | } | |||
|
309 | ||||
|
310 | DataSeriesIterator cbegin() const override | |||
|
311 | { | |||
|
312 | return DataSeriesIterator{DataSeriesIteratorValue{ | |||
|
313 | std::make_unique<dataseries_detail::IteratorValue<Dim, true> >(*this, true)}}; | |||
|
314 | } | |||
|
315 | ||||
|
316 | DataSeriesIterator cend() const override | |||
|
317 | { | |||
|
318 | return DataSeriesIterator{DataSeriesIteratorValue{ | |||
|
319 | std::make_unique<dataseries_detail::IteratorValue<Dim, true> >(*this, false)}}; | |||
|
320 | } | |||
|
321 | ||||
|
322 | void erase(DataSeriesIterator first, DataSeriesIterator last) | |||
|
323 | { | |||
|
324 | auto firstImpl | |||
|
325 | = dynamic_cast<dataseries_detail::IteratorValue<Dim, false> *>(first->impl()); | |||
|
326 | auto lastImpl = dynamic_cast<dataseries_detail::IteratorValue<Dim, false> *>(last->impl()); | |||
|
327 | ||||
|
328 | if (firstImpl && lastImpl) { | |||
|
329 | m_XAxisData->erase(firstImpl->m_XIt, lastImpl->m_XIt); | |||
|
330 | m_ValuesData->erase(firstImpl->m_ValuesIt, lastImpl->m_ValuesIt); | |||
|
331 | } | |||
|
332 | } | |||
|
333 | ||||
|
334 | void insert(DataSeriesIterator first, DataSeriesIterator last, bool prepend = false) | |||
|
335 | { | |||
|
336 | auto firstImpl = dynamic_cast<dataseries_detail::IteratorValue<Dim, true> *>(first->impl()); | |||
|
337 | auto lastImpl = dynamic_cast<dataseries_detail::IteratorValue<Dim, true> *>(last->impl()); | |||
|
338 | ||||
|
339 | if (firstImpl && lastImpl) { | |||
|
340 | m_XAxisData->insert(firstImpl->m_XIt, lastImpl->m_XIt, prepend); | |||
|
341 | m_ValuesData->insert(firstImpl->m_ValuesIt, lastImpl->m_ValuesIt, prepend); | |||
|
342 | } | |||
|
343 | } | |||
|
344 | ||||
|
345 | /// @sa IDataSeries::minXAxisData() | |||
|
346 | DataSeriesIterator minXAxisData(double minXAxisData) const override | |||
|
347 | { | |||
|
348 | return std::lower_bound( | |||
|
349 | cbegin(), cend(), minXAxisData, | |||
|
350 | [](const auto &itValue, const auto &value) { return itValue.x() < value; }); | |||
|
351 | } | |||
|
352 | ||||
|
353 | /// @sa IDataSeries::maxXAxisData() | |||
|
354 | DataSeriesIterator maxXAxisData(double maxXAxisData) const override | |||
|
355 | { | |||
|
356 | // Gets the first element that greater than max value | |||
|
357 | auto it = std::upper_bound( | |||
|
358 | cbegin(), cend(), maxXAxisData, | |||
|
359 | [](const auto &value, const auto &itValue) { return value < itValue.x(); }); | |||
|
360 | ||||
|
361 | return it == cbegin() ? cend() : --it; | |||
|
362 | } | |||
|
363 | ||||
|
364 | std::pair<DataSeriesIterator, DataSeriesIterator> xAxisRange(double minXAxisData, | |||
|
365 | double maxXAxisData) const override | |||
|
366 | { | |||
|
367 | if (minXAxisData > maxXAxisData) { | |||
|
368 | std::swap(minXAxisData, maxXAxisData); | |||
|
369 | } | |||
|
370 | ||||
|
371 | auto begin = cbegin(); | |||
|
372 | auto end = cend(); | |||
|
373 | ||||
|
374 | auto lowerIt = std::lower_bound( | |||
|
375 | begin, end, minXAxisData, | |||
|
376 | [](const auto &itValue, const auto &value) { return itValue.x() < value; }); | |||
|
377 | auto upperIt = std::upper_bound( | |||
|
378 | lowerIt, end, maxXAxisData, | |||
|
379 | [](const auto &value, const auto &itValue) { return value < itValue.x(); }); | |||
|
380 | ||||
|
381 | return std::make_pair(lowerIt, upperIt); | |||
|
382 | } | |||
|
383 | ||||
|
384 | std::pair<DataSeriesIterator, DataSeriesIterator> | |||
|
385 | valuesBounds(double minXAxisData, double maxXAxisData) const override | |||
|
386 | { | |||
|
387 | // Places iterators to the correct x-axis range | |||
|
388 | auto xAxisRangeIts = xAxisRange(minXAxisData, maxXAxisData); | |||
|
389 | ||||
|
390 | // Returns end iterators if the range is empty | |||
|
391 | if (xAxisRangeIts.first == xAxisRangeIts.second) { | |||
|
392 | return std::make_pair(cend(), cend()); | |||
|
393 | } | |||
|
394 | ||||
|
395 | // Gets the iterator on the min of all values data | |||
|
396 | auto minIt = std::min_element( | |||
|
397 | xAxisRangeIts.first, xAxisRangeIts.second, [](const auto &it1, const auto &it2) { | |||
|
398 | return SortUtils::minCompareWithNaN(it1.minValue(), it2.minValue()); | |||
|
399 | }); | |||
|
400 | ||||
|
401 | // Gets the iterator on the max of all values data | |||
|
402 | auto maxIt = std::max_element( | |||
|
403 | xAxisRangeIts.first, xAxisRangeIts.second, [](const auto &it1, const auto &it2) { | |||
|
404 | return SortUtils::maxCompareWithNaN(it1.maxValue(), it2.maxValue()); | |||
|
405 | }); | |||
|
406 | ||||
|
407 | return std::make_pair(minIt, maxIt); | |||
|
408 | } | |||
|
409 | ||||
|
410 | /// @return the y-axis associated to the data series | |||
|
411 | const OptionalAxis &yAxis() const { return m_YAxis; } | |||
|
412 | OptionalAxis &yAxis() { return m_YAxis; } | |||
|
413 | ||||
|
414 | // /////// // | |||
|
415 | // Mutexes // | |||
|
416 | // /////// // | |||
|
417 | ||||
|
418 | virtual void lockRead() { m_Lock.lockForRead(); } | |||
|
419 | virtual void lockWrite() { m_Lock.lockForWrite(); } | |||
|
420 | virtual void unlock() { m_Lock.unlock(); } | |||
|
421 | ||||
|
422 | protected: | |||
|
423 | /// Protected ctor (DataSeries is abstract). | |||
|
424 | /// | |||
|
425 | /// Data vectors must be consistent with each other, otherwise an exception will be thrown (@sa | |||
|
426 | /// class description for consistent rules) | |||
|
427 | /// @remarks data series is automatically sorted on its x-axis data | |||
|
428 | /// @throws std::invalid_argument if the data are inconsistent with each other | |||
|
429 | explicit DataSeries(std::shared_ptr<ArrayData<1> > xAxisData, const Unit &xAxisUnit, | |||
|
430 | std::shared_ptr<ArrayData<Dim> > valuesData, const Unit &valuesUnit, | |||
|
431 | OptionalAxis yAxis = OptionalAxis{}) | |||
|
432 | : m_XAxisData{xAxisData}, | |||
|
433 | m_XAxisUnit{xAxisUnit}, | |||
|
434 | m_ValuesData{valuesData}, | |||
|
435 | m_ValuesUnit{valuesUnit}, | |||
|
436 | m_YAxis{std::move(yAxis)} | |||
|
437 | { | |||
|
438 | if (m_XAxisData->size() != m_ValuesData->size()) { | |||
|
439 | throw std::invalid_argument{ | |||
|
440 | "The number of values by component must be equal to the number of x-axis data"}; | |||
|
441 | } | |||
|
442 | ||||
|
443 | // Validates y-axis (if defined) | |||
|
444 | if (yAxis.isDefined() && (yAxis.size() != m_ValuesData->componentCount())) { | |||
|
445 | throw std::invalid_argument{ | |||
|
446 | "As the y-axis is defined, the number of value components must be equal to the " | |||
|
447 | "number of y-axis data"}; | |||
|
448 | } | |||
|
449 | ||||
|
450 | // Sorts data if it's not the case | |||
|
451 | const auto &xAxisCData = m_XAxisData->cdata(); | |||
|
452 | if (!std::is_sorted(xAxisCData.cbegin(), xAxisCData.cend())) { | |||
|
453 | sort(); | |||
|
454 | } | |||
|
455 | } | |||
|
456 | ||||
|
457 | /// Copy ctor | |||
|
458 | explicit DataSeries(const DataSeries<Dim> &other) | |||
|
459 | : m_XAxisData{std::make_shared<ArrayData<1> >(*other.m_XAxisData)}, | |||
|
460 | m_XAxisUnit{other.m_XAxisUnit}, | |||
|
461 | m_ValuesData{std::make_shared<ArrayData<Dim> >(*other.m_ValuesData)}, | |||
|
462 | m_ValuesUnit{other.m_ValuesUnit}, | |||
|
463 | m_YAxis{other.m_YAxis} | |||
|
464 | { | |||
|
465 | // Since a series is ordered from its construction and is always ordered, it is not | |||
|
466 | // necessary to call the sort method here ('other' is sorted) | |||
|
467 | } | |||
|
468 | ||||
|
469 | /// Assignment operator | |||
|
470 | template <int D> | |||
|
471 | DataSeries &operator=(DataSeries<D> other) | |||
|
472 | { | |||
|
473 | std::swap(m_XAxisData, other.m_XAxisData); | |||
|
474 | std::swap(m_XAxisUnit, other.m_XAxisUnit); | |||
|
475 | std::swap(m_ValuesData, other.m_ValuesData); | |||
|
476 | std::swap(m_ValuesUnit, other.m_ValuesUnit); | |||
|
477 | std::swap(m_YAxis, other.m_YAxis); | |||
|
478 | ||||
|
479 | return *this; | |||
|
480 | } | |||
|
481 | ||||
|
482 | private: | |||
|
483 | /** | |||
|
484 | * Sorts data series on its x-axis data | |||
|
485 | */ | |||
|
486 | void sort() noexcept | |||
|
487 | { | |||
|
488 | auto permutation = SortUtils::sortPermutation(*m_XAxisData, std::less<double>()); | |||
|
489 | m_XAxisData = m_XAxisData->sort(permutation); | |||
|
490 | m_ValuesData = m_ValuesData->sort(permutation); | |||
|
491 | } | |||
|
492 | ||||
|
493 | // x-axis | |||
|
494 | std::shared_ptr<ArrayData<1> > m_XAxisData; | |||
|
495 | Unit m_XAxisUnit; | |||
|
496 | ||||
|
497 | // values | |||
|
498 | std::shared_ptr<ArrayData<Dim> > m_ValuesData; | |||
|
499 | Unit m_ValuesUnit; | |||
|
500 | ||||
|
501 | // y-axis (optional) | |||
|
502 | OptionalAxis m_YAxis; | |||
|
503 | ||||
|
504 | QReadWriteLock m_Lock; | |||
|
505 | }; | |||
|
506 | ||||
|
507 | #endif // SCIQLOP_DATASERIES_H |
@@ -0,0 +1,81 | |||||
|
1 | #ifndef SCIQLOP_DATASERIESITERATOR_H | |||
|
2 | #define SCIQLOP_DATASERIESITERATOR_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | #include "Data/SqpIterator.h" | |||
|
6 | ||||
|
7 | #include <QVector> | |||
|
8 | #include <memory> | |||
|
9 | ||||
|
10 | /** | |||
|
11 | * @brief The DataSeriesIteratorValue class represents the current value of a data series iterator. | |||
|
12 | * It offers standard access methods for the data in the series (x-axis, values), but it is up to | |||
|
13 | * each series to define its own implementation of how to retrieve this data, by implementing the | |||
|
14 | * DataSeriesIteratorValue::Impl interface | |||
|
15 | * | |||
|
16 | * @sa DataSeriesIterator | |||
|
17 | */ | |||
|
18 | class SCIQLOP_CORE_EXPORT DataSeriesIteratorValue { | |||
|
19 | public: | |||
|
20 | struct Impl { | |||
|
21 | virtual ~Impl() noexcept = default; | |||
|
22 | virtual std::unique_ptr<Impl> clone() const = 0; | |||
|
23 | virtual int distance(const Impl &other) const = 0; | |||
|
24 | virtual bool equals(const Impl &other) const = 0; | |||
|
25 | virtual bool lowerThan(const Impl &other) const = 0; | |||
|
26 | virtual std::unique_ptr<Impl> advance(int offset) const = 0; | |||
|
27 | virtual void next(int offset) = 0; | |||
|
28 | virtual void prev() = 0; | |||
|
29 | virtual double x() const = 0; | |||
|
30 | virtual std::vector<double> y() const = 0; | |||
|
31 | virtual double value() const = 0; | |||
|
32 | virtual double value(int componentIndex) const = 0; | |||
|
33 | virtual double minValue() const = 0; | |||
|
34 | virtual double maxValue() const = 0; | |||
|
35 | virtual QVector<double> values() const = 0; | |||
|
36 | ||||
|
37 | virtual void swap(Impl &other) = 0; | |||
|
38 | }; | |||
|
39 | ||||
|
40 | explicit DataSeriesIteratorValue(std::unique_ptr<Impl> impl); | |||
|
41 | DataSeriesIteratorValue(const DataSeriesIteratorValue &other); | |||
|
42 | DataSeriesIteratorValue &operator=(DataSeriesIteratorValue other); | |||
|
43 | ||||
|
44 | int distance(const DataSeriesIteratorValue &other) const; | |||
|
45 | bool equals(const DataSeriesIteratorValue &other) const; | |||
|
46 | bool lowerThan(const DataSeriesIteratorValue &other) const; | |||
|
47 | ||||
|
48 | DataSeriesIteratorValue advance(int offset) const; | |||
|
49 | /// Advances to the next value | |||
|
50 | void next(int offset = 1); | |||
|
51 | /// Moves back to the previous value | |||
|
52 | void prev(); | |||
|
53 | /// Gets x-axis data | |||
|
54 | double x() const; | |||
|
55 | /// Gets y-axis data | |||
|
56 | std::vector<double> y() const; | |||
|
57 | /// Gets value data | |||
|
58 | double value() const; | |||
|
59 | /// Gets value data depending on an index | |||
|
60 | double value(int componentIndex) const; | |||
|
61 | /// Gets min of all values data | |||
|
62 | double minValue() const; | |||
|
63 | /// Gets max of all values data | |||
|
64 | double maxValue() const; | |||
|
65 | /// Gets all values data | |||
|
66 | QVector<double> values() const; | |||
|
67 | ||||
|
68 | Impl *impl(); | |||
|
69 | ||||
|
70 | friend void swap(DataSeriesIteratorValue &lhs, DataSeriesIteratorValue &rhs) | |||
|
71 | { | |||
|
72 | std::swap(lhs.m_Impl, rhs.m_Impl); | |||
|
73 | } | |||
|
74 | ||||
|
75 | private: | |||
|
76 | std::unique_ptr<Impl> m_Impl; | |||
|
77 | }; | |||
|
78 | ||||
|
79 | using DataSeriesIterator = SqpIterator<DataSeriesIteratorValue>; | |||
|
80 | ||||
|
81 | #endif // SCIQLOP_DATASERIESITERATOR_H |
@@ -0,0 +1,83 | |||||
|
1 | #ifndef SCIQLOP_DATASERIESMERGEHELPER_H | |||
|
2 | #define SCIQLOP_DATASERIESMERGEHELPER_H | |||
|
3 | ||||
|
4 | template <int Dim> | |||
|
5 | class DataSeries; | |||
|
6 | ||||
|
7 | namespace detail { | |||
|
8 | ||||
|
9 | /** | |||
|
10 | * Scope that can be used for a merge operation | |||
|
11 | * @tparam FEnd the type of function that will be executed at the end of the scope | |||
|
12 | */ | |||
|
13 | template <typename FEnd> | |||
|
14 | struct MergeScope { | |||
|
15 | explicit MergeScope(FEnd end) : m_End{end} {} | |||
|
16 | virtual ~MergeScope() noexcept { m_End(); } | |||
|
17 | FEnd m_End; | |||
|
18 | }; | |||
|
19 | ||||
|
20 | /** | |||
|
21 | * Creates a scope for merge operation | |||
|
22 | * @tparam end the function executed at the end of the scope | |||
|
23 | */ | |||
|
24 | template <typename FEnd> | |||
|
25 | MergeScope<FEnd> scope(FEnd end) | |||
|
26 | { | |||
|
27 | return MergeScope<FEnd>{end}; | |||
|
28 | } | |||
|
29 | ||||
|
30 | } // namespace detail | |||
|
31 | ||||
|
32 | ||||
|
33 | /// Helper used to merge two DataSeries | |||
|
34 | /// @sa DataSeries | |||
|
35 | struct DataSeriesMergeHelper { | |||
|
36 | /// Merges the source data series into the dest data series. Data of the source data series are | |||
|
37 | /// consumed | |||
|
38 | template <int Dim> | |||
|
39 | static void merge(DataSeries<Dim> &source, DataSeries<Dim> &dest) | |||
|
40 | { | |||
|
41 | // Creates a scope to clear source data series at the end of the merge | |||
|
42 | auto _ = detail::scope([&source]() { source.clear(); }); | |||
|
43 | ||||
|
44 | // Case : source data series is empty -> no merge is made | |||
|
45 | if (source.isEmpty()) { | |||
|
46 | return; | |||
|
47 | } | |||
|
48 | ||||
|
49 | // Case : dest data series is empty -> we simply swap the data | |||
|
50 | if (dest.isEmpty()) { | |||
|
51 | std::swap(dest.m_XAxisData, source.m_XAxisData); | |||
|
52 | std::swap(dest.m_ValuesData, source.m_ValuesData); | |||
|
53 | return; | |||
|
54 | } | |||
|
55 | ||||
|
56 | auto destMin = dest.cbegin()->x(); | |||
|
57 | auto destMax = (--dest.cend())->x(); | |||
|
58 | ||||
|
59 | auto sourceBegin = source.cbegin(); | |||
|
60 | auto sourceEnd = source.cend(); | |||
|
61 | auto sourceMin = sourceBegin->x(); | |||
|
62 | auto sourceMax = (--source.cend())->x(); | |||
|
63 | ||||
|
64 | // Case : source bounds are inside dest bounds -> no merge is made | |||
|
65 | if (sourceMin >= destMin && sourceMax <= destMax) { | |||
|
66 | return; | |||
|
67 | } | |||
|
68 | ||||
|
69 | // Default case : | |||
|
70 | // - prepend to dest the values of source that are lower than min value of dest | |||
|
71 | // - append to dest the values of source that are greater than max value of dest | |||
|
72 | auto lowerIt | |||
|
73 | = std::lower_bound(sourceBegin, sourceEnd, destMin, | |||
|
74 | [](const auto &it, const auto &val) { return it.x() < val; }); | |||
|
75 | auto upperIt | |||
|
76 | = std::upper_bound(lowerIt, sourceEnd, destMax, | |||
|
77 | [](const auto &val, const auto &it) { return val < it.x(); }); | |||
|
78 | dest.insert(sourceBegin, lowerIt, true); | |||
|
79 | dest.insert(upperIt, sourceEnd); | |||
|
80 | } | |||
|
81 | }; | |||
|
82 | ||||
|
83 | #endif // SCIQLOP_DATASERIESMERGEHELPER_H |
@@ -0,0 +1,26 | |||||
|
1 | #ifndef SCIQLOP_DATASERIESTYPE_H | |||
|
2 | #define SCIQLOP_DATASERIESTYPE_H | |||
|
3 | ||||
|
4 | #include <QString> | |||
|
5 | ||||
|
6 | enum class DataSeriesType { SCALAR, SPECTROGRAM, VECTOR, UNKNOWN }; | |||
|
7 | ||||
|
8 | struct DataSeriesTypeUtils { | |||
|
9 | static DataSeriesType fromString(const QString &type) | |||
|
10 | { | |||
|
11 | if (type == QStringLiteral("scalar")) { | |||
|
12 | return DataSeriesType::SCALAR; | |||
|
13 | } | |||
|
14 | else if (type == QStringLiteral("spectrogram")) { | |||
|
15 | return DataSeriesType::SPECTROGRAM; | |||
|
16 | } | |||
|
17 | else if (type == QStringLiteral("vector")) { | |||
|
18 | return DataSeriesType::VECTOR; | |||
|
19 | } | |||
|
20 | else { | |||
|
21 | return DataSeriesType::UNKNOWN; | |||
|
22 | } | |||
|
23 | } | |||
|
24 | }; | |||
|
25 | ||||
|
26 | #endif // SCIQLOP_DATASERIESTYPE_H |
@@ -0,0 +1,317 | |||||
|
1 | #ifndef SCIQLOP_DATASERIESUTILS_H | |||
|
2 | #define SCIQLOP_DATASERIESUTILS_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <Common/SortUtils.h> | |||
|
7 | #include <Data/DataSeriesIterator.h> | |||
|
8 | ||||
|
9 | #include <QLoggingCategory> | |||
|
10 | #include <cmath> | |||
|
11 | ||||
|
12 | Q_DECLARE_LOGGING_CATEGORY(LOG_DataSeriesUtils) | |||
|
13 | ||||
|
14 | /** | |||
|
15 | * Utility class with methods for data series | |||
|
16 | */ | |||
|
17 | struct SCIQLOP_CORE_EXPORT DataSeriesUtils { | |||
|
18 | /** | |||
|
19 | * Define a meshs. | |||
|
20 | * | |||
|
21 | * A mesh is a regular grid representing cells of the same width (in x) and of the same height | |||
|
22 | * (in y). At each mesh point is associated a value. | |||
|
23 | * | |||
|
24 | * Each axis of the mesh is defined by a minimum value, a number of values is a mesh step. | |||
|
25 | * For example: if min = 1, nbValues = 5 and step = 2 => the axis of the mesh will be [1, 3, 5, | |||
|
26 | * 7, 9]. | |||
|
27 | * | |||
|
28 | * The values are defined in an array of size {nbX * nbY}. The data is stored along the X axis. | |||
|
29 | * | |||
|
30 | * For example, the mesh: | |||
|
31 | * Y = 2 [ 7 ; 8 ; 9 | |||
|
32 | * Y = 1 4 ; 5 ; 6 | |||
|
33 | * Y = 0 1 ; 2 ; 3 ] | |||
|
34 | * X = 0 X = 1 X = 2 | |||
|
35 | * | |||
|
36 | * will be represented by data [1, 2, 3, 4, 5, 6, 7, 8, 9] | |||
|
37 | */ | |||
|
38 | struct Mesh { | |||
|
39 | explicit Mesh() = default; | |||
|
40 | explicit Mesh(int nbX, double xMin, double xStep, int nbY, double yMin, double yStep) | |||
|
41 | : m_NbX{nbX}, | |||
|
42 | m_XMin{xMin}, | |||
|
43 | m_XStep{xStep}, | |||
|
44 | m_NbY{nbY}, | |||
|
45 | m_YMin{yMin}, | |||
|
46 | m_YStep{yStep}, | |||
|
47 | m_Data(nbX * nbY) | |||
|
48 | { | |||
|
49 | } | |||
|
50 | ||||
|
51 | inline bool isEmpty() const { return m_Data.size() == 0; } | |||
|
52 | inline double xMax() const { return m_XMin + (m_NbX - 1) * m_XStep; } | |||
|
53 | inline double yMax() const { return m_YMin + (m_NbY - 1) * m_YStep; } | |||
|
54 | ||||
|
55 | int m_NbX{0}; | |||
|
56 | double m_XMin{}; | |||
|
57 | double m_XStep{}; | |||
|
58 | int m_NbY{0}; | |||
|
59 | double m_YMin{}; | |||
|
60 | double m_YStep{}; | |||
|
61 | std::vector<double> m_Data{}; | |||
|
62 | }; | |||
|
63 | ||||
|
64 | /** | |||
|
65 | * Represents a resolution used to generate the data of a mesh on the x-axis or in Y. | |||
|
66 | * | |||
|
67 | * A resolution is represented by a value and flag indicating if it's in the logarithmic scale | |||
|
68 | * @sa Mesh | |||
|
69 | */ | |||
|
70 | struct Resolution { | |||
|
71 | double m_Val{std::numeric_limits<double>::quiet_NaN()}; | |||
|
72 | bool m_Logarithmic{false}; | |||
|
73 | }; | |||
|
74 | ||||
|
75 | /** | |||
|
76 | * Processes data from a data series to complete the data holes with a fill value. | |||
|
77 | * | |||
|
78 | * A data hole is determined by the resolution passed in parameter: if, between two continuous | |||
|
79 | * data on the x-axis, the difference between these data is greater than the resolution, then | |||
|
80 | * there is one or more holes between them. The holes are filled by adding: | |||
|
81 | * - for the x-axis, new data corresponding to the 'step resolution' starting from the first | |||
|
82 | * data; | |||
|
83 | * - for values, a default value (fill value) for each new data added on the x-axis. | |||
|
84 | * | |||
|
85 | * For example, with : | |||
|
86 | * - xAxisData = [0, 1, 5, 7, 14 ] | |||
|
87 | * - valuesData = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] (two components per x-axis data) | |||
|
88 | * - fillValue = NaN | |||
|
89 | * - and resolution = 2; | |||
|
90 | * | |||
|
91 | * For the x axis, we calculate as data holes: [3, 9, 11, 13]. These holes are added to the | |||
|
92 | * x-axis data, and NaNs (two per x-axis data) are added to the values: | |||
|
93 | * => xAxisData = [0, 1, 3, 5, 7, 9, 11, 13, 14 ] | |||
|
94 | * => valuesData = [0, 1, 2, 3, NaN, NaN, 4, 5, 6, 7, NaN, NaN, NaN, NaN, NaN, NaN, 8, 9] | |||
|
95 | * | |||
|
96 | * It is also possible to set bounds for the data series. If these bounds are defined and exceed | |||
|
97 | * the limits of the data series, data holes are added to the series at the beginning and/or the | |||
|
98 | * end. | |||
|
99 | * | |||
|
100 | * The generation of data holes at the beginning/end of the data series is performed starting | |||
|
101 | * from the x-axis series limit and adding data holes at each 'resolution step' as long as the | |||
|
102 | * new bound is not reached. | |||
|
103 | * | |||
|
104 | * For example, with : | |||
|
105 | * - xAxisData = [3, 4, 5, 6, 7 ] | |||
|
106 | * - valuesData = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] | |||
|
107 | * - fillValue = NaN | |||
|
108 | * - minBound = 0 | |||
|
109 | * - maxBound = 12 | |||
|
110 | * - and resolution = 2; | |||
|
111 | * | |||
|
112 | * => Starting from 3 and decreasing 2 by 2 until reaching 0 : a data hole at value 1 will be | |||
|
113 | * added to the beginning of the series | |||
|
114 | * => Starting from 7 and increasing 2 by 2 until reaching 12 : data holes at values 9 and 11 | |||
|
115 | * will be added to the end of the series | |||
|
116 | * | |||
|
117 | * So : | |||
|
118 | * => xAxisData = [1, 3, 4, 5, 6, 7, 9, 11 ] | |||
|
119 | * => valuesData = [NaN, NaN, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, NaN, NaN, NaN, NaN] | |||
|
120 | * | |||
|
121 | * @param xAxisData the x-axis data of the data series | |||
|
122 | * @param valuesData the values data of the data series | |||
|
123 | * @param resolution the resoultion (on x-axis) used to determinate data holes | |||
|
124 | * @param fillValue the fill value used for data holes in the values data | |||
|
125 | * @param minBound the limit at which to start filling data holes for the series. If set to NaN, | |||
|
126 | * the limit is not used | |||
|
127 | * @param maxBound the limit at which to end filling data holes for the series. If set to NaN, | |||
|
128 | * the limit is not used | |||
|
129 | * | |||
|
130 | * @remarks There is no control over the consistency between x-axis data and values data. The | |||
|
131 | * method considers that the data is well formed (the total number of values data is a multiple | |||
|
132 | * of the number of x-axis data) | |||
|
133 | */ | |||
|
134 | static void fillDataHoles(std::vector<double> &xAxisData, std::vector<double> &valuesData, | |||
|
135 | double resolution, | |||
|
136 | double fillValue = std::numeric_limits<double>::quiet_NaN(), | |||
|
137 | double minBound = std::numeric_limits<double>::quiet_NaN(), | |||
|
138 | double maxBound = std::numeric_limits<double>::quiet_NaN()); | |||
|
139 | /** | |||
|
140 | * Computes the resolution of a dataset passed as a parameter. | |||
|
141 | * | |||
|
142 | * The resolution of a dataset is the minimum difference between two values that follow in the | |||
|
143 | * set. | |||
|
144 | * For example: | |||
|
145 | * - for the set [0, 2, 4, 8, 10, 11, 13] => the resolution is 1 (difference between 10 and 11). | |||
|
146 | * | |||
|
147 | * A resolution can be calculated on the logarithmic scale (base of 10). In this case, the | |||
|
148 | * dataset is first converted to logarithmic values. | |||
|
149 | * For example: | |||
|
150 | * - for the set [10, 100, 10000, 1000000], the values are converted to [1, 2, 4, 6] => the | |||
|
151 | * logarithmic resolution is 1 (difference between 1 and 2). | |||
|
152 | * | |||
|
153 | * @param begin the iterator pointing to the beginning of the dataset | |||
|
154 | * @param end the iterator pointing to the end of the dataset | |||
|
155 | * @param logarithmic computes a logarithmic resolution or not | |||
|
156 | * @return the resolution computed | |||
|
157 | * @warning the method considers the dataset as sorted and doesn't control it. | |||
|
158 | */ | |||
|
159 | template <typename Iterator> | |||
|
160 | static Resolution resolution(Iterator begin, Iterator end, bool logarithmic = false); | |||
|
161 | ||||
|
162 | /** | |||
|
163 | * Computes a regular mesh for a data series, according to resolutions for x-axis and y-axis | |||
|
164 | * passed as parameters. | |||
|
165 | * | |||
|
166 | * The mesh is created from the resolutions in x and y and the boundaries delimiting the data | |||
|
167 | * series. If the resolutions do not allow to obtain a regular mesh, they are recalculated. | |||
|
168 | * | |||
|
169 | * For example : | |||
|
170 | * Let x-axis data = [0, 1, 3, 5, 9], its associated values ββ= [0, 10, 30, 50, 90] and | |||
|
171 | * xResolution = 2. | |||
|
172 | * Based on the resolution, the mesh would be [0, 2, 4, 6, 8, 10] and would be invalid because | |||
|
173 | * it exceeds the maximum bound of the data. The resolution is thus recalculated so that the | |||
|
174 | * mesh holds between the data terminals. | |||
|
175 | * So => resolution is 1.8 and the mesh is [0, 1.8, 3.6, 5.4, 7.2, 9]. | |||
|
176 | * | |||
|
177 | * Once the mesh is generated in x and y, the values ββare associated with each mesh point, | |||
|
178 | * based on the data in the series, finding the existing data at which the mesh point would be | |||
|
179 | * or would be closest to, without exceeding it. | |||
|
180 | * | |||
|
181 | * In the example, we determine the value of each mesh point: | |||
|
182 | * - x = 0 => value = 0 (existing x in the data series) | |||
|
183 | * - x = 1.8 => value = 10 (the closest existing x: 1) | |||
|
184 | * - x = 3.6 => value = 30 (the closest existing x: 3) | |||
|
185 | * - x = 5.4 => value = 50 (the closest existing x: 5) | |||
|
186 | * - x = 7.2 => value = 50 (the closest existing x: 5) | |||
|
187 | * - x = 9 => value = 90 (existing x in the data series) | |||
|
188 | * | |||
|
189 | * Same algorithm is applied for y-axis. | |||
|
190 | * | |||
|
191 | * @param begin the iterator pointing to the beginning of the data series | |||
|
192 | * @param end the iterator pointing to the end of the data series | |||
|
193 | * @param xResolution the resolution expected for the mesh's x-axis | |||
|
194 | * @param yResolution the resolution expected for the mesh's y-axis | |||
|
195 | * @return the mesh created, an empty mesh if the input data do not allow to generate a regular | |||
|
196 | * mesh (empty data, null resolutions, logarithmic x-axis) | |||
|
197 | * @warning the method considers the dataset as sorted and doesn't control it. | |||
|
198 | */ | |||
|
199 | static Mesh regularMesh(DataSeriesIterator begin, DataSeriesIterator end, | |||
|
200 | Resolution xResolution, Resolution yResolution); | |||
|
201 | ||||
|
202 | /** | |||
|
203 | * Calculates the min and max thresholds of a dataset. | |||
|
204 | * | |||
|
205 | * The thresholds of a dataset correspond to the min and max limits of the set to which the | |||
|
206 | * outliers are exluded (values distant from the others) For example, for the set [1, 2, 3, 4, | |||
|
207 | * 5, 10000], 10000 is an outlier and will be excluded from the thresholds. | |||
|
208 | * | |||
|
209 | * Bounds determining the thresholds is calculated according to the mean and the standard | |||
|
210 | * deviation of the defined data. The thresholds are limited to the min / max values of the | |||
|
211 | * dataset: if for example the calculated min threshold is 2 but the min value of the datasetset | |||
|
212 | * is 4, 4 is returned as the min threshold. | |||
|
213 | * | |||
|
214 | * @param begin the beginning of the dataset | |||
|
215 | * @param end the end of the dataset | |||
|
216 | * @param logarithmic computes threshold with a logarithmic scale or not | |||
|
217 | * @return the thresholds computed, a couple of nan values if it couldn't be computed | |||
|
218 | */ | |||
|
219 | template <typename Iterator> | |||
|
220 | static std::pair<double, double> thresholds(Iterator begin, Iterator end, | |||
|
221 | bool logarithmic = false); | |||
|
222 | }; | |||
|
223 | ||||
|
224 | template <typename Iterator> | |||
|
225 | DataSeriesUtils::Resolution DataSeriesUtils::resolution(Iterator begin, Iterator end, | |||
|
226 | bool logarithmic) | |||
|
227 | { | |||
|
228 | // Retrieves data into a work dataset | |||
|
229 | using ValueType = typename Iterator::value_type; | |||
|
230 | std::vector<ValueType> values{}; | |||
|
231 | std::copy(begin, end, std::back_inserter(values)); | |||
|
232 | ||||
|
233 | // Converts data if logarithmic flag is activated | |||
|
234 | if (logarithmic) { | |||
|
235 | std::for_each(values.begin(), values.end(), | |||
|
236 | [logarithmic](auto &val) { val = std::log10(val); }); | |||
|
237 | } | |||
|
238 | ||||
|
239 | // Computes the differences between the values in the dataset | |||
|
240 | std::adjacent_difference(values.begin(), values.end(), values.begin()); | |||
|
241 | ||||
|
242 | // Retrieves the smallest difference | |||
|
243 | auto resolutionIt = std::min_element(values.begin(), values.end()); | |||
|
244 | auto resolution | |||
|
245 | = resolutionIt != values.end() ? *resolutionIt : std::numeric_limits<double>::quiet_NaN(); | |||
|
246 | ||||
|
247 | return Resolution{resolution, logarithmic}; | |||
|
248 | } | |||
|
249 | ||||
|
250 | template <typename Iterator> | |||
|
251 | std::pair<double, double> DataSeriesUtils::thresholds(Iterator begin, Iterator end, | |||
|
252 | bool logarithmic) | |||
|
253 | { | |||
|
254 | /// Lambda that converts values in case of logaritmic scale | |||
|
255 | auto toLog = [logarithmic](const auto &value) { | |||
|
256 | if (logarithmic) { | |||
|
257 | // Logaritmic scale doesn't include zero value | |||
|
258 | return !(std::isnan(value) || value < std::numeric_limits<double>::epsilon()) | |||
|
259 | ? std::log10(value) | |||
|
260 | : std::numeric_limits<double>::quiet_NaN(); | |||
|
261 | } | |||
|
262 | else { | |||
|
263 | return value; | |||
|
264 | } | |||
|
265 | }; | |||
|
266 | ||||
|
267 | /// Lambda that converts values to linear scale | |||
|
268 | auto fromLog | |||
|
269 | = [logarithmic](const auto &value) { return logarithmic ? std::pow(10, value) : value; }; | |||
|
270 | ||||
|
271 | /// Lambda used to sum data and divide the sum by the number of data. It is used to calculate | |||
|
272 | /// the mean and standard deviation | |||
|
273 | /// @param fun the data addition function | |||
|
274 | auto accumulate = [begin, end](auto fun) { | |||
|
275 | double sum; | |||
|
276 | int nbValues; | |||
|
277 | std::tie(sum, nbValues) = std::accumulate( | |||
|
278 | begin, end, std::make_pair(0., 0), [fun](const auto &input, const auto &value) { | |||
|
279 | auto computedValue = fun(value); | |||
|
280 | ||||
|
281 | // NaN values are excluded from the sum | |||
|
282 | return !std::isnan(computedValue) | |||
|
283 | ? std::make_pair(input.first + computedValue, input.second + 1) | |||
|
284 | : input; | |||
|
285 | }); | |||
|
286 | ||||
|
287 | return nbValues != 0 ? sum / nbValues : std::numeric_limits<double>::quiet_NaN(); | |||
|
288 | }; | |||
|
289 | ||||
|
290 | // Computes mean | |||
|
291 | auto mean = accumulate([toLog](const auto &val) { return toLog(val); }); | |||
|
292 | if (std::isnan(mean)) { | |||
|
293 | return {std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN()}; | |||
|
294 | } | |||
|
295 | ||||
|
296 | // Computes standard deviation | |||
|
297 | auto variance | |||
|
298 | = accumulate([mean, toLog](const auto &val) { return std::pow(toLog(val) - mean, 2); }); | |||
|
299 | auto sigma = std::sqrt(variance); | |||
|
300 | ||||
|
301 | // Computes thresholds | |||
|
302 | auto minThreshold = fromLog(mean - 3 * sigma); | |||
|
303 | auto maxThreshold = fromLog(mean + 3 * sigma); | |||
|
304 | ||||
|
305 | // Finds min/max values | |||
|
306 | auto minIt = std::min_element(begin, end, [toLog](const auto &it1, const auto &it2) { | |||
|
307 | return SortUtils::minCompareWithNaN(toLog(it1), toLog(it2)); | |||
|
308 | }); | |||
|
309 | auto maxIt = std::max_element(begin, end, [toLog](const auto &it1, const auto &it2) { | |||
|
310 | return SortUtils::maxCompareWithNaN(toLog(it1), toLog(it2)); | |||
|
311 | }); | |||
|
312 | ||||
|
313 | // Returns thresholds (bounded to min/max values) | |||
|
314 | return {std::max(*minIt, minThreshold), std::min(*maxIt, maxThreshold)}; | |||
|
315 | } | |||
|
316 | ||||
|
317 | #endif // SCIQLOP_DATASERIESUTILS_H |
@@ -0,0 +1,68 | |||||
|
1 | #ifndef SCIQLOP_SQPRANGE_H | |||
|
2 | #define SCIQLOP_SQPRANGE_H | |||
|
3 | ||||
|
4 | #include <QObject> | |||
|
5 | ||||
|
6 | #include <QDebug> | |||
|
7 | ||||
|
8 | #include <Common/DateUtils.h> | |||
|
9 | #include <Common/MetaTypes.h> | |||
|
10 | ||||
|
11 | #include <cmath> | |||
|
12 | ||||
|
13 | /** | |||
|
14 | * @brief The SqpRange struct holds the information of time parameters | |||
|
15 | */ | |||
|
16 | struct DateTimeRange { | |||
|
17 | /// Creates SqpRange from dates and times | |||
|
18 | static DateTimeRange fromDateTime(const QDate &startDate, const QTime &startTime, | |||
|
19 | const QDate &endDate, const QTime &endTime) | |||
|
20 | { | |||
|
21 | return {DateUtils::secondsSinceEpoch(QDateTime{startDate, startTime, Qt::UTC}), | |||
|
22 | DateUtils::secondsSinceEpoch(QDateTime{endDate, endTime, Qt::UTC})}; | |||
|
23 | } | |||
|
24 | ||||
|
25 | /// Start time (UTC) | |||
|
26 | double m_TStart; | |||
|
27 | /// End time (UTC) | |||
|
28 | double m_TEnd; | |||
|
29 | ||||
|
30 | double delta()const {return this->m_TEnd - this->m_TStart;} | |||
|
31 | ||||
|
32 | bool contains(const DateTimeRange &dateTime) const noexcept | |||
|
33 | { | |||
|
34 | return (m_TStart <= dateTime.m_TStart && m_TEnd >= dateTime.m_TEnd); | |||
|
35 | } | |||
|
36 | ||||
|
37 | bool intersect(const DateTimeRange &dateTime) const noexcept | |||
|
38 | { | |||
|
39 | return (m_TEnd >= dateTime.m_TStart && m_TStart <= dateTime.m_TEnd); | |||
|
40 | } | |||
|
41 | ||||
|
42 | bool operator==(const DateTimeRange &other) const | |||
|
43 | { | |||
|
44 | auto equals = [](const auto &v1, const auto &v2) { | |||
|
45 | return (std::isnan(v1) && std::isnan(v2)) || v1 == v2; | |||
|
46 | }; | |||
|
47 | ||||
|
48 | return equals(m_TStart, other.m_TStart) && equals(m_TEnd, other.m_TEnd); | |||
|
49 | } | |||
|
50 | bool operator!=(const DateTimeRange &other) const { return !(*this == other); } | |||
|
51 | }; | |||
|
52 | ||||
|
53 | const auto INVALID_RANGE | |||
|
54 | = DateTimeRange{std::numeric_limits<double>::quiet_NaN(), std::numeric_limits<double>::quiet_NaN()}; | |||
|
55 | ||||
|
56 | inline QDebug operator<<(QDebug d, DateTimeRange obj) | |||
|
57 | { | |||
|
58 | auto tendDateTimeStart = DateUtils::dateTime(obj.m_TStart); | |||
|
59 | auto tendDateTimeEnd = DateUtils::dateTime(obj.m_TEnd); | |||
|
60 | ||||
|
61 | d << "ts: " << tendDateTimeStart << " te: " << tendDateTimeEnd; | |||
|
62 | return d; | |||
|
63 | } | |||
|
64 | ||||
|
65 | // Required for using shared_ptr in signals/slots | |||
|
66 | SCIQLOP_REGISTER_META_TYPE(SQPRANGE_REGISTRY, DateTimeRange) | |||
|
67 | ||||
|
68 | #endif // SCIQLOP_SQPRANGE_H |
@@ -0,0 +1,107 | |||||
|
1 | #ifndef SCIQLOP_IDATAPROVIDER_H | |||
|
2 | #define SCIQLOP_IDATAPROVIDER_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | #include <Common/deprecate.h> | |||
|
6 | ||||
|
7 | #include <memory> | |||
|
8 | ||||
|
9 | #include <QObject> | |||
|
10 | #include <QUuid> | |||
|
11 | ||||
|
12 | #include <Common/MetaTypes.h> | |||
|
13 | ||||
|
14 | #include <Data/DateTimeRange.h> | |||
|
15 | ||||
|
16 | #include <functional> | |||
|
17 | ||||
|
18 | class DataProviderParameters; | |||
|
19 | class IDataSeries; | |||
|
20 | DEPRECATE( | |||
|
21 | class QNetworkReply; | |||
|
22 | class QNetworkRequest; | |||
|
23 | ) | |||
|
24 | ||||
|
25 | /** | |||
|
26 | * @brief The IDataProvider interface aims to declare a data provider. | |||
|
27 | * | |||
|
28 | * A data provider is an entity that generates data and returns it according to various parameters | |||
|
29 | * (time interval, product to retrieve the data, etc.) | |||
|
30 | * | |||
|
31 | * @sa IDataSeries | |||
|
32 | */ | |||
|
33 | class SCIQLOP_CORE_EXPORT IDataProvider : public QObject { | |||
|
34 | ||||
|
35 | Q_OBJECT | |||
|
36 | public: | |||
|
37 | virtual ~IDataProvider() noexcept = default; | |||
|
38 | virtual std::shared_ptr<IDataProvider> clone() const = 0; | |||
|
39 | ||||
|
40 | DEPRECATE( | |||
|
41 | /** | |||
|
42 | * @brief requestDataLoading provide datas for the data identified by acqIdentifier and | |||
|
43 | * parameters | |||
|
44 | */ | |||
|
45 | virtual void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters ¶meters) | |||
|
46 | = 0; | |||
|
47 | ) | |||
|
48 | ||||
|
49 | virtual QUuid getData(const DataProviderParameters ¶meters){return QUuid::createUuid();} | |||
|
50 | ||||
|
51 | ||||
|
52 | DEPRECATE( | |||
|
53 | /** | |||
|
54 | * @brief requestDataAborting stop data loading of the data identified by acqIdentifier | |||
|
55 | */ | |||
|
56 | virtual void requestDataAborting(QUuid acqIdentifier) = 0; | |||
|
57 | ) | |||
|
58 | ||||
|
59 | virtual void abort(QUuid requestID){} | |||
|
60 | ||||
|
61 | signals: | |||
|
62 | DEPRECATE( | |||
|
63 | /** | |||
|
64 | * @brief dataProvided send dataSeries under dateTime and that corresponds of the data | |||
|
65 | * identified by acqIdentifier | |||
|
66 | */ | |||
|
67 | void dataProvided(QUuid acqIdentifier, std::shared_ptr<IDataSeries> dateSeriesAcquired, | |||
|
68 | const DateTimeRange &dataRangeAcquired); | |||
|
69 | ) | |||
|
70 | ||||
|
71 | void finished(QUuid requestID, std::shared_ptr<IDataSeries> dataSerie, | |||
|
72 | const DateTimeRange &range); | |||
|
73 | ||||
|
74 | DEPRECATE( | |||
|
75 | /** | |||
|
76 | * @brief dataProvidedProgress notify the progression of the data identifier by acqIdentifier | |||
|
77 | */ | |||
|
78 | void dataProvidedProgress(QUuid acqIdentifier, double progress); | |||
|
79 | ) | |||
|
80 | ||||
|
81 | void progress(QUuid requestID, double progress); | |||
|
82 | ||||
|
83 | DEPRECATE( | |||
|
84 | /** | |||
|
85 | * @brief dataProvidedFailed notify that data acquisition has failed | |||
|
86 | */ | |||
|
87 | void dataProvidedFailed(QUuid acqIdentifier); | |||
|
88 | ) | |||
|
89 | ||||
|
90 | void failed(QUuid requestID); | |||
|
91 | ||||
|
92 | /** | |||
|
93 | * @brief requestConstructed send a request for the data identified by acqIdentifier | |||
|
94 | * @callback is the methode call by the reply of the request when it is finished. | |||
|
95 | */ | |||
|
96 | DEPRECATE( | |||
|
97 | void requestConstructed(std::shared_ptr<QNetworkRequest> request, QUuid acqIdentifier, | |||
|
98 | std::function<void(QNetworkReply *, QUuid)> callback); | |||
|
99 | ) | |||
|
100 | }; | |||
|
101 | ||||
|
102 | // Required for using shared_ptr in signals/slots | |||
|
103 | SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_PTR_REGISTRY, std::shared_ptr<IDataProvider>) | |||
|
104 | SCIQLOP_REGISTER_META_TYPE(IDATAPROVIDER_FUNCTION_REGISTRY, | |||
|
105 | std::function<void(QNetworkReply *, QUuid)>) | |||
|
106 | ||||
|
107 | #endif // SCIQLOP_IDATAPROVIDER_H |
@@ -0,0 +1,102 | |||||
|
1 | #ifndef SCIQLOP_IDATASERIES_H | |||
|
2 | #define SCIQLOP_IDATASERIES_H | |||
|
3 | ||||
|
4 | #include <Common/MetaTypes.h> | |||
|
5 | #include <Data/DataSeriesIterator.h> | |||
|
6 | #include <Data/DateTimeRange.h> | |||
|
7 | #include <Data/Unit.h> | |||
|
8 | ||||
|
9 | #include <memory> | |||
|
10 | ||||
|
11 | #include <QString> | |||
|
12 | ||||
|
13 | template <int Dim> | |||
|
14 | class ArrayData; | |||
|
15 | ||||
|
16 | /** | |||
|
17 | * @brief The IDataSeries aims to declare a data series. | |||
|
18 | * | |||
|
19 | * A data series is an entity that contains at least : | |||
|
20 | * - one dataset representing the x-axis | |||
|
21 | * - one dataset representing the values | |||
|
22 | * | |||
|
23 | * Each dataset is represented by an ArrayData, and is associated with a unit. | |||
|
24 | * | |||
|
25 | * An ArrayData can be unidimensional or two-dimensional, depending on the implementation of the | |||
|
26 | * IDataSeries. The x-axis dataset is always unidimensional. | |||
|
27 | * | |||
|
28 | * @sa ArrayData | |||
|
29 | */ | |||
|
30 | class IDataSeries { | |||
|
31 | public: | |||
|
32 | virtual ~IDataSeries() noexcept = default; | |||
|
33 | ||||
|
34 | /// Returns the x-axis dataset | |||
|
35 | virtual std::shared_ptr<ArrayData<1> > xAxisData() = 0; | |||
|
36 | ||||
|
37 | /// Returns the x-axis dataset (as const) | |||
|
38 | virtual const std::shared_ptr<ArrayData<1> > xAxisData() const = 0; | |||
|
39 | ||||
|
40 | virtual Unit xAxisUnit() const = 0; | |||
|
41 | ||||
|
42 | /// @return the y-axis unit, if axis is defined, default unit otherwise | |||
|
43 | virtual Unit yAxisUnit() const = 0; | |||
|
44 | ||||
|
45 | virtual Unit valuesUnit() const = 0; | |||
|
46 | ||||
|
47 | virtual void merge(IDataSeries *dataSeries) = 0; | |||
|
48 | /// Removes from data series all entries whose value on the x-axis is not between min and max | |||
|
49 | virtual void purge(double min, double max) = 0; | |||
|
50 | ||||
|
51 | /// @todo Review the name and signature of this method | |||
|
52 | virtual std::shared_ptr<IDataSeries> subDataSeries(const DateTimeRange &range) = 0; | |||
|
53 | ||||
|
54 | virtual std::unique_ptr<IDataSeries> clone() const = 0; | |||
|
55 | ||||
|
56 | /// @return the total number of points contained in the data series | |||
|
57 | virtual int nbPoints() const = 0; | |||
|
58 | ||||
|
59 | /// @return the bounds of the y-axis axis (if defined) | |||
|
60 | virtual std::pair<double, double> yBounds() const = 0; | |||
|
61 | ||||
|
62 | // ///////// // | |||
|
63 | // Iterators // | |||
|
64 | // ///////// // | |||
|
65 | ||||
|
66 | virtual DataSeriesIterator cbegin() const = 0; | |||
|
67 | virtual DataSeriesIterator cend() const = 0; | |||
|
68 | virtual DataSeriesIterator begin() = 0; | |||
|
69 | virtual DataSeriesIterator end() = 0; | |||
|
70 | ||||
|
71 | /// @return the iterator to the first entry of the data series whose x-axis data is greater than | |||
|
72 | /// or equal to the value passed in parameter, or the end iterator if there is no matching value | |||
|
73 | virtual DataSeriesIterator minXAxisData(double minXAxisData) const = 0; | |||
|
74 | ||||
|
75 | /// @return the iterator to the last entry of the data series whose x-axis data is less than or | |||
|
76 | /// equal to the value passed in parameter, or the end iterator if there is no matching value | |||
|
77 | virtual DataSeriesIterator maxXAxisData(double maxXAxisData) const = 0; | |||
|
78 | ||||
|
79 | /// @return the iterators pointing to the range of data whose x-axis values are between min and | |||
|
80 | /// max passed in parameters | |||
|
81 | virtual std::pair<DataSeriesIterator, DataSeriesIterator> | |||
|
82 | xAxisRange(double minXAxisData, double maxXAxisData) const = 0; | |||
|
83 | ||||
|
84 | /// @return two iterators pointing to the data that have respectively the min and the max value | |||
|
85 | /// data of a data series' range. The search is performed for a given x-axis range. | |||
|
86 | /// @sa xAxisRange() | |||
|
87 | virtual std::pair<DataSeriesIterator, DataSeriesIterator> | |||
|
88 | valuesBounds(double minXAxisData, double maxXAxisData) const = 0; | |||
|
89 | ||||
|
90 | // /////// // | |||
|
91 | // Mutexes // | |||
|
92 | // /////// // | |||
|
93 | ||||
|
94 | virtual void lockRead() = 0; | |||
|
95 | virtual void lockWrite() = 0; | |||
|
96 | virtual void unlock() = 0; | |||
|
97 | }; | |||
|
98 | ||||
|
99 | // Required for using shared_ptr in signals/slots | |||
|
100 | SCIQLOP_REGISTER_META_TYPE(IDATASERIES_PTR_REGISTRY, std::shared_ptr<IDataSeries>) | |||
|
101 | ||||
|
102 | #endif // SCIQLOP_IDATASERIES_H |
@@ -0,0 +1,66 | |||||
|
1 | #ifndef SCIQLOP_OPTIONALAXIS_H | |||
|
2 | #define SCIQLOP_OPTIONALAXIS_H | |||
|
3 | ||||
|
4 | #include <Data/ArrayDataIterator.h> | |||
|
5 | ||||
|
6 | #include "CoreGlobal.h" | |||
|
7 | #include "Unit.h" | |||
|
8 | ||||
|
9 | #include <memory> | |||
|
10 | ||||
|
11 | template <int Dim> | |||
|
12 | class ArrayData; | |||
|
13 | ||||
|
14 | /** | |||
|
15 | * @brief The OptionalAxis class defines an optional data axis for a series of data. | |||
|
16 | * | |||
|
17 | * An optional data axis is an axis that can be defined or not for a data series. If defined, it | |||
|
18 | * contains a unit and data (1-dim ArrayData). It is then possible to access the data or the unit. | |||
|
19 | * In the case of an undefined axis, the axis has no data and no unit. The methods for accessing the | |||
|
20 | * data or the unit are always callable but will return undefined values. | |||
|
21 | * | |||
|
22 | * @sa DataSeries | |||
|
23 | * @sa ArrayData | |||
|
24 | */ | |||
|
25 | class SCIQLOP_CORE_EXPORT OptionalAxis { | |||
|
26 | public: | |||
|
27 | /// Ctor for an undefined axis | |||
|
28 | explicit OptionalAxis(); | |||
|
29 | /// Ctor for a defined axis | |||
|
30 | /// @param data the axis' data | |||
|
31 | /// @param unit the axis' unit | |||
|
32 | /// @throws std::invalid_argument if no data is associated to the axis | |||
|
33 | explicit OptionalAxis(std::shared_ptr<ArrayData<1> > data, Unit unit); | |||
|
34 | ||||
|
35 | /// Copy ctor | |||
|
36 | OptionalAxis(const OptionalAxis &other); | |||
|
37 | /// Assignment operator | |||
|
38 | OptionalAxis &operator=(OptionalAxis other); | |||
|
39 | ||||
|
40 | /// @return the flag that indicates if the axis is defined or not | |||
|
41 | bool isDefined() const; | |||
|
42 | ||||
|
43 | ///@return the min and max values of the data on the axis, NaN values if there is no data | |||
|
44 | std::pair<double, double> bounds() const; | |||
|
45 | ||||
|
46 | /// @return the number of data on the axis, 0 if the axis is not defined | |||
|
47 | int size() const; | |||
|
48 | /// @return the unit of the axis, an empty unit if the axis is not defined | |||
|
49 | Unit unit() const; | |||
|
50 | ||||
|
51 | bool operator==(const OptionalAxis &other); | |||
|
52 | bool operator!=(const OptionalAxis &other); | |||
|
53 | ||||
|
54 | // Iterators on data | |||
|
55 | ArrayDataIterator begin(); | |||
|
56 | ArrayDataIterator end(); | |||
|
57 | ArrayDataIterator cbegin() const; | |||
|
58 | ArrayDataIterator cend() const; | |||
|
59 | ||||
|
60 | private: | |||
|
61 | bool m_Defined; ///< Axis is defined or not | |||
|
62 | std::shared_ptr<ArrayData<1> > m_Data; ///< Axis' data | |||
|
63 | Unit m_Unit; ///< Axis' unit | |||
|
64 | }; | |||
|
65 | ||||
|
66 | #endif // SCIQLOP_OPTIONALAXIS_H |
@@ -0,0 +1,27 | |||||
|
1 | #ifndef SCIQLOP_SCALARSERIES_H | |||
|
2 | #define SCIQLOP_SCALARSERIES_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <Data/DataSeries.h> | |||
|
7 | ||||
|
8 | /** | |||
|
9 | * @brief The ScalarSeries class is the implementation for a data series representing a scalar. | |||
|
10 | */ | |||
|
11 | class SCIQLOP_CORE_EXPORT ScalarSeries : public DataSeries<1> { | |||
|
12 | public: | |||
|
13 | /** | |||
|
14 | * Ctor with two vectors. The vectors must have the same size, otherwise a ScalarSeries with no | |||
|
15 | * values will be created. | |||
|
16 | * @param xAxisData x-axis data | |||
|
17 | * @param valuesData values data | |||
|
18 | */ | |||
|
19 | explicit ScalarSeries(std::vector<double> xAxisData, std::vector<double> valuesData, | |||
|
20 | const Unit &xAxisUnit, const Unit &valuesUnit); | |||
|
21 | ||||
|
22 | std::unique_ptr<IDataSeries> clone() const override; | |||
|
23 | ||||
|
24 | std::shared_ptr<IDataSeries> subDataSeries(const DateTimeRange &range) override; | |||
|
25 | }; | |||
|
26 | ||||
|
27 | #endif // SCIQLOP_SCALARSERIES_H |
@@ -0,0 +1,40 | |||||
|
1 | #ifndef SCIQLOP_SPECTROGRAMSERIES_H | |||
|
2 | #define SCIQLOP_SPECTROGRAMSERIES_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <Data/DataSeries.h> | |||
|
7 | ||||
|
8 | /** | |||
|
9 | * @brief The SpectrogramSeries class is the implementation for a data series representing a | |||
|
10 | * spectrogram. | |||
|
11 | * | |||
|
12 | * It defines values on a x-axis and a y-axis. | |||
|
13 | */ | |||
|
14 | class SCIQLOP_CORE_EXPORT SpectrogramSeries : public DataSeries<2> { | |||
|
15 | public: | |||
|
16 | /// Ctor | |||
|
17 | explicit SpectrogramSeries(std::vector<double> xAxisData, std::vector<double> yAxisData, | |||
|
18 | std::vector<double> valuesData, const Unit &xAxisUnit, | |||
|
19 | const Unit &yAxisUnit, const Unit &valuesUnit, | |||
|
20 | double xResolution = std::numeric_limits<double>::quiet_NaN()); | |||
|
21 | ||||
|
22 | /// Ctor directly with the y-axis | |||
|
23 | explicit SpectrogramSeries(std::shared_ptr<ArrayData<1> > xAxisData, const Unit &xAxisUnit, | |||
|
24 | std::shared_ptr<ArrayData<2> > valuesData, const Unit &valuesUnit, | |||
|
25 | OptionalAxis yAxis, | |||
|
26 | double xResolution = std::numeric_limits<double>::quiet_NaN()); | |||
|
27 | ||||
|
28 | /// @sa DataSeries::clone() | |||
|
29 | std::unique_ptr<IDataSeries> clone() const override; | |||
|
30 | ||||
|
31 | /// @sa DataSeries::subDataSeries() | |||
|
32 | std::shared_ptr<IDataSeries> subDataSeries(const DateTimeRange &range) override; | |||
|
33 | ||||
|
34 | inline double xResolution() const noexcept { return m_XResolution; } | |||
|
35 | ||||
|
36 | private: | |||
|
37 | double m_XResolution; ///< Resolution used on x-axis to build the spectrogram | |||
|
38 | }; | |||
|
39 | ||||
|
40 | #endif // SCIQLOP_SPECTROGRAMSERIES_H |
@@ -0,0 +1,112 | |||||
|
1 | #ifndef SCIQLOP_SQPITERATOR_H | |||
|
2 | #define SCIQLOP_SQPITERATOR_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | /** | |||
|
7 | * @brief The SqpIterator class represents an iterator used in SciQlop. It defines all operators | |||
|
8 | * needed for a standard forward iterator | |||
|
9 | * @tparam T the type of object handled in iterator | |||
|
10 | * @sa http://www.cplusplus.com/reference/iterator/ | |||
|
11 | */ | |||
|
12 | template <typename T> | |||
|
13 | class SCIQLOP_CORE_EXPORT SqpIterator { | |||
|
14 | public: | |||
|
15 | using iterator_category = std::random_access_iterator_tag; | |||
|
16 | using value_type = const T; | |||
|
17 | using difference_type = std::ptrdiff_t; | |||
|
18 | using pointer = value_type *; | |||
|
19 | using reference = value_type &; | |||
|
20 | ||||
|
21 | explicit SqpIterator(T value) : m_CurrentValue{std::move(value)} {} | |||
|
22 | ||||
|
23 | virtual ~SqpIterator() noexcept = default; | |||
|
24 | SqpIterator(const SqpIterator &) = default; | |||
|
25 | SqpIterator &operator=(SqpIterator other) | |||
|
26 | { | |||
|
27 | swap(m_CurrentValue, other.m_CurrentValue); | |||
|
28 | return *this; | |||
|
29 | } | |||
|
30 | ||||
|
31 | SqpIterator &operator++() | |||
|
32 | { | |||
|
33 | m_CurrentValue.next(); | |||
|
34 | return *this; | |||
|
35 | } | |||
|
36 | ||||
|
37 | SqpIterator &operator--() | |||
|
38 | { | |||
|
39 | m_CurrentValue.prev(); | |||
|
40 | return *this; | |||
|
41 | } | |||
|
42 | ||||
|
43 | SqpIterator operator++(int)const | |||
|
44 | { | |||
|
45 | auto result = *this; | |||
|
46 | this->operator++(); | |||
|
47 | return result; | |||
|
48 | } | |||
|
49 | SqpIterator operator--(int)const | |||
|
50 | { | |||
|
51 | auto result = *this; | |||
|
52 | this->operator--(); | |||
|
53 | return result; | |||
|
54 | } | |||
|
55 | ||||
|
56 | SqpIterator &operator+=(int offset) | |||
|
57 | { | |||
|
58 | if (offset >= 0) { | |||
|
59 | m_CurrentValue.next(offset); | |||
|
60 | } | |||
|
61 | else { | |||
|
62 | while (offset++) { | |||
|
63 | m_CurrentValue.prev(); | |||
|
64 | } | |||
|
65 | } | |||
|
66 | ||||
|
67 | return *this; | |||
|
68 | } | |||
|
69 | SqpIterator &operator-=(int offset) { return *this += -offset; } | |||
|
70 | ||||
|
71 | SqpIterator operator+(int offset) const | |||
|
72 | { | |||
|
73 | auto result = *this; | |||
|
74 | result += offset; | |||
|
75 | return result; | |||
|
76 | } | |||
|
77 | SqpIterator operator-(int offset) const | |||
|
78 | { | |||
|
79 | auto result = *this; | |||
|
80 | result -= offset; | |||
|
81 | return result; | |||
|
82 | } | |||
|
83 | ||||
|
84 | int operator-(const SqpIterator &other) const | |||
|
85 | { | |||
|
86 | return m_CurrentValue.distance(other.m_CurrentValue); | |||
|
87 | } | |||
|
88 | ||||
|
89 | const T *operator->() const { return &m_CurrentValue; } | |||
|
90 | const T &operator*() const { return m_CurrentValue; } | |||
|
91 | T *operator->() { return &m_CurrentValue; } | |||
|
92 | T &operator*() { return m_CurrentValue; } | |||
|
93 | T &operator[](int offset) const { return m_CurrentValue.advance(offset); } | |||
|
94 | ||||
|
95 | bool operator==(const SqpIterator &other) const | |||
|
96 | { | |||
|
97 | return m_CurrentValue.equals(other.m_CurrentValue); | |||
|
98 | } | |||
|
99 | bool operator!=(const SqpIterator &other) const { return !(*this == other); } | |||
|
100 | bool operator>(const SqpIterator &other) const { return other.m_CurrentValue.lowerThan(*this); } | |||
|
101 | bool operator<(const SqpIterator &other) const | |||
|
102 | { | |||
|
103 | return m_CurrentValue.lowerThan(other.m_CurrentValue); | |||
|
104 | } | |||
|
105 | bool operator>=(const SqpIterator &other) const { return !(*this < other); } | |||
|
106 | bool operator<=(const SqpIterator &other) const { return !(*this > other); } | |||
|
107 | ||||
|
108 | private: | |||
|
109 | T m_CurrentValue; | |||
|
110 | }; | |||
|
111 | ||||
|
112 | #endif // SCIQLOP_SQPITERATOR_H |
@@ -0,0 +1,27 | |||||
|
1 | #ifndef SCIQLOP_UNIT_H | |||
|
2 | #define SCIQLOP_UNIT_H | |||
|
3 | ||||
|
4 | #include <Common/MetaTypes.h> | |||
|
5 | ||||
|
6 | #include <QString> | |||
|
7 | #include <tuple> | |||
|
8 | ||||
|
9 | struct Unit { | |||
|
10 | explicit Unit(const QString &name = {}, bool timeUnit = false) | |||
|
11 | : m_Name{name}, m_TimeUnit{timeUnit} | |||
|
12 | { | |||
|
13 | } | |||
|
14 | ||||
|
15 | inline bool operator==(const Unit &other) const | |||
|
16 | { | |||
|
17 | return std::tie(m_Name, m_TimeUnit) == std::tie(other.m_Name, other.m_TimeUnit); | |||
|
18 | } | |||
|
19 | inline bool operator!=(const Unit &other) const { return !(*this == other); } | |||
|
20 | ||||
|
21 | QString m_Name; ///< Unit name | |||
|
22 | bool m_TimeUnit; ///< The unit is a unit of time (UTC) | |||
|
23 | }; | |||
|
24 | ||||
|
25 | SCIQLOP_REGISTER_META_TYPE(UNIT_REGISTRY, Unit) | |||
|
26 | ||||
|
27 | #endif // SCIQLOP_UNIT_H |
@@ -0,0 +1,26 | |||||
|
1 | #ifndef SCIQLOP_VARIABLEREQUEST_H | |||
|
2 | #define SCIQLOP_VARIABLEREQUEST_H | |||
|
3 | ||||
|
4 | #include <QObject> | |||
|
5 | ||||
|
6 | #include <QUuid> | |||
|
7 | ||||
|
8 | #include <Common/MetaTypes.h> | |||
|
9 | #include <Data/IDataSeries.h> | |||
|
10 | #include <Data/DateTimeRange.h> | |||
|
11 | ||||
|
12 | #include <memory> | |||
|
13 | ||||
|
14 | /** | |||
|
15 | * @brief The VariableRequest struct holds the information of an acquisition request | |||
|
16 | */ | |||
|
17 | struct VariableRequest { | |||
|
18 | QUuid m_VariableGroupId; | |||
|
19 | DateTimeRange m_RangeRequested; | |||
|
20 | DateTimeRange m_CacheRangeRequested; | |||
|
21 | std::shared_ptr<IDataSeries> m_DataSeries; | |||
|
22 | }; | |||
|
23 | ||||
|
24 | SCIQLOP_REGISTER_META_TYPE(VARIABLEREQUEST_REGISTRY, VariableRequest) | |||
|
25 | ||||
|
26 | #endif // SCIQLOP_VARIABLEREQUEST_H |
@@ -0,0 +1,34 | |||||
|
1 | #ifndef SCIQLOP_VECTORSERIES_H | |||
|
2 | #define SCIQLOP_VECTORSERIES_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <Data/DataSeries.h> | |||
|
7 | ||||
|
8 | /** | |||
|
9 | * @brief The VectorSeries class is the implementation for a data series representing a vector. | |||
|
10 | */ | |||
|
11 | class SCIQLOP_CORE_EXPORT VectorSeries : public DataSeries<2> { | |||
|
12 | public: | |||
|
13 | /** | |||
|
14 | * Ctor with three vectors (one per component). The vectors must have the same size, otherwise a | |||
|
15 | * ScalarSeries with no values will be created. | |||
|
16 | * @param xAxisData x-axis data | |||
|
17 | * @param xvaluesData x-values data | |||
|
18 | * @param yvaluesData y-values data | |||
|
19 | * @param zvaluesData z-values data | |||
|
20 | */ | |||
|
21 | explicit VectorSeries(std::vector<double> xAxisData, std::vector<double> xValuesData, | |||
|
22 | std::vector<double> yValuesData, std::vector<double> zValuesData, | |||
|
23 | const Unit &xAxisUnit, const Unit &valuesUnit); | |||
|
24 | ||||
|
25 | /// Default Ctor | |||
|
26 | explicit VectorSeries(std::vector<double> xAxisData, std::vector<double> valuesData, | |||
|
27 | const Unit &xAxisUnit, const Unit &valuesUnit); | |||
|
28 | ||||
|
29 | std::unique_ptr<IDataSeries> clone() const; | |||
|
30 | ||||
|
31 | std::shared_ptr<IDataSeries> subDataSeries(const DateTimeRange &range) override; | |||
|
32 | }; | |||
|
33 | ||||
|
34 | #endif // SCIQLOP_VECTORSERIES_H |
@@ -0,0 +1,106 | |||||
|
1 | #ifndef SCIQLOP_DATASOURCECONTROLLER_H | |||
|
2 | #define SCIQLOP_DATASOURCECONTROLLER_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <QLoggingCategory> | |||
|
7 | #include <QObject> | |||
|
8 | #include <QUuid> | |||
|
9 | ||||
|
10 | #include <Common/spimpl.h> | |||
|
11 | ||||
|
12 | Q_DECLARE_LOGGING_CATEGORY(LOG_DataSourceController) | |||
|
13 | ||||
|
14 | class DataSourceItem; | |||
|
15 | class IDataProvider; | |||
|
16 | ||||
|
17 | /** | |||
|
18 | * @brief The DataSourceController class aims to make the link between SciQlop and its plugins. This | |||
|
19 | * is the intermediate class that SciQlop has to use in the way to connect a data source. Please | |||
|
20 | * first use register method to initialize a plugin specified by its metadata name (JSON plugin | |||
|
21 | * source) then others specifics method will be able to access it. You can load a data source driver | |||
|
22 | * plugin then create a data source. | |||
|
23 | */ | |||
|
24 | class SCIQLOP_CORE_EXPORT DataSourceController : public QObject { | |||
|
25 | Q_OBJECT | |||
|
26 | public: | |||
|
27 | explicit DataSourceController(QObject *parent = 0); | |||
|
28 | virtual ~DataSourceController(); | |||
|
29 | ||||
|
30 | /** | |||
|
31 | * Registers a data source. The method delivers a unique id that can be used afterwards to | |||
|
32 | * access to the data source properties (structure, connection parameters, data provider, etc.) | |||
|
33 | * @param dataSourceName the name of the data source | |||
|
34 | * @return the unique id with which the data source has been registered | |||
|
35 | */ | |||
|
36 | QUuid registerDataSource(const QString &dataSourceName) noexcept; | |||
|
37 | ||||
|
38 | /** | |||
|
39 | * Sets the structure of a data source. The controller takes ownership of the structure. | |||
|
40 | * @param dataSourceUid the unique id with which the data source has been registered into the | |||
|
41 | * controller. If it is invalid, the method has no effect. | |||
|
42 | * @param dataSourceItem the structure of the data source. It must be not null to be registered | |||
|
43 | * @sa registerDataSource() | |||
|
44 | */ | |||
|
45 | void setDataSourceItem(const QUuid &dataSourceUid, | |||
|
46 | std::unique_ptr<DataSourceItem> dataSourceItem) noexcept; | |||
|
47 | ||||
|
48 | /** | |||
|
49 | * Sets the data provider used to retrieve data from of a data source. The controller takes | |||
|
50 | * ownership of the provider. | |||
|
51 | * @param dataSourceUid the unique id with which the data source has been registered into the | |||
|
52 | * controller. If it is invalid, the method has no effect. | |||
|
53 | * @param dataProvider the provider of the data source | |||
|
54 | * @sa registerDataSource() | |||
|
55 | */ | |||
|
56 | void setDataProvider(const QUuid &dataSourceUid, | |||
|
57 | std::unique_ptr<IDataProvider> dataProvider) noexcept; | |||
|
58 | ||||
|
59 | /** | |||
|
60 | * Loads an item (product) as a variable in SciQlop | |||
|
61 | * @param dataSourceUid the unique id of the data source containing the item. It is used to get | |||
|
62 | * the data provider associated to the data source, and pass it to for the variable creation | |||
|
63 | * @param productItem the item to load | |||
|
64 | */ | |||
|
65 | void loadProductItem(const QUuid &dataSourceUid, const DataSourceItem &productItem) noexcept; | |||
|
66 | ||||
|
67 | /// Returns the MIME data associated to a list of product meta data | |||
|
68 | static QByteArray mimeDataForProductsData(const QVariantList &productsData); | |||
|
69 | ||||
|
70 | /// Returns the list of meta data contained in a MIME data | |||
|
71 | static QVariantList productsDataForMimeData(const QByteArray &mimeData); | |||
|
72 | ||||
|
73 | public slots: | |||
|
74 | /// Manage init/end of the controller | |||
|
75 | void initialize(); | |||
|
76 | void finalize(); | |||
|
77 | ||||
|
78 | /// Request the creation of a variable from the ID_DATA_KEY of a product | |||
|
79 | void requestVariableFromProductIdKey(const QString &datasourceIdKey); | |||
|
80 | ||||
|
81 | /// Request the creation of a variable from metadata of a product | |||
|
82 | void requestVariable(const QVariantHash &productData); | |||
|
83 | ||||
|
84 | signals: | |||
|
85 | /// Signal emitted when a structure has been set for a data source | |||
|
86 | void dataSourceItemSet(DataSourceItem *dataSourceItem); | |||
|
87 | ||||
|
88 | /** | |||
|
89 | * Signal emitted when a variable creation is asked for a product | |||
|
90 | * @param variableName the name of the variable | |||
|
91 | * @param variableMetadata the metadata of the variable | |||
|
92 | * @param variableProvider the provider that will be used to retrieve the data of the variable | |||
|
93 | * (can be null) | |||
|
94 | */ | |||
|
95 | void variableCreationRequested(const QString &variableName, | |||
|
96 | const QVariantHash &variableMetadata, | |||
|
97 | std::shared_ptr<IDataProvider> variableProvider); | |||
|
98 | ||||
|
99 | private: | |||
|
100 | void waitForFinish(); | |||
|
101 | ||||
|
102 | class DataSourceControllerPrivate; | |||
|
103 | spimpl::unique_impl_ptr<DataSourceControllerPrivate> impl; | |||
|
104 | }; | |||
|
105 | ||||
|
106 | #endif // SCIQLOP_DATASOURCECONTROLLER_H |
@@ -0,0 +1,164 | |||||
|
1 | #ifndef SCIQLOP_DATASOURCEITEM_H | |||
|
2 | #define SCIQLOP_DATASOURCEITEM_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <Common/spimpl.h> | |||
|
7 | ||||
|
8 | #include <QVariant> | |||
|
9 | #include <QVector> | |||
|
10 | ||||
|
11 | class DataSourceItemAction; | |||
|
12 | ||||
|
13 | /** | |||
|
14 | * Possible types of an item | |||
|
15 | */ | |||
|
16 | enum class DataSourceItemType { NODE, PRODUCT, COMPONENT }; | |||
|
17 | ||||
|
18 | /** | |||
|
19 | * @brief The DataSourceItem class aims to represent a structure element of a data source. | |||
|
20 | * A data source has a tree structure that is made up of a main DataSourceItem object (root) | |||
|
21 | * containing other DataSourceItem objects (children). | |||
|
22 | * For each DataSourceItem can be associated a set of data representing it. | |||
|
23 | */ | |||
|
24 | class SCIQLOP_CORE_EXPORT DataSourceItem { | |||
|
25 | public: | |||
|
26 | /// Key associated with the name of the item | |||
|
27 | static const QString NAME_DATA_KEY; | |||
|
28 | /// Key associated with the plugin of the item | |||
|
29 | static const QString PLUGIN_DATA_KEY; | |||
|
30 | /// Key associated with a unique id of the plugin | |||
|
31 | static const QString ID_DATA_KEY; | |||
|
32 | ||||
|
33 | explicit DataSourceItem(DataSourceItemType type, const QString &name); | |||
|
34 | explicit DataSourceItem(DataSourceItemType type, QVariantHash data = {}); | |||
|
35 | ||||
|
36 | std::unique_ptr<DataSourceItem> clone() const; | |||
|
37 | ||||
|
38 | /// @return the actions of the item as a vector | |||
|
39 | QVector<DataSourceItemAction *> actions() const noexcept; | |||
|
40 | ||||
|
41 | /** | |||
|
42 | * Adds an action to the item. The item takes ownership of the action, and the action is | |||
|
43 | * automatically associated to the item | |||
|
44 | * @param action the action to add | |||
|
45 | */ | |||
|
46 | void addAction(std::unique_ptr<DataSourceItemAction> action) noexcept; | |||
|
47 | ||||
|
48 | /** | |||
|
49 | * Adds a child to the item. The item takes ownership of the child. | |||
|
50 | * @param child the child to add | |||
|
51 | */ | |||
|
52 | void appendChild(std::unique_ptr<DataSourceItem> child) noexcept; | |||
|
53 | ||||
|
54 | /** | |||
|
55 | * Returns the item's child associated to an index | |||
|
56 | * @param childIndex the index to search | |||
|
57 | * @return a pointer to the child if index is valid, nullptr otherwise | |||
|
58 | */ | |||
|
59 | DataSourceItem *child(int childIndex) const noexcept; | |||
|
60 | ||||
|
61 | int childCount() const noexcept; | |||
|
62 | ||||
|
63 | /** | |||
|
64 | * Get the data associated to a key | |||
|
65 | * @param key the key to search | |||
|
66 | * @return the data found if key is valid, default QVariant otherwise | |||
|
67 | */ | |||
|
68 | QVariant data(const QString &key) const noexcept; | |||
|
69 | ||||
|
70 | /// Gets all data | |||
|
71 | QVariantHash data() const noexcept; | |||
|
72 | ||||
|
73 | /** | |||
|
74 | * Merge in the item the source item passed as parameter. | |||
|
75 | * | |||
|
76 | * The merge is done by adding as child of the item the complete tree represented by the source | |||
|
77 | * item. If a part of the tree already exists in the item (based on the name of the nodes), it | |||
|
78 | * is merged by completing the existing tree by items "leaves" (products, components or nodes | |||
|
79 | * with no child). | |||
|
80 | * | |||
|
81 | * For example, with item representing the tree: | |||
|
82 | * R (root node) | |||
|
83 | * - N1 (node) | |||
|
84 | * -- N11 (node) | |||
|
85 | * --- P1 (product) | |||
|
86 | * --- P2 (product) | |||
|
87 | * - N2 (node) | |||
|
88 | * | |||
|
89 | * and the source item representing the tree: | |||
|
90 | * N1 (root node) | |||
|
91 | * - N11 (node) | |||
|
92 | * -- P3 (product) | |||
|
93 | * - N12 (node) | |||
|
94 | * | |||
|
95 | * The leaves of the source item to merge into the item are N1/N11/P3 and N1/N12 => we therefore | |||
|
96 | * have the following merge result: | |||
|
97 | * R | |||
|
98 | * - N1 | |||
|
99 | * -- N11 | |||
|
100 | * --- P1 | |||
|
101 | * --- P2 | |||
|
102 | * --- P3 (added leaf) | |||
|
103 | * -- N12 (added leaf) | |||
|
104 | * | |||
|
105 | * @param item the source item | |||
|
106 | * @remarks No control is performed on products or components that are merged into the same tree | |||
|
107 | * part (two products or components may have the same name) | |||
|
108 | * @remarks the merge is made by copy (source item is not changed and still exists after the | |||
|
109 | * operation) | |||
|
110 | */ | |||
|
111 | void merge(const DataSourceItem &item); | |||
|
112 | ||||
|
113 | bool isRoot() const noexcept; | |||
|
114 | ||||
|
115 | QString name() const noexcept; | |||
|
116 | ||||
|
117 | /** | |||
|
118 | * Get the item's parent | |||
|
119 | * @return a pointer to the parent if it exists, nullptr if the item is a root | |||
|
120 | */ | |||
|
121 | DataSourceItem *parentItem() const noexcept; | |||
|
122 | ||||
|
123 | /** | |||
|
124 | * Gets the item's root | |||
|
125 | * @return the top parent, the item itself if it's the root item | |||
|
126 | */ | |||
|
127 | const DataSourceItem &rootItem() const noexcept; | |||
|
128 | ||||
|
129 | /** | |||
|
130 | * Sets or appends a value to a key | |||
|
131 | * @param key the key | |||
|
132 | * @param value the value | |||
|
133 | * @param append if true, the value is added to the values already existing for the key, | |||
|
134 | * otherwise it replaces the existing values | |||
|
135 | */ | |||
|
136 | void setData(const QString &key, const QVariant &value, bool append = false) noexcept; | |||
|
137 | ||||
|
138 | DataSourceItemType type() const noexcept; | |||
|
139 | ||||
|
140 | /** | |||
|
141 | * @brief Searches the first child matching the specified data. | |||
|
142 | * @param data The data to search. | |||
|
143 | * @param recursive So the search recursively. | |||
|
144 | * @return the item matching the data or nullptr if it was not found. | |||
|
145 | */ | |||
|
146 | DataSourceItem *findItem(const QVariantHash &data, bool recursive); | |||
|
147 | ||||
|
148 | /** | |||
|
149 | * @brief Searches the first child matching the specified \p ID_DATA_KEY in its metadata. | |||
|
150 | * @param id The id to search. | |||
|
151 | * @param recursive So the search recursively. | |||
|
152 | * @return the item matching the data or nullptr if it was not found. | |||
|
153 | */ | |||
|
154 | DataSourceItem *findItem(const QString &datasourceIdKey, bool recursive); | |||
|
155 | ||||
|
156 | bool operator==(const DataSourceItem &other); | |||
|
157 | bool operator!=(const DataSourceItem &other); | |||
|
158 | ||||
|
159 | private: | |||
|
160 | class DataSourceItemPrivate; | |||
|
161 | spimpl::unique_impl_ptr<DataSourceItemPrivate> impl; | |||
|
162 | }; | |||
|
163 | ||||
|
164 | #endif // SCIQLOP_DATASOURCEITEMMODEL_H |
@@ -0,0 +1,54 | |||||
|
1 | #ifndef SCIQLOP_DATASOURCEITEMACTION_H | |||
|
2 | #define SCIQLOP_DATASOURCEITEMACTION_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <Common/spimpl.h> | |||
|
7 | ||||
|
8 | #include <QLoggingCategory> | |||
|
9 | #include <QObject> | |||
|
10 | ||||
|
11 | #include <functional> | |||
|
12 | ||||
|
13 | Q_DECLARE_LOGGING_CATEGORY(LOG_DataSourceItemAction) | |||
|
14 | ||||
|
15 | class DataSourceItem; | |||
|
16 | ||||
|
17 | /** | |||
|
18 | * @brief The DataSourceItemAction class represents an action on a data source item. | |||
|
19 | * | |||
|
20 | * An action is a function that will be executed when the slot execute() is called. | |||
|
21 | */ | |||
|
22 | class SCIQLOP_CORE_EXPORT DataSourceItemAction : public QObject { | |||
|
23 | ||||
|
24 | Q_OBJECT | |||
|
25 | ||||
|
26 | public: | |||
|
27 | /// Signature of the function associated to the action | |||
|
28 | using ExecuteFunction = std::function<void(DataSourceItem &dataSourceItem)>; | |||
|
29 | ||||
|
30 | /** | |||
|
31 | * Ctor | |||
|
32 | * @param name the name of the action | |||
|
33 | * @param fun the function that will be called when the action is executed | |||
|
34 | * @sa execute() | |||
|
35 | */ | |||
|
36 | explicit DataSourceItemAction(const QString &name, ExecuteFunction fun); | |||
|
37 | ||||
|
38 | std::unique_ptr<DataSourceItemAction> clone() const; | |||
|
39 | ||||
|
40 | QString name() const noexcept; | |||
|
41 | ||||
|
42 | /// Sets the data source item concerned by the action | |||
|
43 | void setDataSourceItem(DataSourceItem *dataSourceItem) noexcept; | |||
|
44 | ||||
|
45 | public slots: | |||
|
46 | /// Executes the action | |||
|
47 | void execute(); | |||
|
48 | ||||
|
49 | private: | |||
|
50 | class DataSourceItemActionPrivate; | |||
|
51 | spimpl::unique_impl_ptr<DataSourceItemActionPrivate> impl; | |||
|
52 | }; | |||
|
53 | ||||
|
54 | #endif // SCIQLOP_DATASOURCEITEMACTION_H |
@@ -0,0 +1,15 | |||||
|
1 | #ifndef SCIQLOP_DATASOURCEITEMMERGEHELPER_H | |||
|
2 | #define SCIQLOP_DATASOURCEITEMMERGEHELPER_H | |||
|
3 | ||||
|
4 | class DataSourceItem; | |||
|
5 | ||||
|
6 | /** | |||
|
7 | * @brief The DataSourceItemMergeHelper struct is used to merge two data source items | |||
|
8 | * @sa DataSourceItem::merge() | |||
|
9 | */ | |||
|
10 | struct DataSourceItemMergeHelper { | |||
|
11 | /// Merges source item into dest item | |||
|
12 | static void merge(const DataSourceItem &source, DataSourceItem &dest); | |||
|
13 | }; | |||
|
14 | ||||
|
15 | #endif // SCIQLOP_DATASOURCEITEMMERGEHELPER_H |
@@ -0,0 +1,72 | |||||
|
1 | #ifndef DOWNLOADER_H | |||
|
2 | #define DOWNLOADER_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | #include "Response.h" | |||
|
6 | ||||
|
7 | #include <Common/MetaTypes.h> | |||
|
8 | #include <Common/spimpl.h> | |||
|
9 | #include <functional> | |||
|
10 | ||||
|
11 | #include <QString> | |||
|
12 | #include <QByteArray> | |||
|
13 | #include <QUuid> | |||
|
14 | ||||
|
15 | /** | |||
|
16 | * @brief The Downloader handles all data donwloads in SciQLOP. | |||
|
17 | * | |||
|
18 | * Simple synchronous GET example: | |||
|
19 | * @code{.cpp} | |||
|
20 | * auto response = Downloader::get("http://example.com") | |||
|
21 | * std::cout << "Status code: " << response.status_code() << std::endl << "Data: " << response.data().toStdString() << std::endl; | |||
|
22 | * @endcode | |||
|
23 | * | |||
|
24 | * @note | |||
|
25 | * This is a quick and KISS implementation using QNetworkAccessManager isolating from Qt stuff (Signal/slots). | |||
|
26 | * This could be impemented with a different backend in the future. | |||
|
27 | * | |||
|
28 | * @sa Response | |||
|
29 | */ | |||
|
30 | class SCIQLOP_CORE_EXPORT Downloader{ | |||
|
31 | public: | |||
|
32 | /** | |||
|
33 | * @brief does a synchronous GET request on the given url | |||
|
34 | * @param url | |||
|
35 | * @param user | |||
|
36 | * @param passwd | |||
|
37 | * @return Response object containing request data and http status code | |||
|
38 | * @sa Downloader::getAsync | |||
|
39 | */ | |||
|
40 | static Response get(const QString& url, const QString& user="", const QString& passwd=""); | |||
|
41 | /** | |||
|
42 | * @brief does an asynchronous GET request on the given url | |||
|
43 | * @param url | |||
|
44 | * @param callback | |||
|
45 | * @param user | |||
|
46 | * @param passwd | |||
|
47 | * @return QUuid an unique identifier associated to this request | |||
|
48 | * @sa Downloader::get, Downloader::downloadFinished | |||
|
49 | */ | |||
|
50 | static QUuid getAsync(const QString& url, std::function<void (QUuid, Response)> callback, const QString& user="", const QString& passwd=""); | |||
|
51 | /** | |||
|
52 | * @brief downloadFinished | |||
|
53 | * @param uuid | |||
|
54 | * @return true if the request associated to this uuid is complete | |||
|
55 | */ | |||
|
56 | static bool downloadFinished(QUuid uuid); | |||
|
57 | ||||
|
58 | static Downloader& instance() | |||
|
59 | { | |||
|
60 | static Downloader inst; | |||
|
61 | return inst; | |||
|
62 | } | |||
|
63 | ||||
|
64 | private: | |||
|
65 | class p_Downloader; | |||
|
66 | ||||
|
67 | explicit Downloader(); | |||
|
68 | ||||
|
69 | spimpl::unique_impl_ptr<Downloader::p_Downloader> impl; | |||
|
70 | }; | |||
|
71 | ||||
|
72 | #endif // DOWNLOADER_H |
@@ -0,0 +1,53 | |||||
|
1 | #ifndef SCIQLOP_NETWORKCONTROLLER_H | |||
|
2 | #define SCIQLOP_NETWORKCONTROLLER_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <QLoggingCategory> | |||
|
7 | #include <QObject> | |||
|
8 | #include <QUuid> | |||
|
9 | ||||
|
10 | #include <Common/MetaTypes.h> | |||
|
11 | #include <Common/spimpl.h> | |||
|
12 | #include <functional> | |||
|
13 | ||||
|
14 | Q_DECLARE_LOGGING_CATEGORY(LOG_NetworkController) | |||
|
15 | ||||
|
16 | class QNetworkReply; | |||
|
17 | class QNetworkRequest; | |||
|
18 | ||||
|
19 | /** | |||
|
20 | * @brief The NetworkController class aims to handle all network connection of SciQlop. | |||
|
21 | */ | |||
|
22 | class SCIQLOP_CORE_EXPORT NetworkController : public QObject { | |||
|
23 | Q_OBJECT | |||
|
24 | public: | |||
|
25 | explicit NetworkController(QObject *parent = 0); | |||
|
26 | ||||
|
27 | void initialize(); | |||
|
28 | void finalize(); | |||
|
29 | ||||
|
30 | public slots: | |||
|
31 | /// Execute request and call callback when the reply is finished. Identifier is attached to the | |||
|
32 | /// callback | |||
|
33 | void onProcessRequested(std::shared_ptr<QNetworkRequest> request, QUuid identifier, | |||
|
34 | std::function<void(QNetworkReply *, QUuid)> callback); | |||
|
35 | /// Cancel the request of identifier | |||
|
36 | void onReplyCanceled(QUuid identifier); | |||
|
37 | ||||
|
38 | signals: | |||
|
39 | void replyFinished(QNetworkReply *reply, QUuid identifier); | |||
|
40 | void replyDownloadProgress(QUuid identifier, std::shared_ptr<QNetworkRequest> networkRequest, | |||
|
41 | double progress); | |||
|
42 | ||||
|
43 | private: | |||
|
44 | void waitForFinish(); | |||
|
45 | ||||
|
46 | class NetworkControllerPrivate; | |||
|
47 | spimpl::unique_impl_ptr<NetworkControllerPrivate> impl; | |||
|
48 | }; | |||
|
49 | ||||
|
50 | SCIQLOP_REGISTER_META_TYPE(NETWORKREQUEST_REGISTRY, std::shared_ptr<QNetworkRequest>) | |||
|
51 | ||||
|
52 | ||||
|
53 | #endif // SCIQLOP_NETWORKCONTROLLER_H |
@@ -0,0 +1,25 | |||||
|
1 | #ifndef RESPONSE_H | |||
|
2 | #define RESPONSE_H | |||
|
3 | ||||
|
4 | #include <QByteArray> | |||
|
5 | #include <QString> | |||
|
6 | ||||
|
7 | /** | |||
|
8 | * @brief The Response class holds a Network request response | |||
|
9 | * | |||
|
10 | */ | |||
|
11 | class Response | |||
|
12 | { | |||
|
13 | int _status_code; | |||
|
14 | QByteArray _data; | |||
|
15 | public: | |||
|
16 | Response(){} | |||
|
17 | Response(QByteArray data, int status_code) | |||
|
18 | :_status_code(status_code),_data(data) | |||
|
19 | { | |||
|
20 | ||||
|
21 | } | |||
|
22 | int status_code(){return _status_code;} | |||
|
23 | QByteArray& data(){return _data;} | |||
|
24 | }; | |||
|
25 | #endif // RESPONSE_H |
@@ -0,0 +1,20 | |||||
|
1 | #ifndef SCIQLOP_IPLUGIN_H | |||
|
2 | #define SCIQLOP_IPLUGIN_H | |||
|
3 | ||||
|
4 | #include <QString> | |||
|
5 | #include <QtPlugin> | |||
|
6 | ||||
|
7 | /** | |||
|
8 | * @brief Interface for a plugin | |||
|
9 | */ | |||
|
10 | class IPlugin { | |||
|
11 | public: | |||
|
12 | virtual ~IPlugin() = default; | |||
|
13 | ||||
|
14 | /// Initializes the plugin | |||
|
15 | virtual void initialize() = 0; | |||
|
16 | }; | |||
|
17 | ||||
|
18 | Q_DECLARE_INTERFACE(IPlugin, "sciqlop.plugin.IPlugin") | |||
|
19 | ||||
|
20 | #endif // SCIQLOP_IPLUGIN_H |
@@ -0,0 +1,41 | |||||
|
1 | #ifndef SCIQLOP_PLUGINMANAGER_H | |||
|
2 | #define SCIQLOP_PLUGINMANAGER_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <Common/spimpl.h> | |||
|
7 | ||||
|
8 | #include <QLoggingCategory> | |||
|
9 | ||||
|
10 | class QDir; | |||
|
11 | ||||
|
12 | Q_DECLARE_LOGGING_CATEGORY(LOG_PluginManager) | |||
|
13 | ||||
|
14 | /** | |||
|
15 | * @brief The PluginManager class aims to handle the plugins loaded dynamically into SciQLop. | |||
|
16 | */ | |||
|
17 | class PluginManager { | |||
|
18 | public: | |||
|
19 | explicit PluginManager(); | |||
|
20 | ||||
|
21 | /** | |||
|
22 | * Loads plugins into SciQlop. The loaded plugins are those located in the directory passed in | |||
|
23 | * parameter | |||
|
24 | * @param pluginDir the directory containing the plugins | |||
|
25 | */ | |||
|
26 | void loadPlugins(const QDir &pluginDir); | |||
|
27 | ||||
|
28 | /** | |||
|
29 | * Loads static plugins into SciQlop. SciQLOP supports statically linked plugins. | |||
|
30 | */ | |||
|
31 | void loadStaticPlugins(); | |||
|
32 | ||||
|
33 | /// @returns the number of plugins loaded | |||
|
34 | int nbPluginsLoaded() const noexcept; | |||
|
35 | ||||
|
36 | private: | |||
|
37 | struct PluginManagerPrivate; | |||
|
38 | spimpl::unique_impl_ptr<PluginManagerPrivate> impl; | |||
|
39 | }; | |||
|
40 | ||||
|
41 | #endif // SCIQLOP_PLUGINMANAGER_H |
@@ -0,0 +1,21 | |||||
|
1 | #ifndef SCIQLOP_ISQPSETTINGSBINDABLE_H | |||
|
2 | #define SCIQLOP_ISQPSETTINGSBINDABLE_H | |||
|
3 | ||||
|
4 | #include <QSettings> | |||
|
5 | ||||
|
6 | /** | |||
|
7 | * @brief The ISqpSettingsBindable interface represents an object that can bind a variable | |||
|
8 | */ | |||
|
9 | class ISqpSettingsBindable { | |||
|
10 | ||||
|
11 | public: | |||
|
12 | virtual ~ISqpSettingsBindable() = default; | |||
|
13 | ||||
|
14 | /// Loads settings into the object | |||
|
15 | virtual void loadSettings() = 0; | |||
|
16 | ||||
|
17 | /// Saves settings from the object | |||
|
18 | virtual void saveSettings() const = 0; | |||
|
19 | }; | |||
|
20 | ||||
|
21 | #endif // SCIQLOP_ISQPSETTINGSBINDABLE_H |
@@ -0,0 +1,22 | |||||
|
1 | #ifndef SCIQLOP_SQPSETTINGSDEFS_H | |||
|
2 | #define SCIQLOP_SQPSETTINGSDEFS_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <QString> | |||
|
7 | ||||
|
8 | // //////////////// // | |||
|
9 | // General settings // | |||
|
10 | // //////////////// // | |||
|
11 | ||||
|
12 | ||||
|
13 | struct SCIQLOP_CORE_EXPORT SqpSettings { | |||
|
14 | static double toleranceValue(const QString &key, double defaultValue) noexcept; | |||
|
15 | }; | |||
|
16 | extern SCIQLOP_CORE_EXPORT const QString GENERAL_TOLERANCE_AT_INIT_KEY; | |||
|
17 | extern SCIQLOP_CORE_EXPORT const double GENERAL_TOLERANCE_AT_INIT_DEFAULT_VALUE; | |||
|
18 | ||||
|
19 | extern SCIQLOP_CORE_EXPORT const QString GENERAL_TOLERANCE_AT_UPDATE_KEY; | |||
|
20 | extern SCIQLOP_CORE_EXPORT const double GENERAL_TOLERANCE_AT_UPDATE_DEFAULT_VALUE; | |||
|
21 | ||||
|
22 | #endif // SCIQLOP_SQPSETTINGSDEFS_H |
@@ -0,0 +1,48 | |||||
|
1 | #ifndef SCIQLOP_TIMECONTROLLER_H | |||
|
2 | #define SCIQLOP_TIMECONTROLLER_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <Data/DateTimeRange.h> | |||
|
7 | ||||
|
8 | #include <QLoggingCategory> | |||
|
9 | #include <QObject> | |||
|
10 | ||||
|
11 | #include <Common/spimpl.h> | |||
|
12 | ||||
|
13 | ||||
|
14 | Q_DECLARE_LOGGING_CATEGORY(LOG_TimeController) | |||
|
15 | ||||
|
16 | /** | |||
|
17 | * @brief The TimeController class aims to handle the Time parameters notification in SciQlop. | |||
|
18 | */ | |||
|
19 | class SCIQLOP_CORE_EXPORT TimeController : public QObject { | |||
|
20 | Q_OBJECT | |||
|
21 | public: | |||
|
22 | explicit TimeController(QObject *parent = 0); | |||
|
23 | ||||
|
24 | DateTimeRange dateTime() const noexcept; | |||
|
25 | ||||
|
26 | /// Returns the MIME data associated to a time range | |||
|
27 | static QByteArray mimeDataForTimeRange(const DateTimeRange &timeRange); | |||
|
28 | ||||
|
29 | /// Returns the time range contained in a MIME data | |||
|
30 | static DateTimeRange timeRangeForMimeData(const QByteArray &mimeData); | |||
|
31 | ||||
|
32 | signals: | |||
|
33 | /// Signal emitted to notify that time parameters has beed updated | |||
|
34 | void timeUpdated(DateTimeRange time); | |||
|
35 | ||||
|
36 | public slots: | |||
|
37 | /// Slot called when a new dateTime has been defined. | |||
|
38 | void setDateTimeRange(DateTimeRange dateTime); | |||
|
39 | ||||
|
40 | /// Slot called when the dateTime has to be notified. Call timeUpdated signal | |||
|
41 | void onTimeNotify(); | |||
|
42 | ||||
|
43 | private: | |||
|
44 | class TimeControllerPrivate; | |||
|
45 | spimpl::unique_impl_ptr<TimeControllerPrivate> impl; | |||
|
46 | }; | |||
|
47 | ||||
|
48 | #endif // SCIQLOP_TIMECONTROLLER_H |
@@ -0,0 +1,95 | |||||
|
1 | #ifndef SCIQLOP_VARIABLE_H | |||
|
2 | #define SCIQLOP_VARIABLE_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <Data/DataSeriesIterator.h> | |||
|
7 | #include <Data/DataSeriesType.h> | |||
|
8 | #include <Data/DateTimeRange.h> | |||
|
9 | ||||
|
10 | #include <QLoggingCategory> | |||
|
11 | #include <QObject> | |||
|
12 | ||||
|
13 | #include <Common/MetaTypes.h> | |||
|
14 | #include <Common/spimpl.h> | |||
|
15 | ||||
|
16 | Q_DECLARE_LOGGING_CATEGORY(LOG_Variable) | |||
|
17 | ||||
|
18 | class IDataSeries; | |||
|
19 | class QString; | |||
|
20 | ||||
|
21 | /** | |||
|
22 | * @brief The Variable class represents a variable in SciQlop. | |||
|
23 | */ | |||
|
24 | class SCIQLOP_CORE_EXPORT Variable : public QObject { | |||
|
25 | ||||
|
26 | Q_OBJECT | |||
|
27 | ||||
|
28 | public: | |||
|
29 | explicit Variable(const QString &name, const QVariantHash &metadata = {}); | |||
|
30 | ||||
|
31 | /// Copy ctor | |||
|
32 | explicit Variable(const Variable &other); | |||
|
33 | ||||
|
34 | std::shared_ptr<Variable> clone() const; | |||
|
35 | ||||
|
36 | QString name() const noexcept; | |||
|
37 | void setName(const QString &name) noexcept; | |||
|
38 | DateTimeRange range() const noexcept; | |||
|
39 | void setRange(const DateTimeRange &range) noexcept; | |||
|
40 | DateTimeRange cacheRange() const noexcept; | |||
|
41 | void setCacheRange(const DateTimeRange &cacheRange) noexcept; | |||
|
42 | ||||
|
43 | /// @return the number of points hold by the variable. The number of points is updated each time | |||
|
44 | /// the data series changes | |||
|
45 | int nbPoints() const noexcept; | |||
|
46 | ||||
|
47 | /// Returns the real range of the variable, i.e. the min and max x-axis values of the data | |||
|
48 | /// series between the range of the variable. The real range is updated each time the variable | |||
|
49 | /// range or the data series changed | |||
|
50 | /// @return the real range, invalid range if the data series is null or empty | |||
|
51 | /// @sa setDataSeries() | |||
|
52 | /// @sa setRange() | |||
|
53 | DateTimeRange realRange() const noexcept; | |||
|
54 | ||||
|
55 | /// @return the data of the variable, nullptr if there is no data | |||
|
56 | std::shared_ptr<IDataSeries> dataSeries() const noexcept; | |||
|
57 | ||||
|
58 | /// @return the type of data that the variable holds | |||
|
59 | DataSeriesType type() const noexcept; | |||
|
60 | ||||
|
61 | QVariantHash metadata() const noexcept; | |||
|
62 | ||||
|
63 | bool contains(const DateTimeRange &range) const noexcept; | |||
|
64 | bool intersect(const DateTimeRange &range) const noexcept; | |||
|
65 | bool isInside(const DateTimeRange &range) const noexcept; | |||
|
66 | ||||
|
67 | bool cacheContains(const DateTimeRange &range) const noexcept; | |||
|
68 | bool cacheIntersect(const DateTimeRange &range) const noexcept; | |||
|
69 | bool cacheIsInside(const DateTimeRange &range) const noexcept; | |||
|
70 | ||||
|
71 | QVector<DateTimeRange> provideNotInCacheRangeList(const DateTimeRange &range) const noexcept; | |||
|
72 | QVector<DateTimeRange> provideInCacheRangeList(const DateTimeRange &range) const noexcept; | |||
|
73 | void mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept; | |||
|
74 | ||||
|
75 | static QVector<DateTimeRange> provideNotInCacheRangeList(const DateTimeRange &oldRange, | |||
|
76 | const DateTimeRange &nextRange); | |||
|
77 | ||||
|
78 | static QVector<DateTimeRange> provideInCacheRangeList(const DateTimeRange &oldRange, | |||
|
79 | const DateTimeRange &nextRange); | |||
|
80 | ||||
|
81 | signals: | |||
|
82 | void updated(); | |||
|
83 | /// Signal emitted when when the data series of the variable is loaded for the first time | |||
|
84 | void dataInitialized(); | |||
|
85 | ||||
|
86 | private: | |||
|
87 | class VariablePrivate; | |||
|
88 | spimpl::unique_impl_ptr<VariablePrivate> impl; | |||
|
89 | }; | |||
|
90 | ||||
|
91 | // Required for using shared_ptr in signals/slots | |||
|
92 | SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_REGISTRY, std::shared_ptr<Variable>) | |||
|
93 | SCIQLOP_REGISTER_META_TYPE(VARIABLE_PTR_VECTOR_REGISTRY, QVector<std::shared_ptr<Variable> >) | |||
|
94 | ||||
|
95 | #endif // SCIQLOP_VARIABLE_H |
@@ -0,0 +1,66 | |||||
|
1 | #ifndef SCIQLOP_VARIABLEACQUISITIONWORKER_H | |||
|
2 | #define SCIQLOP_VARIABLEACQUISITIONWORKER_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <Data/DataProviderParameters.h> | |||
|
7 | #include <QLoggingCategory> | |||
|
8 | #include <QObject> | |||
|
9 | #include <QUuid> | |||
|
10 | ||||
|
11 | #include <Data/AcquisitionDataPacket.h> | |||
|
12 | #include <Data/IDataSeries.h> | |||
|
13 | #include <Data/DateTimeRange.h> | |||
|
14 | ||||
|
15 | #include <QLoggingCategory> | |||
|
16 | ||||
|
17 | #include <Common/spimpl.h> | |||
|
18 | ||||
|
19 | Q_DECLARE_LOGGING_CATEGORY(LOG_VariableAcquisitionWorker) | |||
|
20 | ||||
|
21 | class Variable; | |||
|
22 | class IDataProvider; | |||
|
23 | ||||
|
24 | /// This class aims to handle all acquisition request | |||
|
25 | class SCIQLOP_CORE_EXPORT VariableAcquisitionWorker : public QObject { | |||
|
26 | Q_OBJECT | |||
|
27 | public: | |||
|
28 | explicit VariableAcquisitionWorker(QObject *parent = 0); | |||
|
29 | virtual ~VariableAcquisitionWorker(); | |||
|
30 | ||||
|
31 | QUuid pushVariableRequest(QUuid varRequestId, QUuid vIdentifier, DateTimeRange rangeRequested, | |||
|
32 | DateTimeRange cacheRangeRequested, DataProviderParameters parameters, | |||
|
33 | std::shared_ptr<IDataProvider> provider); | |||
|
34 | ||||
|
35 | void abortProgressRequested(QUuid vIdentifier); | |||
|
36 | ||||
|
37 | void initialize(); | |||
|
38 | void finalize(); | |||
|
39 | signals: | |||
|
40 | void dataProvided(QUuid vIdentifier, const DateTimeRange &rangeRequested, | |||
|
41 | const DateTimeRange &cacheRangeRequested, | |||
|
42 | QVector<AcquisitionDataPacket> dataAcquired); | |||
|
43 | ||||
|
44 | void variableRequestInProgress(QUuid vIdentifier, double progress); | |||
|
45 | ||||
|
46 | ||||
|
47 | void variableCanceledRequested(QUuid vIdentifier); | |||
|
48 | ||||
|
49 | ||||
|
50 | public slots: | |||
|
51 | void onVariableDataAcquired(QUuid acqIdentifier, std::shared_ptr<IDataSeries> dataSeries, | |||
|
52 | DateTimeRange dataRangeAcquired); | |||
|
53 | void onVariableRetrieveDataInProgress(QUuid acqIdentifier, double progress); | |||
|
54 | void onVariableAcquisitionFailed(QUuid acqIdentifier); | |||
|
55 | ||||
|
56 | private: | |||
|
57 | void waitForFinish(); | |||
|
58 | ||||
|
59 | class VariableAcquisitionWorkerPrivate; | |||
|
60 | spimpl::unique_impl_ptr<VariableAcquisitionWorkerPrivate> impl; | |||
|
61 | ||||
|
62 | private slots: | |||
|
63 | void onExecuteRequest(QUuid acqIdentifier); | |||
|
64 | }; | |||
|
65 | ||||
|
66 | #endif // SCIQLOP_VARIABLEACQUISITIONWORKER_H |
@@ -0,0 +1,45 | |||||
|
1 | #ifndef SCIQLOP_VARIABLECACHECONTROLLER_H | |||
|
2 | #define SCIQLOP_VARIABLECACHECONTROLLER_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <QLoggingCategory> | |||
|
7 | #include <QObject> | |||
|
8 | ||||
|
9 | #include <Data/DateTimeRange.h> | |||
|
10 | ||||
|
11 | #include <QLoggingCategory> | |||
|
12 | ||||
|
13 | #include <Common/spimpl.h> | |||
|
14 | ||||
|
15 | Q_DECLARE_LOGGING_CATEGORY(LOG_VariableCacheController) | |||
|
16 | ||||
|
17 | class Variable; | |||
|
18 | ||||
|
19 | /// This class aims to store in the cache all of the dateTime already requested to the variable. | |||
|
20 | class SCIQLOP_CORE_EXPORT VariableCacheController : public QObject { | |||
|
21 | Q_OBJECT | |||
|
22 | public: | |||
|
23 | explicit VariableCacheController(QObject *parent = 0); | |||
|
24 | ||||
|
25 | ||||
|
26 | void addDateTime(std::shared_ptr<Variable> variable, const DateTimeRange &dateTime); | |||
|
27 | ||||
|
28 | /// Clears cache concerning a variable | |||
|
29 | void clear(std::shared_ptr<Variable> variable) noexcept; | |||
|
30 | ||||
|
31 | /// Return all of the SqpDataTime part of the dateTime whose are not in the cache | |||
|
32 | QVector<DateTimeRange> provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable, | |||
|
33 | const DateTimeRange &dateTime); | |||
|
34 | ||||
|
35 | ||||
|
36 | QVector<DateTimeRange> dateCacheList(std::shared_ptr<Variable> variable) const noexcept; | |||
|
37 | ||||
|
38 | void displayCache(std::shared_ptr<Variable> variable) const; | |||
|
39 | ||||
|
40 | private: | |||
|
41 | class VariableCacheControllerPrivate; | |||
|
42 | spimpl::unique_impl_ptr<VariableCacheControllerPrivate> impl; | |||
|
43 | }; | |||
|
44 | ||||
|
45 | #endif // SCIQLOP_VARIABLECACHECONTROLLER_H |
@@ -0,0 +1,32 | |||||
|
1 | #ifndef SCIQLOP_VARIABLECACHESTRATEGY_H | |||
|
2 | #define SCIQLOP_VARIABLECACHESTRATEGY_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <QLoggingCategory> | |||
|
7 | #include <QObject> | |||
|
8 | ||||
|
9 | #include <Data/DateTimeRange.h> | |||
|
10 | ||||
|
11 | #include <QLoggingCategory> | |||
|
12 | ||||
|
13 | #include <Common/spimpl.h> | |||
|
14 | #include <utility> | |||
|
15 | ||||
|
16 | ||||
|
17 | Q_DECLARE_LOGGING_CATEGORY(LOG_VariableCacheStrategy) | |||
|
18 | ||||
|
19 | class Variable; | |||
|
20 | ||||
|
21 | /// This class aims to hande the cache strategy. | |||
|
22 | class SCIQLOP_CORE_EXPORT VariableCacheStrategy { | |||
|
23 | ||||
|
24 | public: | |||
|
25 | virtual ~VariableCacheStrategy() noexcept = default; | |||
|
26 | virtual std::pair<DateTimeRange, DateTimeRange> computeRange(const DateTimeRange &vRange, | |||
|
27 | const DateTimeRange &rangeRequested) | |||
|
28 | = 0; | |||
|
29 | }; | |||
|
30 | ||||
|
31 | ||||
|
32 | #endif // SCIQLOP_VARIABLECACHESTRATEGY_H |
@@ -0,0 +1,46 | |||||
|
1 | #ifndef SCIQLOP_VARIABLECACHESTRATEGYFACTORY_H | |||
|
2 | #define SCIQLOP_VARIABLECACHESTRATEGYFACTORY_H | |||
|
3 | ||||
|
4 | ||||
|
5 | #include <memory> | |||
|
6 | #include <stdexcept> | |||
|
7 | ||||
|
8 | #include "VariableCacheStrategy.h" | |||
|
9 | #include "VariableSingleThresholdCacheStrategy.h" | |||
|
10 | ||||
|
11 | #include <QLoggingCategory> | |||
|
12 | #include <QString> | |||
|
13 | ||||
|
14 | Q_LOGGING_CATEGORY(LOG_VariableCacheStrategyFactory, "VariableCacheStrategyFactory") | |||
|
15 | ||||
|
16 | enum class CacheStrategy { SingleThreshold, TwoThreashold }; | |||
|
17 | ||||
|
18 | class VariableCacheStrategyFactory { | |||
|
19 | ||||
|
20 | using cacheStratPtr = std::unique_ptr<VariableCacheStrategy>; | |||
|
21 | ||||
|
22 | public: | |||
|
23 | static cacheStratPtr createCacheStrategy(CacheStrategy specificStrategy) | |||
|
24 | { | |||
|
25 | switch (specificStrategy) { | |||
|
26 | case CacheStrategy::SingleThreshold: { | |||
|
27 | return std::unique_ptr<VariableCacheStrategy>{ | |||
|
28 | new VariableSingleThresholdCacheStrategy{}}; | |||
|
29 | break; | |||
|
30 | } | |||
|
31 | case CacheStrategy::TwoThreashold: { | |||
|
32 | qCCritical(LOG_VariableCacheStrategyFactory()) | |||
|
33 | << QObject::tr("cache strategy not implemented yet"); | |||
|
34 | break; | |||
|
35 | } | |||
|
36 | default: | |||
|
37 | qCCritical(LOG_VariableCacheStrategyFactory()) | |||
|
38 | << QObject::tr("Unknown cache strategy"); | |||
|
39 | } | |||
|
40 | ||||
|
41 | return nullptr; | |||
|
42 | } | |||
|
43 | }; | |||
|
44 | ||||
|
45 | ||||
|
46 | #endif // VARIABLECACHESTRATEGYFACTORY_H |
@@ -0,0 +1,147 | |||||
|
1 | #ifndef SCIQLOP_VARIABLECONTROLLER_H | |||
|
2 | #define SCIQLOP_VARIABLECONTROLLER_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <Data/AcquisitionDataPacket.h> | |||
|
7 | #include <Data/DateTimeRange.h> | |||
|
8 | ||||
|
9 | #include <QLoggingCategory> | |||
|
10 | #include <QObject> | |||
|
11 | #include <QUuid> | |||
|
12 | ||||
|
13 | #include <Common/spimpl.h> | |||
|
14 | ||||
|
15 | class IDataProvider; | |||
|
16 | class QItemSelectionModel; | |||
|
17 | class TimeController; | |||
|
18 | class Variable; | |||
|
19 | class VariableModel; | |||
|
20 | ||||
|
21 | Q_DECLARE_LOGGING_CATEGORY(LOG_VariableController) | |||
|
22 | ||||
|
23 | ||||
|
24 | /** | |||
|
25 | * Possible types of zoom operation | |||
|
26 | */ | |||
|
27 | enum class AcquisitionZoomType { ZoomOut, ZoomIn, PanRight, PanLeft, Unknown }; | |||
|
28 | ||||
|
29 | ||||
|
30 | /** | |||
|
31 | * @brief The VariableController class aims to handle the variables in SciQlop. | |||
|
32 | */ | |||
|
33 | class SCIQLOP_CORE_EXPORT VariableController : public QObject { | |||
|
34 | Q_OBJECT | |||
|
35 | public: | |||
|
36 | explicit VariableController(QObject *parent = 0); | |||
|
37 | virtual ~VariableController(); | |||
|
38 | ||||
|
39 | VariableModel *variableModel() noexcept; | |||
|
40 | QItemSelectionModel *variableSelectionModel() noexcept; | |||
|
41 | ||||
|
42 | ||||
|
43 | /** | |||
|
44 | * Clones the variable passed in parameter and adds the duplicate to the controller | |||
|
45 | * @param variable the variable to duplicate | |||
|
46 | * @return the duplicate created, nullptr if the variable couldn't be created | |||
|
47 | */ | |||
|
48 | std::shared_ptr<Variable> cloneVariable(std::shared_ptr<Variable> variable) noexcept; | |||
|
49 | ||||
|
50 | /// Returns the MIME data associated to a list of variables | |||
|
51 | QByteArray mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const; | |||
|
52 | ||||
|
53 | /// Returns the list of variables contained in a MIME data | |||
|
54 | QList<std::shared_ptr<Variable> > variablesForMimeData(const QByteArray &mimeData) const; | |||
|
55 | ||||
|
56 | static AcquisitionZoomType getZoomType(const DateTimeRange &range, const DateTimeRange &oldRange); | |||
|
57 | ||||
|
58 | /// Returns True if there are pending downloads | |||
|
59 | bool hasPendingDownloads(); | |||
|
60 | signals: | |||
|
61 | /// Signal emitted when a variable is about to be deleted from the controller | |||
|
62 | void variableAboutToBeDeleted(std::shared_ptr<Variable> variable); | |||
|
63 | ||||
|
64 | /// Signal emitted when a data acquisition is requested on a range for a variable | |||
|
65 | void rangeChanged(std::shared_ptr<Variable> variable, const DateTimeRange &range); | |||
|
66 | ||||
|
67 | /// Signal emitted when a sub range of the cacheRange of the variable can be displayed | |||
|
68 | void updateVarDisplaying(std::shared_ptr<Variable> variable, const DateTimeRange &range); | |||
|
69 | ||||
|
70 | /// Signal emitted when all acquisitions related to the variables have been completed (whether | |||
|
71 | /// validated, canceled, or failed) | |||
|
72 | void acquisitionFinished(); | |||
|
73 | ||||
|
74 | void variableAdded(const std::shared_ptr<Variable> &variable); | |||
|
75 | ||||
|
76 | public slots: | |||
|
77 | /** | |||
|
78 | * Deletes from the controller the variable passed in parameter. | |||
|
79 | * | |||
|
80 | * Delete a variable includes: | |||
|
81 | * - the deletion of the various references to the variable in SciQlop | |||
|
82 | * - the deletion of the model variable | |||
|
83 | * - the deletion of the provider associated with the variable | |||
|
84 | * - removing the cache associated with the variable | |||
|
85 | * | |||
|
86 | * @param variable the variable to delete from the controller. | |||
|
87 | */ | |||
|
88 | void deleteVariable(std::shared_ptr<Variable> variable) noexcept; | |||
|
89 | ||||
|
90 | /** | |||
|
91 | * Deletes from the controller the variables passed in parameter. | |||
|
92 | * @param variables the variables to delete from the controller. | |||
|
93 | * @sa deleteVariable() | |||
|
94 | */ | |||
|
95 | void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept; | |||
|
96 | ||||
|
97 | /// Request the data loading of the variable whithin range | |||
|
98 | void onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, const DateTimeRange &range, | |||
|
99 | bool synchronise); | |||
|
100 | /** | |||
|
101 | * Creates a new variable and adds it to the model | |||
|
102 | * @param name the name of the new variable | |||
|
103 | * @param metadata the metadata of the new variable | |||
|
104 | * @param provider the data provider for the new variable | |||
|
105 | * @return the pointer to the new variable or nullptr if the creation failed | |||
|
106 | */ | |||
|
107 | std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata, | |||
|
108 | std::shared_ptr<IDataProvider> provider, const DateTimeRange &range) noexcept; | |||
|
109 | ||||
|
110 | /// Update the temporal parameters of every selected variable to dateTime | |||
|
111 | void onDateTimeOnSelection(const DateTimeRange &dateTime); | |||
|
112 | ||||
|
113 | /// Update the temporal parameters of the specified variable | |||
|
114 | void onUpdateDateTime(std::shared_ptr<Variable> variable, const DateTimeRange &dateTime); | |||
|
115 | ||||
|
116 | ||||
|
117 | void onDataProvided(QUuid vIdentifier, const DateTimeRange &rangeRequested, | |||
|
118 | const DateTimeRange &cacheRangeRequested, | |||
|
119 | QVector<AcquisitionDataPacket> dataAcquired); | |||
|
120 | ||||
|
121 | void onVariableRetrieveDataInProgress(QUuid identifier, double progress); | |||
|
122 | ||||
|
123 | /// Cancel the current request for the variable | |||
|
124 | void onAbortProgressRequested(std::shared_ptr<Variable> variable); | |||
|
125 | void onAbortAcquisitionRequested(QUuid vIdentifier); | |||
|
126 | ||||
|
127 | // synchronization group methods | |||
|
128 | void onAddSynchronizationGroupId(QUuid synchronizationGroupId); | |||
|
129 | void onRemoveSynchronizationGroupId(QUuid synchronizationGroupId); | |||
|
130 | void onAddSynchronized(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId); | |||
|
131 | ||||
|
132 | /// Desynchronizes the variable of the group whose identifier is passed in parameter | |||
|
133 | /// @remarks the method does nothing if the variable is not part of the group | |||
|
134 | void desynchronize(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId); | |||
|
135 | ||||
|
136 | void initialize(); | |||
|
137 | void finalize(); | |||
|
138 | ||||
|
139 | private: | |||
|
140 | void waitForFinish(); | |||
|
141 | ||||
|
142 | class VariableControllerPrivate; | |||
|
143 | spimpl::unique_impl_ptr<VariableControllerPrivate> impl; | |||
|
144 | }; | |||
|
145 | ||||
|
146 | ||||
|
147 | #endif // SCIQLOP_VARIABLECONTROLLER_H |
@@ -0,0 +1,26 | |||||
|
1 | #include <Common/spimpl.h> | |||
|
2 | #include <memory> | |||
|
3 | #include <vector> | |||
|
4 | #include <QHash> | |||
|
5 | #include <Variable/Variable.h> | |||
|
6 | #include <Variable/VariableSynchronizationGroup.h> | |||
|
7 | #include <Variable/VariableModel.h> | |||
|
8 | #include <Data/IDataProvider.h> | |||
|
9 | #include "Data/DateTimeRange.h" | |||
|
10 | #include <QMutexLocker> | |||
|
11 | #include <QUuid> | |||
|
12 | #include <QItemSelectionModel> | |||
|
13 | ||||
|
14 | class VariableController2Private; | |||
|
15 | class VariableController2 | |||
|
16 | { | |||
|
17 | spimpl::unique_impl_ptr<VariableController2Private> impl; | |||
|
18 | ||||
|
19 | public: | |||
|
20 | explicit VariableController2(); | |||
|
21 | std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata, | |||
|
22 | std::shared_ptr<IDataProvider> provider, const DateTimeRange &range); | |||
|
23 | void changeRange(QUuid variable, DateTimeRange r); | |||
|
24 | void asyncChangeRange(QUuid variable, DateTimeRange r); | |||
|
25 | ||||
|
26 | }; |
@@ -0,0 +1,111 | |||||
|
1 | #ifndef SCIQLOP_VARIABLEMODEL_H | |||
|
2 | #define SCIQLOP_VARIABLEMODEL_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <Data/DateTimeRange.h> | |||
|
7 | ||||
|
8 | #include <QAbstractTableModel> | |||
|
9 | #include <QLoggingCategory> | |||
|
10 | ||||
|
11 | #include <Common/MetaTypes.h> | |||
|
12 | #include <Common/spimpl.h> | |||
|
13 | ||||
|
14 | Q_DECLARE_LOGGING_CATEGORY(LOG_VariableModel) | |||
|
15 | ||||
|
16 | enum VariableRoles { ProgressRole = Qt::UserRole }; | |||
|
17 | ||||
|
18 | ||||
|
19 | class IDataSeries; | |||
|
20 | class Variable; | |||
|
21 | class VariableController; | |||
|
22 | ||||
|
23 | /** | |||
|
24 | * @brief The VariableModel class aims to hold the variables that have been created in SciQlop | |||
|
25 | */ | |||
|
26 | class SCIQLOP_CORE_EXPORT VariableModel : public QAbstractTableModel { | |||
|
27 | Q_OBJECT | |||
|
28 | public: | |||
|
29 | explicit VariableModel(VariableController *parent = nullptr); | |||
|
30 | ||||
|
31 | /** | |||
|
32 | * Adds an existing variable in the model. | |||
|
33 | * @param variable the variable to add. | |||
|
34 | * @remarks the variable's name is modified to avoid name duplicates | |||
|
35 | * @remarks this method does nothing if the variable already exists in the model | |||
|
36 | */ | |||
|
37 | void addVariable(std::shared_ptr<Variable> variable) noexcept; | |||
|
38 | ||||
|
39 | /** | |||
|
40 | * Checks that a variable is contained in the model | |||
|
41 | * @param variable the variable to check | |||
|
42 | * @return true if the variable is in the model, false otherwise | |||
|
43 | */ | |||
|
44 | bool containsVariable(std::shared_ptr<Variable> variable) const noexcept; | |||
|
45 | ||||
|
46 | /** | |||
|
47 | * Creates a new variable in the model | |||
|
48 | * @param name the name of the new variable | |||
|
49 | * @param metadata the metadata associated to the new variable | |||
|
50 | * @return the pointer to the new variable | |||
|
51 | */ | |||
|
52 | std::shared_ptr<Variable> createVariable(const QString &name, | |||
|
53 | const QVariantHash &metadata) noexcept; | |||
|
54 | ||||
|
55 | /** | |||
|
56 | * Deletes a variable from the model, if it exists | |||
|
57 | * @param variable the variable to delete | |||
|
58 | */ | |||
|
59 | void deleteVariable(std::shared_ptr<Variable> variable) noexcept; | |||
|
60 | ||||
|
61 | ||||
|
62 | std::shared_ptr<Variable> variable(int index) const; | |||
|
63 | std::vector<std::shared_ptr<Variable> > variables() const; | |||
|
64 | ||||
|
65 | void setDataProgress(std::shared_ptr<Variable> variable, double progress); | |||
|
66 | ||||
|
67 | ||||
|
68 | // /////////////////////////// // | |||
|
69 | // QAbstractTableModel methods // | |||
|
70 | // /////////////////////////// // | |||
|
71 | ||||
|
72 | virtual int columnCount(const QModelIndex &parent = QModelIndex{}) const override; | |||
|
73 | virtual int rowCount(const QModelIndex &parent = QModelIndex{}) const override; | |||
|
74 | virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; | |||
|
75 | virtual QVariant headerData(int section, Qt::Orientation orientation, | |||
|
76 | int role = Qt::DisplayRole) const override; | |||
|
77 | virtual Qt::ItemFlags flags(const QModelIndex &index) const override; | |||
|
78 | ||||
|
79 | // ///////////////// // | |||
|
80 | // Drag&Drop methods // | |||
|
81 | // ///////////////// // | |||
|
82 | ||||
|
83 | virtual Qt::DropActions supportedDropActions() const override; | |||
|
84 | virtual Qt::DropActions supportedDragActions() const override; | |||
|
85 | virtual QStringList mimeTypes() const override; | |||
|
86 | virtual QMimeData *mimeData(const QModelIndexList &indexes) const override; | |||
|
87 | virtual bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, | |||
|
88 | const QModelIndex &parent) const override; | |||
|
89 | virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, | |||
|
90 | const QModelIndex &parent) override; | |||
|
91 | ||||
|
92 | void abortProgress(const QModelIndex &index); | |||
|
93 | ||||
|
94 | signals: | |||
|
95 | void abortProgessRequested(std::shared_ptr<Variable> variable); | |||
|
96 | void requestVariable(const QVariantHash &productData); | |||
|
97 | void requestVariableRangeUpdate(std::shared_ptr<Variable> variable, const DateTimeRange &range); | |||
|
98 | ||||
|
99 | private: | |||
|
100 | class VariableModelPrivate; | |||
|
101 | spimpl::unique_impl_ptr<VariableModelPrivate> impl; | |||
|
102 | ||||
|
103 | private slots: | |||
|
104 | /// Slot called when data of a variable has been updated | |||
|
105 | void onVariableUpdated() noexcept; | |||
|
106 | }; | |||
|
107 | ||||
|
108 | // Registers QVector<int> metatype so it can be used in VariableModel::dataChanged() signal | |||
|
109 | SCIQLOP_REGISTER_META_TYPE(QVECTOR_INT_REGISTRY, QVector<int>) | |||
|
110 | ||||
|
111 | #endif // SCIQLOP_VARIABLEMODEL_H |
@@ -0,0 +1,32 | |||||
|
1 | #ifndef SCIQLOP_VARIABLESINGLETHRESHOLDCACHESTRATEGY_H | |||
|
2 | #define SCIQLOP_VARIABLESINGLETHRESHOLDCACHESTRATEGY_H | |||
|
3 | ||||
|
4 | #include "Settings/SqpSettingsDefs.h" | |||
|
5 | #include "VariableCacheStrategy.h" | |||
|
6 | ||||
|
7 | ||||
|
8 | /// This class aims to hande the cache strategy. | |||
|
9 | class SCIQLOP_CORE_EXPORT VariableSingleThresholdCacheStrategy : public VariableCacheStrategy { | |||
|
10 | public: | |||
|
11 | VariableSingleThresholdCacheStrategy() = default; | |||
|
12 | ||||
|
13 | std::pair<DateTimeRange, DateTimeRange> computeRange(const DateTimeRange &vRange, | |||
|
14 | const DateTimeRange &rangeRequested) override | |||
|
15 | { | |||
|
16 | ||||
|
17 | auto varRanges = std::pair<DateTimeRange, DateTimeRange>{}; | |||
|
18 | ||||
|
19 | auto toleranceFactor = SqpSettings::toleranceValue( | |||
|
20 | GENERAL_TOLERANCE_AT_UPDATE_KEY, GENERAL_TOLERANCE_AT_UPDATE_DEFAULT_VALUE); | |||
|
21 | auto tolerance = toleranceFactor * (rangeRequested.m_TEnd - rangeRequested.m_TStart); | |||
|
22 | ||||
|
23 | varRanges.first = rangeRequested; | |||
|
24 | varRanges.second | |||
|
25 | = DateTimeRange{rangeRequested.m_TStart - tolerance, rangeRequested.m_TEnd + tolerance}; | |||
|
26 | ||||
|
27 | return varRanges; | |||
|
28 | } | |||
|
29 | }; | |||
|
30 | ||||
|
31 | ||||
|
32 | #endif // SCIQLOP_VARIABLESINGLETHRESHOLDCACHESTRATEGY_H |
@@ -0,0 +1,39 | |||||
|
1 | #ifndef SCIQLOP_VARIABLESYNCHRONIZATIONGROUP_H | |||
|
2 | #define SCIQLOP_VARIABLESYNCHRONIZATIONGROUP_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <QLoggingCategory> | |||
|
7 | #include <QObject> | |||
|
8 | #include <QUuid> | |||
|
9 | ||||
|
10 | #include <Data/DateTimeRange.h> | |||
|
11 | ||||
|
12 | #include <set> | |||
|
13 | ||||
|
14 | #include <QLoggingCategory> | |||
|
15 | ||||
|
16 | #include <Common/spimpl.h> | |||
|
17 | ||||
|
18 | Q_DECLARE_LOGGING_CATEGORY(LOG_VariableSynchronizationGroup) | |||
|
19 | ||||
|
20 | class Variable; | |||
|
21 | ||||
|
22 | /// This class aims to hande the cache strategy. | |||
|
23 | class SCIQLOP_CORE_EXPORT VariableSynchronizationGroup : public QObject { | |||
|
24 | Q_OBJECT | |||
|
25 | public: | |||
|
26 | explicit VariableSynchronizationGroup(QObject *parent = Q_NULLPTR); | |||
|
27 | explicit VariableSynchronizationGroup(QUuid variable, QObject *parent = Q_NULLPTR); | |||
|
28 | ||||
|
29 | void addVariable(QUuid vIdentifier); | |||
|
30 | void removeVariable(QUuid vIdentifier); | |||
|
31 | ||||
|
32 | const std::set<QUuid> &getIds() const noexcept; | |||
|
33 | ||||
|
34 | private: | |||
|
35 | class VariableSynchronizationGroupPrivate; | |||
|
36 | spimpl::unique_impl_ptr<VariableSynchronizationGroupPrivate> impl; | |||
|
37 | }; | |||
|
38 | ||||
|
39 | #endif // SCIQLOP_VARIABLESYNCHRONIZATIONGROUP_H |
@@ -0,0 +1,35 | |||||
|
1 | #ifndef SCIQLOP_VARIABLESYNCHRONIZATIONGROUP2_H | |||
|
2 | #define SCIQLOP_VARIABLESYNCHRONIZATIONGROUP2_H | |||
|
3 | ||||
|
4 | #include <QUuid> | |||
|
5 | #include <set> | |||
|
6 | ||||
|
7 | #include "CoreGlobal.h" | |||
|
8 | #include <Common/spimpl.h> | |||
|
9 | #include <Common/containers.h> | |||
|
10 | ||||
|
11 | class SCIQLOP_CORE_EXPORT VariableSynchronizationGroup2 | |||
|
12 | { | |||
|
13 | ||||
|
14 | public: | |||
|
15 | explicit VariableSynchronizationGroup2()=default; | |||
|
16 | // Convenience ctor to build a group with a default variable | |||
|
17 | explicit VariableSynchronizationGroup2(QUuid variable) | |||
|
18 | :_variables{{variable}} | |||
|
19 | {} | |||
|
20 | ||||
|
21 | void addVariable(QUuid variable); | |||
|
22 | void removeVariable(QUuid variable); | |||
|
23 | ||||
|
24 | bool contains(QUuid variable) | |||
|
25 | { | |||
|
26 | return SciQLop::containers::contains(this->_variables,variable); | |||
|
27 | } | |||
|
28 | ||||
|
29 | const std::set<QUuid> &variables() const noexcept; | |||
|
30 | ||||
|
31 | private: | |||
|
32 | std::set<QUuid> _variables; | |||
|
33 | }; | |||
|
34 | ||||
|
35 | #endif // SCIQLOP_VARIABLESYNCHRONIZATIONGROUP2_H |
@@ -0,0 +1,98 | |||||
|
1 | // TODO copyright | |||
|
2 | /** | |||
|
3 | * @file Version.h | |||
|
4 | */ | |||
|
5 | #ifndef SCIQLOP_VERSION_H | |||
|
6 | #define SCIQLOP_VERSION_H | |||
|
7 | ||||
|
8 | /*************************************************** | |||
|
9 | * DON'T CHANGE THIS FILE. AUTOGENERATED BY CMAKE. * | |||
|
10 | ***************************************************/ | |||
|
11 | ||||
|
12 | //#include "SciqlopExport.h" | |||
|
13 | #include <QtCore/QString> | |||
|
14 | ||||
|
15 | class QDateTime; | |||
|
16 | ||||
|
17 | namespace sciqlop { | |||
|
18 | ||||
|
19 | /** | |||
|
20 | * Holds the version of Sciqlop. | |||
|
21 | * | |||
|
22 | * @attention Don't update this class directly, it is generated from the | |||
|
23 | * `resources/Version.h.in` and `resources/Version.cpp.in` files, along with | |||
|
24 | * the cmake variables defined in the `cmake/sciqlop_version.cmake` file. | |||
|
25 | * | |||
|
26 | * To change the Sciqlop version number, update the `cmake/sciqlop_version.cmake` | |||
|
27 | * file, and to change this class other than to change the version number, | |||
|
28 | * update the `resources/Version.h.in` and `resources/Version.cpp.in` files. | |||
|
29 | * @ingroup Utils | |||
|
30 | */ | |||
|
31 | class /*SCIQLOP_API*/ Version { | |||
|
32 | public: | |||
|
33 | /** | |||
|
34 | * Retrieve the version of Sciqlop. | |||
|
35 | * | |||
|
36 | * The version is of the form MAJOR.MINOR.PATCH. If a suffix has been | |||
|
37 | * provided to the version, it is appended after the PATCH. | |||
|
38 | * | |||
|
39 | * The version can be modified by updating the cmake/sciqlop_version.cmake | |||
|
40 | * file. | |||
|
41 | * | |||
|
42 | * @return The version of Sciqlop as a QString. | |||
|
43 | */ | |||
|
44 | static QString version() | |||
|
45 | { | |||
|
46 | static const QString v("0.1.0"); | |||
|
47 | return v; | |||
|
48 | } | |||
|
49 | ||||
|
50 | /** | |||
|
51 | * @return The datetime of the build. | |||
|
52 | */ | |||
|
53 | static QDateTime buildDateTime(); | |||
|
54 | ||||
|
55 | /** | |||
|
56 | * Major version. | |||
|
57 | */ | |||
|
58 | static const int VERSION_MAJOR = 0; | |||
|
59 | /** | |||
|
60 | * Minor version. | |||
|
61 | */ | |||
|
62 | static const int VERSION_MINOR = 1; | |||
|
63 | /** | |||
|
64 | * Patch version. | |||
|
65 | */ | |||
|
66 | static const int VERSION_PATCH = 0; | |||
|
67 | /** | |||
|
68 | * Suffix version. | |||
|
69 | */ | |||
|
70 | static const char *VERSION_SUFFIX; | |||
|
71 | ||||
|
72 | /** | |||
|
73 | * Compile date computed with the __DATE__ macro. | |||
|
74 | * | |||
|
75 | * From the C99 standard: | |||
|
76 | * __DATE__: The date of translation of the preprocessing translation unit: | |||
|
77 | * a character string literal of the form "Mmm dd yyyy", where the names of | |||
|
78 | * the months are the same as those generated by the asctime function, and | |||
|
79 | * the first character of dd is a space character if the value is less than | |||
|
80 | * 10. If the date of translation is not available, an | |||
|
81 | * implementation-defined valid date shall be supplied. | |||
|
82 | */ | |||
|
83 | static const char *BUILD_DATE; | |||
|
84 | /** | |||
|
85 | * Compile time computed with the __TIME__ macro. | |||
|
86 | * | |||
|
87 | * From the C99 standard: | |||
|
88 | * __TIME__: The time of translation of the preprocessing translation unit: | |||
|
89 | * a character string literal of the form "hh:mm:ss" as in the time | |||
|
90 | * generated by the asctime function. If the time of translation is not | |||
|
91 | * available, an implementation-defined valid time shall be supplied. | |||
|
92 | */ | |||
|
93 | static const char *BUILD_TIME; | |||
|
94 | }; | |||
|
95 | ||||
|
96 | } // namespace sciqlop | |||
|
97 | ||||
|
98 | #endif // SCIQLOP_VERSION_H |
@@ -0,0 +1,51 | |||||
|
1 | #ifndef SCIQLOP_VISUALIZATIONCONTROLLER_H | |||
|
2 | #define SCIQLOP_VISUALIZATIONCONTROLLER_H | |||
|
3 | ||||
|
4 | #include "CoreGlobal.h" | |||
|
5 | ||||
|
6 | #include <Data/DateTimeRange.h> | |||
|
7 | ||||
|
8 | #include <QLoggingCategory> | |||
|
9 | #include <QObject> | |||
|
10 | #include <QUuid> | |||
|
11 | ||||
|
12 | #include <Common/spimpl.h> | |||
|
13 | ||||
|
14 | Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationController) | |||
|
15 | ||||
|
16 | class DataSourceItem; | |||
|
17 | class Variable; | |||
|
18 | ||||
|
19 | /** | |||
|
20 | * @brief The VisualizationController class aims to make the link between SciQlop and its plugins. | |||
|
21 | * This is the intermediate class that SciQlop has to use in the way to connect a data source. | |||
|
22 | * Please first use register method to initialize a plugin specified by its metadata name (JSON | |||
|
23 | * plugin source) then others specifics method will be able to access it. You can load a data source | |||
|
24 | * driver plugin then create a data source. | |||
|
25 | */ | |||
|
26 | class SCIQLOP_CORE_EXPORT VisualizationController : public QObject { | |||
|
27 | Q_OBJECT | |||
|
28 | public: | |||
|
29 | explicit VisualizationController(QObject *parent = 0); | |||
|
30 | virtual ~VisualizationController(); | |||
|
31 | ||||
|
32 | signals: | |||
|
33 | /// Signal emitted when a variable is about to be deleted from SciQlop | |||
|
34 | void variableAboutToBeDeleted(std::shared_ptr<Variable> variable); | |||
|
35 | ||||
|
36 | /// Signal emitted when a data acquisition is requested on a range for a variable | |||
|
37 | void rangeChanged(std::shared_ptr<Variable> variable, const DateTimeRange &range); | |||
|
38 | ||||
|
39 | public slots: | |||
|
40 | /// Manage init/end of the controller | |||
|
41 | void initialize(); | |||
|
42 | void finalize(); | |||
|
43 | ||||
|
44 | private: | |||
|
45 | void waitForFinish(); | |||
|
46 | ||||
|
47 | class VisualizationControllerPrivate; | |||
|
48 | spimpl::unique_impl_ptr<VisualizationControllerPrivate> impl; | |||
|
49 | }; | |||
|
50 | ||||
|
51 | #endif // SCIQLOP_VISUALIZATIONCONTROLLER_H |
@@ -0,0 +1,75 | |||||
|
1 | ||||
|
2 | qxorm_dep = dependency('QxOrm', required : true, fallback:['QxOrm','qxorm_dep']) | |||
|
3 | libcatalogs_dep = dependency('libcatalogs', required : true, fallback:['libcatalogs','libcatalogs_dep']) | |||
|
4 | ||||
|
5 | ||||
|
6 | core_moc_headers = [ | |||
|
7 | 'include/Catalogue/CatalogueController.h', | |||
|
8 | 'include/Common/SignalWaiter.h', | |||
|
9 | 'include/Data/IDataProvider.h', | |||
|
10 | 'include/DataSource/DataSourceController.h', | |||
|
11 | 'include/DataSource/DataSourceItemAction.h', | |||
|
12 | 'include/Network/NetworkController.h', | |||
|
13 | 'include/Time/TimeController.h', | |||
|
14 | 'include/Variable/Variable.h', | |||
|
15 | 'include/Variable/VariableCacheController.h', | |||
|
16 | 'include/Variable/VariableController.h', | |||
|
17 | 'include/Variable/VariableAcquisitionWorker.h', | |||
|
18 | 'include/Variable/VariableSynchronizationGroup.h', | |||
|
19 | 'include/Variable/VariableModel.h', | |||
|
20 | 'include/Visualization/VisualizationController.h' | |||
|
21 | ] | |||
|
22 | ||||
|
23 | ||||
|
24 | core_moc_files = qt5.preprocess(moc_headers : core_moc_headers) | |||
|
25 | ||||
|
26 | core_sources = [ | |||
|
27 | 'src/Common/DateUtils.cpp', | |||
|
28 | 'src/Common/SignalWaiter.cpp', | |||
|
29 | 'src/Common/StringUtils.cpp', | |||
|
30 | 'src/Common/MimeTypesDef.cpp', | |||
|
31 | 'src/Catalogue/CatalogueController.cpp', | |||
|
32 | 'src/Data/ScalarSeries.cpp', | |||
|
33 | 'src/Data/SpectrogramSeries.cpp', | |||
|
34 | 'src/Data/DataSeriesIterator.cpp', | |||
|
35 | 'src/Data/ArrayDataIterator.cpp', | |||
|
36 | 'src/Data/VectorSeries.cpp', | |||
|
37 | 'src/Data/OptionalAxis.cpp', | |||
|
38 | 'src/Data/DataSeriesUtils.cpp', | |||
|
39 | 'src/DataSource/DataSourceController.cpp', | |||
|
40 | 'src/DataSource/DataSourceItem.cpp', | |||
|
41 | 'src/DataSource/DataSourceItemAction.cpp', | |||
|
42 | 'src/DataSource/DataSourceItemMergeHelper.cpp', | |||
|
43 | 'src/Network/NetworkController.cpp', | |||
|
44 | 'src/PluginManager/PluginManager.cpp', | |||
|
45 | 'src/Settings/SqpSettingsDefs.cpp', | |||
|
46 | 'src/Time/TimeController.cpp', | |||
|
47 | 'src/Variable/Variable.cpp', | |||
|
48 | 'src/Variable/VariableCacheController.cpp', | |||
|
49 | 'src/Variable/VariableController.cpp', | |||
|
50 | 'src/Variable/VariableAcquisitionWorker.cpp', | |||
|
51 | 'src/Variable/VariableSynchronizationGroup.cpp', | |||
|
52 | 'src/Variable/VariableModel.cpp', | |||
|
53 | 'src/Visualization/VisualizationController.cpp' | |||
|
54 | ] | |||
|
55 | ||||
|
56 | core_inc = include_directories(['include', 'include/Plugin']) | |||
|
57 | ||||
|
58 | sciqlop_core_lib = library('sciqlopcore', | |||
|
59 | core_sources, | |||
|
60 | core_moc_files, | |||
|
61 | cpp_args : '-DCORE_LIB', | |||
|
62 | include_directories : core_inc, | |||
|
63 | dependencies : [qt5core, qt5network, libcatalogs_dep], | |||
|
64 | install : true | |||
|
65 | ) | |||
|
66 | ||||
|
67 | ||||
|
68 | sciqlop_core = declare_dependency(link_with : sciqlop_core_lib, | |||
|
69 | include_directories : core_inc, | |||
|
70 | dependencies : [qt5core, qt5network, libcatalogs_dep]) | |||
|
71 | ||||
|
72 | ||||
|
73 | ||||
|
74 | subdir('tests') | |||
|
75 |
@@ -0,0 +1,78 | |||||
|
1 | #include "Version.h" | |||
|
2 | ||||
|
3 | /*************************************************** | |||
|
4 | * @SCIQLOP_CMAKE_GENERATION_WARNING@ * | |||
|
5 | ***************************************************/ | |||
|
6 | ||||
|
7 | #include <QtCore/QDateTime> | |||
|
8 | #include <QtCore/QStringList> | |||
|
9 | ||||
|
10 | namespace sciqlop { | |||
|
11 | ||||
|
12 | const char *Version::VERSION_SUFFIX = "@SCIQLOP_VERSION_SUFFIX@"; | |||
|
13 | ||||
|
14 | /** | |||
|
15 | * From the C99 standard: | |||
|
16 | * __DATE__: The date of translation of the preprocessing translation unit: | |||
|
17 | * a character string literal of the form "Mmm dd yyyy", where the names of | |||
|
18 | * the months are the same as those generated by the asctime function, and | |||
|
19 | * the first character of dd is a space character if the value is less than | |||
|
20 | * 10. If the date of translation is not available, an | |||
|
21 | * implementation-defined valid date shall be supplied. | |||
|
22 | */ | |||
|
23 | const char *Version::BUILD_DATE = __DATE__; | |||
|
24 | /** | |||
|
25 | * From the C99 standard: | |||
|
26 | * __TIME__: The time of translation of the preprocessing translation unit: | |||
|
27 | * a character string literal of the form "hh:mm:ss" as in the time | |||
|
28 | * generated by the asctime function. If the time of translation is not | |||
|
29 | * available, an implementation-defined valid time shall be supplied. | |||
|
30 | */ | |||
|
31 | const char *Version::BUILD_TIME = __TIME__; | |||
|
32 | ||||
|
33 | QDateTime Version::buildDateTime() | |||
|
34 | { | |||
|
35 | static QDateTime buildDateTime; | |||
|
36 | if (!buildDateTime.isValid()) { | |||
|
37 | // Convert BUILD_DATE to a QDate | |||
|
38 | // The __DATE__ macro return the month name with the asctime() function, | |||
|
39 | // which doesn't support localization, the month names returned are | |||
|
40 | // always the same. On the contrary, the "MMM" format on | |||
|
41 | // QDate::fromString() is localized, so this method can't be used to | |||
|
42 | // retrieve the month and we must manually do it instead. | |||
|
43 | QString buildDateStr = QString(BUILD_DATE); | |||
|
44 | QString buildMonthStr = buildDateStr.left(3); | |||
|
45 | QString buildDayAndYearStr = buildDateStr.mid(4).trimmed(); | |||
|
46 | ||||
|
47 | QDate buildDate = QDate::fromString(buildDayAndYearStr, "d yyyy"); | |||
|
48 | QStringList monthList = QStringList() << "Jan" | |||
|
49 | << "Feb" | |||
|
50 | << "Mar" | |||
|
51 | << "Apr" | |||
|
52 | << "May" | |||
|
53 | << "Jun" | |||
|
54 | << "Jul" | |||
|
55 | << "Aug" | |||
|
56 | << "Sep" | |||
|
57 | << "Oct" | |||
|
58 | << "Nov" | |||
|
59 | << "Dec"; | |||
|
60 | for (int i = 0; i < monthList.size(); ++i) { | |||
|
61 | if (buildMonthStr == monthList.at(i)) { | |||
|
62 | buildDate.setDate(buildDate.year(), i + 1, buildDate.day()); | |||
|
63 | break; | |||
|
64 | } | |||
|
65 | } | |||
|
66 | ||||
|
67 | // Convert BUILD_TIME to a QTime | |||
|
68 | QTime buildTime = QTime::fromString(BUILD_TIME, "hh:mm:ss"); | |||
|
69 | ||||
|
70 | // Set the buildDateTime | |||
|
71 | buildDateTime.setDate(buildDate); | |||
|
72 | buildDateTime.setTime(buildTime); | |||
|
73 | } | |||
|
74 | ||||
|
75 | return buildDateTime; | |||
|
76 | } | |||
|
77 | ||||
|
78 | } // namespace sciqlop |
@@ -0,0 +1,98 | |||||
|
1 | // TODO copyright | |||
|
2 | /** | |||
|
3 | * @file Version.h | |||
|
4 | */ | |||
|
5 | #ifndef SCIQLOP_VERSION_H | |||
|
6 | #define SCIQLOP_VERSION_H | |||
|
7 | ||||
|
8 | /*************************************************** | |||
|
9 | * @SCIQLOP_CMAKE_GENERATION_WARNING@ * | |||
|
10 | ***************************************************/ | |||
|
11 | ||||
|
12 | //#include "SciqlopExport.h" | |||
|
13 | #include <QtCore/QString> | |||
|
14 | ||||
|
15 | class QDateTime; | |||
|
16 | ||||
|
17 | namespace sciqlop { | |||
|
18 | ||||
|
19 | /** | |||
|
20 | * Holds the version of Sciqlop. | |||
|
21 | * | |||
|
22 | * @attention Don't update this class directly, it is generated from the | |||
|
23 | * `resources/Version.h.in` and `resources/Version.cpp.in` files, along with | |||
|
24 | * the cmake variables defined in the `cmake/sciqlop_version.cmake` file. | |||
|
25 | * | |||
|
26 | * To change the Sciqlop version number, update the `cmake/sciqlop_version.cmake` | |||
|
27 | * file, and to change this class other than to change the version number, | |||
|
28 | * update the `resources/Version.h.in` and `resources/Version.cpp.in` files. | |||
|
29 | * @ingroup Utils | |||
|
30 | */ | |||
|
31 | class /*SCIQLOP_API*/ Version { | |||
|
32 | public: | |||
|
33 | /** | |||
|
34 | * Retrieve the version of Sciqlop. | |||
|
35 | * | |||
|
36 | * The version is of the form MAJOR.MINOR.PATCH. If a suffix has been | |||
|
37 | * provided to the version, it is appended after the PATCH. | |||
|
38 | * | |||
|
39 | * The version can be modified by updating the cmake/sciqlop_version.cmake | |||
|
40 | * file. | |||
|
41 | * | |||
|
42 | * @return The version of Sciqlop as a QString. | |||
|
43 | */ | |||
|
44 | static QString version() | |||
|
45 | { | |||
|
46 | static const QString v("@SCIQLOP_VERSION@"); | |||
|
47 | return v; | |||
|
48 | } | |||
|
49 | ||||
|
50 | /** | |||
|
51 | * @return The datetime of the build. | |||
|
52 | */ | |||
|
53 | static QDateTime buildDateTime(); | |||
|
54 | ||||
|
55 | /** | |||
|
56 | * Major version. | |||
|
57 | */ | |||
|
58 | static const int VERSION_MAJOR = @SCIQLOP_VERSION_MAJOR@; | |||
|
59 | /** | |||
|
60 | * Minor version. | |||
|
61 | */ | |||
|
62 | static const int VERSION_MINOR = @SCIQLOP_VERSION_MINOR@; | |||
|
63 | /** | |||
|
64 | * Patch version. | |||
|
65 | */ | |||
|
66 | static const int VERSION_PATCH = @SCIQLOP_VERSION_PATCH@; | |||
|
67 | /** | |||
|
68 | * Suffix version. | |||
|
69 | */ | |||
|
70 | static const char *VERSION_SUFFIX; | |||
|
71 | ||||
|
72 | /** | |||
|
73 | * Compile date computed with the __DATE__ macro. | |||
|
74 | * | |||
|
75 | * From the C99 standard: | |||
|
76 | * __DATE__: The date of translation of the preprocessing translation unit: | |||
|
77 | * a character string literal of the form "Mmm dd yyyy", where the names of | |||
|
78 | * the months are the same as those generated by the asctime function, and | |||
|
79 | * the first character of dd is a space character if the value is less than | |||
|
80 | * 10. If the date of translation is not available, an | |||
|
81 | * implementation-defined valid date shall be supplied. | |||
|
82 | */ | |||
|
83 | static const char *BUILD_DATE; | |||
|
84 | /** | |||
|
85 | * Compile time computed with the __TIME__ macro. | |||
|
86 | * | |||
|
87 | * From the C99 standard: | |||
|
88 | * __TIME__: The time of translation of the preprocessing translation unit: | |||
|
89 | * a character string literal of the form "hh:mm:ss" as in the time | |||
|
90 | * generated by the asctime function. If the time of translation is not | |||
|
91 | * available, an implementation-defined valid time shall be supplied. | |||
|
92 | */ | |||
|
93 | static const char *BUILD_TIME; | |||
|
94 | }; | |||
|
95 | ||||
|
96 | } // namespace sciqlop | |||
|
97 | ||||
|
98 | #endif // SCIQLOP_VERSION_H |
This diff has been collapsed as it changes many lines, (574 lines changed) Show them Hide them | |||||
@@ -0,0 +1,574 | |||||
|
1 | #include <Catalogue/CatalogueController.h> | |||
|
2 | ||||
|
3 | #include <Variable/Variable.h> | |||
|
4 | ||||
|
5 | #include <CatalogueDao.h> | |||
|
6 | ||||
|
7 | #include <ComparaisonPredicate.h> | |||
|
8 | #include <CompoundPredicate.h> | |||
|
9 | #include <DBCatalogue.h> | |||
|
10 | #include <DBEvent.h> | |||
|
11 | #include <DBEventProduct.h> | |||
|
12 | #include <DBTag.h> | |||
|
13 | #include <IRequestPredicate.h> | |||
|
14 | ||||
|
15 | #include <QDataStream> | |||
|
16 | #include <QMutex> | |||
|
17 | #include <QThread> | |||
|
18 | ||||
|
19 | #include <QDir> | |||
|
20 | #include <QStandardPaths> | |||
|
21 | ||||
|
22 | Q_LOGGING_CATEGORY(LOG_CatalogueController, "CatalogueController") | |||
|
23 | ||||
|
24 | namespace { | |||
|
25 | ||||
|
26 | static QString REPOSITORY_WORK_SUFFIX = QString{"_work"}; | |||
|
27 | static QString REPOSITORY_TRASH_SUFFIX = QString{"_trash"}; | |||
|
28 | } | |||
|
29 | ||||
|
30 | /** | |||
|
31 | * Possible types of an repository | |||
|
32 | */ | |||
|
33 | enum class DBType { SYNC, WORK, TRASH }; | |||
|
34 | class CatalogueController::CatalogueControllerPrivate { | |||
|
35 | ||||
|
36 | public: | |||
|
37 | explicit CatalogueControllerPrivate(CatalogueController *parent) : m_Q{parent} {} | |||
|
38 | ||||
|
39 | CatalogueDao m_CatalogueDao; | |||
|
40 | ||||
|
41 | QStringList m_RepositoryList; | |||
|
42 | CatalogueController *m_Q; | |||
|
43 | ||||
|
44 | QSet<QString> m_KeysWithChanges; | |||
|
45 | ||||
|
46 | QString eventUniqueKey(const std::shared_ptr<DBEvent> &event) const; | |||
|
47 | QString catalogueUniqueKey(const std::shared_ptr<DBCatalogue> &catalogue) const; | |||
|
48 | ||||
|
49 | void copyDBtoDB(const QString &dbFrom, const QString &dbTo); | |||
|
50 | QString toWorkRepository(QString repository); | |||
|
51 | QString toSyncRepository(QString repository); | |||
|
52 | void savAllDB(); | |||
|
53 | ||||
|
54 | void saveEvent(std::shared_ptr<DBEvent> event, bool persist = true); | |||
|
55 | void saveCatalogue(std::shared_ptr<DBCatalogue> catalogue, bool persist = true); | |||
|
56 | ||||
|
57 | std::shared_ptr<IRequestPredicate> createFinder(const QUuid &uniqId, const QString &repository, | |||
|
58 | DBType type); | |||
|
59 | }; | |||
|
60 | ||||
|
61 | CatalogueController::CatalogueController(QObject *parent) | |||
|
62 | : impl{spimpl::make_unique_impl<CatalogueControllerPrivate>(this)} | |||
|
63 | { | |||
|
64 | qCDebug(LOG_CatalogueController()) << tr("CatalogueController construction") | |||
|
65 | << QThread::currentThread(); | |||
|
66 | } | |||
|
67 | ||||
|
68 | CatalogueController::~CatalogueController() | |||
|
69 | { | |||
|
70 | qCDebug(LOG_CatalogueController()) << tr("CatalogueController destruction") | |||
|
71 | << QThread::currentThread(); | |||
|
72 | } | |||
|
73 | ||||
|
74 | QStringList CatalogueController::getRepositories() const | |||
|
75 | { | |||
|
76 | return impl->m_RepositoryList; | |||
|
77 | } | |||
|
78 | ||||
|
79 | void CatalogueController::addDB(const QString &dbPath) | |||
|
80 | { | |||
|
81 | QDir dbDir(dbPath); | |||
|
82 | if (dbDir.exists()) { | |||
|
83 | auto dirName = dbDir.dirName(); | |||
|
84 | ||||
|
85 | if (std::find(impl->m_RepositoryList.cbegin(), impl->m_RepositoryList.cend(), dirName) | |||
|
86 | != impl->m_RepositoryList.cend()) { | |||
|
87 | qCCritical(LOG_CatalogueController()) | |||
|
88 | << tr("Impossible to addDB that is already loaded"); | |||
|
89 | } | |||
|
90 | ||||
|
91 | if (!impl->m_CatalogueDao.addDB(dbPath, dirName)) { | |||
|
92 | qCCritical(LOG_CatalogueController()) | |||
|
93 | << tr("Impossible to addDB %1 from %2 ").arg(dirName, dbPath); | |||
|
94 | } | |||
|
95 | else { | |||
|
96 | impl->m_RepositoryList << dirName; | |||
|
97 | impl->copyDBtoDB(dirName, impl->toWorkRepository(dirName)); | |||
|
98 | } | |||
|
99 | } | |||
|
100 | else { | |||
|
101 | qCCritical(LOG_CatalogueController()) << tr("Impossible to addDB that not exists: ") | |||
|
102 | << dbPath; | |||
|
103 | } | |||
|
104 | } | |||
|
105 | ||||
|
106 | void CatalogueController::saveDB(const QString &destinationPath, const QString &repository) | |||
|
107 | { | |||
|
108 | if (!impl->m_CatalogueDao.saveDB(destinationPath, repository)) { | |||
|
109 | qCCritical(LOG_CatalogueController()) | |||
|
110 | << tr("Impossible to saveDB %1 from %2 ").arg(repository, destinationPath); | |||
|
111 | } | |||
|
112 | } | |||
|
113 | ||||
|
114 | std::list<std::shared_ptr<DBEvent> > | |||
|
115 | CatalogueController::retrieveEvents(const QString &repository) const | |||
|
116 | { | |||
|
117 | QString dbDireName = repository.isEmpty() ? REPOSITORY_DEFAULT : repository; | |||
|
118 | ||||
|
119 | auto eventsShared = std::list<std::shared_ptr<DBEvent> >{}; | |||
|
120 | auto events = impl->m_CatalogueDao.getEvents(impl->toWorkRepository(dbDireName)); | |||
|
121 | for (auto event : events) { | |||
|
122 | eventsShared.push_back(std::make_shared<DBEvent>(event)); | |||
|
123 | } | |||
|
124 | return eventsShared; | |||
|
125 | } | |||
|
126 | ||||
|
127 | std::list<std::shared_ptr<DBEvent> > CatalogueController::retrieveAllEvents() const | |||
|
128 | { | |||
|
129 | auto eventsShared = std::list<std::shared_ptr<DBEvent> >{}; | |||
|
130 | for (auto repository : impl->m_RepositoryList) { | |||
|
131 | eventsShared.splice(eventsShared.end(), retrieveEvents(repository)); | |||
|
132 | } | |||
|
133 | ||||
|
134 | return eventsShared; | |||
|
135 | } | |||
|
136 | ||||
|
137 | std::list<std::shared_ptr<DBEvent> > | |||
|
138 | CatalogueController::retrieveEventsFromCatalogue(std::shared_ptr<DBCatalogue> catalogue) const | |||
|
139 | { | |||
|
140 | auto eventsShared = std::list<std::shared_ptr<DBEvent> >{}; | |||
|
141 | auto events = impl->m_CatalogueDao.getCatalogueEvents(*catalogue); | |||
|
142 | for (auto event : events) { | |||
|
143 | eventsShared.push_back(std::make_shared<DBEvent>(event)); | |||
|
144 | } | |||
|
145 | return eventsShared; | |||
|
146 | } | |||
|
147 | ||||
|
148 | void CatalogueController::updateEvent(std::shared_ptr<DBEvent> event) | |||
|
149 | { | |||
|
150 | event->setRepository(impl->toWorkRepository(event->getRepository())); | |||
|
151 | ||||
|
152 | auto uniqueId = impl->eventUniqueKey(event); | |||
|
153 | impl->m_KeysWithChanges.insert(uniqueId); | |||
|
154 | ||||
|
155 | impl->m_CatalogueDao.updateEvent(*event); | |||
|
156 | } | |||
|
157 | ||||
|
158 | void CatalogueController::updateEventProduct(std::shared_ptr<DBEventProduct> eventProduct) | |||
|
159 | { | |||
|
160 | impl->m_CatalogueDao.updateEventProduct(*eventProduct); | |||
|
161 | } | |||
|
162 | ||||
|
163 | void CatalogueController::removeEvent(std::shared_ptr<DBEvent> event) | |||
|
164 | { | |||
|
165 | // Remove it from both repository and repository_work | |||
|
166 | event->setRepository(impl->toWorkRepository(event->getRepository())); | |||
|
167 | impl->m_CatalogueDao.removeEvent(*event); | |||
|
168 | event->setRepository(impl->toSyncRepository(event->getRepository())); | |||
|
169 | impl->m_CatalogueDao.removeEvent(*event); | |||
|
170 | impl->savAllDB(); | |||
|
171 | } | |||
|
172 | ||||
|
173 | void CatalogueController::addEvent(std::shared_ptr<DBEvent> event) | |||
|
174 | { | |||
|
175 | event->setRepository(impl->toWorkRepository(event->getRepository())); | |||
|
176 | ||||
|
177 | auto eventTemp = *event; | |||
|
178 | impl->m_CatalogueDao.addEvent(eventTemp); | |||
|
179 | ||||
|
180 | // Call update is necessary at the creation of add Event if it has some tags or some event | |||
|
181 | // products | |||
|
182 | if (!event->getEventProducts().empty() || !event->getTags().empty()) { | |||
|
183 | ||||
|
184 | auto eventProductsTemp = eventTemp.getEventProducts(); | |||
|
185 | auto eventProductTempUpdated = std::list<DBEventProduct>{}; | |||
|
186 | for (auto eventProductTemp : eventProductsTemp) { | |||
|
187 | eventProductTemp.setEvent(eventTemp); | |||
|
188 | eventProductTempUpdated.push_back(eventProductTemp); | |||
|
189 | } | |||
|
190 | eventTemp.setEventProducts(eventProductTempUpdated); | |||
|
191 | ||||
|
192 | impl->m_CatalogueDao.updateEvent(eventTemp); | |||
|
193 | } | |||
|
194 | ||||
|
195 | auto workPred = impl->createFinder(event->getUniqId(), event->getRepository(), DBType::WORK); | |||
|
196 | ||||
|
197 | auto workEvent = impl->m_CatalogueDao.getEvent(workPred); | |||
|
198 | *event = workEvent; | |||
|
199 | ||||
|
200 | ||||
|
201 | auto uniqueId = impl->eventUniqueKey(event); | |||
|
202 | impl->m_KeysWithChanges.insert(uniqueId); | |||
|
203 | } | |||
|
204 | ||||
|
205 | void CatalogueController::saveEvent(std::shared_ptr<DBEvent> event) | |||
|
206 | { | |||
|
207 | impl->saveEvent(event, true); | |||
|
208 | impl->m_KeysWithChanges.remove(impl->eventUniqueKey(event)); | |||
|
209 | } | |||
|
210 | ||||
|
211 | void CatalogueController::discardEvent(std::shared_ptr<DBEvent> event, bool &removed) | |||
|
212 | { | |||
|
213 | auto syncPred = impl->createFinder(event->getUniqId(), event->getRepository(), DBType::SYNC); | |||
|
214 | auto workPred = impl->createFinder(event->getUniqId(), event->getRepository(), DBType::WORK); | |||
|
215 | ||||
|
216 | auto syncEvent = impl->m_CatalogueDao.getEvent(syncPred); | |||
|
217 | if (!syncEvent.getUniqId().isNull()) { | |||
|
218 | removed = false; | |||
|
219 | impl->m_CatalogueDao.copyEvent(syncEvent, impl->toWorkRepository(event->getRepository()), | |||
|
220 | true); | |||
|
221 | ||||
|
222 | auto workEvent = impl->m_CatalogueDao.getEvent(workPred); | |||
|
223 | *event = workEvent; | |||
|
224 | impl->m_KeysWithChanges.remove(impl->eventUniqueKey(event)); | |||
|
225 | } | |||
|
226 | else { | |||
|
227 | removed = true; | |||
|
228 | // Since the element wasn't in sync repository. Discard it means remove it | |||
|
229 | event->setRepository(impl->toWorkRepository(event->getRepository())); | |||
|
230 | impl->m_CatalogueDao.removeEvent(*event); | |||
|
231 | } | |||
|
232 | } | |||
|
233 | ||||
|
234 | bool CatalogueController::eventHasChanges(std::shared_ptr<DBEvent> event) const | |||
|
235 | { | |||
|
236 | return impl->m_KeysWithChanges.contains(impl->eventUniqueKey(event)); | |||
|
237 | } | |||
|
238 | ||||
|
239 | std::list<std::shared_ptr<DBCatalogue> > | |||
|
240 | CatalogueController::retrieveCatalogues(const QString &repository) const | |||
|
241 | { | |||
|
242 | QString dbDireName = repository.isEmpty() ? REPOSITORY_DEFAULT : repository; | |||
|
243 | ||||
|
244 | auto cataloguesShared = std::list<std::shared_ptr<DBCatalogue> >{}; | |||
|
245 | auto catalogues = impl->m_CatalogueDao.getCatalogues(impl->toWorkRepository(dbDireName)); | |||
|
246 | for (auto catalogue : catalogues) { | |||
|
247 | cataloguesShared.push_back(std::make_shared<DBCatalogue>(catalogue)); | |||
|
248 | } | |||
|
249 | return cataloguesShared; | |||
|
250 | } | |||
|
251 | ||||
|
252 | void CatalogueController::addCatalogue(std::shared_ptr<DBCatalogue> catalogue) | |||
|
253 | { | |||
|
254 | catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository())); | |||
|
255 | ||||
|
256 | auto catalogueTemp = *catalogue; | |||
|
257 | impl->m_CatalogueDao.addCatalogue(catalogueTemp); | |||
|
258 | ||||
|
259 | auto workPred | |||
|
260 | = impl->createFinder(catalogue->getUniqId(), catalogue->getRepository(), DBType::WORK); | |||
|
261 | ||||
|
262 | auto workCatalogue = impl->m_CatalogueDao.getCatalogue(workPred); | |||
|
263 | *catalogue = workCatalogue; | |||
|
264 | ||||
|
265 | auto uniqueId = impl->catalogueUniqueKey(catalogue); | |||
|
266 | impl->m_KeysWithChanges.insert(uniqueId); | |||
|
267 | } | |||
|
268 | ||||
|
269 | void CatalogueController::updateCatalogue(std::shared_ptr<DBCatalogue> catalogue) | |||
|
270 | { | |||
|
271 | catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository())); | |||
|
272 | ||||
|
273 | auto uniqueId = impl->catalogueUniqueKey(catalogue); | |||
|
274 | impl->m_KeysWithChanges.insert(uniqueId); | |||
|
275 | ||||
|
276 | impl->m_CatalogueDao.updateCatalogue(*catalogue); | |||
|
277 | } | |||
|
278 | ||||
|
279 | void CatalogueController::removeCatalogue(std::shared_ptr<DBCatalogue> catalogue) | |||
|
280 | { | |||
|
281 | // Remove it from both repository and repository_work | |||
|
282 | catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository())); | |||
|
283 | impl->m_CatalogueDao.removeCatalogue(*catalogue); | |||
|
284 | catalogue->setRepository(impl->toSyncRepository(catalogue->getRepository())); | |||
|
285 | impl->m_CatalogueDao.removeCatalogue(*catalogue); | |||
|
286 | impl->savAllDB(); | |||
|
287 | } | |||
|
288 | ||||
|
289 | void CatalogueController::saveCatalogue(std::shared_ptr<DBCatalogue> catalogue) | |||
|
290 | { | |||
|
291 | impl->saveCatalogue(catalogue, true); | |||
|
292 | impl->m_KeysWithChanges.remove(impl->catalogueUniqueKey(catalogue)); | |||
|
293 | ||||
|
294 | // remove key of events of the catalogue | |||
|
295 | if (catalogue->getType() == CatalogueType::STATIC) { | |||
|
296 | auto events = this->retrieveEventsFromCatalogue(catalogue); | |||
|
297 | for (auto event : events) { | |||
|
298 | impl->m_KeysWithChanges.remove(impl->eventUniqueKey(event)); | |||
|
299 | } | |||
|
300 | } | |||
|
301 | } | |||
|
302 | ||||
|
303 | void CatalogueController::discardCatalogue(std::shared_ptr<DBCatalogue> catalogue, bool &removed) | |||
|
304 | { | |||
|
305 | auto syncPred | |||
|
306 | = impl->createFinder(catalogue->getUniqId(), catalogue->getRepository(), DBType::SYNC); | |||
|
307 | auto workPred | |||
|
308 | = impl->createFinder(catalogue->getUniqId(), catalogue->getRepository(), DBType::WORK); | |||
|
309 | ||||
|
310 | auto syncCatalogue = impl->m_CatalogueDao.getCatalogue(syncPred); | |||
|
311 | if (!syncCatalogue.getUniqId().isNull()) { | |||
|
312 | removed = false; | |||
|
313 | impl->m_CatalogueDao.copyCatalogue( | |||
|
314 | syncCatalogue, impl->toWorkRepository(catalogue->getRepository()), true); | |||
|
315 | ||||
|
316 | auto workCatalogue = impl->m_CatalogueDao.getCatalogue(workPred); | |||
|
317 | *catalogue = workCatalogue; | |||
|
318 | impl->m_KeysWithChanges.remove(impl->catalogueUniqueKey(catalogue)); | |||
|
319 | } | |||
|
320 | else { | |||
|
321 | removed = true; | |||
|
322 | // Since the element wasn't in sync repository. Discard it means remove it | |||
|
323 | catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository())); | |||
|
324 | impl->m_CatalogueDao.removeCatalogue(*catalogue); | |||
|
325 | } | |||
|
326 | } | |||
|
327 | ||||
|
328 | void CatalogueController::saveAll() | |||
|
329 | { | |||
|
330 | for (auto repository : impl->m_RepositoryList) { | |||
|
331 | // Save Event | |||
|
332 | auto events = this->retrieveEvents(repository); | |||
|
333 | for (auto event : events) { | |||
|
334 | impl->saveEvent(event, false); | |||
|
335 | } | |||
|
336 | ||||
|
337 | // Save Catalogue | |||
|
338 | auto catalogues = this->retrieveCatalogues(repository); | |||
|
339 | for (auto catalogue : catalogues) { | |||
|
340 | impl->saveCatalogue(catalogue, false); | |||
|
341 | } | |||
|
342 | } | |||
|
343 | ||||
|
344 | impl->savAllDB(); | |||
|
345 | impl->m_KeysWithChanges.clear(); | |||
|
346 | } | |||
|
347 | ||||
|
348 | bool CatalogueController::hasChanges() const | |||
|
349 | { | |||
|
350 | return !impl->m_KeysWithChanges.isEmpty(); | |||
|
351 | } | |||
|
352 | ||||
|
353 | QByteArray | |||
|
354 | CatalogueController::mimeDataForEvents(const QVector<std::shared_ptr<DBEvent> > &events) const | |||
|
355 | { | |||
|
356 | auto encodedData = QByteArray{}; | |||
|
357 | ||||
|
358 | QMap<QString, QVariantList> idsPerRepository; | |||
|
359 | for (auto event : events) { | |||
|
360 | idsPerRepository[event->getRepository()] << event->getUniqId(); | |||
|
361 | } | |||
|
362 | ||||
|
363 | QDataStream stream{&encodedData, QIODevice::WriteOnly}; | |||
|
364 | stream << idsPerRepository; | |||
|
365 | ||||
|
366 | return encodedData; | |||
|
367 | } | |||
|
368 | ||||
|
369 | QVector<std::shared_ptr<DBEvent> > | |||
|
370 | CatalogueController::eventsForMimeData(const QByteArray &mimeData) const | |||
|
371 | { | |||
|
372 | auto events = QVector<std::shared_ptr<DBEvent> >{}; | |||
|
373 | QDataStream stream{mimeData}; | |||
|
374 | ||||
|
375 | QMap<QString, QVariantList> idsPerRepository; | |||
|
376 | stream >> idsPerRepository; | |||
|
377 | ||||
|
378 | for (auto it = idsPerRepository.cbegin(); it != idsPerRepository.cend(); ++it) { | |||
|
379 | auto repository = it.key(); | |||
|
380 | auto allRepositoryEvent = retrieveEvents(repository); | |||
|
381 | for (auto uuid : it.value()) { | |||
|
382 | for (auto repositoryEvent : allRepositoryEvent) { | |||
|
383 | if (uuid.toUuid() == repositoryEvent->getUniqId()) { | |||
|
384 | events << repositoryEvent; | |||
|
385 | } | |||
|
386 | } | |||
|
387 | } | |||
|
388 | } | |||
|
389 | ||||
|
390 | return events; | |||
|
391 | } | |||
|
392 | ||||
|
393 | QByteArray CatalogueController::mimeDataForCatalogues( | |||
|
394 | const QVector<std::shared_ptr<DBCatalogue> > &catalogues) const | |||
|
395 | { | |||
|
396 | auto encodedData = QByteArray{}; | |||
|
397 | ||||
|
398 | QMap<QString, QVariantList> idsPerRepository; | |||
|
399 | for (auto catalogue : catalogues) { | |||
|
400 | idsPerRepository[catalogue->getRepository()] << catalogue->getUniqId(); | |||
|
401 | } | |||
|
402 | ||||
|
403 | QDataStream stream{&encodedData, QIODevice::WriteOnly}; | |||
|
404 | stream << idsPerRepository; | |||
|
405 | ||||
|
406 | return encodedData; | |||
|
407 | } | |||
|
408 | ||||
|
409 | QVector<std::shared_ptr<DBCatalogue> > | |||
|
410 | CatalogueController::cataloguesForMimeData(const QByteArray &mimeData) const | |||
|
411 | { | |||
|
412 | auto catalogues = QVector<std::shared_ptr<DBCatalogue> >{}; | |||
|
413 | QDataStream stream{mimeData}; | |||
|
414 | ||||
|
415 | QMap<QString, QVariantList> idsPerRepository; | |||
|
416 | stream >> idsPerRepository; | |||
|
417 | ||||
|
418 | for (auto it = idsPerRepository.cbegin(); it != idsPerRepository.cend(); ++it) { | |||
|
419 | auto repository = it.key(); | |||
|
420 | auto allRepositoryCatalogues = retrieveCatalogues(repository); | |||
|
421 | for (auto uuid : it.value()) { | |||
|
422 | for (auto repositoryCatalogues : allRepositoryCatalogues) { | |||
|
423 | if (uuid.toUuid() == repositoryCatalogues->getUniqId()) { | |||
|
424 | catalogues << repositoryCatalogues; | |||
|
425 | } | |||
|
426 | } | |||
|
427 | } | |||
|
428 | } | |||
|
429 | ||||
|
430 | return catalogues; | |||
|
431 | } | |||
|
432 | ||||
|
433 | void CatalogueController::initialize() | |||
|
434 | { | |||
|
435 | qCDebug(LOG_CatalogueController()) << tr("CatalogueController init") | |||
|
436 | << QThread::currentThread(); | |||
|
437 | ||||
|
438 | impl->m_CatalogueDao.initialize(); | |||
|
439 | auto defaultRepositoryLocation | |||
|
440 | = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); | |||
|
441 | ||||
|
442 | QDir defaultRepositoryLocationDir; | |||
|
443 | if (defaultRepositoryLocationDir.mkpath(defaultRepositoryLocation)) { | |||
|
444 | defaultRepositoryLocationDir.cd(defaultRepositoryLocation); | |||
|
445 | auto defaultRepository = defaultRepositoryLocationDir.absoluteFilePath(REPOSITORY_DEFAULT); | |||
|
446 | ||||
|
447 | qCInfo(LOG_CatalogueController()) << tr("Persistant data loading from: ") | |||
|
448 | << defaultRepository; | |||
|
449 | ||||
|
450 | QDir dbDir(defaultRepository); | |||
|
451 | impl->m_RepositoryList << REPOSITORY_DEFAULT; | |||
|
452 | if (dbDir.exists()) { | |||
|
453 | auto dirName = dbDir.dirName(); | |||
|
454 | ||||
|
455 | if (impl->m_CatalogueDao.addDB(defaultRepository, dirName)) { | |||
|
456 | impl->copyDBtoDB(dirName, impl->toWorkRepository(dirName)); | |||
|
457 | } | |||
|
458 | } | |||
|
459 | else { | |||
|
460 | qCInfo(LOG_CatalogueController()) << tr("Initialisation of Default repository detected") | |||
|
461 | << defaultRepository; | |||
|
462 | } | |||
|
463 | } | |||
|
464 | else { | |||
|
465 | qCWarning(LOG_CatalogueController()) | |||
|
466 | << tr("Cannot load the persistent default repository from ") | |||
|
467 | << defaultRepositoryLocation; | |||
|
468 | } | |||
|
469 | ||||
|
470 | qCDebug(LOG_CatalogueController()) << tr("CatalogueController init END"); | |||
|
471 | } | |||
|
472 | ||||
|
473 | QString CatalogueController::CatalogueControllerPrivate::eventUniqueKey( | |||
|
474 | const std::shared_ptr<DBEvent> &event) const | |||
|
475 | { | |||
|
476 | return event->getUniqId().toString().append(event->getRepository()); | |||
|
477 | } | |||
|
478 | ||||
|
479 | QString CatalogueController::CatalogueControllerPrivate::catalogueUniqueKey( | |||
|
480 | const std::shared_ptr<DBCatalogue> &catalogue) const | |||
|
481 | { | |||
|
482 | return catalogue->getUniqId().toString().append(catalogue->getRepository()); | |||
|
483 | } | |||
|
484 | ||||
|
485 | void CatalogueController::CatalogueControllerPrivate::copyDBtoDB(const QString &dbFrom, | |||
|
486 | const QString &dbTo) | |||
|
487 | { | |||
|
488 | // auto cataloguesShared = std::list<std::shared_ptr<DBCatalogue> >{}; | |||
|
489 | auto catalogues = m_CatalogueDao.getCatalogues(dbFrom); | |||
|
490 | auto events = m_CatalogueDao.getEvents(dbFrom); | |||
|
491 | for (auto catalogue : catalogues) { | |||
|
492 | m_CatalogueDao.copyCatalogue(catalogue, dbTo, true); | |||
|
493 | } | |||
|
494 | ||||
|
495 | for (auto event : events) { | |||
|
496 | m_CatalogueDao.copyEvent(event, dbTo, true); | |||
|
497 | } | |||
|
498 | } | |||
|
499 | ||||
|
500 | QString CatalogueController::CatalogueControllerPrivate::toWorkRepository(QString repository) | |||
|
501 | { | |||
|
502 | auto syncRepository = toSyncRepository(repository); | |||
|
503 | ||||
|
504 | return QString("%1%2").arg(syncRepository, REPOSITORY_WORK_SUFFIX); | |||
|
505 | } | |||
|
506 | ||||
|
507 | QString CatalogueController::CatalogueControllerPrivate::toSyncRepository(QString repository) | |||
|
508 | { | |||
|
509 | auto syncRepository = repository; | |||
|
510 | if (repository.endsWith(REPOSITORY_WORK_SUFFIX)) { | |||
|
511 | syncRepository.remove(REPOSITORY_WORK_SUFFIX); | |||
|
512 | } | |||
|
513 | else if (repository.endsWith(REPOSITORY_TRASH_SUFFIX)) { | |||
|
514 | syncRepository.remove(REPOSITORY_TRASH_SUFFIX); | |||
|
515 | } | |||
|
516 | return syncRepository; | |||
|
517 | } | |||
|
518 | ||||
|
519 | void CatalogueController::CatalogueControllerPrivate::savAllDB() | |||
|
520 | { | |||
|
521 | for (auto repository : m_RepositoryList) { | |||
|
522 | auto defaultRepositoryLocation | |||
|
523 | = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); | |||
|
524 | m_CatalogueDao.saveDB(defaultRepositoryLocation, repository); | |||
|
525 | } | |||
|
526 | } | |||
|
527 | ||||
|
528 | void CatalogueController::CatalogueControllerPrivate::saveEvent(std::shared_ptr<DBEvent> event, | |||
|
529 | bool persist) | |||
|
530 | { | |||
|
531 | m_CatalogueDao.copyEvent(*event, toSyncRepository(event->getRepository()), true); | |||
|
532 | if (persist) { | |||
|
533 | savAllDB(); | |||
|
534 | } | |||
|
535 | } | |||
|
536 | ||||
|
537 | void CatalogueController::CatalogueControllerPrivate::saveCatalogue( | |||
|
538 | std::shared_ptr<DBCatalogue> catalogue, bool persist) | |||
|
539 | { | |||
|
540 | m_CatalogueDao.copyCatalogue(*catalogue, toSyncRepository(catalogue->getRepository()), true); | |||
|
541 | if (persist) { | |||
|
542 | savAllDB(); | |||
|
543 | } | |||
|
544 | } | |||
|
545 | ||||
|
546 | std::shared_ptr<IRequestPredicate> CatalogueController::CatalogueControllerPrivate::createFinder( | |||
|
547 | const QUuid &uniqId, const QString &repository, DBType type) | |||
|
548 | { | |||
|
549 | // update catalogue parameter | |||
|
550 | auto uniqIdPredicate = std::make_shared<ComparaisonPredicate>(QString{"uniqId"}, uniqId, | |||
|
551 | ComparaisonOperation::EQUALEQUAL); | |||
|
552 | ||||
|
553 | auto repositoryType = repository; | |||
|
554 | switch (type) { | |||
|
555 | case DBType::SYNC: | |||
|
556 | repositoryType = toSyncRepository(repositoryType); | |||
|
557 | break; | |||
|
558 | case DBType::WORK: | |||
|
559 | repositoryType = toWorkRepository(repositoryType); | |||
|
560 | break; | |||
|
561 | case DBType::TRASH: | |||
|
562 | default: | |||
|
563 | break; | |||
|
564 | } | |||
|
565 | ||||
|
566 | auto repositoryPredicate = std::make_shared<ComparaisonPredicate>( | |||
|
567 | QString{"repository"}, repositoryType, ComparaisonOperation::EQUALEQUAL); | |||
|
568 | ||||
|
569 | auto finderPred = std::make_shared<CompoundPredicate>(CompoundOperation::AND); | |||
|
570 | finderPred->AddRequestPredicate(uniqIdPredicate); | |||
|
571 | finderPred->AddRequestPredicate(repositoryPredicate); | |||
|
572 | ||||
|
573 | return finderPred; | |||
|
574 | } |
@@ -0,0 +1,13 | |||||
|
1 | #include "Common/DateUtils.h" | |||
|
2 | ||||
|
3 | QDateTime DateUtils::dateTime(double secs, Qt::TimeSpec timeSpec) noexcept | |||
|
4 | { | |||
|
5 | // Uses msecs to be Qt 4 compatible | |||
|
6 | return QDateTime::fromMSecsSinceEpoch(secs * 1000., timeSpec); | |||
|
7 | } | |||
|
8 | ||||
|
9 | double DateUtils::secondsSinceEpoch(const QDateTime &dateTime) noexcept | |||
|
10 | { | |||
|
11 | // Uses msecs to be Qt 4 compatible | |||
|
12 | return dateTime.toMSecsSinceEpoch() / 1000.; | |||
|
13 | } |
@@ -0,0 +1,10 | |||||
|
1 | #include "Common/MimeTypesDef.h" | |||
|
2 | ||||
|
3 | const QString MIME_TYPE_GRAPH = QStringLiteral("sciqlop/graph"); | |||
|
4 | const QString MIME_TYPE_ZONE = QStringLiteral("sciqlop/zone"); | |||
|
5 | const QString MIME_TYPE_VARIABLE_LIST = QStringLiteral("sciqlop/var-list"); | |||
|
6 | const QString MIME_TYPE_PRODUCT_LIST = QStringLiteral("sciqlop/product-list"); | |||
|
7 | const QString MIME_TYPE_TIME_RANGE = QStringLiteral("sciqlop/time-range"); | |||
|
8 | const QString MIME_TYPE_SELECTION_ZONE = QStringLiteral("sciqlop/selection-zone"); | |||
|
9 | const QString MIME_TYPE_EVENT_LIST = QStringLiteral("sciqlop/event-list"); | |||
|
10 | const QString MIME_TYPE_SOURCE_CATALOGUE_LIST = QStringLiteral("sciqlop/source-catalogue-list"); |
@@ -0,0 +1,36 | |||||
|
1 | #include "Common/SignalWaiter.h" | |||
|
2 | ||||
|
3 | #include <QTimer> | |||
|
4 | ||||
|
5 | namespace { | |||
|
6 | ||||
|
7 | const auto DEFAULT_TIMEOUT = 30000; | |||
|
8 | ||||
|
9 | } // namespace | |||
|
10 | ||||
|
11 | SignalWaiter::SignalWaiter(QObject &sender, const char *signal) : m_Timeout{false} | |||
|
12 | { | |||
|
13 | connect(&sender, signal, &m_EventLoop, SLOT(quit())); | |||
|
14 | } | |||
|
15 | ||||
|
16 | bool SignalWaiter::wait(int timeout) | |||
|
17 | { | |||
|
18 | if (timeout == 0) { | |||
|
19 | timeout = DEFAULT_TIMEOUT; | |||
|
20 | } | |||
|
21 | ||||
|
22 | QTimer timer{}; | |||
|
23 | timer.setInterval(timeout); | |||
|
24 | timer.start(); | |||
|
25 | connect(&timer, &QTimer::timeout, this, &SignalWaiter::timeout); | |||
|
26 | ||||
|
27 | m_EventLoop.exec(); | |||
|
28 | ||||
|
29 | return !m_Timeout; | |||
|
30 | } | |||
|
31 | ||||
|
32 | void SignalWaiter::timeout() | |||
|
33 | { | |||
|
34 | m_Timeout = true; | |||
|
35 | m_EventLoop.quit(); | |||
|
36 | } |
@@ -0,0 +1,30 | |||||
|
1 | #include "Common/StringUtils.h" | |||
|
2 | ||||
|
3 | #include <QRegExp> | |||
|
4 | #include <QString> | |||
|
5 | ||||
|
6 | #include <set> | |||
|
7 | ||||
|
8 | QString StringUtils::uniqueName(const QString &defaultName, | |||
|
9 | const std::vector<QString> &forbiddenNames) noexcept | |||
|
10 | { | |||
|
11 | // Gets the base of the unique name to generate, by removing trailing number (for example, base | |||
|
12 | // name of "FGM12" is "FGM") | |||
|
13 | auto baseName = defaultName; | |||
|
14 | baseName.remove(QRegExp{QStringLiteral("\\d*$")}); | |||
|
15 | ||||
|
16 | // Finds the unique name by adding an index to the base name and stops when the generated name | |||
|
17 | // isn't forbidden | |||
|
18 | QString newName{}; | |||
|
19 | auto forbidden = true; | |||
|
20 | for (auto i = 0; forbidden; ++i) { | |||
|
21 | newName = (i == 0) ? baseName : baseName + QString::number(i); | |||
|
22 | forbidden = newName.isEmpty() | |||
|
23 | || std::any_of(forbiddenNames.cbegin(), forbiddenNames.cend(), | |||
|
24 | [&newName](const auto &name) { | |||
|
25 | return name.compare(newName, Qt::CaseInsensitive) == 0; | |||
|
26 | }); | |||
|
27 | } | |||
|
28 | ||||
|
29 | return newName; | |||
|
30 | } |
@@ -0,0 +1,77 | |||||
|
1 | #include "Data/ArrayDataIterator.h" | |||
|
2 | ||||
|
3 | ArrayDataIteratorValue::ArrayDataIteratorValue(std::unique_ptr<ArrayDataIteratorValue::Impl> impl) | |||
|
4 | : m_Impl{std::move(impl)} | |||
|
5 | { | |||
|
6 | } | |||
|
7 | ||||
|
8 | ArrayDataIteratorValue::ArrayDataIteratorValue(const ArrayDataIteratorValue &other) | |||
|
9 | : m_Impl{other.m_Impl->clone()} | |||
|
10 | { | |||
|
11 | } | |||
|
12 | ||||
|
13 | ArrayDataIteratorValue &ArrayDataIteratorValue::operator=(ArrayDataIteratorValue other) | |||
|
14 | { | |||
|
15 | m_Impl->swap(*other.m_Impl); | |||
|
16 | return *this; | |||
|
17 | } | |||
|
18 | ||||
|
19 | int ArrayDataIteratorValue::distance(const ArrayDataIteratorValue &other) const | |||
|
20 | { | |||
|
21 | return m_Impl->distance(*other.m_Impl); | |||
|
22 | } | |||
|
23 | ||||
|
24 | bool ArrayDataIteratorValue::equals(const ArrayDataIteratorValue &other) const | |||
|
25 | { | |||
|
26 | return m_Impl->equals(*other.m_Impl); | |||
|
27 | } | |||
|
28 | ||||
|
29 | bool ArrayDataIteratorValue::lowerThan(const ArrayDataIteratorValue &other) const | |||
|
30 | { | |||
|
31 | return m_Impl->lowerThan(*other.m_Impl); | |||
|
32 | } | |||
|
33 | ||||
|
34 | ArrayDataIteratorValue ArrayDataIteratorValue::advance(int offset) const | |||
|
35 | { | |||
|
36 | return ArrayDataIteratorValue{m_Impl->advance(offset)}; | |||
|
37 | } | |||
|
38 | ||||
|
39 | void ArrayDataIteratorValue::next(int offset) | |||
|
40 | { | |||
|
41 | m_Impl->next(offset); | |||
|
42 | } | |||
|
43 | ||||
|
44 | void ArrayDataIteratorValue::prev() | |||
|
45 | { | |||
|
46 | m_Impl->prev(); | |||
|
47 | } | |||
|
48 | ||||
|
49 | double ArrayDataIteratorValue::at(int componentIndex) const | |||
|
50 | { | |||
|
51 | return m_Impl->at(componentIndex); | |||
|
52 | } | |||
|
53 | ||||
|
54 | double ArrayDataIteratorValue::first() const | |||
|
55 | { | |||
|
56 | return m_Impl->first(); | |||
|
57 | } | |||
|
58 | ||||
|
59 | double ArrayDataIteratorValue::min() const | |||
|
60 | { | |||
|
61 | return m_Impl->min(); | |||
|
62 | } | |||
|
63 | ||||
|
64 | double ArrayDataIteratorValue::max() const | |||
|
65 | { | |||
|
66 | return m_Impl->max(); | |||
|
67 | } | |||
|
68 | ||||
|
69 | QVector<double> ArrayDataIteratorValue::values() const | |||
|
70 | { | |||
|
71 | return m_Impl->values(); | |||
|
72 | } | |||
|
73 | ||||
|
74 | ArrayDataIteratorValue::Impl *ArrayDataIteratorValue::impl() | |||
|
75 | { | |||
|
76 | return m_Impl.get(); | |||
|
77 | } |
@@ -0,0 +1,88 | |||||
|
1 | #include "Data/DataSeriesIterator.h" | |||
|
2 | ||||
|
3 | DataSeriesIteratorValue::DataSeriesIteratorValue( | |||
|
4 | std::unique_ptr<DataSeriesIteratorValue::Impl> impl) | |||
|
5 | : m_Impl{std::move(impl)} | |||
|
6 | { | |||
|
7 | } | |||
|
8 | ||||
|
9 | DataSeriesIteratorValue::DataSeriesIteratorValue(const DataSeriesIteratorValue &other) | |||
|
10 | : m_Impl{other.m_Impl->clone()} | |||
|
11 | { | |||
|
12 | } | |||
|
13 | ||||
|
14 | DataSeriesIteratorValue &DataSeriesIteratorValue::operator=(DataSeriesIteratorValue other) | |||
|
15 | { | |||
|
16 | m_Impl->swap(*other.m_Impl); | |||
|
17 | return *this; | |||
|
18 | } | |||
|
19 | ||||
|
20 | int DataSeriesIteratorValue::distance(const DataSeriesIteratorValue &other) const | |||
|
21 | { | |||
|
22 | return m_Impl->distance(*other.m_Impl); | |||
|
23 | } | |||
|
24 | ||||
|
25 | bool DataSeriesIteratorValue::equals(const DataSeriesIteratorValue &other) const | |||
|
26 | { | |||
|
27 | return m_Impl->equals(*other.m_Impl); | |||
|
28 | } | |||
|
29 | ||||
|
30 | bool DataSeriesIteratorValue::lowerThan(const DataSeriesIteratorValue &other) const | |||
|
31 | { | |||
|
32 | return m_Impl->lowerThan(*other.m_Impl); | |||
|
33 | } | |||
|
34 | ||||
|
35 | DataSeriesIteratorValue DataSeriesIteratorValue::advance(int offset) const | |||
|
36 | { | |||
|
37 | return DataSeriesIteratorValue{m_Impl->advance(offset)}; | |||
|
38 | } | |||
|
39 | ||||
|
40 | void DataSeriesIteratorValue::next(int offset) | |||
|
41 | { | |||
|
42 | m_Impl->next(offset); | |||
|
43 | } | |||
|
44 | ||||
|
45 | void DataSeriesIteratorValue::prev() | |||
|
46 | { | |||
|
47 | m_Impl->prev(); | |||
|
48 | } | |||
|
49 | ||||
|
50 | double DataSeriesIteratorValue::x() const | |||
|
51 | { | |||
|
52 | return m_Impl->x(); | |||
|
53 | } | |||
|
54 | ||||
|
55 | std::vector<double> DataSeriesIteratorValue::y() const | |||
|
56 | { | |||
|
57 | return m_Impl->y(); | |||
|
58 | } | |||
|
59 | ||||
|
60 | double DataSeriesIteratorValue::value() const | |||
|
61 | { | |||
|
62 | return m_Impl->value(); | |||
|
63 | } | |||
|
64 | ||||
|
65 | double DataSeriesIteratorValue::value(int componentIndex) const | |||
|
66 | { | |||
|
67 | return m_Impl->value(componentIndex); | |||
|
68 | } | |||
|
69 | ||||
|
70 | double DataSeriesIteratorValue::minValue() const | |||
|
71 | { | |||
|
72 | return m_Impl->minValue(); | |||
|
73 | } | |||
|
74 | ||||
|
75 | double DataSeriesIteratorValue::maxValue() const | |||
|
76 | { | |||
|
77 | return m_Impl->maxValue(); | |||
|
78 | } | |||
|
79 | ||||
|
80 | QVector<double> DataSeriesIteratorValue::values() const | |||
|
81 | { | |||
|
82 | return m_Impl->values(); | |||
|
83 | } | |||
|
84 | ||||
|
85 | DataSeriesIteratorValue::Impl *DataSeriesIteratorValue::impl() | |||
|
86 | { | |||
|
87 | return m_Impl.get(); | |||
|
88 | } |
@@ -0,0 +1,194 | |||||
|
1 | #include "Data/DataSeriesUtils.h" | |||
|
2 | ||||
|
3 | Q_LOGGING_CATEGORY(LOG_DataSeriesUtils, "DataSeriesUtils") | |||
|
4 | ||||
|
5 | void DataSeriesUtils::fillDataHoles(std::vector<double> &xAxisData, std::vector<double> &valuesData, | |||
|
6 | double resolution, double fillValue, double minBound, | |||
|
7 | double maxBound) | |||
|
8 | { | |||
|
9 | if (resolution == 0. || std::isnan(resolution)) { | |||
|
10 | qCWarning(LOG_DataSeriesUtils()) | |||
|
11 | << "Can't fill data holes with a null resolution, no changes will be made"; | |||
|
12 | return; | |||
|
13 | } | |||
|
14 | ||||
|
15 | if (xAxisData.empty()) { | |||
|
16 | qCWarning(LOG_DataSeriesUtils()) | |||
|
17 | << "Can't fill data holes for empty data, no changes will be made"; | |||
|
18 | return; | |||
|
19 | } | |||
|
20 | ||||
|
21 | // Gets the number of values per x-axis data | |||
|
22 | auto nbComponents = valuesData.size() / xAxisData.size(); | |||
|
23 | ||||
|
24 | // Generates fill values that will be used to complete values data | |||
|
25 | std::vector<double> fillValues(nbComponents, fillValue); | |||
|
26 | ||||
|
27 | // Checks if there are data holes on the beginning of the data and generates the hole at the | |||
|
28 | // extremity if it's the case | |||
|
29 | auto minXAxisData = xAxisData.front(); | |||
|
30 | if (!std::isnan(minBound) && minBound < minXAxisData) { | |||
|
31 | auto holeSize = static_cast<int>((minXAxisData - minBound) / resolution); | |||
|
32 | if (holeSize > 0) { | |||
|
33 | xAxisData.insert(xAxisData.begin(), minXAxisData - holeSize * resolution); | |||
|
34 | valuesData.insert(valuesData.begin(), fillValues.begin(), fillValues.end()); | |||
|
35 | } | |||
|
36 | } | |||
|
37 | ||||
|
38 | // Same for the end of the data | |||
|
39 | auto maxXAxisData = xAxisData.back(); | |||
|
40 | if (!std::isnan(maxBound) && maxBound > maxXAxisData) { | |||
|
41 | auto holeSize = static_cast<int>((maxBound - maxXAxisData) / resolution); | |||
|
42 | if (holeSize > 0) { | |||
|
43 | xAxisData.insert(xAxisData.end(), maxXAxisData + holeSize * resolution); | |||
|
44 | valuesData.insert(valuesData.end(), fillValues.begin(), fillValues.end()); | |||
|
45 | } | |||
|
46 | } | |||
|
47 | ||||
|
48 | // Generates other data holes | |||
|
49 | auto xAxisIt = xAxisData.begin(); | |||
|
50 | while (xAxisIt != xAxisData.end()) { | |||
|
51 | // Stops at first value which has a gap greater than resolution with the value next to it | |||
|
52 | xAxisIt = std::adjacent_find( | |||
|
53 | xAxisIt, xAxisData.end(), | |||
|
54 | [resolution](const auto &a, const auto &b) { return (b - a) > resolution; }); | |||
|
55 | ||||
|
56 | if (xAxisIt != xAxisData.end()) { | |||
|
57 | auto nextXAxisIt = xAxisIt + 1; | |||
|
58 | ||||
|
59 | // Gets the values that has a gap greater than resolution between them | |||
|
60 | auto lowValue = *xAxisIt; | |||
|
61 | auto highValue = *nextXAxisIt; | |||
|
62 | ||||
|
63 | // Completes holes between the two values by creating new values (according to the | |||
|
64 | // resolution) | |||
|
65 | for (auto i = lowValue + resolution; i < highValue; i += resolution) { | |||
|
66 | // Gets the iterator of values data from which to insert fill values | |||
|
67 | auto nextValuesIt = valuesData.begin() | |||
|
68 | + std::distance(xAxisData.begin(), nextXAxisIt) * nbComponents; | |||
|
69 | ||||
|
70 | // New value is inserted before nextXAxisIt | |||
|
71 | nextXAxisIt = xAxisData.insert(nextXAxisIt, i) + 1; | |||
|
72 | ||||
|
73 | // New values are inserted before nextValuesIt | |||
|
74 | valuesData.insert(nextValuesIt, fillValues.begin(), fillValues.end()); | |||
|
75 | } | |||
|
76 | ||||
|
77 | // Moves to the next value to continue loop on the x-axis data | |||
|
78 | xAxisIt = nextXAxisIt; | |||
|
79 | } | |||
|
80 | } | |||
|
81 | } | |||
|
82 | ||||
|
83 | namespace { | |||
|
84 | ||||
|
85 | /** | |||
|
86 | * Generates axis's mesh properties according to data and resolution | |||
|
87 | * @param begin the iterator pointing to the beginning of the data | |||
|
88 | * @param end the iterator pointing to the end of the data | |||
|
89 | * @param fun the function to retrieve data from the data iterators | |||
|
90 | * @param resolution the resolution to use for the axis' mesh | |||
|
91 | * @return a tuple representing the mesh properties : <nb values, min value, value step> | |||
|
92 | */ | |||
|
93 | template <typename Iterator, typename IteratorFun> | |||
|
94 | std::tuple<int, double, double> meshProperties(Iterator begin, Iterator end, IteratorFun fun, | |||
|
95 | double resolution) | |||
|
96 | { | |||
|
97 | // Computes the gap between min and max data. This will be used to determinate the step between | |||
|
98 | // each data of the mesh | |||
|
99 | auto min = fun(begin); | |||
|
100 | auto max = fun(end - 1); | |||
|
101 | auto gap = max - min; | |||
|
102 | ||||
|
103 | // Computes the step trying to use the fixed resolution. If the resolution doesn't separate the | |||
|
104 | // values evenly , it is recalculated. | |||
|
105 | // For example, for a resolution of 2.0: | |||
|
106 | // - for interval [0; 8] => resolution is valid, the generated mesh will be [0, 2, 4, 6, 8] | |||
|
107 | // - for interval [0; 9] => it's impossible to create a regular mesh with this resolution | |||
|
108 | // The resolution is recalculated and is worth 1.8. The generated mesh will be [0, 1.8, 3.6, | |||
|
109 | // 5.4, 7.2, 9] | |||
|
110 | auto nbVal = static_cast<int>(std::ceil(gap / resolution)); | |||
|
111 | auto step = gap / nbVal; | |||
|
112 | ||||
|
113 | // last data is included in the total number of values | |||
|
114 | return std::make_tuple(nbVal + 1, min, step); | |||
|
115 | } | |||
|
116 | ||||
|
117 | } // namespace | |||
|
118 | ||||
|
119 | DataSeriesUtils::Mesh DataSeriesUtils::regularMesh(DataSeriesIterator begin, DataSeriesIterator end, | |||
|
120 | Resolution xResolution, Resolution yResolution) | |||
|
121 | { | |||
|
122 | // Checks preconditions | |||
|
123 | if (xResolution.m_Val == 0. || std::isnan(xResolution.m_Val) || yResolution.m_Val == 0. | |||
|
124 | || std::isnan(yResolution.m_Val)) { | |||
|
125 | qCWarning(LOG_DataSeriesUtils()) << "Can't generate mesh with a null resolution"; | |||
|
126 | return Mesh{}; | |||
|
127 | } | |||
|
128 | ||||
|
129 | if (xResolution.m_Logarithmic) { | |||
|
130 | qCWarning(LOG_DataSeriesUtils()) | |||
|
131 | << "Can't generate mesh with a logarithmic x-axis resolution"; | |||
|
132 | return Mesh{}; | |||
|
133 | } | |||
|
134 | ||||
|
135 | if (std::distance(begin, end) == 0) { | |||
|
136 | qCWarning(LOG_DataSeriesUtils()) << "Can't generate mesh for empty data"; | |||
|
137 | return Mesh{}; | |||
|
138 | } | |||
|
139 | ||||
|
140 | auto yData = begin->y(); | |||
|
141 | if (yData.empty()) { | |||
|
142 | qCWarning(LOG_DataSeriesUtils()) << "Can't generate mesh for data with no y-axis"; | |||
|
143 | return Mesh{}; | |||
|
144 | } | |||
|
145 | ||||
|
146 | // Converts y-axis and its resolution to logarithmic values | |||
|
147 | if (yResolution.m_Logarithmic) { | |||
|
148 | std::for_each(yData.begin(), yData.end(), [](auto &val) { val = std::log10(val); }); | |||
|
149 | } | |||
|
150 | ||||
|
151 | // Computes mesh properties | |||
|
152 | int nbX, nbY; | |||
|
153 | double xMin, xStep, yMin, yStep; | |||
|
154 | std::tie(nbX, xMin, xStep) | |||
|
155 | = meshProperties(begin, end, [](const auto &it) { return it->x(); }, xResolution.m_Val); | |||
|
156 | std::tie(nbY, yMin, yStep) = meshProperties( | |||
|
157 | yData.begin(), yData.end(), [](const auto &it) { return *it; }, yResolution.m_Val); | |||
|
158 | ||||
|
159 | // Generates mesh according to the x-axis and y-axis steps | |||
|
160 | Mesh result{nbX, xMin, xStep, nbY, yMin, yStep}; | |||
|
161 | ||||
|
162 | for (auto meshXIndex = 0; meshXIndex < nbX; ++meshXIndex) { | |||
|
163 | auto meshX = xMin + meshXIndex * xStep; | |||
|
164 | // According to current x-axis of the mesh, finds in the data series the interval in which | |||
|
165 | // the data is or gets closer (without exceeding it). | |||
|
166 | // An interval is defined by a value and extends to +/- 50% of the resolution. For example, | |||
|
167 | // for a value of 3 and a resolution of 1, the associated interval is [2.5, 3.5]. | |||
|
168 | auto xIt = std::lower_bound(begin, end, meshX, | |||
|
169 | [xResolution](const auto &it, const auto &val) { | |||
|
170 | return it.x() - xResolution.m_Val / 2. < val; | |||
|
171 | }) | |||
|
172 | - 1; | |||
|
173 | ||||
|
174 | // When the corresponding entry of the data series is found, generates the values of the | |||
|
175 | // mesh by retrieving the values of the entry, for each y-axis value of the mesh | |||
|
176 | auto values = xIt->values(); | |||
|
177 | ||||
|
178 | for (auto meshYIndex = 0; meshYIndex < nbY; ++meshYIndex) { | |||
|
179 | auto meshY = yMin + meshYIndex * yStep; | |||
|
180 | ||||
|
181 | auto yBegin = yData.begin(); | |||
|
182 | auto yIt = std::lower_bound(yBegin, yData.end(), meshY, | |||
|
183 | [yResolution](const auto &it, const auto &val) { | |||
|
184 | return it - yResolution.m_Val / 2. < val; | |||
|
185 | }) | |||
|
186 | - 1; | |||
|
187 | ||||
|
188 | auto valueIndex = std::distance(yBegin, yIt); | |||
|
189 | result.m_Data[result.m_NbX * meshYIndex + meshXIndex] = values.at(valueIndex); | |||
|
190 | } | |||
|
191 | } | |||
|
192 | ||||
|
193 | return result; | |||
|
194 | } |
@@ -0,0 +1,107 | |||||
|
1 | #include <Data/OptionalAxis.h> | |||
|
2 | ||||
|
3 | #include "Data/ArrayData.h" | |||
|
4 | ||||
|
5 | OptionalAxis::OptionalAxis() | |||
|
6 | : m_Defined{false}, m_Data{std::make_shared<ArrayData<1> >(std::vector<double>{})}, m_Unit{} | |||
|
7 | { | |||
|
8 | } | |||
|
9 | ||||
|
10 | OptionalAxis::OptionalAxis(std::shared_ptr<ArrayData<1> > data, Unit unit) | |||
|
11 | : m_Defined{true}, m_Data{data}, m_Unit{std::move(unit)} | |||
|
12 | { | |||
|
13 | if (m_Data == nullptr) { | |||
|
14 | throw std::invalid_argument{"Data can't be null for a defined axis"}; | |||
|
15 | } | |||
|
16 | } | |||
|
17 | ||||
|
18 | OptionalAxis::OptionalAxis(const OptionalAxis &other) | |||
|
19 | : m_Defined{other.m_Defined}, m_Data{other.m_Data}, m_Unit{other.m_Unit} | |||
|
20 | { | |||
|
21 | } | |||
|
22 | ||||
|
23 | OptionalAxis &OptionalAxis::operator=(OptionalAxis other) | |||
|
24 | { | |||
|
25 | std::swap(m_Defined, other.m_Defined); | |||
|
26 | std::swap(m_Data, other.m_Data); | |||
|
27 | std::swap(m_Unit, other.m_Unit); | |||
|
28 | ||||
|
29 | return *this; | |||
|
30 | } | |||
|
31 | ||||
|
32 | bool OptionalAxis::isDefined() const | |||
|
33 | { | |||
|
34 | return m_Defined; | |||
|
35 | } | |||
|
36 | ||||
|
37 | std::pair<double, double> OptionalAxis::bounds() const | |||
|
38 | { | |||
|
39 | if (!m_Defined || m_Data->size() == 0) { | |||
|
40 | return std::make_pair(std::numeric_limits<double>::quiet_NaN(), | |||
|
41 | std::numeric_limits<double>::quiet_NaN()); | |||
|
42 | } | |||
|
43 | else { | |||
|
44 | ||||
|
45 | auto minIt = std::min_element( | |||
|
46 | m_Data->cbegin(), m_Data->cend(), [](const auto &it1, const auto &it2) { | |||
|
47 | return SortUtils::minCompareWithNaN(it1.first(), it2.first()); | |||
|
48 | }); | |||
|
49 | ||||
|
50 | // Gets the iterator on the max of all values data | |||
|
51 | auto maxIt = std::max_element( | |||
|
52 | m_Data->cbegin(), m_Data->cend(), [](const auto &it1, const auto &it2) { | |||
|
53 | return SortUtils::maxCompareWithNaN(it1.first(), it2.first()); | |||
|
54 | }); | |||
|
55 | ||||
|
56 | return std::make_pair(minIt->first(), maxIt->first()); | |||
|
57 | } | |||
|
58 | } | |||
|
59 | ||||
|
60 | int OptionalAxis::size() const | |||
|
61 | { | |||
|
62 | return m_Defined ? m_Data->size() : 0; | |||
|
63 | } | |||
|
64 | ||||
|
65 | Unit OptionalAxis::unit() const | |||
|
66 | { | |||
|
67 | return m_Defined ? m_Unit : Unit{}; | |||
|
68 | } | |||
|
69 | ||||
|
70 | bool OptionalAxis::operator==(const OptionalAxis &other) | |||
|
71 | { | |||
|
72 | // Axis not defined | |||
|
73 | if (!m_Defined) { | |||
|
74 | return !other.m_Defined; | |||
|
75 | } | |||
|
76 | ||||
|
77 | // Axis defined | |||
|
78 | return m_Unit == other.m_Unit | |||
|
79 | && std::equal( | |||
|
80 | m_Data->cbegin(), m_Data->cend(), other.m_Data->cbegin(), other.m_Data->cend(), | |||
|
81 | [](const auto &it1, const auto &it2) { return it1.values() == it2.values(); }); | |||
|
82 | } | |||
|
83 | ||||
|
84 | bool OptionalAxis::operator!=(const OptionalAxis &other) | |||
|
85 | { | |||
|
86 | return !(*this == other); | |||
|
87 | } | |||
|
88 | ||||
|
89 | ArrayDataIterator OptionalAxis::begin() | |||
|
90 | { | |||
|
91 | return m_Data->begin(); | |||
|
92 | } | |||
|
93 | ||||
|
94 | ArrayDataIterator OptionalAxis::end() | |||
|
95 | { | |||
|
96 | return m_Data->end(); | |||
|
97 | } | |||
|
98 | ||||
|
99 | ArrayDataIterator OptionalAxis::cbegin() const | |||
|
100 | { | |||
|
101 | return m_Data->cbegin(); | |||
|
102 | } | |||
|
103 | ||||
|
104 | ArrayDataIterator OptionalAxis::cend() const | |||
|
105 | { | |||
|
106 | return m_Data->cend(); | |||
|
107 | } |
@@ -0,0 +1,31 | |||||
|
1 | #include <Data/ScalarSeries.h> | |||
|
2 | ||||
|
3 | ScalarSeries::ScalarSeries(std::vector<double> xAxisData, std::vector<double> valuesData, | |||
|
4 | const Unit &xAxisUnit, const Unit &valuesUnit) | |||
|
5 | : DataSeries{std::make_shared<ArrayData<1> >(std::move(xAxisData)), xAxisUnit, | |||
|
6 | std::make_shared<ArrayData<1> >(std::move(valuesData)), valuesUnit} | |||
|
7 | { | |||
|
8 | } | |||
|
9 | ||||
|
10 | std::unique_ptr<IDataSeries> ScalarSeries::clone() const | |||
|
11 | { | |||
|
12 | return std::make_unique<ScalarSeries>(*this); | |||
|
13 | } | |||
|
14 | ||||
|
15 | std::shared_ptr<IDataSeries> ScalarSeries::subDataSeries(const DateTimeRange &range) | |||
|
16 | { | |||
|
17 | auto subXAxisData = std::vector<double>(); | |||
|
18 | auto subValuesData = std::vector<double>(); | |||
|
19 | this->lockRead(); | |||
|
20 | { | |||
|
21 | auto bounds = xAxisRange(range.m_TStart, range.m_TEnd); | |||
|
22 | for (auto it = bounds.first; it != bounds.second; ++it) { | |||
|
23 | subXAxisData.push_back(it->x()); | |||
|
24 | subValuesData.push_back(it->value()); | |||
|
25 | } | |||
|
26 | } | |||
|
27 | this->unlock(); | |||
|
28 | ||||
|
29 | return std::make_shared<ScalarSeries>(std::move(subXAxisData), std::move(subValuesData), | |||
|
30 | this->xAxisUnit(), this->valuesUnit()); | |||
|
31 | } |
@@ -0,0 +1,50 | |||||
|
1 | #include <Data/SpectrogramSeries.h> | |||
|
2 | ||||
|
3 | SpectrogramSeries::SpectrogramSeries(std::vector<double> xAxisData, std::vector<double> yAxisData, | |||
|
4 | std::vector<double> valuesData, const Unit &xAxisUnit, | |||
|
5 | const Unit &yAxisUnit, const Unit &valuesUnit, | |||
|
6 | double resolution) | |||
|
7 | : SpectrogramSeries{ | |||
|
8 | std::make_shared<ArrayData<1> >(std::move(xAxisData)), | |||
|
9 | xAxisUnit, | |||
|
10 | std::make_shared<ArrayData<2> >(std::move(valuesData), yAxisData.size()), | |||
|
11 | valuesUnit, | |||
|
12 | OptionalAxis{std::make_shared<ArrayData<1> >(std::move(yAxisData)), yAxisUnit}, | |||
|
13 | resolution} | |||
|
14 | { | |||
|
15 | } | |||
|
16 | ||||
|
17 | SpectrogramSeries::SpectrogramSeries(std::shared_ptr<ArrayData<1> > xAxisData, | |||
|
18 | const Unit &xAxisUnit, | |||
|
19 | std::shared_ptr<ArrayData<2> > valuesData, | |||
|
20 | const Unit &valuesUnit, OptionalAxis yAxis, double resolution) | |||
|
21 | : DataSeries{std::move(xAxisData), xAxisUnit, std::move(valuesData), valuesUnit, | |||
|
22 | std::move(yAxis)}, | |||
|
23 | m_XResolution{resolution} | |||
|
24 | { | |||
|
25 | } | |||
|
26 | ||||
|
27 | std::unique_ptr<IDataSeries> SpectrogramSeries::clone() const | |||
|
28 | { | |||
|
29 | return std::make_unique<SpectrogramSeries>(*this); | |||
|
30 | } | |||
|
31 | ||||
|
32 | std::shared_ptr<IDataSeries> SpectrogramSeries::subDataSeries(const DateTimeRange &range) | |||
|
33 | { | |||
|
34 | auto subXAxisData = std::vector<double>(); | |||
|
35 | auto subValuesData = QVector<double>(); // Uses QVector to append easily values to it | |||
|
36 | this->lockRead(); | |||
|
37 | auto bounds = xAxisRange(range.m_TStart, range.m_TEnd); | |||
|
38 | for (auto it = bounds.first; it != bounds.second; ++it) { | |||
|
39 | subXAxisData.push_back(it->x()); | |||
|
40 | subValuesData.append(it->values()); | |||
|
41 | } | |||
|
42 | ||||
|
43 | auto yAxis = this->yAxis(); | |||
|
44 | this->unlock(); | |||
|
45 | ||||
|
46 | return std::make_shared<SpectrogramSeries>( | |||
|
47 | std::make_shared<ArrayData<1> >(std::move(subXAxisData)), this->xAxisUnit(), | |||
|
48 | std::make_shared<ArrayData<2> >(subValuesData.toStdVector(), yAxis.size()), | |||
|
49 | this->valuesUnit(), std::move(yAxis)); | |||
|
50 | } |
@@ -0,0 +1,83 | |||||
|
1 | #include "Data/VectorSeries.h" | |||
|
2 | ||||
|
3 | namespace { | |||
|
4 | ||||
|
5 | /** | |||
|
6 | * Flatten the three components of a vector to a single QVector that can be passed to an ArrayData | |||
|
7 | * | |||
|
8 | * Example: | |||
|
9 | * xValues = {1, 2, 3} | |||
|
10 | * yValues = {4, 5, 6} | |||
|
11 | * zValues = {7, 8, 9} | |||
|
12 | * | |||
|
13 | * result = {1, 4, 7, 2, 5, 8, 3, 6, 9} | |||
|
14 | * | |||
|
15 | * @param xValues the x-component values of the vector | |||
|
16 | * @param yValues the y-component values of the vector | |||
|
17 | * @param zValues the z-component values of the vector | |||
|
18 | * @return the single QVector | |||
|
19 | * @remarks the three components are consumed | |||
|
20 | * @sa ArrayData | |||
|
21 | */ | |||
|
22 | std::vector<double> flatten(std::vector<double> xValues, std::vector<double> yValues, | |||
|
23 | std::vector<double> zValues) | |||
|
24 | { | |||
|
25 | if (xValues.size() != yValues.size() || xValues.size() != zValues.size()) { | |||
|
26 | /// @todo ALX : log | |||
|
27 | return {}; | |||
|
28 | } | |||
|
29 | ||||
|
30 | auto result = std::vector<double>(); | |||
|
31 | result.reserve(xValues.size() * 3); | |||
|
32 | for (auto i = 0u; i < xValues.size(); ++i) { | |||
|
33 | result.push_back(xValues[i]); | |||
|
34 | result.push_back(yValues[i]); | |||
|
35 | result.push_back(zValues[i]); | |||
|
36 | } | |||
|
37 | ||||
|
38 | return result; | |||
|
39 | } | |||
|
40 | ||||
|
41 | } // namespace | |||
|
42 | ||||
|
43 | VectorSeries::VectorSeries(std::vector<double> xAxisData, std::vector<double> xValuesData, | |||
|
44 | std::vector<double> yValuesData, std::vector<double> zValuesData, | |||
|
45 | const Unit &xAxisUnit, const Unit &valuesUnit) | |||
|
46 | : VectorSeries{std::move(xAxisData), flatten(std::move(xValuesData), std::move(yValuesData), | |||
|
47 | std::move(zValuesData)), | |||
|
48 | xAxisUnit, valuesUnit} | |||
|
49 | { | |||
|
50 | } | |||
|
51 | ||||
|
52 | VectorSeries::VectorSeries(std::vector<double> xAxisData, std::vector<double> valuesData, | |||
|
53 | const Unit &xAxisUnit, const Unit &valuesUnit) | |||
|
54 | : DataSeries{std::make_shared<ArrayData<1> >(std::move(xAxisData)), xAxisUnit, | |||
|
55 | std::make_shared<ArrayData<2> >(std::move(valuesData), 3), valuesUnit} | |||
|
56 | { | |||
|
57 | } | |||
|
58 | ||||
|
59 | std::unique_ptr<IDataSeries> VectorSeries::clone() const | |||
|
60 | { | |||
|
61 | return std::make_unique<VectorSeries>(*this); | |||
|
62 | } | |||
|
63 | ||||
|
64 | std::shared_ptr<IDataSeries> VectorSeries::subDataSeries(const DateTimeRange &range) | |||
|
65 | { | |||
|
66 | auto subXAxisData = std::vector<double>(); | |||
|
67 | auto subValuesData = std::vector<double>(); | |||
|
68 | ||||
|
69 | this->lockRead(); | |||
|
70 | { | |||
|
71 | auto bounds = xAxisRange(range.m_TStart, range.m_TEnd); | |||
|
72 | for (auto it = bounds.first; it != bounds.second; ++it) { | |||
|
73 | subXAxisData.push_back(it->x()); | |||
|
74 | subValuesData.push_back(it->value(0)); | |||
|
75 | subValuesData.push_back(it->value(1)); | |||
|
76 | subValuesData.push_back(it->value(2)); | |||
|
77 | } | |||
|
78 | } | |||
|
79 | this->unlock(); | |||
|
80 | ||||
|
81 | return std::make_shared<VectorSeries>(std::move(subXAxisData), std::move(subValuesData), | |||
|
82 | this->xAxisUnit(), this->valuesUnit()); | |||
|
83 | } |
@@ -0,0 +1,197 | |||||
|
1 | #include "DataSource/DataSourceController.h" | |||
|
2 | #include "DataSource/DataSourceItem.h" | |||
|
3 | ||||
|
4 | #include <Data/IDataProvider.h> | |||
|
5 | ||||
|
6 | #include <QMutex> | |||
|
7 | #include <QThread> | |||
|
8 | ||||
|
9 | #include <QDataStream> | |||
|
10 | #include <QDir> | |||
|
11 | #include <QStandardPaths> | |||
|
12 | ||||
|
13 | Q_LOGGING_CATEGORY(LOG_DataSourceController, "DataSourceController") | |||
|
14 | ||||
|
15 | class DataSourceController::DataSourceControllerPrivate { | |||
|
16 | public: | |||
|
17 | QMutex m_WorkingMutex; | |||
|
18 | /// Data sources registered | |||
|
19 | QHash<QUuid, QString> m_DataSources; | |||
|
20 | /// Data sources structures | |||
|
21 | std::map<QUuid, std::unique_ptr<DataSourceItem> > m_DataSourceItems; | |||
|
22 | /// Data providers registered | |||
|
23 | /// @remarks Data providers are stored as shared_ptr as they can be sent to a variable and | |||
|
24 | /// continue to live without necessarily the data source controller | |||
|
25 | std::map<QUuid, std::shared_ptr<IDataProvider> > m_DataProviders; | |||
|
26 | ||||
|
27 | // Search for the first datasource item matching the specified data | |||
|
28 | DataSourceItem *findDataSourceItem(const QVariantHash &data) | |||
|
29 | { | |||
|
30 | DataSourceItem *sourceItem = nullptr; | |||
|
31 | for (const auto &item : m_DataSourceItems) { | |||
|
32 | sourceItem = item.second->findItem(data, true); | |||
|
33 | if (sourceItem) { | |||
|
34 | break; | |||
|
35 | } | |||
|
36 | } | |||
|
37 | ||||
|
38 | return sourceItem; | |||
|
39 | } | |||
|
40 | ||||
|
41 | // Search for the first datasource item matching the specified ID_DATA_KEY | |||
|
42 | DataSourceItem *findDataSourceItem(const QString &datasourceIdKey) | |||
|
43 | { | |||
|
44 | DataSourceItem *sourceItem = nullptr; | |||
|
45 | for (const auto &item : m_DataSourceItems) { | |||
|
46 | sourceItem = item.second->findItem(datasourceIdKey, true); | |||
|
47 | if (sourceItem) { | |||
|
48 | break; | |||
|
49 | } | |||
|
50 | } | |||
|
51 | ||||
|
52 | return sourceItem; | |||
|
53 | } | |||
|
54 | }; | |||
|
55 | ||||
|
56 | DataSourceController::DataSourceController(QObject *parent) | |||
|
57 | : impl{spimpl::make_unique_impl<DataSourceControllerPrivate>()} | |||
|
58 | { | |||
|
59 | qCDebug(LOG_DataSourceController()) << tr("DataSourceController construction") | |||
|
60 | << QThread::currentThread(); | |||
|
61 | } | |||
|
62 | ||||
|
63 | DataSourceController::~DataSourceController() | |||
|
64 | { | |||
|
65 | qCDebug(LOG_DataSourceController()) << tr("DataSourceController destruction") | |||
|
66 | << QThread::currentThread(); | |||
|
67 | this->waitForFinish(); | |||
|
68 | } | |||
|
69 | ||||
|
70 | QUuid DataSourceController::registerDataSource(const QString &dataSourceName) noexcept | |||
|
71 | { | |||
|
72 | auto dataSourceUid = QUuid::createUuid(); | |||
|
73 | impl->m_DataSources.insert(dataSourceUid, dataSourceName); | |||
|
74 | ||||
|
75 | return dataSourceUid; | |||
|
76 | } | |||
|
77 | ||||
|
78 | void DataSourceController::setDataSourceItem( | |||
|
79 | const QUuid &dataSourceUid, std::unique_ptr<DataSourceItem> dataSourceItem) noexcept | |||
|
80 | { | |||
|
81 | if (!dataSourceItem) { | |||
|
82 | qCWarning(LOG_DataSourceController()) | |||
|
83 | << tr("Data source item can't be registered (null item)"); | |||
|
84 | return; | |||
|
85 | } | |||
|
86 | ||||
|
87 | if (impl->m_DataSources.contains(dataSourceUid)) { | |||
|
88 | // The data provider is implicitly converted to a shared_ptr | |||
|
89 | impl->m_DataSourceItems.insert(std::make_pair(dataSourceUid, std::move(dataSourceItem))); | |||
|
90 | ||||
|
91 | // Retrieves the data source item to emit the signal with it | |||
|
92 | auto it = impl->m_DataSourceItems.find(dataSourceUid); | |||
|
93 | if (it != impl->m_DataSourceItems.end()) { | |||
|
94 | emit dataSourceItemSet(it->second.get()); | |||
|
95 | } | |||
|
96 | } | |||
|
97 | else { | |||
|
98 | qCWarning(LOG_DataSourceController()) << tr("Can't set data source item for uid %1 : no " | |||
|
99 | "data source has been registered with the uid") | |||
|
100 | .arg(dataSourceUid.toString()); | |||
|
101 | } | |||
|
102 | } | |||
|
103 | ||||
|
104 | void DataSourceController::setDataProvider(const QUuid &dataSourceUid, | |||
|
105 | std::unique_ptr<IDataProvider> dataProvider) noexcept | |||
|
106 | { | |||
|
107 | if (impl->m_DataSources.contains(dataSourceUid)) { | |||
|
108 | impl->m_DataProviders.insert(std::make_pair(dataSourceUid, std::move(dataProvider))); | |||
|
109 | } | |||
|
110 | else { | |||
|
111 | qCWarning(LOG_DataSourceController()) << tr("Can't set data provider for uid %1 : no data " | |||
|
112 | "source has been registered with the uid") | |||
|
113 | .arg(dataSourceUid.toString()); | |||
|
114 | } | |||
|
115 | } | |||
|
116 | ||||
|
117 | void DataSourceController::loadProductItem(const QUuid &dataSourceUid, | |||
|
118 | const DataSourceItem &productItem) noexcept | |||
|
119 | { | |||
|
120 | if (productItem.type() == DataSourceItemType::PRODUCT | |||
|
121 | || productItem.type() == DataSourceItemType::COMPONENT) { | |||
|
122 | /// Retrieves the data provider of the data source (if any) | |||
|
123 | auto it = impl->m_DataProviders.find(dataSourceUid); | |||
|
124 | auto dataProvider = (it != impl->m_DataProviders.end()) ? it->second : nullptr; | |||
|
125 | ||||
|
126 | emit variableCreationRequested(productItem.name(), productItem.data(), dataProvider); | |||
|
127 | } | |||
|
128 | else { | |||
|
129 | qCWarning(LOG_DataSourceController()) << tr("Can't load an item that is not a product"); | |||
|
130 | } | |||
|
131 | } | |||
|
132 | ||||
|
133 | QByteArray DataSourceController::mimeDataForProductsData(const QVariantList &productsData) | |||
|
134 | { | |||
|
135 | QByteArray encodedData; | |||
|
136 | QDataStream stream{&encodedData, QIODevice::WriteOnly}; | |||
|
137 | ||||
|
138 | stream << productsData; | |||
|
139 | ||||
|
140 | return encodedData; | |||
|
141 | } | |||
|
142 | ||||
|
143 | QVariantList DataSourceController::productsDataForMimeData(const QByteArray &mimeData) | |||
|
144 | { | |||
|
145 | QDataStream stream{mimeData}; | |||
|
146 | ||||
|
147 | QVariantList productList; | |||
|
148 | stream >> productList; | |||
|
149 | ||||
|
150 | return productList; | |||
|
151 | } | |||
|
152 | ||||
|
153 | void DataSourceController::initialize() | |||
|
154 | { | |||
|
155 | qCDebug(LOG_DataSourceController()) << tr("DataSourceController init") | |||
|
156 | << QThread::currentThread(); | |||
|
157 | impl->m_WorkingMutex.lock(); | |||
|
158 | qCDebug(LOG_DataSourceController()) << tr("DataSourceController init END"); | |||
|
159 | } | |||
|
160 | ||||
|
161 | void DataSourceController::finalize() | |||
|
162 | { | |||
|
163 | impl->m_WorkingMutex.unlock(); | |||
|
164 | } | |||
|
165 | ||||
|
166 | void DataSourceController::requestVariableFromProductIdKey(const QString &datasourceIdKey) | |||
|
167 | { | |||
|
168 | auto sourceItem = impl->findDataSourceItem(datasourceIdKey); | |||
|
169 | ||||
|
170 | if (sourceItem) { | |||
|
171 | auto sourceName = sourceItem->rootItem().name(); | |||
|
172 | auto sourceId = impl->m_DataSources.key(sourceName); | |||
|
173 | loadProductItem(sourceId, *sourceItem); | |||
|
174 | } | |||
|
175 | else { | |||
|
176 | qCWarning(LOG_DataSourceController()) << tr("requestVariable, product data not found"); | |||
|
177 | } | |||
|
178 | } | |||
|
179 | ||||
|
180 | void DataSourceController::requestVariable(const QVariantHash &productData) | |||
|
181 | { | |||
|
182 | auto sourceItem = impl->findDataSourceItem(productData); | |||
|
183 | ||||
|
184 | if (sourceItem) { | |||
|
185 | auto sourceName = sourceItem->rootItem().name(); | |||
|
186 | auto sourceId = impl->m_DataSources.key(sourceName); | |||
|
187 | loadProductItem(sourceId, *sourceItem); | |||
|
188 | } | |||
|
189 | else { | |||
|
190 | qCWarning(LOG_DataSourceController()) << tr("requestVariable, product data not found"); | |||
|
191 | } | |||
|
192 | } | |||
|
193 | ||||
|
194 | void DataSourceController::waitForFinish() | |||
|
195 | { | |||
|
196 | QMutexLocker locker{&impl->m_WorkingMutex}; | |||
|
197 | } |
@@ -0,0 +1,205 | |||||
|
1 | #include <DataSource/DataSourceItem.h> | |||
|
2 | #include <DataSource/DataSourceItemAction.h> | |||
|
3 | #include <DataSource/DataSourceItemMergeHelper.h> | |||
|
4 | ||||
|
5 | #include <QVector> | |||
|
6 | ||||
|
7 | const QString DataSourceItem::NAME_DATA_KEY = QStringLiteral("name"); | |||
|
8 | const QString DataSourceItem::PLUGIN_DATA_KEY = QStringLiteral("plugin"); | |||
|
9 | const QString DataSourceItem::ID_DATA_KEY = QStringLiteral("uuid"); | |||
|
10 | ||||
|
11 | struct DataSourceItem::DataSourceItemPrivate { | |||
|
12 | explicit DataSourceItemPrivate(DataSourceItemType type, QVariantHash data) | |||
|
13 | : m_Parent{nullptr}, m_Children{}, m_Type{type}, m_Data{std::move(data)}, m_Actions{} | |||
|
14 | { | |||
|
15 | } | |||
|
16 | ||||
|
17 | DataSourceItem *m_Parent; | |||
|
18 | std::vector<std::unique_ptr<DataSourceItem> > m_Children; | |||
|
19 | DataSourceItemType m_Type; | |||
|
20 | QVariantHash m_Data; | |||
|
21 | std::vector<std::unique_ptr<DataSourceItemAction> > m_Actions; | |||
|
22 | }; | |||
|
23 | ||||
|
24 | DataSourceItem::DataSourceItem(DataSourceItemType type, const QString &name) | |||
|
25 | : DataSourceItem{type, QVariantHash{{NAME_DATA_KEY, name}}} | |||
|
26 | { | |||
|
27 | } | |||
|
28 | ||||
|
29 | DataSourceItem::DataSourceItem(DataSourceItemType type, QVariantHash data) | |||
|
30 | : impl{spimpl::make_unique_impl<DataSourceItemPrivate>(type, std::move(data))} | |||
|
31 | { | |||
|
32 | } | |||
|
33 | ||||
|
34 | std::unique_ptr<DataSourceItem> DataSourceItem::clone() const | |||
|
35 | { | |||
|
36 | auto result = std::make_unique<DataSourceItem>(impl->m_Type, impl->m_Data); | |||
|
37 | ||||
|
38 | // Clones children | |||
|
39 | for (const auto &child : impl->m_Children) { | |||
|
40 | result->appendChild(std::move(child->clone())); | |||
|
41 | } | |||
|
42 | ||||
|
43 | // Clones actions | |||
|
44 | for (const auto &action : impl->m_Actions) { | |||
|
45 | result->addAction(std::move(action->clone())); | |||
|
46 | } | |||
|
47 | ||||
|
48 | return result; | |||
|
49 | } | |||
|
50 | ||||
|
51 | QVector<DataSourceItemAction *> DataSourceItem::actions() const noexcept | |||
|
52 | { | |||
|
53 | auto result = QVector<DataSourceItemAction *>{}; | |||
|
54 | ||||
|
55 | std::transform(std::cbegin(impl->m_Actions), std::cend(impl->m_Actions), | |||
|
56 | std::back_inserter(result), [](const auto &action) { return action.get(); }); | |||
|
57 | ||||
|
58 | return result; | |||
|
59 | } | |||
|
60 | ||||
|
61 | void DataSourceItem::addAction(std::unique_ptr<DataSourceItemAction> action) noexcept | |||
|
62 | { | |||
|
63 | action->setDataSourceItem(this); | |||
|
64 | impl->m_Actions.push_back(std::move(action)); | |||
|
65 | } | |||
|
66 | ||||
|
67 | void DataSourceItem::appendChild(std::unique_ptr<DataSourceItem> child) noexcept | |||
|
68 | { | |||
|
69 | child->impl->m_Parent = this; | |||
|
70 | impl->m_Children.push_back(std::move(child)); | |||
|
71 | } | |||
|
72 | ||||
|
73 | DataSourceItem *DataSourceItem::child(int childIndex) const noexcept | |||
|
74 | { | |||
|
75 | if (childIndex < 0 || childIndex >= childCount()) { | |||
|
76 | return nullptr; | |||
|
77 | } | |||
|
78 | else { | |||
|
79 | return impl->m_Children.at(childIndex).get(); | |||
|
80 | } | |||
|
81 | } | |||
|
82 | ||||
|
83 | int DataSourceItem::childCount() const noexcept | |||
|
84 | { | |||
|
85 | return impl->m_Children.size(); | |||
|
86 | } | |||
|
87 | ||||
|
88 | QVariant DataSourceItem::data(const QString &key) const noexcept | |||
|
89 | { | |||
|
90 | return impl->m_Data.value(key); | |||
|
91 | } | |||
|
92 | ||||
|
93 | QVariantHash DataSourceItem::data() const noexcept | |||
|
94 | { | |||
|
95 | return impl->m_Data; | |||
|
96 | } | |||
|
97 | ||||
|
98 | void DataSourceItem::merge(const DataSourceItem &item) | |||
|
99 | { | |||
|
100 | DataSourceItemMergeHelper::merge(item, *this); | |||
|
101 | } | |||
|
102 | ||||
|
103 | bool DataSourceItem::isRoot() const noexcept | |||
|
104 | { | |||
|
105 | return impl->m_Parent == nullptr; | |||
|
106 | } | |||
|
107 | ||||
|
108 | QString DataSourceItem::name() const noexcept | |||
|
109 | { | |||
|
110 | return data(NAME_DATA_KEY).toString(); | |||
|
111 | } | |||
|
112 | ||||
|
113 | DataSourceItem *DataSourceItem::parentItem() const noexcept | |||
|
114 | { | |||
|
115 | return impl->m_Parent; | |||
|
116 | } | |||
|
117 | ||||
|
118 | const DataSourceItem &DataSourceItem::rootItem() const noexcept | |||
|
119 | { | |||
|
120 | return isRoot() ? *this : parentItem()->rootItem(); | |||
|
121 | } | |||
|
122 | ||||
|
123 | void DataSourceItem::setData(const QString &key, const QVariant &value, bool append) noexcept | |||
|
124 | { | |||
|
125 | auto it = impl->m_Data.constFind(key); | |||
|
126 | if (append && it != impl->m_Data.constEnd()) { | |||
|
127 | // Case of an existing value to which we want to add to the new value | |||
|
128 | if (it->canConvert<QVariantList>()) { | |||
|
129 | auto variantList = it->value<QVariantList>(); | |||
|
130 | variantList.append(value); | |||
|
131 | ||||
|
132 | impl->m_Data.insert(key, variantList); | |||
|
133 | } | |||
|
134 | else { | |||
|
135 | impl->m_Data.insert(key, QVariantList{*it, value}); | |||
|
136 | } | |||
|
137 | } | |||
|
138 | else { | |||
|
139 | // Other cases : | |||
|
140 | // - new value in map OR | |||
|
141 | // - replacement of an existing value (not appending) | |||
|
142 | impl->m_Data.insert(key, value); | |||
|
143 | } | |||
|
144 | } | |||
|
145 | ||||
|
146 | DataSourceItemType DataSourceItem::type() const noexcept | |||
|
147 | { | |||
|
148 | return impl->m_Type; | |||
|
149 | } | |||
|
150 | ||||
|
151 | DataSourceItem *DataSourceItem::findItem(const QVariantHash &data, bool recursive) | |||
|
152 | { | |||
|
153 | for (const auto &child : impl->m_Children) { | |||
|
154 | if (child->impl->m_Data == data) { | |||
|
155 | return child.get(); | |||
|
156 | } | |||
|
157 | ||||
|
158 | if (recursive) { | |||
|
159 | if (auto foundItem = child->findItem(data, true)) { | |||
|
160 | return foundItem; | |||
|
161 | } | |||
|
162 | } | |||
|
163 | } | |||
|
164 | ||||
|
165 | return nullptr; | |||
|
166 | } | |||
|
167 | ||||
|
168 | DataSourceItem *DataSourceItem::findItem(const QString &datasourceIdKey, bool recursive) | |||
|
169 | { | |||
|
170 | for (const auto &child : impl->m_Children) { | |||
|
171 | auto childId = child->impl->m_Data.value(ID_DATA_KEY); | |||
|
172 | if (childId == datasourceIdKey) { | |||
|
173 | return child.get(); | |||
|
174 | } | |||
|
175 | ||||
|
176 | if (recursive) { | |||
|
177 | if (auto foundItem = child->findItem(datasourceIdKey, true)) { | |||
|
178 | return foundItem; | |||
|
179 | } | |||
|
180 | } | |||
|
181 | } | |||
|
182 | ||||
|
183 | return nullptr; | |||
|
184 | } | |||
|
185 | ||||
|
186 | bool DataSourceItem::operator==(const DataSourceItem &other) | |||
|
187 | { | |||
|
188 | // Compares items' attributes | |||
|
189 | if (std::tie(impl->m_Type, impl->m_Data) == std::tie(other.impl->m_Type, other.impl->m_Data)) { | |||
|
190 | // Compares contents of items' children | |||
|
191 | return std::equal(std::cbegin(impl->m_Children), std::cend(impl->m_Children), | |||
|
192 | std::cbegin(other.impl->m_Children), std::cend(other.impl->m_Children), | |||
|
193 | [](const auto &itemChild, const auto &otherChild) { | |||
|
194 | return *itemChild == *otherChild; | |||
|
195 | }); | |||
|
196 | } | |||
|
197 | else { | |||
|
198 | return false; | |||
|
199 | } | |||
|
200 | } | |||
|
201 | ||||
|
202 | bool DataSourceItem::operator!=(const DataSourceItem &other) | |||
|
203 | { | |||
|
204 | return !(*this == other); | |||
|
205 | } |
@@ -0,0 +1,49 | |||||
|
1 | #include <DataSource/DataSourceItemAction.h> | |||
|
2 | ||||
|
3 | #include <functional> | |||
|
4 | ||||
|
5 | Q_LOGGING_CATEGORY(LOG_DataSourceItemAction, "DataSourceItemAction") | |||
|
6 | ||||
|
7 | struct DataSourceItemAction::DataSourceItemActionPrivate { | |||
|
8 | explicit DataSourceItemActionPrivate(const QString &name, | |||
|
9 | DataSourceItemAction::ExecuteFunction fun) | |||
|
10 | : m_Name{name}, m_Fun{std::move(fun)}, m_DataSourceItem{nullptr} | |||
|
11 | { | |||
|
12 | } | |||
|
13 | ||||
|
14 | QString m_Name; | |||
|
15 | DataSourceItemAction::ExecuteFunction m_Fun; | |||
|
16 | /// Item associated to the action (can be null, in which case the action will not be executed) | |||
|
17 | DataSourceItem *m_DataSourceItem; | |||
|
18 | }; | |||
|
19 | ||||
|
20 | DataSourceItemAction::DataSourceItemAction(const QString &name, ExecuteFunction fun) | |||
|
21 | : impl{spimpl::make_unique_impl<DataSourceItemActionPrivate>(name, std::move(fun))} | |||
|
22 | { | |||
|
23 | } | |||
|
24 | ||||
|
25 | std::unique_ptr<DataSourceItemAction> DataSourceItemAction::clone() const | |||
|
26 | { | |||
|
27 | return std::make_unique<DataSourceItemAction>(impl->m_Name, impl->m_Fun); | |||
|
28 | } | |||
|
29 | ||||
|
30 | QString DataSourceItemAction::name() const noexcept | |||
|
31 | { | |||
|
32 | return impl->m_Name; | |||
|
33 | } | |||
|
34 | ||||
|
35 | void DataSourceItemAction::setDataSourceItem(DataSourceItem *dataSourceItem) noexcept | |||
|
36 | { | |||
|
37 | impl->m_DataSourceItem = dataSourceItem; | |||
|
38 | } | |||
|
39 | ||||
|
40 | void DataSourceItemAction::execute() | |||
|
41 | { | |||
|
42 | if (impl->m_DataSourceItem) { | |||
|
43 | impl->m_Fun(*impl->m_DataSourceItem); | |||
|
44 | } | |||
|
45 | else { | |||
|
46 | qCDebug(LOG_DataSourceItemAction()) | |||
|
47 | << tr("Can't execute action : no item has been associated"); | |||
|
48 | } | |||
|
49 | } |
@@ -0,0 +1,55 | |||||
|
1 | #include "DataSource/DataSourceItemMergeHelper.h" | |||
|
2 | ||||
|
3 | #include <DataSource/DataSourceItem.h> | |||
|
4 | ||||
|
5 | namespace { | |||
|
6 | ||||
|
7 | /** | |||
|
8 | * Finds in a tree an item similar to the item passed in parameter | |||
|
9 | * @param item the item for which to find a similar item | |||
|
10 | * @param root the root item of the tree | |||
|
11 | * @return the similar item if found, nullptr otherwise | |||
|
12 | */ | |||
|
13 | DataSourceItem *findSimilarItem(const DataSourceItem &item, const DataSourceItem &root) | |||
|
14 | { | |||
|
15 | // An item is considered similar to the another item if: | |||
|
16 | // - the items are both nodes AND | |||
|
17 | // - the names of the items are identical | |||
|
18 | ||||
|
19 | if (item.type() != DataSourceItemType::NODE) { | |||
|
20 | return nullptr; | |||
|
21 | } | |||
|
22 | ||||
|
23 | DataSourceItem *result{nullptr}; | |||
|
24 | bool found{false}; | |||
|
25 | for (auto i = 0, count = root.childCount(); i < count && !found; ++i) { | |||
|
26 | auto child = root.child(i); | |||
|
27 | ||||
|
28 | found = child->type() == DataSourceItemType::NODE | |||
|
29 | && QString::compare(child->name(), item.name(), Qt::CaseInsensitive) == 0; | |||
|
30 | if (found) { | |||
|
31 | result = child; | |||
|
32 | } | |||
|
33 | } | |||
|
34 | ||||
|
35 | return result; | |||
|
36 | } | |||
|
37 | ||||
|
38 | } // namespace | |||
|
39 | ||||
|
40 | void DataSourceItemMergeHelper::merge(const DataSourceItem &source, DataSourceItem &dest) | |||
|
41 | { | |||
|
42 | // Checks if the source item can be merged into the destination item (i.e. there is a child item | |||
|
43 | // similar to the source item) | |||
|
44 | if (auto subItem = findSimilarItem(source, dest)) { | |||
|
45 | // If there is an item similar to the source item, applies the merge recursively | |||
|
46 | for (auto i = 0, count = source.childCount(); i < count; ++i) { | |||
|
47 | merge(*source.child(i), *subItem); | |||
|
48 | } | |||
|
49 | } | |||
|
50 | else { | |||
|
51 | // If no item is similar to the source item, the item is copied as the child of the | |||
|
52 | // destination item | |||
|
53 | dest.appendChild(source.clone()); | |||
|
54 | } | |||
|
55 | } |
@@ -0,0 +1,123 | |||||
|
1 | #include <Network/Downloader.h> | |||
|
2 | #include <memory> | |||
|
3 | ||||
|
4 | #include <QNetworkRequest> | |||
|
5 | #include <QNetworkReply> | |||
|
6 | #include <QNetworkAccessManager> | |||
|
7 | #include <QAuthenticator> | |||
|
8 | #include <QVariant> | |||
|
9 | #include <QHash> | |||
|
10 | #include <QPair> | |||
|
11 | #include <QCoreApplication> | |||
|
12 | #include <QReadWriteLock> | |||
|
13 | ||||
|
14 | class Downloader::p_Downloader | |||
|
15 | { | |||
|
16 | using login_pair=QPair<QString,QString>; | |||
|
17 | QNetworkAccessManager manager; | |||
|
18 | QHash<QString,login_pair> auth; | |||
|
19 | QReadWriteLock pending_requests_lock; | |||
|
20 | QHash<QUuid,QNetworkReply*> pending_requests; | |||
|
21 | ||||
|
22 | QNetworkRequest buildRequest(const QString& url, const QString &user="", const QString &passwd="") | |||
|
23 | { | |||
|
24 | QNetworkRequest request; | |||
|
25 | request.setUrl(QUrl(url)); | |||
|
26 | request.setRawHeader("User-Agent", "SciQLop 1.0"); | |||
|
27 | if(user!="" and passwd!="") | |||
|
28 | { | |||
|
29 | //might grow quickly since we can have tons of URLs for the same host | |||
|
30 | auth[url]=login_pair(user,passwd); | |||
|
31 | QString login = "Basic "+user+":"+passwd; | |||
|
32 | request.setRawHeader("Authorization",login.toLocal8Bit()); | |||
|
33 | } | |||
|
34 | return request; | |||
|
35 | } | |||
|
36 | ||||
|
37 | public: | |||
|
38 | explicit p_Downloader() | |||
|
39 | { | |||
|
40 | ||||
|
41 | auto login_bambda = [this](QNetworkReply * reply, QAuthenticator * authenticator) | |||
|
42 | { | |||
|
43 | if(auth.contains(reply->url().toString())) | |||
|
44 | { | |||
|
45 | auto login = auth[reply->url().toString()]; | |||
|
46 | authenticator->setUser(login.first); | |||
|
47 | authenticator->setPassword(login.second); | |||
|
48 | } | |||
|
49 | }; | |||
|
50 | ||||
|
51 | QObject::connect(&manager, &QNetworkAccessManager::authenticationRequired, login_bambda); | |||
|
52 | } | |||
|
53 | ||||
|
54 | Response get(const QString& url, const QString &user="", const QString &passwd="") | |||
|
55 | { | |||
|
56 | QNetworkRequest request = buildRequest(url, user, passwd); | |||
|
57 | QNetworkReply *reply = manager.get(request); | |||
|
58 | while (!reply->isFinished()) | |||
|
59 | QCoreApplication::processEvents(); | |||
|
60 | QVariant status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); | |||
|
61 | Response resp = Response(reply->readAll(), status_code.toInt()); | |||
|
62 | delete reply; | |||
|
63 | if(user!="" and passwd!="") | |||
|
64 | auth.remove(url); | |||
|
65 | return resp; | |||
|
66 | } | |||
|
67 | ||||
|
68 | QUuid getAsync(const QString &url, std::function<void (QUuid ,Response)> callback, const QString &user, const QString &passwd) | |||
|
69 | { | |||
|
70 | auto uuid = QUuid::createUuid(); | |||
|
71 | QNetworkRequest request = buildRequest(url, user, passwd); | |||
|
72 | QNetworkReply *reply = manager.get(request); | |||
|
73 | auto callback_wrapper = [url, uuid, callback, this](){ | |||
|
74 | QNetworkReply* reply; | |||
|
75 | { | |||
|
76 | QWriteLocker locker(&pending_requests_lock); | |||
|
77 | reply = pending_requests.take(uuid); | |||
|
78 | } | |||
|
79 | QVariant status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); | |||
|
80 | Response resp = Response(reply->readAll(), status_code.toInt()); | |||
|
81 | auth.remove(url); | |||
|
82 | delete reply; | |||
|
83 | callback(uuid, resp); | |||
|
84 | }; | |||
|
85 | QObject::connect(reply, &QNetworkReply::finished, callback_wrapper); | |||
|
86 | { | |||
|
87 | QWriteLocker locker(&pending_requests_lock); | |||
|
88 | pending_requests[uuid] = reply; | |||
|
89 | } | |||
|
90 | return uuid; | |||
|
91 | } | |||
|
92 | bool downloadFinished(QUuid uuid) | |||
|
93 | { | |||
|
94 | QReadLocker locker(&pending_requests_lock); | |||
|
95 | if(pending_requests.contains(uuid)) | |||
|
96 | { | |||
|
97 | auto req = pending_requests[uuid]; | |||
|
98 | return req->isFinished(); | |||
|
99 | } | |||
|
100 | return true; | |||
|
101 | } | |||
|
102 | }; | |||
|
103 | ||||
|
104 | Response Downloader::get(const QString &url, const QString &user, const QString &passwd) | |||
|
105 | { | |||
|
106 | return Downloader::instance().impl->get(url, user, passwd); | |||
|
107 | } | |||
|
108 | ||||
|
109 | QUuid Downloader::getAsync(const QString &url, std::function<void (QUuid ,Response)> callback, const QString &user, const QString &passwd) | |||
|
110 | { | |||
|
111 | return Downloader::instance().impl->getAsync(url, callback, user, passwd); | |||
|
112 | } | |||
|
113 | ||||
|
114 | bool Downloader::downloadFinished(QUuid uuid) | |||
|
115 | { | |||
|
116 | return Downloader::instance().impl->downloadFinished(uuid); | |||
|
117 | } | |||
|
118 | ||||
|
119 | Downloader::Downloader() | |||
|
120 | :impl(spimpl::make_unique_impl<p_Downloader>()) | |||
|
121 | { | |||
|
122 | } | |||
|
123 |
@@ -0,0 +1,148 | |||||
|
1 | #include "Network/NetworkController.h" | |||
|
2 | ||||
|
3 | #include <QMutex> | |||
|
4 | #include <QNetworkAccessManager> | |||
|
5 | #include <QNetworkReply> | |||
|
6 | #include <QNetworkRequest> | |||
|
7 | #include <QReadWriteLock> | |||
|
8 | #include <QThread> | |||
|
9 | ||||
|
10 | #include <unordered_map> | |||
|
11 | ||||
|
12 | Q_LOGGING_CATEGORY(LOG_NetworkController, "NetworkController") | |||
|
13 | ||||
|
14 | struct NetworkController::NetworkControllerPrivate { | |||
|
15 | explicit NetworkControllerPrivate(NetworkController *parent) : m_WorkingMutex{} {} | |||
|
16 | ||||
|
17 | void lockRead() { m_Lock.lockForRead(); } | |||
|
18 | void lockWrite() { m_Lock.lockForWrite(); } | |||
|
19 | void unlock() { m_Lock.unlock(); } | |||
|
20 | ||||
|
21 | QMutex m_WorkingMutex; | |||
|
22 | ||||
|
23 | QReadWriteLock m_Lock; | |||
|
24 | std::unordered_map<QNetworkReply *, QUuid> m_NetworkReplyToId; | |||
|
25 | std::unique_ptr<QNetworkAccessManager> m_AccessManager{nullptr}; | |||
|
26 | }; | |||
|
27 | ||||
|
28 | NetworkController::NetworkController(QObject *parent) | |||
|
29 | : QObject(parent), impl{spimpl::make_unique_impl<NetworkControllerPrivate>(this)} | |||
|
30 | { | |||
|
31 | } | |||
|
32 | ||||
|
33 | void NetworkController::onProcessRequested(std::shared_ptr<QNetworkRequest> request, | |||
|
34 | QUuid identifier, | |||
|
35 | std::function<void(QNetworkReply *, QUuid)> callback) | |||
|
36 | { | |||
|
37 | qCDebug(LOG_NetworkController()) << tr("NetworkController onProcessRequested") | |||
|
38 | << QThread::currentThread()->objectName() << &request; | |||
|
39 | auto reply = impl->m_AccessManager->get(*request); | |||
|
40 | ||||
|
41 | // Store the couple reply id | |||
|
42 | impl->lockWrite(); | |||
|
43 | impl->m_NetworkReplyToId[reply] = identifier; | |||
|
44 | qCDebug(LOG_NetworkController()) << tr("Store for reply: ") << identifier; | |||
|
45 | impl->unlock(); | |||
|
46 | ||||
|
47 | auto onReplyFinished = [request, reply, this, identifier, callback]() { | |||
|
48 | ||||
|
49 | qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyFinished") | |||
|
50 | << QThread::currentThread() << request.get() << reply; | |||
|
51 | impl->lockRead(); | |||
|
52 | auto it = impl->m_NetworkReplyToId.find(reply); | |||
|
53 | if (it != impl->m_NetworkReplyToId.cend()) { | |||
|
54 | qCDebug(LOG_NetworkController()) << tr("Remove for reply: ") << it->second; | |||
|
55 | impl->unlock(); | |||
|
56 | impl->lockWrite(); | |||
|
57 | impl->m_NetworkReplyToId.erase(reply); | |||
|
58 | impl->unlock(); | |||
|
59 | // Deletes reply | |||
|
60 | callback(reply, identifier); | |||
|
61 | reply->deleteLater(); | |||
|
62 | } | |||
|
63 | else { | |||
|
64 | impl->unlock(); | |||
|
65 | } | |||
|
66 | ||||
|
67 | qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyFinished END") | |||
|
68 | << QThread::currentThread() << reply; | |||
|
69 | }; | |||
|
70 | ||||
|
71 | auto onReplyProgress = [reply, request, this](qint64 bytesRead, qint64 totalBytes) { | |||
|
72 | ||||
|
73 | // NOTE: a totalbytes of 0 can happened when a request has been aborted | |||
|
74 | if (totalBytes > 0) { | |||
|
75 | double progress = (bytesRead * 100.0) / totalBytes; | |||
|
76 | qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyProgress") << progress | |||
|
77 | << QThread::currentThread() << request.get() << reply | |||
|
78 | << bytesRead << totalBytes; | |||
|
79 | impl->lockRead(); | |||
|
80 | auto it = impl->m_NetworkReplyToId.find(reply); | |||
|
81 | if (it != impl->m_NetworkReplyToId.cend()) { | |||
|
82 | auto id = it->second; | |||
|
83 | impl->unlock(); | |||
|
84 | emit this->replyDownloadProgress(id, request, progress); | |||
|
85 | } | |||
|
86 | else { | |||
|
87 | impl->unlock(); | |||
|
88 | } | |||
|
89 | ||||
|
90 | qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyProgress END") | |||
|
91 | << QThread::currentThread() << reply; | |||
|
92 | } | |||
|
93 | }; | |||
|
94 | ||||
|
95 | ||||
|
96 | connect(reply, &QNetworkReply::finished, this, onReplyFinished); | |||
|
97 | connect(reply, &QNetworkReply::downloadProgress, this, onReplyProgress); | |||
|
98 | qCDebug(LOG_NetworkController()) << tr("NetworkController registered END") | |||
|
99 | << QThread::currentThread()->objectName() << reply; | |||
|
100 | } | |||
|
101 | ||||
|
102 | void NetworkController::initialize() | |||
|
103 | { | |||
|
104 | qCDebug(LOG_NetworkController()) << tr("NetworkController init") << QThread::currentThread(); | |||
|
105 | impl->m_WorkingMutex.lock(); | |||
|
106 | impl->m_AccessManager = std::make_unique<QNetworkAccessManager>(); | |||
|
107 | ||||
|
108 | ||||
|
109 | auto onReplyErrors = [this](QNetworkReply *reply, const QList<QSslError> &errors) { | |||
|
110 | qCCritical(LOG_NetworkController()) << tr("NetworkAcessManager errors: ") << errors; | |||
|
111 | ||||
|
112 | }; | |||
|
113 | ||||
|
114 | ||||
|
115 | connect(impl->m_AccessManager.get(), &QNetworkAccessManager::sslErrors, this, onReplyErrors); | |||
|
116 | ||||
|
117 | qCDebug(LOG_NetworkController()) << tr("NetworkController init END"); | |||
|
118 | } | |||
|
119 | ||||
|
120 | void NetworkController::finalize() | |||
|
121 | { | |||
|
122 | impl->m_WorkingMutex.unlock(); | |||
|
123 | } | |||
|
124 | ||||
|
125 | void NetworkController::onReplyCanceled(QUuid identifier) | |||
|
126 | { | |||
|
127 | auto findReply = [identifier](const auto &entry) { return identifier == entry.second; }; | |||
|
128 | qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyCanceled") | |||
|
129 | << QThread::currentThread() << identifier; | |||
|
130 | ||||
|
131 | ||||
|
132 | impl->lockRead(); | |||
|
133 | auto end = impl->m_NetworkReplyToId.cend(); | |||
|
134 | auto it = std::find_if(impl->m_NetworkReplyToId.cbegin(), end, findReply); | |||
|
135 | impl->unlock(); | |||
|
136 | if (it != end) { | |||
|
137 | qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyCanceled ABORT DONE") | |||
|
138 | << QThread::currentThread() << identifier; | |||
|
139 | it->first->abort(); | |||
|
140 | } | |||
|
141 | qCDebug(LOG_NetworkController()) << tr("NetworkController onReplyCanceled END") | |||
|
142 | << QThread::currentThread(); | |||
|
143 | } | |||
|
144 | ||||
|
145 | void NetworkController::waitForFinish() | |||
|
146 | { | |||
|
147 | QMutexLocker locker{&impl->m_WorkingMutex}; | |||
|
148 | } |
@@ -0,0 +1,137 | |||||
|
1 | #include <PluginManager/PluginManager.h> | |||
|
2 | ||||
|
3 | #include <Plugin/IPlugin.h> | |||
|
4 | ||||
|
5 | #include <QDir> | |||
|
6 | #include <QLibrary> | |||
|
7 | #include <QPluginLoader> | |||
|
8 | ||||
|
9 | Q_LOGGING_CATEGORY(LOG_PluginManager, "PluginManager") | |||
|
10 | ||||
|
11 | namespace { | |||
|
12 | ||||
|
13 | /// Key for retrieving metadata of the plugin | |||
|
14 | const auto PLUGIN_METADATA_KEY = QStringLiteral("MetaData"); | |||
|
15 | ||||
|
16 | /// Key for retrieving the name of the plugin in its metadata | |||
|
17 | const auto PLUGIN_NAME_KEY = QStringLiteral("name"); | |||
|
18 | ||||
|
19 | /// Helper to state the plugin loading operation | |||
|
20 | struct LoadPluginState { | |||
|
21 | explicit LoadPluginState(const QString &pluginPath) | |||
|
22 | : m_PluginPath{pluginPath}, m_Valid{true}, m_ErrorMessage{} | |||
|
23 | { | |||
|
24 | } | |||
|
25 | ||||
|
26 | void log() const | |||
|
27 | { | |||
|
28 | if (m_Valid) { | |||
|
29 | qCDebug(LOG_PluginManager()) | |||
|
30 | << QObject::tr("File '%1' has been loaded as a plugin").arg(m_PluginPath); | |||
|
31 | } | |||
|
32 | else { | |||
|
33 | qCWarning(LOG_PluginManager()) | |||
|
34 | << QObject::tr("File '%1' can't be loaded as a plugin: %2") | |||
|
35 | .arg(m_PluginPath) | |||
|
36 | .arg(m_ErrorMessage); | |||
|
37 | } | |||
|
38 | } | |||
|
39 | ||||
|
40 | void setError(const QString &errorMessage) | |||
|
41 | { | |||
|
42 | m_Valid = false; | |||
|
43 | m_ErrorMessage = errorMessage; | |||
|
44 | } | |||
|
45 | ||||
|
46 | QString m_PluginPath; | |||
|
47 | bool m_Valid; | |||
|
48 | QString m_ErrorMessage; | |||
|
49 | }; | |||
|
50 | ||||
|
51 | } // namespace | |||
|
52 | ||||
|
53 | struct PluginManager::PluginManagerPrivate { | |||
|
54 | /** | |||
|
55 | * Loads a single plugin into SciQlop. The method has no effect if the plugin is malformed (e.g. | |||
|
56 | * wrong library type, missing metadata, etc.) | |||
|
57 | * @param pluginPath the path to the plugin library. | |||
|
58 | */ | |||
|
59 | void loadPlugin(const QString &pluginPath) | |||
|
60 | { | |||
|
61 | qCDebug(LOG_PluginManager()) | |||
|
62 | << QObject::tr("Attempting to load file '%1' as a plugin").arg(pluginPath); | |||
|
63 | ||||
|
64 | LoadPluginState loadState{pluginPath}; | |||
|
65 | ||||
|
66 | if (QLibrary::isLibrary(pluginPath)) { | |||
|
67 | QPluginLoader pluginLoader{pluginPath}; | |||
|
68 | ||||
|
69 | // Retrieving the plugin name to check if it can be loaded (i.e. no plugin with the same | |||
|
70 | // name has been registered yet) | |||
|
71 | auto metadata = pluginLoader.metaData().value(PLUGIN_METADATA_KEY).toObject(); | |||
|
72 | auto pluginName = metadata.value(PLUGIN_NAME_KEY).toString(); | |||
|
73 | ||||
|
74 | if (pluginName.isEmpty()) { | |||
|
75 | loadState.setError(QObject::tr("empty file name")); | |||
|
76 | } | |||
|
77 | else if (m_RegisteredPlugins.contains(pluginName)) { | |||
|
78 | loadState.setError(QObject::tr("name '%1' already registered").arg(pluginName)); | |||
|
79 | } | |||
|
80 | else { | |||
|
81 | if (auto pluginInstance = qobject_cast<IPlugin *>(pluginLoader.instance())) { | |||
|
82 | pluginInstance->initialize(); | |||
|
83 | m_RegisteredPlugins.insert(pluginName, pluginPath); | |||
|
84 | } | |||
|
85 | else { | |||
|
86 | loadState.setError(QObject::tr("the file is not a Sciqlop plugin")); | |||
|
87 | } | |||
|
88 | } | |||
|
89 | } | |||
|
90 | else { | |||
|
91 | loadState.setError(QObject::tr("the file is not a library")); | |||
|
92 | } | |||
|
93 | ||||
|
94 | // Log loading result | |||
|
95 | loadState.log(); | |||
|
96 | } | |||
|
97 | ||||
|
98 | void loadStaticPlugins() | |||
|
99 | { | |||
|
100 | for (QObject *plugin : QPluginLoader::staticInstances()) { | |||
|
101 | qobject_cast<IPlugin *>(plugin)->initialize(); | |||
|
102 | m_RegisteredPlugins.insert(plugin->metaObject()->className(), "StaticPlugin"); | |||
|
103 | } | |||
|
104 | } | |||
|
105 | ||||
|
106 | /// Registered plugins (key: plugin name, value: plugin path) | |||
|
107 | QHash<QString, QString> m_RegisteredPlugins; | |||
|
108 | }; | |||
|
109 | ||||
|
110 | PluginManager::PluginManager() : impl{spimpl::make_unique_impl<PluginManagerPrivate>()} | |||
|
111 | { | |||
|
112 | } | |||
|
113 | ||||
|
114 | void PluginManager::loadPlugins(const QDir &pluginDir) | |||
|
115 | { | |||
|
116 | // Load plugins | |||
|
117 | auto pluginInfoList | |||
|
118 | = pluginDir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name); | |||
|
119 | for (auto entryInfo : qAsConst(pluginInfoList)) { | |||
|
120 | if (entryInfo.isDir()) { | |||
|
121 | this->loadPlugins(QDir{entryInfo.absoluteFilePath()}); | |||
|
122 | } | |||
|
123 | else if (QLibrary::isLibrary(entryInfo.absoluteFilePath())) { | |||
|
124 | impl->loadPlugin(entryInfo.absoluteFilePath()); | |||
|
125 | } | |||
|
126 | } | |||
|
127 | } | |||
|
128 | ||||
|
129 | void PluginManager::loadStaticPlugins() | |||
|
130 | { | |||
|
131 | impl->loadStaticPlugins(); | |||
|
132 | } | |||
|
133 | ||||
|
134 | int PluginManager::nbPluginsLoaded() const noexcept | |||
|
135 | { | |||
|
136 | return impl->m_RegisteredPlugins.size(); | |||
|
137 | } |
@@ -0,0 +1,18 | |||||
|
1 | #include "Settings/SqpSettingsDefs.h" | |||
|
2 | ||||
|
3 | #include <QSettings> | |||
|
4 | ||||
|
5 | ||||
|
6 | /// Gets a tolerance value from application settings. If the setting can't be found, the default | |||
|
7 | /// value passed in parameter is returned | |||
|
8 | double SqpSettings::toleranceValue(const QString &key, double defaultValue) noexcept | |||
|
9 | { | |||
|
10 | return QSettings{}.value(key, defaultValue).toDouble(); | |||
|
11 | } | |||
|
12 | ||||
|
13 | ||||
|
14 | const QString GENERAL_TOLERANCE_AT_INIT_KEY = QStringLiteral("toleranceInit"); | |||
|
15 | const double GENERAL_TOLERANCE_AT_INIT_DEFAULT_VALUE = 0.2; | |||
|
16 | ||||
|
17 | const QString GENERAL_TOLERANCE_AT_UPDATE_KEY = QStringLiteral("toleranceUpdate"); | |||
|
18 | const double GENERAL_TOLERANCE_AT_UPDATE_DEFAULT_VALUE = 0.2; |
@@ -0,0 +1,51 | |||||
|
1 | #include "Time/TimeController.h" | |||
|
2 | ||||
|
3 | #include <QDataStream> | |||
|
4 | ||||
|
5 | Q_LOGGING_CATEGORY(LOG_TimeController, "TimeController") | |||
|
6 | ||||
|
7 | struct TimeController::TimeControllerPrivate { | |||
|
8 | ||||
|
9 | DateTimeRange m_DateTime; | |||
|
10 | }; | |||
|
11 | ||||
|
12 | TimeController::TimeController(QObject *parent) | |||
|
13 | : QObject{parent}, impl{spimpl::make_unique_impl<TimeControllerPrivate>()} | |||
|
14 | { | |||
|
15 | qCDebug(LOG_TimeController()) << tr("TimeController construction"); | |||
|
16 | } | |||
|
17 | ||||
|
18 | DateTimeRange TimeController::dateTime() const noexcept | |||
|
19 | { | |||
|
20 | return impl->m_DateTime; | |||
|
21 | } | |||
|
22 | ||||
|
23 | QByteArray TimeController::mimeDataForTimeRange(const DateTimeRange &timeRange) | |||
|
24 | { | |||
|
25 | QByteArray encodedData; | |||
|
26 | QDataStream stream{&encodedData, QIODevice::WriteOnly}; | |||
|
27 | ||||
|
28 | stream << timeRange.m_TStart << timeRange.m_TEnd; | |||
|
29 | ||||
|
30 | return encodedData; | |||
|
31 | } | |||
|
32 | ||||
|
33 | DateTimeRange TimeController::timeRangeForMimeData(const QByteArray &mimeData) | |||
|
34 | { | |||
|
35 | QDataStream stream{mimeData}; | |||
|
36 | ||||
|
37 | DateTimeRange timeRange; | |||
|
38 | stream >> timeRange.m_TStart >> timeRange.m_TEnd; | |||
|
39 | ||||
|
40 | return timeRange; | |||
|
41 | } | |||
|
42 | ||||
|
43 | void TimeController::setDateTimeRange(DateTimeRange dateTime) | |||
|
44 | { | |||
|
45 | impl->m_DateTime = dateTime; | |||
|
46 | } | |||
|
47 | ||||
|
48 | void TimeController::onTimeNotify() | |||
|
49 | { | |||
|
50 | emit timeUpdated(impl->m_DateTime); | |||
|
51 | } |
@@ -0,0 +1,430 | |||||
|
1 | #include "Variable/Variable.h" | |||
|
2 | ||||
|
3 | #include <Data/IDataSeries.h> | |||
|
4 | #include <Data/DateTimeRange.h> | |||
|
5 | ||||
|
6 | #include <QMutex> | |||
|
7 | #include <QReadWriteLock> | |||
|
8 | #include <QThread> | |||
|
9 | ||||
|
10 | Q_LOGGING_CATEGORY(LOG_Variable, "Variable") | |||
|
11 | ||||
|
12 | namespace { | |||
|
13 | ||||
|
14 | /** | |||
|
15 | * Searches in metadata for a value that can be converted to DataSeriesType | |||
|
16 | * @param metadata the metadata where to search | |||
|
17 | * @return the value converted to a DataSeriesType if it was found, UNKNOWN type otherwise | |||
|
18 | * @sa DataSeriesType | |||
|
19 | */ | |||
|
20 | DataSeriesType findDataSeriesType(const QVariantHash &metadata) | |||
|
21 | { | |||
|
22 | auto dataSeriesType = DataSeriesType::UNKNOWN; | |||
|
23 | ||||
|
24 | // Go through the metadata and stop at the first value that could be converted to DataSeriesType | |||
|
25 | for (auto it = metadata.cbegin(), end = metadata.cend(); | |||
|
26 | it != end && dataSeriesType == DataSeriesType::UNKNOWN; ++it) { | |||
|
27 | dataSeriesType = DataSeriesTypeUtils::fromString(it.value().toString()); | |||
|
28 | } | |||
|
29 | ||||
|
30 | return dataSeriesType; | |||
|
31 | } | |||
|
32 | ||||
|
33 | } // namespace | |||
|
34 | ||||
|
35 | struct Variable::VariablePrivate { | |||
|
36 | explicit VariablePrivate(const QString &name, const QVariantHash &metadata) | |||
|
37 | : m_Name{name}, | |||
|
38 | m_Range{INVALID_RANGE}, | |||
|
39 | m_CacheRange{INVALID_RANGE}, | |||
|
40 | m_Metadata{metadata}, | |||
|
41 | m_DataSeries{nullptr}, | |||
|
42 | m_RealRange{INVALID_RANGE}, | |||
|
43 | m_NbPoints{0}, | |||
|
44 | m_Type{findDataSeriesType(m_Metadata)} | |||
|
45 | { | |||
|
46 | } | |||
|
47 | ||||
|
48 | VariablePrivate(const VariablePrivate &other) | |||
|
49 | : m_Name{other.m_Name}, | |||
|
50 | m_Range{other.m_Range}, | |||
|
51 | m_CacheRange{other.m_CacheRange}, | |||
|
52 | m_Metadata{other.m_Metadata}, | |||
|
53 | m_DataSeries{other.m_DataSeries != nullptr ? other.m_DataSeries->clone() : nullptr}, | |||
|
54 | m_RealRange{other.m_RealRange}, | |||
|
55 | m_NbPoints{other.m_NbPoints}, | |||
|
56 | m_Type{findDataSeriesType(m_Metadata)} | |||
|
57 | { | |||
|
58 | } | |||
|
59 | ||||
|
60 | void lockRead() { m_Lock.lockForRead(); } | |||
|
61 | void lockWrite() { m_Lock.lockForWrite(); } | |||
|
62 | void unlock() { m_Lock.unlock(); } | |||
|
63 | ||||
|
64 | void purgeDataSeries() | |||
|
65 | { | |||
|
66 | if (m_DataSeries) { | |||
|
67 | m_DataSeries->purge(m_CacheRange.m_TStart, m_CacheRange.m_TEnd); | |||
|
68 | } | |||
|
69 | updateRealRange(); | |||
|
70 | updateNbPoints(); | |||
|
71 | } | |||
|
72 | ||||
|
73 | void updateNbPoints() { m_NbPoints = m_DataSeries ? m_DataSeries->nbPoints() : 0; } | |||
|
74 | ||||
|
75 | /// Updates real range according to current variable range and data series | |||
|
76 | void updateRealRange() | |||
|
77 | { | |||
|
78 | if (m_DataSeries) { | |||
|
79 | m_DataSeries->lockRead(); | |||
|
80 | auto end = m_DataSeries->cend(); | |||
|
81 | auto minXAxisIt = m_DataSeries->minXAxisData(m_Range.m_TStart); | |||
|
82 | auto maxXAxisIt = m_DataSeries->maxXAxisData(m_Range.m_TEnd); | |||
|
83 | ||||
|
84 | m_RealRange | |||
|
85 | = (minXAxisIt != end && maxXAxisIt != end && minXAxisIt->x() <= maxXAxisIt->x()) | |||
|
86 | ? DateTimeRange{minXAxisIt->x(), maxXAxisIt->x()} | |||
|
87 | : INVALID_RANGE; | |||
|
88 | m_DataSeries->unlock(); | |||
|
89 | } | |||
|
90 | else { | |||
|
91 | m_RealRange = INVALID_RANGE; | |||
|
92 | } | |||
|
93 | } | |||
|
94 | ||||
|
95 | QString m_Name; | |||
|
96 | ||||
|
97 | DateTimeRange m_Range; | |||
|
98 | DateTimeRange m_CacheRange; | |||
|
99 | QVariantHash m_Metadata; | |||
|
100 | std::shared_ptr<IDataSeries> m_DataSeries; | |||
|
101 | DateTimeRange m_RealRange; | |||
|
102 | int m_NbPoints; | |||
|
103 | DataSeriesType m_Type; | |||
|
104 | ||||
|
105 | QReadWriteLock m_Lock; | |||
|
106 | }; | |||
|
107 | ||||
|
108 | Variable::Variable(const QString &name, const QVariantHash &metadata) | |||
|
109 | : impl{spimpl::make_unique_impl<VariablePrivate>(name, metadata)} | |||
|
110 | { | |||
|
111 | } | |||
|
112 | ||||
|
113 | Variable::Variable(const Variable &other) | |||
|
114 | : impl{spimpl::make_unique_impl<VariablePrivate>(*other.impl)} | |||
|
115 | { | |||
|
116 | } | |||
|
117 | ||||
|
118 | std::shared_ptr<Variable> Variable::clone() const | |||
|
119 | { | |||
|
120 | return std::make_shared<Variable>(*this); | |||
|
121 | } | |||
|
122 | ||||
|
123 | QString Variable::name() const noexcept | |||
|
124 | { | |||
|
125 | impl->lockRead(); | |||
|
126 | auto name = impl->m_Name; | |||
|
127 | impl->unlock(); | |||
|
128 | return name; | |||
|
129 | } | |||
|
130 | ||||
|
131 | void Variable::setName(const QString &name) noexcept | |||
|
132 | { | |||
|
133 | impl->lockWrite(); | |||
|
134 | impl->m_Name = name; | |||
|
135 | impl->unlock(); | |||
|
136 | } | |||
|
137 | ||||
|
138 | DateTimeRange Variable::range() const noexcept | |||
|
139 | { | |||
|
140 | impl->lockRead(); | |||
|
141 | auto range = impl->m_Range; | |||
|
142 | impl->unlock(); | |||
|
143 | return range; | |||
|
144 | } | |||
|
145 | ||||
|
146 | void Variable::setRange(const DateTimeRange &range) noexcept | |||
|
147 | { | |||
|
148 | impl->lockWrite(); | |||
|
149 | impl->m_Range = range; | |||
|
150 | impl->updateRealRange(); | |||
|
151 | impl->unlock(); | |||
|
152 | } | |||
|
153 | ||||
|
154 | DateTimeRange Variable::cacheRange() const noexcept | |||
|
155 | { | |||
|
156 | impl->lockRead(); | |||
|
157 | auto cacheRange = impl->m_CacheRange; | |||
|
158 | impl->unlock(); | |||
|
159 | return cacheRange; | |||
|
160 | } | |||
|
161 | ||||
|
162 | void Variable::setCacheRange(const DateTimeRange &cacheRange) noexcept | |||
|
163 | { | |||
|
164 | impl->lockWrite(); | |||
|
165 | if (cacheRange != impl->m_CacheRange) { | |||
|
166 | impl->m_CacheRange = cacheRange; | |||
|
167 | } | |||
|
168 | impl->unlock(); | |||
|
169 | } | |||
|
170 | ||||
|
171 | int Variable::nbPoints() const noexcept | |||
|
172 | { | |||
|
173 | return impl->m_NbPoints; | |||
|
174 | } | |||
|
175 | ||||
|
176 | DateTimeRange Variable::realRange() const noexcept | |||
|
177 | { | |||
|
178 | return impl->m_RealRange; | |||
|
179 | } | |||
|
180 | ||||
|
181 | void Variable::mergeDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept | |||
|
182 | { | |||
|
183 | qCDebug(LOG_Variable()) << "TORM Variable::mergeDataSeries" | |||
|
184 | << QThread::currentThread()->objectName(); | |||
|
185 | if (!dataSeries) { | |||
|
186 | /// @todo ALX : log | |||
|
187 | return; | |||
|
188 | } | |||
|
189 | ||||
|
190 | auto dataInit = false; | |||
|
191 | ||||
|
192 | // Add or merge the data | |||
|
193 | impl->lockWrite(); | |||
|
194 | if (!impl->m_DataSeries) { | |||
|
195 | impl->m_DataSeries = dataSeries->clone(); | |||
|
196 | dataInit = true; | |||
|
197 | } | |||
|
198 | else { | |||
|
199 | impl->m_DataSeries->merge(dataSeries.get()); | |||
|
200 | } | |||
|
201 | impl->purgeDataSeries(); | |||
|
202 | impl->unlock(); | |||
|
203 | ||||
|
204 | if (dataInit) { | |||
|
205 | emit dataInitialized(); | |||
|
206 | } | |||
|
207 | } | |||
|
208 | ||||
|
209 | ||||
|
210 | std::shared_ptr<IDataSeries> Variable::dataSeries() const noexcept | |||
|
211 | { | |||
|
212 | impl->lockRead(); | |||
|
213 | auto dataSeries = impl->m_DataSeries; | |||
|
214 | impl->unlock(); | |||
|
215 | ||||
|
216 | return dataSeries; | |||
|
217 | } | |||
|
218 | ||||
|
219 | DataSeriesType Variable::type() const noexcept | |||
|
220 | { | |||
|
221 | impl->lockRead(); | |||
|
222 | auto type = impl->m_Type; | |||
|
223 | impl->unlock(); | |||
|
224 | ||||
|
225 | return type; | |||
|
226 | } | |||
|
227 | ||||
|
228 | QVariantHash Variable::metadata() const noexcept | |||
|
229 | { | |||
|
230 | impl->lockRead(); | |||
|
231 | auto metadata = impl->m_Metadata; | |||
|
232 | impl->unlock(); | |||
|
233 | return metadata; | |||
|
234 | } | |||
|
235 | ||||
|
236 | bool Variable::contains(const DateTimeRange &range) const noexcept | |||
|
237 | { | |||
|
238 | impl->lockRead(); | |||
|
239 | auto res = impl->m_Range.contains(range); | |||
|
240 | impl->unlock(); | |||
|
241 | return res; | |||
|
242 | } | |||
|
243 | ||||
|
244 | bool Variable::intersect(const DateTimeRange &range) const noexcept | |||
|
245 | { | |||
|
246 | ||||
|
247 | impl->lockRead(); | |||
|
248 | auto res = impl->m_Range.intersect(range); | |||
|
249 | impl->unlock(); | |||
|
250 | return res; | |||
|
251 | } | |||
|
252 | ||||
|
253 | bool Variable::isInside(const DateTimeRange &range) const noexcept | |||
|
254 | { | |||
|
255 | impl->lockRead(); | |||
|
256 | auto res = range.contains(DateTimeRange{impl->m_Range.m_TStart, impl->m_Range.m_TEnd}); | |||
|
257 | impl->unlock(); | |||
|
258 | return res; | |||
|
259 | } | |||
|
260 | ||||
|
261 | bool Variable::cacheContains(const DateTimeRange &range) const noexcept | |||
|
262 | { | |||
|
263 | impl->lockRead(); | |||
|
264 | auto res = impl->m_CacheRange.contains(range); | |||
|
265 | impl->unlock(); | |||
|
266 | return res; | |||
|
267 | } | |||
|
268 | ||||
|
269 | bool Variable::cacheIntersect(const DateTimeRange &range) const noexcept | |||
|
270 | { | |||
|
271 | impl->lockRead(); | |||
|
272 | auto res = impl->m_CacheRange.intersect(range); | |||
|
273 | impl->unlock(); | |||
|
274 | return res; | |||
|
275 | } | |||
|
276 | ||||
|
277 | bool Variable::cacheIsInside(const DateTimeRange &range) const noexcept | |||
|
278 | { | |||
|
279 | impl->lockRead(); | |||
|
280 | auto res = range.contains(DateTimeRange{impl->m_CacheRange.m_TStart, impl->m_CacheRange.m_TEnd}); | |||
|
281 | impl->unlock(); | |||
|
282 | return res; | |||
|
283 | } | |||
|
284 | ||||
|
285 | ||||
|
286 | QVector<DateTimeRange> Variable::provideNotInCacheRangeList(const DateTimeRange &range) const noexcept | |||
|
287 | { | |||
|
288 | // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange | |||
|
289 | auto notInCache = QVector<DateTimeRange>{}; | |||
|
290 | if (impl->m_CacheRange != INVALID_RANGE) { | |||
|
291 | ||||
|
292 | if (!this->cacheContains(range)) { | |||
|
293 | if (range.m_TEnd <= impl->m_CacheRange.m_TStart | |||
|
294 | || range.m_TStart >= impl->m_CacheRange.m_TEnd) { | |||
|
295 | notInCache << range; | |||
|
296 | } | |||
|
297 | else if (range.m_TStart < impl->m_CacheRange.m_TStart | |||
|
298 | && range.m_TEnd <= impl->m_CacheRange.m_TEnd) { | |||
|
299 | notInCache << DateTimeRange{range.m_TStart, impl->m_CacheRange.m_TStart}; | |||
|
300 | } | |||
|
301 | else if (range.m_TStart < impl->m_CacheRange.m_TStart | |||
|
302 | && range.m_TEnd > impl->m_CacheRange.m_TEnd) { | |||
|
303 | notInCache << DateTimeRange{range.m_TStart, impl->m_CacheRange.m_TStart} | |||
|
304 | << DateTimeRange{impl->m_CacheRange.m_TEnd, range.m_TEnd}; | |||
|
305 | } | |||
|
306 | else if (range.m_TStart < impl->m_CacheRange.m_TEnd) { | |||
|
307 | notInCache << DateTimeRange{impl->m_CacheRange.m_TEnd, range.m_TEnd}; | |||
|
308 | } | |||
|
309 | else { | |||
|
310 | qCCritical(LOG_Variable()) << tr("Detection of unknown case.") | |||
|
311 | << QThread::currentThread(); | |||
|
312 | } | |||
|
313 | } | |||
|
314 | } | |||
|
315 | else { | |||
|
316 | notInCache << range; | |||
|
317 | } | |||
|
318 | ||||
|
319 | return notInCache; | |||
|
320 | } | |||
|
321 | ||||
|
322 | QVector<DateTimeRange> Variable::provideInCacheRangeList(const DateTimeRange &range) const noexcept | |||
|
323 | { | |||
|
324 | // This code assume that cach in contigue. Can return 0 or 1 SqpRange | |||
|
325 | ||||
|
326 | auto inCache = QVector<DateTimeRange>{}; | |||
|
327 | ||||
|
328 | if (impl->m_CacheRange != INVALID_RANGE) { | |||
|
329 | ||||
|
330 | if (this->cacheIntersect(range)) { | |||
|
331 | if (range.m_TStart <= impl->m_CacheRange.m_TStart | |||
|
332 | && range.m_TEnd >= impl->m_CacheRange.m_TStart | |||
|
333 | && range.m_TEnd < impl->m_CacheRange.m_TEnd) { | |||
|
334 | inCache << DateTimeRange{impl->m_CacheRange.m_TStart, range.m_TEnd}; | |||
|
335 | } | |||
|
336 | ||||
|
337 | else if (range.m_TStart >= impl->m_CacheRange.m_TStart | |||
|
338 | && range.m_TEnd <= impl->m_CacheRange.m_TEnd) { | |||
|
339 | inCache << range; | |||
|
340 | } | |||
|
341 | else if (range.m_TStart > impl->m_CacheRange.m_TStart | |||
|
342 | && range.m_TEnd > impl->m_CacheRange.m_TEnd) { | |||
|
343 | inCache << DateTimeRange{range.m_TStart, impl->m_CacheRange.m_TEnd}; | |||
|
344 | } | |||
|
345 | else if (range.m_TStart <= impl->m_CacheRange.m_TStart | |||
|
346 | && range.m_TEnd >= impl->m_CacheRange.m_TEnd) { | |||
|
347 | inCache << impl->m_CacheRange; | |||
|
348 | } | |||
|
349 | else { | |||
|
350 | qCCritical(LOG_Variable()) << tr("Detection of unknown case.") | |||
|
351 | << QThread::currentThread(); | |||
|
352 | } | |||
|
353 | } | |||
|
354 | } | |||
|
355 | ||||
|
356 | return inCache; | |||
|
357 | } | |||
|
358 | ||||
|
359 | ||||
|
360 | QVector<DateTimeRange> Variable::provideNotInCacheRangeList(const DateTimeRange &oldRange, | |||
|
361 | const DateTimeRange &nextRange) | |||
|
362 | { | |||
|
363 | ||||
|
364 | // This code assume that cach in contigue. Can return 0, 1 or 2 SqpRange | |||
|
365 | auto notInCache = QVector<DateTimeRange>{}; | |||
|
366 | if (oldRange != INVALID_RANGE) { | |||
|
367 | ||||
|
368 | if (!oldRange.contains(nextRange)) { | |||
|
369 | if (nextRange.m_TEnd <= oldRange.m_TStart || nextRange.m_TStart >= oldRange.m_TEnd) { | |||
|
370 | notInCache << nextRange; | |||
|
371 | } | |||
|
372 | else if (nextRange.m_TStart < oldRange.m_TStart | |||
|
373 | && nextRange.m_TEnd <= oldRange.m_TEnd) { | |||
|
374 | notInCache << DateTimeRange{nextRange.m_TStart, oldRange.m_TStart}; | |||
|
375 | } | |||
|
376 | else if (nextRange.m_TStart < oldRange.m_TStart && nextRange.m_TEnd > oldRange.m_TEnd) { | |||
|
377 | notInCache << DateTimeRange{nextRange.m_TStart, oldRange.m_TStart} | |||
|
378 | << DateTimeRange{oldRange.m_TEnd, nextRange.m_TEnd}; | |||
|
379 | } | |||
|
380 | else if (nextRange.m_TStart < oldRange.m_TEnd) { | |||
|
381 | notInCache << DateTimeRange{oldRange.m_TEnd, nextRange.m_TEnd}; | |||
|
382 | } | |||
|
383 | else { | |||
|
384 | qCCritical(LOG_Variable()) << tr("Detection of unknown case.") | |||
|
385 | << QThread::currentThread(); | |||
|
386 | } | |||
|
387 | } | |||
|
388 | } | |||
|
389 | else { | |||
|
390 | notInCache << nextRange; | |||
|
391 | } | |||
|
392 | ||||
|
393 | return notInCache; | |||
|
394 | } | |||
|
395 | ||||
|
396 | QVector<DateTimeRange> Variable::provideInCacheRangeList(const DateTimeRange &oldRange, | |||
|
397 | const DateTimeRange &nextRange) | |||
|
398 | { | |||
|
399 | // This code assume that cach is contigue. Can return 0 or 1 SqpRange | |||
|
400 | ||||
|
401 | auto inCache = QVector<DateTimeRange>{}; | |||
|
402 | ||||
|
403 | if (oldRange != INVALID_RANGE) { | |||
|
404 | ||||
|
405 | if (oldRange.intersect(nextRange)) { | |||
|
406 | if (nextRange.m_TStart <= oldRange.m_TStart && nextRange.m_TEnd >= oldRange.m_TStart | |||
|
407 | && nextRange.m_TEnd < oldRange.m_TEnd) { | |||
|
408 | inCache << DateTimeRange{oldRange.m_TStart, nextRange.m_TEnd}; | |||
|
409 | } | |||
|
410 | ||||
|
411 | else if (nextRange.m_TStart >= oldRange.m_TStart | |||
|
412 | && nextRange.m_TEnd <= oldRange.m_TEnd) { | |||
|
413 | inCache << nextRange; | |||
|
414 | } | |||
|
415 | else if (nextRange.m_TStart > oldRange.m_TStart && nextRange.m_TEnd > oldRange.m_TEnd) { | |||
|
416 | inCache << DateTimeRange{nextRange.m_TStart, oldRange.m_TEnd}; | |||
|
417 | } | |||
|
418 | else if (nextRange.m_TStart <= oldRange.m_TStart | |||
|
419 | && nextRange.m_TEnd >= oldRange.m_TEnd) { | |||
|
420 | inCache << oldRange; | |||
|
421 | } | |||
|
422 | else { | |||
|
423 | qCCritical(LOG_Variable()) << tr("Detection of unknown case.") | |||
|
424 | << QThread::currentThread(); | |||
|
425 | } | |||
|
426 | } | |||
|
427 | } | |||
|
428 | ||||
|
429 | return inCache; | |||
|
430 | } |
@@ -0,0 +1,416 | |||||
|
1 | #include "Variable/VariableAcquisitionWorker.h" | |||
|
2 | ||||
|
3 | #include "Variable/Variable.h" | |||
|
4 | ||||
|
5 | #include <Data/AcquisitionRequest.h> | |||
|
6 | #include <Data/DateTimeRange.h> | |||
|
7 | ||||
|
8 | #include <unordered_map> | |||
|
9 | #include <utility> | |||
|
10 | ||||
|
11 | #include <QMutex> | |||
|
12 | #include <QReadWriteLock> | |||
|
13 | #include <QThread> | |||
|
14 | ||||
|
15 | #include <cmath> | |||
|
16 | ||||
|
17 | Q_LOGGING_CATEGORY(LOG_VariableAcquisitionWorker, "VariableAcquisitionWorker") | |||
|
18 | ||||
|
19 | struct VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate { | |||
|
20 | ||||
|
21 | explicit VariableAcquisitionWorkerPrivate(VariableAcquisitionWorker *parent) | |||
|
22 | : m_Lock{QReadWriteLock::Recursive}, q{parent} | |||
|
23 | { | |||
|
24 | } | |||
|
25 | ||||
|
26 | void lockRead() { m_Lock.lockForRead(); } | |||
|
27 | void lockWrite() { m_Lock.lockForWrite(); } | |||
|
28 | void unlock() { m_Lock.unlock(); } | |||
|
29 | ||||
|
30 | void removeVariableRequest(QUuid vIdentifier); | |||
|
31 | ||||
|
32 | /// Remove the current request and execute the next one if exist | |||
|
33 | void updateToNextRequest(QUuid vIdentifier); | |||
|
34 | ||||
|
35 | /// Remove and/or abort all AcqRequest in link with varRequestId | |||
|
36 | void cancelVarRequest(QUuid varRequestId); | |||
|
37 | void removeAcqRequest(QUuid acqRequestId); | |||
|
38 | ||||
|
39 | QMutex m_WorkingMutex; | |||
|
40 | QReadWriteLock m_Lock; | |||
|
41 | ||||
|
42 | std::map<QUuid, QVector<AcquisitionDataPacket> > m_AcqIdentifierToAcqDataPacketVectorMap; | |||
|
43 | std::map<QUuid, AcquisitionRequest> m_AcqIdentifierToAcqRequestMap; | |||
|
44 | std::map<QUuid, std::pair<QUuid, QUuid> > m_VIdentifierToCurrrentAcqIdNextIdPairMap; | |||
|
45 | VariableAcquisitionWorker *q; | |||
|
46 | }; | |||
|
47 | ||||
|
48 | ||||
|
49 | VariableAcquisitionWorker::VariableAcquisitionWorker(QObject *parent) | |||
|
50 | : QObject{parent}, impl{spimpl::make_unique_impl<VariableAcquisitionWorkerPrivate>(this)} | |||
|
51 | { | |||
|
52 | } | |||
|
53 | ||||
|
54 | VariableAcquisitionWorker::~VariableAcquisitionWorker() | |||
|
55 | { | |||
|
56 | qCInfo(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker destruction") | |||
|
57 | << QThread::currentThread(); | |||
|
58 | this->waitForFinish(); | |||
|
59 | } | |||
|
60 | ||||
|
61 | ||||
|
62 | QUuid VariableAcquisitionWorker::pushVariableRequest(QUuid varRequestId, QUuid vIdentifier, | |||
|
63 | DateTimeRange rangeRequested, | |||
|
64 | DateTimeRange cacheRangeRequested, | |||
|
65 | DataProviderParameters parameters, | |||
|
66 | std::shared_ptr<IDataProvider> provider) | |||
|
67 | { | |||
|
68 | qCDebug(LOG_VariableAcquisitionWorker()) | |||
|
69 | << tr("TORM VariableAcquisitionWorker::pushVariableRequest ") << cacheRangeRequested; | |||
|
70 | auto varRequestIdCanceled = QUuid(); | |||
|
71 | ||||
|
72 | // Request creation | |||
|
73 | auto acqRequest = AcquisitionRequest{}; | |||
|
74 | qCDebug(LOG_VariableAcquisitionWorker()) << tr("PushVariableRequest ") << vIdentifier | |||
|
75 | << varRequestId; | |||
|
76 | acqRequest.m_VarRequestId = varRequestId; | |||
|
77 | acqRequest.m_vIdentifier = vIdentifier; | |||
|
78 | acqRequest.m_DataProviderParameters = parameters; | |||
|
79 | acqRequest.m_RangeRequested = rangeRequested; | |||
|
80 | acqRequest.m_CacheRangeRequested = cacheRangeRequested; | |||
|
81 | acqRequest.m_Size = parameters.m_Times.size(); | |||
|
82 | acqRequest.m_Provider = provider; | |||
|
83 | ||||
|
84 | ||||
|
85 | // Register request | |||
|
86 | impl->lockWrite(); | |||
|
87 | impl->m_AcqIdentifierToAcqRequestMap.insert( | |||
|
88 | std::make_pair(acqRequest.m_AcqIdentifier, acqRequest)); | |||
|
89 | ||||
|
90 | auto it = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier); | |||
|
91 | if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) { | |||
|
92 | // A current request already exists, we can replace the next one | |||
|
93 | auto oldAcqId = it->second.second; | |||
|
94 | auto acqIdentifierToAcqRequestMapIt = impl->m_AcqIdentifierToAcqRequestMap.find(oldAcqId); | |||
|
95 | if (acqIdentifierToAcqRequestMapIt != impl->m_AcqIdentifierToAcqRequestMap.cend()) { | |||
|
96 | auto oldAcqRequest = acqIdentifierToAcqRequestMapIt->second; | |||
|
97 | varRequestIdCanceled = oldAcqRequest.m_VarRequestId; | |||
|
98 | } | |||
|
99 | ||||
|
100 | it->second.second = acqRequest.m_AcqIdentifier; | |||
|
101 | impl->unlock(); | |||
|
102 | ||||
|
103 | // remove old acqIdentifier from the worker | |||
|
104 | impl->cancelVarRequest(varRequestIdCanceled); | |||
|
105 | // impl->m_AcqIdentifierToAcqRequestMap.erase(oldAcqId); | |||
|
106 | } | |||
|
107 | else { | |||
|
108 | // First request for the variable, it must be stored and executed | |||
|
109 | impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.insert( | |||
|
110 | std::make_pair(vIdentifier, std::make_pair(acqRequest.m_AcqIdentifier, QUuid()))); | |||
|
111 | impl->unlock(); | |||
|
112 | ||||
|
113 | QMetaObject::invokeMethod(this, "onExecuteRequest", Qt::QueuedConnection, | |||
|
114 | Q_ARG(QUuid, acqRequest.m_AcqIdentifier)); | |||
|
115 | } | |||
|
116 | ||||
|
117 | return varRequestIdCanceled; | |||
|
118 | } | |||
|
119 | ||||
|
120 | void VariableAcquisitionWorker::abortProgressRequested(QUuid vIdentifier) | |||
|
121 | { | |||
|
122 | impl->lockRead(); | |||
|
123 | ||||
|
124 | auto it = impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier); | |||
|
125 | if (it != impl->m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) { | |||
|
126 | auto currentAcqId = it->second.first; | |||
|
127 | ||||
|
128 | auto it = impl->m_AcqIdentifierToAcqRequestMap.find(currentAcqId); | |||
|
129 | if (it != impl->m_AcqIdentifierToAcqRequestMap.cend()) { | |||
|
130 | auto request = it->second; | |||
|
131 | impl->unlock(); | |||
|
132 | ||||
|
133 | // Remove the current request from the worker | |||
|
134 | impl->updateToNextRequest(vIdentifier); | |||
|
135 | ||||
|
136 | // notify the request aborting to the provider | |||
|
137 | request.m_Provider->requestDataAborting(currentAcqId); | |||
|
138 | } | |||
|
139 | else { | |||
|
140 | impl->unlock(); | |||
|
141 | qCWarning(LOG_VariableAcquisitionWorker()) | |||
|
142 | << tr("Impossible to abort an unknown acquisition request") << currentAcqId; | |||
|
143 | } | |||
|
144 | } | |||
|
145 | else { | |||
|
146 | impl->unlock(); | |||
|
147 | } | |||
|
148 | } | |||
|
149 | ||||
|
150 | void VariableAcquisitionWorker::onVariableRetrieveDataInProgress(QUuid acqIdentifier, | |||
|
151 | double progress) | |||
|
152 | { | |||
|
153 | qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM: onVariableRetrieveDataInProgress ") | |||
|
154 | << acqIdentifier << progress; | |||
|
155 | impl->lockRead(); | |||
|
156 | auto aIdToARit = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier); | |||
|
157 | if (aIdToARit != impl->m_AcqIdentifierToAcqRequestMap.cend()) { | |||
|
158 | auto currentPartSize = (aIdToARit->second.m_Size != 0) ? 100 / aIdToARit->second.m_Size : 0; | |||
|
159 | ||||
|
160 | auto currentPartProgress | |||
|
161 | = std::isnan(progress) ? 0.0 : (progress * currentPartSize) / 100.0; | |||
|
162 | auto currentAlreadyProgress = aIdToARit->second.m_Progression * currentPartSize; | |||
|
163 | ||||
|
164 | auto finalProgression = currentAlreadyProgress + currentPartProgress; | |||
|
165 | emit variableRequestInProgress(aIdToARit->second.m_vIdentifier, finalProgression); | |||
|
166 | qCDebug(LOG_VariableAcquisitionWorker()) | |||
|
167 | << tr("TORM: onVariableRetrieveDataInProgress ") | |||
|
168 | << QThread::currentThread()->objectName() << aIdToARit->second.m_vIdentifier | |||
|
169 | << currentPartSize << currentAlreadyProgress << currentPartProgress << finalProgression; | |||
|
170 | if (finalProgression == 100.0) { | |||
|
171 | emit variableRequestInProgress(aIdToARit->second.m_vIdentifier, 0.0); | |||
|
172 | } | |||
|
173 | } | |||
|
174 | impl->unlock(); | |||
|
175 | } | |||
|
176 | ||||
|
177 | void VariableAcquisitionWorker::onVariableAcquisitionFailed(QUuid acqIdentifier) | |||
|
178 | { | |||
|
179 | qCDebug(LOG_VariableAcquisitionWorker()) << tr("onVariableAcquisitionFailed") | |||
|
180 | << QThread::currentThread(); | |||
|
181 | impl->lockRead(); | |||
|
182 | auto it = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier); | |||
|
183 | if (it != impl->m_AcqIdentifierToAcqRequestMap.cend()) { | |||
|
184 | auto request = it->second; | |||
|
185 | impl->unlock(); | |||
|
186 | qCDebug(LOG_VariableAcquisitionWorker()) << tr("onVariableAcquisitionFailed") | |||
|
187 | << acqIdentifier << request.m_vIdentifier | |||
|
188 | << QThread::currentThread(); | |||
|
189 | emit variableCanceledRequested(request.m_vIdentifier); | |||
|
190 | } | |||
|
191 | else { | |||
|
192 | impl->unlock(); | |||
|
193 | // TODO log no acqIdentifier recognized | |||
|
194 | } | |||
|
195 | } | |||
|
196 | ||||
|
197 | void VariableAcquisitionWorker::onVariableDataAcquired(QUuid acqIdentifier, | |||
|
198 | std::shared_ptr<IDataSeries> dataSeries, | |||
|
199 | DateTimeRange dataRangeAcquired) | |||
|
200 | { | |||
|
201 | qCDebug(LOG_VariableAcquisitionWorker()) << tr("TORM: onVariableDataAcquired on range ") | |||
|
202 | << acqIdentifier << dataRangeAcquired; | |||
|
203 | impl->lockWrite(); | |||
|
204 | auto aIdToARit = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier); | |||
|
205 | if (aIdToARit != impl->m_AcqIdentifierToAcqRequestMap.cend()) { | |||
|
206 | // Store the result | |||
|
207 | auto dataPacket = AcquisitionDataPacket{}; | |||
|
208 | dataPacket.m_Range = dataRangeAcquired; | |||
|
209 | dataPacket.m_DateSeries = dataSeries; | |||
|
210 | ||||
|
211 | auto aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier); | |||
|
212 | if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) { | |||
|
213 | // A current request result already exists, we can update it | |||
|
214 | aIdToADPVit->second.push_back(dataPacket); | |||
|
215 | } | |||
|
216 | else { | |||
|
217 | // First request result for the variable, it must be stored | |||
|
218 | impl->m_AcqIdentifierToAcqDataPacketVectorMap.insert( | |||
|
219 | std::make_pair(acqIdentifier, QVector<AcquisitionDataPacket>() << dataPacket)); | |||
|
220 | } | |||
|
221 | ||||
|
222 | ||||
|
223 | // Decrement the counter of the request | |||
|
224 | auto &acqRequest = aIdToARit->second; | |||
|
225 | acqRequest.m_Progression = acqRequest.m_Progression + 1; | |||
|
226 | ||||
|
227 | // if the counter is 0, we can return data then run the next request if it exists and | |||
|
228 | // removed the finished request | |||
|
229 | if (acqRequest.m_Size == acqRequest.m_Progression) { | |||
|
230 | auto varId = acqRequest.m_vIdentifier; | |||
|
231 | auto rangeRequested = acqRequest.m_RangeRequested; | |||
|
232 | auto cacheRangeRequested = acqRequest.m_CacheRangeRequested; | |||
|
233 | // Return the data | |||
|
234 | aIdToADPVit = impl->m_AcqIdentifierToAcqDataPacketVectorMap.find(acqIdentifier); | |||
|
235 | if (aIdToADPVit != impl->m_AcqIdentifierToAcqDataPacketVectorMap.cend()) { | |||
|
236 | emit dataProvided(varId, rangeRequested, cacheRangeRequested, aIdToADPVit->second); | |||
|
237 | } | |||
|
238 | impl->unlock(); | |||
|
239 | ||||
|
240 | // Update to the next request | |||
|
241 | impl->updateToNextRequest(acqRequest.m_vIdentifier); | |||
|
242 | } | |||
|
243 | else { | |||
|
244 | impl->unlock(); | |||
|
245 | } | |||
|
246 | } | |||
|
247 | else { | |||
|
248 | impl->unlock(); | |||
|
249 | qCWarning(LOG_VariableAcquisitionWorker()) | |||
|
250 | << tr("Impossible to retrieve AcquisitionRequest for the incoming data."); | |||
|
251 | } | |||
|
252 | } | |||
|
253 | ||||
|
254 | void VariableAcquisitionWorker::onExecuteRequest(QUuid acqIdentifier) | |||
|
255 | { | |||
|
256 | qCDebug(LOG_VariableAcquisitionWorker()) << tr("onExecuteRequest") << QThread::currentThread(); | |||
|
257 | impl->lockRead(); | |||
|
258 | auto it = impl->m_AcqIdentifierToAcqRequestMap.find(acqIdentifier); | |||
|
259 | if (it != impl->m_AcqIdentifierToAcqRequestMap.cend()) { | |||
|
260 | auto request = it->second; | |||
|
261 | impl->unlock(); | |||
|
262 | emit variableRequestInProgress(request.m_vIdentifier, 0.1); | |||
|
263 | request.m_Provider->requestDataLoading(acqIdentifier, request.m_DataProviderParameters); | |||
|
264 | } | |||
|
265 | else { | |||
|
266 | impl->unlock(); | |||
|
267 | // TODO log no acqIdentifier recognized | |||
|
268 | } | |||
|
269 | } | |||
|
270 | ||||
|
271 | void VariableAcquisitionWorker::initialize() | |||
|
272 | { | |||
|
273 | qCDebug(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker init") | |||
|
274 | << QThread::currentThread(); | |||
|
275 | impl->m_WorkingMutex.lock(); | |||
|
276 | qCDebug(LOG_VariableAcquisitionWorker()) << tr("VariableAcquisitionWorker init END"); | |||
|
277 | } | |||
|
278 | ||||
|
279 | void VariableAcquisitionWorker::finalize() | |||
|
280 | { | |||
|
281 | impl->m_WorkingMutex.unlock(); | |||
|
282 | } | |||
|
283 | ||||
|
284 | void VariableAcquisitionWorker::waitForFinish() | |||
|
285 | { | |||
|
286 | QMutexLocker locker{&impl->m_WorkingMutex}; | |||
|
287 | } | |||
|
288 | ||||
|
289 | void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::removeVariableRequest( | |||
|
290 | QUuid vIdentifier) | |||
|
291 | { | |||
|
292 | lockWrite(); | |||
|
293 | auto it = m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier); | |||
|
294 | ||||
|
295 | if (it != m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) { | |||
|
296 | // A current request already exists, we can replace the next one | |||
|
297 | ||||
|
298 | m_AcqIdentifierToAcqRequestMap.erase(it->second.first); | |||
|
299 | m_AcqIdentifierToAcqDataPacketVectorMap.erase(it->second.first); | |||
|
300 | ||||
|
301 | m_AcqIdentifierToAcqRequestMap.erase(it->second.second); | |||
|
302 | m_AcqIdentifierToAcqDataPacketVectorMap.erase(it->second.second); | |||
|
303 | } | |||
|
304 | m_VIdentifierToCurrrentAcqIdNextIdPairMap.erase(vIdentifier); | |||
|
305 | unlock(); | |||
|
306 | } | |||
|
307 | ||||
|
308 | void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::updateToNextRequest( | |||
|
309 | QUuid vIdentifier) | |||
|
310 | { | |||
|
311 | lockRead(); | |||
|
312 | auto it = m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier); | |||
|
313 | if (it != m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) { | |||
|
314 | if (it->second.second.isNull()) { | |||
|
315 | unlock(); | |||
|
316 | // There is no next request, we can remove the variable request | |||
|
317 | removeVariableRequest(vIdentifier); | |||
|
318 | } | |||
|
319 | else { | |||
|
320 | auto acqIdentifierToRemove = it->second.first; | |||
|
321 | // Move the next request to the current request | |||
|
322 | auto nextRequestId = it->second.second; | |||
|
323 | it->second.first = nextRequestId; | |||
|
324 | it->second.second = QUuid(); | |||
|
325 | unlock(); | |||
|
326 | // Remove AcquisitionRequest and results; | |||
|
327 | lockWrite(); | |||
|
328 | m_AcqIdentifierToAcqRequestMap.erase(acqIdentifierToRemove); | |||
|
329 | m_AcqIdentifierToAcqDataPacketVectorMap.erase(acqIdentifierToRemove); | |||
|
330 | unlock(); | |||
|
331 | // Execute the current request | |||
|
332 | QMetaObject::invokeMethod(q, "onExecuteRequest", Qt::QueuedConnection, | |||
|
333 | Q_ARG(QUuid, nextRequestId)); | |||
|
334 | } | |||
|
335 | } | |||
|
336 | else { | |||
|
337 | unlock(); | |||
|
338 | qCCritical(LOG_VariableAcquisitionWorker()) | |||
|
339 | << tr("Impossible to execute the acquisition on an unfound variable "); | |||
|
340 | } | |||
|
341 | } | |||
|
342 | ||||
|
343 | void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::cancelVarRequest( | |||
|
344 | QUuid varRequestId) | |||
|
345 | { | |||
|
346 | qCDebug(LOG_VariableAcquisitionWorker()) | |||
|
347 | << "VariableAcquisitionWorkerPrivate::cancelVarRequest 0"; | |||
|
348 | lockRead(); | |||
|
349 | // get all AcqIdentifier in link with varRequestId | |||
|
350 | QVector<QUuid> acqIdsToRm; | |||
|
351 | auto cend = m_AcqIdentifierToAcqRequestMap.cend(); | |||
|
352 | for (auto it = m_AcqIdentifierToAcqRequestMap.cbegin(); it != cend; ++it) { | |||
|
353 | if (it->second.m_VarRequestId == varRequestId) { | |||
|
354 | acqIdsToRm << it->first; | |||
|
355 | } | |||
|
356 | } | |||
|
357 | unlock(); | |||
|
358 | // run aborting or removing of acqIdsToRm | |||
|
359 | ||||
|
360 | for (auto acqId : acqIdsToRm) { | |||
|
361 | removeAcqRequest(acqId); | |||
|
362 | } | |||
|
363 | qCDebug(LOG_VariableAcquisitionWorker()) | |||
|
364 | << "VariableAcquisitionWorkerPrivate::cancelVarRequest end"; | |||
|
365 | } | |||
|
366 | ||||
|
367 | void VariableAcquisitionWorker::VariableAcquisitionWorkerPrivate::removeAcqRequest( | |||
|
368 | QUuid acqRequestId) | |||
|
369 | { | |||
|
370 | qCDebug(LOG_VariableAcquisitionWorker()) | |||
|
371 | << "VariableAcquisitionWorkerPrivate::removeAcqRequest"; | |||
|
372 | QUuid vIdentifier; | |||
|
373 | std::shared_ptr<IDataProvider> provider; | |||
|
374 | lockRead(); | |||
|
375 | auto acqIt = m_AcqIdentifierToAcqRequestMap.find(acqRequestId); | |||
|
376 | if (acqIt != m_AcqIdentifierToAcqRequestMap.cend()) { | |||
|
377 | vIdentifier = acqIt->second.m_vIdentifier; | |||
|
378 | provider = acqIt->second.m_Provider; | |||
|
379 | ||||
|
380 | auto it = m_VIdentifierToCurrrentAcqIdNextIdPairMap.find(vIdentifier); | |||
|
381 | if (it != m_VIdentifierToCurrrentAcqIdNextIdPairMap.cend()) { | |||
|
382 | if (it->second.first == acqRequestId) { | |||
|
383 | // acqRequest is currently running -> let's aborting it | |||
|
384 | unlock(); | |||
|
385 | ||||
|
386 | // Remove the current request from the worker | |||
|
387 | updateToNextRequest(vIdentifier); | |||
|
388 | ||||
|
389 | // notify the request aborting to the provider | |||
|
390 | provider->requestDataAborting(acqRequestId); | |||
|
391 | } | |||
|
392 | else if (it->second.second == acqRequestId) { | |||
|
393 | it->second.second = QUuid(); | |||
|
394 | unlock(); | |||
|
395 | } | |||
|
396 | else { | |||
|
397 | unlock(); | |||
|
398 | } | |||
|
399 | } | |||
|
400 | else { | |||
|
401 | unlock(); | |||
|
402 | } | |||
|
403 | } | |||
|
404 | else { | |||
|
405 | unlock(); | |||
|
406 | } | |||
|
407 | ||||
|
408 | lockWrite(); | |||
|
409 | ||||
|
410 | m_AcqIdentifierToAcqDataPacketVectorMap.erase(acqRequestId); | |||
|
411 | m_AcqIdentifierToAcqRequestMap.erase(acqRequestId); | |||
|
412 | ||||
|
413 | unlock(); | |||
|
414 | qCDebug(LOG_VariableAcquisitionWorker()) | |||
|
415 | << "VariableAcquisitionWorkerPrivate::removeAcqRequest END"; | |||
|
416 | } |
@@ -0,0 +1,225 | |||||
|
1 | #include "Variable/VariableCacheController.h" | |||
|
2 | ||||
|
3 | #include "Variable/Variable.h" | |||
|
4 | #include <unordered_map> | |||
|
5 | ||||
|
6 | #include <QThread> | |||
|
7 | Q_LOGGING_CATEGORY(LOG_VariableCacheController, "VariableCacheController") | |||
|
8 | ||||
|
9 | struct VariableCacheController::VariableCacheControllerPrivate { | |||
|
10 | ||||
|
11 | std::unordered_map<std::shared_ptr<Variable>, QVector<DateTimeRange> > m_VariableToSqpRangeListMap; | |||
|
12 | ||||
|
13 | void addInCacheDataByEnd(const DateTimeRange &dateTime, QVector<DateTimeRange> &dateTimeList, | |||
|
14 | QVector<DateTimeRange> ¬InCache, int cacheIndex, double currentTStart); | |||
|
15 | ||||
|
16 | void addInCacheDataByStart(const DateTimeRange &dateTime, QVector<DateTimeRange> &dateTimeList, | |||
|
17 | QVector<DateTimeRange> ¬InCache, int cacheIndex, double currentTStart); | |||
|
18 | ||||
|
19 | ||||
|
20 | void addDateTimeRecurse(const DateTimeRange &dateTime, QVector<DateTimeRange> &dateTimeList, | |||
|
21 | int cacheIndex); | |||
|
22 | }; | |||
|
23 | ||||
|
24 | ||||
|
25 | VariableCacheController::VariableCacheController(QObject *parent) | |||
|
26 | : QObject{parent}, impl{spimpl::make_unique_impl<VariableCacheControllerPrivate>()} | |||
|
27 | { | |||
|
28 | } | |||
|
29 | ||||
|
30 | void VariableCacheController::addDateTime(std::shared_ptr<Variable> variable, | |||
|
31 | const DateTimeRange &dateTime) | |||
|
32 | { | |||
|
33 | qCDebug(LOG_VariableCacheController()) << "VariableCacheController::addDateTime" | |||
|
34 | << QThread::currentThread()->objectName(); | |||
|
35 | if (variable) { | |||
|
36 | auto findVariableIte = impl->m_VariableToSqpRangeListMap.find(variable); | |||
|
37 | if (findVariableIte == impl->m_VariableToSqpRangeListMap.end()) { | |||
|
38 | impl->m_VariableToSqpRangeListMap[variable].push_back(dateTime); | |||
|
39 | } | |||
|
40 | else { | |||
|
41 | ||||
|
42 | // addDateTime modify the list<SqpRange> of the variable in a way to ensure | |||
|
43 | // that the list is ordered : l(0) < l(1). We assume also a < b | |||
|
44 | // (with a & b of type SqpRange) means ts(b) > te(a) | |||
|
45 | ||||
|
46 | // The algorithm will try the merge of two interval: | |||
|
47 | // - dateTime will be compare with the first interval of the list: | |||
|
48 | // A: if it is inferior, it will be inserted and it's finished. | |||
|
49 | // B: if it is in intersection, it will be merge then the merged one | |||
|
50 | // will be compared to the next interval. The old one is remove from the list | |||
|
51 | // C: if it is superior, we do the same with the next interval of the list | |||
|
52 | ||||
|
53 | try { | |||
|
54 | impl->addDateTimeRecurse(dateTime, impl->m_VariableToSqpRangeListMap.at(variable), | |||
|
55 | 0); | |||
|
56 | } | |||
|
57 | catch (const std::out_of_range &e) { | |||
|
58 | qCWarning(LOG_VariableCacheController()) << "addDateTime" << e.what(); | |||
|
59 | } | |||
|
60 | } | |||
|
61 | } | |||
|
62 | } | |||
|
63 | ||||
|
64 | void VariableCacheController::clear(std::shared_ptr<Variable> variable) noexcept | |||
|
65 | { | |||
|
66 | if (!variable) { | |||
|
67 | qCCritical(LOG_VariableCacheController()) << "Can't clear variable cache: variable is null"; | |||
|
68 | return; | |||
|
69 | } | |||
|
70 | ||||
|
71 | auto nbEntries = impl->m_VariableToSqpRangeListMap.erase(variable); | |||
|
72 | ||||
|
73 | auto clearCacheMessage | |||
|
74 | = (nbEntries != 0) | |||
|
75 | ? tr("Variable cache cleared for variable %1").arg(variable->name()) | |||
|
76 | : tr("No deletion of variable cache: no cache was associated with the variable"); | |||
|
77 | qCDebug(LOG_VariableCacheController()) << clearCacheMessage; | |||
|
78 | } | |||
|
79 | ||||
|
80 | QVector<DateTimeRange> | |||
|
81 | VariableCacheController::provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable, | |||
|
82 | const DateTimeRange &dateTime) | |||
|
83 | { | |||
|
84 | qCDebug(LOG_VariableCacheController()) | |||
|
85 | << "VariableCacheController::provideNotInCacheDateTimeList" | |||
|
86 | << QThread::currentThread()->objectName(); | |||
|
87 | auto notInCache = QVector<DateTimeRange>{}; | |||
|
88 | ||||
|
89 | // This algorithm is recursif. The idea is to localise the start time then the end time in the | |||
|
90 | // list of date time request associated to the variable | |||
|
91 | // We assume that the list is ordered in a way that l(0) < l(1). We assume also a < b | |||
|
92 | // (with a & b of type SqpRange) means ts(b) > te(a) | |||
|
93 | auto it = impl->m_VariableToSqpRangeListMap.find(variable); | |||
|
94 | if (it != impl->m_VariableToSqpRangeListMap.end()) { | |||
|
95 | impl->addInCacheDataByStart(dateTime, it->second, notInCache, 0, dateTime.m_TStart); | |||
|
96 | } | |||
|
97 | else { | |||
|
98 | notInCache << dateTime; | |||
|
99 | } | |||
|
100 | ||||
|
101 | return notInCache; | |||
|
102 | } | |||
|
103 | ||||
|
104 | QVector<DateTimeRange> | |||
|
105 | VariableCacheController::dateCacheList(std::shared_ptr<Variable> variable) const noexcept | |||
|
106 | { | |||
|
107 | qCDebug(LOG_VariableCacheController()) << "VariableCacheController::dateCacheList" | |||
|
108 | << QThread::currentThread()->objectName(); | |||
|
109 | try { | |||
|
110 | return impl->m_VariableToSqpRangeListMap.at(variable); | |||
|
111 | } | |||
|
112 | catch (const std::out_of_range &e) { | |||
|
113 | qCWarning(LOG_VariableCacheController()) << e.what(); | |||
|
114 | return QVector<DateTimeRange>{}; | |||
|
115 | } | |||
|
116 | } | |||
|
117 | ||||
|
118 | void VariableCacheController::VariableCacheControllerPrivate::addDateTimeRecurse( | |||
|
119 | const DateTimeRange &dateTime, QVector<DateTimeRange> &dateTimeList, int cacheIndex) | |||
|
120 | { | |||
|
121 | const auto dateTimeListSize = dateTimeList.count(); | |||
|
122 | if (cacheIndex >= dateTimeListSize) { | |||
|
123 | dateTimeList.push_back(dateTime); | |||
|
124 | // there is no anymore interval to compore, we can just push_back it | |||
|
125 | return; | |||
|
126 | } | |||
|
127 | ||||
|
128 | auto currentDateTime = dateTimeList[cacheIndex]; | |||
|
129 | ||||
|
130 | if (dateTime.m_TEnd < currentDateTime.m_TStart) { | |||
|
131 | // The compared one is < to current one compared, we can insert it | |||
|
132 | dateTimeList.insert(cacheIndex, dateTime); | |||
|
133 | } | |||
|
134 | else if (dateTime.m_TStart > currentDateTime.m_TEnd) { | |||
|
135 | // The compared one is > to current one compared we can comparet if to the next one | |||
|
136 | addDateTimeRecurse(dateTime, dateTimeList, ++cacheIndex); | |||
|
137 | } | |||
|
138 | else { | |||
|
139 | // Merge cases: we need to merge the two interval, remove the old one from the list then | |||
|
140 | // rerun the algo from this index with the merged interval | |||
|
141 | auto mTStart = std::min(dateTime.m_TStart, currentDateTime.m_TStart); | |||
|
142 | auto mTEnd = std::max(dateTime.m_TEnd, currentDateTime.m_TEnd); | |||
|
143 | auto mergeDateTime = DateTimeRange{mTStart, mTEnd}; | |||
|
144 | ||||
|
145 | dateTimeList.remove(cacheIndex); | |||
|
146 | addDateTimeRecurse(mergeDateTime, dateTimeList, cacheIndex); | |||
|
147 | } | |||
|
148 | } | |||
|
149 | ||||
|
150 | ||||
|
151 | void VariableCacheController::VariableCacheControllerPrivate::addInCacheDataByEnd( | |||
|
152 | const DateTimeRange &dateTime, QVector<DateTimeRange> &dateTimeList, QVector<DateTimeRange> ¬InCache, | |||
|
153 | int cacheIndex, double currentTStart) | |||
|
154 | { | |||
|
155 | const auto dateTimeListSize = dateTimeList.count(); | |||
|
156 | if (cacheIndex >= dateTimeListSize) { | |||
|
157 | if (currentTStart < dateTime.m_TEnd) { | |||
|
158 | ||||
|
159 | // te localised after all other interval: The last interval is [currentTsart, te] | |||
|
160 | notInCache.push_back(DateTimeRange{currentTStart, dateTime.m_TEnd}); | |||
|
161 | } | |||
|
162 | return; | |||
|
163 | } | |||
|
164 | ||||
|
165 | auto currentDateTimeJ = dateTimeList[cacheIndex]; | |||
|
166 | if (dateTime.m_TEnd <= currentDateTimeJ.m_TStart) { | |||
|
167 | // te localised between to interval: The last interval is [currentTsart, te] | |||
|
168 | notInCache.push_back(DateTimeRange{currentTStart, dateTime.m_TEnd}); | |||
|
169 | } | |||
|
170 | else { | |||
|
171 | notInCache.push_back(DateTimeRange{currentTStart, currentDateTimeJ.m_TStart}); | |||
|
172 | if (dateTime.m_TEnd > currentDateTimeJ.m_TEnd) { | |||
|
173 | // te not localised before the current interval: we need to look at the next interval | |||
|
174 | addInCacheDataByEnd(dateTime, dateTimeList, notInCache, ++cacheIndex, | |||
|
175 | currentDateTimeJ.m_TEnd); | |||
|
176 | } | |||
|
177 | } | |||
|
178 | } | |||
|
179 | ||||
|
180 | void VariableCacheController::VariableCacheControllerPrivate::addInCacheDataByStart( | |||
|
181 | const DateTimeRange &dateTime, QVector<DateTimeRange> &dateTimeList, QVector<DateTimeRange> ¬InCache, | |||
|
182 | int cacheIndex, double currentTStart) | |||
|
183 | { | |||
|
184 | const auto dateTimeListSize = dateTimeList.count(); | |||
|
185 | if (cacheIndex >= dateTimeListSize) { | |||
|
186 | // ts localised after all other interval: The last interval is [ts, te] | |||
|
187 | notInCache.push_back(DateTimeRange{currentTStart, dateTime.m_TEnd}); | |||
|
188 | return; | |||
|
189 | } | |||
|
190 | ||||
|
191 | auto currentDateTimeI = dateTimeList[cacheIndex]; | |||
|
192 | if (currentTStart < currentDateTimeI.m_TStart) { | |||
|
193 | ||||
|
194 | // ts localised between to interval: let's localized te | |||
|
195 | addInCacheDataByEnd(dateTime, dateTimeList, notInCache, cacheIndex, currentTStart); | |||
|
196 | } | |||
|
197 | else if (currentTStart < currentDateTimeI.m_TEnd) { | |||
|
198 | if (dateTime.m_TEnd > currentDateTimeI.m_TEnd) { | |||
|
199 | // ts not localised before the current interval: we need to look at the next interval | |||
|
200 | // We can assume now current tstart is the last interval tend, because data between them | |||
|
201 | // are | |||
|
202 | // in the cache | |||
|
203 | addInCacheDataByStart(dateTime, dateTimeList, notInCache, ++cacheIndex, | |||
|
204 | currentDateTimeI.m_TEnd); | |||
|
205 | } | |||
|
206 | } | |||
|
207 | else { | |||
|
208 | // ts not localised before the current interval: we need to look at the next interval | |||
|
209 | addInCacheDataByStart(dateTime, dateTimeList, notInCache, ++cacheIndex, currentTStart); | |||
|
210 | } | |||
|
211 | } | |||
|
212 | ||||
|
213 | ||||
|
214 | void VariableCacheController::displayCache(std::shared_ptr<Variable> variable) const | |||
|
215 | { | |||
|
216 | auto variableDateTimeList = impl->m_VariableToSqpRangeListMap.find(variable); | |||
|
217 | if (variableDateTimeList != impl->m_VariableToSqpRangeListMap.end()) { | |||
|
218 | qCInfo(LOG_VariableCacheController()) << tr("VariableCacheController::displayCache") | |||
|
219 | << variableDateTimeList->second; | |||
|
220 | } | |||
|
221 | else { | |||
|
222 | qCWarning(LOG_VariableCacheController()) | |||
|
223 | << tr("Cannot display a variable that is not in the cache"); | |||
|
224 | } | |||
|
225 | } |
This diff has been collapsed as it changes many lines, (1103 lines changed) Show them Hide them | |||||
@@ -0,0 +1,1103 | |||||
|
1 | #include <Variable/Variable.h> | |||
|
2 | #include <Variable/VariableAcquisitionWorker.h> | |||
|
3 | #include <Variable/VariableCacheStrategy.h> | |||
|
4 | #include <Variable/VariableCacheStrategyFactory.h> | |||
|
5 | #include <Variable/VariableController.h> | |||
|
6 | #include <Variable/VariableModel.h> | |||
|
7 | #include <Variable/VariableSynchronizationGroup.h> | |||
|
8 | ||||
|
9 | #include <Data/DataProviderParameters.h> | |||
|
10 | #include <Data/IDataProvider.h> | |||
|
11 | #include <Data/IDataSeries.h> | |||
|
12 | #include <Data/VariableRequest.h> | |||
|
13 | #include <Time/TimeController.h> | |||
|
14 | ||||
|
15 | #include <Common/Numeric.h> | |||
|
16 | ||||
|
17 | #include <QDataStream> | |||
|
18 | #include <QMutex> | |||
|
19 | #include <QThread> | |||
|
20 | #include <QUuid> | |||
|
21 | #include <QtCore/QItemSelectionModel> | |||
|
22 | ||||
|
23 | #include <deque> | |||
|
24 | #include <set> | |||
|
25 | #include <unordered_map> | |||
|
26 | ||||
|
27 | Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController") | |||
|
28 | ||||
|
29 | namespace { | |||
|
30 | ||||
|
31 | DateTimeRange computeSynchroRangeRequested(const DateTimeRange &varRange, const DateTimeRange &graphRange, | |||
|
32 | const DateTimeRange &oldGraphRange) | |||
|
33 | { | |||
|
34 | auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange); | |||
|
35 | ||||
|
36 | auto varRangeRequested = varRange; | |||
|
37 | switch (zoomType) { | |||
|
38 | case AcquisitionZoomType::ZoomIn: { | |||
|
39 | auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart; | |||
|
40 | auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd; | |||
|
41 | varRangeRequested.m_TStart += deltaLeft; | |||
|
42 | varRangeRequested.m_TEnd -= deltaRight; | |||
|
43 | break; | |||
|
44 | } | |||
|
45 | ||||
|
46 | case AcquisitionZoomType::ZoomOut: { | |||
|
47 | auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart; | |||
|
48 | auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd; | |||
|
49 | varRangeRequested.m_TStart -= deltaLeft; | |||
|
50 | varRangeRequested.m_TEnd += deltaRight; | |||
|
51 | break; | |||
|
52 | } | |||
|
53 | case AcquisitionZoomType::PanRight: { | |||
|
54 | auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart; | |||
|
55 | auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd; | |||
|
56 | varRangeRequested.m_TStart += deltaLeft; | |||
|
57 | varRangeRequested.m_TEnd += deltaRight; | |||
|
58 | break; | |||
|
59 | } | |||
|
60 | case AcquisitionZoomType::PanLeft: { | |||
|
61 | auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart; | |||
|
62 | auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd; | |||
|
63 | varRangeRequested.m_TStart -= deltaLeft; | |||
|
64 | varRangeRequested.m_TEnd -= deltaRight; | |||
|
65 | break; | |||
|
66 | } | |||
|
67 | case AcquisitionZoomType::Unknown: { | |||
|
68 | qCCritical(LOG_VariableController()) | |||
|
69 | << VariableController::tr("Impossible to synchronize: zoom type unknown"); | |||
|
70 | break; | |||
|
71 | } | |||
|
72 | default: | |||
|
73 | qCCritical(LOG_VariableController()) << VariableController::tr( | |||
|
74 | "Impossible to synchronize: zoom type not take into account"); | |||
|
75 | // No action | |||
|
76 | break; | |||
|
77 | } | |||
|
78 | ||||
|
79 | return varRangeRequested; | |||
|
80 | } | |||
|
81 | } | |||
|
82 | ||||
|
83 | enum class VariableRequestHandlerState { OFF, RUNNING, PENDING }; | |||
|
84 | ||||
|
85 | struct VariableRequestHandler { | |||
|
86 | ||||
|
87 | VariableRequestHandler() | |||
|
88 | { | |||
|
89 | m_CanUpdate = false; | |||
|
90 | m_State = VariableRequestHandlerState::OFF; | |||
|
91 | } | |||
|
92 | ||||
|
93 | QUuid m_VarId; | |||
|
94 | VariableRequest m_RunningVarRequest; | |||
|
95 | VariableRequest m_PendingVarRequest; | |||
|
96 | VariableRequestHandlerState m_State; | |||
|
97 | bool m_CanUpdate; | |||
|
98 | }; | |||
|
99 | ||||
|
100 | struct VariableController::VariableControllerPrivate { | |||
|
101 | explicit VariableControllerPrivate(VariableController *parent) | |||
|
102 | : m_WorkingMutex{}, | |||
|
103 | m_VariableModel{new VariableModel{parent}}, | |||
|
104 | m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}}, | |||
|
105 | // m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()}, | |||
|
106 | m_VariableCacheStrategy{VariableCacheStrategyFactory::createCacheStrategy( | |||
|
107 | CacheStrategy::SingleThreshold)}, | |||
|
108 | m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()}, | |||
|
109 | q{parent} | |||
|
110 | { | |||
|
111 | ||||
|
112 | m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread); | |||
|
113 | m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread"); | |||
|
114 | } | |||
|
115 | ||||
|
116 | ||||
|
117 | virtual ~VariableControllerPrivate() | |||
|
118 | { | |||
|
119 | qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction"); | |||
|
120 | m_VariableAcquisitionWorkerThread.quit(); | |||
|
121 | m_VariableAcquisitionWorkerThread.wait(); | |||
|
122 | } | |||
|
123 | ||||
|
124 | ||||
|
125 | void processRequest(std::shared_ptr<Variable> var, const DateTimeRange &rangeRequested, | |||
|
126 | QUuid varRequestId); | |||
|
127 | ||||
|
128 | std::shared_ptr<Variable> findVariable(QUuid vIdentifier); | |||
|
129 | std::shared_ptr<IDataSeries> | |||
|
130 | retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector); | |||
|
131 | ||||
|
132 | void registerProvider(std::shared_ptr<IDataProvider> provider); | |||
|
133 | ||||
|
134 | void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest); | |||
|
135 | QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries); | |||
|
136 | void updateVariables(QUuid varRequestId); | |||
|
137 | void updateVariableRequest(QUuid varRequestId); | |||
|
138 | void cancelVariableRequest(QUuid varRequestId); | |||
|
139 | void executeVarRequest(std::shared_ptr<Variable> var, VariableRequest &varRequest); | |||
|
140 | bool hasPendingDownloads(); | |||
|
141 | template <typename VariableIterator> | |||
|
142 | void desynchronize(VariableIterator variableIt, const QUuid &syncGroupId); | |||
|
143 | ||||
|
144 | QMutex m_WorkingMutex; | |||
|
145 | /// Variable model. The VariableController has the ownership | |||
|
146 | VariableModel *m_VariableModel; | |||
|
147 | QItemSelectionModel *m_VariableSelectionModel; | |||
|
148 | ||||
|
149 | ||||
|
150 | std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy; | |||
|
151 | std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker; | |||
|
152 | QThread m_VariableAcquisitionWorkerThread; | |||
|
153 | ||||
|
154 | std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> > | |||
|
155 | m_VariableToProviderMap; | |||
|
156 | std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap; | |||
|
157 | std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> > | |||
|
158 | m_GroupIdToVariableSynchronizationGroupMap; | |||
|
159 | std::map<QUuid, QUuid> m_VariableIdGroupIdMap; | |||
|
160 | std::set<std::shared_ptr<IDataProvider> > m_ProviderSet; | |||
|
161 | ||||
|
162 | std::map<QUuid, std::list<QUuid> > m_VarGroupIdToVarIds; | |||
|
163 | std::map<QUuid, std::unique_ptr<VariableRequestHandler> > m_VarIdToVarRequestHandler; | |||
|
164 | ||||
|
165 | VariableController *q; | |||
|
166 | }; | |||
|
167 | ||||
|
168 | ||||
|
169 | VariableController::VariableController(QObject *parent) | |||
|
170 | : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)} | |||
|
171 | { | |||
|
172 | qCDebug(LOG_VariableController()) << tr("VariableController construction") | |||
|
173 | << QThread::currentThread(); | |||
|
174 | ||||
|
175 | connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this, | |||
|
176 | &VariableController::onAbortProgressRequested); | |||
|
177 | ||||
|
178 | connect(impl->m_VariableAcquisitionWorker.get(), | |||
|
179 | &VariableAcquisitionWorker::variableCanceledRequested, this, | |||
|
180 | &VariableController::onAbortAcquisitionRequested); | |||
|
181 | ||||
|
182 | connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this, | |||
|
183 | &VariableController::onDataProvided); | |||
|
184 | connect(impl->m_VariableAcquisitionWorker.get(), | |||
|
185 | &VariableAcquisitionWorker::variableRequestInProgress, this, | |||
|
186 | &VariableController::onVariableRetrieveDataInProgress); | |||
|
187 | ||||
|
188 | ||||
|
189 | connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started, | |||
|
190 | impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize); | |||
|
191 | connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished, | |||
|
192 | impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize); | |||
|
193 | ||||
|
194 | connect(impl->m_VariableModel, &VariableModel::requestVariableRangeUpdate, this, | |||
|
195 | &VariableController::onUpdateDateTime); | |||
|
196 | ||||
|
197 | impl->m_VariableAcquisitionWorkerThread.start(); | |||
|
198 | } | |||
|
199 | ||||
|
200 | VariableController::~VariableController() | |||
|
201 | { | |||
|
202 | qCDebug(LOG_VariableController()) << tr("VariableController destruction") | |||
|
203 | << QThread::currentThread(); | |||
|
204 | this->waitForFinish(); | |||
|
205 | } | |||
|
206 | ||||
|
207 | VariableModel *VariableController::variableModel() noexcept | |||
|
208 | { | |||
|
209 | return impl->m_VariableModel; | |||
|
210 | } | |||
|
211 | ||||
|
212 | QItemSelectionModel *VariableController::variableSelectionModel() noexcept | |||
|
213 | { | |||
|
214 | return impl->m_VariableSelectionModel; | |||
|
215 | } | |||
|
216 | ||||
|
217 | std::shared_ptr<Variable> | |||
|
218 | VariableController::cloneVariable(std::shared_ptr<Variable> variable) noexcept | |||
|
219 | { | |||
|
220 | if (impl->m_VariableModel->containsVariable(variable)) { | |||
|
221 | // Clones variable | |||
|
222 | auto duplicate = variable->clone(); | |||
|
223 | ||||
|
224 | // Adds clone to model | |||
|
225 | impl->m_VariableModel->addVariable(duplicate); | |||
|
226 | ||||
|
227 | // Generates clone identifier | |||
|
228 | impl->m_VariableToIdentifierMap[duplicate] = QUuid::createUuid(); | |||
|
229 | ||||
|
230 | // Registers provider | |||
|
231 | auto variableProvider = impl->m_VariableToProviderMap.at(variable); | |||
|
232 | auto duplicateProvider = variableProvider != nullptr ? variableProvider->clone() : nullptr; | |||
|
233 | ||||
|
234 | impl->m_VariableToProviderMap[duplicate] = duplicateProvider; | |||
|
235 | if (duplicateProvider) { | |||
|
236 | impl->registerProvider(duplicateProvider); | |||
|
237 | } | |||
|
238 | ||||
|
239 | return duplicate; | |||
|
240 | } | |||
|
241 | else { | |||
|
242 | qCCritical(LOG_VariableController()) | |||
|
243 | << tr("Can't create duplicate of variable %1: variable not registered in the model") | |||
|
244 | .arg(variable->name()); | |||
|
245 | return nullptr; | |||
|
246 | } | |||
|
247 | } | |||
|
248 | ||||
|
249 | void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept | |||
|
250 | { | |||
|
251 | if (!variable) { | |||
|
252 | qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null"; | |||
|
253 | return; | |||
|
254 | } | |||
|
255 | ||||
|
256 | // Spreads in SciQlop that the variable will be deleted, so that potential receivers can | |||
|
257 | // make some treatments before the deletion | |||
|
258 | emit variableAboutToBeDeleted(variable); | |||
|
259 | ||||
|
260 | auto variableIt = impl->m_VariableToIdentifierMap.find(variable); | |||
|
261 | Q_ASSERT(variableIt != impl->m_VariableToIdentifierMap.cend()); | |||
|
262 | ||||
|
263 | auto variableId = variableIt->second; | |||
|
264 | ||||
|
265 | // Removes variable's handler | |||
|
266 | impl->m_VarIdToVarRequestHandler.erase(variableId); | |||
|
267 | ||||
|
268 | // Desynchronizes variable (if the variable is in a sync group) | |||
|
269 | auto syncGroupIt = impl->m_VariableIdGroupIdMap.find(variableId); | |||
|
270 | if (syncGroupIt != impl->m_VariableIdGroupIdMap.cend()) { | |||
|
271 | impl->desynchronize(variableIt, syncGroupIt->second); | |||
|
272 | } | |||
|
273 | ||||
|
274 | // Deletes identifier | |||
|
275 | impl->m_VariableToIdentifierMap.erase(variableIt); | |||
|
276 | ||||
|
277 | // Deletes provider | |||
|
278 | auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable); | |||
|
279 | qCDebug(LOG_VariableController()) | |||
|
280 | << tr("Number of providers deleted for variable %1: %2") | |||
|
281 | .arg(variable->name(), QString::number(nbProvidersDeleted)); | |||
|
282 | ||||
|
283 | ||||
|
284 | // Deletes from model | |||
|
285 | impl->m_VariableModel->deleteVariable(variable); | |||
|
286 | } | |||
|
287 | ||||
|
288 | void VariableController::deleteVariables( | |||
|
289 | const QVector<std::shared_ptr<Variable> > &variables) noexcept | |||
|
290 | { | |||
|
291 | for (auto variable : qAsConst(variables)) { | |||
|
292 | deleteVariable(variable); | |||
|
293 | } | |||
|
294 | } | |||
|
295 | ||||
|
296 | QByteArray | |||
|
297 | VariableController::mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const | |||
|
298 | { | |||
|
299 | auto encodedData = QByteArray{}; | |||
|
300 | ||||
|
301 | QVariantList ids; | |||
|
302 | for (auto &var : variables) { | |||
|
303 | auto itVar = impl->m_VariableToIdentifierMap.find(var); | |||
|
304 | if (itVar == impl->m_VariableToIdentifierMap.cend()) { | |||
|
305 | qCCritical(LOG_VariableController()) | |||
|
306 | << tr("Impossible to find the data for an unknown variable."); | |||
|
307 | } | |||
|
308 | ||||
|
309 | ids << itVar->second.toByteArray(); | |||
|
310 | } | |||
|
311 | ||||
|
312 | QDataStream stream{&encodedData, QIODevice::WriteOnly}; | |||
|
313 | stream << ids; | |||
|
314 | ||||
|
315 | return encodedData; | |||
|
316 | } | |||
|
317 | ||||
|
318 | QList<std::shared_ptr<Variable> > | |||
|
319 | VariableController::variablesForMimeData(const QByteArray &mimeData) const | |||
|
320 | { | |||
|
321 | auto variables = QList<std::shared_ptr<Variable> >{}; | |||
|
322 | QDataStream stream{mimeData}; | |||
|
323 | ||||
|
324 | QVariantList ids; | |||
|
325 | stream >> ids; | |||
|
326 | ||||
|
327 | for (auto id : ids) { | |||
|
328 | auto uuid = QUuid{id.toByteArray()}; | |||
|
329 | auto var = impl->findVariable(uuid); | |||
|
330 | variables << var; | |||
|
331 | } | |||
|
332 | ||||
|
333 | return variables; | |||
|
334 | } | |||
|
335 | ||||
|
336 | std::shared_ptr<Variable> | |||
|
337 | VariableController::createVariable(const QString &name, const QVariantHash &metadata, | |||
|
338 | std::shared_ptr<IDataProvider> provider, const DateTimeRange& range) noexcept | |||
|
339 | { | |||
|
340 | // if (!impl->m_TimeController) { | |||
|
341 | // qCCritical(LOG_VariableController()) | |||
|
342 | // << tr("Impossible to create variable: The time controller is null"); | |||
|
343 | // return nullptr; | |||
|
344 | // } | |||
|
345 | ||||
|
346 | // auto range = impl->m_TimeController->dateTime(); | |||
|
347 | ||||
|
348 | if (auto newVariable = impl->m_VariableModel->createVariable(name, metadata)) { | |||
|
349 | auto varId = QUuid::createUuid(); | |||
|
350 | ||||
|
351 | // Create the handler | |||
|
352 | auto varRequestHandler = std::make_unique<VariableRequestHandler>(); | |||
|
353 | varRequestHandler->m_VarId = varId; | |||
|
354 | ||||
|
355 | impl->m_VarIdToVarRequestHandler.insert( | |||
|
356 | std::make_pair(varId, std::move(varRequestHandler))); | |||
|
357 | ||||
|
358 | // store the provider | |||
|
359 | impl->registerProvider(provider); | |||
|
360 | ||||
|
361 | // Associate the provider | |||
|
362 | impl->m_VariableToProviderMap[newVariable] = provider; | |||
|
363 | impl->m_VariableToIdentifierMap[newVariable] = varId; | |||
|
364 | ||||
|
365 | this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{newVariable}, range, false); | |||
|
366 | ||||
|
367 | // auto varRequestId = QUuid::createUuid(); | |||
|
368 | // qCInfo(LOG_VariableController()) << "createVariable: " << varId << varRequestId; | |||
|
369 | // impl->processRequest(newVariable, range, varRequestId); | |||
|
370 | // impl->updateVariableRequest(varRequestId); | |||
|
371 | ||||
|
372 | emit variableAdded(newVariable); | |||
|
373 | ||||
|
374 | return newVariable; | |||
|
375 | } | |||
|
376 | ||||
|
377 | qCCritical(LOG_VariableController()) << tr("Impossible to create variable"); | |||
|
378 | return nullptr; | |||
|
379 | } | |||
|
380 | ||||
|
381 | void VariableController::onDateTimeOnSelection(const DateTimeRange &dateTime) | |||
|
382 | { | |||
|
383 | // NOTE: Even if acquisition request is aborting, the graphe range will be changed | |||
|
384 | qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection" | |||
|
385 | << QThread::currentThread()->objectName(); | |||
|
386 | auto selectedRows = impl->m_VariableSelectionModel->selectedRows(); | |||
|
387 | ||||
|
388 | // NOTE we only permit the time modification for one variable | |||
|
389 | // DEPRECATED | |||
|
390 | // auto variables = QVector<std::shared_ptr<Variable> >{}; | |||
|
391 | // for (const auto &selectedRow : qAsConst(selectedRows)) { | |||
|
392 | // if (auto selectedVariable = | |||
|
393 | // impl->m_VariableModel->variable(selectedRow.row())) { | |||
|
394 | // variables << selectedVariable; | |||
|
395 | ||||
|
396 | // // notify that rescale operation has to be done | |||
|
397 | // emit rangeChanged(selectedVariable, dateTime); | |||
|
398 | // } | |||
|
399 | // } | |||
|
400 | // if (!variables.isEmpty()) { | |||
|
401 | // this->onRequestDataLoading(variables, dateTime, synchro); | |||
|
402 | // } | |||
|
403 | if (selectedRows.size() == 1) { | |||
|
404 | ||||
|
405 | if (auto selectedVariable | |||
|
406 | = impl->m_VariableModel->variable(qAsConst(selectedRows).first().row())) { | |||
|
407 | ||||
|
408 | onUpdateDateTime(selectedVariable, dateTime); | |||
|
409 | } | |||
|
410 | } | |||
|
411 | else if (selectedRows.size() > 1) { | |||
|
412 | qCCritical(LOG_VariableController()) | |||
|
413 | << tr("Impossible to set time for more than 1 variable in the same time"); | |||
|
414 | } | |||
|
415 | else { | |||
|
416 | qCWarning(LOG_VariableController()) | |||
|
417 | << tr("There is no variable selected to set the time one"); | |||
|
418 | } | |||
|
419 | } | |||
|
420 | ||||
|
421 | void VariableController::onUpdateDateTime(std::shared_ptr<Variable> variable, | |||
|
422 | const DateTimeRange &dateTime) | |||
|
423 | { | |||
|
424 | auto itVar = impl->m_VariableToIdentifierMap.find(variable); | |||
|
425 | if (itVar == impl->m_VariableToIdentifierMap.cend()) { | |||
|
426 | qCCritical(LOG_VariableController()) | |||
|
427 | << tr("Impossible to onDateTimeOnSelection request for unknown variable"); | |||
|
428 | return; | |||
|
429 | } | |||
|
430 | ||||
|
431 | // notify that rescale operation has to be done | |||
|
432 | emit rangeChanged(variable, dateTime); | |||
|
433 | ||||
|
434 | auto synchro | |||
|
435 | = impl->m_VariableIdGroupIdMap.find(itVar->second) != impl->m_VariableIdGroupIdMap.cend(); | |||
|
436 | ||||
|
437 | this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{variable}, dateTime, synchro); | |||
|
438 | } | |||
|
439 | ||||
|
440 | void VariableController::onDataProvided(QUuid vIdentifier, const DateTimeRange &rangeRequested, | |||
|
441 | const DateTimeRange &cacheRangeRequested, | |||
|
442 | QVector<AcquisitionDataPacket> dataAcquired) | |||
|
443 | { | |||
|
444 | qCDebug(LOG_VariableController()) << tr("onDataProvided") << QThread::currentThread(); | |||
|
445 | auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired); | |||
|
446 | auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries); | |||
|
447 | if (!varRequestId.isNull()) { | |||
|
448 | impl->updateVariables(varRequestId); | |||
|
449 | } | |||
|
450 | } | |||
|
451 | ||||
|
452 | void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress) | |||
|
453 | { | |||
|
454 | qCDebug(LOG_VariableController()) | |||
|
455 | << "TORM: variableController::onVariableRetrieveDataInProgress" | |||
|
456 | << QThread::currentThread()->objectName() << progress; | |||
|
457 | if (auto var = impl->findVariable(identifier)) { | |||
|
458 | impl->m_VariableModel->setDataProgress(var, progress); | |||
|
459 | } | |||
|
460 | else { | |||
|
461 | qCCritical(LOG_VariableController()) | |||
|
462 | << tr("Impossible to notify progression of a null variable"); | |||
|
463 | } | |||
|
464 | } | |||
|
465 | ||||
|
466 | void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable) | |||
|
467 | { | |||
|
468 | qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortProgressRequested" | |||
|
469 | << QThread::currentThread()->objectName() << variable->name(); | |||
|
470 | ||||
|
471 | auto itVar = impl->m_VariableToIdentifierMap.find(variable); | |||
|
472 | if (itVar == impl->m_VariableToIdentifierMap.cend()) { | |||
|
473 | qCCritical(LOG_VariableController()) | |||
|
474 | << tr("Impossible to onAbortProgressRequested request for unknown variable"); | |||
|
475 | return; | |||
|
476 | } | |||
|
477 | ||||
|
478 | auto varId = itVar->second; | |||
|
479 | ||||
|
480 | auto itVarHandler = impl->m_VarIdToVarRequestHandler.find(varId); | |||
|
481 | if (itVarHandler == impl->m_VarIdToVarRequestHandler.cend()) { | |||
|
482 | qCCritical(LOG_VariableController()) | |||
|
483 | << tr("Impossible to onAbortProgressRequested for variable with unknown handler"); | |||
|
484 | return; | |||
|
485 | } | |||
|
486 | ||||
|
487 | auto varHandler = itVarHandler->second.get(); | |||
|
488 | ||||
|
489 | // case where a variable has a running request | |||
|
490 | if (varHandler->m_State != VariableRequestHandlerState::OFF) { | |||
|
491 | impl->cancelVariableRequest(varHandler->m_RunningVarRequest.m_VariableGroupId); | |||
|
492 | } | |||
|
493 | } | |||
|
494 | ||||
|
495 | void VariableController::onAbortAcquisitionRequested(QUuid vIdentifier) | |||
|
496 | { | |||
|
497 | qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortAcquisitionRequested" | |||
|
498 | << QThread::currentThread()->objectName() << vIdentifier; | |||
|
499 | ||||
|
500 | if (auto var = impl->findVariable(vIdentifier)) { | |||
|
501 | this->onAbortProgressRequested(var); | |||
|
502 | } | |||
|
503 | else { | |||
|
504 | qCCritical(LOG_VariableController()) | |||
|
505 | << tr("Impossible to abort Acquisition Requestof a null variable"); | |||
|
506 | } | |||
|
507 | } | |||
|
508 | ||||
|
509 | void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId) | |||
|
510 | { | |||
|
511 | qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId" | |||
|
512 | << QThread::currentThread()->objectName() | |||
|
513 | << synchronizationGroupId; | |||
|
514 | auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>(); | |||
|
515 | impl->m_GroupIdToVariableSynchronizationGroupMap.insert( | |||
|
516 | std::make_pair(synchronizationGroupId, vSynchroGroup)); | |||
|
517 | } | |||
|
518 | ||||
|
519 | void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId) | |||
|
520 | { | |||
|
521 | impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId); | |||
|
522 | } | |||
|
523 | ||||
|
524 | void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable, | |||
|
525 | QUuid synchronizationGroupId) | |||
|
526 | ||||
|
527 | { | |||
|
528 | qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized" | |||
|
529 | << synchronizationGroupId; | |||
|
530 | auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable); | |||
|
531 | if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) { | |||
|
532 | auto groupIdToVSGIt | |||
|
533 | = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId); | |||
|
534 | if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) { | |||
|
535 | impl->m_VariableIdGroupIdMap.insert( | |||
|
536 | std::make_pair(varToVarIdIt->second, synchronizationGroupId)); | |||
|
537 | groupIdToVSGIt->second->addVariable(varToVarIdIt->second); | |||
|
538 | } | |||
|
539 | else { | |||
|
540 | qCCritical(LOG_VariableController()) | |||
|
541 | << tr("Impossible to synchronize a variable with an unknown sycnhronization group") | |||
|
542 | << variable->name(); | |||
|
543 | } | |||
|
544 | } | |||
|
545 | else { | |||
|
546 | qCCritical(LOG_VariableController()) | |||
|
547 | << tr("Impossible to synchronize a variable with no identifier") << variable->name(); | |||
|
548 | } | |||
|
549 | } | |||
|
550 | ||||
|
551 | void VariableController::desynchronize(std::shared_ptr<Variable> variable, | |||
|
552 | QUuid synchronizationGroupId) | |||
|
553 | { | |||
|
554 | // Gets variable id | |||
|
555 | auto variableIt = impl->m_VariableToIdentifierMap.find(variable); | |||
|
556 | if (variableIt == impl->m_VariableToIdentifierMap.cend()) { | |||
|
557 | qCCritical(LOG_VariableController()) | |||
|
558 | << tr("Can't desynchronize variable %1: variable identifier not found") | |||
|
559 | .arg(variable->name()); | |||
|
560 | return; | |||
|
561 | } | |||
|
562 | ||||
|
563 | impl->desynchronize(variableIt, synchronizationGroupId); | |||
|
564 | } | |||
|
565 | ||||
|
566 | void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, | |||
|
567 | const DateTimeRange &range, bool synchronise) | |||
|
568 | { | |||
|
569 | // variables is assumed synchronized | |||
|
570 | // TODO: Asser variables synchronization | |||
|
571 | // we want to load data of the variable for the dateTime. | |||
|
572 | if (variables.isEmpty()) { | |||
|
573 | return; | |||
|
574 | } | |||
|
575 | ||||
|
576 | auto varRequestId = QUuid::createUuid(); | |||
|
577 | qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading" | |||
|
578 | << QThread::currentThread()->objectName() << varRequestId | |||
|
579 | << range << synchronise; | |||
|
580 | ||||
|
581 | if (!synchronise) { | |||
|
582 | auto varIds = std::list<QUuid>{}; | |||
|
583 | for (const auto &var : variables) { | |||
|
584 | auto vId = impl->m_VariableToIdentifierMap.at(var); | |||
|
585 | varIds.push_back(vId); | |||
|
586 | } | |||
|
587 | impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds)); | |||
|
588 | for (const auto &var : variables) { | |||
|
589 | qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId | |||
|
590 | << varIds.size(); | |||
|
591 | impl->processRequest(var, range, varRequestId); | |||
|
592 | } | |||
|
593 | } | |||
|
594 | else { | |||
|
595 | auto vId = impl->m_VariableToIdentifierMap.at(variables.first()); | |||
|
596 | auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId); | |||
|
597 | if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) { | |||
|
598 | auto groupId = varIdToGroupIdIt->second; | |||
|
599 | ||||
|
600 | auto vSynchronizationGroup | |||
|
601 | = impl->m_GroupIdToVariableSynchronizationGroupMap.at(groupId); | |||
|
602 | auto vSyncIds = vSynchronizationGroup->getIds(); | |||
|
603 | ||||
|
604 | auto varIds = std::list<QUuid>{}; | |||
|
605 | for (auto vId : vSyncIds) { | |||
|
606 | varIds.push_back(vId); | |||
|
607 | } | |||
|
608 | impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds)); | |||
|
609 | ||||
|
610 | for (auto vId : vSyncIds) { | |||
|
611 | auto var = impl->findVariable(vId); | |||
|
612 | ||||
|
613 | // Don't process already processed var | |||
|
614 | if (var != nullptr) { | |||
|
615 | qCDebug(LOG_VariableController()) << "processRequest synchro for" << var->name() | |||
|
616 | << varRequestId; | |||
|
617 | auto vSyncRangeRequested | |||
|
618 | = variables.contains(var) | |||
|
619 | ? range | |||
|
620 | : computeSynchroRangeRequested(var->range(), range, | |||
|
621 | variables.first()->range()); | |||
|
622 | qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested; | |||
|
623 | impl->processRequest(var, vSyncRangeRequested, varRequestId); | |||
|
624 | } | |||
|
625 | else { | |||
|
626 | qCCritical(LOG_VariableController()) | |||
|
627 | ||||
|
628 | << tr("Impossible to synchronize a null variable"); | |||
|
629 | } | |||
|
630 | } | |||
|
631 | } | |||
|
632 | } | |||
|
633 | ||||
|
634 | impl->updateVariables(varRequestId); | |||
|
635 | } | |||
|
636 | ||||
|
637 | ||||
|
638 | void VariableController::initialize() | |||
|
639 | { | |||
|
640 | qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread(); | |||
|
641 | impl->m_WorkingMutex.lock(); | |||
|
642 | qCDebug(LOG_VariableController()) << tr("VariableController init END"); | |||
|
643 | } | |||
|
644 | ||||
|
645 | void VariableController::finalize() | |||
|
646 | { | |||
|
647 | impl->m_WorkingMutex.unlock(); | |||
|
648 | } | |||
|
649 | ||||
|
650 | void VariableController::waitForFinish() | |||
|
651 | { | |||
|
652 | QMutexLocker locker{&impl->m_WorkingMutex}; | |||
|
653 | } | |||
|
654 | ||||
|
655 | bool VariableController::hasPendingDownloads() | |||
|
656 | { | |||
|
657 | return impl->hasPendingDownloads(); | |||
|
658 | } | |||
|
659 | ||||
|
660 | AcquisitionZoomType VariableController::getZoomType(const DateTimeRange &range, const DateTimeRange &oldRange) | |||
|
661 | { | |||
|
662 | if (almost_equal(range.delta(), oldRange.delta(), 1)) // same delta -> must be a pan or nothing | |||
|
663 | { | |||
|
664 | if(range.m_TStart > oldRange.m_TStart) | |||
|
665 | return AcquisitionZoomType::PanRight; | |||
|
666 | if(range.m_TStart < oldRange.m_TStart) | |||
|
667 | return AcquisitionZoomType::PanLeft; | |||
|
668 | } | |||
|
669 | else // different delta -> must be a zoom | |||
|
670 | { | |||
|
671 | if(range.m_TStart > oldRange.m_TStart) | |||
|
672 | return AcquisitionZoomType::ZoomIn; | |||
|
673 | if(range.m_TStart < oldRange.m_TStart) | |||
|
674 | return AcquisitionZoomType::ZoomOut; | |||
|
675 | } | |||
|
676 | return AcquisitionZoomType::Unknown; | |||
|
677 | } | |||
|
678 | ||||
|
679 | void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var, | |||
|
680 | const DateTimeRange &rangeRequested, | |||
|
681 | QUuid varRequestId) | |||
|
682 | { | |||
|
683 | auto itVar = m_VariableToIdentifierMap.find(var); | |||
|
684 | if (itVar == m_VariableToIdentifierMap.cend()) { | |||
|
685 | qCCritical(LOG_VariableController()) | |||
|
686 | << tr("Impossible to process request for unknown variable"); | |||
|
687 | return; | |||
|
688 | } | |||
|
689 | ||||
|
690 | auto varId = itVar->second; | |||
|
691 | ||||
|
692 | auto itVarHandler = m_VarIdToVarRequestHandler.find(varId); | |||
|
693 | if (itVarHandler == m_VarIdToVarRequestHandler.cend()) { | |||
|
694 | qCCritical(LOG_VariableController()) | |||
|
695 | << tr("Impossible to process request for variable with unknown handler"); | |||
|
696 | return; | |||
|
697 | } | |||
|
698 | ||||
|
699 | auto oldRange = var->range(); | |||
|
700 | ||||
|
701 | auto varHandler = itVarHandler->second.get(); | |||
|
702 | ||||
|
703 | if (varHandler->m_State != VariableRequestHandlerState::OFF) { | |||
|
704 | oldRange = varHandler->m_RunningVarRequest.m_RangeRequested; | |||
|
705 | } | |||
|
706 | ||||
|
707 | auto varRequest = VariableRequest{}; | |||
|
708 | varRequest.m_VariableGroupId = varRequestId; | |||
|
709 | auto varStrategyRangesRequested | |||
|
710 | = m_VariableCacheStrategy->computeRange(oldRange, rangeRequested); | |||
|
711 | varRequest.m_RangeRequested = varStrategyRangesRequested.first; | |||
|
712 | varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second; | |||
|
713 | ||||
|
714 | switch (varHandler->m_State) { | |||
|
715 | case VariableRequestHandlerState::OFF: { | |||
|
716 | qCDebug(LOG_VariableController()) << tr("Process Request OFF") | |||
|
717 | << varRequest.m_RangeRequested | |||
|
718 | << varRequest.m_CacheRangeRequested; | |||
|
719 | varHandler->m_RunningVarRequest = varRequest; | |||
|
720 | varHandler->m_State = VariableRequestHandlerState::RUNNING; | |||
|
721 | executeVarRequest(var, varRequest); | |||
|
722 | break; | |||
|
723 | } | |||
|
724 | case VariableRequestHandlerState::RUNNING: { | |||
|
725 | qCDebug(LOG_VariableController()) << tr("Process Request RUNNING") | |||
|
726 | << varRequest.m_RangeRequested | |||
|
727 | << varRequest.m_CacheRangeRequested; | |||
|
728 | varHandler->m_State = VariableRequestHandlerState::PENDING; | |||
|
729 | varHandler->m_PendingVarRequest = varRequest; | |||
|
730 | break; | |||
|
731 | } | |||
|
732 | case VariableRequestHandlerState::PENDING: { | |||
|
733 | qCDebug(LOG_VariableController()) << tr("Process Request PENDING") | |||
|
734 | << varRequest.m_RangeRequested | |||
|
735 | << varRequest.m_CacheRangeRequested; | |||
|
736 | auto variableGroupIdToCancel = varHandler->m_PendingVarRequest.m_VariableGroupId; | |||
|
737 | cancelVariableRequest(variableGroupIdToCancel); | |||
|
738 | // Cancel variable can make state downgrade | |||
|
739 | varHandler->m_State = VariableRequestHandlerState::PENDING; | |||
|
740 | varHandler->m_PendingVarRequest = varRequest; | |||
|
741 | ||||
|
742 | break; | |||
|
743 | } | |||
|
744 | default: | |||
|
745 | qCCritical(LOG_VariableController()) | |||
|
746 | << QObject::tr("Unknown VariableRequestHandlerState"); | |||
|
747 | } | |||
|
748 | } | |||
|
749 | ||||
|
750 | std::shared_ptr<Variable> | |||
|
751 | VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier) | |||
|
752 | { | |||
|
753 | std::shared_ptr<Variable> var; | |||
|
754 | auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; }; | |||
|
755 | ||||
|
756 | auto end = m_VariableToIdentifierMap.cend(); | |||
|
757 | auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply); | |||
|
758 | if (it != end) { | |||
|
759 | var = it->first; | |||
|
760 | } | |||
|
761 | else { | |||
|
762 | qCCritical(LOG_VariableController()) | |||
|
763 | << tr("Impossible to find the variable with the identifier: ") << vIdentifier; | |||
|
764 | } | |||
|
765 | ||||
|
766 | return var; | |||
|
767 | } | |||
|
768 | ||||
|
769 | std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries( | |||
|
770 | const QVector<AcquisitionDataPacket> acqDataPacketVector) | |||
|
771 | { | |||
|
772 | qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size") | |||
|
773 | << acqDataPacketVector.size(); | |||
|
774 | std::shared_ptr<IDataSeries> dataSeries; | |||
|
775 | if (!acqDataPacketVector.isEmpty()) { | |||
|
776 | dataSeries = acqDataPacketVector[0].m_DateSeries; | |||
|
777 | for (int i = 1; i < acqDataPacketVector.size(); ++i) { | |||
|
778 | dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get()); | |||
|
779 | } | |||
|
780 | } | |||
|
781 | qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END") | |||
|
782 | << acqDataPacketVector.size(); | |||
|
783 | return dataSeries; | |||
|
784 | } | |||
|
785 | ||||
|
786 | void VariableController::VariableControllerPrivate::registerProvider( | |||
|
787 | std::shared_ptr<IDataProvider> provider) | |||
|
788 | { | |||
|
789 | if (m_ProviderSet.find(provider) == m_ProviderSet.end()) { | |||
|
790 | qCDebug(LOG_VariableController()) << tr("Registering of a new provider") | |||
|
791 | << provider->objectName(); | |||
|
792 | m_ProviderSet.insert(provider); | |||
|
793 | connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(), | |||
|
794 | &VariableAcquisitionWorker::onVariableDataAcquired); | |||
|
795 | connect(provider.get(), &IDataProvider::dataProvidedProgress, | |||
|
796 | m_VariableAcquisitionWorker.get(), | |||
|
797 | &VariableAcquisitionWorker::onVariableRetrieveDataInProgress); | |||
|
798 | connect(provider.get(), &IDataProvider::dataProvidedFailed, | |||
|
799 | m_VariableAcquisitionWorker.get(), | |||
|
800 | &VariableAcquisitionWorker::onVariableAcquisitionFailed); | |||
|
801 | } | |||
|
802 | else { | |||
|
803 | qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists "); | |||
|
804 | } | |||
|
805 | } | |||
|
806 | ||||
|
807 | QUuid VariableController::VariableControllerPrivate::acceptVariableRequest( | |||
|
808 | QUuid varId, std::shared_ptr<IDataSeries> dataSeries) | |||
|
809 | { | |||
|
810 | auto itVarHandler = m_VarIdToVarRequestHandler.find(varId); | |||
|
811 | if (itVarHandler == m_VarIdToVarRequestHandler.cend()) { | |||
|
812 | return QUuid(); | |||
|
813 | } | |||
|
814 | ||||
|
815 | auto varHandler = itVarHandler->second.get(); | |||
|
816 | if (varHandler->m_State == VariableRequestHandlerState::OFF) { | |||
|
817 | qCCritical(LOG_VariableController()) | |||
|
818 | << tr("acceptVariableRequest impossible on a variable with OFF state"); | |||
|
819 | } | |||
|
820 | ||||
|
821 | varHandler->m_RunningVarRequest.m_DataSeries = dataSeries; | |||
|
822 | varHandler->m_CanUpdate = true; | |||
|
823 | ||||
|
824 | // Element traitΓ©, on a dΓ©jΓ toutes les donnΓ©es necessaires | |||
|
825 | auto varGroupId = varHandler->m_RunningVarRequest.m_VariableGroupId; | |||
|
826 | qCDebug(LOG_VariableController()) << "Variable::acceptVariableRequest" << varGroupId | |||
|
827 | << m_VarGroupIdToVarIds.size(); | |||
|
828 | ||||
|
829 | return varHandler->m_RunningVarRequest.m_VariableGroupId; | |||
|
830 | } | |||
|
831 | ||||
|
832 | void VariableController::VariableControllerPrivate::updateVariables(QUuid varRequestId) | |||
|
833 | { | |||
|
834 | qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables" | |||
|
835 | << QThread::currentThread()->objectName() << varRequestId; | |||
|
836 | ||||
|
837 | auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId); | |||
|
838 | if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) { | |||
|
839 | qCWarning(LOG_VariableController()) | |||
|
840 | << tr("Impossible to updateVariables of unknown variables") << varRequestId; | |||
|
841 | return; | |||
|
842 | } | |||
|
843 | ||||
|
844 | auto &varIds = varGroupIdToVarIdsIt->second; | |||
|
845 | auto varIdsEnd = varIds.end(); | |||
|
846 | bool processVariableUpdate = true; | |||
|
847 | qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables" | |||
|
848 | << varRequestId << varIds.size(); | |||
|
849 | for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd) && processVariableUpdate; | |||
|
850 | ++varIdsIt) { | |||
|
851 | auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt); | |||
|
852 | if (itVarHandler != m_VarIdToVarRequestHandler.cend()) { | |||
|
853 | processVariableUpdate &= itVarHandler->second->m_CanUpdate; | |||
|
854 | } | |||
|
855 | } | |||
|
856 | ||||
|
857 | if (processVariableUpdate) { | |||
|
858 | qCDebug(LOG_VariableController()) << "Final update OK for the var request" << varIds.size(); | |||
|
859 | for (auto varIdsIt = varIds.begin(); varIdsIt != varIdsEnd; ++varIdsIt) { | |||
|
860 | auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt); | |||
|
861 | if (itVarHandler != m_VarIdToVarRequestHandler.cend()) { | |||
|
862 | if (auto var = findVariable(*varIdsIt)) { | |||
|
863 | auto &varRequest = itVarHandler->second->m_RunningVarRequest; | |||
|
864 | var->setRange(varRequest.m_RangeRequested); | |||
|
865 | var->setCacheRange(varRequest.m_CacheRangeRequested); | |||
|
866 | qCDebug(LOG_VariableController()) << tr("1: onDataProvided") | |||
|
867 | << varRequest.m_RangeRequested | |||
|
868 | << varRequest.m_CacheRangeRequested; | |||
|
869 | qCDebug(LOG_VariableController()) << tr("2: onDataProvided var points before") | |||
|
870 | << var->nbPoints() | |||
|
871 | << varRequest.m_DataSeries->nbPoints(); | |||
|
872 | var->mergeDataSeries(varRequest.m_DataSeries); | |||
|
873 | qCDebug(LOG_VariableController()) << tr("3: onDataProvided var points after") | |||
|
874 | << var->nbPoints(); | |||
|
875 | ||||
|
876 | emit var->updated(); | |||
|
877 | qCDebug(LOG_VariableController()) << tr("Update OK"); | |||
|
878 | } | |||
|
879 | else { | |||
|
880 | qCCritical(LOG_VariableController()) | |||
|
881 | << tr("Impossible to update data to a null variable"); | |||
|
882 | } | |||
|
883 | } | |||
|
884 | } | |||
|
885 | updateVariableRequest(varRequestId); | |||
|
886 | ||||
|
887 | // cleaning varRequestId | |||
|
888 | qCDebug(LOG_VariableController()) << tr("m_VarGroupIdToVarIds erase") << varRequestId; | |||
|
889 | m_VarGroupIdToVarIds.erase(varRequestId); | |||
|
890 | if (m_VarGroupIdToVarIds.empty()) { | |||
|
891 | emit q->acquisitionFinished(); | |||
|
892 | } | |||
|
893 | } | |||
|
894 | } | |||
|
895 | ||||
|
896 | ||||
|
897 | void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId) | |||
|
898 | { | |||
|
899 | auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId); | |||
|
900 | if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) { | |||
|
901 | qCCritical(LOG_VariableController()) << QObject::tr( | |||
|
902 | "Impossible to updateVariableRequest since varGroupdId isn't here anymore"); | |||
|
903 | ||||
|
904 | return; | |||
|
905 | } | |||
|
906 | ||||
|
907 | auto &varIds = varGroupIdToVarIdsIt->second; | |||
|
908 | auto varIdsEnd = varIds.end(); | |||
|
909 | for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) { | |||
|
910 | auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt); | |||
|
911 | if (itVarHandler != m_VarIdToVarRequestHandler.cend()) { | |||
|
912 | ||||
|
913 | auto varHandler = itVarHandler->second.get(); | |||
|
914 | varHandler->m_CanUpdate = false; | |||
|
915 | ||||
|
916 | ||||
|
917 | switch (varHandler->m_State) { | |||
|
918 | case VariableRequestHandlerState::OFF: { | |||
|
919 | qCCritical(LOG_VariableController()) | |||
|
920 | << QObject::tr("Impossible to update a variable with handler in OFF state"); | |||
|
921 | } break; | |||
|
922 | case VariableRequestHandlerState::RUNNING: { | |||
|
923 | varHandler->m_State = VariableRequestHandlerState::OFF; | |||
|
924 | varHandler->m_RunningVarRequest = VariableRequest{}; | |||
|
925 | break; | |||
|
926 | } | |||
|
927 | case VariableRequestHandlerState::PENDING: { | |||
|
928 | varHandler->m_State = VariableRequestHandlerState::RUNNING; | |||
|
929 | varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest; | |||
|
930 | varHandler->m_PendingVarRequest = VariableRequest{}; | |||
|
931 | auto var = findVariable(itVarHandler->first); | |||
|
932 | executeVarRequest(var, varHandler->m_RunningVarRequest); | |||
|
933 | updateVariables(varHandler->m_RunningVarRequest.m_VariableGroupId); | |||
|
934 | break; | |||
|
935 | } | |||
|
936 | default: | |||
|
937 | qCCritical(LOG_VariableController()) | |||
|
938 | << QObject::tr("Unknown VariableRequestHandlerState"); | |||
|
939 | } | |||
|
940 | } | |||
|
941 | } | |||
|
942 | } | |||
|
943 | ||||
|
944 | ||||
|
945 | void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId) | |||
|
946 | { | |||
|
947 | qCDebug(LOG_VariableController()) << tr("cancelVariableRequest") << varRequestId; | |||
|
948 | ||||
|
949 | auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId); | |||
|
950 | if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) { | |||
|
951 | qCCritical(LOG_VariableController()) | |||
|
952 | << tr("Impossible to cancelVariableRequest for unknown varGroupdId") << varRequestId; | |||
|
953 | return; | |||
|
954 | } | |||
|
955 | ||||
|
956 | auto &varIds = varGroupIdToVarIdsIt->second; | |||
|
957 | auto varIdsEnd = varIds.end(); | |||
|
958 | for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) { | |||
|
959 | auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt); | |||
|
960 | if (itVarHandler != m_VarIdToVarRequestHandler.cend()) { | |||
|
961 | ||||
|
962 | auto varHandler = itVarHandler->second.get(); | |||
|
963 | varHandler->m_VarId = QUuid{}; | |||
|
964 | switch (varHandler->m_State) { | |||
|
965 | case VariableRequestHandlerState::OFF: { | |||
|
966 | qCWarning(LOG_VariableController()) | |||
|
967 | << QObject::tr("Impossible to cancel a variable with no running request"); | |||
|
968 | break; | |||
|
969 | } | |||
|
970 | case VariableRequestHandlerState::RUNNING: { | |||
|
971 | ||||
|
972 | if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) { | |||
|
973 | auto var = findVariable(itVarHandler->first); | |||
|
974 | auto varProvider = m_VariableToProviderMap.at(var); | |||
|
975 | if (varProvider != nullptr) { | |||
|
976 | m_VariableAcquisitionWorker->abortProgressRequested( | |||
|
977 | itVarHandler->first); | |||
|
978 | } | |||
|
979 | m_VariableModel->setDataProgress(var, 0.0); | |||
|
980 | varHandler->m_CanUpdate = false; | |||
|
981 | varHandler->m_State = VariableRequestHandlerState::OFF; | |||
|
982 | varHandler->m_RunningVarRequest = VariableRequest{}; | |||
|
983 | } | |||
|
984 | else { | |||
|
985 | // TODO: log Impossible to cancel the running variable request beacause its | |||
|
986 | // varRequestId isn't not the canceled one | |||
|
987 | } | |||
|
988 | break; | |||
|
989 | } | |||
|
990 | case VariableRequestHandlerState::PENDING: { | |||
|
991 | if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) { | |||
|
992 | auto var = findVariable(itVarHandler->first); | |||
|
993 | auto varProvider = m_VariableToProviderMap.at(var); | |||
|
994 | if (varProvider != nullptr) { | |||
|
995 | m_VariableAcquisitionWorker->abortProgressRequested( | |||
|
996 | itVarHandler->first); | |||
|
997 | } | |||
|
998 | m_VariableModel->setDataProgress(var, 0.0); | |||
|
999 | varHandler->m_CanUpdate = false; | |||
|
1000 | varHandler->m_State = VariableRequestHandlerState::RUNNING; | |||
|
1001 | varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest; | |||
|
1002 | varHandler->m_PendingVarRequest = VariableRequest{}; | |||
|
1003 | executeVarRequest(var, varHandler->m_RunningVarRequest); | |||
|
1004 | } | |||
|
1005 | else if (varHandler->m_PendingVarRequest.m_VariableGroupId == varRequestId) { | |||
|
1006 | varHandler->m_State = VariableRequestHandlerState::RUNNING; | |||
|
1007 | varHandler->m_PendingVarRequest = VariableRequest{}; | |||
|
1008 | } | |||
|
1009 | else { | |||
|
1010 | // TODO: log Impossible to cancel the variable request beacause its | |||
|
1011 | // varRequestId isn't not the canceled one | |||
|
1012 | } | |||
|
1013 | break; | |||
|
1014 | } | |||
|
1015 | default: | |||
|
1016 | qCCritical(LOG_VariableController()) | |||
|
1017 | << QObject::tr("Unknown VariableRequestHandlerState"); | |||
|
1018 | } | |||
|
1019 | } | |||
|
1020 | } | |||
|
1021 | qCDebug(LOG_VariableController()) << tr("cancelVariableRequest: erase") << varRequestId; | |||
|
1022 | m_VarGroupIdToVarIds.erase(varRequestId); | |||
|
1023 | if (m_VarGroupIdToVarIds.empty()) { | |||
|
1024 | emit q->acquisitionFinished(); | |||
|
1025 | } | |||
|
1026 | } | |||
|
1027 | ||||
|
1028 | void VariableController::VariableControllerPrivate::executeVarRequest(std::shared_ptr<Variable> var, | |||
|
1029 | VariableRequest &varRequest) | |||
|
1030 | { | |||
|
1031 | qCDebug(LOG_VariableController()) << tr("TORM: executeVarRequest"); | |||
|
1032 | ||||
|
1033 | auto varIdIt = m_VariableToIdentifierMap.find(var); | |||
|
1034 | if (varIdIt == m_VariableToIdentifierMap.cend()) { | |||
|
1035 | qCWarning(LOG_VariableController()) << tr( | |||
|
1036 | "Can't execute request of a variable that is not registered (may has been deleted)"); | |||
|
1037 | return; | |||
|
1038 | } | |||
|
1039 | ||||
|
1040 | auto varId = varIdIt->second; | |||
|
1041 | ||||
|
1042 | auto varCacheRange = var->cacheRange(); | |||
|
1043 | auto varCacheRangeRequested = varRequest.m_CacheRangeRequested; | |||
|
1044 | auto notInCacheRangeList | |||
|
1045 | = Variable::provideNotInCacheRangeList(varCacheRange, varCacheRangeRequested); | |||
|
1046 | auto inCacheRangeList | |||
|
1047 | = Variable::provideInCacheRangeList(varCacheRange, varCacheRangeRequested); | |||
|
1048 | ||||
|
1049 | if (!notInCacheRangeList.empty()) { | |||
|
1050 | ||||
|
1051 | auto varProvider = m_VariableToProviderMap.at(var); | |||
|
1052 | if (varProvider != nullptr) { | |||
|
1053 | qCDebug(LOG_VariableController()) << "executeVarRequest " << varRequest.m_RangeRequested | |||
|
1054 | << varRequest.m_CacheRangeRequested; | |||
|
1055 | m_VariableAcquisitionWorker->pushVariableRequest( | |||
|
1056 | varRequest.m_VariableGroupId, varId, varRequest.m_RangeRequested, | |||
|
1057 | varRequest.m_CacheRangeRequested, | |||
|
1058 | DataProviderParameters{std::move(notInCacheRangeList), var->metadata()}, | |||
|
1059 | varProvider); | |||
|
1060 | } | |||
|
1061 | else { | |||
|
1062 | qCCritical(LOG_VariableController()) | |||
|
1063 | << "Impossible to provide data with a null provider"; | |||
|
1064 | } | |||
|
1065 | ||||
|
1066 | if (!inCacheRangeList.empty()) { | |||
|
1067 | emit q->updateVarDisplaying(var, inCacheRangeList.first()); | |||
|
1068 | } | |||
|
1069 | } | |||
|
1070 | else { | |||
|
1071 | acceptVariableRequest(varId, | |||
|
1072 | var->dataSeries()->subDataSeries(varRequest.m_CacheRangeRequested)); | |||
|
1073 | } | |||
|
1074 | } | |||
|
1075 | ||||
|
1076 | bool VariableController::VariableControllerPrivate::hasPendingDownloads() | |||
|
1077 | { | |||
|
1078 | return !m_VarGroupIdToVarIds.empty(); | |||
|
1079 | } | |||
|
1080 | ||||
|
1081 | template <typename VariableIterator> | |||
|
1082 | void VariableController::VariableControllerPrivate::desynchronize(VariableIterator variableIt, | |||
|
1083 | const QUuid &syncGroupId) | |||
|
1084 | { | |||
|
1085 | const auto &variable = variableIt->first; | |||
|
1086 | const auto &variableId = variableIt->second; | |||
|
1087 | ||||
|
1088 | // Gets synchronization group | |||
|
1089 | auto groupIt = m_GroupIdToVariableSynchronizationGroupMap.find(syncGroupId); | |||
|
1090 | if (groupIt == m_GroupIdToVariableSynchronizationGroupMap.cend()) { | |||
|
1091 | qCCritical(LOG_VariableController()) | |||
|
1092 | << tr("Can't desynchronize variable %1: unknown synchronization group") | |||
|
1093 | .arg(variable->name()); | |||
|
1094 | return; | |||
|
1095 | } | |||
|
1096 | ||||
|
1097 | // Removes variable from synchronization group | |||
|
1098 | auto synchronizationGroup = groupIt->second; | |||
|
1099 | synchronizationGroup->removeVariable(variableId); | |||
|
1100 | ||||
|
1101 | // Removes link between variable and synchronization group | |||
|
1102 | m_VariableIdGroupIdMap.erase(variableId); | |||
|
1103 | } |
@@ -0,0 +1,25 | |||||
|
1 | #include "Variable/VariableController2.h" | |||
|
2 | ||||
|
3 | ||||
|
4 | class VariableController2Private | |||
|
5 | { | |||
|
6 | ||||
|
7 | public: | |||
|
8 | VariableController2Private(QObject* parent=Q_NULLPTR) | |||
|
9 | {} | |||
|
10 | ~VariableController2Private() = default; | |||
|
11 | std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata, std::shared_ptr<IDataProvider> provider, const DateTimeRange &range) | |||
|
12 | { | |||
|
13 | return std::make_shared<Variable>(name,metadata); | |||
|
14 | } | |||
|
15 | }; | |||
|
16 | ||||
|
17 | VariableController2::VariableController2() | |||
|
18 | :impl{spimpl::make_unique_impl<VariableController2Private>()} | |||
|
19 | {} | |||
|
20 | ||||
|
21 | std::shared_ptr<Variable> VariableController2::createVariable(const QString &name, const QVariantHash &metadata, std::shared_ptr<IDataProvider> provider, const DateTimeRange &range) | |||
|
22 | { | |||
|
23 | return impl->createVariable(name, metadata, provider, range); | |||
|
24 | } | |||
|
25 |
@@ -0,0 +1,393 | |||||
|
1 | #include <Variable/Variable.h> | |||
|
2 | #include <Variable/VariableController.h> | |||
|
3 | #include <Variable/VariableModel.h> | |||
|
4 | ||||
|
5 | #include <Common/DateUtils.h> | |||
|
6 | #include <Common/MimeTypesDef.h> | |||
|
7 | #include <Common/StringUtils.h> | |||
|
8 | ||||
|
9 | #include <Data/IDataSeries.h> | |||
|
10 | ||||
|
11 | #include <DataSource/DataSourceController.h> | |||
|
12 | #include <Time/TimeController.h> | |||
|
13 | ||||
|
14 | #include <QMimeData> | |||
|
15 | #include <QSize> | |||
|
16 | #include <QTimer> | |||
|
17 | #include <unordered_map> | |||
|
18 | ||||
|
19 | Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel") | |||
|
20 | ||||
|
21 | namespace { | |||
|
22 | ||||
|
23 | // Column indexes | |||
|
24 | const auto NAME_COLUMN = 0; | |||
|
25 | const auto TSTART_COLUMN = 1; | |||
|
26 | const auto TEND_COLUMN = 2; | |||
|
27 | const auto NBPOINTS_COLUMN = 3; | |||
|
28 | const auto UNIT_COLUMN = 4; | |||
|
29 | const auto MISSION_COLUMN = 5; | |||
|
30 | const auto PLUGIN_COLUMN = 6; | |||
|
31 | const auto NB_COLUMNS = 7; | |||
|
32 | ||||
|
33 | // Column properties | |||
|
34 | const auto DEFAULT_HEIGHT = 25; | |||
|
35 | const auto DEFAULT_WIDTH = 100; | |||
|
36 | ||||
|
37 | struct ColumnProperties { | |||
|
38 | ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH, | |||
|
39 | int height = DEFAULT_HEIGHT) | |||
|
40 | : m_Name{name}, m_Width{width}, m_Height{height} | |||
|
41 | { | |||
|
42 | } | |||
|
43 | ||||
|
44 | QString m_Name; | |||
|
45 | int m_Width; | |||
|
46 | int m_Height; | |||
|
47 | }; | |||
|
48 | ||||
|
49 | const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{ | |||
|
50 | {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}}, | |||
|
51 | {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {NBPOINTS_COLUMN, {QObject::tr("Nb points")}}, | |||
|
52 | {UNIT_COLUMN, {QObject::tr("Unit")}}, {MISSION_COLUMN, {QObject::tr("Mission")}}, | |||
|
53 | {PLUGIN_COLUMN, {QObject::tr("Plugin")}}}; | |||
|
54 | ||||
|
55 | QString uniqueName(const QString &defaultName, | |||
|
56 | const std::vector<std::shared_ptr<Variable> > &variables) | |||
|
57 | { | |||
|
58 | auto forbiddenNames = std::vector<QString>(variables.size()); | |||
|
59 | std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(), | |||
|
60 | [](const auto &variable) { return variable->name(); }); | |||
|
61 | auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames); | |||
|
62 | Q_ASSERT(!uniqueName.isEmpty()); | |||
|
63 | ||||
|
64 | return uniqueName; | |||
|
65 | } | |||
|
66 | ||||
|
67 | } // namespace | |||
|
68 | ||||
|
69 | struct VariableModel::VariableModelPrivate { | |||
|
70 | /// Variables created in SciQlop | |||
|
71 | std::vector<std::shared_ptr<Variable> > m_Variables; | |||
|
72 | std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress; | |||
|
73 | VariableController *m_VariableController; | |||
|
74 | ||||
|
75 | /// Return the row index of the variable. -1 if it's not found | |||
|
76 | int indexOfVariable(Variable *variable) const noexcept; | |||
|
77 | }; | |||
|
78 | ||||
|
79 | VariableModel::VariableModel(VariableController *parent) | |||
|
80 | : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()} | |||
|
81 | { | |||
|
82 | impl->m_VariableController = parent; | |||
|
83 | } | |||
|
84 | ||||
|
85 | void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept | |||
|
86 | { | |||
|
87 | auto insertIndex = rowCount(); | |||
|
88 | beginInsertRows({}, insertIndex, insertIndex); | |||
|
89 | ||||
|
90 | // Generates unique name for the variable | |||
|
91 | variable->setName(uniqueName(variable->name(), impl->m_Variables)); | |||
|
92 | ||||
|
93 | impl->m_Variables.push_back(variable); | |||
|
94 | connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated); | |||
|
95 | ||||
|
96 | endInsertRows(); | |||
|
97 | } | |||
|
98 | ||||
|
99 | bool VariableModel::containsVariable(std::shared_ptr<Variable> variable) const noexcept | |||
|
100 | { | |||
|
101 | auto end = impl->m_Variables.cend(); | |||
|
102 | return std::find(impl->m_Variables.cbegin(), end, variable) != end; | |||
|
103 | } | |||
|
104 | ||||
|
105 | std::shared_ptr<Variable> VariableModel::createVariable(const QString &name, | |||
|
106 | const QVariantHash &metadata) noexcept | |||
|
107 | { | |||
|
108 | auto variable = std::make_shared<Variable>(name, metadata); | |||
|
109 | addVariable(variable); | |||
|
110 | ||||
|
111 | return variable; | |||
|
112 | } | |||
|
113 | ||||
|
114 | void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept | |||
|
115 | { | |||
|
116 | if (!variable) { | |||
|
117 | qCCritical(LOG_Variable()) << "Can't delete a null variable from the model"; | |||
|
118 | return; | |||
|
119 | } | |||
|
120 | ||||
|
121 | // Finds variable in the model | |||
|
122 | auto begin = impl->m_Variables.cbegin(); | |||
|
123 | auto end = impl->m_Variables.cend(); | |||
|
124 | auto it = std::find(begin, end, variable); | |||
|
125 | if (it != end) { | |||
|
126 | auto removeIndex = std::distance(begin, it); | |||
|
127 | ||||
|
128 | // Deletes variable | |||
|
129 | beginRemoveRows({}, removeIndex, removeIndex); | |||
|
130 | impl->m_Variables.erase(it); | |||
|
131 | endRemoveRows(); | |||
|
132 | } | |||
|
133 | else { | |||
|
134 | qCritical(LOG_VariableModel()) | |||
|
135 | << tr("Can't delete variable %1 from the model: the variable is not in the model") | |||
|
136 | .arg(variable->name()); | |||
|
137 | } | |||
|
138 | ||||
|
139 | // Removes variable from progress map | |||
|
140 | impl->m_VariableToProgress.erase(variable); | |||
|
141 | } | |||
|
142 | ||||
|
143 | ||||
|
144 | std::shared_ptr<Variable> VariableModel::variable(int index) const | |||
|
145 | { | |||
|
146 | return (index >= 0u && static_cast<size_t>(index) < impl->m_Variables.size()) | |||
|
147 | ? impl->m_Variables[index] | |||
|
148 | : nullptr; | |||
|
149 | } | |||
|
150 | ||||
|
151 | std::vector<std::shared_ptr<Variable> > VariableModel::variables() const | |||
|
152 | { | |||
|
153 | return impl->m_Variables; | |||
|
154 | } | |||
|
155 | ||||
|
156 | void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress) | |||
|
157 | { | |||
|
158 | if (progress > 0.0) { | |||
|
159 | impl->m_VariableToProgress[variable] = progress; | |||
|
160 | } | |||
|
161 | else { | |||
|
162 | impl->m_VariableToProgress.erase(variable); | |||
|
163 | } | |||
|
164 | auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN); | |||
|
165 | ||||
|
166 | emit dataChanged(modelIndex, modelIndex); | |||
|
167 | } | |||
|
168 | ||||
|
169 | int VariableModel::columnCount(const QModelIndex &parent) const | |||
|
170 | { | |||
|
171 | Q_UNUSED(parent); | |||
|
172 | ||||
|
173 | return NB_COLUMNS; | |||
|
174 | } | |||
|
175 | ||||
|
176 | int VariableModel::rowCount(const QModelIndex &parent) const | |||
|
177 | { | |||
|
178 | Q_UNUSED(parent); | |||
|
179 | ||||
|
180 | return impl->m_Variables.size(); | |||
|
181 | } | |||
|
182 | ||||
|
183 | QVariant VariableModel::data(const QModelIndex &index, int role) const | |||
|
184 | { | |||
|
185 | if (!index.isValid()) { | |||
|
186 | return QVariant{}; | |||
|
187 | } | |||
|
188 | ||||
|
189 | if (index.row() < 0 || index.row() >= rowCount()) { | |||
|
190 | return QVariant{}; | |||
|
191 | } | |||
|
192 | ||||
|
193 | if (role == Qt::DisplayRole) { | |||
|
194 | if (auto variable = impl->m_Variables.at(index.row()).get()) { | |||
|
195 | switch (index.column()) { | |||
|
196 | case NAME_COLUMN: | |||
|
197 | return variable->name(); | |||
|
198 | case TSTART_COLUMN: { | |||
|
199 | auto range = variable->realRange(); | |||
|
200 | return range != INVALID_RANGE | |||
|
201 | ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT) | |||
|
202 | : QVariant{}; | |||
|
203 | } | |||
|
204 | case TEND_COLUMN: { | |||
|
205 | auto range = variable->realRange(); | |||
|
206 | return range != INVALID_RANGE | |||
|
207 | ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT) | |||
|
208 | : QVariant{}; | |||
|
209 | } | |||
|
210 | case NBPOINTS_COLUMN: | |||
|
211 | return variable->nbPoints(); | |||
|
212 | case UNIT_COLUMN: | |||
|
213 | return variable->metadata().value(QStringLiteral("units")); | |||
|
214 | case MISSION_COLUMN: | |||
|
215 | return variable->metadata().value(QStringLiteral("mission")); | |||
|
216 | case PLUGIN_COLUMN: | |||
|
217 | return variable->metadata().value(QStringLiteral("plugin")); | |||
|
218 | default: | |||
|
219 | // No action | |||
|
220 | break; | |||
|
221 | } | |||
|
222 | ||||
|
223 | qWarning(LOG_VariableModel()) | |||
|
224 | << tr("Can't get data (unknown column %1)").arg(index.column()); | |||
|
225 | } | |||
|
226 | else { | |||
|
227 | qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)"); | |||
|
228 | } | |||
|
229 | } | |||
|
230 | else if (role == VariableRoles::ProgressRole) { | |||
|
231 | if (auto variable = impl->m_Variables.at(index.row())) { | |||
|
232 | ||||
|
233 | auto it = impl->m_VariableToProgress.find(variable); | |||
|
234 | if (it != impl->m_VariableToProgress.cend()) { | |||
|
235 | return it->second; | |||
|
236 | } | |||
|
237 | } | |||
|
238 | } | |||
|
239 | ||||
|
240 | return QVariant{}; | |||
|
241 | } | |||
|
242 | ||||
|
243 | QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const | |||
|
244 | { | |||
|
245 | if (role != Qt::DisplayRole && role != Qt::SizeHintRole) { | |||
|
246 | return QVariant{}; | |||
|
247 | } | |||
|
248 | ||||
|
249 | if (orientation == Qt::Horizontal) { | |||
|
250 | auto propertiesIt = COLUMN_PROPERTIES.find(section); | |||
|
251 | if (propertiesIt != COLUMN_PROPERTIES.cend()) { | |||
|
252 | // Role is either DisplayRole or SizeHintRole | |||
|
253 | return (role == Qt::DisplayRole) | |||
|
254 | ? QVariant{propertiesIt->m_Name} | |||
|
255 | : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}}; | |||
|
256 | } | |||
|
257 | else { | |||
|
258 | qWarning(LOG_VariableModel()) | |||
|
259 | << tr("Can't get header data (unknown column %1)").arg(section); | |||
|
260 | } | |||
|
261 | } | |||
|
262 | ||||
|
263 | return QVariant{}; | |||
|
264 | } | |||
|
265 | ||||
|
266 | Qt::ItemFlags VariableModel::flags(const QModelIndex &index) const | |||
|
267 | { | |||
|
268 | return QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; | |||
|
269 | } | |||
|
270 | ||||
|
271 | Qt::DropActions VariableModel::supportedDropActions() const | |||
|
272 | { | |||
|
273 | return Qt::CopyAction | Qt::MoveAction; | |||
|
274 | } | |||
|
275 | ||||
|
276 | Qt::DropActions VariableModel::supportedDragActions() const | |||
|
277 | { | |||
|
278 | return Qt::CopyAction | Qt::MoveAction; | |||
|
279 | } | |||
|
280 | ||||
|
281 | QStringList VariableModel::mimeTypes() const | |||
|
282 | { | |||
|
283 | return {MIME_TYPE_VARIABLE_LIST, MIME_TYPE_TIME_RANGE}; | |||
|
284 | } | |||
|
285 | ||||
|
286 | QMimeData *VariableModel::mimeData(const QModelIndexList &indexes) const | |||
|
287 | { | |||
|
288 | auto mimeData = new QMimeData; | |||
|
289 | ||||
|
290 | QList<std::shared_ptr<Variable> > variableList; | |||
|
291 | ||||
|
292 | ||||
|
293 | DateTimeRange firstTimeRange; | |||
|
294 | for (const auto &index : indexes) { | |||
|
295 | if (index.column() == 0) { // only the first column | |||
|
296 | auto variable = impl->m_Variables.at(index.row()); | |||
|
297 | if (variable.get() && index.isValid()) { | |||
|
298 | ||||
|
299 | if (variableList.isEmpty()) { | |||
|
300 | // Gets the range of the first variable | |||
|
301 | firstTimeRange = std::move(variable->range()); | |||
|
302 | } | |||
|
303 | ||||
|
304 | variableList << variable; | |||
|
305 | } | |||
|
306 | } | |||
|
307 | } | |||
|
308 | ||||
|
309 | auto variablesEncodedData = impl->m_VariableController->mimeDataForVariables(variableList); | |||
|
310 | mimeData->setData(MIME_TYPE_VARIABLE_LIST, variablesEncodedData); | |||
|
311 | ||||
|
312 | if (variableList.count() == 1) { | |||
|
313 | // No time range MIME data if multiple variables are dragged | |||
|
314 | auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange); | |||
|
315 | mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData); | |||
|
316 | } | |||
|
317 | ||||
|
318 | return mimeData; | |||
|
319 | } | |||
|
320 | ||||
|
321 | bool VariableModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, | |||
|
322 | int column, const QModelIndex &parent) const | |||
|
323 | { | |||
|
324 | // drop of a product | |||
|
325 | return data->hasFormat(MIME_TYPE_PRODUCT_LIST) | |||
|
326 | || (data->hasFormat(MIME_TYPE_TIME_RANGE) && parent.isValid() | |||
|
327 | && !data->hasFormat(MIME_TYPE_VARIABLE_LIST)); | |||
|
328 | } | |||
|
329 | ||||
|
330 | bool VariableModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, | |||
|
331 | const QModelIndex &parent) | |||
|
332 | { | |||
|
333 | auto dropDone = false; | |||
|
334 | ||||
|
335 | if (data->hasFormat(MIME_TYPE_PRODUCT_LIST)) { | |||
|
336 | ||||
|
337 | auto productList | |||
|
338 | = DataSourceController::productsDataForMimeData(data->data(MIME_TYPE_PRODUCT_LIST)); | |||
|
339 | ||||
|
340 | for (auto metaData : productList) { | |||
|
341 | emit requestVariable(metaData.toHash()); | |||
|
342 | } | |||
|
343 | ||||
|
344 | dropDone = true; | |||
|
345 | } | |||
|
346 | else if (data->hasFormat(MIME_TYPE_TIME_RANGE) && parent.isValid()) { | |||
|
347 | auto variable = this->variable(parent.row()); | |||
|
348 | auto range = TimeController::timeRangeForMimeData(data->data(MIME_TYPE_TIME_RANGE)); | |||
|
349 | ||||
|
350 | emit requestVariableRangeUpdate(variable, range); | |||
|
351 | ||||
|
352 | dropDone = true; | |||
|
353 | } | |||
|
354 | ||||
|
355 | return dropDone; | |||
|
356 | } | |||
|
357 | ||||
|
358 | void VariableModel::abortProgress(const QModelIndex &index) | |||
|
359 | { | |||
|
360 | if (auto variable = impl->m_Variables.at(index.row())) { | |||
|
361 | emit abortProgessRequested(variable); | |||
|
362 | } | |||
|
363 | } | |||
|
364 | ||||
|
365 | void VariableModel::onVariableUpdated() noexcept | |||
|
366 | { | |||
|
367 | // Finds variable that has been updated in the model | |||
|
368 | if (auto updatedVariable = dynamic_cast<Variable *>(sender())) { | |||
|
369 | auto updatedVariableIndex = impl->indexOfVariable(updatedVariable); | |||
|
370 | ||||
|
371 | if (updatedVariableIndex > -1) { | |||
|
372 | emit dataChanged(createIndex(updatedVariableIndex, 0), | |||
|
373 | createIndex(updatedVariableIndex, columnCount() - 1)); | |||
|
374 | } | |||
|
375 | } | |||
|
376 | } | |||
|
377 | ||||
|
378 | int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept | |||
|
379 | { | |||
|
380 | auto begin = std::cbegin(m_Variables); | |||
|
381 | auto end = std::cend(m_Variables); | |||
|
382 | auto it | |||
|
383 | = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; }); | |||
|
384 | ||||
|
385 | if (it != end) { | |||
|
386 | // Gets the index of the variable in the model: we assume here that views have the same | |||
|
387 | // order as the model | |||
|
388 | return std::distance(begin, it); | |||
|
389 | } | |||
|
390 | else { | |||
|
391 | return -1; | |||
|
392 | } | |||
|
393 | } |
@@ -0,0 +1,38 | |||||
|
1 | #include "Variable/VariableSynchronizationGroup.h" | |||
|
2 | ||||
|
3 | #include "Variable/Variable.h" | |||
|
4 | ||||
|
5 | ||||
|
6 | Q_LOGGING_CATEGORY(LOG_VariableSynchronizationGroup, "VariableSynchronizationGroup") | |||
|
7 | ||||
|
8 | struct VariableSynchronizationGroup::VariableSynchronizationGroupPrivate { | |||
|
9 | ||||
|
10 | std::set<QUuid> m_VariableIdSet; | |||
|
11 | }; | |||
|
12 | ||||
|
13 | ||||
|
14 | VariableSynchronizationGroup::VariableSynchronizationGroup(QObject *parent) | |||
|
15 | : QObject{parent}, impl{spimpl::make_unique_impl<VariableSynchronizationGroupPrivate>()} | |||
|
16 | { | |||
|
17 | } | |||
|
18 | ||||
|
19 | VariableSynchronizationGroup::VariableSynchronizationGroup(QUuid variable, QObject *parent) | |||
|
20 | :QObject{parent}, impl{spimpl::make_unique_impl<VariableSynchronizationGroupPrivate>()} | |||
|
21 | { | |||
|
22 | this->addVariable(variable); | |||
|
23 | } | |||
|
24 | ||||
|
25 | void VariableSynchronizationGroup::addVariable(QUuid vIdentifier) | |||
|
26 | { | |||
|
27 | impl->m_VariableIdSet.insert(vIdentifier); | |||
|
28 | } | |||
|
29 | ||||
|
30 | void VariableSynchronizationGroup::removeVariable(QUuid vIdentifier) | |||
|
31 | { | |||
|
32 | impl->m_VariableIdSet.erase(vIdentifier); | |||
|
33 | } | |||
|
34 | ||||
|
35 | const std::set<QUuid> &VariableSynchronizationGroup::getIds() const noexcept | |||
|
36 | { | |||
|
37 | return impl->m_VariableIdSet; | |||
|
38 | } |
@@ -0,0 +1,78 | |||||
|
1 | #include "Version.h" | |||
|
2 | ||||
|
3 | /*************************************************** | |||
|
4 | * DON'T CHANGE THIS FILE. AUTOGENERATED BY CMAKE. * | |||
|
5 | ***************************************************/ | |||
|
6 | ||||
|
7 | #include <QtCore/QDateTime> | |||
|
8 | #include <QtCore/QStringList> | |||
|
9 | ||||
|
10 | namespace sciqlop { | |||
|
11 | ||||
|
12 | const char *Version::VERSION_SUFFIX = ""; | |||
|
13 | ||||
|
14 | /** | |||
|
15 | * From the C99 standard: | |||
|
16 | * __DATE__: The date of translation of the preprocessing translation unit: | |||
|
17 | * a character string literal of the form "Mmm dd yyyy", where the names of | |||
|
18 | * the months are the same as those generated by the asctime function, and | |||
|
19 | * the first character of dd is a space character if the value is less than | |||
|
20 | * 10. If the date of translation is not available, an | |||
|
21 | * implementation-defined valid date shall be supplied. | |||
|
22 | */ | |||
|
23 | const char *Version::BUILD_DATE = __DATE__; | |||
|
24 | /** | |||
|
25 | * From the C99 standard: | |||
|
26 | * __TIME__: The time of translation of the preprocessing translation unit: | |||
|
27 | * a character string literal of the form "hh:mm:ss" as in the time | |||
|
28 | * generated by the asctime function. If the time of translation is not | |||
|
29 | * available, an implementation-defined valid time shall be supplied. | |||
|
30 | */ | |||
|
31 | const char *Version::BUILD_TIME = __TIME__; | |||
|
32 | ||||
|
33 | QDateTime Version::buildDateTime() | |||
|
34 | { | |||
|
35 | static QDateTime buildDateTime; | |||
|
36 | if (!buildDateTime.isValid()) { | |||
|
37 | // Convert BUILD_DATE to a QDate | |||
|
38 | // The __DATE__ macro return the month name with the asctime() function, | |||
|
39 | // which doesn't support localization, the month names returned are | |||
|
40 | // always the same. On the contrary, the "MMM" format on | |||
|
41 | // QDate::fromString() is localized, so this method can't be used to | |||
|
42 | // retrieve the month and we must manually do it instead. | |||
|
43 | QString buildDateStr = QString(BUILD_DATE); | |||
|
44 | QString buildMonthStr = buildDateStr.left(3); | |||
|
45 | QString buildDayAndYearStr = buildDateStr.mid(4).trimmed(); | |||
|
46 | ||||
|
47 | QDate buildDate = QDate::fromString(buildDayAndYearStr, "d yyyy"); | |||
|
48 | QStringList monthList = QStringList() << "Jan" | |||
|
49 | << "Feb" | |||
|
50 | << "Mar" | |||
|
51 | << "Apr" | |||
|
52 | << "May" | |||
|
53 | << "Jun" | |||
|
54 | << "Jul" | |||
|
55 | << "Aug" | |||
|
56 | << "Sep" | |||
|
57 | << "Oct" | |||
|
58 | << "Nov" | |||
|
59 | << "Dec"; | |||
|
60 | for (int i = 0; i < monthList.size(); ++i) { | |||
|
61 | if (buildMonthStr == monthList.at(i)) { | |||
|
62 | buildDate.setDate(buildDate.year(), i + 1, buildDate.day()); | |||
|
63 | break; | |||
|
64 | } | |||
|
65 | } | |||
|
66 | ||||
|
67 | // Convert BUILD_TIME to a QTime | |||
|
68 | QTime buildTime = QTime::fromString(BUILD_TIME, "hh:mm:ss"); | |||
|
69 | ||||
|
70 | // Set the buildDateTime | |||
|
71 | buildDateTime.setDate(buildDate); | |||
|
72 | buildDateTime.setTime(buildTime); | |||
|
73 | } | |||
|
74 | ||||
|
75 | return buildDateTime; | |||
|
76 | } | |||
|
77 | ||||
|
78 | } // namespace sciqlop |
@@ -0,0 +1,48 | |||||
|
1 | #include <Visualization/VisualizationController.h> | |||
|
2 | ||||
|
3 | #include <Variable/Variable.h> | |||
|
4 | ||||
|
5 | #include <QMutex> | |||
|
6 | #include <QThread> | |||
|
7 | ||||
|
8 | #include <QDir> | |||
|
9 | #include <QStandardPaths> | |||
|
10 | ||||
|
11 | Q_LOGGING_CATEGORY(LOG_VisualizationController, "VisualizationController") | |||
|
12 | ||||
|
13 | class VisualizationController::VisualizationControllerPrivate { | |||
|
14 | public: | |||
|
15 | QMutex m_WorkingMutex; | |||
|
16 | }; | |||
|
17 | ||||
|
18 | VisualizationController::VisualizationController(QObject *parent) | |||
|
19 | : impl{spimpl::make_unique_impl<VisualizationControllerPrivate>()} | |||
|
20 | { | |||
|
21 | qCDebug(LOG_VisualizationController()) << tr("VisualizationController construction") | |||
|
22 | << QThread::currentThread(); | |||
|
23 | } | |||
|
24 | ||||
|
25 | VisualizationController::~VisualizationController() | |||
|
26 | { | |||
|
27 | qCDebug(LOG_VisualizationController()) << tr("VisualizationController destruction") | |||
|
28 | << QThread::currentThread(); | |||
|
29 | this->waitForFinish(); | |||
|
30 | } | |||
|
31 | ||||
|
32 | void VisualizationController::initialize() | |||
|
33 | { | |||
|
34 | qCDebug(LOG_VisualizationController()) << tr("VisualizationController init") | |||
|
35 | << QThread::currentThread(); | |||
|
36 | impl->m_WorkingMutex.lock(); | |||
|
37 | qCDebug(LOG_VisualizationController()) << tr("VisualizationController init END"); | |||
|
38 | } | |||
|
39 | ||||
|
40 | void VisualizationController::finalize() | |||
|
41 | { | |||
|
42 | impl->m_WorkingMutex.unlock(); | |||
|
43 | } | |||
|
44 | ||||
|
45 | void VisualizationController::waitForFinish() | |||
|
46 | { | |||
|
47 | QMutexLocker locker{&impl->m_WorkingMutex}; | |||
|
48 | } |
@@ -0,0 +1,126 | |||||
|
1 | #include <pybind11/pybind11.h> | |||
|
2 | #include <pybind11/operators.h> | |||
|
3 | #include <pybind11/embed.h> | |||
|
4 | #include <pybind11/numpy.h> | |||
|
5 | #include <pybind11/chrono.h> | |||
|
6 | #include <pybind11/functional.h> | |||
|
7 | ||||
|
8 | #include <string> | |||
|
9 | #include <sstream> | |||
|
10 | ||||
|
11 | #include "pywrappers_common.h" | |||
|
12 | #include "CoreWrappers.h" | |||
|
13 | ||||
|
14 | #include <Data/DataSeriesType.h> | |||
|
15 | #include <Data/ScalarSeries.h> | |||
|
16 | #include <Data/VectorSeries.h> | |||
|
17 | #include <Data/Unit.h> | |||
|
18 | #include <Data/IDataProvider.h> | |||
|
19 | ||||
|
20 | #include <Variable/VariableController.h> | |||
|
21 | ||||
|
22 | #include <Time/TimeController.h> | |||
|
23 | ||||
|
24 | #include <Network/Downloader.h> | |||
|
25 | ||||
|
26 | ||||
|
27 | ||||
|
28 | namespace py = pybind11; | |||
|
29 | using namespace std::chrono; | |||
|
30 | ||||
|
31 | PYBIND11_MODULE(pysciqlopcore,m){ | |||
|
32 | ||||
|
33 | py::enum_<DataSeriesType>(m, "DataSeriesType") | |||
|
34 | .value("SCALAR", DataSeriesType::SCALAR) | |||
|
35 | .value("SPECTROGRAM", DataSeriesType::SPECTROGRAM) | |||
|
36 | .value("UNKNOWN", DataSeriesType::UNKNOWN) | |||
|
37 | .export_values(); | |||
|
38 | ||||
|
39 | py::class_<Unit>(m, "Unit") | |||
|
40 | .def_readwrite("name", &Unit::m_Name) | |||
|
41 | .def_readwrite("time_unit", &Unit::m_TimeUnit) | |||
|
42 | .def(py::self == py::self) | |||
|
43 | .def(py::self != py::self) | |||
|
44 | .def("__repr__",__repr__<Unit>); | |||
|
45 | ||||
|
46 | py::class_<Response>(m,"Response") | |||
|
47 | .def("status_code", &Response::status_code); | |||
|
48 | ||||
|
49 | py::class_<Downloader>(m,"Downloader") | |||
|
50 | .def_static("get", Downloader::get) | |||
|
51 | .def_static("getAsync", Downloader::getAsync) | |||
|
52 | .def_static("downloadFinished", Downloader::downloadFinished); | |||
|
53 | ||||
|
54 | py::class_<DataSeriesIteratorValue>(m,"DataSeriesIteratorValue") | |||
|
55 | .def_property_readonly("x", &DataSeriesIteratorValue::x) | |||
|
56 | .def("value", py::overload_cast<>(&DataSeriesIteratorValue::value, py::const_)) | |||
|
57 | .def("value", py::overload_cast<int>(&DataSeriesIteratorValue::value, py::const_)); | |||
|
58 | ||||
|
59 | py::class_<IDataSeries, std::shared_ptr<IDataSeries>>(m, "IDataSeries") | |||
|
60 | .def("nbPoints", &IDataSeries::nbPoints) | |||
|
61 | .def_property_readonly("xAxisUnit", &IDataSeries::xAxisUnit) | |||
|
62 | .def_property_readonly("yAxisUnit", &IDataSeries::yAxisUnit) | |||
|
63 | .def_property_readonly("valuesUnit", &IDataSeries::valuesUnit) | |||
|
64 | .def("__getitem__", [](IDataSeries& serie, int key) { | |||
|
65 | return *(serie.begin()+key); | |||
|
66 | }, py::is_operator()) | |||
|
67 | .def("__len__", &IDataSeries::nbPoints) | |||
|
68 | .def("__iter__", [](IDataSeries& serie) { | |||
|
69 | return py::make_iterator(serie.begin(), serie.end()); | |||
|
70 | }, py::keep_alive<0, 1>()) | |||
|
71 | .def("__repr__",__repr__<IDataSeries>); | |||
|
72 | ||||
|
73 | py::class_<ScalarSeries, std::shared_ptr<ScalarSeries>, IDataSeries>(m, "ScalarSeries") | |||
|
74 | .def("nbPoints", &ScalarSeries::nbPoints); | |||
|
75 | ||||
|
76 | py::class_<VectorSeries, std::shared_ptr<VectorSeries>, IDataSeries>(m, "VectorSeries") | |||
|
77 | .def("nbPoints", &VectorSeries::nbPoints); | |||
|
78 | ||||
|
79 | ||||
|
80 | py::class_<IDataProvider, std::shared_ptr<IDataProvider>>(m, "IDataProvider"); | |||
|
81 | ||||
|
82 | ||||
|
83 | py::class_<Variable,std::shared_ptr<Variable>>(m, "Variable") | |||
|
84 | .def(py::init<const QString&>()) | |||
|
85 | .def_property("name", &Variable::name, &Variable::setName) | |||
|
86 | .def_property("range", &Variable::range, &Variable::setRange) | |||
|
87 | .def_property("cacheRange", &Variable::cacheRange, &Variable::setCacheRange) | |||
|
88 | .def_property_readonly("nbPoints", &Variable::nbPoints) | |||
|
89 | .def_property_readonly("dataSeries", &Variable::dataSeries) | |||
|
90 | .def("__len__", [](Variable& variable) { | |||
|
91 | auto rng = variable.dataSeries()->xAxisRange(variable.range().m_TStart,variable.range().m_TEnd); | |||
|
92 | return std::distance(rng.first,rng.second); | |||
|
93 | }) | |||
|
94 | .def("__iter__", [](Variable& variable) { | |||
|
95 | auto rng = variable.dataSeries()->xAxisRange(variable.range().m_TStart,variable.range().m_TEnd); | |||
|
96 | return py::make_iterator(rng.first, rng.second); | |||
|
97 | }, py::keep_alive<0, 1>()) | |||
|
98 | .def("__getitem__", [](Variable& variable, int key) { | |||
|
99 | //insane and slow! | |||
|
100 | auto rng = variable.dataSeries()->xAxisRange(variable.range().m_TStart,variable.range().m_TEnd); | |||
|
101 | if(key<0) | |||
|
102 | return *(rng.second+key); | |||
|
103 | else | |||
|
104 | return *(rng.first+key); | |||
|
105 | }) | |||
|
106 | .def("__repr__",__repr__<Variable>); | |||
|
107 | ||||
|
108 | ||||
|
109 | py::class_<DateTimeRange>(m,"SqpRange") | |||
|
110 | .def("fromDateTime", &DateTimeRange::fromDateTime, py::return_value_policy::move) | |||
|
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) | |||
|
113 | { | |||
|
114 | double start_ = 0.001 * duration_cast<milliseconds>(start.time_since_epoch()).count(); | |||
|
115 | double stop_ = 0.001 * duration_cast<milliseconds>(stop.time_since_epoch()).count(); | |||
|
116 | return DateTimeRange{start_, stop_}; | |||
|
117 | })) | |||
|
118 | .def_property_readonly("start", [](const DateTimeRange& range){ | |||
|
119 | return system_clock::from_time_t(range.m_TStart); | |||
|
120 | }) | |||
|
121 | .def_property_readonly("stop", [](const DateTimeRange& range){ | |||
|
122 | return system_clock::from_time_t(range.m_TEnd); | |||
|
123 | }) | |||
|
124 | .def("__repr__", __repr__<DateTimeRange>); | |||
|
125 | ||||
|
126 | } |
@@ -0,0 +1,54 | |||||
|
1 | #pragma once | |||
|
2 | #include <pybind11/pybind11.h> | |||
|
3 | #include <pybind11/operators.h> | |||
|
4 | ||||
|
5 | #include <string> | |||
|
6 | #include <sstream> | |||
|
7 | #include "pywrappers_common.h" | |||
|
8 | #include "QtWrappers.h" | |||
|
9 | #include <Data/DataSeriesType.h> | |||
|
10 | #include <Data/Unit.h> | |||
|
11 | #include <Data/IDataSeries.h> | |||
|
12 | #include <Variable/Variable.h> | |||
|
13 | #include <Data/DateTimeRange.h> | |||
|
14 | ||||
|
15 | ||||
|
16 | std::ostream &operator <<(std::ostream& os, const Unit& u) | |||
|
17 | { | |||
|
18 | os << "=========================" << std::endl | |||
|
19 | << "Unit:" << std::endl | |||
|
20 | << " Name: " << u.m_Name << std::endl | |||
|
21 | << " Is_TimeUnit: " << u.m_TimeUnit << std::endl; | |||
|
22 | return os; | |||
|
23 | } | |||
|
24 | ||||
|
25 | ||||
|
26 | std::ostream &operator <<(std::ostream& os, const IDataSeries& ds) | |||
|
27 | { | |||
|
28 | os << "=========================" << std::endl | |||
|
29 | << "DataSerie:" << std::endl | |||
|
30 | << " Number of points:" << ds.nbPoints() << std::endl | |||
|
31 | << " X Axis Unit:" << std::endl << ds.xAxisUnit() << std::endl | |||
|
32 | << " Y Axis Unit:" << std::endl << ds.yAxisUnit()<< std::endl | |||
|
33 | << " Values Axis Unit:" << std::endl << ds.valuesUnit()<< std::endl; | |||
|
34 | return os; | |||
|
35 | } | |||
|
36 | ||||
|
37 | std::ostream &operator <<(std::ostream& os, const DateTimeRange& range) | |||
|
38 | { | |||
|
39 | os << "=========================" << std::endl | |||
|
40 | << "SqpRange:" << std::endl | |||
|
41 | << " Start date: " << DateUtils::dateTime(range.m_TStart).toString() << std::endl | |||
|
42 | << " Stop date: " << DateUtils::dateTime(range.m_TEnd).toString() << std::endl; | |||
|
43 | return os; | |||
|
44 | } | |||
|
45 | ||||
|
46 | std::ostream &operator <<(std::ostream& os, const Variable& variable) | |||
|
47 | { | |||
|
48 | os << "=========================" << std::endl | |||
|
49 | << "Variable:" << std::endl | |||
|
50 | << " Name: " << variable.name() << std::endl | |||
|
51 | << " range: " << std::endl << variable.range() << std::endl | |||
|
52 | << " cache range: " << std::endl << variable.cacheRange() << std::endl; | |||
|
53 | return os; | |||
|
54 | } |
@@ -0,0 +1,33 | |||||
|
1 | #include <QString> | |||
|
2 | #include <QUuid> | |||
|
3 | #include <QDate> | |||
|
4 | #include <QTime> | |||
|
5 | #include <string> | |||
|
6 | #include <sstream> | |||
|
7 | #include "pywrappers_common.h" | |||
|
8 | #include <pybind11/pybind11.h> | |||
|
9 | #include "QtWrappers.h" | |||
|
10 | ||||
|
11 | namespace py = pybind11; | |||
|
12 | ||||
|
13 | ||||
|
14 | ||||
|
15 | PYBIND11_MODULE(sciqlopqt,m){ | |||
|
16 | py::class_<QString>(m, "QString") | |||
|
17 | .def(py::init([](const std::string& value){return QString::fromStdString(value);})) | |||
|
18 | .def("__repr__", __repr__<QString>); | |||
|
19 | ||||
|
20 | py::class_<QUuid>(m,"QUuid") | |||
|
21 | .def(py::init([](){return QUuid::createUuid();})) | |||
|
22 | .def("__repr__",__repr__<QUuid>); | |||
|
23 | ||||
|
24 | py::class_<QDate>(m,"QDate") | |||
|
25 | .def(py::init<int,int,int>()); | |||
|
26 | ||||
|
27 | py::class_<QTime>(m,"QTime") | |||
|
28 | .def(py::init<int,int,int>()); | |||
|
29 | ||||
|
30 | ||||
|
31 | py::implicitly_convertible<std::string, QString>(); | |||
|
32 | } | |||
|
33 |
@@ -0,0 +1,19 | |||||
|
1 | #pragma once | |||
|
2 | #include <QString> | |||
|
3 | #include <QUuid> | |||
|
4 | #include <QDate> | |||
|
5 | #include <QTime> | |||
|
6 | #include <string> | |||
|
7 | #include <sstream> | |||
|
8 | ||||
|
9 | std::ostream &operator <<(std::ostream& os, const QString& qstr) | |||
|
10 | { | |||
|
11 | os << qstr.toStdString(); | |||
|
12 | return os; | |||
|
13 | } | |||
|
14 | ||||
|
15 | std::ostream &operator <<(std::ostream& os, const QUuid& uuid) | |||
|
16 | { | |||
|
17 | os << "QUuid:" << uuid.toString() << std::endl; | |||
|
18 | return os; | |||
|
19 | } |
@@ -0,0 +1,18 | |||||
|
1 | #ifndef PYWRAPPERS_COMMON_H | |||
|
2 | #define PYWRAPPERS_COMMON_H | |||
|
3 | #include <QString> | |||
|
4 | #include <string> | |||
|
5 | #include <sstream> | |||
|
6 | #include <QUuid> | |||
|
7 | #include <pybind11/pybind11.h> | |||
|
8 | ||||
|
9 | ||||
|
10 | template <typename T> | |||
|
11 | std::string __repr__(const T& obj) | |||
|
12 | { | |||
|
13 | std::stringstream sstr; | |||
|
14 | sstr << obj; | |||
|
15 | return sstr.str(); | |||
|
16 | } | |||
|
17 | ||||
|
18 | #endif //PYWRAPPERS_COMMON_H |
This diff has been collapsed as it changes many lines, (600 lines changed) Show them Hide them | |||||
@@ -0,0 +1,600 | |||||
|
1 | nan 2367273.000 1124463.250 605334.062 949495.438 558631.250 171724.562 97278.945 54197.648 14615.454 25975.436 115463.398 231692.016 260595.812 223407.406 141419.109 116846.844 99756.195 70274.383 46652.840 42645.891 61115.137 60539.559 48677.336 35179.809 23402.457 28590.951 29292.633 26239.006 25935.523 22649.926 16662.158 | |||
|
2 | nan 2422577.750 1131101.250 538548.938 925961.812 552279.938 201756.094 146998.859 60744.926 26670.064 30229.688 114544.547 244329.453 250743.203 195465.156 155628.562 116313.969 109107.953 81568.977 49208.387 49123.578 48385.910 37940.684 35995.691 37733.352 22095.961 33350.590 20205.867 21844.482 25246.188 27523.301 23830.967 | |||
|
3 | nan 2463700.250 1351991.500 520161.812 973399.938 555940.188 217292.094 100582.242 41614.551 40203.160 58969.812 96075.602 199354.641 260084.156 186499.375 124606.531 111169.383 102743.648 70549.508 57165.324 59018.402 41213.109 24721.998 39055.105 42080.016 30442.988 26745.469 23520.963 29016.867 23870.287 24103.113 20700.203 | |||
|
4 | nan 2525074.250 1413553.125 548721.438 942125.812 607173.875 242373.438 117053.055 60627.488 29120.523 32499.312 90196.445 148000.094 211521.953 184655.391 143882.203 93185.336 78552.055 58333.375 46191.062 33037.734 51874.797 43149.953 37301.945 38333.441 31303.502 33153.031 21325.572 19964.238 25682.100 19152.139 23458.359 | |||
|
5 | nan 2256211.500 1396373.750 584572.438 914332.938 628669.250 284402.750 118993.977 55335.125 22608.523 29873.318 85919.820 197937.406 259558.609 206938.109 151471.266 112563.352 95499.898 66763.344 52830.340 40706.859 35360.574 39490.473 42995.105 52022.559 43016.137 21589.270 31638.844 15280.637 27225.270 12852.585 22268.885 | |||
|
6 | nan 2405211.000 1432198.875 544279.562 912487.250 706930.438 269372.656 108567.617 51159.422 28009.086 20051.049 55950.590 192534.766 195718.312 173830.141 144043.078 125908.453 83549.227 67479.445 60376.773 48679.613 45474.648 20795.836 24972.039 30030.117 34988.414 20921.781 25183.045 29420.176 26815.398 25763.857 17020.131 | |||
|
7 | nan 2318568.250 1567757.250 608594.875 992330.938 693040.562 310568.062 119458.617 47365.938 35133.293 24635.949 71419.047 207065.234 290855.219 176470.859 151914.703 97923.008 99805.102 62659.039 51589.121 41729.508 31524.467 39487.160 34734.809 33717.527 37701.434 24549.520 17815.551 13179.841 24073.557 19829.027 36924.484 | |||
|
8 | nan 2327883.250 1572264.375 610527.938 968564.062 791135.188 358055.969 142583.219 63569.664 33017.059 14079.334 57818.074 164144.984 185229.859 178662.172 156333.562 104715.805 88329.055 54839.387 40609.562 43743.148 42431.379 35861.516 32950.168 40340.934 28266.838 34442.566 22405.891 18101.344 26492.033 16408.705 16102.952 | |||
|
9 | nan 2231563.000 1639660.750 696082.500 944114.625 792134.250 347232.281 148897.234 50644.941 26591.674 16286.129 41177.512 141648.578 232960.594 204804.656 147097.484 115821.648 76131.633 58264.449 77683.078 32322.037 37370.508 37030.266 33612.258 47882.461 28412.627 23246.445 19791.266 12173.932 17617.225 12615.890 19133.607 | |||
|
10 | nan 2237112.250 1446951.875 724860.938 908101.625 847380.812 384326.125 157451.812 73753.234 42102.324 25361.717 54202.523 151112.438 232353.484 180309.344 146179.719 112911.695 109887.500 79440.945 64896.801 46046.090 31311.324 41887.688 24814.389 22435.221 34634.441 24328.338 12601.593 11115.796 21145.986 16977.076 16069.781 | |||
|
11 | nan 2159640.250 1589956.500 760490.438 807664.438 768661.938 313351.062 136850.375 98390.750 32265.908 17538.477 26507.055 133801.469 177507.719 187623.812 162101.641 110703.180 103625.898 60705.047 74318.766 56540.109 38750.941 36644.391 28552.994 36025.586 19701.732 28855.850 23144.195 19804.105 18178.246 14807.034 16815.023 | |||
|
12 | nan 2088978.750 1437443.625 724145.562 814043.062 833867.062 350415.469 170360.844 77882.633 35495.254 18179.232 42373.383 140690.984 220115.266 170086.266 175287.859 117389.617 65121.488 54672.863 78444.805 46972.031 25359.113 30545.744 31449.664 28412.107 23713.402 19369.727 25859.174 23923.148 18024.461 20907.219 21803.945 | |||
|
13 | nan 1947685.125 1352270.500 716528.250 894990.062 829693.250 426800.500 197640.766 77934.781 31005.869 13779.767 47375.934 131878.562 170386.953 152312.188 148965.250 123847.117 80954.461 52315.516 35012.031 47600.023 31517.824 32652.574 24890.906 26924.424 38454.730 14819.140 14980.423 14661.859 9975.334 15040.319 12264.437 | |||
|
14 | nan 1951270.500 1424481.250 761638.500 934648.250 805357.188 443148.875 161547.109 88709.109 37203.680 32421.707 56489.562 131096.922 210154.188 150494.016 106466.969 113051.883 73493.898 73594.312 76671.781 50510.301 42503.020 19808.977 31741.037 30205.256 26793.908 28125.650 17339.848 30193.131 8638.891 14795.328 11283.676 | |||
|
15 | nan 2218344.000 1614095.500 831611.000 843168.188 832652.062 411670.531 179459.359 81452.359 37734.859 29475.264 38281.664 136801.766 206073.141 191655.406 121239.156 101949.656 73000.430 71836.672 54534.016 44514.641 28209.119 30890.314 25771.389 35960.984 37785.215 25666.492 23101.289 12478.665 24115.119 13066.941 14634.816 | |||
|
16 | nan 1888798.500 1430126.875 910922.375 759764.438 802868.062 401356.469 156704.109 80444.125 38276.734 21807.863 48174.785 94984.656 198263.109 206447.609 133511.906 128630.398 55506.527 93960.219 50203.309 47357.766 38264.840 33174.387 31130.676 21668.291 26576.844 26522.375 18213.303 22411.740 17420.910 23092.359 10520.488 | |||
|
17 | nan 1878304.125 1296965.500 700479.500 827198.812 859147.938 446786.094 233487.250 106249.547 34124.078 31919.861 29350.576 84830.289 166102.156 196453.562 117701.406 110752.547 87182.383 71165.367 60178.621 49356.766 31360.986 25331.938 24063.180 40553.402 17266.227 42173.262 15084.624 23788.234 6634.067 8008.962 14223.770 | |||
|
18 | nan 2036296.000 1309512.000 738226.812 840537.625 913745.438 431757.312 224089.188 97181.148 37837.254 26289.770 25962.439 64587.750 178398.188 170375.547 106879.281 95621.969 95147.031 56260.316 50603.047 45526.738 37819.141 25305.607 19695.299 29592.656 25785.867 15180.081 16812.549 26756.914 12253.069 23936.506 10124.329 | |||
|
19 | nan 2005232.750 1355763.500 748488.375 911421.188 890152.562 476476.906 205125.234 103422.469 34255.434 29684.711 27854.436 73527.445 159400.859 165075.438 122931.898 105524.703 92661.031 76121.367 50911.289 39446.539 29036.900 36910.426 27837.670 21292.658 30648.443 19791.234 19161.865 18446.109 11623.621 8061.365 3364.245 | |||
|
20 | nan 2036248.750 1370985.625 829171.375 730216.562 976354.375 557984.375 238805.297 95531.219 31057.805 38493.445 31578.594 47120.652 104800.922 168727.688 147900.062 89470.297 63947.375 65061.828 72320.586 35839.340 28895.689 26382.344 30662.248 29974.545 19590.422 19819.441 12521.182 17222.852 7776.023 11080.270 16582.514 | |||
|
21 | nan 1854826.875 1336922.625 800885.062 819455.938 968533.625 521668.625 247728.344 98644.781 60611.996 21196.701 18155.830 73271.000 142955.859 153612.062 117850.406 112156.625 80905.781 60848.375 41312.777 43233.309 31006.674 28532.492 21826.930 26991.844 11220.285 25021.289 21211.561 17817.154 9836.011 14883.497 15601.438 | |||
|
22 | nan 1913749.250 1252928.375 854204.062 660047.125 1031203.438 522602.094 272209.938 125648.367 68952.547 25226.744 19401.455 85712.070 122085.281 150276.234 118788.047 83855.672 65243.059 59840.309 65289.852 61555.723 27539.939 23650.867 14536.597 28425.154 35375.547 19150.861 19722.529 15070.343 8143.148 39029.262 16940.652 | |||
|
23 | nan 1961721.125 1282066.125 794605.000 794347.438 986607.375 571705.250 240067.766 121068.281 45813.977 29688.264 26368.355 54516.039 115209.227 171925.594 109822.367 65253.246 77325.570 45254.805 52105.164 42991.051 43470.422 22109.107 27165.832 21737.471 19535.383 14398.723 29151.586 24774.406 10486.038 19413.561 9462.326 | |||
|
24 | nan 1908573.500 1356527.500 878851.750 863427.250 1008319.188 629594.062 252074.703 135531.516 36853.406 25874.908 18688.555 40288.230 98873.758 126258.656 124231.250 90237.742 77347.406 86330.250 43028.629 30422.818 39314.688 24006.238 32966.477 15309.988 19564.002 16297.312 23406.477 8547.728 12683.457 6446.491 12545.426 | |||
|
25 | nan 2022319.500 1328720.125 825504.750 747311.562 985132.750 566903.625 293692.469 142736.312 66756.844 51536.062 34507.391 37106.605 85987.406 130377.250 95744.375 76714.789 81354.625 58968.824 45261.746 43389.703 30571.119 34791.738 26257.748 33332.422 15052.472 19137.594 21306.227 21353.195 13727.316 14326.437 22678.461 | |||
|
26 | nan 1992378.125 1356892.375 882226.625 905021.000 959093.625 630375.250 300734.469 141096.812 70775.719 41677.387 13422.943 46524.848 95842.617 117292.523 140609.641 79756.281 86269.695 73219.141 37123.824 26810.105 28594.436 24233.926 20455.518 20350.182 25284.031 16066.415 13230.562 14007.919 9645.735 9532.373 13682.887 | |||
|
27 | nan 1889643.875 1286280.500 881985.000 718755.688 965112.375 585206.062 271437.531 151977.734 67986.883 65873.469 18681.619 48765.223 83418.430 120027.977 85750.180 82817.078 80260.078 57450.340 53618.223 42440.953 27252.732 30284.207 33588.078 20248.152 21940.961 20897.961 18447.576 13734.146 13207.247 17154.826 13234.104 | |||
|
28 | nan 1961231.500 1304677.875 940278.000 824689.625 973146.188 617536.438 278786.781 136880.344 74938.133 21368.258 37145.113 28025.137 92087.031 137325.188 101454.898 80916.938 65363.078 49138.559 40796.191 35042.746 33751.758 13158.266 31686.342 15138.844 17452.182 14919.113 6783.307 19261.158 19251.404 19797.434 11587.604 | |||
|
29 | nan 1793520.000 1277192.500 980381.375 941661.625 1055635.875 592191.875 287281.688 135660.422 67149.156 43800.453 19609.238 50904.637 99462.656 122615.727 114060.945 95618.578 91147.016 66326.258 46485.734 35069.797 28491.920 28898.582 29738.273 28331.236 25764.320 12488.241 18649.711 6260.947 9051.464 2893.012 5939.744 | |||
|
30 | nan 2019399.250 1335581.750 906105.625 917968.375 1051092.125 670490.188 301860.375 145778.391 65762.570 29588.670 33545.277 47920.090 86076.023 113316.547 122335.406 71488.188 59548.859 44726.418 61063.453 43911.301 33318.047 28760.613 24533.250 18836.180 17893.373 11529.969 38593.691 5286.197 12237.934 8776.556 12552.207 | |||
|
31 | nan 2157296.000 1459212.875 929084.750 853437.438 951457.375 658414.688 291697.938 134565.797 40535.121 26402.775 33461.605 64090.188 96931.375 123649.078 107828.531 112001.969 74695.469 63299.062 64488.875 35457.062 36000.039 39197.746 34412.797 29639.201 31635.332 20806.389 19678.496 19309.898 29129.051 31413.930 14691.844 | |||
|
32 | nan 2043905.875 1407164.500 962280.250 841953.562 960359.000 662083.875 288672.219 157999.938 40284.059 44864.766 15934.362 57477.059 121449.672 91880.562 103493.375 68781.461 88219.094 67103.492 81965.125 59654.090 42916.160 62845.578 26969.107 40484.426 38701.152 30115.189 19346.131 31233.811 22956.711 12391.587 10027.432 | |||
|
33 | nan 1960438.125 1352008.500 928001.750 774466.375 1049215.000 613558.375 371048.625 153682.031 46066.840 33166.160 14508.171 49806.234 97588.172 118534.242 102386.180 65005.527 76633.555 92296.195 61475.477 60122.879 38488.512 33916.781 33919.703 38187.641 28888.570 23910.662 35598.176 32803.574 50541.566 23638.666 19201.344 | |||
|
34 | nan 2001427.250 1389642.250 949657.812 850322.375 1011181.188 704181.938 337808.719 130352.820 70868.094 34681.141 28426.586 42587.184 81877.805 78676.664 131175.938 71125.133 62512.922 60339.023 57112.648 39730.949 57522.203 53100.648 40704.719 45553.047 49263.660 28629.818 34607.312 24042.600 15877.534 21799.084 13800.713 | |||
|
35 | nan 2123296.250 1282430.500 1032341.812 864813.812 1025054.375 750304.562 377625.281 148277.516 66633.000 39631.016 34378.234 52976.891 49237.816 125649.508 140337.766 69401.133 51066.449 59519.066 45796.562 45053.438 41309.176 48717.227 24782.773 19769.445 28877.408 25720.523 27297.799 34363.613 26393.164 18009.750 10347.437 | |||
|
36 | nan 1966103.625 1356617.500 889828.750 816012.938 1007507.438 749116.562 385872.781 151962.953 95136.695 33120.859 12025.038 53240.902 58415.688 118644.273 95972.648 101605.883 30924.631 33245.500 36916.062 59871.078 31536.701 37216.414 32376.936 44200.090 32726.768 33428.887 24159.207 24300.332 21302.139 23009.287 11092.485 | |||
|
37 | nan 2026956.000 1499082.875 1023654.812 857667.375 1069121.125 671992.062 353538.125 182597.859 92581.086 16913.598 33457.348 47884.703 90415.070 104327.094 74123.055 68694.633 61443.062 50572.641 36504.203 38414.367 46986.734 38750.941 42599.188 31855.811 37463.656 25800.787 22094.160 29513.832 27318.744 23781.598 13789.834 | |||
|
38 | nan 2020679.250 1304119.375 993476.750 870372.812 1011484.188 688236.562 364046.531 157770.766 64627.066 35993.176 27665.148 51793.016 93993.227 110193.031 97171.250 69880.195 60886.648 69949.180 53123.766 32551.900 48025.164 53612.891 35373.121 39259.184 34458.027 27251.586 24048.414 24023.449 23333.793 9557.129 11401.827 | |||
|
39 | nan 2089778.375 1470628.875 998781.562 931868.188 926446.625 740756.938 436657.125 178754.266 68426.633 46010.609 40936.473 58174.859 50120.664 116484.898 108493.172 59425.289 63958.715 40220.027 43297.039 33243.996 54927.840 44205.125 36967.938 41365.305 18532.121 18704.355 34165.008 30458.342 30908.502 16338.566 10798.084 | |||
|
40 | nan 1928284.000 1361050.000 993765.000 875096.562 828665.375 799489.188 382332.000 181673.609 81898.898 40122.941 41135.395 40776.012 68722.578 90948.617 104257.898 72040.492 51552.949 35830.684 26355.439 45886.703 23431.752 36319.609 50188.359 25956.211 30001.654 21305.299 23210.611 26287.162 34091.551 32026.994 9418.091 | |||
|
41 | nan 2053886.125 1329425.125 1034424.938 768720.938 918037.812 784851.625 448262.281 177481.641 75076.445 46571.246 29062.283 61109.922 73259.594 89151.875 94885.648 72959.781 59880.750 46335.496 41518.309 30213.738 35320.785 22079.275 18391.738 22359.117 12899.137 18648.826 9617.816 13159.619 22532.781 10049.246 10707.566 | |||
|
42 | nan 1886924.125 1462093.875 971070.562 836705.938 846619.812 764999.062 448326.125 186449.297 93786.062 44330.414 55613.734 40314.246 55257.965 96437.383 128734.867 85408.914 54846.402 39619.410 42811.215 33769.289 33272.496 31525.314 29469.867 20585.877 19942.305 19547.641 17854.795 20291.520 20854.508 9562.719 9295.973 | |||
|
43 | nan 1937009.625 1391639.875 996952.438 846049.000 909661.812 870804.750 427000.406 144342.672 90840.016 43229.797 31542.324 34369.895 70377.594 82415.102 79435.375 78728.695 42335.125 42685.629 66457.812 19183.484 28225.398 40696.859 31923.514 33515.223 30852.230 28933.000 24836.695 29131.852 19074.434 21523.764 19276.008 | |||
|
44 | nan 1925796.375 1499349.500 930307.000 775772.562 914125.750 726969.438 397452.781 204917.438 112678.469 39743.211 46962.441 47465.336 56183.148 71338.133 85033.094 79313.828 66496.414 60878.723 62416.004 58371.785 54981.812 30454.799 33105.453 31699.549 23994.439 30178.770 23974.586 21449.828 12610.879 13031.241 19201.523 | |||
|
45 | nan 1993081.875 1445510.750 933125.062 784652.250 964650.938 713359.562 442746.469 178987.188 76384.469 51981.441 31350.352 26742.242 85503.586 77370.820 98977.102 48708.574 44815.125 67203.711 58973.465 55835.875 41607.824 42186.543 57157.590 46899.953 23983.301 20787.916 31260.180 19487.400 24943.248 27727.164 13860.851 | |||
|
46 | nan 1929036.750 1527957.125 1028152.812 848805.062 854584.625 779955.188 433243.781 156023.672 70210.617 43480.047 32081.293 29788.502 45326.340 92618.617 87333.805 67865.133 73528.367 35145.113 26916.568 27997.471 17806.248 21615.395 25823.457 16229.006 21505.250 10279.625 3853.153 18154.326 20732.799 12852.230 18722.654 | |||
|
47 | nan 2003110.875 1402431.125 885685.188 868478.062 897656.938 770370.438 445684.969 209169.344 74135.617 40261.301 36820.508 33048.707 62005.441 82824.945 78002.359 108336.570 60012.598 32139.188 24682.656 27350.180 16597.664 21628.596 18539.020 15535.837 22927.312 18372.623 19716.768 10550.970 20262.740 13944.943 17752.451 | |||
|
48 | nan 2026987.500 1446152.125 884275.750 874416.938 900398.562 723227.438 479688.031 213662.938 110109.570 54926.441 12451.358 29729.682 73726.680 106440.750 66711.219 65506.586 65109.453 45699.012 42340.520 36561.277 28383.906 16875.143 10157.482 8939.509 24875.963 18916.146 17074.939 12633.675 11241.134 13350.156 10972.732 | |||
|
49 | nan 1980893.125 1434583.125 898213.438 775990.188 870349.938 807592.438 455821.500 225586.312 74302.789 47827.953 25828.574 28872.943 71727.969 95976.703 111625.406 91445.094 68692.695 47304.289 50055.871 36013.883 21832.932 26026.969 28358.701 15982.234 9723.867 18387.143 25026.742 13480.347 14532.816 3605.021 11083.049 | |||
|
50 | nan 1952296.000 1462476.250 978493.062 894112.188 920463.438 713905.375 485713.906 220533.094 72606.773 64742.363 28465.588 49493.441 57908.027 61853.766 86063.781 45757.363 72353.273 46105.430 33252.492 18462.133 27338.025 28513.898 26821.373 26059.963 11010.688 21141.420 16362.781 17853.998 26131.793 8137.598 11822.960 | |||
|
51 | nan 1825903.625 1420257.250 849505.938 779326.562 843900.062 768747.250 461757.531 212248.109 98618.633 51402.848 26182.055 48274.523 70524.688 127185.406 124576.750 70646.570 63906.461 49209.809 39234.215 45112.934 34283.289 18009.104 27680.264 20175.779 28179.824 25706.020 16564.279 33182.105 9401.891 11207.892 15319.368 | |||
|
52 | nan 1847602.375 1568724.750 926388.000 807855.562 891227.562 740886.125 413326.812 183543.672 106627.797 49381.164 39398.156 47840.715 68718.078 72517.148 93529.773 74212.094 56616.789 42338.629 36107.613 20682.018 39272.816 17461.092 10977.689 12796.465 18014.924 12885.075 10951.532 11047.954 7375.930 17242.664 11011.046 | |||
|
53 | nan 1846332.375 1522968.625 864770.438 836462.812 834484.625 792368.625 416279.469 268493.281 85465.570 52531.965 31902.475 31242.977 74649.328 99891.922 107701.977 50344.227 51536.387 44833.871 45431.238 30363.344 19929.688 16330.931 9397.693 10491.346 11206.929 17329.285 16819.668 17348.461 11985.531 9650.864 9006.053 | |||
|
54 | nan 1887623.625 1510570.875 1033199.438 686350.000 737604.938 724395.000 521800.625 268605.219 84169.508 52504.453 43685.453 29419.904 33000.797 96778.305 67826.234 59666.199 67560.805 43445.422 32180.068 25613.936 19370.312 20822.025 30252.855 25796.070 8183.030 15748.412 6075.366 11960.419 14227.703 8565.939 5399.175 | |||
|
55 | nan 1846647.500 1670000.375 989315.938 825167.750 804169.812 749907.500 436180.312 237979.188 98494.102 60731.902 41267.875 25998.182 42794.039 75166.797 91411.180 74139.531 68714.281 33390.586 29208.268 17536.996 24011.836 21537.367 24181.742 16832.529 23184.367 18245.398 18685.238 10132.159 9220.987 8683.858 12131.124 | |||
|
56 | nan 1918737.250 1522895.875 986108.938 762971.938 902689.375 818800.812 448675.594 249095.234 110073.867 51308.004 26310.176 46322.531 38297.117 99495.695 94190.055 74639.469 65877.203 46540.762 26573.023 26392.475 19045.814 17261.492 21653.217 28520.283 8938.194 15934.843 18790.154 48203.949 13188.028 15168.572 7852.000 | |||
|
57 | nan 1752037.625 1501434.375 959113.562 768704.812 798402.625 717478.250 440198.969 252691.109 124620.219 55411.215 23578.846 53116.738 58418.691 88971.273 75648.008 78710.047 65321.164 31729.125 37962.020 20163.277 27708.695 30029.551 32685.887 12286.750 18418.268 27172.877 24466.221 15517.746 16328.490 8841.533 7362.631 | |||
|
58 | nan 1853869.500 1533616.000 1015161.562 696079.312 854556.562 803073.375 519110.969 210199.594 107556.594 76839.070 40644.410 29833.676 72197.227 63259.164 79583.555 69878.469 68661.422 53074.285 39226.816 29317.686 24022.154 39343.285 13326.835 25847.682 23076.330 13750.506 19084.602 14783.751 22179.217 9970.032 10911.473 | |||
|
59 | nan 1810484.500 1659155.625 943847.938 649853.375 778350.562 690730.312 474651.469 255689.516 114513.367 48321.371 37315.891 39284.258 45988.352 107773.547 77281.805 64312.188 47340.316 51651.160 37854.703 32841.113 25488.773 23438.547 19802.520 14774.606 18773.457 16238.347 10918.835 16156.931 13045.521 10127.652 12697.145 | |||
|
60 | nan 1638367.875 1652006.125 1022965.812 736401.250 732758.500 619981.562 554643.000 245718.859 122064.719 43168.707 42714.125 33249.785 83622.320 78410.844 55059.516 73200.680 56603.137 45806.383 35949.461 23366.441 37070.816 22382.324 23828.861 18165.398 13534.340 9616.490 17176.652 12179.053 4410.424 15408.446 10484.301 | |||
|
61 | nan 1677436.125 1657593.125 1159197.875 695630.188 793709.625 729582.000 515382.594 246432.406 87122.859 51506.125 26099.125 28030.107 22108.182 48444.234 59061.051 72371.500 52185.574 38161.402 32258.225 31493.914 30753.689 24767.344 33248.594 29654.232 17870.277 22405.867 23944.676 26569.682 12193.749 7841.388 14434.412 | |||
|
62 | nan 1515689.375 1648216.750 1246238.625 797450.562 703197.750 724627.125 594344.750 308760.531 77316.086 42533.879 16166.118 10039.837 5491.377 16335.496 21674.799 42883.551 31350.533 52142.191 31303.752 33781.359 22370.049 22046.840 27316.400 28116.674 22504.301 20268.418 18074.305 26046.900 38023.535 22924.025 39135.688 | |||
|
63 | nan 1554406.500 1717581.500 1167712.625 779271.750 754884.688 681493.250 572837.188 342902.656 122814.672 37595.023 16877.609 16536.311 1297.936 5682.823 7222.178 2435.430 13837.054 7937.786 14005.575 8746.640 28344.312 30153.781 50700.496 40193.582 45341.117 55171.660 58088.922 60833.074 95713.781 69413.781 82878.367 | |||
|
64 | nan 1600948.875 1659736.000 1131049.250 675721.562 684622.250 666073.562 589692.562 312468.438 158182.516 48920.441 25622.158 2500.781 6306.678 4933.032 5832.843 10935.240 3646.790 11651.818 14225.194 11725.039 12081.334 18318.492 22124.352 18830.014 23223.170 37166.984 34438.613 77802.477 69955.992 83406.875 116148.758 | |||
|
65 | nan 1473290.000 1733282.375 1149439.125 742847.938 746355.188 752270.750 547945.000 292180.844 105888.930 37107.590 14688.881 7731.734 14475.272 14826.769 15969.866 26825.494 35356.016 29245.619 30573.748 28541.199 47265.871 38110.801 29374.213 32491.332 18463.102 18703.785 19536.221 31984.051 19483.076 33380.789 5836.036 | |||
|
66 | nan 1318765.125 1640408.500 1251877.875 719958.188 643632.688 584201.562 563681.375 255261.047 103413.297 30554.148 15173.281 7665.527 7388.036 13332.840 20160.619 52117.273 55914.574 42508.660 23582.520 20986.830 33351.645 28818.662 15927.169 26522.742 34012.480 18029.264 26008.801 44594.016 33683.770 32171.400 29981.986 | |||
|
67 | nan 1044845.250 1516997.625 1253120.750 726083.062 655790.938 713210.750 507463.031 305704.969 118862.773 42076.754 14435.497 9229.783 15260.975 18530.676 25454.387 15869.725 30238.174 49710.609 31375.199 18407.045 48295.023 22971.283 33564.801 32237.336 29929.924 26201.314 24785.414 38241.758 42197.250 40183.922 27001.248 | |||
|
68 | nan 1030252.812 1423476.750 1299638.500 724140.375 606194.688 599558.688 449309.125 267891.719 135065.828 22726.189 7212.905 15484.138 8245.324 4978.947 6816.420 3786.178 13529.726 17785.965 8023.780 4384.377 10303.590 20899.961 15772.278 12711.803 20957.074 13310.303 28129.414 22839.123 15891.098 21432.102 27924.205 | |||
|
69 | nan 876732.250 1458354.500 1179068.875 742961.312 509954.188 492147.594 512597.125 357395.969 130325.523 43644.742 24428.350 5813.458 5208.080 4451.804 12344.656 18010.287 23648.066 14541.524 12560.281 28706.219 24855.613 28048.875 36709.527 27481.932 40881.852 35999.578 53711.352 64292.434 76186.438 103831.625 101412.023 | |||
|
70 | nan 811526.375 1304184.125 1195976.500 753904.125 495109.094 555249.062 591749.562 303389.375 126939.328 34943.672 8529.920 13396.322 17823.625 13166.885 17932.564 23238.811 43423.957 38967.074 27976.564 29025.654 21656.467 17657.182 25236.875 20517.459 23255.449 18506.029 12514.043 21332.705 10260.397 10071.277 12987.348 | |||
|
71 | nan 683545.250 1165994.500 1185156.375 720375.125 611296.438 549998.062 444017.219 245003.688 129381.742 55977.789 27607.404 26664.764 34731.387 35647.211 44259.496 57599.652 39635.242 34658.246 37243.320 29508.318 22565.619 22903.029 30454.393 31744.230 14840.612 9487.935 6025.867 1930.676 9331.771 6104.003 10413.471 | |||
|
72 | nan 619791.562 1118914.000 1298263.625 722172.938 428026.625 527011.250 448183.531 299495.406 105420.594 52356.902 25421.963 22641.029 31505.721 29896.324 60414.516 61837.602 40829.848 38393.145 12468.190 18674.508 24376.326 20116.773 4788.952 18150.170 8054.593 23924.830 24876.721 14347.098 13439.095 14773.171 2826.904 | |||
|
73 | nan 639682.688 1068305.500 1143019.125 681035.062 458077.125 563283.938 425312.312 284330.438 107004.328 68885.727 35447.051 35816.590 25616.268 33958.367 35916.262 34912.867 41465.676 30270.143 29596.195 24966.967 23069.383 24322.570 13439.581 23636.133 22800.223 16116.162 11581.355 15795.741 3454.571 8510.837 12066.845 | |||
|
74 | nan 610667.375 981463.250 1178371.125 757790.688 436890.812 504035.688 411689.312 287728.969 136989.094 43251.527 23542.521 10938.085 20223.752 25356.861 40532.547 34655.441 37529.535 44900.156 32006.221 31993.758 19915.643 17568.232 13480.000 18078.904 16829.873 19211.977 15298.278 8321.124 5468.084 17725.258 10315.735 | |||
|
75 | nan 599676.562 976263.375 1304130.500 803263.188 504591.406 487526.969 386078.375 286156.281 134613.109 50262.000 21807.814 6219.871 7382.472 27318.145 54445.199 41912.258 31414.387 50847.816 38324.707 39411.207 28501.643 13691.078 19439.943 12495.129 11518.583 14132.446 11453.465 11121.075 10073.313 8175.742 5778.964 | |||
|
76 | nan 619113.938 956931.375 1177842.250 783858.062 476859.875 424738.688 456799.875 299898.969 143229.391 57188.188 26728.719 27770.398 18616.221 26798.131 44051.527 51849.074 34313.098 35656.387 20607.896 21112.674 15427.568 12496.301 20025.939 16196.531 13684.233 22513.359 17597.053 16619.156 6409.066 12624.656 11591.966 | |||
|
77 | nan 662062.875 975570.750 1142196.875 753644.562 544187.750 505756.188 456846.188 275406.219 159450.406 49687.828 41124.496 20230.768 15698.702 19948.549 31686.592 56765.965 21180.727 30573.625 28493.500 27959.438 21045.326 12572.241 34141.227 13104.146 9935.963 21787.764 23206.949 4873.439 10140.228 7130.906 7584.705 | |||
|
78 | nan 664770.562 890039.750 1264976.875 882228.750 533644.562 470065.688 469364.375 242171.094 176537.141 79230.062 28004.625 6297.970 18546.133 20955.895 29365.752 73810.008 60707.547 34373.391 27762.061 34620.695 31668.188 13560.845 14377.662 16241.932 11790.332 13433.246 10834.726 12007.037 24825.406 17280.105 13298.254 | |||
|
79 | nan 656703.938 931430.438 1353822.250 998405.250 548524.062 490364.312 445123.812 307599.125 159970.312 51069.676 21269.264 8667.284 16481.111 6826.874 21683.836 23049.389 75815.430 47559.688 21689.326 36223.883 33034.109 31655.658 28693.168 22017.951 14933.903 18737.289 13039.810 10784.212 6227.836 5271.357 25889.898 | |||
|
80 | nan 670495.312 1007752.812 1212480.125 931306.938 600269.938 514291.000 449235.875 323095.188 173010.047 73254.484 30858.857 14350.388 7646.188 4864.473 8719.038 15456.403 16727.600 18173.289 10418.240 32966.949 22000.564 41174.633 26149.080 8864.894 20063.709 9557.312 22589.691 28609.764 18136.320 9418.954 24450.398 | |||
|
81 | nan 675088.062 807560.438 1100621.875 1081659.875 628874.375 459157.375 422154.500 315317.281 150679.844 88532.523 33365.320 15302.327 6513.050 1448.063 10536.957 14173.345 11951.138 5491.798 25140.445 32712.924 16993.498 29995.262 21471.076 30570.162 30468.201 40878.488 64904.973 49547.809 46561.816 54752.973 75208.523 | |||
|
82 | nan 723371.062 784055.375 1279996.000 1029103.438 531069.438 422702.375 450252.969 278747.125 199229.438 71857.648 21295.264 15207.944 5014.372 5258.617 11262.480 19784.117 16470.221 22419.787 24730.639 19056.736 19101.232 10989.134 17379.871 10916.880 22444.820 10793.407 11925.983 13052.613 5815.229 6577.487 8942.959 | |||
|
83 | nan 750147.688 786720.438 1180090.875 1020610.375 542666.750 455033.531 424546.125 318848.219 189149.047 90019.906 21009.674 10837.814 4669.566 6334.588 12461.544 30593.592 16251.000 25765.096 29622.342 38618.168 18847.129 20730.586 9174.601 6765.782 5265.804 8632.626 8414.104 14199.382 7900.723 5661.849 4257.960 | |||
|
84 | nan 714524.625 781070.062 1056070.125 1053692.875 666259.312 438523.906 385810.219 361912.500 140177.797 70892.906 31403.227 18942.744 5024.254 0.000 8707.456 24774.701 39866.641 24230.424 12602.879 30263.076 20767.877 15210.497 14094.163 10396.350 24671.000 15535.997 16396.818 5567.657 7561.461 12086.459 6541.355 | |||
|
85 | nan 640444.750 707438.750 1044966.625 984798.438 544429.125 443524.406 399400.312 292091.625 173050.406 73491.773 23748.049 8889.603 9401.926 4811.105 27740.506 23648.076 11720.159 14357.725 30837.580 15041.375 17869.352 19218.012 18934.705 15018.710 20577.420 20710.973 16318.812 8066.795 9303.663 11692.810 9781.730 | |||
|
86 | nan 646131.375 697941.062 933592.750 1014055.750 576940.500 479134.031 362549.688 310362.219 172812.062 70426.961 29318.551 13814.381 4992.495 15109.496 13492.379 30644.580 27165.883 35209.473 36809.500 15781.850 17335.379 18055.820 18185.330 19283.330 8341.803 2755.048 11245.749 14053.781 8137.356 11852.145 4779.338 | |||
|
87 | nan 643117.875 696414.125 795674.625 982717.438 592684.688 388603.719 357634.094 326445.531 142200.719 77046.625 26166.525 11345.194 8817.586 19005.348 15056.663 28081.219 28247.412 25662.258 30584.475 35724.500 16915.898 12381.193 18567.498 6382.614 8669.240 12723.812 4357.511 6350.117 19008.816 12647.988 6669.713 | |||
|
88 | nan 581107.750 598952.188 868566.938 927345.438 612121.438 381229.219 391263.031 306654.781 161896.625 88923.523 23299.611 6457.689 24868.781 15596.645 16499.887 31709.145 31548.748 40275.500 48047.535 18317.391 20281.992 19932.135 15034.657 22193.291 7564.159 10801.997 12704.844 9230.788 6704.186 5140.310 8263.778 | |||
|
89 | nan 672144.188 647294.250 749914.938 880324.000 709905.938 397926.094 312174.969 295567.156 146687.891 90941.188 17719.336 11892.206 14412.163 15903.499 23054.820 20159.064 16729.316 24723.217 28848.908 21670.508 25563.012 5458.541 14785.350 9296.671 8635.215 12147.788 6887.191 13820.707 9931.187 12394.760 12036.421 | |||
|
90 | nan 719998.062 652681.938 826477.000 867928.812 678155.188 461214.906 385055.188 279792.500 198997.984 107967.492 23347.465 4548.156 9875.500 8917.652 9210.327 7847.119 22365.154 23708.111 20367.564 22991.346 14833.428 26900.420 23849.900 16378.044 11683.001 9325.097 7491.114 11580.423 4388.866 3857.141 6061.876 | |||
|
91 | nan 666568.125 639483.562 764811.750 958006.812 726772.062 383040.219 397340.594 245360.016 176647.297 56852.562 14621.153 7772.213 6312.310 3930.235 5496.105 23904.482 12419.128 17847.188 25606.523 42539.754 15159.324 13281.168 14118.662 19949.602 8497.651 6645.403 1921.766 4617.701 4762.292 5598.851 929.997 | |||
|
92 | nan 676545.375 665390.750 662847.562 862922.000 674786.750 342703.219 338087.281 281663.656 172254.938 74851.602 23833.969 5018.013 12475.491 8077.544 7615.957 8468.293 23054.527 20714.584 17049.592 18557.295 13521.193 19934.877 3939.030 16075.578 12647.512 23759.639 8992.324 2627.001 3019.822 11946.040 11144.488 | |||
|
93 | nan 657499.312 718900.750 686485.812 867378.812 645711.250 475331.594 283532.969 301182.938 160663.141 49947.090 28910.014 16601.674 8686.465 6945.967 8915.206 17310.771 14136.441 14978.481 24889.299 15046.243 5557.056 7588.545 9562.616 17514.299 10701.027 10812.483 4088.162 10203.555 10502.578 6672.157 9270.577 | |||
|
94 | nan 577556.750 690200.562 702204.000 805011.562 690713.125 331779.906 308270.625 310352.219 175422.453 77916.570 16407.289 21449.180 8724.655 4442.178 10942.093 18497.480 16904.707 19557.090 25281.193 24345.545 11869.577 17154.311 13001.884 7554.161 14913.137 16055.263 15453.479 3426.527 8170.347 32936.234 10757.819 | |||
|
95 | nan 640441.250 638929.688 727305.938 773376.250 667216.062 382592.188 324309.562 312448.312 222306.094 79041.500 43368.879 11998.369 1972.984 1427.903 6074.490 11445.046 9401.543 7216.881 26477.736 13837.216 27132.523 5284.574 8966.793 6962.212 25849.387 11536.187 9919.290 1516.345 4334.489 12907.400 10286.926 | |||
|
96 | nan 604420.562 586967.250 663735.250 762891.250 651857.312 395072.781 342879.125 316089.438 159695.609 96654.820 23285.889 11483.074 4564.659 4886.536 9703.733 11871.740 7947.903 4103.656 21446.561 18839.697 11882.731 11806.090 26073.443 32220.992 23069.855 16452.031 14672.512 18070.959 15918.848 14478.574 22831.250 | |||
|
97 | nan 603562.062 708505.438 587964.812 720729.250 705897.938 421907.094 283886.812 285267.281 175000.750 83809.430 45264.215 3942.271 1297.937 7489.750 0.000 7906.081 13475.863 17328.191 15985.733 18448.467 18046.732 14183.806 14792.843 20989.727 8818.390 14067.947 4216.148 10346.121 4733.975 2844.856 1887.522 | |||
|
98 | nan 658018.188 710541.938 689335.562 783376.375 623747.438 443516.375 365363.250 288563.625 138634.750 69169.555 41163.215 11453.685 9837.700 6292.379 10267.079 5351.564 11075.733 35348.203 14222.306 17151.508 10981.366 14688.937 17642.928 23570.852 12264.243 11975.851 10466.217 10743.840 5671.364 14155.301 11654.634 | |||
|
99 | nan 648779.875 639027.438 591736.750 750886.438 681407.750 445975.969 335824.969 279510.781 172727.875 99502.367 26613.537 14954.559 8378.885 10083.987 16452.268 23798.887 28813.654 28891.664 15831.843 22140.680 14040.551 20900.623 15465.010 14592.854 4608.536 11649.340 7532.650 12731.624 8375.061 3376.759 4004.706 | |||
|
100 | nan 630297.250 656347.312 616680.062 808790.062 694933.312 435850.969 375994.500 291402.781 194099.688 82923.430 29133.094 3250.943 8305.750 8599.128 6323.943 1878.037 14068.094 10410.393 30847.131 29387.863 23060.854 13992.993 16784.480 20682.744 15811.144 16166.851 14583.749 9743.868 18151.055 4276.015 12256.563 | |||
|
101 | nan 651741.562 728578.875 627965.625 687632.562 656288.250 525223.500 297181.844 265682.125 183712.594 78365.570 38811.902 9652.056 5736.543 11049.991 5511.026 3560.995 2996.748 8092.794 2257.704 3318.117 2124.836 8496.429 2825.708 11298.031 15807.812 18257.066 13787.469 26610.244 16610.627 23883.820 35965.266 | |||
|
102 | nan 636734.250 757409.375 605645.812 755669.750 639350.938 423943.125 314545.969 277082.344 193197.641 82201.586 25809.969 10105.604 9012.421 3174.890 6300.076 0.000 2299.009 10393.010 5128.127 23893.664 18669.979 10516.753 5453.950 19043.002 21737.031 9010.431 24287.682 32182.250 15165.574 27784.627 67715.586 | |||
|
103 | nan 672613.875 736734.438 633151.438 629417.438 623688.062 530866.750 337728.469 228305.516 233814.438 116445.492 36675.078 15058.222 8938.408 4473.424 711.182 3596.513 3518.616 16576.123 9696.595 8322.629 11941.733 11859.709 8431.694 12001.188 18947.389 10492.780 9874.251 12521.088 12172.199 11416.344 12268.251 | |||
|
104 | nan 634990.000 720988.000 627353.062 622451.312 687210.562 508450.469 308878.969 294044.375 230574.688 105611.398 29135.668 15877.815 3957.206 4400.350 1259.726 697.491 8323.440 9038.395 9414.777 15475.838 8680.460 5550.914 9484.836 8446.124 14105.581 9214.566 10548.022 23257.400 7380.398 8909.958 7155.036 | |||
|
105 | nan 656649.438 693478.938 755325.250 680434.438 772256.000 514672.281 301323.469 259507.250 197725.641 98398.805 37299.379 8106.522 1445.115 4933.036 8758.004 5385.524 8130.971 4562.201 10259.420 6186.934 6121.328 620.224 10035.635 17058.016 7242.717 22207.305 21163.600 35196.949 19410.270 24736.283 31435.531 | |||
|
106 | nan 596825.188 683126.688 665868.938 680779.750 686855.250 513884.875 306489.719 211665.547 194426.062 115793.281 46755.262 20659.871 10146.953 1245.609 2392.462 5143.754 3646.793 1339.197 6903.142 5000.054 15667.731 5369.745 23354.842 14895.903 19788.451 22185.779 16646.791 25344.883 44397.691 13677.475 11633.152 | |||
|
107 | nan 648174.938 767518.438 671545.750 614658.250 640561.062 533511.188 353124.219 248337.016 218047.203 134864.141 35438.301 12194.794 7641.933 0.000 2459.369 4957.451 5530.783 3452.692 7513.196 6134.952 4921.864 6922.983 18974.363 20011.738 16742.684 26977.844 32654.744 24933.643 14691.762 28047.779 11653.446 | |||
|
108 | nan 551986.750 693434.625 680661.188 714202.938 633895.312 516363.188 301914.469 273108.781 196291.703 109872.102 40158.730 22989.988 4495.722 7535.665 6300.076 9082.595 0.000 4590.616 0.000 1269.091 7073.234 2729.271 9388.787 8155.758 11715.817 17701.232 20581.953 14449.218 21848.643 16388.701 12930.301 | |||
|
109 | nan 570837.625 732485.438 616297.875 493928.281 706395.625 590394.062 415048.031 279432.344 212351.344 120672.570 57418.773 6611.914 7091.596 6945.967 3829.756 3581.880 0.000 9087.342 6711.359 4403.593 0.000 11570.769 1688.811 8687.439 7060.786 15289.801 9849.548 10171.715 24480.314 11182.915 29649.164 | |||
|
110 | nan 673843.938 712613.125 627565.000 587150.312 599180.375 522042.312 353210.938 232477.656 177331.141 111455.805 45723.051 7276.124 3957.206 6981.362 3697.862 3024.485 4139.109 4739.157 7778.514 9903.141 8787.960 11159.578 14802.965 12917.088 16368.125 13439.609 14741.207 25324.844 11085.944 13409.491 18012.051 | |||
|
111 | nan 675431.188 672638.688 736617.000 665038.125 589164.812 494833.469 338997.375 337979.625 215404.016 78000.125 27775.037 26039.664 1297.937 3159.700 4506.215 6651.100 0.000 3447.550 11999.105 8959.395 10566.916 2706.700 17867.357 9148.527 22663.430 21947.793 8377.801 8975.813 23279.420 9540.324 11983.682 | |||
|
112 | nan 568013.562 711753.750 625215.062 640971.000 587849.875 496284.094 399045.469 278056.031 214556.406 131154.688 49780.000 11166.509 4475.331 703.877 2483.237 7143.508 9503.694 669.599 2207.366 7235.289 3883.674 5342.925 8949.737 1798.321 589.830 8445.129 5100.122 6303.353 6616.415 6213.183 15775.438 | |||
|
113 | nan 568986.938 687753.062 713011.062 588847.938 591439.562 514610.406 384384.312 269166.625 167645.453 124051.055 43269.715 11378.036 2533.969 3227.816 6178.464 1878.037 0.000 0.000 10718.346 9928.585 6741.036 5505.576 13616.293 10210.862 25124.631 11839.555 8393.087 20128.479 4361.633 17414.156 9794.957 | |||
|
114 | nan 720052.938 706111.188 757448.562 640223.875 721293.938 529813.938 350464.969 264093.094 219586.609 107495.125 69970.875 17965.129 6506.021 3696.473 10486.399 6258.545 2363.302 4151.246 4538.193 2831.695 2819.506 5887.539 12473.691 6703.564 15455.300 3701.268 16532.287 2863.367 8644.243 14014.241 12552.865 | |||
|
115 | nan 496189.969 704866.500 668686.062 572462.688 607990.562 548265.750 398741.000 320979.938 170172.156 107079.102 71962.203 35185.691 18302.812 8666.377 7223.061 4835.381 5276.737 5754.214 1128.852 0.000 2756.464 1687.253 5318.847 11955.622 11863.188 2982.665 5044.694 5820.208 14251.568 6714.089 7124.455 | |||
|
116 | nan 620866.812 783042.062 777483.250 673172.438 502182.031 500910.500 431708.219 302472.938 178698.141 113522.703 39585.379 13277.082 14582.234 1245.609 4358.499 5400.157 2342.898 5156.114 7846.126 12018.528 4330.802 4212.784 4778.375 7379.016 7236.933 4472.420 7948.099 8720.301 17125.992 23073.055 16876.164 | |||
|
117 | nan 670931.250 715988.375 715899.125 658813.000 693809.875 557978.500 365408.156 303518.312 216007.000 122379.344 53344.473 17079.305 5709.878 13498.851 0.000 3132.923 2342.898 3418.595 3501.425 0.000 3303.069 3211.854 4157.389 4628.425 6597.999 12122.517 8693.831 4798.369 10986.198 14624.827 15616.605 | |||
|
118 | nan 621441.750 647107.750 745615.688 732515.188 667949.625 624803.062 410975.906 274072.469 183898.234 157299.641 73043.844 23046.344 23910.838 6294.303 3697.862 0.000 8400.800 8069.784 2249.506 1107.072 7542.285 7543.209 609.390 14325.707 1984.226 1129.287 2529.717 968.857 2462.591 20054.836 41525.699 | |||
|
119 | nan 604863.125 578697.812 729725.000 767233.000 626879.625 504539.281 458828.500 262967.469 187438.641 126616.195 76984.195 32369.801 12141.307 7421.635 12805.069 5958.387 7019.089 2315.570 3397.948 2426.850 2124.836 2910.440 3186.781 3116.836 7043.176 12428.875 10706.029 0.000 4500.564 1094.259 11684.065 | |||
|
120 | nan 600955.875 605152.938 770861.375 763643.750 652629.000 619800.688 458258.625 381924.625 240665.859 144065.234 80595.469 45106.086 14285.991 14915.047 5511.026 0.000 6975.657 4533.279 0.000 2206.104 3883.674 5900.036 4157.389 2016.547 10561.244 12801.548 33409.906 88582.758 139414.031 106594.094 98144.148 | |||
|
121 | nan 557635.500 551956.938 650400.062 676626.438 654904.562 545158.562 478832.500 343818.719 208686.484 139802.109 89809.367 44284.766 11174.062 8159.440 2392.462 0.000 4749.540 2266.623 2929.016 4412.272 614.049 3805.312 4331.271 2016.547 9996.952 9881.300 46381.270 88425.422 80574.500 70855.625 75155.961 | |||
|
122 | nan 589461.312 617501.250 762474.812 695329.562 618575.000 508242.906 406193.406 319471.781 195144.641 142392.500 123174.305 39326.551 11174.042 1245.609 4830.598 4752.239 0.000 8636.347 4518.603 3433.869 3875.274 2099.488 1640.820 2055.044 2039.717 3957.234 10722.431 3889.579 10133.010 12977.296 5506.431 | |||
|
123 | nan 580723.500 666344.062 715283.438 648414.500 634291.375 465932.969 422226.312 265849.969 183696.406 158517.000 88124.688 38092.395 16471.381 6888.950 12278.249 8495.039 0.000 3587.186 4518.603 6877.483 0.000 4231.302 5823.831 3703.646 573.415 2008.516 1965.592 2906.599 10537.923 6525.970 4185.261 | |||
|
124 | nan 618608.250 535342.875 643509.125 729180.688 580790.562 558779.250 479741.594 296993.719 208377.656 160509.609 91413.492 20773.883 7123.220 4963.762 3170.551 4811.939 3539.021 5700.125 4518.603 10096.603 1086.646 4185.964 2089.165 4657.713 2574.056 9910.798 2941.250 14384.449 11314.733 17264.023 25651.189 | |||
|
125 | nan 587554.438 560117.562 629765.375 664857.438 612785.062 548751.750 462471.531 302082.031 215158.703 128712.672 137948.078 59229.301 21970.875 15124.344 7223.096 2361.039 3489.065 2266.623 2929.016 5529.934 1118.810 4212.784 0.000 3194.642 11678.415 14855.285 19948.064 25705.688 33154.941 44814.965 46992.266 | |||
|
126 | nan 648193.438 503012.719 639085.312 686347.188 634568.062 513652.375 414901.875 299174.562 204682.562 139613.266 108859.242 58319.375 14953.844 5859.562 2438.136 16110.845 5370.583 1151.972 4644.043 0.000 2237.621 3366.756 0.000 4145.883 573.415 2555.818 5426.682 7626.023 15197.392 12672.494 17727.857 | |||
|
127 | nan 694221.562 525117.750 593773.750 677233.938 658034.062 526623.625 428907.594 300720.562 176152.672 159758.141 99013.320 44443.527 32388.904 2673.513 0.000 5982.428 6516.808 6356.231 656.160 6534.833 6506.606 10662.570 5327.449 10742.515 21676.100 21874.170 9669.490 27297.494 44601.445 44389.348 44474.477 | |||
|
128 | nan 754791.562 517712.906 580447.000 607539.750 671229.250 576796.562 402854.219 390780.469 276399.531 152961.641 98974.195 50379.738 23237.143 12050.790 7313.835 0.000 4706.201 5817.278 10655.872 1894.683 3252.048 1098.612 3098.419 5227.863 7987.189 16331.906 16026.077 30685.732 37887.789 40045.898 44077.035 | |||
|
129 | nan 710882.562 477220.781 536067.875 711364.062 593330.500 553231.812 473519.312 393887.312 223079.453 147883.875 101811.797 43270.219 19635.018 8706.770 5558.142 7149.631 3539.021 0.000 2925.257 625.592 5553.492 8345.995 10024.531 38037.285 48001.754 71222.211 62308.391 94247.742 87260.758 74991.570 157329.734 | |||
|
130 | nan 670030.062 566937.062 541374.438 570309.375 593677.188 578687.250 500716.594 378426.719 240912.688 156025.250 97747.805 69304.344 29423.752 10184.882 3661.647 9525.304 10538.293 1151.972 1162.265 2225.317 4917.539 12638.506 18585.986 24952.318 66902.344 72025.602 60893.887 45103.141 65234.039 77242.156 73376.594 | |||
|
131 | nan 796311.062 565116.938 479977.000 621716.500 578718.562 544876.375 481252.000 408633.219 223074.562 130740.250 65085.566 51279.703 29006.158 6933.435 21421.439 8253.843 5788.074 0.000 4067.931 3332.388 11828.919 6909.972 22815.479 16842.805 35975.707 35535.863 55366.863 85975.742 67331.719 63116.074 66680.211 | |||
|
132 | nan 853686.625 559972.000 522376.000 572120.750 593118.875 590022.438 393769.406 320086.062 306596.281 168814.234 122837.992 57337.703 23356.779 10554.761 0.000 3717.199 9304.253 4519.198 6678.004 3938.768 2184.260 5342.926 2096.779 0.000 8639.930 16826.531 13319.006 23852.117 34945.180 33958.359 40516.453 | |||
|
133 | nan 881607.188 588399.312 588223.562 671747.188 733013.688 587992.500 515715.312 346918.188 272725.969 130875.883 73477.273 25964.332 17605.426 724.027 5623.096 4485.086 1175.719 7070.192 2249.506 4973.086 0.000 2086.476 4178.331 4666.923 589.830 0.000 571.263 0.000 1541.140 2821.198 0.000 | |||
|
134 | nan 800201.812 624925.000 551437.125 561044.188 593953.188 559526.938 489008.625 319906.156 233883.359 179502.250 101655.406 40864.312 6377.781 9950.307 6847.251 697.491 3518.617 9853.470 1766.751 1107.072 2165.401 3166.517 1671.852 3734.170 6197.936 4961.605 11640.230 21459.633 20412.023 17717.906 39190.254 | |||
|
135 | nan 962096.438 601209.438 554030.062 504069.219 618193.625 528956.438 441170.375 328262.812 235089.891 161582.938 103807.242 48852.484 26772.779 9608.906 3615.973 4758.431 4763.937 4582.193 1766.751 4329.586 2797.028 2144.826 6869.964 1031.267 6066.320 2589.323 1921.766 13285.287 6640.463 9315.152 14308.575 | |||
|
136 | nan 833692.000 623058.000 535834.250 549319.438 640051.125 521212.594 489565.781 312694.469 197629.703 155009.844 102384.297 38465.133 19181.377 1282.478 3719.096 4752.239 2299.009 7600.154 6303.615 7684.058 5585.650 4278.883 3111.203 4140.162 5076.562 3529.918 1958.454 1516.345 5712.016 5169.595 7474.775 | |||
|
137 | nan 764070.375 694986.188 449777.094 470926.719 611173.375 510125.188 428348.906 362079.812 254194.938 146672.125 114950.344 46488.117 19203.273 11278.118 10411.107 5928.288 3553.418 0.000 637.899 643.500 3224.735 8451.124 2096.780 599.437 1163.245 5886.021 5534.229 1110.649 9319.457 6533.350 1818.525 | |||
|
138 | nan 865241.812 658884.625 463354.281 449594.875 566936.062 549382.438 485588.000 294651.125 286220.906 143374.891 109666.070 64263.559 22118.047 12499.579 711.182 7872.506 1210.519 1186.070 1800.165 7647.705 2165.401 3339.946 13076.149 2655.697 3980.827 580.807 10710.447 24994.520 9976.874 20075.898 19954.170 | |||
|
139 | nan 910979.812 641367.312 499198.531 423798.281 501184.594 545420.500 422231.469 317646.594 276672.781 184007.047 123478.258 59947.539 36304.691 9412.891 5054.760 0.000 7092.439 3654.768 1162.265 0.000 0.000 4775.916 6798.614 10205.778 6231.961 8189.825 22559.967 32500.199 24593.514 49285.891 38677.676 | |||
|
140 | nan 802534.250 677279.938 542864.812 448730.531 547042.062 531210.438 461497.281 351874.531 249648.859 140886.203 100887.320 51755.961 20169.062 14987.250 3719.096 4826.633 2351.437 6848.817 0.000 5491.454 631.627 0.000 5187.584 4683.606 18497.398 19678.967 15459.551 32186.336 21894.920 26421.268 17979.322 | |||
|
141 | nan 882665.938 757725.688 456667.469 499659.500 561652.688 500721.031 420532.094 379400.938 246169.938 176944.234 92528.219 57643.234 17461.168 13715.940 0.000 4782.401 0.000 1151.972 4456.873 2178.278 1086.646 4198.976 9326.840 4632.562 0.000 5928.450 14198.991 9484.396 18432.531 37957.934 61528.066 | |||
|
142 | nan 855897.062 737379.250 537966.062 504400.312 550446.250 570543.250 453240.125 368497.375 236525.188 139450.562 103523.656 50302.309 32297.125 17701.129 3630.894 0.000 3015.820 3587.187 4006.145 6122.020 631.627 4421.289 7346.918 3086.312 10004.292 7462.783 17977.680 7690.820 9401.244 28386.250 36434.602 | |||
|
143 | nan 927984.812 723380.062 517627.469 426887.406 562204.688 588150.750 484315.906 352215.375 267109.000 167248.047 131562.094 56600.453 34595.574 11507.009 3881.734 5415.687 2982.411 1855.669 6691.803 1107.072 614.049 0.000 4752.025 2016.547 8981.738 4543.197 9771.525 8261.520 15036.896 30301.889 16575.408 | |||
|
144 | nan 840039.938 747267.938 573978.750 483419.531 570679.562 608870.250 440312.875 399520.094 288590.625 162382.172 106160.117 60706.215 17925.820 5760.053 1951.116 4737.607 4676.650 3554.504 2877.293 4472.230 2237.621 4185.964 2659.420 8173.658 4013.703 9089.723 12179.578 8161.782 15646.530 9824.465 15663.449 | |||
|
145 | nan 872424.375 791652.438 530440.062 490617.812 552866.938 596419.562 487266.906 428658.688 366825.250 182662.734 124228.852 50379.598 33406.234 23679.377 1223.511 7825.736 3680.150 2922.174 3974.118 3271.849 8898.407 2702.452 0.000 2655.697 9630.855 7641.354 8797.834 17187.439 21281.846 12162.187 5568.629 | |||
|
146 | nan 902116.562 907326.250 604202.062 466598.312 464029.969 577367.188 552508.938 438186.000 323351.062 248905.547 97339.680 89141.953 34660.059 17727.447 9757.472 7831.594 4280.158 3467.543 0.000 4716.461 614.049 2086.476 7334.980 10766.718 8085.767 12813.735 11627.975 34599.605 34783.090 52930.414 51801.703 | |||
|
147 | nan 771445.188 872488.562 543045.938 475568.219 466438.375 526469.250 515327.625 425585.406 345967.000 209268.250 136709.516 76617.148 31769.711 27909.744 1259.726 4976.864 4236.820 669.599 5647.456 9353.030 13444.230 2144.826 7468.828 5133.384 6214.352 9416.657 17096.051 12633.744 24131.898 25900.844 33776.332 | |||
|
148 | nan 828714.062 897044.188 575745.250 416277.531 401136.219 446089.031 464715.969 476686.406 391432.906 236792.906 140216.312 86308.391 40722.832 27505.180 3706.748 2361.039 4413.519 2338.042 2863.526 3493.104 0.000 6951.015 6742.519 11735.345 18923.062 17770.625 11224.785 9544.165 22722.857 27593.730 19369.961 | |||
|
149 | nan 769295.188 884933.938 612063.125 458538.094 423286.875 492869.531 466600.000 489815.000 387195.469 212473.812 135846.203 102089.094 31694.145 25530.350 8762.152 3626.676 6097.325 0.000 1294.059 1765.432 0.000 6299.260 6162.873 10468.949 13000.418 17824.967 12183.340 30527.842 26095.143 44778.453 23265.252 | |||
|
150 | nan 719110.750 758226.562 723530.250 523549.281 471517.875 461262.531 505995.594 395744.875 341412.594 226026.234 136425.203 81246.352 57208.773 39177.941 15867.728 20835.945 9455.743 14068.012 1162.266 4933.187 11682.874 11535.324 44389.934 86110.617 81971.117 44395.805 66866.398 64043.504 116028.820 195340.859 261105.766 | |||
|
151 | nan 746157.438 957720.250 844237.812 553932.938 459511.781 382648.406 419195.969 414917.281 399651.312 288995.375 168888.734 129857.203 86219.719 31330.637 33232.379 29842.000 21395.139 8020.839 6974.929 1107.072 4474.739 2746.533 8296.585 14433.653 20280.268 28719.432 34617.152 49860.715 39327.152 64349.488 80110.891 | |||
|
152 | nan 715343.562 844355.812 745376.938 547579.875 393054.312 382927.188 337042.844 421919.031 329044.781 286495.250 220398.547 123064.883 109458.023 53248.289 43866.066 25796.988 14283.571 7034.737 6241.885 3271.849 7122.996 7443.220 1688.811 6144.534 11661.480 12002.088 41806.391 32091.342 46876.750 45727.688 58626.684 | |||
|
153 | nan 693371.062 806822.938 746917.375 537554.375 473507.188 350651.281 433018.031 396461.219 317917.812 291694.844 204090.297 131886.406 81577.438 62838.152 24898.217 26202.389 12247.600 4769.471 2196.136 8647.099 4838.112 5244.489 37144.531 42660.914 50948.902 52351.234 60527.004 104922.375 102822.117 187901.109 229704.141 | |||
|
154 | nan 726480.625 871801.625 831070.438 530227.750 433950.406 424700.375 391290.875 387657.875 390878.188 289935.031 225278.938 135922.609 77055.977 50819.203 23911.195 12603.300 5325.311 7036.094 1766.752 3271.849 7114.597 2765.051 8852.084 8336.209 23948.383 42962.152 54645.898 36031.410 50163.773 45557.766 43026.598 | |||
|
155 | nan 784676.250 851260.938 813095.812 600158.438 357129.750 403495.531 435041.500 455325.906 371249.781 281540.406 211530.938 113094.672 101037.133 48912.961 35355.676 18512.262 7585.287 4036.240 4470.639 6102.158 1118.810 3131.719 5774.637 1963.178 9955.985 8749.763 15586.613 24460.367 20344.039 35722.785 32962.211 | |||
|
156 | nan 805165.625 1009893.188 833852.938 558814.750 447079.000 373333.344 432367.812 421008.906 342699.781 300193.531 198516.984 126775.594 91837.453 44735.066 29486.596 17297.545 22230.668 5262.113 0.000 5004.546 4249.705 0.000 2642.461 5326.861 2022.107 6463.567 4970.162 9705.532 12435.949 8909.935 6753.175 | |||
|
157 | nan 918425.750 936635.250 876425.375 627467.312 431822.219 389741.031 349336.031 397210.688 332767.969 264626.125 227115.859 159966.609 106410.922 64243.648 57903.016 48328.613 16823.338 12788.895 8057.146 7970.286 4890.257 12382.729 4170.174 6324.772 9138.031 9856.157 38328.160 17231.062 17630.936 27912.820 26257.008 | |||
|
158 | nan 907989.625 911723.938 878505.938 646558.812 441391.219 391759.781 404449.812 377255.531 320435.031 310518.875 185110.703 120435.508 69451.797 46091.285 41885.168 29422.398 11918.801 12737.594 0.000 12147.837 2851.670 8623.250 7566.202 7149.931 8586.082 21302.098 26319.895 39783.285 41549.602 31785.211 40259.016 | |||
|
159 | nan 916125.250 977378.750 863182.375 687507.312 385859.969 414930.094 401525.594 394876.500 417738.031 285432.094 193955.141 105925.242 91850.688 48206.285 46930.199 40640.219 25310.139 9292.455 4724.102 6136.258 2138.088 6312.272 10916.897 2599.302 4036.318 6545.454 2109.424 8824.688 11910.770 10871.871 10775.973 | |||
|
160 | nan 861404.438 1010105.250 793167.812 707437.750 460710.969 337984.031 374536.375 394806.469 309330.062 260548.797 198510.094 144445.828 77825.344 56091.371 51806.938 31740.838 24827.367 16967.938 11190.379 9578.348 18098.914 21351.307 26272.455 47826.102 38342.996 36315.957 55282.191 65650.984 112014.180 105333.000 98268.148 | |||
|
161 | nan 329960.844 409635.406 458661.188 432011.719 390502.812 335850.594 448710.375 549639.312 785047.438 978758.625 1998075.625 3344193.000 5289928.500 5605319.500 5560264.000 5192447.000 4703186.000 3837637.750 2882478.250 2036112.500 1487727.875 963883.250 719143.188 464359.969 270295.094 170457.281 90298.914 45561.598 40457.316 21238.373 8080.453 | |||
|
162 | nan 645081.375 642395.625 636018.188 595986.438 594224.688 509316.781 376801.719 251699.266 230112.734 195058.797 174642.500 156789.312 131108.328 84432.203 60871.840 46634.590 30515.674 8247.934 17988.277 15509.800 17206.732 17921.639 2126.521 20773.537 11971.184 15219.559 14547.423 10137.945 9054.011 10686.810 3586.105 | |||
|
163 | nan 609261.562 730982.438 697204.938 604530.688 547848.438 433557.375 317675.031 281648.594 231974.312 219431.609 160081.453 182904.016 105150.969 72276.266 55199.625 38175.195 19423.012 21678.314 5989.838 7418.907 7182.474 8473.150 1811.212 9873.384 6002.935 3019.967 1538.161 2892.045 0.000 1516.268 0.000 | |||
|
164 | nan 482872.719 654350.688 732380.312 635881.500 559089.250 422941.969 309276.125 235006.703 239557.703 182295.516 155004.359 153328.031 124785.672 88806.883 57216.160 39705.285 25123.719 15653.172 16974.830 20943.086 48091.598 161049.016 94660.023 20250.693 14524.406 6899.412 0.000 7625.638 8573.862 0.000 8700.204 | |||
|
165 | nan 652528.500 753730.812 720853.438 607353.938 517680.906 464586.781 346712.719 331939.406 281684.719 242289.266 149541.500 121582.305 98149.969 59552.062 39145.641 26215.227 31417.342 11049.012 2422.912 6214.763 11981.050 8523.199 5379.662 7296.729 9745.501 1966.059 555.365 0.000 1870.773 547.130 4228.480 | |||
|
166 | nan 581986.938 619218.188 695720.188 533266.750 522726.406 350296.688 316081.781 222895.047 219343.938 215935.688 199877.438 141207.766 118482.422 71820.102 49687.324 51648.625 14056.638 31294.270 21928.719 20337.498 22882.262 17012.764 14545.329 21457.646 29265.275 33101.535 33746.504 21057.389 23514.203 23783.414 5867.939 | |||
|
167 | nan 568328.938 789769.438 809736.938 636914.438 494130.625 403034.781 326125.281 245222.500 234014.234 226279.156 164662.266 127104.922 70309.883 94229.406 84032.500 61845.539 27116.227 34782.234 14596.828 27674.705 23086.414 11288.802 18966.900 24804.656 26046.436 45318.801 56774.613 67717.586 51976.797 60971.004 53629.922 | |||
|
168 | nan 610739.250 673058.375 751567.375 696950.938 579130.562 434623.188 382083.812 256906.891 207924.906 120576.297 150591.547 149148.766 121539.117 74416.227 44759.383 41318.336 22796.020 26260.648 17809.316 16328.848 20227.891 2768.604 10533.260 7958.933 3131.057 1028.792 0.000 4865.927 4377.153 3114.577 3671.767 | |||
|
169 | nan 602738.500 695466.750 760661.500 673729.562 588659.938 565761.562 377671.906 279189.219 196183.359 157067.188 182319.109 98660.875 94681.672 73107.523 53533.266 58882.289 30195.236 9670.715 7390.930 4767.197 10375.821 8231.344 0.000 6720.249 1044.774 4630.773 3541.604 4968.325 2479.195 3751.492 2783.240 | |||
|
170 | nan 523927.188 570993.312 658142.250 595331.438 522346.812 517852.719 384086.219 324552.938 249114.844 184134.062 135767.062 108970.227 78880.711 81356.875 49338.812 32899.992 18820.818 28396.383 14786.781 5719.726 7240.107 8139.709 5817.375 8390.688 2586.431 1953.874 2550.047 2469.487 2053.450 4213.064 0.000 | |||
|
171 | nan 661068.750 708478.062 649644.625 651707.500 539507.250 492368.000 339089.469 206613.953 245602.953 200100.641 173915.141 141926.094 114495.820 60042.246 64349.254 27023.867 14282.119 33568.961 16989.154 13376.015 5558.402 15512.415 4692.520 6139.213 11210.382 3945.049 2945.638 7856.512 1906.487 1892.054 1887.523 | |||
|
172 | nan 661426.875 699426.062 664836.938 661503.875 542108.250 469059.969 338530.969 289650.875 219728.938 200304.859 167503.938 122586.922 115986.508 59513.816 54576.816 48557.352 15179.077 26252.693 26070.779 14766.269 16731.148 9569.466 2659.420 6154.192 2595.522 3127.719 1921.767 2441.999 956.717 3206.669 929.998 | |||
|
173 | nan 689196.188 601211.562 703228.125 666304.938 568298.250 440329.281 368906.281 271219.312 178890.234 255672.750 194269.891 115699.273 115923.070 95901.727 53992.000 36447.902 17015.770 13961.456 15486.469 15237.082 8147.881 13337.757 10385.290 12864.753 5096.357 3738.102 9867.000 8684.835 2479.195 969.138 6957.161 | |||
|
174 | nan 671435.312 767147.250 681398.375 647008.938 529676.750 447339.688 336840.906 234741.000 280036.875 222018.844 192713.109 128574.180 89063.234 88811.531 56051.727 27348.404 22581.002 12564.610 17363.756 13417.532 14031.447 13602.244 29131.170 13602.303 8415.987 27654.562 17295.031 12123.871 14898.359 11769.570 13180.369 | |||
|
175 | nan 479706.312 610349.688 555283.500 634320.312 545662.500 489958.688 342125.219 249492.094 182291.859 160683.922 223278.594 109794.203 95950.320 62772.641 59195.125 36710.602 29376.307 6223.665 12338.395 12430.204 15673.531 17106.445 16642.748 29941.199 31398.779 44949.520 66874.633 103044.750 102974.617 97952.695 94455.141 | |||
|
176 | nan 506874.281 567607.062 663131.250 611271.750 584031.250 432542.906 486839.812 294458.031 281176.875 152617.906 171980.703 134074.953 118154.656 89587.883 64858.297 40726.199 34846.730 9608.962 24314.023 20022.158 4480.147 6312.273 1079.421 4745.322 4006.334 1563.859 555.365 6770.167 2463.719 5318.738 7428.673 | |||
|
177 | nan 533983.812 571993.062 548378.688 531242.250 479108.406 382187.500 389113.906 272195.531 255286.562 171202.391 81411.336 113037.625 105560.344 89355.406 57342.191 44483.410 36485.785 24836.061 17582.664 17184.236 4917.540 5086.852 5829.243 7310.045 1984.227 10019.676 3953.137 1947.492 2411.401 0.000 4162.580 | |||
|
178 | nan 484680.531 509279.000 554911.562 703844.125 509347.188 433340.594 355095.156 286611.156 202126.547 170941.016 143094.234 117441.844 85747.625 75400.570 60053.434 31106.881 26699.830 10052.118 11881.228 17460.102 8613.793 7410.766 5650.938 9069.296 11059.603 9740.239 18477.363 8960.957 5698.919 13980.626 13738.057 | |||
|
179 | nan 820479.438 856431.625 862968.250 784533.625 641094.438 408414.719 358675.000 195858.500 207469.609 163126.609 168170.984 118177.656 74969.633 61647.324 46831.809 16255.679 18157.176 14408.425 7364.311 17490.961 14368.281 36541.152 63328.402 51005.512 55969.516 37655.184 39400.848 55646.840 77062.961 65020.488 66769.352 | |||
|
180 | nan 690883.438 747950.562 643360.938 653307.688 594514.375 476784.688 387281.375 300087.719 228956.984 160286.859 129774.906 100203.422 83168.125 73016.008 50529.391 14375.382 24122.727 19878.582 13055.402 16289.321 7885.827 4930.692 12334.547 4812.771 5627.806 5471.637 3843.534 563.161 0.000 941.277 4605.917 | |||
|
181 | nan 388779.531 463146.312 436102.031 496659.594 485880.188 413787.594 427186.969 310748.000 324416.469 234028.359 269439.781 186769.375 128581.406 115282.672 87480.969 58810.711 38792.172 30071.623 36249.445 20311.799 17444.170 12975.703 7213.069 4976.345 5822.809 6562.767 2958.307 4798.372 9276.278 531.903 0.000 | |||
|
182 | nan 78260.836 96977.078 98009.281 112698.344 129250.000 153067.016 243909.438 391311.688 859660.000 1609267.250 3248549.500 5293539.500 7223480.500 7533035.000 5942708.500 5456951.000 4732988.500 4420403.500 3565991.750 2646643.500 2035441.625 1343681.625 1016985.750 659906.250 412693.406 249515.062 144706.016 84137.156 47243.016 29580.592 17112.344 | |||
|
183 | nan 426801.375 459576.469 496385.969 486459.094 576986.938 579562.938 487876.625 510396.719 393821.125 370583.656 292906.625 287307.125 218200.984 179323.906 145442.984 127767.844 107328.898 78192.953 64675.465 43330.309 33731.027 20145.305 18784.082 8457.745 2570.016 4936.541 6862.605 0.000 0.000 0.000 0.000 | |||
|
184 | nan 410732.812 430513.781 549324.000 502342.469 493203.781 452127.625 350994.406 322423.469 279020.938 254561.359 242895.641 230535.438 158783.812 97889.305 102939.953 67079.273 42695.238 41260.973 40365.457 51170.336 19056.812 19177.146 16660.590 18216.357 4834.236 6553.628 3382.655 10542.767 4519.146 5368.466 823.258 | |||
|
185 | nan 478534.312 586353.812 624974.562 562060.938 556461.750 522106.625 451801.219 374801.625 328662.375 294080.781 257916.641 220849.734 187193.984 107479.906 87547.633 33669.559 32050.967 38230.109 31145.055 33546.488 18857.318 16757.418 6633.469 11764.204 17228.361 17877.783 12746.672 5863.142 1443.977 4349.600 7405.788 | |||
|
186 | nan 295634.844 506221.781 578562.062 644921.438 615336.438 509028.125 471826.000 489283.469 427734.281 349927.375 281599.281 240832.047 171751.781 221323.766 193900.812 225131.000 163654.953 130592.102 103985.508 80580.062 78280.359 38252.363 19856.201 21778.014 13470.574 1966.060 8759.614 4769.695 2979.173 2861.194 1483.055 | |||
|
187 | nan 416571.125 491746.594 594276.000 545045.688 615518.438 522881.375 480528.812 455745.875 403759.875 417024.281 367340.094 313662.219 387571.219 254822.859 209594.938 150914.234 114500.750 95942.031 59381.250 67759.734 35678.723 23487.477 21815.449 9403.590 5696.429 9872.758 4525.559 3872.719 7554.550 7486.053 4254.908 | |||
|
188 | nan 389479.531 466733.406 481736.781 532667.062 611758.562 563012.062 557476.250 521853.812 526318.938 534340.250 529972.562 386757.906 326612.594 191845.234 162035.734 116497.828 113162.203 82807.781 67053.625 59335.691 59497.426 46293.477 27129.268 32695.443 13817.821 7101.119 10878.484 4405.166 956.718 2383.964 929.998 | |||
|
189 | nan 479429.188 817040.188 856998.750 916593.750 729180.688 559134.438 400349.812 447506.688 314455.531 373624.031 379588.375 294226.250 238033.906 175190.031 152814.516 87287.094 48898.090 55544.816 52423.012 54625.789 65779.875 30660.082 25869.264 24505.602 15036.191 12781.787 11796.113 10498.676 7169.954 9859.735 2240.499 | |||
|
190 | nan 577922.125 707578.062 794521.625 713369.062 666235.438 563157.500 470957.375 423749.500 373915.625 329130.031 338707.375 263162.875 203808.953 113238.031 131397.234 83008.898 71728.906 71107.273 60740.863 54182.789 36854.840 25596.719 25340.426 11460.774 8237.666 9218.667 7927.049 8261.824 3846.182 3681.246 2734.024 | |||
|
191 | nan 88605.242 140386.562 229550.984 275420.812 397687.031 410985.281 435377.500 503751.469 425522.219 299021.344 284046.094 201377.562 260089.312 209634.297 159589.688 128782.477 74608.609 81989.406 67317.844 40500.727 21608.123 6410.011 14527.218 4148.105 11059.231 3982.352 1921.768 1894.512 556.105 2904.388 4208.640 | |||
|
192 | nan 305365.125 413012.031 599945.875 823893.062 890525.938 757426.062 609416.312 505758.906 438449.000 428410.531 342720.281 275552.531 294712.812 208258.234 170792.375 131386.547 135267.859 64612.254 79894.586 43479.422 35800.426 19747.236 7060.810 21742.158 7987.193 4017.033 1011.886 3842.004 1870.773 0.000 0.000 | |||
|
193 | nan 408030.312 548579.812 613044.000 660627.312 894948.938 807223.000 667996.250 494950.812 419406.219 380624.625 329186.562 241948.641 161506.359 141353.281 162091.859 140689.797 88803.203 53752.637 36822.223 28634.814 27966.217 21408.346 21550.754 2645.291 7703.781 5557.929 0.000 1937.715 1906.488 1892.055 0.000 | |||
|
194 | nan 314942.938 418909.812 616128.312 595200.250 605084.000 629391.062 456514.812 397798.875 351432.281 292469.375 320426.938 348670.906 429682.375 468851.875 584726.688 664696.562 781250.062 697986.375 627773.000 425786.969 342586.906 229697.141 150099.734 82041.141 47031.480 28093.742 25587.568 17757.115 10948.152 5977.146 2287.078 | |||
|
195 | nan 548663.750 721115.375 749804.562 979148.812 979681.812 914373.812 688187.375 583450.250 422831.969 354525.844 333845.031 251048.734 215884.359 172866.688 141145.141 115345.633 108498.273 71108.445 93999.414 35528.027 28607.688 24661.180 9781.162 12912.728 10727.359 8977.946 5405.667 3861.358 4320.986 0.000 3308.771 | |||
|
196 | nan 766854.062 932543.562 1009064.062 1006260.000 849515.625 774211.625 649024.125 448692.531 327749.125 255865.203 289488.500 204365.891 177313.891 103796.148 99704.953 100761.555 97756.672 62681.625 47281.684 39701.449 40507.438 36048.027 22773.525 23560.449 8417.767 17802.287 6951.842 3386.166 1923.091 9819.553 1553.308 | |||
|
197 | nan 387099.094 530856.062 557225.875 731600.562 748048.688 699052.562 737705.750 538277.125 565245.312 369880.281 346392.031 325466.656 209805.188 184364.469 155198.719 108190.203 113610.672 96779.672 56059.336 36889.094 21363.018 13685.850 4340.614 6361.566 7035.286 564.644 1011.886 1966.393 2423.069 2821.199 2400.570 | |||
|
198 | nan 379558.625 424473.281 587330.938 625123.062 619244.625 722727.438 675334.688 649446.812 505906.688 450294.281 416244.594 363510.375 305722.719 237327.688 202339.234 196195.750 112068.047 85231.961 37797.668 37801.375 10930.907 14495.543 3111.205 6259.133 4995.568 5911.111 3909.264 0.000 6597.383 0.000 0.000 | |||
|
199 | nan 47523.773 48289.039 80794.047 94264.398 112306.273 199188.016 214175.641 325033.375 657804.750 1397846.125 2507237.750 3847885.500 5164801.000 7184627.500 9810900.000 10695913.000 10053692.000 8036416.500 5547983.000 3757917.750 2469516.500 1467602.125 1024495.438 517207.719 354360.531 157427.297 87726.758 46686.688 42852.160 21129.918 20300.516 | |||
|
200 | nan 369316.000 507402.281 674756.562 807419.250 877020.188 748204.625 609989.312 567523.938 521144.688 421220.469 281621.969 221518.688 173788.812 157543.203 101443.445 67441.781 29821.014 70826.875 35429.398 26646.520 13563.579 29394.939 19964.740 14711.540 23719.160 13524.553 5393.682 4425.660 5707.300 3767.774 1915.051 | |||
|
201 | nan 680355.000 848718.625 939678.938 1015588.938 961089.625 1036200.938 830376.375 751475.562 682992.062 587147.875 528008.375 485533.875 452908.906 344292.188 291234.438 292943.469 239720.438 204054.953 148021.141 130803.953 70897.211 42786.738 42960.035 18201.576 6567.291 6583.394 4463.472 4435.880 6657.070 5268.817 957.526 | |||
|
202 | nan 745757.250 803852.375 966895.062 1067377.000 964035.625 830543.750 766702.750 496991.406 526538.688 436615.000 339261.531 336889.719 333707.188 247309.656 233171.406 211524.484 143392.812 97080.469 61863.949 78344.766 43790.855 23130.635 21973.785 10467.770 4570.660 3964.493 4928.797 1906.327 2426.878 4783.154 2759.865 | |||
|
203 | nan 482361.125 598609.688 570023.938 675093.312 687966.688 677346.500 635640.812 619744.000 522483.781 420164.969 455955.000 488066.312 523454.406 488118.406 379823.375 382093.531 235470.406 213364.188 139588.953 152583.891 66565.023 48789.672 20947.641 17580.914 14662.124 0.000 3108.148 9544.197 1923.091 0.000 957.526 | |||
|
204 | nan 393028.406 548211.688 592752.188 681745.875 691936.500 611201.438 603468.938 450696.875 386095.094 341020.781 313340.125 262828.688 166226.828 157015.188 154611.938 103558.398 91510.992 67209.562 50498.621 29888.295 23221.496 11471.813 8805.368 4117.581 0.000 2965.277 2904.564 6313.557 2879.809 3732.636 525.530 | |||
|
205 | nan 390209.781 484197.188 537140.562 581399.688 634148.312 646031.250 766701.938 805324.562 728412.375 640984.250 535904.750 563259.000 439789.969 257125.250 241542.641 151852.531 137470.016 80595.445 61463.379 42803.863 27193.367 11153.036 11028.873 11319.421 1044.774 2530.704 982.796 547.489 0.000 531.903 0.000 | |||
|
206 | nan 93577.234 142482.234 109061.281 159852.438 211498.656 232608.453 244616.297 357091.875 550142.250 909945.562 1542764.375 2404568.250 3084983.250 4251491.500 5985218.500 7506821.000 8514096.000 7562167.500 5705261.000 4289576.000 3110752.000 2194615.750 1483071.125 1039731.562 627809.000 486717.188 261453.062 142814.094 123820.875 67206.062 31130.225 | |||
|
207 | nan 38746.848 44762.406 80972.898 111266.727 139230.516 208831.109 355048.344 755325.562 1232840.625 2087924.500 3010426.750 5275331.500 9380484.000 13465564.000 14601866.000 12671562.000 9821548.000 6899067.000 5023597.000 3527611.000 2323301.750 1515542.500 1087356.500 731649.938 454916.375 235534.938 135194.484 73239.680 54450.859 28264.346 36238.340 | |||
|
208 | nan 408697.031 586934.875 677270.750 778700.250 771835.562 694546.312 800348.562 649288.000 616226.750 488982.000 427909.031 289397.500 319760.875 244640.297 158951.609 126841.305 64398.051 62283.496 62050.602 33744.934 22344.924 17050.914 13634.220 8596.649 4954.602 11031.322 2546.775 2416.118 4708.880 6500.466 540.574 | |||
|
209 | nan 507388.875 651061.250 835373.812 871372.375 811961.250 731421.250 822924.438 666784.750 650871.312 580362.438 509584.406 413720.875 368374.875 409009.000 396072.469 309194.344 225375.234 187530.406 117366.773 91469.258 53319.074 27871.557 15898.350 22597.080 4626.150 5753.891 3909.265 0.000 8669.871 6146.440 5197.350 | |||
|
210 | nan 411460.719 569188.438 760301.812 795168.188 775449.375 807839.812 638753.875 581094.188 512888.875 503597.969 465210.781 392878.375 367239.344 230244.797 211209.734 148545.734 134696.250 90304.977 51870.676 38771.809 21705.340 25453.113 11612.687 9610.437 5409.788 5973.060 2493.031 31451.732 1882.441 6213.851 0.000 | |||
|
211 | nan 477364.969 628692.938 818613.625 866580.438 772399.625 633639.562 638062.625 459986.531 470111.500 371090.125 283021.750 259116.047 239879.953 155596.375 112899.656 103872.844 64952.539 44613.223 41559.801 46468.133 48424.914 15163.937 17832.117 15947.824 6793.932 4993.285 0.000 0.000 5676.305 6690.477 2787.393 | |||
|
212 | nan 444308.625 598821.500 705146.438 738639.875 728270.688 647459.125 583981.750 476260.812 417704.688 369484.094 380160.031 252788.406 225414.453 159096.609 108060.883 79632.508 49765.578 45774.230 41024.504 25328.480 18913.682 14390.579 20795.865 13461.369 21434.561 6803.446 4520.894 2875.184 3438.245 1994.803 929.998 | |||
|
213 | nan 492698.969 689999.812 750846.750 811712.062 748457.875 855054.250 624139.938 548324.812 597209.125 524070.094 499459.719 442670.281 355712.844 295520.781 228757.516 231705.141 133507.406 73775.758 78290.680 40760.367 22486.703 18963.094 11661.185 4045.673 5670.924 3919.935 3880.223 1930.679 2839.158 3692.642 1818.526 | |||
|
214 | nan 537356.625 642588.312 761776.438 777515.812 720267.750 771830.250 625351.438 565499.125 500953.500 392931.719 391624.375 282883.125 305973.031 224856.906 201566.406 165302.438 119678.750 63092.984 80861.383 41841.953 34640.012 22833.275 12277.712 11228.731 3168.938 8876.388 1011.886 5719.702 2482.383 1875.719 2409.956 | |||
|
215 | nan 374575.812 418403.031 477230.625 493163.219 457105.969 433240.031 484192.219 387887.906 369719.562 365624.375 478124.219 737184.188 967681.812 1127034.000 1067081.250 814409.750 644324.000 560279.000 415279.594 319909.094 152208.938 88471.383 55003.102 55192.723 16959.080 20316.148 9840.552 9842.348 4778.922 8352.554 1765.157 | |||
|
216 | nan 423044.219 580637.875 642461.750 665844.062 703033.625 666412.188 600146.625 479963.875 415668.625 409799.594 354529.219 312195.281 423291.312 357602.719 316877.906 218577.797 165866.516 100000.500 81489.617 51978.312 37783.984 24754.789 31486.055 16933.445 7827.927 6516.595 3501.004 1894.512 0.000 547.130 1818.526 | |||
|
217 | nan 277990.625 425632.875 468105.625 419796.281 411076.594 473971.812 495069.000 662701.562 957683.812 1748601.250 2659543.250 4755764.000 7068243.500 8298051.500 7461339.000 5959275.500 4291221.500 3016027.500 2238893.000 1591903.500 1067861.125 713946.750 476468.500 336418.531 177696.766 130999.031 73960.547 29914.713 36066.000 8516.463 10472.060 | |||
|
218 | nan 218076.766 283617.406 363989.812 354961.531 319330.219 248018.438 293153.938 279589.500 303346.906 453208.875 640070.125 1061494.625 1286866.875 1925580.125 2970281.000 4079418.250 4834368.500 4675099.500 4035673.000 3190392.000 2172283.500 1548750.875 979547.562 679027.000 380375.656 214652.234 158077.609 95098.594 47691.277 20344.414 13175.819 | |||
|
219 | nan 69789.078 132955.750 182873.406 237352.047 268065.969 270802.969 327826.562 544260.062 1037626.625 1880497.500 2860195.500 4510384.000 8050762.000 14054556.000 19006828.000 19090074.000 15666442.000 11320827.000 7870204.500 5400891.000 3456392.250 2209490.500 1515193.125 989580.812 598494.562 297987.625 183984.375 86610.406 36868.246 28476.920 12553.753 | |||
|
220 | nan 570166.562 691672.125 775502.250 899654.750 874190.188 699033.750 667388.500 554355.438 433774.406 416380.219 355344.094 409317.781 396072.500 395499.375 366760.219 336291.594 233504.547 179752.484 120950.227 56575.301 53929.566 51517.578 4735.021 19499.955 13165.293 4066.132 1011.886 1532.019 3793.864 0.000 0.000 | |||
|
221 | nan 109746.492 187173.828 218522.188 200875.953 299429.781 315163.562 258908.250 263342.688 337850.875 355607.281 610768.062 931927.562 1229194.625 1620516.500 1992304.125 2148347.500 2165281.000 1932061.125 1509820.125 1148557.125 836471.625 555004.438 432492.719 294677.125 157610.891 114738.305 74258.344 58105.648 24875.426 30372.977 7872.188 | |||
|
222 | nan 560796.688 825785.250 1028702.750 911633.000 858161.625 754590.750 604343.938 524033.531 488595.812 406446.594 338921.750 441105.094 437778.188 510234.281 553520.312 565424.750 555118.750 475958.594 373571.156 236077.297 190983.297 125266.156 97800.219 47461.352 31297.377 17743.424 12335.731 6027.036 4683.828 0.000 4994.715 | |||
|
223 | nan 334271.781 410400.688 467519.781 568247.000 582776.938 514763.188 384371.969 292639.219 262037.016 326837.219 310379.188 392769.094 474513.000 456601.812 411202.531 421539.906 399384.906 299708.062 244286.109 191502.453 86374.445 67061.367 54374.723 18995.932 26315.658 21252.000 2793.090 6574.358 3881.517 6957.321 5506.461 | |||
|
224 | nan 259059.500 409899.875 469611.969 543510.938 619600.312 558047.438 532212.250 622020.438 788120.438 1271593.750 1962930.000 2571620.250 2986586.000 2521127.000 1513393.250 785355.750 264294.969 136471.000 87303.031 75863.055 36544.988 24467.432 24399.695 6776.667 11831.408 5973.060 1921.768 2108.185 0.000 531.903 2038.681 | |||
|
225 | nan 162335.688 224036.250 265705.031 339787.375 377334.781 501967.875 700919.750 1261963.500 2205556.000 4068537.500 5858782.000 7503592.500 10061556.000 13530951.000 16624205.000 17607006.000 15397175.000 12783407.000 8724477.000 5416374.500 3149752.000 1874906.875 1247673.875 727002.250 519704.969 312244.625 172994.750 87097.023 53628.223 30752.738 13582.894 | |||
|
226 | nan 61641.898 126013.617 162925.641 207433.047 207590.438 182161.766 242639.734 435442.031 790228.438 1538258.375 2570847.750 3835148.750 5633011.500 7029048.500 8744534.000 11843579.000 14800860.000 15995943.000 14116812.000 12057225.000 9519059.000 6915424.500 5144657.000 3547416.750 2266325.000 1504638.875 806970.438 581310.938 284064.125 184989.062 87359.211 | |||
|
227 | nan 122904.930 202222.953 199423.141 317620.500 351609.156 377896.875 442777.500 645861.562 1362430.500 2681398.250 4170512.250 6404601.500 9464898.000 12474410.000 14989985.000 13788668.000 10864316.000 8075830.500 5338935.500 3564755.000 2172257.250 1404236.750 876338.938 605848.688 280913.250 174357.438 112195.273 55253.340 34559.395 21864.582 11432.661 | |||
|
228 | nan 199261.859 322552.875 369503.125 463673.719 552439.562 475761.188 440395.281 355044.250 495030.312 949598.625 1632255.625 2436277.750 2895405.750 3244561.750 2951539.000 2181784.000 1442007.750 957053.812 570215.062 316859.500 158489.672 97638.594 46290.117 41324.117 28163.037 17788.109 6348.925 5332.468 4761.244 1473.181 4594.604 | |||
|
229 | nan 73967.508 123688.352 226797.656 216708.844 230523.000 339426.219 496686.000 1007682.250 2338232.500 4407883.500 7067494.500 11942713.000 18604080.000 23490408.000 24128026.000 21887876.000 15214854.000 9479529.000 5014084.500 2564309.000 1129665.500 539044.312 314424.000 146204.953 64570.961 43333.648 18369.014 10301.646 9338.332 12461.093 1231.252 | |||
|
230 | nan 473476.219 663329.500 818204.250 903934.375 829346.938 857165.250 645245.625 584813.062 442264.000 381052.500 493644.219 702374.750 1025220.188 1326112.875 1337218.875 1184196.125 929307.938 767459.062 472981.812 244139.047 134993.969 94588.500 51674.609 22973.230 20643.336 8779.720 12438.940 5223.094 10930.047 6882.334 4353.573 | |||
|
231 | nan 252416.234 337794.000 589604.688 578639.438 627033.062 542421.750 422940.312 356724.062 330299.250 318183.125 293891.562 332335.344 373916.062 407464.406 383723.406 332036.438 336834.125 215879.812 150928.359 120690.195 62356.910 46143.922 30987.582 23548.934 9656.090 6165.028 20718.760 6282.475 3829.578 3338.619 1012.734 | |||
|
232 | nan 609237.688 837838.938 1148608.875 1288409.125 1230529.625 948440.375 703534.188 518791.188 366792.781 337218.969 283631.375 230670.188 215236.812 133040.891 102496.453 100547.867 100863.828 61020.340 45431.129 17532.373 12255.694 10717.047 9062.902 13304.137 4023.945 3601.952 2970.342 5384.739 2447.116 0.000 1869.382 | |||
|
233 | nan 617325.250 957383.250 1183719.000 1071849.250 1112841.500 927996.062 811295.938 743673.750 530815.000 400197.469 297169.375 291235.594 212244.453 188141.094 165705.938 167104.562 108959.227 118552.508 68794.281 47960.246 37366.629 22429.508 15143.729 5179.373 17149.879 2990.392 6360.536 0.000 2908.127 0.000 0.000 | |||
|
234 | nan 476685.125 736856.625 860677.250 938357.062 971780.812 869861.250 644145.375 617323.375 422730.219 371423.031 271200.719 299169.375 306212.875 260922.547 234762.750 199984.953 143180.438 73866.367 56786.273 36154.672 27984.951 17871.363 29548.980 14337.829 5237.021 7588.233 1975.511 2453.815 2482.382 2383.963 4680.150 | |||
|
235 | nan 527189.562 674113.312 906105.188 1017933.750 946032.750 889951.250 914436.000 768444.750 581195.062 430948.969 339530.219 253469.859 211797.594 199445.703 118822.258 121682.375 97308.703 56187.137 34652.316 49839.562 33087.965 22930.998 11294.827 19302.471 12048.543 2534.682 2945.639 3016.976 2426.878 0.000 5221.875 | |||
|
236 | nan 567046.375 878353.062 1343463.500 1409166.750 1347550.875 989796.812 675280.000 547274.312 365651.781 297906.125 259397.766 192219.844 181959.109 149420.438 160335.859 115782.719 85173.617 77969.625 46953.395 25125.502 20466.627 6542.336 4216.978 10262.116 3759.972 2953.091 3076.323 7669.231 956.718 0.000 4366.542 | |||
|
237 | nan 488541.781 782576.062 1377073.625 1308773.250 1025885.250 844377.812 729273.312 514871.469 405244.500 251970.594 247407.188 227694.188 166304.766 175491.344 121068.203 111088.398 73921.164 73480.180 62954.988 41303.289 26493.957 21913.924 11671.333 10922.603 4051.584 5898.954 4067.880 563.161 7611.062 969.139 540.574 | |||
|
238 | nan 373418.031 675966.375 1043895.000 1287085.625 1199127.875 1043354.375 859496.062 659505.500 502048.594 401063.719 307428.250 337308.844 313799.594 273835.375 237136.562 188240.562 167092.984 78119.328 44837.422 31273.732 32957.414 17894.455 19699.930 13469.438 12599.818 6942.727 3909.263 0.000 3951.367 3364.126 3352.437 | |||
|
239 | nan 494934.375 693770.250 895827.062 1229827.750 1348236.125 1068454.875 733321.125 510042.406 485287.000 342028.969 250428.109 187986.234 125614.703 130962.328 77697.820 63148.977 73937.367 85678.938 64402.559 40497.297 41293.141 39882.871 36161.598 31198.055 19627.986 12776.553 10655.751 3439.146 13598.993 5514.991 3731.063 | |||
|
240 | nan 321397.125 641868.000 1090071.500 1447184.750 1439750.375 1231199.250 834522.812 738199.500 500527.406 534187.562 482214.031 422003.531 391103.719 412529.469 299264.281 239559.312 197013.109 139809.828 106483.922 47419.145 48693.621 30116.207 26112.600 22884.164 3185.352 5626.692 4463.471 4336.511 1541.141 5643.547 929.998 | |||
|
241 | nan 343995.281 428161.188 587670.062 1040995.812 1009064.000 1071980.750 823153.375 528215.000 376052.031 311335.375 321232.812 205599.984 136315.984 109921.727 97958.430 66711.508 64945.734 68779.781 58868.562 48254.562 26036.492 19747.568 24089.824 9822.776 5215.979 5161.307 5920.379 10276.993 4656.561 5136.111 5540.639 | |||
|
242 | nan 458666.500 583654.625 849140.812 885886.562 850769.375 952943.188 785359.812 668595.750 607492.438 431225.594 267646.031 161636.281 103802.898 112670.805 79411.859 76152.797 70088.984 77643.023 55483.629 32665.221 27939.449 36078.293 20208.682 10743.309 10968.706 7063.866 5979.979 3293.164 3848.937 955.286 2810.768 | |||
|
243 | nan 393093.875 585366.000 704454.562 850758.562 882438.750 819135.812 703737.062 585332.750 557949.812 423645.406 335914.875 230254.516 155154.594 99064.797 108240.023 109067.070 81242.383 46440.191 27506.908 22857.529 36224.965 24739.850 23269.252 25855.148 11550.024 16102.612 12994.307 21153.305 15748.858 9740.906 5870.067 | |||
|
244 | nan 416525.594 496825.281 599643.562 659455.000 789146.000 728028.438 644632.750 539932.250 459500.375 365159.344 277450.375 230769.047 161764.094 98809.258 97261.977 84591.695 81179.406 49305.977 42265.023 27006.523 15504.669 32093.205 29774.029 33720.484 17771.795 11339.179 5756.161 4347.938 3470.250 3690.744 1765.156 | |||
|
245 | nan 557113.250 423157.312 534517.562 738596.062 706805.812 660022.812 612055.500 477450.000 379887.531 320456.875 223662.703 171256.359 114157.297 118130.906 57977.047 50732.285 50721.910 45614.621 16298.559 35487.379 41219.906 21485.061 25521.852 15512.534 16160.267 8406.243 3121.311 3789.022 12299.726 1063.807 1869.382 | |||
|
246 | nan 536842.125 577744.375 610648.375 613885.250 700358.938 682858.000 602217.750 486394.125 439038.375 233184.906 223900.250 149730.016 143576.922 77926.867 61983.438 49707.176 52154.734 42639.191 24345.361 23327.121 13882.225 30159.756 35131.086 51330.504 94204.062 86687.906 124041.219 86522.617 66821.516 68171.336 29284.438 | |||
|
247 | nan 680622.250 737964.938 740216.438 760126.250 736742.938 759178.750 589512.500 473306.906 321418.531 288096.500 222471.297 166239.438 147674.953 92217.164 64703.828 61328.590 58648.812 31619.686 32146.676 25996.773 25189.611 15726.110 16113.237 14666.488 13961.156 17836.305 15701.612 14209.510 18374.430 14801.774 19660.564 | |||
|
248 | nan 637070.188 771427.375 749177.938 749047.812 749773.875 791744.438 606179.750 512516.312 405122.406 288576.844 238562.234 185683.219 141943.547 126060.867 66707.992 65863.328 44883.570 34507.941 28684.188 28879.852 30222.508 24916.148 17503.508 19857.420 22698.596 20115.355 19393.102 37482.484 51678.434 27474.357 36326.762 | |||
|
249 | nan 637867.312 653314.688 749969.062 816031.438 784826.750 756348.188 613965.188 499600.812 433667.281 325110.031 284140.219 177613.141 122508.773 110908.570 93643.547 69043.633 42417.062 45005.496 43792.531 36412.602 19461.457 36904.672 36774.875 39951.016 49476.578 76083.164 116306.430 78927.141 82680.398 57172.473 49527.898 | |||
|
250 | nan 804648.250 703204.875 783506.438 766678.625 677926.562 685744.375 668929.562 449545.000 456497.812 339399.812 278593.938 173906.453 118905.406 100064.867 74230.031 24007.064 57721.449 27147.633 50974.066 12835.369 17319.555 30822.074 63052.477 47640.270 39945.652 55484.285 64484.637 78962.070 122607.883 115371.328 89285.656 | |||
|
251 | nan 878624.062 709390.375 801635.625 733421.688 671568.375 601913.062 592017.875 518209.469 383932.375 299102.094 254917.000 192490.438 123990.148 106888.844 100686.750 30113.139 39779.375 39437.387 22295.238 19004.795 22352.037 20566.939 12142.212 16679.896 26878.201 25788.256 9500.669 29273.818 32378.363 26397.074 37370.793 | |||
|
252 | nan 808929.812 852094.812 741176.062 675877.750 714367.250 515880.812 530573.875 425676.219 390536.031 262405.969 228043.438 140818.531 115056.578 83295.859 68740.164 48102.527 24220.830 46857.770 38179.328 53213.875 32305.701 38455.652 44978.234 46825.172 64649.453 77257.195 89714.344 144129.266 142183.594 116673.047 110250.945 | |||
|
253 | nan 954469.438 924214.812 761548.625 670082.125 656187.000 575456.688 435476.625 387391.312 372847.969 277134.344 171855.266 173586.016 148673.312 104079.023 70428.180 60782.191 48201.047 32691.842 37048.711 22345.086 14253.815 22699.336 35662.414 57033.387 66203.180 89775.367 102356.492 113815.117 152798.438 200647.859 167672.609 | |||
|
254 | nan 1106056.125 968736.812 902128.812 608647.250 533021.188 509581.094 465338.625 322600.281 262759.906 253370.234 195559.203 140731.000 98869.492 77026.398 68549.758 48040.648 32239.586 31415.342 82582.320 112893.047 92580.430 105311.531 137557.375 157775.891 125499.875 90280.641 217915.500 338888.781 365807.281 355274.844 332027.438 | |||
|
255 | nan 1001982.000 857967.438 889970.938 724101.438 626882.938 549112.062 531233.062 355179.406 313231.531 207576.484 235995.641 157622.969 114142.930 75164.156 32976.617 31651.406 33105.754 12555.766 28040.861 25947.738 15625.688 26706.338 12030.750 16826.961 20268.949 9340.754 11650.340 9755.533 14137.022 9197.252 5796.223 | |||
|
256 | nan 1219634.500 980517.438 880922.000 788588.375 605405.250 583528.625 502426.594 427400.406 249100.859 257586.438 186135.797 114838.945 99823.133 57590.141 57273.051 58117.703 28486.182 18452.553 17973.004 29079.404 20964.068 15032.338 8902.799 11752.669 19518.939 4368.568 15943.017 11498.628 11917.897 15491.585 14112.546 | |||
|
257 | nan 1397940.125 1185028.250 926166.250 809047.562 661573.438 469776.906 512236.031 388021.219 276370.438 276363.969 210795.500 98296.617 96322.625 53616.941 46383.664 42383.297 32206.648 28075.029 25904.539 15323.881 6039.602 17628.568 13862.372 9663.045 10146.095 3953.578 10028.811 12940.176 9476.132 7008.859 8338.819 | |||
|
258 | nan 1387320.125 1471035.125 1058237.625 817003.750 617091.375 492500.719 475090.531 426340.500 315411.938 220960.359 149236.688 159391.891 79683.867 42776.902 45241.762 30413.793 34301.875 24228.268 17531.305 29441.670 28757.811 25421.225 21052.664 25026.211 26133.051 33188.531 36830.027 34192.441 29500.883 32039.676 18083.434 | |||
|
259 | nan 1532774.500 1611795.500 1090506.875 771578.625 596103.938 540499.625 504348.125 356560.219 333724.812 201727.062 178550.750 135429.250 81686.133 69534.789 34069.621 36297.348 24771.105 33844.652 9587.066 13744.921 11002.118 20209.701 5928.026 5819.918 3626.675 5430.424 9389.441 9696.168 9133.013 8415.878 14101.894 | |||
|
260 | nan 1404801.500 1662617.125 1241779.000 761595.625 691101.938 652034.250 504515.688 391748.625 298104.375 282958.031 162913.531 138284.516 94937.992 79881.203 55495.215 32575.182 22391.873 29810.883 28567.945 15914.395 21261.658 15638.416 33977.402 20326.551 16838.623 28194.895 17238.986 24193.332 19411.387 16885.748 13151.074 | |||
|
261 | nan 1512249.000 1850447.625 1399063.500 781169.000 651463.062 538034.312 502688.531 427614.031 255543.312 158778.016 145441.734 139143.859 79941.547 74914.734 40658.566 44914.906 30063.770 19843.895 26464.436 9607.517 18223.320 7690.399 15114.142 7826.424 16852.936 10964.249 20691.625 15640.290 20978.637 16631.568 7060.760 | |||
|
262 | nan 1373579.875 1697563.500 1386471.625 880391.812 539514.750 559906.188 490410.031 394664.594 315065.188 157321.344 129420.125 94256.070 90061.820 76543.961 63747.516 28219.232 33111.559 31245.076 22265.076 22491.582 24620.102 20047.119 29506.361 24761.943 27155.705 23713.795 21786.508 22183.850 25420.074 21935.033 21333.281 | |||
|
263 | nan 1598209.625 1955271.250 1754371.500 1021733.750 597410.188 575605.562 537576.938 418131.719 284855.688 174942.922 109214.125 101798.227 68402.703 86953.070 37236.668 37449.242 21307.611 27303.693 18748.707 10220.593 21053.320 10059.213 24858.283 21583.080 13803.815 17683.242 23940.781 29594.357 20961.010 18647.406 21328.420 | |||
|
264 | nan 1501992.875 2187798.750 1791672.500 1107464.625 741193.062 504690.094 537206.750 363141.219 270145.625 156050.156 115287.781 116899.523 81282.648 62072.035 47055.559 43688.031 51542.059 41709.340 16675.260 32753.307 22101.725 28058.949 28429.600 13606.419 17337.143 32646.232 21761.553 29611.164 28865.008 20183.402 20492.799 | |||
|
265 | nan 1397115.125 2209492.750 1936222.000 1199219.125 749673.438 574907.438 515652.969 447348.625 311152.969 161270.422 79592.352 100711.031 70891.211 62370.125 69405.445 45458.785 24482.787 32848.457 27044.074 24459.137 28524.674 32809.641 45244.234 23347.883 19098.229 26699.846 25382.557 37179.691 45373.934 32597.443 29398.502 | |||
|
266 | nan 1304387.875 2135144.500 1953861.500 1093536.125 668374.125 491791.625 462207.688 422311.906 307294.500 214056.641 175385.859 158119.875 121005.047 80522.117 56996.348 59503.723 63825.988 25620.076 34302.871 26581.451 21040.361 26932.523 29580.512 27036.613 43253.473 39190.781 29987.494 34266.566 47504.738 39388.566 30279.883 | |||
|
267 | nan 1448674.250 1813902.500 1940127.500 1334484.125 704107.562 534718.750 477869.031 432570.094 307825.375 200749.344 141221.875 147977.031 110227.227 97660.727 58041.352 37367.590 31262.268 18446.795 15841.625 17210.164 2698.768 4614.972 18174.570 7904.357 6160.981 14106.812 25213.770 29371.477 21307.205 21062.623 28364.770 | |||
|
268 | nan 1874438.875 1901802.375 2279600.250 1378911.125 733951.812 549941.438 556335.938 405100.719 302752.469 163424.656 144150.594 158495.234 95443.648 65340.891 44810.297 50762.691 31440.588 31407.686 32172.812 32073.439 22671.639 12648.091 37126.422 27447.988 32860.973 33424.031 32744.488 61698.699 42962.453 51570.875 55455.023 | |||
|
269 | nan 1779331.875 1893302.000 2254604.750 1450478.625 747411.750 632444.625 480155.000 388788.688 300907.375 206463.750 200384.547 140215.359 102974.430 100532.953 69928.125 48488.434 27713.039 12716.228 12598.513 4392.421 8178.764 5640.979 7670.811 12135.296 9199.694 12486.116 17164.916 16991.305 9554.632 11764.368 13809.485 | |||
|
270 | nan 1598349.625 1854432.875 2220033.500 1555920.000 815145.812 557188.688 546775.875 509820.188 275608.781 351025.812 266274.281 178139.969 103257.797 47049.324 30783.037 15255.778 11447.976 5722.573 17186.738 21369.354 22474.049 22298.184 16418.381 25064.814 10636.109 12808.828 13802.801 19519.660 20665.117 16612.529 19311.420 | |||
|
271 | nan 1459702.625 1925545.500 2129080.250 1740908.125 869108.750 607090.438 484822.219 434677.312 359592.719 272811.531 233692.344 185410.062 102052.875 55493.676 32149.174 22269.799 9510.586 7115.894 21953.104 18119.939 19587.523 9736.136 29229.287 23770.961 30249.711 14342.032 31041.217 16849.023 18969.404 23379.133 17515.275 | |||
|
272 | nan 1617910.500 2109086.000 2288436.250 1785899.625 844306.562 638882.250 521561.219 456020.688 457736.281 306271.812 217230.406 153167.312 82380.969 47579.574 27975.033 19347.131 18142.400 46057.949 18029.084 24701.932 18833.170 30539.664 8369.892 26637.881 19682.744 16331.719 15535.281 14314.475 8597.389 18273.064 4605.242 | |||
|
273 | nan 1640235.625 2210042.500 2496727.000 1711109.875 921626.375 704372.812 551583.500 453288.406 473989.188 368439.719 245145.094 107049.023 51915.566 37704.859 27320.293 38708.297 40621.551 37495.734 34151.141 17810.281 25082.418 18221.559 32593.799 17904.910 30334.693 28330.154 14923.251 16677.357 21057.570 10390.385 11553.451 | |||
|
274 | nan 1745358.875 2245066.250 2326935.250 1781322.875 885729.188 738886.750 577368.688 557923.750 421733.781 252789.891 156950.750 70348.930 53061.051 22478.949 63929.887 40338.621 58588.285 67406.484 66372.266 40676.621 45588.023 16384.283 18548.070 32040.846 29062.830 39173.242 16666.113 18293.746 17453.232 13227.452 14930.822 | |||
|
275 | nan 2130667.000 2630968.250 2639281.750 1699487.125 972564.438 764730.250 610209.750 488669.781 413416.906 273313.750 198987.750 117163.398 53919.551 16805.150 27520.580 60660.215 41932.957 49339.965 44663.328 42131.578 76534.930 58679.277 39664.531 41459.391 36643.359 43808.082 47810.777 31566.062 25178.133 22921.215 24931.994 | |||
|
276 | nan 1962460.375 2608406.250 2833022.500 1859235.250 1087960.125 772668.250 640436.062 604654.812 498816.094 250284.000 132097.766 77420.195 57124.961 51169.797 71622.172 58930.664 88872.898 70111.203 55401.984 15946.696 32081.283 38368.457 26216.189 29823.574 24277.898 19064.242 19086.852 23075.066 16336.376 25096.512 13270.649 | |||
|
277 | nan 1984375.625 2687219.000 2933741.750 1772577.875 1049654.875 842269.375 754581.625 659498.375 409656.906 225631.641 100206.078 87370.094 41371.598 82390.641 64584.359 83043.375 78916.086 36882.625 37161.484 36190.113 31135.787 39310.027 29801.049 31501.699 46934.754 22670.162 25457.807 31624.693 19185.189 15579.062 17589.268 | |||
|
278 | nan 1906132.750 2623840.250 2812692.500 1883202.375 1026143.188 906240.938 754391.062 602176.000 382118.625 199545.797 93778.492 86066.430 91707.148 83396.398 112582.156 71776.195 57961.859 41053.742 42279.695 30421.221 21678.100 29515.592 49601.488 33542.211 30048.842 35646.727 25959.654 23179.830 25240.758 28944.717 23399.395 | |||
|
279 | nan 1950959.250 2615714.000 2853267.750 1786667.250 1007196.562 865527.062 811316.000 639944.938 378884.000 196934.594 127492.547 51651.223 94763.578 86166.055 126644.031 47209.754 39870.418 46057.148 37336.273 53531.312 20646.420 42164.895 33549.422 39785.422 48730.703 69338.805 26043.537 28079.143 27891.074 38617.117 14706.978 | |||
|
280 | nan 1806515.625 2445845.750 3056127.750 1853880.375 1177577.125 922563.812 763139.188 514194.125 317699.125 195919.453 121876.430 53601.551 79714.945 87337.156 90290.305 58959.641 38413.441 40861.277 34921.812 42246.359 31321.732 38124.152 36814.672 67988.555 37395.047 30377.557 31219.344 26536.951 27470.711 29440.613 14495.435 | |||
|
281 | nan 1905666.125 2517567.750 2882405.500 1800393.625 980745.250 869347.812 752372.000 607629.938 339279.031 214723.344 104588.047 76236.219 123790.469 115881.945 96405.578 76712.930 60036.977 46812.465 35566.598 26386.867 31942.930 45413.176 54369.238 41904.785 54664.336 33847.590 21101.279 37316.281 37157.871 17150.080 43732.711 | |||
|
282 | nan 1859265.250 2622307.250 2920585.750 1949707.125 1068838.375 1057678.875 851816.812 594013.188 332830.531 212757.594 85915.094 89906.055 101409.594 130875.594 92613.914 41064.496 53275.715 49819.109 37599.223 51718.848 41806.539 47706.965 41478.176 47259.590 52224.973 54500.363 42180.805 26913.908 32125.062 34772.371 28789.912 | |||
|
283 | nan 1898617.125 2579683.750 2906881.000 1800537.250 1103055.875 943727.188 830818.188 561994.062 327761.938 196686.500 73379.508 105239.492 111678.430 104348.320 72678.609 59062.625 44012.676 37293.141 55137.613 35049.543 49374.234 45133.152 47804.688 41409.559 54797.309 34744.660 68384.719 46235.102 29660.369 30811.574 57970.527 | |||
|
284 | nan 1909825.500 2528058.750 2926901.000 1765989.250 1030683.812 931975.562 774608.375 593888.875 306354.469 134856.781 101092.883 66107.641 125442.469 137858.344 77000.844 73411.867 61274.547 49392.859 45994.004 38962.039 40770.848 30264.906 50466.602 35692.484 50568.438 40124.590 44525.922 40185.984 44257.297 33452.949 28903.725 | |||
|
285 | nan 1880190.375 2472342.750 2986270.250 1852753.875 1085000.875 1029477.250 755451.812 500013.188 279548.625 170373.734 112954.945 101335.930 118810.703 130587.758 83159.852 40640.969 40562.672 34953.773 57401.625 45170.762 37080.344 34344.160 43568.609 57255.762 58822.664 43830.172 49153.891 33103.887 35625.770 26827.289 31854.957 | |||
|
286 | nan 1796283.625 2584970.250 3063251.000 1669069.625 1095407.625 956462.250 904329.438 549830.062 281894.719 181780.609 106673.383 122990.680 123471.648 133080.438 72937.688 53033.172 40380.746 47194.418 50651.203 54058.426 45393.453 34648.359 42493.250 30640.389 41578.422 45488.012 44673.285 37042.078 32488.023 26735.301 30550.426 | |||
|
287 | nan 1889218.125 2447991.000 3011114.250 1780666.500 1103202.375 958684.562 902387.062 495092.125 263170.000 143880.516 95807.273 140100.984 154814.672 110882.148 79495.820 64314.527 30524.350 64389.789 39462.918 35047.090 39768.859 35261.000 43516.539 62752.301 43731.160 30179.836 41008.367 53024.262 37045.180 31083.367 39584.516 | |||
|
288 | nan 1844494.125 2325053.000 3031274.750 1646125.125 1141288.750 956660.375 801751.000 541806.188 255860.641 187046.656 87721.039 149182.672 168452.016 143835.641 63827.648 38927.664 49375.863 55324.602 53349.590 54407.152 44802.590 42368.152 48549.223 52273.234 30547.395 38094.828 33815.926 57942.926 42262.410 38029.578 46498.703 | |||
|
289 | nan 1844589.875 2445810.750 2870796.500 1878868.750 1093006.250 1035965.938 918223.562 571201.562 273390.969 181573.766 110131.328 153441.594 154557.016 112647.305 76977.742 35697.793 46383.016 38413.465 45845.453 52553.512 30658.619 52178.598 49448.113 47290.090 43676.660 47422.340 41049.832 54365.359 50135.734 31075.188 32337.176 | |||
|
290 | nan 1800669.125 2326264.000 3044541.250 1741438.500 1192563.625 990561.438 872181.000 531750.500 280501.500 161944.359 99621.719 123153.719 133654.969 84061.133 74531.547 45254.887 77129.508 34115.016 45914.625 64221.012 36002.879 61196.012 40145.715 52948.379 42427.953 48485.051 50876.023 48471.516 37894.156 48724.539 37801.711 | |||
|
291 | nan 1846533.125 2237696.750 3048994.500 1813010.750 1077171.875 1082370.375 758770.125 556032.438 284907.719 199164.703 95946.508 124549.180 130012.406 95945.523 78916.078 48279.590 62767.375 33151.090 37177.828 51555.148 49291.461 48386.336 50200.004 67523.211 54378.277 63873.453 60068.660 40572.418 46855.215 28938.205 25448.850 | |||
|
292 | nan 1815597.625 2188361.000 3054915.250 1841923.500 1160242.875 1051950.125 827477.812 532888.938 259153.406 145528.297 91427.695 119939.445 158975.516 86238.203 69593.977 61280.672 52794.641 44660.547 46490.324 37626.059 73857.062 56633.578 70708.258 58094.777 60291.910 59039.012 37257.777 58412.773 45894.754 43098.762 54330.684 | |||
|
293 | nan 1674132.000 2178583.000 3158455.250 1818415.250 1118511.875 1024794.938 832879.188 443395.969 313066.031 177636.875 100721.805 142748.547 92731.609 89069.766 91933.945 67338.258 58038.688 52005.129 42875.809 68954.305 72505.062 71815.656 56590.711 70338.930 51741.422 65214.828 68490.281 42287.754 51066.262 52864.652 29482.914 | |||
|
294 | nan 1744929.625 2195492.750 2997669.000 1781301.125 1230525.875 1082409.375 833261.812 445388.094 281452.969 192212.266 133598.516 175899.344 117673.367 91926.297 72618.445 56724.688 59902.238 64859.691 85428.102 38367.027 58060.449 63266.227 59553.309 62297.777 65653.820 70083.922 81853.828 47922.703 43861.160 52431.184 44048.797 | |||
|
295 | nan 1675180.375 2171032.250 3013881.250 1812469.625 1106471.750 1064564.750 792637.188 461120.469 278142.469 172655.234 137448.625 152581.703 132948.219 96969.422 82781.867 70157.117 36991.586 55068.137 68687.227 76868.492 60769.449 67865.234 53696.074 50680.750 69497.906 49235.152 79157.523 59644.391 59424.434 59144.434 53575.125 | |||
|
296 | nan 1748828.375 2012234.000 2798122.000 1829419.875 1206425.125 1132028.875 886200.000 461807.625 224061.938 157892.094 163530.578 157429.516 99584.297 79959.469 103470.078 52777.074 56615.934 64296.066 64651.234 52722.441 78761.516 74215.438 98595.805 76967.758 79287.281 55972.012 50371.527 49101.086 53292.664 47057.340 32674.779 | |||
|
297 | nan 1709906.875 2079360.125 2971460.250 1832871.125 1213177.875 1079008.875 814815.000 465340.688 274910.875 141521.656 140877.500 193738.734 140616.828 69957.695 87372.398 78958.352 40211.598 65972.992 60007.648 65715.242 78960.078 110037.383 99468.602 77029.852 82444.969 62690.938 54861.422 70115.820 45474.473 41486.156 54809.637 | |||
|
298 | nan 1693838.000 2016462.375 2930413.500 1788993.500 1333533.625 1082736.125 830255.250 480048.688 222250.406 149628.359 156243.047 201689.047 119235.555 101079.742 105322.547 42111.254 74172.383 64285.254 84944.172 108352.656 129266.547 100636.430 96654.977 76648.344 80873.430 61479.535 53983.852 47587.172 43765.438 49496.262 41021.766 | |||
|
299 | nan 1721117.500 2001469.500 2980176.500 1812220.875 1185560.375 1133801.625 807329.250 450232.281 241071.406 107419.680 152132.688 176475.781 133490.109 92529.117 64538.523 63460.664 49330.152 71796.055 97513.719 102621.969 83297.297 70661.414 85908.617 65458.648 83365.117 66830.969 46491.766 67906.906 50790.676 34962.438 34189.527 | |||
|
300 | nan 1699158.875 1839909.625 3133841.000 2035563.625 1295429.750 1117403.125 849281.812 475576.031 219360.859 149417.438 174528.781 192313.953 109639.398 100335.500 55179.949 74446.117 73791.125 80188.156 91974.180 133535.172 89022.156 61534.223 63881.000 65859.438 85302.219 77927.555 64633.160 49606.914 43815.227 37207.621 42266.770 | |||
|
301 | nan 1710041.625 1879353.625 3083533.000 1967920.125 1280469.500 1163814.250 798692.562 492041.000 290259.031 146291.844 183710.328 198717.641 130509.320 81725.375 69765.828 80833.562 54039.898 123608.078 137320.500 106580.773 65987.414 98988.273 57275.176 55816.387 64587.000 59200.039 64040.961 45005.328 36367.648 46436.828 34522.871 | |||
|
302 | nan 1589467.875 2005182.750 3064328.250 1934685.875 1360640.625 1104606.625 833721.062 451612.688 255167.594 134597.109 223462.094 193315.594 172792.250 77074.852 75766.852 69958.938 112874.883 118540.867 142344.984 128398.672 85685.117 64447.234 80805.219 80825.281 86952.648 57702.098 53533.801 58636.766 62605.336 44526.137 33601.641 | |||
|
303 | nan 1664661.125 1772704.125 3066721.750 2084037.500 1223188.500 1105071.000 750747.938 453513.594 285721.094 145745.500 207340.734 171669.609 148714.781 87057.500 80217.883 77947.180 126066.328 114843.594 113266.555 91464.531 104495.617 86543.789 61037.402 47182.688 83266.531 71311.969 56626.527 44543.758 45083.004 44687.387 41386.797 | |||
|
304 | nan 1606334.750 1924942.375 2901464.500 2031575.625 1326781.875 1202169.500 783296.750 508841.281 244137.297 162033.516 219634.844 142730.469 129190.555 86753.516 76925.008 79674.430 131323.141 165848.406 165988.609 120440.305 91566.117 86585.352 63898.496 89911.000 72746.875 75756.625 60037.473 43755.895 45321.641 36371.539 50462.363 | |||
|
305 | nan 1495847.750 1772590.750 2842375.000 2243313.000 1376262.000 1133821.875 882558.250 497505.125 266064.594 205402.109 207011.000 154223.188 136546.875 100363.594 89360.633 122039.680 170594.531 190001.641 146483.734 92078.406 93897.758 87431.719 101312.727 76235.102 80846.305 63872.777 67780.195 71557.258 61024.223 38686.098 36528.602 | |||
|
306 | nan 1604234.375 1824119.500 2857944.750 2159879.500 1429905.375 1134351.500 908595.562 366243.562 256785.516 167129.531 246376.984 153607.562 156396.672 116756.797 114742.453 133048.562 162713.031 228310.594 152234.812 105127.852 101964.453 89518.789 72763.102 63866.977 60984.012 77629.883 59297.562 57860.938 37048.168 41649.523 35720.738 | |||
|
307 | nan 1503344.750 1672512.500 2929082.750 2127399.250 1342387.125 1150344.125 859935.000 407782.719 183162.875 164271.859 221332.453 170532.188 121568.922 86282.008 114956.648 118811.945 172338.266 141937.234 116946.273 101522.328 96099.070 84066.289 77299.617 78825.156 69068.305 60224.723 51824.527 43886.770 53702.203 37012.703 46011.348 | |||
|
308 | nan 1610940.875 1560968.500 2841047.500 2215083.750 1423949.125 1205241.875 788567.062 504246.719 253851.438 223811.094 206126.016 179830.234 131812.766 96791.508 114323.750 115008.000 174985.234 141682.984 164476.391 87842.977 61225.598 70446.688 70107.750 63030.484 75736.562 41537.867 60516.285 59489.785 66308.633 43974.477 59321.312 | |||
|
309 | nan 1473867.500 1511302.750 2915211.750 2188337.750 1515661.750 1218989.875 926639.750 437674.375 215502.891 189097.344 246279.484 168900.406 128192.133 96664.000 104430.844 128943.633 189797.812 163667.359 130010.945 97175.617 87441.070 72224.484 78441.297 67316.781 67178.633 59015.996 61475.836 55087.840 46508.434 59839.812 35756.973 | |||
|
310 | nan 1460632.000 1522872.000 2835725.500 2339125.750 1395822.125 1283210.500 939518.000 422629.219 230603.609 203508.062 240147.453 193991.391 138262.047 127680.633 107513.297 174643.891 191651.250 169722.516 102575.281 87223.586 92355.602 50744.938 75630.617 55629.879 48681.652 80491.797 63880.676 50174.938 64603.746 52818.523 49664.199 | |||
|
311 | nan 1381896.375 1524965.250 2802135.000 2264615.750 1426133.500 1362388.375 1010920.438 429838.500 265096.406 214621.250 231588.156 158983.297 113343.555 108127.656 120210.758 174533.484 178794.281 87748.555 94621.805 60224.766 86534.500 65258.773 67523.281 84874.633 64927.316 50322.410 54881.465 58857.973 54615.461 71071.961 37006.938 | |||
|
312 | nan 1510272.750 1411027.250 2751775.250 2325543.000 1487378.500 1356726.750 794708.438 486563.312 273039.531 221893.688 171258.516 211215.984 147563.953 106759.500 118636.492 155690.297 166946.188 90521.945 100175.992 72062.055 72643.133 87693.445 57549.703 67670.281 65055.246 50644.859 64046.852 53686.926 56391.734 57248.289 54899.363 | |||
|
313 | nan 1485947.125 1358786.125 2611789.000 2430719.750 1458593.625 1333094.625 851724.938 499991.500 282875.469 237890.891 239620.141 192886.266 153476.688 88733.805 139940.078 200265.984 137534.500 94047.234 81473.164 86230.430 57258.129 79167.609 50737.797 73235.508 60814.750 50933.277 60030.891 58843.641 61246.500 62693.578 58868.234 | |||
|
314 | nan 1436548.875 1329848.500 2478736.500 2402130.500 1495873.375 1211619.500 805861.812 395449.000 224150.609 263044.219 258906.516 186495.109 122119.500 117567.695 214725.766 182093.266 130699.180 96743.797 89151.227 86209.398 85067.648 71085.422 71835.984 48862.902 58263.887 74295.305 46662.000 63296.289 68036.609 40633.637 65042.227 | |||
|
315 | nan 1533994.875 1308638.500 2378930.250 2435888.250 1625975.500 1222926.000 961451.375 473300.594 242824.000 288541.062 249760.547 193734.250 125119.102 144882.984 194291.266 127156.148 102746.383 89426.688 93377.664 81045.258 65896.117 64195.875 67221.828 64834.637 58217.273 47057.477 70403.859 76264.055 64852.152 71325.648 72625.969 | |||
|
316 | nan 1384890.500 1286425.750 2362285.750 2462232.750 1545722.375 1281123.000 784826.188 522575.281 297939.000 257745.484 250576.594 174640.984 155369.047 128045.180 205534.406 147989.438 85586.195 96635.445 79459.250 81002.805 83304.164 70244.555 79407.414 58023.066 70882.734 71370.023 84108.945 92944.383 80173.797 62689.324 76721.930 | |||
|
317 | nan 1466457.125 1263406.125 2181122.250 2325383.000 1488035.125 1267765.125 891087.812 442171.375 227355.000 348836.312 187767.328 199658.406 123318.047 107693.898 163160.031 114456.430 102515.320 69186.820 67524.977 91593.586 61049.191 53398.379 76613.484 84973.016 62851.547 64574.141 80862.641 69095.133 71875.617 51924.824 59451.500 | |||
|
318 | nan 1484263.500 1269282.125 2087541.625 2421385.000 1585722.125 1293885.125 918562.750 403756.719 247310.312 284792.000 252578.766 202772.547 142502.641 149725.062 168379.766 100313.469 70991.266 87524.156 102517.375 68756.172 57113.660 77124.680 66843.430 64535.625 80773.492 90920.250 65263.996 86018.055 59412.578 68026.500 66873.508 | |||
|
319 | nan 1546693.625 1169926.875 2098663.000 2236209.750 1664085.125 1344846.625 835292.062 379292.719 246580.062 296526.469 234365.891 205442.797 115264.430 182470.641 206511.609 136962.672 84764.117 73671.359 80835.180 74604.156 59282.910 80461.109 102338.094 74981.945 69103.281 89047.062 84935.344 95569.031 82697.805 80717.484 67339.414 | |||
|
320 | nan 1422670.375 1150535.250 2115182.250 2229905.750 1418050.750 1302506.125 742359.938 431910.406 304041.812 292664.594 231012.312 190607.578 145025.969 153700.562 154695.938 90413.055 107740.227 69138.133 93474.180 97042.930 69108.000 64760.715 69278.445 80802.891 95126.953 82733.930 88182.820 65339.246 93600.867 58299.602 83204.602 | |||
|
321 | nan 1556807.625 1197287.250 2112201.250 2353106.250 1725325.125 1300495.500 745212.062 377215.406 207502.844 284442.062 252413.484 151785.250 135128.234 164775.188 151498.297 96480.047 68856.258 85306.375 80550.414 84935.586 72389.992 83387.297 80182.977 73107.555 82759.430 63907.926 96658.555 86747.367 81983.719 62837.621 50306.199 | |||
|
322 | nan 1565156.750 1234133.625 2072345.250 2404368.250 1612969.875 1256920.250 756202.188 424486.594 277491.156 322030.531 250288.516 206413.062 161227.594 189641.438 130592.844 73645.570 87647.906 86878.156 75157.883 71550.242 65088.066 67598.062 84571.250 85208.820 130111.148 95362.867 73607.695 92669.180 131046.242 84188.492 77794.984 | |||
|
323 | nan 1561887.875 1201527.500 2014229.125 2410008.250 1727967.250 1335478.375 800968.188 400809.219 296245.031 342118.969 254926.859 146503.391 174065.859 198822.344 165283.141 97866.125 86006.375 101836.258 96497.953 70189.016 71341.133 88868.617 82044.797 81523.367 104151.648 104605.570 118745.352 99655.867 97843.922 89403.000 84923.273 | |||
|
324 | nan 1419315.250 1200244.500 1845875.500 2320465.750 1639373.500 1365446.500 881129.375 368643.062 332157.219 357778.094 221851.234 179305.188 174541.266 161515.188 104244.906 97165.406 69140.188 81191.008 84952.359 70761.977 67319.555 87172.148 76895.234 83966.219 99940.906 98509.820 110960.203 108336.000 75514.930 104254.469 69337.930 | |||
|
325 | nan 1484635.625 1201147.875 1887336.125 2320396.500 1695871.875 1441525.125 819999.062 374622.031 286968.969 342154.875 226672.500 190098.469 160753.234 149541.141 99484.477 133405.203 101445.547 105376.797 59913.938 95515.727 87060.828 102500.203 75057.602 122158.023 100825.844 81091.266 84498.094 97021.703 97930.242 58441.113 38932.812 | |||
|
326 | nan 1434850.500 1172225.000 1926092.750 2297493.000 1790044.875 1265469.875 820682.938 407530.375 310566.219 359207.406 242150.359 162926.375 188272.109 173880.641 136324.906 131566.359 82092.195 118693.703 97388.430 80722.891 96492.078 117081.219 98569.930 65343.434 79723.445 95935.922 95762.477 120523.828 92624.242 115388.992 82237.133 | |||
|
327 | nan 1348948.750 1142680.875 1937088.000 2360415.000 1821508.125 1245421.250 728265.250 370754.625 296951.062 317645.188 224332.000 173614.562 208075.359 164133.250 141018.516 82732.031 69395.680 82214.578 92050.523 88195.359 97820.719 115293.883 74554.617 59937.516 81289.281 86466.523 110765.453 87923.367 100134.758 74446.445 64504.254 | |||
|
328 | nan 1373691.375 1086681.125 2089706.500 2315212.000 1871988.125 1433646.375 847252.062 407690.125 293604.781 346985.219 202324.750 173620.469 216462.344 161117.766 115211.328 106233.375 94058.992 84745.844 91669.367 101061.023 107794.625 99055.969 90180.180 81853.156 130188.430 101801.328 124647.430 110269.344 123091.328 105062.875 109666.844 | |||
|
329 | nan 1389964.500 1059310.000 1985463.875 2418365.750 1786208.375 1440932.000 697728.125 417791.188 330979.875 292518.031 253664.609 164243.469 205388.797 164492.859 85079.664 80499.906 126539.406 81575.953 63152.727 87468.781 100213.633 77217.469 104145.875 68658.742 74871.984 108507.102 106033.742 81588.492 102183.055 79067.836 79929.000 | |||
|
330 | nan 1269580.875 1097647.625 1882618.375 2482023.000 1836310.000 1407764.125 832559.750 354696.125 374792.250 299294.750 230210.438 181545.062 259043.016 121411.031 115360.758 113707.758 82814.867 67578.320 113700.922 104115.680 97629.148 88837.688 97002.594 112003.094 85092.562 113638.344 102861.133 109518.305 86191.227 71726.516 72775.594 | |||
|
331 | nan 1203123.500 1041190.250 1939665.250 2398819.750 1919495.125 1289574.000 784328.250 349810.062 300824.469 370955.281 273751.469 205527.641 232526.000 106242.070 88508.219 95682.906 98926.328 60937.684 100023.078 79085.383 88145.383 85605.180 107069.633 108655.625 115716.070 94567.656 113030.727 105715.367 95883.523 74362.805 78237.094 | |||
|
332 | nan 1174146.750 1094718.125 2005907.500 2530138.500 1884005.875 1370580.750 803587.812 422219.188 322668.281 300301.250 209320.406 164695.859 170834.391 142127.062 96742.242 94718.000 89284.156 75293.570 97473.695 94020.680 111696.297 107165.570 93159.523 85149.328 80808.898 123574.555 124078.367 94420.641 105320.430 74838.195 92724.344 | |||
|
333 | nan 1144044.875 1056086.000 1905722.000 2619899.500 1953549.125 1440480.875 679860.562 381148.656 344274.375 336937.531 209676.047 191168.406 194856.484 116002.555 109256.703 62811.254 114468.469 102853.992 104399.945 100228.375 117583.203 103530.680 139058.844 96601.305 117153.820 93403.242 121148.367 137891.672 98841.227 104927.930 93504.555 | |||
|
334 | nan 1129568.000 1088680.750 1998121.500 2586932.250 1931205.500 1364877.250 794898.062 393328.781 341945.219 351041.625 233607.500 212173.609 215559.859 108372.250 87623.391 110971.531 92237.125 106434.945 105347.242 98675.531 90502.453 118043.172 149160.922 121461.648 116240.906 82298.539 97686.547 120393.344 102483.508 80849.141 101330.297 | |||
|
335 | nan 1241127.500 1045829.250 1923510.500 2729489.000 2003070.125 1340139.250 736310.938 382891.000 434205.094 338535.844 306246.969 212791.562 193667.188 132869.406 90541.477 86332.742 68167.844 79475.320 107163.352 95170.555 118969.430 122203.805 137273.078 104566.242 95981.250 75671.805 112213.742 90065.578 112570.445 78168.555 80739.047 | |||
|
336 | nan 1186532.125 1066932.500 1935779.250 2749137.750 2130160.250 1337360.500 661146.938 422711.875 405588.125 323549.469 289666.375 245042.656 158665.469 100725.648 134164.859 84977.172 92528.734 55046.797 126728.875 133363.109 90121.195 130571.023 121498.273 83937.305 114902.680 77523.484 98349.672 121546.492 100666.531 110444.656 91021.297 | |||
|
337 | nan 1125068.625 1037086.562 1986240.125 2810450.500 2178887.000 1479348.750 675734.438 406661.219 408822.531 315182.844 233665.453 218153.484 149219.766 150897.641 78518.945 89565.742 94279.180 118643.000 93083.773 89780.398 122599.500 129369.656 109009.656 143813.359 103652.070 128068.070 117853.469 105271.992 127107.242 108514.078 91224.805 | |||
|
338 | nan 1058267.125 1021074.250 2046803.625 2660401.000 2040363.875 1276456.875 653167.062 401771.812 414128.000 369142.531 275561.969 209539.203 141876.609 93732.391 70080.656 100502.805 110569.273 92263.430 80379.742 119632.617 118911.219 153778.969 141949.516 133376.469 93036.445 148841.547 128439.227 116370.680 136542.984 105508.828 75270.453 | |||
|
339 | nan 1089034.500 1132343.250 1988390.875 2737635.000 2129441.250 1364677.125 618763.875 422051.906 445156.875 324735.594 213417.141 272120.031 195593.016 109488.406 126516.797 104798.000 99730.594 110216.883 120893.906 88225.508 112675.867 130258.805 159469.047 138818.203 133553.734 139875.156 161963.688 168186.203 133967.641 136619.109 86371.258 | |||
|
340 | nan 1019769.812 941539.250 2097033.875 3066905.750 2134390.750 1391669.250 695782.750 415824.719 443350.469 418076.312 215241.516 284213.062 154384.594 114428.227 97600.242 72916.562 101798.047 129980.531 102725.195 113515.477 135683.766 132669.188 147161.688 126445.758 132545.078 145338.266 137034.219 123506.719 113390.195 99413.203 76492.273 | |||
|
341 | nan 980495.250 962322.625 2207447.500 3022215.000 2211876.000 1310010.250 673293.188 414627.719 476111.500 476137.781 263946.688 288211.531 171248.922 101249.352 109956.594 73317.008 102937.828 116548.594 93984.258 109171.242 117838.273 151458.422 115567.648 138950.984 149800.859 136073.281 144611.797 154265.844 125551.281 127885.195 115200.375 | |||
|
342 | nan 861059.250 828197.562 2098247.250 3170542.250 2214827.500 1273894.500 617398.812 503706.531 495352.000 394926.625 298418.031 273957.812 190980.359 104469.500 86229.445 94691.250 100952.633 128512.500 80365.305 115169.383 106400.367 113694.953 120741.758 131288.328 105174.602 94422.414 152714.609 149921.438 135939.125 103446.273 69950.789 | |||
|
343 | nan 946700.812 935041.438 2169365.750 3202259.250 2306612.750 1292329.625 617043.062 480469.312 501741.125 394700.000 203885.000 263630.812 154815.562 106280.594 85041.352 106382.953 86479.883 114233.508 100701.953 107898.656 128696.672 108330.570 95560.672 145089.359 90940.758 143279.328 126064.055 115939.805 138326.016 91729.711 81236.781 | |||
|
344 | nan 900015.938 1017831.000 2397911.750 3433735.000 2312676.250 1380153.500 666125.312 526166.250 473951.719 422273.406 267311.188 263342.375 229424.609 115076.602 118790.281 79539.188 117585.367 103806.352 68205.195 103985.367 104675.625 140941.828 93644.477 141071.562 102780.273 158936.391 159575.797 172347.875 141222.922 131864.688 93969.391 | |||
|
345 | nan 912031.562 902927.812 2265811.750 3561326.500 2293761.000 1261082.500 574808.938 440828.031 466603.594 438889.125 235881.562 259976.797 161637.750 121074.750 111335.273 94940.992 86463.359 83003.289 104969.867 91312.930 88514.945 132637.609 126579.508 124387.844 110473.219 116980.805 110465.367 125722.297 132037.484 126059.867 87541.562 | |||
|
346 | nan 768092.062 966263.938 2409678.000 3506753.500 2405032.250 1249322.125 574236.250 517438.125 579071.375 437997.188 241938.359 314614.906 194401.203 99329.969 120642.047 114802.508 91938.492 130730.875 93757.672 99719.578 132368.406 128756.078 88895.055 117104.273 65594.953 113165.750 111613.648 175794.469 132879.500 99966.469 132853.188 | |||
|
347 | nan 676647.062 882750.188 2584347.750 3617236.250 2379073.000 1179582.375 546212.750 537594.062 577763.562 387044.969 299044.688 344671.875 231770.188 112620.523 114223.508 87209.781 119040.727 129188.172 90983.023 56868.059 83241.195 136088.297 98936.477 100852.078 124318.594 112242.883 167136.391 173091.016 180851.141 144275.125 136045.047 | |||
|
348 | nan 691977.562 890597.250 2604420.750 3516280.750 2308859.750 1195391.500 590571.812 535203.062 607373.062 407762.531 256142.047 352451.688 213965.844 111811.117 139306.438 93009.133 108117.500 158599.234 92441.234 106144.727 118682.367 75648.758 97755.258 104081.695 80407.266 123478.180 146500.656 188215.969 172989.047 151776.391 146471.359 | |||
|
349 | nan 630634.375 891177.375 2617693.500 3669880.000 2330033.000 1101253.875 527440.438 560155.562 580334.500 422254.000 254845.250 365215.094 184465.609 137311.391 138568.141 100116.625 77063.172 106259.773 67031.000 90309.219 103736.508 83833.195 94434.438 97065.570 102984.945 121534.328 152663.625 134851.734 171581.609 184939.688 136975.656 | |||
|
350 | nan 524435.938 860609.188 2683274.250 3777970.500 2185923.500 1062159.375 572613.625 480296.906 640823.438 511504.781 242661.312 364647.969 237907.547 113730.805 106811.281 131780.094 138061.078 114631.797 106563.969 93236.906 95958.203 109313.578 95372.648 111898.008 91788.969 129610.969 213849.016 219999.500 211955.859 190717.484 123107.625 | |||
|
351 | nan 391601.312 895378.250 2890785.000 3908372.000 2222083.000 1033663.250 558061.188 668394.562 689538.562 397684.625 298509.875 380558.062 172892.812 95521.078 97391.594 122033.477 115573.453 106661.773 89816.680 81382.727 100232.828 97894.367 69515.016 77062.719 134461.359 161424.688 209454.312 200820.750 198044.656 145374.688 163841.109 | |||
|
352 | nan 354167.281 777020.812 2823958.500 3857844.250 2239378.750 1022340.375 638828.062 648050.062 693317.438 329259.188 282234.344 422787.500 176739.688 126527.617 180769.234 110254.922 125845.156 120464.148 86915.461 111844.672 82083.586 94430.930 72391.453 85897.930 142027.656 183679.750 210135.000 217412.734 205333.438 179790.500 161894.141 | |||
|
353 | nan 207845.062 742830.125 2798177.000 3881481.750 2176847.000 1000275.625 537606.125 736574.562 653547.812 387683.188 300227.094 399079.594 139311.266 115866.695 84855.539 132355.062 132839.844 108590.023 101127.195 86595.031 89257.195 76039.984 86140.727 108322.148 182865.828 170306.062 272463.969 303068.250 269568.719 211783.188 123108.227 | |||
|
354 | nan 161428.562 751528.812 2416078.250 3775861.000 2032164.125 1006990.000 570880.312 774710.562 699362.812 348684.969 377544.969 358644.062 206635.766 106203.430 127071.500 141663.984 158237.891 100541.953 107568.852 96710.328 113843.250 92207.945 97924.227 112193.281 159776.516 175765.641 266922.562 274030.594 306213.469 214536.734 183210.562 | |||
|
355 | nan 120520.578 699113.750 2269542.250 3890920.250 2169875.250 1034858.812 547162.250 748532.438 681430.750 372141.719 351812.969 352079.656 124081.805 124475.297 99334.125 136853.734 163689.859 95629.031 117208.453 117408.953 97899.602 96941.656 95289.148 151527.234 238293.953 255442.953 268061.031 249604.312 275642.625 193052.156 210996.156 | |||
|
356 | nan 102669.656 671847.562 1899071.875 3751648.750 1980902.875 924880.438 475632.281 792807.562 643260.375 364372.719 418002.531 438552.688 194923.734 151027.109 81742.406 176044.781 169111.484 112031.523 114899.742 87416.523 95434.156 88505.516 119612.695 172995.422 205730.812 269099.531 367197.406 292231.656 299379.344 267518.875 173444.562 | |||
|
357 | nan 84736.758 682968.688 1842922.000 3071906.500 1670723.125 814742.438 567739.625 817183.625 697161.500 352745.844 394163.188 410432.781 153377.609 148254.578 130088.875 158271.188 157021.938 148987.969 94607.508 121059.352 112525.523 72305.117 132706.266 130420.531 244546.188 340643.750 321625.875 295995.156 329264.562 238450.453 219442.641 | |||
|
358 | nan 114936.531 689758.938 1633299.500 2612272.000 1358990.125 786928.375 700445.250 894635.000 587206.312 306356.500 356051.469 408868.531 171968.453 156875.812 138571.734 135204.406 151010.188 98121.258 123560.320 111301.875 92271.695 139860.391 111854.594 143921.766 244619.312 297426.125 369278.688 371900.125 295130.188 255210.156 190187.141 | |||
|
359 | nan 103481.805 532646.438 1359284.750 2189360.250 1018621.250 734244.938 581216.250 878627.625 651225.625 303587.375 351020.812 455826.312 181625.594 125095.195 123733.430 143997.812 164433.281 134644.625 129618.508 92091.367 106046.344 89128.867 162847.062 147799.438 274011.188 458685.906 479062.906 412103.469 349462.219 247767.484 215324.750 | |||
|
360 | nan 95060.180 643215.750 1211152.125 1800551.125 1039763.938 766435.438 681439.375 1055881.250 712431.562 371731.625 340850.125 411174.219 165825.953 120415.203 166464.656 215868.703 155547.828 115137.500 126337.180 108328.695 144656.656 114428.008 188435.703 217481.938 384950.219 521116.469 439947.531 369861.156 332029.625 281381.812 206963.547 | |||
|
361 | nan 95084.953 517121.812 724823.875 1241591.875 1068919.500 637747.875 578338.250 999927.625 474222.531 364252.875 298741.312 364674.812 178096.141 167199.875 159217.062 190867.406 119249.469 135590.125 118584.656 140772.703 142602.172 104082.875 150114.797 207947.250 311061.406 413057.125 465110.906 364582.062 335310.375 188040.188 207249.344 | |||
|
362 | nan 99180.656 473024.469 476344.719 1075305.250 1002014.250 694701.500 604815.875 902889.812 569345.625 259470.000 353156.031 418221.812 233185.891 173277.984 162306.734 174271.750 159449.641 143055.516 158768.812 146236.000 140537.672 133037.281 226207.266 353737.031 406080.625 475879.031 441728.500 481058.000 307290.875 285459.406 242987.891 | |||
|
363 | nan 177229.688 417485.219 397662.406 1069778.375 949922.375 560486.125 718247.062 1020298.250 520603.875 276833.375 282192.844 478276.219 276317.688 166724.547 124987.844 165566.047 166382.641 178661.984 94859.055 160031.547 135826.938 175064.344 259735.094 417752.531 301629.375 419467.000 453550.781 476198.469 339507.062 304325.906 321415.500 | |||
|
364 | nan 111446.578 275085.469 334416.281 861073.188 999971.250 544854.062 693805.938 1004590.062 553106.500 293201.125 363924.969 356933.469 172441.812 152703.984 187275.312 150230.312 177688.250 137574.047 154380.016 206829.516 126597.398 190673.484 287633.125 422703.719 346501.125 449362.688 507316.531 443498.688 377889.375 254895.453 236958.938 | |||
|
365 | nan 151261.234 236983.859 242458.953 497949.781 937634.562 636966.062 808802.000 1027179.000 560760.750 358120.969 327602.312 374513.156 194874.359 253312.938 181469.562 224801.688 243018.906 192378.297 146483.062 160027.281 126778.719 204851.062 304709.125 347155.750 448732.188 482048.906 522051.219 504215.969 424625.781 395656.500 344469.062 | |||
|
366 | nan 162944.609 282725.562 160326.625 324873.531 874226.938 619931.688 812888.188 958528.438 559662.250 372787.156 374438.906 398659.812 255418.688 191612.547 180587.750 151187.438 188523.156 168882.047 202702.703 187149.484 164808.875 298297.062 330635.969 370482.844 497479.531 550180.875 591133.438 561217.750 465075.781 413128.094 347093.812 | |||
|
367 | nan 195862.312 200278.938 101229.375 246725.609 904290.938 506206.469 798808.750 913427.250 556392.188 346559.219 344740.562 521266.781 249853.438 275284.062 208496.641 236669.484 234868.188 192193.500 220323.656 206853.141 167606.141 338175.875 379074.250 472615.906 605917.062 675761.875 757149.875 679524.250 488698.500 429382.688 427044.906 | |||
|
368 | nan 175482.578 256956.766 143433.438 228248.109 874581.812 696210.875 796244.250 931227.250 548631.312 403783.125 394781.719 484715.469 317261.844 235441.391 233968.859 220098.750 181263.156 194357.000 229937.156 207118.359 262219.094 295319.750 356809.719 517742.719 599348.062 700699.375 721572.438 665018.562 584946.562 454953.000 405723.469 | |||
|
369 | nan 202183.859 203959.594 117422.750 262610.125 824507.062 662971.500 852055.938 942302.375 644906.438 444611.031 402288.625 467918.469 353296.094 288573.688 270697.531 261457.141 187826.203 205407.906 234011.734 267626.812 242751.656 341857.219 443316.219 549989.500 807784.812 783038.250 803383.750 748364.188 574129.000 440421.125 389243.188 | |||
|
370 | nan 222498.234 242154.906 130456.695 303537.781 727317.688 631000.938 914541.812 906938.000 614074.688 365448.875 428491.906 627051.000 307338.469 353902.469 245063.203 313130.531 257953.984 249036.641 289970.500 230311.844 222280.406 324072.219 441828.188 535301.062 800654.250 899314.750 883247.625 797789.188 615637.500 524952.625 376721.219 | |||
|
371 | nan 232771.141 146044.172 172820.766 232696.891 699192.312 686746.375 928633.188 946976.750 636350.625 403442.219 375903.312 691055.688 314889.812 285882.250 266600.875 305839.844 283828.781 306202.938 232763.000 254043.000 331001.750 357419.281 442421.719 653150.750 759793.938 986706.250 939883.188 833480.625 702391.312 530801.000 456500.531 | |||
|
372 | nan 234409.859 176254.594 146161.859 257772.953 730761.438 688534.438 922896.562 1002882.375 641893.062 478283.781 343563.969 602535.438 427219.375 358109.375 378093.969 343835.062 262510.969 264456.781 218489.344 227259.516 369057.969 382025.625 516234.625 598290.625 865986.812 948421.062 1068334.000 868896.625 784622.000 588559.750 530017.250 | |||
|
373 | nan 195013.797 181302.797 143973.406 254843.203 783992.375 639478.562 745218.875 970518.188 582073.938 442632.812 453771.125 705176.125 532420.562 357751.969 284193.562 273292.219 297434.094 265028.312 288422.750 228170.016 308481.375 460051.906 567678.500 763805.000 780058.938 940516.625 913904.562 821961.625 695270.938 567190.875 507282.469 | |||
|
374 | nan 216246.016 173446.938 192341.609 386056.625 665741.062 729720.938 897993.062 911964.938 574632.938 416518.594 397426.000 591672.438 511075.781 355133.875 288731.250 380604.719 294822.375 289503.969 318129.188 253675.109 350646.219 492211.719 576223.750 674330.000 828478.438 871452.750 944873.000 913305.625 722746.125 565910.750 595965.688 | |||
|
375 | nan 161797.078 213311.047 249009.141 310913.812 604428.438 714650.375 1078518.250 900963.750 576634.562 434270.406 459423.969 611236.312 607231.125 421778.531 363094.969 304077.656 422280.125 298590.250 386600.094 222672.500 326914.719 426094.406 620964.938 742366.875 876303.812 964538.375 905469.250 996719.625 738879.250 607707.562 632236.250 | |||
|
376 | nan 206400.188 211286.094 142127.531 253207.203 594286.250 857682.625 876619.000 706774.250 601279.938 496478.625 436250.000 527292.688 690034.188 490144.125 362676.969 385627.000 307053.281 351580.562 285483.375 279027.219 260759.594 390293.875 543472.312 812639.062 862822.625 917813.375 931403.375 1003891.938 855358.250 676375.938 742918.438 | |||
|
377 | nan 189775.562 236306.141 231984.688 263578.031 664468.188 710763.312 815431.625 903712.625 671097.875 479711.688 470043.688 626178.938 654546.562 500537.281 320692.281 389350.531 354451.188 359846.406 314895.469 191746.141 301011.781 271398.125 531168.750 657817.562 887683.812 1154266.125 1276416.375 1145856.375 964064.562 953224.438 906948.375 | |||
|
378 | nan 225260.094 245977.484 238631.484 372346.594 583680.625 694870.375 708467.688 783780.938 765600.750 544084.188 532289.312 508605.375 711646.312 440334.875 463500.781 400344.688 437009.188 326859.688 317675.812 260839.906 261322.250 283482.500 469719.000 746711.812 940949.438 1085688.375 1294518.125 1396247.375 1280319.500 1048690.750 896334.562 | |||
|
379 | nan 235172.516 188737.453 248140.016 331085.406 624210.875 765314.812 768824.375 801935.250 640377.062 460768.000 488314.719 506195.500 600088.938 606804.625 372285.938 376393.375 350316.875 285129.531 427397.906 285055.906 237570.062 277736.031 478591.312 723366.250 984640.438 1199347.125 1454119.000 1444524.125 1348206.875 1166817.875 955817.750 | |||
|
380 | nan 251589.984 261323.109 268008.906 348114.438 669379.875 563598.875 781355.250 760466.250 764621.938 582877.625 403704.281 502355.406 626327.250 574637.000 357554.625 440023.875 313967.969 464094.031 313018.719 249659.516 314608.719 307162.375 325867.688 501105.469 602455.625 894433.375 1102915.750 1296011.875 1168607.750 1129921.500 1049055.875 | |||
|
381 | nan 188159.656 180298.688 286127.531 375823.219 544137.125 660794.875 852552.188 819157.188 648086.312 732474.812 699318.250 490446.469 744035.562 763150.562 494379.969 336299.125 321764.625 273562.281 359741.156 323134.375 323408.594 316274.844 368749.875 464218.469 779477.250 917766.812 1232308.500 1258462.625 1134427.375 1146406.500 1244120.375 | |||
|
382 | nan 174720.141 264573.469 278559.562 396200.969 551569.750 739519.062 694833.500 633183.562 494571.781 577697.812 500996.594 466540.188 572465.125 788823.250 462860.688 371056.312 338821.250 325890.781 341731.875 279197.125 268271.031 269366.219 318863.719 516730.500 823058.562 1043006.562 1393737.000 1506546.875 1437734.625 1262723.375 1209539.875 | |||
|
383 | nan 172822.562 234612.656 273080.281 359965.031 702512.750 604864.688 813767.188 786087.250 622688.250 522983.000 565396.688 539473.812 452319.188 783623.188 541765.500 327383.375 323043.375 304460.406 397600.719 232418.297 357256.188 269747.938 355128.312 475788.500 614646.500 967938.062 1278936.125 1383829.250 1428070.000 1278510.875 1151672.625 | |||
|
384 | nan 188339.734 225792.188 292284.656 478316.031 514672.375 554736.062 812583.188 719905.000 503975.375 576422.438 635981.438 648497.500 518620.500 613197.438 591992.938 353116.531 355289.156 333170.406 363187.812 319546.375 279797.375 335123.219 356677.219 609339.750 808235.562 1014343.625 1337053.000 1359605.500 1375880.750 1341130.125 1264742.500 | |||
|
385 | nan 294447.219 241522.359 297656.594 422252.719 728225.875 540017.250 607010.938 738561.312 557531.562 558946.062 615369.438 620375.062 478547.375 542746.438 607227.062 537986.250 340858.844 395041.406 389547.406 323098.625 282105.125 286118.781 392504.375 460361.031 748450.000 817702.188 915981.438 1148337.500 1057650.000 1121774.875 1158777.000 | |||
|
386 | nan 236162.891 234083.438 279527.031 422880.625 533283.438 403109.312 526530.438 783975.250 511703.094 536901.312 601384.062 534855.875 450846.375 421986.812 544850.562 468761.031 352377.031 353902.531 322194.594 311559.125 303340.344 289152.781 281449.812 306167.500 399921.812 428637.219 618927.250 610879.438 791376.938 987721.562 1307296.500 | |||
|
387 | nan 268722.750 289850.469 246317.156 458819.094 453592.969 501521.875 474082.406 640878.938 668264.000 528634.750 549953.562 519411.188 472549.125 480938.125 586152.938 640463.750 573950.188 382374.094 499128.500 439403.125 331766.688 323710.250 309204.594 321186.125 455434.188 449249.500 482860.781 703764.000 790273.812 970349.250 1452117.875 | |||
|
388 | nan 340021.188 297352.375 281344.406 601291.312 573527.188 493728.094 400435.281 490173.625 508015.781 485071.875 506130.281 608453.562 543601.062 469657.031 412091.875 497768.375 423109.281 385606.781 296489.875 346274.062 429656.281 268472.375 342525.375 279299.656 351837.625 359138.344 545087.625 568694.938 914589.562 955197.750 1547898.375 | |||
|
389 | nan 328354.500 260336.797 244328.234 572158.312 560266.250 480208.094 541782.688 587725.688 558772.375 632404.438 569122.625 561495.125 589185.062 706711.562 434771.812 520600.969 505091.719 533268.188 392900.312 383044.594 486804.812 500944.875 418124.031 401108.906 514082.969 487973.188 627628.125 685553.562 665302.562 967086.000 1442447.125 | |||
|
390 | nan 276507.750 394446.000 333484.125 514177.125 460456.875 491643.812 458169.375 507986.469 621809.500 640782.000 572761.250 475496.469 615343.938 526062.125 528716.188 476891.531 594095.750 506129.969 391504.500 464912.625 361915.125 275279.688 523155.031 774665.812 633704.750 466981.875 623966.750 575505.750 561533.500 674282.312 1258242.750 | |||
|
391 | nan 256465.453 271826.125 330863.625 649022.250 510021.688 437635.500 469644.312 516308.719 507257.281 613061.875 519866.469 597067.188 649781.688 640743.438 441822.625 486420.500 564584.938 624819.688 473469.719 432727.375 508870.219 355557.344 404821.594 265781.281 353033.500 260588.312 292060.281 234632.391 241233.062 456755.375 967584.938 | |||
|
392 | nan 218050.188 295727.125 318433.438 531349.688 455296.031 360622.281 429919.781 484575.781 458340.625 436926.469 503174.406 577499.250 488627.719 454921.812 541756.375 454990.281 367635.969 485436.875 703187.562 682894.000 461461.281 385775.906 335869.094 370054.969 344960.875 431055.688 282735.531 274634.156 234073.906 517435.125 969516.062 | |||
|
393 | nan 321539.375 234164.891 364451.719 386711.375 516757.719 458480.031 375316.719 451299.906 531527.438 531764.250 467310.406 499452.969 535570.438 450375.094 391324.812 381576.875 363350.594 354533.312 281560.531 379678.188 787138.938 870745.438 918079.375 767733.062 748239.375 557707.250 416815.969 345834.469 439093.406 745357.938 1297956.125 | |||
|
394 | nan 233174.891 210801.688 333092.844 484010.969 424966.500 373290.312 367878.250 313642.812 484106.094 483896.594 438593.969 370729.281 524103.375 499230.812 417557.906 318903.281 359713.281 374120.219 293305.438 204598.547 330382.125 277267.688 342487.625 347542.938 384721.719 434274.219 420794.906 409583.125 451025.406 667349.250 1338315.500 | |||
|
395 | nan 179639.719 185521.016 265629.719 404460.781 325172.969 307668.219 313592.125 247895.266 342235.531 329970.938 291867.094 289631.531 381917.469 333525.125 295488.156 379216.625 291398.781 282760.188 301385.812 248600.312 318298.469 256617.406 319767.344 561302.562 495919.375 587495.375 505322.531 650403.250 466177.219 473396.312 1060803.125 | |||
|
396 | nan 173074.078 225053.000 183454.062 231386.656 240524.016 238428.156 206418.953 317706.344 226331.750 276924.062 229940.000 227974.906 277926.062 253787.844 244471.594 235199.188 295689.625 193431.844 141868.859 183612.484 146157.750 147101.062 167763.641 203068.766 148474.859 156137.906 199174.453 176464.875 211953.484 225242.516 526432.750 | |||
|
397 | nan 135007.281 137009.938 176833.188 161068.281 251814.953 159451.141 160259.188 171885.906 120113.344 203865.266 187692.891 155937.109 160131.734 176770.828 202088.812 158002.203 152133.766 131958.641 193104.188 176202.234 139610.922 109036.953 109277.727 130425.281 129195.500 111416.805 148960.578 116049.125 102348.820 129373.820 384890.625 | |||
|
398 | nan 104422.430 107292.648 114127.320 120706.508 164796.016 149349.344 151086.391 142502.672 122385.352 100738.719 101629.227 100883.992 131070.781 91222.531 129477.344 108393.547 116175.023 118522.977 124894.328 103257.133 100190.375 89684.117 83460.094 91364.062 86727.406 90580.797 104617.273 45497.238 59903.266 118063.352 831801.812 | |||
|
399 | nan 47155.730 75738.719 82986.656 83210.008 100310.500 101461.195 108401.852 118002.875 81706.781 82844.508 92334.719 99087.453 77537.898 82791.977 79942.188 64955.316 67488.781 45095.371 63182.637 57403.188 65125.215 63314.988 68418.328 69998.203 37919.195 78626.023 58073.648 50403.223 58088.637 131078.969 818842.188 | |||
|
400 | nan 101408.898 93776.758 77571.805 69506.938 77587.227 110450.406 110791.219 76327.078 112115.625 78522.180 96539.648 80042.344 82578.000 59603.539 64057.547 64271.109 71362.617 91652.398 70899.289 59078.547 79263.867 70924.305 68085.438 68995.711 68405.523 50315.398 72617.805 67266.742 58239.453 73926.641 425141.625 | |||
|
401 | nan 73923.930 89809.742 84148.922 120096.375 120652.852 178551.375 145825.297 131915.734 122636.156 126256.906 111741.453 133036.188 119318.430 117100.875 112437.031 113847.945 70256.219 103478.977 85868.461 80651.469 63002.078 73491.578 87186.188 74567.055 94357.711 83330.141 53726.965 86933.750 67413.180 140678.094 757347.625 | |||
|
402 | nan 120201.633 82726.391 133162.062 148274.938 142493.688 182983.234 152240.484 146146.359 148625.828 138541.031 165627.359 144618.453 145629.609 150355.984 102101.398 133917.234 142038.766 128017.758 133110.078 90662.047 114642.250 92667.953 93668.211 115162.281 99585.094 76736.008 108327.648 123586.820 80971.539 144243.672 972559.062 | |||
|
403 | nan 154823.000 128791.898 150180.438 181256.453 201035.594 158963.047 221028.547 119038.148 154696.547 198614.953 181659.281 150287.812 179249.562 209290.844 130683.297 146396.172 145862.000 134289.906 128035.719 106967.398 108270.555 103333.555 119889.195 105916.148 97121.680 114528.070 102441.047 70182.234 84037.555 154187.766 776555.812 | |||
|
404 | nan 150861.000 203393.141 169675.609 166657.500 189051.812 197203.062 210480.812 265254.844 220856.188 165313.453 205464.094 171803.516 186825.688 224568.297 206586.188 160332.844 202728.359 162962.312 163321.156 114519.430 155766.047 136338.891 125618.820 102852.023 93359.883 103990.898 98188.547 121300.977 75973.703 83324.031 580737.750 | |||
|
405 | nan 198497.062 165403.984 188154.438 235794.812 211116.953 256106.859 261635.344 245756.047 242600.844 170505.828 256423.734 220201.984 159734.984 214044.391 206313.312 233966.562 155609.031 188035.953 188141.109 162089.734 119558.305 155565.828 109202.953 137429.016 125497.578 88890.523 115521.258 161772.656 84196.820 119471.281 383460.906 | |||
|
406 | nan 207402.109 178797.266 203654.938 220305.453 349106.500 288127.031 286174.969 269309.125 279122.125 277901.562 304736.594 352344.531 201503.453 246660.984 294452.875 211418.812 182032.766 199645.312 177120.844 200584.656 158185.812 145333.562 130969.617 153988.688 119837.500 125895.320 146192.750 96288.055 126965.328 118609.328 347428.812 | |||
|
407 | nan 185197.125 218692.406 215018.953 292763.812 260382.000 317024.125 242018.359 312163.125 260205.312 354659.625 294477.906 244827.750 296925.344 300473.875 289025.438 272163.281 223296.703 184719.172 222352.797 218577.188 221287.188 189707.250 172675.516 98498.555 128625.703 178574.625 152248.484 117978.828 120555.328 130515.352 252238.391 | |||
|
408 | nan 246052.438 198009.953 247381.953 281865.000 287340.281 290312.000 332915.031 297108.000 296194.656 357824.969 333660.906 379539.062 334269.875 341619.531 275866.188 272752.500 221118.906 213309.359 249085.562 147548.156 154814.109 183645.109 139507.250 205480.797 148861.922 156160.125 99969.008 109333.250 149836.219 79529.461 143237.734 | |||
|
409 | nan 267225.062 199974.984 245548.156 341020.781 392224.781 368572.750 311503.000 408799.031 401727.688 436553.531 315598.625 357115.469 388826.688 315337.469 335145.031 320404.562 239563.891 276336.531 256057.453 212793.266 218793.703 151395.766 173010.984 140184.688 171044.516 170353.891 167548.266 132637.828 108925.070 118159.719 157686.328 | |||
|
410 | nan 228586.484 235457.438 230511.750 319840.062 302628.781 447057.094 338315.125 381777.281 361151.781 396431.000 433293.125 489202.406 365220.375 325626.062 310003.375 318374.344 264383.219 326557.469 176281.688 181103.172 183482.891 139541.578 161856.922 147317.922 199988.750 110651.781 145550.234 140729.062 114858.047 103556.680 175368.656 | |||
|
411 | nan 213408.109 303093.250 443815.406 433712.219 411097.906 474122.312 389095.188 466052.094 402969.875 414153.469 335335.031 370184.719 437715.406 502937.875 438905.000 354724.719 373367.625 352484.344 293705.031 214208.938 254231.312 211197.094 188209.734 163633.766 173474.266 154460.969 133990.281 148992.984 167121.797 158625.234 124949.781 | |||
|
412 | nan 269098.250 317778.125 335255.938 394514.469 417971.188 492879.969 526727.062 405172.625 494729.781 440655.375 462965.719 435255.781 477277.094 515742.875 425664.625 340899.281 323676.094 324163.906 306401.156 273761.281 190508.688 205461.516 157639.766 192254.547 141626.719 205556.703 131338.781 142233.969 112338.680 97190.430 151899.031 | |||
|
413 | nan 445417.000 284272.375 359740.875 403745.906 566121.250 495710.688 488452.688 524583.188 569212.938 598645.562 536098.438 508067.812 532987.375 458964.875 434069.125 401601.000 437921.594 348010.781 338326.031 367720.875 279054.188 141078.438 170539.766 176551.859 152255.156 152974.688 138602.953 83490.195 130706.602 77627.906 111205.453 | |||
|
414 | nan 453214.812 534285.375 586473.438 599955.688 598492.375 664399.125 530800.125 717143.062 742562.562 623512.250 644763.312 767066.750 643416.062 589177.062 675560.938 530273.562 551112.312 413321.219 322672.781 329656.312 261291.453 222676.094 235167.594 137250.688 137386.141 154658.141 113335.406 58079.348 69972.578 96834.148 102247.930 | |||
|
415 | nan 342416.781 446413.812 624587.000 590494.750 857442.062 910835.750 903764.750 834168.062 745812.750 790318.812 852205.062 775760.188 983905.938 653112.250 567599.438 664130.750 489667.125 419261.125 372495.594 309844.406 319025.781 280597.781 169463.750 149892.906 83718.797 108320.344 101774.719 67731.609 82615.117 59768.129 127823.703 | |||
|
416 | nan 415617.312 594242.000 646156.500 601780.625 820175.375 971390.938 1055904.750 866296.062 1154878.000 1150748.875 1088602.500 1209112.875 899955.062 979448.188 602157.188 717004.938 612597.938 579565.500 505203.000 216847.656 229487.438 167638.953 279015.125 136456.391 161604.734 89407.727 98596.344 88998.750 14260.108 104498.422 255621.188 | |||
|
417 | nan 655657.750 588353.062 780112.812 685176.688 828763.938 1093366.500 1067820.125 1134051.250 1377609.500 1137672.750 1235171.375 1333371.375 1026525.750 1098367.625 1025032.438 835795.250 548418.375 593959.062 454499.094 290029.688 169422.375 287659.375 67444.273 107243.750 122066.531 181624.672 76253.922 75050.383 15449.091 85846.195 273238.781 | |||
|
418 | nan 460860.312 670876.750 639573.562 790195.938 902243.062 1148859.750 1117440.500 1219684.375 1235222.625 1140046.125 1208224.375 1280667.250 1284790.375 1213221.875 992009.812 856512.438 794626.938 485923.312 284890.531 395595.125 337033.625 220159.250 200539.750 120231.031 94734.297 38035.695 67753.484 13168.535 61899.664 218118.641 511123.906 | |||
|
419 | nan 436523.500 656622.062 727357.750 924059.812 1087725.625 1075487.750 1145291.125 1369840.125 1185951.500 1194199.500 1355756.500 1398413.500 1221731.625 1020723.438 844851.375 733983.812 749303.438 486736.875 354314.188 386560.875 163858.734 282161.031 141504.016 104475.406 103892.656 74529.094 20408.812 16424.924 32324.783 610557.562 1247251.500 | |||
|
420 | nan 395898.188 646792.812 668448.062 695208.562 881000.375 1002289.938 1108432.375 1310763.875 1239757.625 1189800.500 1467957.125 1249288.375 1141198.875 1077258.875 858378.812 800772.375 651427.125 433543.812 512111.188 374885.375 210349.984 193546.547 187393.906 37687.609 31454.074 124656.305 41521.395 24516.846 75373.086 1889480.500 3336831.250 | |||
|
421 | nan 265265.531 430023.312 493942.312 555388.812 622687.438 754945.812 869078.438 714497.500 880563.625 966517.375 993280.375 955802.938 683113.500 744772.062 622220.500 530148.625 355579.375 378476.969 338846.656 269681.156 208407.906 170246.375 241853.844 139639.156 98145.203 70892.391 164851.812 69097.938 412282.281 5967802.500 9112200.000 | |||
|
422 | nan 245876.844 399009.969 354791.469 331656.375 441952.219 456597.594 471026.875 482191.469 336219.719 415169.688 506527.469 416574.594 427466.875 360633.719 301913.125 309266.375 317027.719 230179.562 265163.844 280026.531 190914.109 184472.750 205212.344 108542.633 138377.438 116279.148 147731.234 93231.383 1422295.125 15453610.000 19615730.000 | |||
|
423 | nan 130151.344 125892.125 118737.094 158393.703 121955.055 137677.719 146686.203 121373.047 155757.609 136383.797 182314.875 151086.438 134589.359 113503.258 142937.906 126028.969 110654.531 112683.125 103339.219 93631.570 89620.031 82476.516 89837.234 115423.250 86866.117 93464.391 130773.703 153447.312 2880567.750 26127208.000 28408774.000 | |||
|
424 | nan 6244.571 9638.547 4270.723 12036.480 7996.828 6431.668 10216.888 6999.702 11316.435 8236.646 5255.739 9573.993 8213.852 15980.895 5562.687 9070.595 9038.642 4536.986 8451.660 6752.561 10962.317 7581.485 16525.248 4125.552 6050.993 9507.413 4426.484 218314.047 5080108.500 36579264.000 35476464.000 | |||
|
425 | nan 8083.877 3007.078 4251.486 3117.317 1265.523 1282.011 0.000 5793.325 2508.698 2038.466 0.000 3774.847 2467.048 704.453 0.000 0.000 664.926 1321.643 6793.250 1734.080 0.000 2146.579 3276.704 599.927 3087.012 4500.438 983.599 212801.484 5372563.500 34572240.000 31027828.000 | |||
|
426 | nan 2627.139 10489.991 0.000 4854.314 694.571 0.000 2476.659 1985.455 2493.149 3312.495 1315.354 6315.363 2536.041 0.000 0.000 0.000 4191.672 1187.039 0.000 4387.966 2126.574 3772.562 0.000 5137.528 0.000 3935.333 7333.449 144480.703 4379804.500 25811348.000 22779124.000 | |||
|
427 | nan 1832.902 4642.389 0.000 703.633 6139.683 7443.874 5771.570 2496.083 7688.842 1278.287 0.000 2502.828 0.000 1283.527 0.000 1879.572 0.000 1152.914 1163.215 0.000 1119.725 620.731 0.000 583.232 3971.727 3114.054 1935.332 110164.008 3168965.500 20015324.000 18027544.000 | |||
|
428 | nan 0.000 0.000 4250.085 0.000 2449.356 0.000 0.000 2480.613 3805.891 2547.290 0.000 5100.914 2467.048 3230.455 0.000 2362.969 3030.160 0.000 0.000 0.000 2139.836 0.000 0.000 583.232 573.884 1955.471 3858.670 31950.877 1130516.500 7711383.500 8223883.000 | |||
|
429 | nan 3543.177 4134.300 2568.331 2433.266 0.000 4962.534 3826.119 3856.126 2508.698 2547.290 5330.698 1309.670 2514.146 1283.527 5084.795 2413.997 1176.680 2924.563 5561.894 5543.021 2175.101 3195.948 0.000 1062.660 2023.760 0.000 0.000 41195.348 1249261.250 8139923.500 7898238.000 | |||
|
430 | nan 13212.616 25864.258 24562.207 32615.279 32547.861 14588.916 26219.195 23593.336 21493.717 29034.143 21988.123 22767.643 10827.076 15044.741 17838.680 26915.707 30076.639 7523.545 29371.012 16697.992 21833.508 15058.147 17636.262 14295.418 22429.662 10316.795 11413.381 17864.932 182087.797 2285669.000 3080528.250 | |||
|
431 | nan 141613.750 232335.562 179548.484 168172.844 194801.609 207803.891 168631.484 223880.812 236719.516 187334.125 216028.797 216759.938 201819.766 156308.891 221250.234 148432.969 200105.047 175066.922 196538.188 125272.531 149352.141 172598.141 130600.703 126760.875 138709.328 124010.820 129339.492 72994.141 182212.781 1522496.500 2235700.750 | |||
|
432 | nan 302081.938 355111.281 325726.594 301343.625 465333.219 458394.531 453072.719 423594.219 578315.250 597069.062 532976.250 396507.812 511518.031 515022.969 360628.719 407395.000 306177.812 359333.875 278582.375 305368.688 278896.125 214217.500 180361.688 183211.453 147893.359 209444.484 142646.359 76717.805 75752.195 854682.375 1649141.625 | |||
|
433 | nan 393080.906 460245.219 459742.469 778984.625 663221.625 568622.938 727396.750 892339.750 869761.062 885256.062 889936.625 797055.438 811060.938 702981.688 642945.375 544524.438 551948.250 273381.344 379543.594 315601.875 220301.141 239586.109 204358.703 134801.125 128308.508 99770.695 44617.398 66108.219 88293.117 1360955.250 2504757.000 | |||
|
434 | nan 248910.188 484430.125 880701.062 875089.438 933448.000 987938.375 1030345.812 1192543.000 1028143.750 1199254.750 1180857.500 1157358.000 1178052.500 859493.625 800826.250 508676.312 561857.500 427977.094 427521.094 230240.844 136687.953 175270.312 64314.348 90649.469 76525.336 66165.344 34640.711 36383.066 25344.883 1032157.062 2061092.750 | |||
|
435 | nan 443210.625 631848.750 566485.688 880162.750 907274.812 1083627.500 1129698.875 1187961.375 1506555.625 1245339.250 1453628.875 1323770.125 1504526.000 1113621.000 881617.375 890256.438 733623.562 427771.469 385327.406 153360.172 133998.641 174749.938 142618.984 56435.102 102938.742 44550.543 6625.050 24559.512 26611.502 247031.047 499475.531 | |||
|
436 | nan 437064.688 423156.531 844704.062 919047.250 1256784.125 1248854.375 1477551.750 1625534.500 1263413.375 1600735.125 1434646.125 1322928.125 1360981.500 1239272.750 984757.938 863999.750 666935.438 597089.375 374607.031 211383.734 128874.781 156643.188 97374.555 13258.210 16020.044 35853.367 0.000 6109.183 3623.485 10274.503 51007.414 | |||
|
437 | nan 393884.469 425252.531 662188.500 1019325.562 993070.750 1058961.000 1295677.000 1389369.125 1671697.500 1281204.875 1791046.750 1393128.250 1183564.750 1202036.000 1025630.062 765620.000 641255.250 560731.062 248015.156 187599.609 217250.000 239960.938 69646.406 40243.797 38044.672 34330.754 28418.908 6963.210 7441.611 8623.627 0.000 | |||
|
438 | nan 365155.781 797556.062 683767.812 877517.062 931987.438 1100501.125 1165564.875 1410422.875 1577854.750 1354576.625 1322238.000 1249376.250 1167346.500 939319.188 1089262.500 692354.750 681649.000 418583.281 370445.312 186946.828 241523.484 134064.141 103290.547 79958.570 66268.055 33684.855 40926.363 55034.828 15129.949 11609.913 40129.711 | |||
|
439 | nan 361146.125 520136.469 707675.562 722470.500 991326.438 1012425.000 1080017.000 1242077.250 1376639.875 1341645.750 1339314.750 1164899.125 1093342.000 1163113.125 762514.250 614050.250 446152.594 381290.312 343552.406 208256.938 179905.562 198075.984 89773.648 81974.117 29446.031 98147.945 11336.092 15675.918 23630.773 30487.324 48382.578 | |||
|
440 | nan 552940.375 567319.562 695641.750 673642.438 764318.812 945889.938 1200963.500 1143749.625 1049139.625 973581.000 1065638.250 1042137.938 1029199.750 991303.750 633518.000 571752.375 538902.188 639232.250 400304.188 265281.719 142097.766 147253.141 202197.656 85569.898 108254.945 102565.727 42841.246 16406.955 17388.424 12789.965 98080.203 | |||
|
441 | nan 549512.875 484628.500 561090.562 811300.812 639085.750 883895.250 847333.188 1074281.250 877757.250 736672.625 735972.250 817802.562 842699.375 805203.750 728038.938 523515.125 451290.312 394558.531 381304.531 312435.219 315405.594 220796.562 149265.000 207006.547 135016.172 62502.809 74517.492 91875.320 64165.910 66786.250 100511.453 | |||
|
442 | nan 330854.281 424599.719 620743.938 508907.969 587922.625 620888.438 632769.625 713994.000 712756.938 727138.938 844615.188 621023.062 810578.750 705681.062 707561.125 511671.031 477370.625 489320.969 282622.688 291070.750 256270.188 224762.406 106309.281 72208.555 118829.477 83573.633 49721.422 53348.453 42384.121 21408.312 234116.750 | |||
|
443 | nan 346858.281 364009.562 422876.812 528088.562 469929.594 595932.562 509366.312 618140.875 732864.438 611194.500 761433.688 694883.250 657434.312 679280.312 536988.250 467393.625 417261.125 296142.781 259608.984 366353.125 221056.094 251018.266 164938.438 237983.594 125330.820 101746.469 161468.734 76492.227 103615.219 21544.445 362824.844 | |||
|
444 | nan 279285.281 275305.812 429790.812 384241.375 400515.000 458152.406 515820.031 620681.812 562534.188 527345.062 580545.562 424362.688 496025.000 529854.438 406526.469 353779.750 325237.406 375368.156 279702.000 224821.500 232526.641 201372.438 154075.156 154078.438 106534.750 142440.016 112841.500 84375.766 86647.633 74274.352 335202.562 | |||
|
445 | nan 297133.812 299153.719 367636.250 345256.531 495237.500 449019.188 481398.781 547113.938 585998.625 583604.125 626191.062 515424.812 532253.000 443127.000 439237.812 417400.906 216090.234 387344.688 227711.688 200821.344 189352.562 278378.781 192570.109 175671.688 157163.234 107423.242 81391.281 112372.695 94218.078 118374.719 288150.469 | |||
|
446 | nan 270156.688 269104.375 444523.875 532869.938 415343.781 432979.031 411866.812 436805.094 497784.375 481174.094 379297.469 363002.781 365920.594 390756.781 374817.188 359231.375 250583.750 322895.000 261233.156 199955.609 236136.906 191191.797 219945.656 192298.688 168597.688 148602.609 80784.656 172941.922 118108.719 131189.234 235281.906 | |||
|
447 | nan 247993.250 231283.844 374755.125 410374.312 405989.625 325503.969 353307.719 404774.969 394655.688 403356.781 443932.594 369006.438 453492.188 375694.531 404551.781 423032.281 391606.875 326728.625 231765.109 233923.938 266902.781 210135.938 187670.734 141560.328 136761.812 132739.484 126123.250 85412.719 104697.719 90695.133 209185.391 | |||
|
448 | nan 292979.781 250750.734 300513.375 325013.875 383579.281 413129.719 359436.719 427117.406 444489.094 501833.625 388531.781 364168.219 342187.562 425379.125 296811.375 247309.438 310061.656 240581.359 274675.875 317017.625 217338.000 214177.297 180484.016 190794.844 201944.484 147524.391 127716.078 133655.844 88544.938 121666.555 221643.016 | |||
|
449 | nan 265204.688 265362.469 310891.094 209745.594 375865.500 377601.688 340183.812 416358.906 403954.594 344338.594 341252.625 369882.469 460050.000 269024.219 414701.781 273097.250 267295.281 363322.969 220929.750 283105.938 217376.797 207576.344 192872.938 147332.391 129285.703 100525.031 127957.977 122671.031 149429.641 109338.117 169582.391 | |||
|
450 | nan 279804.438 204147.047 266346.062 247229.906 255911.250 337095.062 425231.969 331528.031 310244.219 417390.312 293691.875 393447.469 386882.469 324743.938 263712.469 301489.375 207562.203 237123.453 160097.203 268355.750 229916.562 180411.516 153375.766 156089.406 158382.016 182584.625 138838.438 136456.797 109812.844 108380.000 231090.953 | |||
|
451 | nan 232992.547 195146.250 193585.609 284773.344 273303.406 359493.906 299689.750 304136.844 385475.000 337795.875 331609.719 320011.281 280439.125 284264.375 260575.000 296102.500 272072.875 326424.375 242987.250 182211.266 172667.672 133071.188 138985.188 176227.203 211058.594 157522.906 147637.000 120655.930 107146.055 76127.930 195314.312 | |||
|
452 | nan 165731.234 207504.766 207205.234 255442.609 263167.031 217994.734 265811.469 276896.719 235511.062 249501.406 268903.844 292935.781 288081.312 275751.281 205316.047 235681.703 198865.750 166014.984 174737.266 188012.203 205016.750 127777.719 149575.828 156685.188 134459.375 162775.797 120500.492 97509.492 120873.820 95500.297 84992.906 | |||
|
453 | nan 135984.234 202766.297 182827.656 263593.281 227400.297 232952.500 247720.188 224543.641 201920.391 209810.859 231253.609 299564.875 178097.734 242530.188 169144.891 194847.391 187505.000 162148.219 187992.781 128849.633 111829.953 202999.859 147809.594 135905.125 121237.156 122710.820 100837.172 116238.547 95649.945 109114.742 112762.969 | |||
|
454 | nan 125538.703 143547.688 157035.203 219901.062 153104.469 190333.734 244872.750 224042.609 214366.438 206370.297 187083.375 245829.312 198860.891 148759.562 179882.031 184526.797 215084.547 181104.641 114828.727 163901.375 111802.742 164539.688 167935.750 164252.297 124908.078 150209.859 133765.016 107766.203 96406.258 113458.523 90475.219 | |||
|
455 | nan 119440.094 95262.906 137398.266 154456.375 138803.312 216625.000 182194.438 184007.438 177478.531 165127.641 166680.531 111603.648 156867.328 144940.172 184251.391 133857.047 135851.156 103073.867 155603.734 120857.648 114692.523 126795.953 108810.398 96388.922 85061.836 98531.430 78892.039 138307.203 134095.812 78821.031 105870.227 | |||
|
456 | nan 105205.820 123034.422 104342.180 144975.438 103202.594 115028.945 162627.188 128873.078 177738.484 121767.969 149008.531 155714.062 161920.938 154234.750 124420.133 141321.844 98565.531 108884.352 94259.133 94192.312 111138.031 90995.125 94258.055 96738.820 69534.133 74783.406 78042.953 78975.859 80968.703 73111.195 100080.656 | |||
|
457 | nan 87923.148 98677.781 113410.469 131862.562 97965.430 120034.219 103394.469 116474.328 104703.281 85289.781 108650.078 117540.047 114048.922 86630.734 98239.578 123837.500 77897.852 94785.922 93023.820 108785.883 85391.070 101283.219 75948.367 99732.523 55210.312 103810.219 65979.891 74636.445 49709.141 63424.484 74742.570 | |||
|
458 | nan 88376.234 91088.492 99730.383 99308.508 81024.461 104752.719 119290.070 100743.422 103891.133 96227.258 100838.453 100618.625 100454.867 96580.008 104792.648 96410.148 111171.797 94104.922 80191.227 81557.852 76337.211 110612.742 83130.094 81732.625 73624.055 69637.367 76446.250 70537.438 69887.789 48968.371 72481.211 | |||
|
459 | nan 96747.133 110025.703 130176.781 109972.922 160993.812 144132.984 108008.672 136023.141 138823.109 138092.656 135548.266 165966.891 158669.984 133515.016 130269.102 146003.703 147250.203 127611.703 129331.180 150969.719 122179.195 114571.828 85065.102 92989.930 112280.719 78717.578 85282.523 97969.656 77699.453 58347.684 64015.238 | |||
|
460 | nan 152157.766 193655.547 204521.703 153430.266 229972.047 180761.531 183272.375 234867.844 216426.250 172143.312 259234.547 200210.641 256609.844 246695.203 208015.516 206339.812 166352.734 204653.391 152889.734 166377.141 169661.516 149292.672 132112.438 139611.625 146884.766 107815.570 112495.727 119064.297 126293.383 108131.508 81538.789 | |||
|
461 | nan 192254.312 270294.344 375162.031 346586.375 288708.219 289384.562 296053.281 281825.031 362140.969 275601.875 374693.812 256754.109 288182.125 278076.188 232115.656 238014.062 246405.250 197149.312 210327.062 197798.594 224192.516 174262.484 138339.828 164271.969 228519.594 170330.703 118338.992 111785.344 119949.602 152356.234 97931.695 | |||
|
462 | nan 219143.266 334304.531 365040.375 355879.031 290855.656 361952.250 423563.375 415241.469 442376.000 501782.625 426545.312 404874.375 374300.312 391379.000 384084.531 401275.625 325656.125 275839.594 290730.719 250458.062 207700.500 162320.828 201144.750 170637.547 187941.719 174864.891 103394.422 132612.828 79401.594 81338.492 129797.930 | |||
|
463 | nan 326008.375 458839.125 524539.875 394869.969 386043.781 477270.375 403724.531 439198.188 501610.000 465785.594 523916.594 508404.406 460793.406 446241.594 411966.906 347156.719 368029.594 279183.062 344083.125 242992.109 238432.594 212537.156 193684.094 211669.000 172399.766 155118.094 126251.469 118995.133 91888.203 98136.430 68330.195 | |||
|
464 | nan 494486.312 389530.406 563826.625 447983.625 516884.594 461899.406 505952.594 503147.375 595390.750 444334.125 656998.938 643614.562 514359.219 555491.250 441390.688 525214.625 466171.906 321284.969 358333.281 384961.625 220924.859 253679.438 134659.609 165128.844 160014.141 169492.344 110221.977 87411.148 100727.969 76406.570 55616.191 | |||
|
465 | nan 401153.625 491546.406 492346.688 341054.969 439220.000 375694.125 551279.875 612107.062 598423.562 623016.938 430224.500 546098.875 512596.125 454382.125 431738.125 459638.031 286296.531 284523.219 288503.875 232509.141 166219.453 201031.766 192927.000 122345.273 114929.258 109766.320 102004.656 128612.805 83402.570 41532.887 69975.766 | |||
|
466 | nan 255922.000 464380.094 634541.000 417636.000 419591.125 616106.062 535682.500 620453.312 634099.750 587163.250 540430.812 592067.438 712598.688 519874.625 584499.250 438411.469 430849.719 365008.375 237999.203 297643.375 252551.562 226172.906 208480.203 113205.305 164499.938 198667.141 141519.266 110026.172 89845.867 104597.375 112076.883 | |||
|
467 | nan 379167.125 482084.969 497254.625 468269.969 379031.219 482548.594 530933.062 566272.062 602371.000 684018.312 654888.562 574633.750 613480.125 636200.750 454108.719 423975.281 388418.125 369381.969 266951.531 271023.031 299432.969 234763.656 189862.922 159693.625 123316.930 146886.453 124175.219 119687.820 66955.578 84418.242 91488.203 | |||
|
468 | nan 278598.781 556517.500 665489.250 469641.031 615805.375 537066.375 590059.562 591104.562 580237.062 635774.500 671706.562 526147.938 577367.750 536573.938 473659.969 455757.625 407252.500 414098.281 199076.891 239400.203 274458.938 252406.047 156643.078 142471.297 114698.125 102085.594 83803.297 92965.172 86290.094 85597.625 135039.953 | |||
|
469 | nan 371809.500 565469.625 617355.062 512830.312 570897.438 590128.062 416311.594 531218.375 758321.250 609796.188 658086.125 560287.062 586732.562 555244.562 467061.281 440863.125 410570.406 332302.625 288162.375 272668.031 212143.000 165316.734 182841.203 165157.469 110865.180 187106.609 112019.453 136409.047 119717.820 82063.977 87161.289 | |||
|
470 | nan 380610.688 399146.031 612248.125 487175.188 485206.406 425473.875 626758.438 490944.125 626817.438 555100.375 624081.375 547895.062 468729.812 452564.500 433080.188 451956.719 540545.875 324032.781 314291.062 329843.844 224318.453 179246.734 193663.406 127069.695 147213.609 123074.578 110766.781 135802.547 36721.309 92442.430 75007.367 | |||
|
471 | nan 291525.688 437193.219 583291.625 569286.812 475172.500 541887.375 533979.250 500181.219 613746.438 434142.188 536146.750 589794.062 543399.938 515913.031 464571.000 432594.469 388370.688 237001.016 344073.438 396070.969 244203.656 271392.344 183004.484 119637.422 140195.359 184685.266 110670.031 120746.602 99689.070 79270.883 61078.898 | |||
|
472 | nan 214856.141 586173.125 587697.812 431236.531 447251.375 481104.125 506125.281 493498.312 503795.812 453243.188 428739.219 546802.750 459717.531 497501.281 448458.500 443706.469 380756.344 351473.938 325921.281 245270.641 278764.844 209111.484 169461.188 143671.391 167589.625 167437.125 168115.578 133605.000 114320.047 87857.789 49551.914 | |||
|
473 | nan 286947.594 534021.562 715894.750 379987.875 386160.188 507321.719 402012.812 494135.469 527222.312 629133.000 559396.750 532619.500 471521.312 470285.281 363524.094 307294.094 362249.406 318787.156 330925.125 206730.891 217831.484 182612.250 159411.797 139591.188 164743.109 102114.953 124241.867 74707.141 125084.203 77338.555 91108.344 | |||
|
474 | nan 268329.219 605172.125 760973.875 428294.812 452165.031 421606.125 556829.938 473231.719 542896.625 523223.969 522937.188 516578.500 560039.125 428607.906 351234.875 401924.625 310557.781 323013.062 306859.312 259140.453 189919.688 236975.141 229381.047 135060.891 205151.000 147890.047 88906.422 131677.234 112491.617 88973.406 91192.055 | |||
|
475 | nan 279902.375 474361.125 713897.750 340593.656 371481.719 362005.875 437315.281 429071.188 387969.000 456916.094 492265.625 501623.906 426067.500 443872.375 428457.188 412377.969 387321.906 258127.312 344154.031 192265.453 197098.047 175589.703 149346.438 245465.188 136331.250 95179.406 103161.883 110203.102 138828.609 51309.711 81541.922 | |||
|
476 | nan 263858.812 410179.625 767140.812 461880.594 468043.781 578524.625 497477.781 436506.812 506557.188 603768.438 506641.188 511363.469 535966.562 563446.625 437647.281 337094.594 345155.438 302720.938 318290.844 234185.984 212977.750 196970.000 146008.375 145740.859 193683.484 117330.320 185268.766 99496.180 111385.922 115720.930 66122.094 | |||
|
477 | nan 280146.562 438774.781 852190.625 456936.469 379300.469 387732.812 436653.969 491436.906 455249.000 465438.219 533057.562 477672.219 442165.281 420142.031 374282.125 367274.375 312973.719 279893.781 264334.344 239369.953 254065.547 135328.500 191374.906 165377.141 193667.797 113372.805 74492.781 138408.016 118371.969 89131.719 75655.867 | |||
|
478 | nan 290708.156 588339.750 819420.062 469567.781 493297.375 347104.781 381082.062 475216.812 449297.375 448098.375 459526.688 339302.219 402057.219 465661.531 367953.719 407100.531 356445.625 316296.844 272949.906 261678.594 292936.938 194405.500 168941.203 145460.016 135254.141 164317.500 165914.188 98504.906 144986.469 92673.359 58983.172 | |||
|
479 | nan 276827.469 393022.781 775812.188 489455.875 392559.125 466470.500 378989.531 391584.469 433326.375 460894.875 414555.812 405268.469 349156.219 442760.781 368478.719 336359.719 351147.188 219404.516 323277.469 144181.266 210140.234 203092.859 161936.438 100466.070 142929.688 132782.688 114419.203 120864.930 93992.773 100986.172 75116.016 | |||
|
480 | nan 290145.781 452922.219 1013799.625 404020.594 474914.000 412462.469 464874.906 468079.500 522080.531 448691.781 475177.469 469996.188 455929.688 459174.219 364831.688 338948.031 257520.406 301188.812 307541.438 240034.766 239389.562 161477.859 176000.641 163160.812 120122.398 167813.438 141065.328 107876.930 145367.688 101559.547 95918.555 | |||
|
481 | nan 305996.625 351360.281 1032588.250 506817.188 471118.719 456834.094 350415.375 411838.000 387942.312 495313.375 402820.906 462334.625 364416.000 387708.594 444542.531 373938.656 323955.656 276476.125 221336.000 181098.812 173864.234 228170.594 154767.641 195315.438 171460.516 113427.703 100649.617 110427.969 116421.727 104209.258 98833.273 | |||
|
482 | nan 255192.234 294071.656 1074587.875 481774.094 286913.125 398237.312 417103.406 398579.781 378518.719 391811.531 349726.719 362483.094 311293.281 400574.125 248323.750 282471.875 314214.312 222897.688 249572.438 191656.766 190573.188 183399.453 203472.688 140164.688 138245.969 146424.469 134076.172 77186.766 98462.320 99655.203 58381.777 | |||
|
483 | nan 326100.750 390185.906 1123754.375 525711.750 359765.375 367896.719 330011.375 422652.531 421258.500 463296.375 368249.594 357445.812 389744.531 357924.531 315272.688 282924.000 342337.125 234158.953 267865.875 192437.234 192488.812 159236.812 268406.938 157636.062 132031.641 157314.109 157087.078 132650.484 94310.242 111627.422 65562.109 | |||
|
484 | nan 360661.938 350536.625 1130756.125 559721.562 318247.438 315433.031 342893.531 309704.625 399377.875 349612.219 310411.625 335604.781 363590.000 346160.156 374551.625 248618.938 339781.562 221434.906 215495.234 218202.688 188889.891 143109.016 157888.547 112530.844 189430.234 138412.516 122386.977 97497.719 78953.945 89552.695 78342.305 | |||
|
485 | nan 388203.781 252611.891 1162397.250 609053.438 458800.688 402106.469 327999.688 397751.125 302252.625 376095.969 384863.125 366811.500 402515.469 248615.484 293577.219 305496.594 306128.469 240872.656 234266.406 207718.094 181923.938 117726.148 207859.859 159088.266 119375.117 126495.297 122874.656 121195.805 118140.555 140187.766 107397.906 | |||
|
486 | nan 260351.906 287522.500 1034516.188 548844.312 315832.188 308784.156 304139.219 277349.781 301213.062 384399.281 376245.312 361747.625 334574.375 303789.375 275091.531 228119.234 304273.219 233050.984 174263.109 191358.188 178667.703 146897.594 169714.234 138241.281 182974.266 105622.875 139530.078 114493.648 124006.078 112484.055 111329.797 | |||
|
487 | nan 327205.906 280282.125 1043735.188 615557.812 267359.375 295499.375 254225.297 328397.625 348593.938 357204.688 320311.219 226043.656 304146.281 250621.609 312466.531 344799.719 241128.844 192839.594 171952.484 149229.500 200582.062 164811.312 125837.023 122725.500 136870.422 112252.273 123030.430 122575.727 87954.953 114488.477 78523.555 | |||
|
488 | nan 322422.062 327457.875 1110049.500 630767.750 360382.844 328089.438 283312.500 317954.969 283576.656 197947.609 281711.531 272700.531 312222.531 320684.750 295570.500 206954.562 209880.438 270222.094 195682.984 203756.656 203776.062 170470.312 149177.641 152976.203 107942.102 156717.234 98674.250 102882.883 117137.195 102411.922 123578.078 | |||
|
489 | nan 392812.875 423091.188 1113243.625 597161.812 286644.938 261157.688 247831.203 227707.562 266802.969 281940.375 353692.375 255885.844 243589.688 234428.859 255590.641 253125.641 227106.500 171598.688 208299.688 154865.047 137588.188 151765.344 170384.891 130257.281 143478.859 112790.945 186471.578 108194.773 111209.172 131305.516 96251.453 | |||
|
490 | nan 363273.875 498938.625 1004211.562 692048.062 343991.406 257338.047 232618.484 240810.438 215146.906 287505.250 246484.453 266759.781 244357.609 215713.062 233156.688 212794.203 281753.812 238849.109 142983.391 139874.109 145039.016 185093.312 140968.516 121679.258 166365.141 163915.391 138557.203 133639.453 85317.242 59697.301 78195.750 | |||
|
491 | nan 361100.344 730427.688 1032740.062 772394.188 339257.406 215416.688 180606.500 231933.859 251658.312 247727.797 270818.219 306018.219 250121.156 233657.062 205440.016 227194.641 130679.477 166488.984 183198.578 181532.453 146278.672 140943.688 154046.266 149233.141 139973.469 142322.172 77131.906 133579.734 116100.125 89754.305 87022.820 | |||
|
492 | nan 357681.531 894181.562 1166991.000 907067.000 322124.531 219705.906 210777.812 188582.688 189886.672 227588.547 228883.406 192022.297 190968.938 254040.234 197662.141 189363.656 188645.812 202018.484 193955.359 127142.297 142577.797 126974.906 119001.078 148889.344 132287.734 106999.805 127365.820 99797.781 69916.594 83099.164 71516.695 | |||
|
493 | nan 263534.438 1020699.188 1293422.125 801855.062 339276.219 207684.000 221186.562 214567.453 200008.703 185970.938 203441.641 219362.344 243143.250 222841.641 179767.656 163077.922 180693.984 104382.672 176900.688 133853.703 109506.344 130387.617 143941.016 151503.219 106452.148 113912.992 138612.391 100530.633 83543.805 108942.148 59185.516 | |||
|
494 | nan 297571.906 1018464.812 1515054.500 809387.938 315625.812 240587.891 211130.344 169781.656 177033.453 254464.234 227282.859 209222.453 142664.391 168865.359 142013.516 167285.562 168266.922 139908.438 122983.375 139375.797 134472.734 122843.203 151004.641 100843.023 110090.672 105861.492 70260.719 105198.281 100830.047 98558.125 64911.648 | |||
|
495 | nan 307148.781 1205107.375 1607637.250 880603.000 272436.656 185440.062 162382.703 190344.266 185352.328 108307.547 186980.688 173752.438 183768.594 205249.734 157359.594 158873.234 146772.422 112564.695 152654.312 133645.094 144729.078 138605.172 137315.984 80602.086 121587.898 106539.781 88764.906 108698.477 74231.406 109726.172 82797.984 | |||
|
496 | nan 237788.453 1234498.625 1718500.500 904805.250 284754.094 170125.750 188277.797 148413.656 217567.516 153192.281 235679.141 172694.703 217411.297 196314.094 113948.469 137838.906 131976.141 136912.922 125155.195 119184.828 107202.508 111554.531 128703.148 102512.883 68820.781 74580.000 64675.215 117527.445 97652.195 66068.094 85101.508 | |||
|
497 | nan 247914.906 1076528.125 1988759.875 985325.625 273519.656 156406.172 181385.266 186330.250 146280.797 155277.812 182583.234 171023.109 136673.203 131088.609 140909.078 113472.883 138196.047 135658.984 127008.250 132747.641 124036.555 89003.219 101781.328 82898.875 85636.484 90085.430 73530.469 77871.188 86791.188 75157.305 59964.977 | |||
|
498 | nan 202308.562 1220918.500 2093622.500 999165.938 362005.344 151887.562 126801.469 149661.578 183478.094 111498.617 169282.828 124560.422 181880.609 166969.984 140388.203 164945.594 121070.398 121044.203 119040.758 143634.328 116785.500 97517.945 109734.180 86785.648 97172.047 102871.375 92415.523 69530.250 66071.594 75983.219 67029.281 | |||
|
499 | nan 242715.453 1227116.875 2102712.250 993413.938 314051.906 173722.953 124423.180 142184.734 123910.594 176005.172 182743.438 129424.977 150749.734 146798.984 130003.242 128555.719 147579.547 99183.445 104190.680 98520.492 87807.961 130366.445 106396.148 105332.070 90092.508 97359.242 85337.188 76719.797 92028.031 69210.930 54713.387 | |||
|
500 | nan 224881.312 1046571.938 2330662.250 1118521.500 310969.594 141436.188 121689.148 162326.500 159224.312 163722.766 156809.641 140380.203 142980.641 129985.195 107396.273 133910.938 129154.758 113368.367 138776.125 108295.719 86394.430 73427.219 125015.180 112512.305 77367.688 85287.055 81489.945 86081.523 67520.070 63879.352 77720.969 | |||
|
501 | nan 266425.125 1083077.625 2721694.500 1188287.500 422847.375 184404.484 137885.984 117783.398 191019.859 156807.078 109851.172 150623.016 135833.859 90823.383 107167.125 90081.359 96329.797 148727.250 88726.742 113408.547 94686.398 102318.719 64305.852 106973.828 83923.742 85401.008 78040.508 63980.352 87572.773 65043.684 56563.027 | |||
|
502 | nan 267216.750 1212588.500 2821754.250 1128041.500 371773.125 173019.969 143055.797 120460.500 163437.734 190907.859 156003.000 120228.617 148739.438 114353.008 124626.328 96500.703 91778.477 98384.594 91362.164 102195.055 75671.406 101500.320 71316.102 77931.719 65485.500 92732.555 71669.141 56625.066 86383.430 80528.734 99578.172 | |||
|
503 | nan 287370.531 993445.188 2770927.750 1203981.125 382978.688 195189.859 127602.117 124085.625 177753.359 183577.016 128927.633 80613.055 93931.180 110901.344 122154.578 75042.945 96923.453 78767.070 99984.031 98180.000 97103.453 81076.109 76803.516 78760.570 84724.641 61867.621 74955.820 62908.246 79308.492 50793.371 63008.953 | |||
|
504 | nan 300200.875 881674.188 2878410.000 1433746.625 380376.844 131749.438 111642.172 101401.469 146636.422 137240.688 127469.828 127054.383 89832.141 106606.750 128354.750 78244.719 100814.867 63025.500 90510.133 63426.473 74211.453 66423.445 79112.672 72881.578 76384.250 67782.758 70104.609 65603.742 84479.141 74368.844 55905.988 | |||
|
505 | nan 365787.500 900002.250 3040766.500 1504078.500 370777.000 185157.422 109652.898 119016.453 149759.266 154018.312 109744.195 93879.203 99812.000 93647.102 102408.008 105816.055 89292.367 80274.055 86955.969 92588.406 71421.102 101351.852 78558.812 70310.461 69242.773 50520.676 61779.391 61243.000 57822.121 46941.090 57936.887 | |||
|
506 | nan 406128.688 829024.750 2939852.250 1490940.375 442113.719 169114.297 117817.227 86257.508 153627.953 132511.109 121514.922 82128.633 114593.328 84704.109 89443.289 95160.742 85292.758 86376.891 96779.383 91108.461 70086.766 60043.773 85722.320 58694.613 82475.680 80444.680 61098.086 75693.094 80776.320 78975.695 62152.566 | |||
|
507 | nan 509990.500 807073.625 2660012.250 1746994.875 485889.094 204370.047 97599.094 95993.070 172403.562 117326.367 122946.898 92492.555 79197.289 89110.633 122255.828 83766.945 96519.102 69778.891 73690.820 81563.930 67197.016 85181.719 74156.445 54498.164 60670.953 64931.391 60477.523 79594.242 71761.281 59859.887 53187.766 | |||
|
508 | nan 591036.062 776921.000 2880443.500 1573543.625 460647.312 177714.891 107407.695 114679.773 180035.391 131914.609 93286.445 106005.203 96219.508 80908.930 91479.016 81056.375 95214.258 115272.250 74250.055 84597.648 65519.051 61046.090 68375.875 89492.992 55362.777 65218.828 45346.871 62567.238 62294.496 62094.812 50360.352 | |||
|
509 | nan 671181.750 734779.688 2766677.000 1744455.125 492131.219 147643.391 133243.062 97782.195 132212.516 158222.766 129231.797 93778.500 91283.359 66459.539 68532.297 80442.016 70654.320 69276.688 103296.695 58858.441 76414.133 68457.969 67217.594 55138.023 44880.664 79272.781 55264.762 64913.125 57318.191 67277.164 52244.348 | |||
|
510 | nan 751936.000 720872.250 2723123.000 1762706.125 560927.125 206903.500 97902.578 100364.883 173816.266 143096.938 155428.312 72689.617 88139.422 78836.352 69993.141 73399.781 80028.844 73738.367 69503.133 63898.188 84676.164 57444.125 65865.594 63553.227 58324.828 61813.484 64719.215 67886.070 54418.578 77852.750 67751.633 | |||
|
511 | nan 830732.625 661709.250 2423897.250 1771234.375 496390.031 183539.266 123075.148 112428.547 149491.109 143673.000 131676.859 104204.344 76387.633 51805.836 86264.906 77816.484 87346.516 73085.938 56999.988 88331.305 60178.172 68215.531 74148.984 51020.812 64996.914 58501.191 65816.445 61676.863 64566.426 60355.875 58435.777 | |||
|
512 | nan 1025197.250 628394.812 2356247.000 2002788.500 664719.312 164984.109 84248.477 85576.602 154502.000 137964.922 97223.977 92645.805 77075.055 82697.422 84456.031 65653.656 61751.586 63030.562 62059.598 74078.992 54956.715 71389.406 52055.973 71094.438 66617.781 60561.953 72028.617 75780.695 45299.926 59394.266 61910.629 | |||
|
513 | nan 1092720.125 568121.250 2258458.500 2009061.250 590947.188 143000.016 108108.672 113349.703 192357.484 147004.125 88202.008 92717.109 66903.539 83055.445 109056.398 71184.633 63687.387 68474.461 60872.535 75602.914 46502.949 50562.301 75740.328 65079.984 59384.613 51177.973 65144.254 71327.391 61705.203 67029.320 58058.402 | |||
|
514 | nan 1208154.375 568269.500 2014280.125 2073213.625 657834.438 171845.016 100975.297 111748.094 161822.094 153408.125 94028.750 123166.297 62454.102 69221.367 96746.648 87583.547 71737.430 78022.117 81908.953 52857.984 81880.320 59690.297 76271.086 73647.047 87296.469 62148.809 72814.422 81579.164 81137.539 65725.336 74378.484 | |||
|
515 | nan 1317302.250 527052.938 1966856.875 2039189.500 731985.750 234410.859 74693.914 150667.891 175547.188 147025.047 99053.703 88558.430 76184.930 67419.281 80155.734 61255.684 84107.188 51499.371 60550.875 72898.570 51435.996 69087.219 58103.500 101434.703 92833.914 96132.422 65010.441 68769.594 44656.566 53735.477 40589.168 | |||
|
516 | nan 1545727.625 665267.938 1841683.500 2112783.000 831717.000 240259.938 102309.992 136087.375 176344.141 140087.641 93781.062 90411.594 78246.180 96774.625 60704.250 70639.117 88896.742 82353.594 60122.953 46242.141 52811.449 67927.258 82750.547 83125.570 87390.367 55732.891 66670.695 53154.941 50296.227 62411.246 78646.039 | |||
|
517 | nan 1533770.875 655025.875 1895106.125 2003105.500 814139.250 186118.141 102212.250 134654.359 188364.188 180032.641 67509.266 79888.688 109510.781 102679.070 91795.656 93010.438 69719.242 70447.602 69331.094 59590.547 65817.000 66826.344 76624.773 60207.984 61169.160 61769.789 53913.359 63023.375 55681.609 57928.898 54116.961 | |||
|
518 | nan 1611951.125 615633.562 1837558.750 2107885.000 689351.375 226768.391 107989.445 128186.227 193912.297 142355.734 113902.453 68041.992 85472.250 102917.969 83417.531 106110.453 67448.750 71221.406 57961.359 61631.746 59621.426 58836.160 58809.898 65633.828 60858.379 80856.555 73088.438 79138.398 87443.516 99753.633 75525.383 | |||
|
519 | nan 1615676.375 630884.875 1509678.750 2020905.875 794837.250 226858.297 94529.594 111993.008 214068.188 160073.703 73202.234 75257.406 85545.805 92782.266 88997.539 62743.637 57200.012 68507.461 73487.531 65909.984 65559.719 73988.094 52096.516 76279.211 66191.789 83712.125 80012.406 57337.688 88281.258 102096.906 79729.523 | |||
|
520 | nan 1547681.625 617038.938 1363105.875 2084683.500 892441.062 230818.547 133591.875 126656.398 213795.938 134620.938 71805.656 92004.602 102813.344 94103.594 89787.852 55213.312 69590.312 55592.703 77235.320 62704.977 75834.609 53670.016 76037.695 74603.820 93638.008 85689.656 112024.945 67222.594 83951.516 77238.633 90024.625 | |||
|
521 | nan 1524408.000 647207.188 1261076.500 2017781.250 932814.062 253000.234 93685.898 131364.484 179767.766 130822.570 97517.180 90839.625 102222.000 109328.047 92653.297 81998.672 88936.570 55880.422 68194.945 78365.445 70134.094 80308.406 68548.977 73260.625 55421.527 69503.258 78455.492 66888.711 62668.777 40855.484 35184.781 | |||
|
522 | nan 1624719.625 706299.938 1205171.250 1940710.875 934670.438 256391.859 118591.578 124437.695 234510.453 165750.219 82586.602 93678.820 131052.844 121153.750 89170.797 102055.320 71096.359 80606.016 73655.531 100269.258 76726.328 66095.055 68123.836 65123.172 53361.535 66328.852 50250.004 48689.836 53557.715 55544.141 45050.637 | |||
|
523 | nan 1765512.125 860317.188 1131342.375 2053417.875 980892.938 247083.984 124503.094 125584.930 226077.891 100831.422 109359.648 88043.328 150549.375 121670.852 93773.805 99396.125 104851.922 86360.719 88921.250 75929.125 68814.461 77044.445 67485.742 66119.914 89133.734 78516.633 64312.566 68047.664 53418.137 59188.812 48223.004 | |||
|
524 | nan 1922191.125 904808.938 1021589.250 1876268.000 934275.438 279528.844 89069.477 170499.188 205368.344 133455.000 106961.352 119011.055 160622.297 135904.672 141612.984 131556.156 80918.594 101055.719 78887.484 84044.094 73942.750 79866.664 78271.367 83633.383 73495.898 67637.617 68919.492 81796.945 77902.570 52039.559 60648.973 | |||
|
525 | nan 1864983.625 928354.750 1092817.125 1896283.500 1019632.750 334800.812 73032.594 166266.656 242939.094 101692.883 110879.844 97382.703 159494.312 143492.391 144848.359 117016.406 99575.250 77487.031 73616.320 95933.008 100473.172 110534.406 111661.023 86904.742 65888.344 102882.281 48984.000 70170.727 85872.922 92432.641 61162.090 | |||
|
526 | nan 1967970.375 1053279.750 1045004.625 1885107.250 980153.938 315600.625 134174.438 123989.148 222153.953 139626.359 89364.633 136548.391 175482.531 162733.188 148914.156 121616.008 114768.367 106958.383 86251.586 88770.070 105275.156 85870.258 80604.094 65768.391 63900.312 78272.148 67608.555 81719.469 58777.312 82830.523 98626.430 | |||
|
527 | nan 2007812.125 1224978.250 1106191.375 1872761.250 1075542.125 347360.500 147749.391 179146.562 253409.953 166548.328 111354.250 178058.312 178173.203 140894.344 127789.820 136845.203 106391.844 85193.812 94200.281 122404.797 60198.359 77838.359 100169.648 84429.852 77368.469 91019.883 74345.000 61527.227 65268.285 73824.359 67432.469 | |||
|
528 | nan 1992036.375 1239407.500 1070773.500 1871520.125 1158030.875 335310.188 128924.555 154419.984 213900.547 175917.422 109145.453 136255.922 123237.250 146086.156 134771.078 150173.109 99460.977 94120.211 128900.547 109785.406 80402.305 87073.367 52298.973 66724.727 87210.664 75747.172 69494.414 80910.234 72133.289 71300.141 70096.703 | |||
|
529 | nan 2004807.250 1246792.500 1004049.062 1751790.500 1171191.625 368806.156 131579.484 196576.094 236736.562 167703.078 121584.008 126437.445 109184.867 133276.328 139177.406 128999.953 131526.312 100082.406 77631.203 99023.453 83478.250 77052.781 97030.328 81896.008 66748.969 49463.273 71932.508 71156.945 69312.297 74330.898 60313.566 | |||
|
530 | nan 1930577.250 1427983.375 907613.938 1703740.000 1213686.125 330972.469 132516.234 139425.266 208345.047 210124.641 183644.156 176316.703 154008.469 123846.844 189094.984 114180.469 124075.867 101573.477 93099.375 78643.781 74218.625 65677.562 88917.344 70073.570 82025.023 67784.633 78004.461 57805.988 51904.402 58170.398 47039.496 | |||
|
531 | nan 1982198.750 1510522.625 920418.062 1705799.125 1174957.875 320228.531 144417.938 173031.047 292046.031 231003.453 171260.938 157972.422 212017.062 167644.438 145964.141 129812.203 164935.672 120310.523 110294.867 86199.594 70094.055 61474.039 56064.941 68761.242 63609.738 75158.078 61930.176 76110.531 64045.387 40314.109 59490.953 | |||
|
532 | nan 1986063.250 1584367.875 868562.750 1560093.500 1144391.750 323648.469 138095.969 189324.688 206875.938 186104.891 136940.578 149370.266 157923.781 170945.109 124138.883 145287.062 141227.938 112923.102 120518.633 76973.281 68559.625 48054.504 78020.969 71469.445 79726.719 62814.016 62486.223 57318.391 62930.016 81594.781 46722.559 | |||
|
533 | nan 2007704.875 1429988.500 918621.188 1586028.750 1216639.625 315278.625 194921.500 195133.906 240638.016 198089.516 174534.875 179940.891 185916.016 206105.906 174448.672 152252.703 157997.406 136790.953 106257.117 70107.656 67945.406 80677.070 93386.094 61196.852 83360.648 91362.656 83486.266 57509.121 57493.016 52569.059 69346.289 | |||
|
534 | nan 1987483.500 1522368.625 906290.938 1465235.875 1079772.125 340012.469 143533.125 171890.984 214665.516 214154.766 189107.422 155241.422 149871.078 189130.125 202270.484 119811.398 147894.594 114648.844 124372.367 92887.016 61247.961 71470.961 62801.984 78496.094 71504.281 86332.641 59132.961 59222.301 57892.703 71840.750 55157.613 | |||
|
535 | nan 2093308.875 1567607.250 943094.438 1570408.000 1149215.875 362203.469 158708.250 243115.109 218092.109 195429.438 188171.031 187130.281 154265.438 219626.344 231725.094 169004.281 130134.117 116366.906 146782.109 116097.773 64880.066 67978.789 79037.742 54817.691 73602.992 64669.227 72005.336 52497.266 69044.344 38177.152 60563.062 | |||
|
536 | nan 2009562.875 1607401.875 946183.562 1385801.750 1185527.375 297126.781 137629.859 200305.109 258740.438 203038.609 190250.109 184216.984 167855.828 222548.391 212108.266 139158.250 136489.484 114780.203 120244.078 101537.719 69992.867 67441.094 97767.758 78003.242 64520.137 70819.461 69605.219 55409.801 49217.324 73865.656 57518.648 | |||
|
537 | nan 1981547.250 1715741.250 926470.938 1343968.750 1183130.500 381746.125 146803.312 202549.266 246660.703 199522.047 205668.000 173367.547 175680.375 226640.344 207517.938 155382.516 133398.203 137760.516 128049.227 105227.750 75209.344 69963.039 80460.391 103023.492 83521.242 80731.289 73378.422 69252.977 73855.719 49130.762 40406.441 | |||
|
538 | nan 2002893.250 1655178.375 959736.750 1498214.250 1210034.750 387487.906 159619.000 193058.797 228456.062 203310.953 212011.000 239118.438 199221.344 212558.266 176655.562 136578.812 158485.062 93989.172 111209.617 115706.469 75131.102 93028.469 68207.078 78689.766 88870.297 57658.660 68321.078 75974.719 44654.273 59861.926 68693.930 | |||
|
539 | nan 1908114.375 1671322.875 984129.000 1360466.125 1209353.500 400460.500 162809.953 175512.125 213540.453 232249.641 190958.609 197849.547 227972.453 192922.000 165544.484 154964.062 132606.594 103666.820 117307.953 74140.570 81541.625 97663.531 67819.992 73639.406 61456.875 80130.070 69992.688 58939.898 58028.125 53688.176 59291.191 | |||
|
540 | nan 2160240.750 1633833.250 989260.188 1351721.875 1130549.750 421213.531 161576.891 222057.109 175046.828 217550.984 248980.594 268627.062 223126.406 196794.203 202128.562 193743.234 137385.828 130206.180 109720.883 91265.992 82252.148 91456.344 75839.688 62890.141 97577.695 63811.750 91370.391 76227.758 72403.273 48484.023 47626.305 | |||
|
541 | nan 2167074.000 1680877.625 967654.562 1241805.500 1250336.125 424100.875 137819.828 223667.797 244692.844 239564.906 238950.234 288098.938 261591.859 198621.594 234971.703 153983.594 143632.500 147706.797 125835.469 114903.273 90964.297 97942.383 91256.461 68483.688 85999.633 78016.609 76223.266 50270.191 75374.312 54866.875 56274.062 | |||
|
542 | nan 1909945.250 1657664.875 1039160.438 1478051.125 1196285.000 410898.031 208410.953 249286.359 176639.516 216569.797 215509.250 280757.375 199231.391 249822.016 216692.562 181008.625 167058.766 119916.203 120214.648 113957.102 95058.906 44661.793 71311.703 83800.727 86513.641 50027.410 78826.102 85076.477 58815.613 58381.715 50150.852 | |||
|
543 | nan 1838526.000 1693690.500 1016853.250 1242376.875 1154844.500 454768.031 190712.203 239223.641 265822.188 230322.016 275393.812 289006.906 198113.406 215497.109 220889.844 175998.500 148759.812 166756.328 113637.398 105028.695 87085.422 87109.609 90479.945 60585.738 77493.930 57543.777 58941.527 41172.867 78483.117 56876.086 58470.887 | |||
|
544 | nan 1806132.125 1752231.250 976978.188 1210131.625 1202970.500 490948.094 175744.250 196111.688 177369.781 215345.047 213616.047 210268.516 196469.609 251319.266 260858.609 203144.344 153974.578 93818.508 97721.852 91292.219 71422.281 61777.289 66933.133 65311.473 58780.598 63816.336 77040.500 62062.746 43891.988 45576.266 55484.098 | |||
|
545 | nan 1894644.875 1694807.250 1011810.438 1174765.750 1189106.875 515335.500 171869.922 186056.734 247155.734 205656.609 237286.547 231484.109 204407.000 260854.812 218092.766 204672.438 145452.562 121428.742 111342.742 88187.336 67534.836 71952.930 47840.496 79742.344 65574.297 54057.004 57293.691 44140.680 54177.887 37123.293 57003.414 | |||
|
546 | nan 1845548.500 1634502.500 969211.812 1242812.250 1149273.000 452392.375 176299.891 200330.984 263131.031 221769.953 289331.344 282077.500 259067.344 241946.766 260801.812 171386.453 164029.266 151612.719 128893.133 121888.328 89863.617 87389.820 74065.836 66712.164 59744.840 77098.133 59502.035 65577.367 66282.320 43951.012 45885.816 | |||
|
547 | nan 1791488.125 1718631.875 988412.375 1155059.125 1176332.000 498238.000 201707.062 224704.562 213274.312 249583.062 329952.375 271736.875 198466.688 232327.641 217940.516 233268.656 140931.078 119029.727 111623.906 71208.281 79766.164 74025.180 71966.977 90188.766 69678.977 62307.016 49876.672 53276.586 47762.426 51937.535 36167.844 | |||
|
548 | nan 1905003.125 1655192.375 1001795.938 1145264.500 1238821.625 573088.938 209365.000 235639.438 229496.109 237305.984 275155.875 316526.406 220799.062 246607.141 247291.516 223852.000 174158.734 154583.125 126785.930 92939.516 95018.406 75382.367 60926.750 68336.539 62083.949 49131.613 72609.578 68482.398 33559.465 62155.113 61080.375 | |||
|
549 | nan 1824318.500 1666059.125 1111853.250 1169180.375 1111496.750 463836.312 189544.688 229210.094 221394.984 300136.375 351581.719 321413.562 221736.250 205882.953 216730.062 257363.156 142448.344 157545.156 113186.477 84106.094 67002.273 77773.188 63762.711 79827.844 81243.414 64290.121 60881.891 44344.715 41748.809 61901.059 56142.297 | |||
|
550 | nan 1808790.875 1682687.250 1081321.125 1403258.000 1077086.000 479171.406 265642.656 174124.250 220619.062 224702.766 358034.625 365747.406 255418.562 234413.750 232370.047 217949.359 149483.016 125442.328 98959.719 113384.469 81760.500 95150.469 78936.086 39251.203 70424.438 72374.430 51110.348 53728.562 36671.668 46650.402 54059.602 | |||
|
551 | nan 1702688.000 1698220.375 888451.562 1216278.875 1141606.000 535987.938 218979.703 228512.312 285880.031 273810.969 314967.281 383043.281 264765.562 266057.562 260340.500 180808.297 147037.234 160926.688 100555.469 77787.633 80911.906 70774.016 76961.906 58394.535 78447.539 65945.812 48789.426 54733.309 55129.777 46466.551 58951.938 | |||
|
552 | nan 1767498.375 1685955.500 1028256.562 1148296.750 1075259.875 554571.562 230705.688 280972.000 266213.688 213506.484 347225.750 374171.875 256762.797 225742.984 203578.797 217120.844 173281.984 126805.008 129398.703 96274.156 58345.211 49643.672 66724.906 81536.516 69700.445 48747.785 53390.848 39664.711 57661.559 57579.836 59617.023 | |||
|
553 | nan 1655182.750 1724722.750 1026744.375 1127433.875 1130922.875 579000.250 239601.047 199408.688 203086.734 222230.359 345828.312 357391.844 261245.609 223864.141 221183.266 199636.750 152593.688 114910.219 87990.820 87243.258 90575.258 71185.656 64965.227 54451.988 67434.000 50124.137 37406.340 52037.453 60121.703 43899.098 73782.531 | |||
|
554 | nan 1734400.375 1909046.750 991676.938 1071856.000 1001955.562 636826.250 243174.734 229435.094 236861.797 232937.250 297141.625 379602.344 252682.047 228337.484 228214.141 196838.750 140468.516 152391.109 109378.578 77191.656 65753.602 78809.719 61581.500 62125.977 50772.578 53467.098 49182.113 50799.988 51200.391 46693.336 33424.348 | |||
|
555 | nan 1986992.750 1636833.125 1088212.125 1040204.250 1142618.750 604385.062 208978.391 265918.156 223542.016 234280.141 298551.719 341161.781 256519.812 159222.969 197995.109 196734.641 170351.953 130195.773 102867.477 81652.180 89855.648 66815.125 64929.402 79706.742 49008.859 69088.680 54772.773 36869.562 52681.504 62065.590 41806.523 | |||
|
556 | nan 1997822.750 1821679.875 1099946.125 1098808.250 1038365.062 530487.438 238791.547 283002.219 216400.641 296683.531 364781.781 500458.500 338093.469 262679.469 242709.344 174654.375 164903.422 132391.641 95643.500 93337.531 88044.180 77393.969 71053.883 55495.648 47646.309 53687.125 51522.387 37701.520 59751.535 63168.613 36201.391 | |||
|
557 | nan 1872812.375 1843405.625 1025487.562 1205737.125 1049543.375 640869.062 246297.438 269059.406 172005.984 262419.500 350716.219 331106.000 288635.562 289015.219 228910.562 193630.250 185565.094 127640.422 83427.898 111420.273 74322.367 71995.445 77387.344 67819.469 47599.965 57814.352 57135.371 35015.855 29434.137 34594.797 41932.652 | |||
|
558 | nan 2039143.625 1871494.125 1085600.000 1134233.125 1048498.000 583330.750 261480.750 234126.797 226194.016 208800.000 360150.844 382266.688 293443.656 268172.375 227760.906 186641.000 194755.453 146396.688 102535.992 92322.219 71266.219 78913.102 72759.406 65041.465 57135.488 52402.715 48974.172 37341.875 47980.051 47545.629 34118.203 | |||
|
559 | nan 1964450.000 1944677.125 1055796.500 1233652.375 1082539.125 594276.250 256241.891 271676.969 227032.734 281160.594 353262.656 436162.688 310550.031 264068.000 231332.594 233437.359 139464.141 105602.758 108512.469 110769.172 63706.402 60938.637 82749.789 78688.141 51586.316 43312.418 40543.219 50974.512 37754.512 31058.207 38827.121 | |||
|
560 | nan 1948730.750 1827932.500 1096639.500 1208374.250 1076578.875 510024.906 292277.406 262897.375 228268.547 263910.688 365615.281 368658.125 339928.625 267377.250 210848.391 186246.453 165855.938 130970.953 90344.836 94247.453 68541.477 68446.531 77094.656 60060.496 63274.016 45059.676 34277.723 54688.352 48666.352 33505.465 39690.984 | |||
|
561 | nan 1973168.125 1849799.125 1137751.625 1173432.500 1016476.188 610202.375 250425.938 279418.531 194153.203 297530.375 291601.312 441885.594 270452.875 252710.406 212465.906 224708.094 144338.656 119386.000 91967.797 77194.148 70096.688 52199.754 73456.281 57109.875 56132.152 52567.551 42427.145 56677.086 39586.816 28877.807 40888.957 | |||
|
562 | nan 2079956.500 1814980.125 1122584.875 1198230.125 978002.375 597198.188 260004.141 214622.359 259105.234 284448.344 340660.906 430183.625 303239.500 257624.734 181557.875 207416.109 186824.203 129777.406 109225.898 110805.172 87909.906 80160.875 73754.117 38669.234 50565.465 37992.117 54898.500 37302.434 34797.145 32924.902 31795.639 | |||
|
563 | nan 2075567.125 1770190.375 1049440.500 1128549.750 1056601.875 600689.000 250944.312 274376.594 233942.641 258664.766 307843.469 384959.031 287154.094 215088.359 181957.562 176705.406 162102.266 95733.031 97626.695 85687.844 91985.688 67065.461 84470.727 62558.664 82513.695 38558.504 51248.727 36123.418 27830.863 32818.457 29243.188 | |||
|
564 | nan 1925829.500 1728420.875 1068254.125 1157953.625 1175888.250 521246.781 273439.219 181949.391 245046.312 316191.656 366612.969 376683.031 318440.719 189719.641 157410.766 169763.484 168606.938 135669.062 91569.523 86436.414 79487.883 73443.469 70381.047 82052.180 73282.148 54532.609 29076.645 58172.051 39518.758 26305.807 35330.906 | |||
|
565 | nan 1958800.125 1718904.750 1126346.250 1171625.375 1058969.875 580942.750 253797.906 271273.156 268212.375 286326.781 348798.812 387464.406 327715.906 179742.188 197435.141 157793.859 139970.781 92031.891 84570.898 68335.891 85929.781 51369.566 58287.199 49866.461 51185.902 48213.660 46307.613 32081.975 29241.623 36094.656 48363.547 | |||
|
566 | nan 1943180.125 1857650.500 1231843.750 1146750.125 1103675.250 533322.000 276486.375 256690.688 310931.188 295243.969 388443.594 440389.969 280776.094 230042.016 174495.438 168435.812 150639.594 108604.656 99662.742 82152.617 77117.305 57332.699 63310.566 78285.148 47730.902 43350.047 34411.492 41796.359 45002.730 38994.449 33406.547 | |||
|
567 | nan 1922594.375 1721444.500 1169967.500 1189488.500 1085151.750 545522.750 286021.969 265446.281 244346.641 323533.531 349591.344 403405.719 347771.344 236041.688 150610.422 158119.984 156594.641 128733.508 84542.227 79381.414 88467.398 40226.133 77741.094 52421.398 43423.035 58238.664 36933.105 34516.664 35433.395 50157.762 25062.676 | |||
|
568 | nan 1949953.250 1812532.875 1076398.875 1174335.875 992792.438 507563.219 277128.500 267636.625 257280.203 311712.375 384855.031 361155.281 320837.094 215570.844 237651.703 149061.469 121625.117 123042.180 105735.023 65489.625 80388.227 47516.777 52488.461 58090.090 43021.102 58622.246 48075.051 33017.891 33448.727 31000.424 31899.299 | |||
|
569 | nan 1856718.125 1727471.625 1143663.250 1155724.750 1046149.750 474536.906 224682.594 258052.703 230125.312 280098.969 321822.969 383894.781 257553.859 226370.156 157733.438 171791.422 114588.000 97254.852 105964.578 56581.297 80875.328 66118.719 57701.766 67036.180 50685.672 66468.977 36617.137 53205.102 39635.242 34963.465 31579.750 | |||
|
570 | nan 1951125.875 1681302.500 1167261.250 1280151.875 979656.062 538307.188 302895.375 230539.609 262839.688 303151.906 329421.375 352146.531 241946.734 224055.766 206487.312 154331.641 151312.312 108194.633 74795.633 69285.531 59858.203 78322.438 70799.188 60012.699 47655.973 45721.199 35014.562 48941.602 49047.812 42870.184 34709.344 | |||
|
571 | nan 2033458.125 1696040.375 1087277.125 1164356.250 979161.438 522888.719 256488.703 248387.250 220388.859 313684.375 365006.031 385235.781 264983.969 237884.562 193171.000 172821.172 94402.281 101058.375 73809.297 73445.633 69979.750 53884.246 44740.461 52638.711 55671.691 34436.141 46372.887 38648.465 35765.602 23016.555 16960.365 | |||
|
572 | nan 1857044.000 1687275.125 1230716.500 1212040.125 1091723.625 540029.562 288371.219 272336.188 262648.000 253932.188 425709.031 418218.312 261001.250 207254.094 165377.078 159807.641 118566.055 94988.195 78977.062 71971.250 62158.086 84507.656 41588.582 56447.949 42785.699 41591.816 34622.160 42111.746 30661.525 23096.221 30979.125 | |||
|
573 | nan 1965662.000 1824411.125 1102461.375 1303478.500 1024879.625 500284.094 277145.688 240864.656 235710.516 317108.906 365879.281 451411.688 306980.250 240953.609 182003.047 154138.891 134460.016 84166.789 88997.664 58314.047 47728.516 43624.039 55973.211 41799.766 40471.684 37972.848 30912.906 34792.297 21260.219 36266.266 23322.070 | |||
|
574 | nan 1874186.750 1622697.625 1184952.625 1200271.125 1113822.250 541869.062 293745.812 268347.188 288811.438 267194.469 328294.281 405398.625 278392.469 196943.641 198101.094 159176.594 116892.625 93689.570 69806.109 64240.379 52799.887 50313.848 76933.656 54970.047 37140.648 43922.609 28415.252 24181.418 22446.047 31416.512 24754.332 | |||
|
575 | nan 1757643.125 1733748.375 1169321.750 1194848.625 1072432.500 502279.469 253012.141 242732.062 261928.188 281800.969 399149.000 420520.375 271750.250 251697.234 184186.297 160251.109 120028.000 84333.445 78787.273 39099.527 72551.094 49826.289 55566.152 47026.078 47599.672 40847.184 27028.467 22522.055 24982.357 27163.438 21751.221 | |||
|
576 | nan 1994470.375 1738657.625 1150993.000 1184698.750 1066390.125 512350.500 304397.969 271296.344 251282.203 280720.219 355048.531 432472.906 282489.281 189851.500 142093.688 106278.156 108638.102 70560.305 70323.930 64501.129 74161.742 36630.711 64340.371 55529.902 27895.221 26695.457 14863.856 22582.564 22965.477 29412.617 30790.518 | |||
|
577 | nan 2006515.250 1770301.500 1204783.875 1149663.125 1050461.375 593111.438 305363.688 270088.844 285775.094 283112.219 406342.781 418372.219 243075.938 255864.094 177727.109 130651.547 99967.992 82727.016 78128.000 63664.023 61286.285 48671.836 63998.688 39059.527 26711.658 25941.025 41217.953 26678.506 15156.278 30178.775 22081.955 | |||
|
578 | nan 1883407.250 1745569.625 1194753.375 1180069.875 1051923.000 532384.250 340213.219 259848.938 227123.234 289633.031 398158.312 324421.312 211819.438 222012.844 146039.922 138395.578 111781.633 84328.828 79375.844 65551.883 41840.426 37039.254 52422.664 30856.781 41519.023 42897.941 21708.670 31752.926 17738.242 19922.861 22268.381 | |||
|
579 | nan 1859627.125 1772580.750 1178170.500 1158663.250 1043293.000 528833.188 264340.125 279582.094 233640.016 276315.938 324156.719 378758.719 225692.500 212783.406 152512.094 152491.703 102765.102 87839.883 59127.164 68169.852 53155.715 65204.012 35255.379 32600.812 36177.910 18606.967 28336.314 27122.383 27108.918 20999.627 14349.784 | |||
|
580 | nan 1760340.875 1705848.000 1238813.125 1184322.000 1046655.438 513416.906 289792.281 282696.375 282274.625 285409.219 326842.156 377981.031 293514.281 202562.453 175480.203 163388.000 132643.969 88800.695 74100.383 43534.246 63974.309 46047.059 68556.328 28041.982 55432.262 34295.129 33933.723 29314.029 15043.306 14094.959 9087.839 | |||
|
581 | nan 1655119.125 1685259.625 1149502.750 1215406.875 998728.938 527527.062 308323.531 271687.312 254687.766 355171.219 336676.562 306562.906 233523.156 258301.656 129005.078 103811.844 113254.250 83670.211 84292.555 37878.461 42524.535 35655.203 57717.250 29757.832 24904.057 27896.113 28991.855 9854.593 35975.027 18875.471 20042.156 | |||
|
582 | nan 1781521.875 1850444.875 1214310.500 1149120.125 1048866.125 479079.875 231123.641 280839.938 227496.594 275865.344 346996.125 327523.500 261310.406 232271.734 164128.453 151754.766 88556.906 76919.141 83133.445 61832.973 45380.375 56291.148 32588.770 39685.875 26177.170 16227.862 22788.811 15438.959 11535.253 31118.217 13712.872 | |||
|
583 | nan 1786228.125 1739191.625 1235662.875 1271317.750 1042681.375 567682.125 334666.438 245239.953 258832.188 284916.062 312967.656 287244.969 258103.438 211243.359 124522.570 134108.312 79538.586 81533.734 66464.305 46879.285 55042.973 44896.316 36996.867 38723.504 28228.689 36458.609 42011.488 15077.237 16662.795 11646.541 19508.381 | |||
|
584 | nan 1747301.625 1828350.125 1222542.125 1196806.125 1084370.500 584525.750 285080.781 238439.734 265197.469 302119.125 377116.625 326033.281 232878.938 189842.500 146024.094 153565.688 107787.070 80966.227 63926.176 43591.301 50987.309 51667.988 20221.865 24898.363 20670.713 18686.910 27183.742 20566.490 20853.662 19624.799 12584.331 | |||
|
585 | nan 1778044.125 1783654.125 1243306.250 1100184.750 996650.250 600336.250 283455.688 262538.500 304256.219 339621.062 334029.531 346007.438 223775.766 213504.734 151038.312 101221.148 99770.633 69304.742 65590.422 37851.754 44916.254 33320.090 33521.352 39118.328 41103.531 20036.617 20032.719 24951.107 22843.143 34708.629 26511.812 | |||
|
586 | nan 1652378.875 1942597.625 1199644.875 1201344.875 1095098.375 666843.625 276235.688 245246.312 283424.969 263315.719 319897.750 274598.406 259601.250 174029.609 133206.172 123835.344 66635.492 66466.469 67281.422 50168.113 41132.449 39206.008 48108.648 24838.674 39600.039 22183.016 13815.595 15535.888 17395.955 16925.398 17048.086 | |||
|
587 | nan 1706785.125 1923706.125 1216424.750 1191667.125 1143430.750 546760.375 313323.688 293490.000 229434.156 327059.031 288340.125 270861.344 183647.953 178607.016 133961.219 108550.406 77392.305 55114.754 51126.141 33605.176 50694.625 48313.766 51915.152 33385.203 31308.537 18564.312 19866.344 14153.149 24530.326 11820.629 9361.973 | |||
|
588 | nan 1672581.625 1827957.125 1308804.250 1204841.000 1068377.875 575933.000 346069.125 274959.625 237973.641 253876.562 291026.938 217201.094 244559.359 151476.453 117977.547 104346.422 66358.969 70456.820 42991.516 42016.879 47600.754 44578.422 45359.660 41835.746 27209.357 23980.893 19281.752 14763.329 13046.860 23633.107 20931.264 | |||
|
589 | nan 1643783.875 1897103.875 1324611.375 1245788.375 1087079.625 633490.562 344388.719 227913.250 304481.719 306919.906 318302.375 275823.125 224647.250 204640.109 141224.906 113762.055 76784.812 44206.109 61477.473 41112.836 41514.066 33645.586 37784.250 25931.238 18375.295 22693.033 27477.779 25289.756 9328.800 14308.119 19554.070 | |||
|
590 | nan 1707853.125 1916631.875 1284476.750 1205270.125 1036232.625 547324.750 274336.375 273571.531 296430.906 272327.125 281554.938 305201.031 200229.406 160322.938 127137.000 105618.570 64473.340 66218.281 33912.039 44772.484 31038.883 51943.039 40680.574 31469.680 34184.586 31581.102 17495.914 14938.738 16226.915 24317.820 18021.076 | |||
|
591 | nan 1777755.625 1890728.750 1186964.125 1307083.875 1113596.125 551079.750 345023.562 222756.500 298427.188 302910.656 347787.406 270792.625 182159.062 128508.383 119452.281 104586.898 69804.203 46800.523 35982.957 47140.480 40124.934 29389.137 36340.238 28913.893 25638.330 18486.508 19329.830 12647.256 19988.352 13544.269 7662.834 | |||
|
592 | nan 1663120.500 1861619.500 1400717.250 1203706.875 1171774.125 495571.594 299971.031 217148.500 277135.750 300843.469 312250.875 317784.875 219176.266 151753.891 130729.250 105989.172 68170.188 56368.113 52224.191 50401.125 34426.164 45393.598 35072.816 30434.283 23595.717 21645.232 14277.390 13319.043 20579.602 8476.293 8923.500 | |||
|
593 | nan 1631005.500 1880104.750 1344876.875 1125778.500 1175260.125 539808.062 327438.250 245976.391 268250.625 241755.453 262548.219 281772.000 201756.703 191725.547 142761.922 115917.531 73733.164 67642.156 51566.672 42692.809 39277.051 23371.375 26224.529 21167.586 24351.725 28346.750 14251.528 11786.422 8612.223 18330.057 13703.196 | |||
|
594 | nan 1551290.500 1875846.000 1339115.875 1087721.625 1101908.250 538968.188 345881.375 255035.344 242531.656 231573.094 296384.875 297615.844 190960.500 123558.055 124745.883 75053.367 85158.289 65496.699 46223.918 38620.254 35671.598 28965.713 39677.527 13456.288 25072.143 22922.170 12771.466 11368.507 15006.400 10648.954 11199.259 | |||
|
595 | nan 1440669.500 1799674.375 1283470.875 1055150.125 1171820.375 545634.688 292868.125 231629.516 266976.531 263168.375 294588.969 308727.375 210075.109 164548.562 141337.906 91034.055 76487.539 60683.977 53806.000 23482.727 50178.613 36872.402 29408.873 24143.029 11004.114 13078.371 16628.012 14545.965 13696.234 17719.559 18911.162 | |||
|
596 | nan 1437264.250 1704788.500 1317431.625 1122165.375 1144114.125 647889.812 266906.281 232530.812 205142.156 271320.312 274799.656 241925.812 207257.594 148980.422 106655.570 90116.945 97366.094 49594.711 31427.471 38586.574 24948.258 26607.393 30517.602 22331.283 28884.914 16196.681 18162.342 12461.491 11513.299 12482.025 7931.969 | |||
|
597 | nan 1401245.125 1698649.875 1325367.625 998605.188 1143491.875 624052.938 308002.281 205557.141 247856.812 240602.109 281908.188 259698.750 189849.141 194465.391 110257.172 97603.023 84110.672 46253.234 51106.438 42576.645 39950.402 20888.492 21792.320 31226.043 15212.318 21756.242 20493.812 10704.656 9682.118 7496.447 11155.763 | |||
|
598 | nan 1441538.500 1783711.125 1468141.250 1081133.500 1024551.750 653758.938 301628.781 251741.438 280077.656 324712.125 325928.375 287891.375 182226.234 151894.438 112240.180 92422.414 64285.262 61262.426 49309.184 41066.547 37055.254 28181.818 45338.441 24682.539 14560.577 17124.148 13048.921 12868.978 15704.970 10411.840 6148.530 | |||
|
599 | nan 1432276.750 1832041.875 1340898.500 1007527.750 1112253.875 661048.250 240452.594 207819.062 222839.500 200246.594 341138.969 253791.547 223968.984 172753.578 99022.742 69034.609 81282.102 54035.102 53167.438 30152.262 44976.371 41288.965 20717.305 19270.818 33039.988 15406.142 20802.518 10756.790 11133.631 9361.802 3869.316 | |||
|
600 | nan 1382353.875 1915056.875 1516034.625 981781.375 1080243.125 609505.562 274666.781 212587.500 282377.781 248837.688 303014.469 251285.641 226359.141 149491.328 117495.242 60568.449 58521.824 56389.438 40825.508 37091.949 18516.533 24323.039 26348.213 27180.627 31649.393 17337.277 19036.719 11545.887 22463.877 6930.066 8308.681 No newline at end of file |
@@ -0,0 +1,38 | |||||
|
1 | add_definitions(-DCORE_TESTS_RESOURCES_DIR="${CMAKE_CURRENT_LIST_DIR}/../tests-resources") | |||
|
2 | ||||
|
3 | ||||
|
4 | declare_test(TestStringUtils TestStringUtils Common/TestStringUtils.cpp "sciqlopcore;Qt5::Test") | |||
|
5 | ||||
|
6 | declare_test(TestContainers TestContainers Common/TestContainers.cpp "sciqlopcore;Qt5::Test") | |||
|
7 | ||||
|
8 | ||||
|
9 | declare_test(TestDataSeriesUtils TestDataSeriesUtils Data/TestDataSeriesUtils.cpp "sciqlopcore;Qt5::Test") | |||
|
10 | declare_test(TestOptionalAxis TestOptionalAxis Data/TestOptionalAxis.cpp "sciqlopcore;Qt5::Test") | |||
|
11 | declare_test(TestSpectrogramSeries TestSpectrogramSeries | |||
|
12 | "Data/TestSpectrogramSeries.cpp;Data/DataSeriesBuilders.h;Data/DataSeriesBuilders.cpp;Data/DataSeriesTestsUtils.h;Data/DataSeriesTestsUtils.cpp" | |||
|
13 | "sciqlopcore;Qt5::Test") | |||
|
14 | declare_test(TestOneDimArrayData TestOneDimArrayData Data/TestOneDimArrayData.cpp "sciqlopcore;Qt5::Test") | |||
|
15 | declare_test(TestScalarSeries TestScalarSeries | |||
|
16 | "Data/TestScalarSeries.cpp;Data/DataSeriesBuilders.h;Data/DataSeriesBuilders.cpp;Data/DataSeriesTestsUtils.h;Data/DataSeriesTestsUtils.cpp" | |||
|
17 | "sciqlopcore;Qt5::Test") | |||
|
18 | declare_test(TestTwoDimArrayData TestTwoDimArrayData Data/TestTwoDimArrayData.cpp "sciqlopcore;Qt5::Test") | |||
|
19 | declare_test(TestVectorSeries TestVectorSeries | |||
|
20 | "Data/TestVectorSeries.cpp;Data/DataSeriesBuilders.h;Data/DataSeriesBuilders.cpp;Data/DataSeriesTestsUtils.h;Data/DataSeriesTestsUtils.cpp" | |||
|
21 | "sciqlopcore;Qt5::Test") | |||
|
22 | ||||
|
23 | declare_test(TestDataSourceController TestDataSourceController | |||
|
24 | "DataSource/TestDataSourceController.cpp;DataSource/DataSourceItemBuilder.cpp" | |||
|
25 | "sciqlopcore;Qt5::Test") | |||
|
26 | declare_test(TestDataSourceItem TestDataSourceItem | |||
|
27 | "DataSource/TestDataSourceItem.cpp;DataSource/DataSourceItemBuilder.cpp" | |||
|
28 | "sciqlopcore;Qt5::Test") | |||
|
29 | ||||
|
30 | declare_test(TestVariable TestVariable Variable/TestVariable.cpp "sciqlopcore;Qt5::Test") | |||
|
31 | declare_test(TestVariableCacheController TestVariableCacheController Variable/TestVariableCacheController.cpp "sciqlopcore;Qt5::Test") | |||
|
32 | declare_test(TestVariableController TestVariableController Variable/TestVariableController.cpp "sciqlopcore;Qt5::Test") | |||
|
33 | declare_test(TestVariableSync TestVariableSync Variable/TestVariableSync.cpp "sciqlopcore;Qt5::Test") | |||
|
34 | ||||
|
35 | declare_test(TestDownloader TestDownloader Network/TestDownloader.cpp "sciqlopcore;Qt5::Test") | |||
|
36 | ||||
|
37 | ||||
|
38 | declare_test(TestVariableController2 TestVariableController2 Variable/TestVariableController2.cpp "sciqlopcore;Qt5::Test") |
@@ -0,0 +1,36 | |||||
|
1 | #include <Common/containers.h> | |||
|
2 | #include <vector> | |||
|
3 | #include <set> | |||
|
4 | #include <list> | |||
|
5 | #include <QVector> | |||
|
6 | #include <QList> | |||
|
7 | ||||
|
8 | #include <QObject> | |||
|
9 | #include <QtTest> | |||
|
10 | ||||
|
11 | template<class T> | |||
|
12 | void test() | |||
|
13 | { | |||
|
14 | T cont{{1,2,3,3,3}}; | |||
|
15 | T empty; | |||
|
16 | ||||
|
17 | QCOMPARE(SciQLop::containers::contains(cont,1),true); | |||
|
18 | QCOMPARE(SciQLop::containers::contains(cont,3),true); | |||
|
19 | ||||
|
20 | QCOMPARE(SciQLop::containers::contains(cont,-1),false); | |||
|
21 | QCOMPARE(SciQLop::containers::contains(empty,1),false); | |||
|
22 | } | |||
|
23 | ||||
|
24 | class TestContainers: public QObject { | |||
|
25 | Q_OBJECT | |||
|
26 | ||||
|
27 | private slots: | |||
|
28 | void testVector() { test< std::vector<int> >();} | |||
|
29 | void testSet() { test< std::set<int> >();} | |||
|
30 | void testList() { test< std::list<int> >();} | |||
|
31 | void testQVector(){ test< QVector<int> >();} | |||
|
32 | void testQList() { test< QList<int> >();} | |||
|
33 | }; | |||
|
34 | ||||
|
35 | QTEST_MAIN(TestContainers) | |||
|
36 | #include "TestContainers.moc" |
@@ -0,0 +1,50 | |||||
|
1 | #include <Common/StringUtils.h> | |||
|
2 | ||||
|
3 | #include <QObject> | |||
|
4 | #include <QtTest> | |||
|
5 | ||||
|
6 | class TestStringUtils : public QObject { | |||
|
7 | Q_OBJECT | |||
|
8 | ||||
|
9 | private slots: | |||
|
10 | void testUniqueName_data(); | |||
|
11 | void testUniqueName(); | |||
|
12 | }; | |||
|
13 | ||||
|
14 | void TestStringUtils::testUniqueName_data() | |||
|
15 | { | |||
|
16 | // ////////////// // | |||
|
17 | // Test structure // | |||
|
18 | // ////////////// // | |||
|
19 | ||||
|
20 | QTest::addColumn<QString>("defaultName"); | |||
|
21 | QTest::addColumn<std::vector<QString> >("forbiddenNames"); | |||
|
22 | QTest::addColumn<QString>("expectedName"); | |||
|
23 | ||||
|
24 | // ////////// // | |||
|
25 | // Test cases // | |||
|
26 | // ////////// // | |||
|
27 | ||||
|
28 | QTest::newRow("uniqueName") << "FGM" << std::vector<QString>{"FGM2"} << "FGM"; | |||
|
29 | QTest::newRow("uniqueName2") << "FGM2" << std::vector<QString>{"FGM", "FGM1", "FGM2"} << "FGM3"; | |||
|
30 | QTest::newRow("uniqueName3") << "FGM1" << std::vector<QString>{"FGM1"} << "FGM"; | |||
|
31 | QTest::newRow("uniqueName4") << "FGM" << std::vector<QString>{"FGM"} << "FGM1"; | |||
|
32 | QTest::newRow("uniqueName5") << "FGM" << std::vector<QString>{"FGM", "FGM1", "FGM3"} << "FGM2"; | |||
|
33 | QTest::newRow("uniqueName6") << "FGM" << std::vector<QString>{"A", "B", "C"} << "FGM"; | |||
|
34 | QTest::newRow("uniqueName7") << "FGM" << std::vector<QString>{"fGm", "FGm1", "Fgm2"} << "FGM3"; | |||
|
35 | QTest::newRow("uniqueName8") << "" << std::vector<QString>{"A", "B", "C"} << "1"; | |||
|
36 | QTest::newRow("uniqueName9") << "24" << std::vector<QString>{"A", "B", "C"} << "1"; | |||
|
37 | } | |||
|
38 | ||||
|
39 | void TestStringUtils::testUniqueName() | |||
|
40 | { | |||
|
41 | QFETCH(QString, defaultName); | |||
|
42 | QFETCH(std::vector<QString>, forbiddenNames); | |||
|
43 | QFETCH(QString, expectedName); | |||
|
44 | ||||
|
45 | auto result = StringUtils::uniqueName(defaultName, forbiddenNames); | |||
|
46 | QCOMPARE(result, expectedName); | |||
|
47 | } | |||
|
48 | ||||
|
49 | QTEST_MAIN(TestStringUtils) | |||
|
50 | #include "TestStringUtils.moc" |
@@ -0,0 +1,90 | |||||
|
1 | #include "DataSeriesBuilders.h" | |||
|
2 | ||||
|
3 | #include <Data/ScalarSeries.h> | |||
|
4 | #include <Data/SpectrogramSeries.h> | |||
|
5 | #include <Data/VectorSeries.h> | |||
|
6 | #include <Data/Unit.h> | |||
|
7 | ||||
|
8 | // ///////////// // | |||
|
9 | // ScalarBuilder // | |||
|
10 | // ///////////// // | |||
|
11 | ||||
|
12 | ScalarBuilder &ScalarBuilder::setX(std::vector<double> xData) | |||
|
13 | { | |||
|
14 | m_XAxisData = std::move(xData); | |||
|
15 | return *this; | |||
|
16 | } | |||
|
17 | ||||
|
18 | ScalarBuilder &ScalarBuilder::setValues(std::vector<double> valuesData) | |||
|
19 | { | |||
|
20 | m_ValuesData =std::move(valuesData); | |||
|
21 | return *this; | |||
|
22 | } | |||
|
23 | ||||
|
24 | std::shared_ptr<ScalarSeries> ScalarBuilder::build() | |||
|
25 | { | |||
|
26 | return std::make_shared<ScalarSeries>(std::move(m_XAxisData), std::move(m_ValuesData), Unit{}, | |||
|
27 | Unit{}); | |||
|
28 | } | |||
|
29 | ||||
|
30 | // ////////////////// // | |||
|
31 | // SpectrogramBuilder // | |||
|
32 | // ////////////////// // | |||
|
33 | ||||
|
34 | SpectrogramBuilder &SpectrogramBuilder::setX(std::vector<double> xData) | |||
|
35 | { | |||
|
36 | m_XAxisData = std::move(xData); | |||
|
37 | return *this; | |||
|
38 | } | |||
|
39 | ||||
|
40 | SpectrogramBuilder &SpectrogramBuilder::setY(std::vector<double> yData) | |||
|
41 | { | |||
|
42 | m_YAxisData =std::move(yData); | |||
|
43 | return *this; | |||
|
44 | } | |||
|
45 | ||||
|
46 | SpectrogramBuilder &SpectrogramBuilder::setValues(std::vector<double> valuesData) | |||
|
47 | { | |||
|
48 | m_ValuesData =std::move(valuesData); | |||
|
49 | return *this; | |||
|
50 | } | |||
|
51 | ||||
|
52 | std::shared_ptr<SpectrogramSeries> SpectrogramBuilder::build() | |||
|
53 | { | |||
|
54 | return std::make_shared<SpectrogramSeries>(std::move(m_XAxisData), std::move(m_YAxisData), std::move(m_ValuesData), Unit{}, | |||
|
55 | Unit{}, Unit{}); | |||
|
56 | } | |||
|
57 | ||||
|
58 | // ///////////// // | |||
|
59 | // VectorBuilder // | |||
|
60 | // ///////////// // | |||
|
61 | ||||
|
62 | VectorBuilder &VectorBuilder::setX(std::vector<double> xData) | |||
|
63 | { | |||
|
64 | m_XAxisData = std::move(xData); | |||
|
65 | return *this; | |||
|
66 | } | |||
|
67 | ||||
|
68 | VectorBuilder &VectorBuilder::setXValues(std::vector<double> xValuesData) | |||
|
69 | { | |||
|
70 | m_XValuesData =std::move(xValuesData); | |||
|
71 | return *this; | |||
|
72 | } | |||
|
73 | ||||
|
74 | VectorBuilder &VectorBuilder::setYValues(std::vector<double> yValuesData) | |||
|
75 | { | |||
|
76 | m_YValuesData =std::move(yValuesData); | |||
|
77 | return *this; | |||
|
78 | } | |||
|
79 | ||||
|
80 | VectorBuilder &VectorBuilder::setZValues(std::vector<double> zValuesData) | |||
|
81 | { | |||
|
82 | m_ZValuesData =std::move(zValuesData); | |||
|
83 | return *this; | |||
|
84 | } | |||
|
85 | ||||
|
86 | std::shared_ptr<VectorSeries> VectorBuilder::build() | |||
|
87 | { | |||
|
88 | return std::make_shared<VectorSeries>(std::move(m_XAxisData), std::move(m_XValuesData), std::move(m_YValuesData), std::move(m_ZValuesData), Unit{}, | |||
|
89 | Unit{}); | |||
|
90 | } |
@@ -0,0 +1,74 | |||||
|
1 | #ifndef SCIQLOP_DATASERIESBUILDERS_H | |||
|
2 | #define SCIQLOP_DATASERIESBUILDERS_H | |||
|
3 | ||||
|
4 | #include <memory> | |||
|
5 | #include <vector> | |||
|
6 | ||||
|
7 | class ScalarSeries; | |||
|
8 | class SpectrogramSeries; | |||
|
9 | class VectorSeries; | |||
|
10 | ||||
|
11 | /** | |||
|
12 | * @brief The ScalarBuilder class aims to facilitate the creation of a ScalarSeries for unit tests | |||
|
13 | * @sa ScalarSeries | |||
|
14 | */ | |||
|
15 | class ScalarBuilder { | |||
|
16 | public: | |||
|
17 | /// Sets x-axis data of the series | |||
|
18 | ScalarBuilder & setX(std::vector<double> xData); | |||
|
19 | /// Sets values data of the series | |||
|
20 | ScalarBuilder & setValues(std::vector<double> valuesData); | |||
|
21 | /// Creates the series | |||
|
22 | std::shared_ptr<ScalarSeries> build(); | |||
|
23 | ||||
|
24 | private: | |||
|
25 | std::vector<double> m_XAxisData{}; | |||
|
26 | std::vector<double> m_ValuesData{}; | |||
|
27 | }; | |||
|
28 | ||||
|
29 | /** | |||
|
30 | * @brief The SpectrogramBuilder class aims to facilitate the creation of a SpectrogramSeries for unit tests | |||
|
31 | * @sa SpectrogramSeries | |||
|
32 | */ | |||
|
33 | class SpectrogramBuilder { | |||
|
34 | public: | |||
|
35 | /// Sets x-axis data of the series | |||
|
36 | SpectrogramBuilder & setX(std::vector<double> xData); | |||
|
37 | /// Sets y-axis data of the series | |||
|
38 | SpectrogramBuilder & setY(std::vector<double> yData); | |||
|
39 | /// Sets values data of the series | |||
|
40 | SpectrogramBuilder & setValues(std::vector<double> valuesData); | |||
|
41 | /// Creates the series | |||
|
42 | std::shared_ptr<SpectrogramSeries> build(); | |||
|
43 | ||||
|
44 | private: | |||
|
45 | std::vector<double> m_XAxisData{}; | |||
|
46 | std::vector<double> m_YAxisData{}; | |||
|
47 | std::vector<double> m_ValuesData{}; | |||
|
48 | }; | |||
|
49 | ||||
|
50 | /** | |||
|
51 | * @brief The VectorBuilder class aims to facilitate the creation of a VectorSeries for unit tests | |||
|
52 | * @sa VectorSeries | |||
|
53 | */ | |||
|
54 | class VectorBuilder { | |||
|
55 | public: | |||
|
56 | /// Sets x-axis data of the series | |||
|
57 | VectorBuilder & setX(std::vector<double> xData); | |||
|
58 | /// Sets x-values data of the series | |||
|
59 | VectorBuilder & setXValues(std::vector<double> xValuesData); | |||
|
60 | /// Sets y-values data of the series | |||
|
61 | VectorBuilder & setYValues(std::vector<double> yValuesData); | |||
|
62 | /// Sets z-values data of the series | |||
|
63 | VectorBuilder & setZValues(std::vector<double> zValuesData); | |||
|
64 | /// Creates the series | |||
|
65 | std::shared_ptr<VectorSeries> build(); | |||
|
66 | ||||
|
67 | private: | |||
|
68 | std::vector<double> m_XAxisData{}; | |||
|
69 | std::vector<double> m_XValuesData{}; | |||
|
70 | std::vector<double> m_YValuesData{}; | |||
|
71 | std::vector<double> m_ZValuesData{}; | |||
|
72 | }; | |||
|
73 | ||||
|
74 | #endif // SCIQLOP_DATASERIESBUILDERS_H |
@@ -0,0 +1,24 | |||||
|
1 | #include "DataSeriesTestsUtils.h" | |||
|
2 | ||||
|
3 | void validateRange(DataSeriesIterator first, DataSeriesIterator last, const DataContainer &xData, | |||
|
4 | const DataContainer &valuesData) | |||
|
5 | { | |||
|
6 | QVERIFY(std::equal(first, last, xData.cbegin(), xData.cend(), | |||
|
7 | [](const auto &it, const auto &expectedX) { return it.x() == expectedX; })); | |||
|
8 | QVERIFY(std::equal( | |||
|
9 | first, last, valuesData.cbegin(), valuesData.cend(), | |||
|
10 | [](const auto &it, const auto &expectedVal) { return it.value() == expectedVal; })); | |||
|
11 | } | |||
|
12 | ||||
|
13 | void validateRange(DataSeriesIterator first, DataSeriesIterator last, const DataContainer &xData, const std::vector<DataContainer> &valuesData) | |||
|
14 | { | |||
|
15 | QVERIFY(std::equal(first, last, xData.cbegin(), xData.cend(), | |||
|
16 | [](const auto &it, const auto &expectedX) { return it.x() == expectedX; })); | |||
|
17 | for (auto i = 0u; i < valuesData.size(); ++i) { | |||
|
18 | auto componentData = valuesData.at(i); | |||
|
19 | ||||
|
20 | QVERIFY(std::equal( | |||
|
21 | first, last, componentData.cbegin(), componentData.cend(), | |||
|
22 | [i](const auto &it, const auto &expectedVal) { return it.value(i) == expectedVal; })); | |||
|
23 | } | |||
|
24 | } |
@@ -0,0 +1,373 | |||||
|
1 | /** | |||
|
2 | * The DataSeriesTestsUtils file contains a set of utility methods that can be used to test the operations on a DataSeries. | |||
|
3 | * | |||
|
4 | * Most of these methods are template methods to adapt to any series (scalars, vectors, spectrograms...) | |||
|
5 | * | |||
|
6 | * @sa DataSeries | |||
|
7 | */ | |||
|
8 | #ifndef SCIQLOP_DATASERIESTESTSUTILS_H | |||
|
9 | #define SCIQLOP_DATASERIESTESTSUTILS_H | |||
|
10 | ||||
|
11 | #include <Data/DataSeriesIterator.h> | |||
|
12 | #include <Data/ScalarSeries.h> | |||
|
13 | #include <Data/SpectrogramSeries.h> | |||
|
14 | #include <Data/VectorSeries.h> | |||
|
15 | ||||
|
16 | #include <memory> | |||
|
17 | #include <QtTest> | |||
|
18 | ||||
|
19 | /// Underlying data in ArrayData | |||
|
20 | using DataContainer = std::vector<double>; | |||
|
21 | ||||
|
22 | Q_DECLARE_METATYPE(std::shared_ptr<ScalarSeries>) | |||
|
23 | Q_DECLARE_METATYPE(std::shared_ptr<SpectrogramSeries>) | |||
|
24 | Q_DECLARE_METATYPE(std::shared_ptr<VectorSeries>) | |||
|
25 | ||||
|
26 | /** | |||
|
27 | * Checks that the range of a 1-dim data series contains the expected x-axis data and values data | |||
|
28 | * @param first the iterator on the beginning of the range to check | |||
|
29 | * @param last the iterator on the end of the range to check | |||
|
30 | * @param xData expected x-axis data for the range | |||
|
31 | * @param valuesData expected values data for the range | |||
|
32 | */ | |||
|
33 | void validateRange(DataSeriesIterator first, DataSeriesIterator last, const DataContainer &xData, | |||
|
34 | const DataContainer &valuesData); | |||
|
35 | ||||
|
36 | /** | |||
|
37 | * Checks that the range of a 2-dim data series contains the expected x-axis data and values data | |||
|
38 | * @param first the iterator on the beginning of the range to check | |||
|
39 | * @param last the iterator on the end of the range to check | |||
|
40 | * @param xData expected x-axis data for the range | |||
|
41 | * @param valuesData expected values data for the range | |||
|
42 | */ | |||
|
43 | void validateRange(DataSeriesIterator first, DataSeriesIterator last, const DataContainer &xData, | |||
|
44 | const std::vector<DataContainer> &valuesData); | |||
|
45 | ||||
|
46 | /** | |||
|
47 | * Sets the structure of unit tests concerning merge of two data series | |||
|
48 | * @tparam DataSeriesType the type of data series to merge | |||
|
49 | * @tparam ExpectedValuesType the type of values expected after merge | |||
|
50 | * @sa testMerge_t() | |||
|
51 | */ | |||
|
52 | template <typename DataSeriesType, typename ExpectedValuesType> | |||
|
53 | void testMerge_struct() { | |||
|
54 | // Data series to merge | |||
|
55 | QTest::addColumn<std::shared_ptr<DataSeriesType> >("dataSeries"); | |||
|
56 | QTest::addColumn<std::shared_ptr<DataSeriesType> >("dataSeries2"); | |||
|
57 | ||||
|
58 | // Expected values in the first data series after merge | |||
|
59 | QTest::addColumn<DataContainer>("expectedXAxisData"); | |||
|
60 | QTest::addColumn<ExpectedValuesType>("expectedValuesData"); | |||
|
61 | } | |||
|
62 | ||||
|
63 | /** | |||
|
64 | * Unit test concerning merge of two data series | |||
|
65 | * @sa testMerge_struct() | |||
|
66 | */ | |||
|
67 | template <typename DataSeriesType, typename ExpectedValuesType> | |||
|
68 | void testMerge_t(){ | |||
|
69 | // Merges series | |||
|
70 | QFETCH(std::shared_ptr<DataSeriesType>, dataSeries); | |||
|
71 | QFETCH(std::shared_ptr<DataSeriesType>, dataSeries2); | |||
|
72 | ||||
|
73 | dataSeries->merge(dataSeries2.get()); | |||
|
74 | ||||
|
75 | // Validates results : we check that the merge is valid | |||
|
76 | QFETCH(DataContainer, expectedXAxisData); | |||
|
77 | QFETCH(ExpectedValuesType, expectedValuesData); | |||
|
78 | ||||
|
79 | validateRange(dataSeries->cbegin(), dataSeries->cend(), expectedXAxisData, expectedValuesData); | |||
|
80 | } | |||
|
81 | ||||
|
82 | /** | |||
|
83 | * Sets the structure of unit tests concerning merge of two data series that are of a different type | |||
|
84 | * @tparam SourceType the type of data series with which to make the merge | |||
|
85 | * @tparam DestType the type of data series in which to make the merge | |||
|
86 | * @sa testMergeDifferentTypes_t() | |||
|
87 | */ | |||
|
88 | template <typename SourceType, typename DestType> | |||
|
89 | void testMergeDifferentTypes_struct() | |||
|
90 | { | |||
|
91 | // Data series to merge | |||
|
92 | QTest::addColumn<std::shared_ptr<DestType> >("dest"); | |||
|
93 | QTest::addColumn<std::shared_ptr<SourceType> >("source"); | |||
|
94 | ||||
|
95 | // Expected values in the dest data series after merge | |||
|
96 | QTest::addColumn<DataContainer>("expectedXAxisData"); | |||
|
97 | QTest::addColumn<DataContainer>("expectedValuesData"); | |||
|
98 | } | |||
|
99 | ||||
|
100 | /** | |||
|
101 | * Unit test concerning merge of two data series that are of a different type | |||
|
102 | * @sa testMergeDifferentTypes_struct() | |||
|
103 | */ | |||
|
104 | template <typename SourceType, typename DestType> | |||
|
105 | void testMergeDifferentTypes_t() | |||
|
106 | { | |||
|
107 | // Merges series | |||
|
108 | QFETCH(std::shared_ptr<SourceType>, source); | |||
|
109 | QFETCH(std::shared_ptr<DestType>, dest); | |||
|
110 | ||||
|
111 | dest->merge(source.get()); | |||
|
112 | ||||
|
113 | // Validates results : we check that the merge is valid and the data series is sorted on its | |||
|
114 | // x-axis data | |||
|
115 | QFETCH(DataContainer, expectedXAxisData); | |||
|
116 | QFETCH(DataContainer, expectedValuesData); | |||
|
117 | ||||
|
118 | validateRange(dest->cbegin(), dest->cend(), expectedXAxisData, expectedValuesData); | |||
|
119 | } | |||
|
120 | ||||
|
121 | /** | |||
|
122 | * Sets the structure of unit tests concerning getting the min x-axis data of a data series | |||
|
123 | * @tparam T the type of data series on which to make the operation | |||
|
124 | * @sa testMinXAxisData_t() | |||
|
125 | */ | |||
|
126 | template <typename T> | |||
|
127 | void testMinXAxisData_struct(){ | |||
|
128 | // Data series to get min data | |||
|
129 | QTest::addColumn<std::shared_ptr<T> >("dataSeries"); | |||
|
130 | ||||
|
131 | // Min data | |||
|
132 | QTest::addColumn<double>("min"); | |||
|
133 | ||||
|
134 | // Expected results | |||
|
135 | QTest::addColumn<bool>( | |||
|
136 | "expectedOK"); // if true, expects to have a result (i.e. the iterator != end iterator) | |||
|
137 | QTest::addColumn<double>( | |||
|
138 | "expectedMin"); // Expected value when method doesn't return end iterator | |||
|
139 | } | |||
|
140 | ||||
|
141 | /** | |||
|
142 | * Unit test concerning getting the min x-axis data of a data series | |||
|
143 | * @sa testMinXAxisData_struct() | |||
|
144 | */ | |||
|
145 | template <typename T> | |||
|
146 | void testMinXAxisData_t() | |||
|
147 | { | |||
|
148 | QFETCH(std::shared_ptr<T>, dataSeries); | |||
|
149 | QFETCH(double, min); | |||
|
150 | ||||
|
151 | QFETCH(bool, expectedOK); | |||
|
152 | QFETCH(double, expectedMin); | |||
|
153 | ||||
|
154 | auto it = dataSeries->minXAxisData(min); | |||
|
155 | ||||
|
156 | QCOMPARE(expectedOK, it != dataSeries->cend()); | |||
|
157 | ||||
|
158 | // If the method doesn't return a end iterator, checks with expected value | |||
|
159 | if (expectedOK) { | |||
|
160 | QCOMPARE(expectedMin, it->x()); | |||
|
161 | } | |||
|
162 | } | |||
|
163 | ||||
|
164 | /** | |||
|
165 | * Sets the structure of unit tests concerning getting the max x-axis data of a data series | |||
|
166 | * @tparam T the type of data series on which to make the operation | |||
|
167 | * @sa testMaxXAxisData_t() | |||
|
168 | */ | |||
|
169 | template <typename T> | |||
|
170 | void testMaxXAxisData_struct(){ | |||
|
171 | // Data series to get max data | |||
|
172 | QTest::addColumn<std::shared_ptr<T> >("dataSeries"); | |||
|
173 | ||||
|
174 | // Max data | |||
|
175 | QTest::addColumn<double>("max"); | |||
|
176 | ||||
|
177 | // Expected results | |||
|
178 | QTest::addColumn<bool>( | |||
|
179 | "expectedOK"); // if true, expects to have a result (i.e. the iterator != end iterator) | |||
|
180 | QTest::addColumn<double>( | |||
|
181 | "expectedMax"); // Expected value when method doesn't return end iterator | |||
|
182 | ||||
|
183 | } | |||
|
184 | ||||
|
185 | /** | |||
|
186 | * Unit test concerning getting the max x-axis data of a data series | |||
|
187 | * @sa testMaxXAxisData_struct() | |||
|
188 | */ | |||
|
189 | template <typename T> | |||
|
190 | void testMaxXAxisData_t() | |||
|
191 | { | |||
|
192 | QFETCH(std::shared_ptr<T>, dataSeries); | |||
|
193 | QFETCH(double, max); | |||
|
194 | ||||
|
195 | QFETCH(bool, expectedOK); | |||
|
196 | QFETCH(double, expectedMax); | |||
|
197 | ||||
|
198 | auto it = dataSeries->maxXAxisData(max); | |||
|
199 | ||||
|
200 | QCOMPARE(expectedOK, it != dataSeries->cend()); | |||
|
201 | ||||
|
202 | // If the method doesn't return a end iterator, checks with expected value | |||
|
203 | if (expectedOK) { | |||
|
204 | QCOMPARE(expectedMax, it->x()); | |||
|
205 | } | |||
|
206 | } | |||
|
207 | ||||
|
208 | /** | |||
|
209 | * Sets the structure of unit tests concerning getting the purge of a data series | |||
|
210 | * @tparam T the type of data series on which to make the operation | |||
|
211 | * @sa testMinXAxisData_t() | |||
|
212 | */ | |||
|
213 | template <typename T> | |||
|
214 | void testPurge_struct() | |||
|
215 | { | |||
|
216 | // Data series to purge | |||
|
217 | QTest::addColumn<std::shared_ptr<T> >("dataSeries"); | |||
|
218 | QTest::addColumn<double>("min"); | |||
|
219 | QTest::addColumn<double>("max"); | |||
|
220 | ||||
|
221 | // Expected values after purge | |||
|
222 | QTest::addColumn<DataContainer>("expectedXAxisData"); | |||
|
223 | QTest::addColumn<std::vector<DataContainer> >("expectedValuesData"); | |||
|
224 | } | |||
|
225 | ||||
|
226 | /** | |||
|
227 | * Unit test concerning getting the purge of a data series | |||
|
228 | * @sa testPurge_struct() | |||
|
229 | */ | |||
|
230 | template <typename T> | |||
|
231 | void testPurge_t(){ | |||
|
232 | QFETCH(std::shared_ptr<T>, dataSeries); | |||
|
233 | QFETCH(double, min); | |||
|
234 | QFETCH(double, max); | |||
|
235 | ||||
|
236 | dataSeries->purge(min, max); | |||
|
237 | ||||
|
238 | // Validates results | |||
|
239 | QFETCH(DataContainer, expectedXAxisData); | |||
|
240 | QFETCH(std::vector<DataContainer>, expectedValuesData); | |||
|
241 | ||||
|
242 | validateRange(dataSeries->cbegin(), dataSeries->cend(), expectedXAxisData, | |||
|
243 | expectedValuesData); | |||
|
244 | } | |||
|
245 | ||||
|
246 | /** | |||
|
247 | * Sets the structure of unit tests concerning getting subdata of a data series | |||
|
248 | * @tparam DataSeriesType the type of data series on which to make the operation | |||
|
249 | * @tparam ExpectedValuesType the type of values expected after the operation | |||
|
250 | * @sa testSubDataSeries_t() | |||
|
251 | */ | |||
|
252 | template <typename DataSeriesType, typename ExpectedValuesType> | |||
|
253 | void testSubDataSeries_struct() { | |||
|
254 | // Data series from which extract the subdata series | |||
|
255 | QTest::addColumn<std::shared_ptr<DataSeriesType> >("dataSeries"); | |||
|
256 | // Range to extract | |||
|
257 | QTest::addColumn<DateTimeRange>("range"); | |||
|
258 | ||||
|
259 | // Expected values for the subdata series | |||
|
260 | QTest::addColumn<DataContainer>("expectedXAxisData"); | |||
|
261 | QTest::addColumn<ExpectedValuesType>("expectedValuesData"); | |||
|
262 | } | |||
|
263 | ||||
|
264 | /** | |||
|
265 | * Unit test concerning getting subdata of a data series | |||
|
266 | * @sa testSubDataSeries_struct() | |||
|
267 | */ | |||
|
268 | template <typename DataSeriesType, typename ExpectedValuesType> | |||
|
269 | void testSubDataSeries_t(){ | |||
|
270 | QFETCH(std::shared_ptr<DataSeriesType>, dataSeries); | |||
|
271 | QFETCH(DateTimeRange, range); | |||
|
272 | ||||
|
273 | // Makes the operation | |||
|
274 | auto subDataSeries = std::dynamic_pointer_cast<DataSeriesType>(dataSeries->subDataSeries(range)); | |||
|
275 | QVERIFY(subDataSeries != nullptr); | |||
|
276 | ||||
|
277 | // Validates results | |||
|
278 | QFETCH(DataContainer, expectedXAxisData); | |||
|
279 | QFETCH(ExpectedValuesType, expectedValuesData); | |||
|
280 | ||||
|
281 | validateRange(subDataSeries->cbegin(), subDataSeries->cend(), expectedXAxisData, expectedValuesData); | |||
|
282 | } | |||
|
283 | ||||
|
284 | /** | |||
|
285 | * Sets the structure of unit tests concerning getting the range of a data series | |||
|
286 | * @tparam T the type of data series on which to make the operation | |||
|
287 | * @sa testXAxisRange_t() | |||
|
288 | */ | |||
|
289 | template <typename T> | |||
|
290 | void testXAxisRange_struct(){ | |||
|
291 | // Data series to get x-axis range | |||
|
292 | QTest::addColumn<std::shared_ptr<T> >("dataSeries"); | |||
|
293 | ||||
|
294 | // Min/max values | |||
|
295 | QTest::addColumn<double>("min"); | |||
|
296 | QTest::addColumn<double>("max"); | |||
|
297 | ||||
|
298 | // Expected values | |||
|
299 | QTest::addColumn<DataContainer>("expectedXAxisData"); | |||
|
300 | QTest::addColumn<DataContainer>("expectedValuesData"); | |||
|
301 | } | |||
|
302 | ||||
|
303 | /** | |||
|
304 | * Unit test concerning getting the range of a data series | |||
|
305 | * @sa testXAxisRange_struct() | |||
|
306 | */ | |||
|
307 | template <typename T> | |||
|
308 | void testXAxisRange_t(){ | |||
|
309 | QFETCH(std::shared_ptr<T>, dataSeries); | |||
|
310 | QFETCH(double, min); | |||
|
311 | QFETCH(double, max); | |||
|
312 | ||||
|
313 | QFETCH(DataContainer, expectedXAxisData); | |||
|
314 | QFETCH(DataContainer, expectedValuesData); | |||
|
315 | ||||
|
316 | auto bounds = dataSeries->xAxisRange(min, max); | |||
|
317 | validateRange(bounds.first, bounds.second, expectedXAxisData, expectedValuesData); | |||
|
318 | } | |||
|
319 | ||||
|
320 | /** | |||
|
321 | * Sets the structure of unit tests concerning getting values bounds of a data series | |||
|
322 | * @tparam T the type of data series on which to make the operation | |||
|
323 | * @sa testValuesBounds_t() | |||
|
324 | */ | |||
|
325 | template <typename T> | |||
|
326 | void testValuesBounds_struct() | |||
|
327 | { | |||
|
328 | // Data series to get values bounds | |||
|
329 | QTest::addColumn<std::shared_ptr<T> >("dataSeries"); | |||
|
330 | ||||
|
331 | // x-axis range | |||
|
332 | QTest::addColumn<double>("minXAxis"); | |||
|
333 | QTest::addColumn<double>("maxXAxis"); | |||
|
334 | ||||
|
335 | // Expected results | |||
|
336 | QTest::addColumn<bool>( | |||
|
337 | "expectedOK"); // Test is expected to be ok (i.e. method doesn't return end iterators) | |||
|
338 | QTest::addColumn<double>("expectedMinValue"); | |||
|
339 | QTest::addColumn<double>("expectedMaxValue"); | |||
|
340 | } | |||
|
341 | ||||
|
342 | /** | |||
|
343 | * Unit test concerning getting values bounds of a data series | |||
|
344 | * @sa testValuesBounds_struct() | |||
|
345 | */ | |||
|
346 | template <typename T> | |||
|
347 | void testValuesBounds_t() | |||
|
348 | { | |||
|
349 | QFETCH(std::shared_ptr<T>, dataSeries); | |||
|
350 | QFETCH(double, minXAxis); | |||
|
351 | QFETCH(double, maxXAxis); | |||
|
352 | ||||
|
353 | QFETCH(bool, expectedOK); | |||
|
354 | QFETCH(double, expectedMinValue); | |||
|
355 | QFETCH(double, expectedMaxValue); | |||
|
356 | ||||
|
357 | auto minMaxIts = dataSeries->valuesBounds(minXAxis, maxXAxis); | |||
|
358 | auto end = dataSeries->cend(); | |||
|
359 | ||||
|
360 | // Checks iterators with expected result | |||
|
361 | QCOMPARE(expectedOK, minMaxIts.first != end && minMaxIts.second != end); | |||
|
362 | ||||
|
363 | if (expectedOK) { | |||
|
364 | auto compare = [](const auto &v1, const auto &v2) { | |||
|
365 | return (std::isnan(v1) && std::isnan(v2)) || v1 == v2; | |||
|
366 | }; | |||
|
367 | ||||
|
368 | QVERIFY(compare(expectedMinValue, minMaxIts.first->minValue())); | |||
|
369 | QVERIFY(compare(expectedMaxValue, minMaxIts.second->maxValue())); | |||
|
370 | } | |||
|
371 | } | |||
|
372 | ||||
|
373 | #endif // SCIQLOP_DATASERIESTESTSUTILS_H |
@@ -0,0 +1,206 | |||||
|
1 | #include <Data/DataSeriesUtils.h> | |||
|
2 | ||||
|
3 | #include <QObject> | |||
|
4 | #include <QtTest> | |||
|
5 | ||||
|
6 | namespace { | |||
|
7 | ||||
|
8 | /// Path for resources | |||
|
9 | const auto TESTS_RESOURCES_PATH | |||
|
10 | = QFileInfo{QString{CORE_TESTS_RESOURCES_DIR}, "TestDataSeriesUtils"}.absoluteFilePath(); | |||
|
11 | ||||
|
12 | QString inputFilePath(const QString &inputFileName) | |||
|
13 | { | |||
|
14 | return QFileInfo{TESTS_RESOURCES_PATH, inputFileName}.absoluteFilePath(); | |||
|
15 | } | |||
|
16 | ||||
|
17 | } // namespace | |||
|
18 | ||||
|
19 | class TestDataSeriesUtils : public QObject { | |||
|
20 | Q_OBJECT | |||
|
21 | ||||
|
22 | private slots: | |||
|
23 | /// Tests @sa DataSeriesUtils::thresholds() method | |||
|
24 | void testThresholds_data(); | |||
|
25 | void testThresholds(); | |||
|
26 | ||||
|
27 | /// Tests @sa DataSeriesUtils::fillDataHoles() method | |||
|
28 | void testFillDataHoles_data(); | |||
|
29 | void testFillDataHoles(); | |||
|
30 | }; | |||
|
31 | ||||
|
32 | void TestDataSeriesUtils::testFillDataHoles_data() | |||
|
33 | { | |||
|
34 | QTest::addColumn<std::vector<double> >("xAxisData"); | |||
|
35 | QTest::addColumn<std::vector<double> >("valuesData"); | |||
|
36 | QTest::addColumn<double>("resolution"); | |||
|
37 | QTest::addColumn<double>("fillValue"); | |||
|
38 | QTest::addColumn<double>("minBound"); | |||
|
39 | QTest::addColumn<double>("maxBound"); | |||
|
40 | QTest::addColumn<std::vector<double> >( | |||
|
41 | "expectedXAxisData"); // expected x-axis data after filling holes | |||
|
42 | QTest::addColumn<std::vector<double> >( | |||
|
43 | "expectedValuesData"); // expected values data after filling holes | |||
|
44 | ||||
|
45 | auto nan = std::numeric_limits<double>::quiet_NaN(); | |||
|
46 | ||||
|
47 | QTest::newRow("fillDataHoles (basic case)") | |||
|
48 | << std::vector<double>{0., 1., 5., 7., 14.} << std::vector<double>{0., 1., 2., 3., 4.} << 2. | |||
|
49 | << nan << nan << nan << std::vector<double>{0., 1., 3., 5., 7., 9., 11., 13., 14.} | |||
|
50 | << std::vector<double>{0., 1., nan, 2., 3., nan, nan, nan, 4.}; | |||
|
51 | ||||
|
52 | QTest::newRow("fillDataHoles (change nb components)") | |||
|
53 | << std::vector<double>{0., 1., 5., 7., 14.} | |||
|
54 | << std::vector<double>{0., 1., 2., 3., 4., 5., 6., 7., 8., 9.} << 2. << nan << nan << nan | |||
|
55 | << std::vector<double>{0., 1., 3., 5., 7., 9., 11., 13., 14.} | |||
|
56 | << std::vector<double>{0., 1., 2., 3., nan, nan, 4., 5., 6., | |||
|
57 | 7., nan, nan, nan, nan, nan, nan, 8., 9.}; | |||
|
58 | ||||
|
59 | QTest::newRow("fillDataHoles (change resolution)") | |||
|
60 | << std::vector<double>{0., 1., 5., 7., 14.} << std::vector<double>{0., 1., 2., 3., 4.} | |||
|
61 | << 1.5 << nan << nan << nan | |||
|
62 | << std::vector<double>{0., 1., 2.5, 4., 5., 6.5, 7., 8.5, 10., 11.5, 13., 14.} | |||
|
63 | << std::vector<double>{0., 1., nan, nan, 2., nan, 3., nan, nan, nan, nan, 4.}; | |||
|
64 | ||||
|
65 | QTest::newRow("fillDataHoles (with no data (no changes made))") | |||
|
66 | << std::vector<double>{} << std::vector<double>{} << 2. << nan << nan << nan | |||
|
67 | << std::vector<double>{} << std::vector<double>{}; | |||
|
68 | ||||
|
69 | QTest::newRow("fillDataHoles (with no resolution (no changes made))") | |||
|
70 | << std::vector<double>{0., 1., 5., 7., 14.} << std::vector<double>{0., 1., 2., 3., 4.} << 0. | |||
|
71 | << nan << nan << nan << std::vector<double>{0., 1., 5., 7., 14.} | |||
|
72 | << std::vector<double>{0., 1., 2., 3., 4.}; | |||
|
73 | ||||
|
74 | QTest::newRow("fillDataHoles (change fill value)") | |||
|
75 | << std::vector<double>{0., 1., 5., 7., 14.} << std::vector<double>{0., 1., 2., 3., 4.} << 2. | |||
|
76 | << -1. << nan << nan << std::vector<double>{0., 1., 3., 5., 7., 9., 11., 13., 14.} | |||
|
77 | << std::vector<double>{0., 1., -1., 2., 3., -1., -1., -1., 4.}; | |||
|
78 | ||||
|
79 | QTest::newRow("fillDataHoles (add data holes to the beginning)") | |||
|
80 | << std::vector<double>{5., 7., 9., 11., 13.} << std::vector<double>{0., 1., 2., 3., 4.} | |||
|
81 | << 2. << nan << 0. << nan << std::vector<double>{1., 3., 5., 7., 9., 11., 13.} | |||
|
82 | << std::vector<double>{nan, nan, 0., 1., 2., 3., 4.}; | |||
|
83 | ||||
|
84 | QTest::newRow("fillDataHoles (add data holes to the end)") | |||
|
85 | << std::vector<double>{5., 7., 9., 11., 13.} << std::vector<double>{0., 1., 2., 3., 4.} | |||
|
86 | << 2. << nan << nan << 21. << std::vector<double>{5., 7., 9., 11., 13., 15., 17., 19., 21.} | |||
|
87 | << std::vector<double>{0., 1., 2., 3., 4., nan, nan, nan, nan}; | |||
|
88 | ||||
|
89 | QTest::newRow("fillDataHoles (invalid min/max bounds (no changes made))") | |||
|
90 | << std::vector<double>{5., 7., 9., 11., 13.} << std::vector<double>{0., 1., 2., 3., 4.} | |||
|
91 | << 2. << nan << 8. << 13. << std::vector<double>{5., 7., 9., 11., 13.} | |||
|
92 | << std::vector<double>{0., 1., 2., 3., 4.}; | |||
|
93 | } | |||
|
94 | ||||
|
95 | void TestDataSeriesUtils::testFillDataHoles() | |||
|
96 | { | |||
|
97 | QFETCH(std::vector<double>, xAxisData); | |||
|
98 | QFETCH(std::vector<double>, valuesData); | |||
|
99 | QFETCH(double, resolution); | |||
|
100 | QFETCH(double, fillValue); | |||
|
101 | QFETCH(double, minBound); | |||
|
102 | QFETCH(double, maxBound); | |||
|
103 | ||||
|
104 | QFETCH(std::vector<double>, expectedXAxisData); | |||
|
105 | QFETCH(std::vector<double>, expectedValuesData); | |||
|
106 | ||||
|
107 | // Executes method (xAxisData and valuesData are modified) | |||
|
108 | DataSeriesUtils::fillDataHoles(xAxisData, valuesData, resolution, fillValue, minBound, | |||
|
109 | maxBound); | |||
|
110 | ||||
|
111 | // Checks results | |||
|
112 | auto equal = [](const auto &data, const auto &expectedData) { | |||
|
113 | // Compares with NaN values | |||
|
114 | return std::equal(data.begin(), data.end(), expectedData.begin(), expectedData.end(), | |||
|
115 | [](const auto &val, const auto &expectedVal) { | |||
|
116 | return (std::isnan(val) && std::isnan(expectedVal)) | |||
|
117 | || val == expectedVal; | |||
|
118 | }); | |||
|
119 | }; | |||
|
120 | QVERIFY(equal(xAxisData, expectedXAxisData)); | |||
|
121 | QVERIFY(equal(valuesData, expectedValuesData)); | |||
|
122 | } | |||
|
123 | ||||
|
124 | namespace { | |||
|
125 | ||||
|
126 | const auto LINE_SEP = QRegularExpression{QStringLiteral("\\s+")}; | |||
|
127 | ||||
|
128 | std::vector<double> fromFile(const QString &filePath) | |||
|
129 | { | |||
|
130 | QFile file{filePath}; | |||
|
131 | ||||
|
132 | if (!file.open(QFile::ReadOnly | QIODevice::Text)) { | |||
|
133 | return {}; | |||
|
134 | } | |||
|
135 | ||||
|
136 | std::vector<double> result{}; | |||
|
137 | ||||
|
138 | QTextStream stream{&file}; | |||
|
139 | QString line{}; | |||
|
140 | ||||
|
141 | while (stream.readLineInto(&line)) { | |||
|
142 | auto lineData = line.split(LINE_SEP, QString::SkipEmptyParts); | |||
|
143 | ||||
|
144 | for (auto data : lineData) { | |||
|
145 | bool valueOk; | |||
|
146 | auto value = data.toDouble(&valueOk); | |||
|
147 | ||||
|
148 | result.push_back(valueOk ? value : std::numeric_limits<double>::quiet_NaN()); | |||
|
149 | } | |||
|
150 | } | |||
|
151 | ||||
|
152 | return result; | |||
|
153 | } | |||
|
154 | ||||
|
155 | } // namespace | |||
|
156 | ||||
|
157 | void TestDataSeriesUtils::testThresholds_data() | |||
|
158 | { | |||
|
159 | QTest::addColumn<std::vector<double> >("input"); | |||
|
160 | QTest::addColumn<bool>("logarithmic"); | |||
|
161 | QTest::addColumn<double>("expectedMinThreshold"); | |||
|
162 | QTest::addColumn<double>("expectedMaxThreshold"); | |||
|
163 | ||||
|
164 | auto nan = std::numeric_limits<double>::quiet_NaN(); | |||
|
165 | ||||
|
166 | QTest::newRow("thresholds (basic case)") | |||
|
167 | << std::vector<double>{1., 2., 3., 4., 5., 6., 7., 8., 9., 10.} << false << 1. << 10.; | |||
|
168 | ||||
|
169 | QTest::newRow("thresholds (with nan values)") | |||
|
170 | << std::vector<double>{nan, 2., 3., 4., 5., 6., 7., 8., 9., nan} << false << 2. << 9.; | |||
|
171 | ||||
|
172 | QTest::newRow("thresholds (case with low values and aberrant value)") | |||
|
173 | << std::vector<double>{1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 2., | |||
|
174 | 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 3., 3., | |||
|
175 | 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 3., 100.} | |||
|
176 | << false << 1. << 47.073; | |||
|
177 | ||||
|
178 | QTest::newRow("thresholds (empty data)") << std::vector<double>{} << false << nan << nan; | |||
|
179 | QTest::newRow("thresholds (only nan values)") << std::vector<double>{nan, nan, nan, nan, nan} | |||
|
180 | << false << nan << nan; | |||
|
181 | ||||
|
182 | QTest::newRow("thresholds (from file with logarithmic scale)") | |||
|
183 | << fromFile(inputFilePath("TestThresholds.txt")) << true << 832.005 << 17655064.730; | |||
|
184 | } | |||
|
185 | ||||
|
186 | void TestDataSeriesUtils::testThresholds() | |||
|
187 | { | |||
|
188 | QFETCH(std::vector<double>, input); | |||
|
189 | QFETCH(bool, logarithmic); | |||
|
190 | QFETCH(double, expectedMinThreshold); | |||
|
191 | QFETCH(double, expectedMaxThreshold); | |||
|
192 | ||||
|
193 | double minThreshold, maxThreshold; | |||
|
194 | std::tie(minThreshold, maxThreshold) | |||
|
195 | = DataSeriesUtils::thresholds(input.begin(), input.end(), logarithmic); | |||
|
196 | ||||
|
197 | auto compareWithNaN = [](const auto &v1, const auto &v2) { | |||
|
198 | return (std::isnan(v1) && std::isnan(v2)) || std::abs(v1 - v2) < 1e-3; | |||
|
199 | }; | |||
|
200 | ||||
|
201 | QVERIFY(compareWithNaN(minThreshold, expectedMinThreshold)); | |||
|
202 | QVERIFY(compareWithNaN(maxThreshold, expectedMaxThreshold)); | |||
|
203 | } | |||
|
204 | ||||
|
205 | QTEST_MAIN(TestDataSeriesUtils) | |||
|
206 | #include "TestDataSeriesUtils.moc" |
@@ -0,0 +1,181 | |||||
|
1 | #include "Data/ArrayData.h" | |||
|
2 | #include <QObject> | |||
|
3 | #include <QtTest> | |||
|
4 | ||||
|
5 | namespace { | |||
|
6 | ||||
|
7 | using DataContainer = std::vector<double>; | |||
|
8 | ||||
|
9 | void verifyArrayData(const ArrayData<1> &arrayData, const DataContainer &expectedData) | |||
|
10 | { | |||
|
11 | QVERIFY(std::equal( | |||
|
12 | arrayData.cbegin(), arrayData.cend(), expectedData.cbegin(), expectedData.cend(), | |||
|
13 | [](const auto &it, const auto &expectedData) { return it.at(0) == expectedData; })); | |||
|
14 | } | |||
|
15 | ||||
|
16 | } // namespace | |||
|
17 | ||||
|
18 | class TestOneDimArrayData : public QObject { | |||
|
19 | Q_OBJECT | |||
|
20 | private slots: | |||
|
21 | /// Tests @sa ArrayData::data() | |||
|
22 | void testData_data(); | |||
|
23 | void testData(); | |||
|
24 | ||||
|
25 | /// Tests @sa ArrayData::add() | |||
|
26 | void testAdd_data(); | |||
|
27 | void testAdd(); | |||
|
28 | ||||
|
29 | /// Tests @sa ArrayData::at(int index) | |||
|
30 | void testAt_data(); | |||
|
31 | void testAt(); | |||
|
32 | ||||
|
33 | /// Tests @sa ArrayData::clear() | |||
|
34 | void testClear_data(); | |||
|
35 | void testClear(); | |||
|
36 | ||||
|
37 | /// Tests @sa ArrayData::size() | |||
|
38 | void testSize_data(); | |||
|
39 | void testSize(); | |||
|
40 | ||||
|
41 | /// Tests @sa ArrayData::sort() | |||
|
42 | void testSort_data(); | |||
|
43 | void testSort(); | |||
|
44 | }; | |||
|
45 | ||||
|
46 | void TestOneDimArrayData::testData_data() | |||
|
47 | { | |||
|
48 | // Test structure | |||
|
49 | QTest::addColumn<DataContainer>("inputData"); // array's data input | |||
|
50 | QTest::addColumn<DataContainer>("expectedData"); // expected data | |||
|
51 | ||||
|
52 | // Test cases | |||
|
53 | QTest::newRow("data1") << DataContainer{1., 2., 3., 4., 5.} | |||
|
54 | << DataContainer{1., 2., 3., 4., 5.}; | |||
|
55 | } | |||
|
56 | ||||
|
57 | void TestOneDimArrayData::testData() | |||
|
58 | { | |||
|
59 | QFETCH(DataContainer, inputData); | |||
|
60 | QFETCH(DataContainer, expectedData); | |||
|
61 | ||||
|
62 | ArrayData<1> arrayData{inputData}; | |||
|
63 | verifyArrayData(arrayData, expectedData); | |||
|
64 | } | |||
|
65 | ||||
|
66 | void TestOneDimArrayData::testAdd_data() | |||
|
67 | { | |||
|
68 | // Test structure | |||
|
69 | QTest::addColumn<DataContainer>("inputData"); // array's data input | |||
|
70 | QTest::addColumn<DataContainer>("otherData"); // array data's input to merge with | |||
|
71 | QTest::addColumn<bool>("prepend"); // prepend or append merge | |||
|
72 | QTest::addColumn<DataContainer>("expectedData"); // expected data after merge | |||
|
73 | ||||
|
74 | // Test cases | |||
|
75 | QTest::newRow("appendMerge") << DataContainer{1., 2., 3., 4., 5.} << DataContainer{6., 7., 8.} | |||
|
76 | << false << DataContainer{1., 2., 3., 4., 5., 6., 7., 8.}; | |||
|
77 | QTest::newRow("prependMerge") << DataContainer{1., 2., 3., 4., 5.} << DataContainer{6., 7., 8.} | |||
|
78 | << true << DataContainer{6., 7., 8., 1., 2., 3., 4., 5.}; | |||
|
79 | } | |||
|
80 | ||||
|
81 | void TestOneDimArrayData::testAdd() | |||
|
82 | { | |||
|
83 | QFETCH(DataContainer, inputData); | |||
|
84 | QFETCH(DataContainer, otherData); | |||
|
85 | QFETCH(bool, prepend); | |||
|
86 | QFETCH(DataContainer, expectedData); | |||
|
87 | ||||
|
88 | ArrayData<1> arrayData{inputData}; | |||
|
89 | ArrayData<1> other{otherData}; | |||
|
90 | ||||
|
91 | arrayData.add(other, prepend); | |||
|
92 | verifyArrayData(arrayData, expectedData); | |||
|
93 | } | |||
|
94 | ||||
|
95 | void TestOneDimArrayData::testAt_data() | |||
|
96 | { | |||
|
97 | // Test structure | |||
|
98 | QTest::addColumn<DataContainer>("inputData"); // array data's input | |||
|
99 | QTest::addColumn<int>("index"); // index to retrieve data | |||
|
100 | QTest::addColumn<double>("expectedData"); // expected data at index | |||
|
101 | ||||
|
102 | // Test cases | |||
|
103 | QTest::newRow("data1") << DataContainer{1., 2., 3., 4., 5.} << 0 << 1.; | |||
|
104 | QTest::newRow("data2") << DataContainer{1., 2., 3., 4., 5.} << 3 << 4.; | |||
|
105 | } | |||
|
106 | ||||
|
107 | void TestOneDimArrayData::testAt() | |||
|
108 | { | |||
|
109 | QFETCH(DataContainer, inputData); | |||
|
110 | QFETCH(int, index); | |||
|
111 | QFETCH(double, expectedData); | |||
|
112 | ||||
|
113 | ArrayData<1> arrayData{inputData}; | |||
|
114 | QVERIFY(arrayData.at(index) == expectedData); | |||
|
115 | } | |||
|
116 | ||||
|
117 | void TestOneDimArrayData::testClear_data() | |||
|
118 | { | |||
|
119 | // Test structure | |||
|
120 | QTest::addColumn<DataContainer>("inputData"); // array data's input | |||
|
121 | ||||
|
122 | // Test cases | |||
|
123 | QTest::newRow("data1") << DataContainer{1., 2., 3., 4., 5.}; | |||
|
124 | } | |||
|
125 | ||||
|
126 | void TestOneDimArrayData::testClear() | |||
|
127 | { | |||
|
128 | QFETCH(DataContainer, inputData); | |||
|
129 | ||||
|
130 | ArrayData<1> arrayData{inputData}; | |||
|
131 | arrayData.clear(); | |||
|
132 | verifyArrayData(arrayData, DataContainer{}); | |||
|
133 | } | |||
|
134 | ||||
|
135 | void TestOneDimArrayData::testSize_data() | |||
|
136 | { | |||
|
137 | // Test structure | |||
|
138 | QTest::addColumn<DataContainer>("inputData"); // array data's input | |||
|
139 | QTest::addColumn<int>("expectedSize"); // expected array data size | |||
|
140 | ||||
|
141 | // Test cases | |||
|
142 | QTest::newRow("data1") << DataContainer{1., 2., 3., 4., 5.} << 5; | |||
|
143 | } | |||
|
144 | ||||
|
145 | void TestOneDimArrayData::testSize() | |||
|
146 | { | |||
|
147 | QFETCH(DataContainer, inputData); | |||
|
148 | QFETCH(int, expectedSize); | |||
|
149 | ||||
|
150 | ArrayData<1> arrayData{inputData}; | |||
|
151 | QVERIFY(arrayData.size() == expectedSize); | |||
|
152 | } | |||
|
153 | ||||
|
154 | void TestOneDimArrayData::testSort_data() | |||
|
155 | { | |||
|
156 | // Test structure | |||
|
157 | QTest::addColumn<DataContainer>("inputData"); // array data's input | |||
|
158 | QTest::addColumn<std::vector<int> >("sortPermutation"); // permutation used to sort data | |||
|
159 | QTest::addColumn<DataContainer>("expectedData"); // expected data after sorting | |||
|
160 | ||||
|
161 | // Test cases | |||
|
162 | QTest::newRow("data1") << DataContainer{1., 2., 3., 4., 5.} << std::vector<int>{0, 2, 3, 1, 4} | |||
|
163 | << DataContainer{1., 3., 4., 2., 5.}; | |||
|
164 | QTest::newRow("data2") << DataContainer{1., 2., 3., 4., 5.} << std::vector<int>{4, 1, 2, 3, 0} | |||
|
165 | << DataContainer{5., 2., 3., 4., 1.}; | |||
|
166 | } | |||
|
167 | ||||
|
168 | void TestOneDimArrayData::testSort() | |||
|
169 | { | |||
|
170 | QFETCH(DataContainer, inputData); | |||
|
171 | QFETCH(std::vector<int>, sortPermutation); | |||
|
172 | QFETCH(DataContainer, expectedData); | |||
|
173 | ||||
|
174 | ArrayData<1> arrayData{inputData}; | |||
|
175 | auto sortedArrayData = arrayData.sort(sortPermutation); | |||
|
176 | QVERIFY(sortedArrayData != nullptr); | |||
|
177 | verifyArrayData(*sortedArrayData, expectedData); | |||
|
178 | } | |||
|
179 | ||||
|
180 | QTEST_MAIN(TestOneDimArrayData) | |||
|
181 | #include "TestOneDimArrayData.moc" |
@@ -0,0 +1,113 | |||||
|
1 | #include <Data/ArrayData.h> | |||
|
2 | #include <Data/OptionalAxis.h> | |||
|
3 | ||||
|
4 | #include <QObject> | |||
|
5 | #include <QtTest> | |||
|
6 | ||||
|
7 | Q_DECLARE_METATYPE(OptionalAxis) | |||
|
8 | ||||
|
9 | class TestOptionalAxis : public QObject { | |||
|
10 | Q_OBJECT | |||
|
11 | ||||
|
12 | private slots: | |||
|
13 | /// Tests the creation of a undefined axis | |||
|
14 | void testNotDefinedAxisCtor(); | |||
|
15 | ||||
|
16 | /// Tests the creation of a undefined axis | |||
|
17 | void testDefinedAxisCtor_data(); | |||
|
18 | void testDefinedAxisCtor(); | |||
|
19 | ||||
|
20 | /// Tests @sa OptionalAxis::size() method | |||
|
21 | void testSize_data(); | |||
|
22 | void testSize(); | |||
|
23 | ||||
|
24 | /// Tests @sa OptionalAxis::unit() method | |||
|
25 | void testUnit_data(); | |||
|
26 | void testUnit(); | |||
|
27 | }; | |||
|
28 | ||||
|
29 | void TestOptionalAxis::testNotDefinedAxisCtor() | |||
|
30 | { | |||
|
31 | OptionalAxis notDefinedAxis{}; | |||
|
32 | QVERIFY(!notDefinedAxis.isDefined()); | |||
|
33 | } | |||
|
34 | ||||
|
35 | void TestOptionalAxis::testDefinedAxisCtor_data() | |||
|
36 | { | |||
|
37 | QTest::addColumn<bool>("noData"); // If set to true, nullptr is passed as data of the axis | |||
|
38 | QTest::addColumn<std::vector<double> >( | |||
|
39 | "data"); // Values assigned to the axis when 'noData' flag is set to false | |||
|
40 | QTest::addColumn<Unit>("unit"); // Unit assigned to the axis | |||
|
41 | ||||
|
42 | QTest::newRow("validData") << false << std::vector<double>{1, 2, 3} << Unit{"Hz"}; | |||
|
43 | QTest::newRow("invalidData") << true << std::vector<double>{} << Unit{"Hz"}; | |||
|
44 | } | |||
|
45 | ||||
|
46 | void TestOptionalAxis::testDefinedAxisCtor() | |||
|
47 | { | |||
|
48 | QFETCH(bool, noData); | |||
|
49 | QFETCH(Unit, unit); | |||
|
50 | ||||
|
51 | // When there is no data, we expect that the constructor returns exception | |||
|
52 | if (noData) { | |||
|
53 | QVERIFY_EXCEPTION_THROWN(OptionalAxis(nullptr, unit), std::invalid_argument); | |||
|
54 | } | |||
|
55 | else { | |||
|
56 | QFETCH(std::vector<double>, data); | |||
|
57 | ||||
|
58 | OptionalAxis axis{std::make_shared<ArrayData<1> >(data), unit}; | |||
|
59 | QVERIFY(axis.isDefined()); | |||
|
60 | } | |||
|
61 | } | |||
|
62 | ||||
|
63 | void TestOptionalAxis::testSize_data() | |||
|
64 | { | |||
|
65 | QTest::addColumn<OptionalAxis>("axis"); // Axis used for test case (defined or not) | |||
|
66 | QTest::addColumn<int>("expectedSize"); // Expected number of data in the axis | |||
|
67 | ||||
|
68 | // Lambda that creates default defined axis (with the values passed in parameter) | |||
|
69 | auto axis = [](std::vector<double> values) { | |||
|
70 | return OptionalAxis{std::make_shared<ArrayData<1> >(std::move(values)), Unit{"Hz"}}; | |||
|
71 | }; | |||
|
72 | ||||
|
73 | QTest::newRow("data1") << axis({}) << 0; | |||
|
74 | QTest::newRow("data2") << axis({1, 2, 3}) << 3; | |||
|
75 | QTest::newRow("data3") << axis({1, 2, 3, 4}) << 4; | |||
|
76 | QTest::newRow("data4 (axis not defined)") << OptionalAxis{} | |||
|
77 | << 0; // Expects 0 for undefined axis | |||
|
78 | } | |||
|
79 | ||||
|
80 | void TestOptionalAxis::testSize() | |||
|
81 | { | |||
|
82 | QFETCH(OptionalAxis, axis); | |||
|
83 | QFETCH(int, expectedSize); | |||
|
84 | ||||
|
85 | QCOMPARE(axis.size(), expectedSize); | |||
|
86 | } | |||
|
87 | ||||
|
88 | void TestOptionalAxis::testUnit_data() | |||
|
89 | { | |||
|
90 | QTest::addColumn<OptionalAxis>("axis"); // Axis used for test case (defined or not) | |||
|
91 | QTest::addColumn<Unit>("expectedUnit"); // Expected unit for the axis | |||
|
92 | ||||
|
93 | // Lambda that creates default defined axis (with the unit passed in parameter) | |||
|
94 | auto axis = [](Unit unit) { | |||
|
95 | return OptionalAxis{std::make_shared<ArrayData<1> >(std::vector<double>{1, 2, 3}), unit}; | |||
|
96 | }; | |||
|
97 | ||||
|
98 | QTest::newRow("data1") << axis(Unit{"Hz"}) << Unit{"Hz"}; | |||
|
99 | QTest::newRow("data2") << axis(Unit{"t", true}) << Unit{"t", true}; | |||
|
100 | QTest::newRow("data3 (axis not defined)") << OptionalAxis{} | |||
|
101 | << Unit{}; // Expects default unit for undefined axis | |||
|
102 | } | |||
|
103 | ||||
|
104 | void TestOptionalAxis::testUnit() | |||
|
105 | { | |||
|
106 | QFETCH(OptionalAxis, axis); | |||
|
107 | QFETCH(Unit, expectedUnit); | |||
|
108 | ||||
|
109 | QCOMPARE(axis.unit(), expectedUnit); | |||
|
110 | } | |||
|
111 | ||||
|
112 | QTEST_MAIN(TestOptionalAxis) | |||
|
113 | #include "TestOptionalAxis.moc" |
@@ -0,0 +1,426 | |||||
|
1 | #include "Data/ScalarSeries.h" | |||
|
2 | ||||
|
3 | #include "DataSeriesBuilders.h" | |||
|
4 | #include "DataSeriesTestsUtils.h" | |||
|
5 | ||||
|
6 | #include <QObject> | |||
|
7 | #include <QtTest> | |||
|
8 | ||||
|
9 | /** | |||
|
10 | * @brief The TestScalarSeries class defines unit tests on scalar series. | |||
|
11 | * | |||
|
12 | * Most of these unit tests use generic tests defined for DataSeries (@sa DataSeriesTestsUtils) | |||
|
13 | */ | |||
|
14 | class TestScalarSeries : public QObject { | |||
|
15 | Q_OBJECT | |||
|
16 | private slots: | |||
|
17 | /// Tests construction of a scalar series | |||
|
18 | void testCtor_data(); | |||
|
19 | void testCtor(); | |||
|
20 | ||||
|
21 | /// Tests merge of two scalar series | |||
|
22 | void testMerge_data(); | |||
|
23 | void testMerge(); | |||
|
24 | ||||
|
25 | /// Tests merge of a vector series in a scalar series | |||
|
26 | void testMergeWithVector_data(); | |||
|
27 | void testMergeWithVector(); | |||
|
28 | ||||
|
29 | /// Tests get min x-axis data of a scalar series | |||
|
30 | void testMinXAxisData_data(); | |||
|
31 | void testMinXAxisData(); | |||
|
32 | ||||
|
33 | /// Tests get max x-axis data of a scalar series | |||
|
34 | void testMaxXAxisData_data(); | |||
|
35 | void testMaxXAxisData(); | |||
|
36 | ||||
|
37 | /// Tests purge of a scalar series | |||
|
38 | void testPurge_data(); | |||
|
39 | void testPurge(); | |||
|
40 | ||||
|
41 | /// Tests get x-axis range of a scalar series | |||
|
42 | void testXAxisRange_data(); | |||
|
43 | void testXAxisRange(); | |||
|
44 | ||||
|
45 | /// Tests get values bounds of a scalar series | |||
|
46 | void testValuesBounds_data(); | |||
|
47 | void testValuesBounds(); | |||
|
48 | }; | |||
|
49 | ||||
|
50 | void TestScalarSeries::testCtor_data() | |||
|
51 | { | |||
|
52 | // x-axis data | |||
|
53 | QTest::addColumn<DataContainer>("xAxisData"); | |||
|
54 | // values data | |||
|
55 | QTest::addColumn<DataContainer>("valuesData"); | |||
|
56 | ||||
|
57 | // construction expected to be valid | |||
|
58 | QTest::addColumn<bool>("expectOK"); | |||
|
59 | // expected x-axis data (when construction is valid) | |||
|
60 | QTest::addColumn<DataContainer>("expectedXAxisData"); | |||
|
61 | // expected values data (when construction is valid) | |||
|
62 | QTest::addColumn<DataContainer>("expectedValuesData"); | |||
|
63 | ||||
|
64 | QTest::newRow("invalidData (different sizes of vectors)") | |||
|
65 | << DataContainer{1., 2., 3., 4., 5.} << DataContainer{100., 200., 300.} << false | |||
|
66 | << DataContainer{} << DataContainer{}; | |||
|
67 | ||||
|
68 | QTest::newRow("sortedData") << DataContainer{1., 2., 3., 4., 5.} | |||
|
69 | << DataContainer{100., 200., 300., 400., 500.} << true | |||
|
70 | << DataContainer{1., 2., 3., 4., 5.} | |||
|
71 | << DataContainer{100., 200., 300., 400., 500.}; | |||
|
72 | ||||
|
73 | QTest::newRow("unsortedData") << DataContainer{5., 4., 3., 2., 1.} | |||
|
74 | << DataContainer{100., 200., 300., 400., 500.} << true | |||
|
75 | << DataContainer{1., 2., 3., 4., 5.} | |||
|
76 | << DataContainer{500., 400., 300., 200., 100.}; | |||
|
77 | ||||
|
78 | QTest::newRow("unsortedData2") | |||
|
79 | << DataContainer{1., 4., 3., 5., 2.} << DataContainer{100., 200., 300., 400., 500.} << true | |||
|
80 | << DataContainer{1., 2., 3., 4., 5.} << DataContainer{100., 500., 300., 200., 400.}; | |||
|
81 | } | |||
|
82 | ||||
|
83 | void TestScalarSeries::testCtor() | |||
|
84 | { | |||
|
85 | // Creates series | |||
|
86 | QFETCH(DataContainer, xAxisData); | |||
|
87 | QFETCH(DataContainer, valuesData); | |||
|
88 | QFETCH(bool, expectOK); | |||
|
89 | ||||
|
90 | if (expectOK) { | |||
|
91 | auto series = std::make_shared<ScalarSeries>(std::move(xAxisData), std::move(valuesData), | |||
|
92 | Unit{}, Unit{}); | |||
|
93 | ||||
|
94 | // Validates results : we check that the data series is sorted on its x-axis data | |||
|
95 | QFETCH(DataContainer, expectedXAxisData); | |||
|
96 | QFETCH(DataContainer, expectedValuesData); | |||
|
97 | ||||
|
98 | validateRange(series->cbegin(), series->cend(), expectedXAxisData, expectedValuesData); | |||
|
99 | } | |||
|
100 | else { | |||
|
101 | QVERIFY_EXCEPTION_THROWN(std::make_shared<ScalarSeries>( | |||
|
102 | std::move(xAxisData), std::move(valuesData), Unit{}, Unit{}), | |||
|
103 | std::invalid_argument); | |||
|
104 | } | |||
|
105 | } | |||
|
106 | ||||
|
107 | void TestScalarSeries::testMerge_data() | |||
|
108 | { | |||
|
109 | testMerge_struct<ScalarSeries, DataContainer>(); | |||
|
110 | ||||
|
111 | QTest::newRow("sortedMerge") << ScalarBuilder{} | |||
|
112 | .setX({1., 2., 3., 4., 5.}) | |||
|
113 | .setValues({100., 200., 300., 400., 500.}) | |||
|
114 | .build() | |||
|
115 | << ScalarBuilder{} | |||
|
116 | .setX({6., 7., 8., 9., 10.}) | |||
|
117 | .setValues({600., 700., 800., 900., 1000.}) | |||
|
118 | .build() | |||
|
119 | << DataContainer{1., 2., 3., 4., 5., 6., 7., 8., 9., 10.} | |||
|
120 | << DataContainer{100., 200., 300., 400., 500., | |||
|
121 | 600., 700., 800., 900., 1000.}; | |||
|
122 | ||||
|
123 | QTest::newRow("unsortedMerge") | |||
|
124 | << ScalarBuilder{} | |||
|
125 | .setX({6., 7., 8., 9., 10.}) | |||
|
126 | .setValues({600., 700., 800., 900., 1000.}) | |||
|
127 | .build() | |||
|
128 | << ScalarBuilder{} | |||
|
129 | .setX({1., 2., 3., 4., 5.}) | |||
|
130 | .setValues({100., 200., 300., 400., 500.}) | |||
|
131 | .build() | |||
|
132 | << DataContainer{1., 2., 3., 4., 5., 6., 7., 8., 9., 10.} | |||
|
133 | << DataContainer{100., 200., 300., 400., 500., 600., 700., 800., 900., 1000.}; | |||
|
134 | ||||
|
135 | QTest::newRow("unsortedMerge2 (merge not made because source is in the bounds of dest)") | |||
|
136 | << ScalarBuilder{} | |||
|
137 | .setX({1., 2., 8., 9., 10}) | |||
|
138 | .setValues({100., 200., 800., 900., 1000.}) | |||
|
139 | .build() | |||
|
140 | << ScalarBuilder{} | |||
|
141 | .setX({3., 4., 5., 6., 7.}) | |||
|
142 | .setValues({300., 400., 500., 600., 700.}) | |||
|
143 | .build() | |||
|
144 | << DataContainer{1., 2., 8., 9., 10.} << DataContainer{100., 200., 800., 900., 1000.}; | |||
|
145 | ||||
|
146 | QTest::newRow("unsortedMerge3") | |||
|
147 | << ScalarBuilder{} | |||
|
148 | .setX({3., 4., 5., 7., 8}) | |||
|
149 | .setValues({300., 400., 500., 700., 800.}) | |||
|
150 | .build() | |||
|
151 | << ScalarBuilder{} | |||
|
152 | .setX({1., 2., 3., 7., 10.}) | |||
|
153 | .setValues({100., 200., 333., 777., 1000.}) | |||
|
154 | .build() | |||
|
155 | << DataContainer{1., 2., 3., 4., 5., 7., 8., 10.} | |||
|
156 | << DataContainer{100., 200., 300., 400., 500., 700., 800., 1000.}; | |||
|
157 | ||||
|
158 | QTest::newRow("emptySource") << ScalarBuilder{} | |||
|
159 | .setX({3., 4., 5., 7., 8}) | |||
|
160 | .setValues({300., 400., 500., 700., 800.}) | |||
|
161 | .build() | |||
|
162 | << ScalarBuilder{}.setX({}).setValues({}).build() | |||
|
163 | << DataContainer{3., 4., 5., 7., 8.} | |||
|
164 | << DataContainer{300., 400., 500., 700., 800.}; | |||
|
165 | } | |||
|
166 | ||||
|
167 | void TestScalarSeries::testMerge() | |||
|
168 | { | |||
|
169 | testMerge_t<ScalarSeries, DataContainer>(); | |||
|
170 | } | |||
|
171 | ||||
|
172 | void TestScalarSeries::testMergeWithVector_data() | |||
|
173 | { | |||
|
174 | testMergeDifferentTypes_struct<VectorSeries, ScalarSeries>(); | |||
|
175 | ||||
|
176 | QTest::newRow("mergeVectorInScalar") << ScalarBuilder{} | |||
|
177 | .setX({1., 2., 3., 4., 5.}) | |||
|
178 | .setValues({100., 200., 300., 400., 500.}) | |||
|
179 | .build() | |||
|
180 | << VectorBuilder{} | |||
|
181 | .setX({6., 7., 8., 9., 10.}) | |||
|
182 | .setXValues({600., 700., 800., 900., 1000.}) | |||
|
183 | .setYValues({610., 710., 810., 910., 1010.}) | |||
|
184 | .setZValues({620., 720., 820., 920., 1020.}) | |||
|
185 | .build() | |||
|
186 | << DataContainer{1., 2., 3., 4., 5.} | |||
|
187 | << DataContainer{100., 200., 300., 400., 500.}; | |||
|
188 | } | |||
|
189 | ||||
|
190 | void TestScalarSeries::testMergeWithVector() | |||
|
191 | { | |||
|
192 | testMergeDifferentTypes_t<VectorSeries, ScalarSeries>(); | |||
|
193 | } | |||
|
194 | ||||
|
195 | void TestScalarSeries::testMinXAxisData_data() | |||
|
196 | { | |||
|
197 | testMinXAxisData_struct<ScalarSeries>(); | |||
|
198 | ||||
|
199 | QTest::newRow("minData1") << ScalarBuilder{} | |||
|
200 | .setX({1., 2., 3., 4., 5.}) | |||
|
201 | .setValues({100., 200., 300., 400., 500.}) | |||
|
202 | .build() | |||
|
203 | << 0. << true << 1.; | |||
|
204 | QTest::newRow("minData2") << ScalarBuilder{} | |||
|
205 | .setX({1., 2., 3., 4., 5.}) | |||
|
206 | .setValues({100., 200., 300., 400., 500.}) | |||
|
207 | .build() | |||
|
208 | << 1. << true << 1.; | |||
|
209 | QTest::newRow("minData3") << ScalarBuilder{} | |||
|
210 | .setX({1., 2., 3., 4., 5.}) | |||
|
211 | .setValues({100., 200., 300., 400., 500.}) | |||
|
212 | .build() | |||
|
213 | << 1.1 << true << 2.; | |||
|
214 | QTest::newRow("minData4") << ScalarBuilder{} | |||
|
215 | .setX({1., 2., 3., 4., 5.}) | |||
|
216 | .setValues({100., 200., 300., 400., 500.}) | |||
|
217 | .build() | |||
|
218 | << 5. << true << 5.; | |||
|
219 | QTest::newRow("minData5") << ScalarBuilder{} | |||
|
220 | .setX({1., 2., 3., 4., 5.}) | |||
|
221 | .setValues({100., 200., 300., 400., 500.}) | |||
|
222 | .build() | |||
|
223 | << 5.1 << false << std::numeric_limits<double>::quiet_NaN(); | |||
|
224 | QTest::newRow("minData6") << ScalarBuilder{}.setX({}).setValues({}).build() << 1.1 << false | |||
|
225 | << std::numeric_limits<double>::quiet_NaN(); | |||
|
226 | } | |||
|
227 | ||||
|
228 | void TestScalarSeries::testMinXAxisData() | |||
|
229 | { | |||
|
230 | testMinXAxisData_t<ScalarSeries>(); | |||
|
231 | } | |||
|
232 | ||||
|
233 | void TestScalarSeries::testMaxXAxisData_data() | |||
|
234 | { | |||
|
235 | testMaxXAxisData_struct<ScalarSeries>(); | |||
|
236 | ||||
|
237 | QTest::newRow("maxData1") << ScalarBuilder{} | |||
|
238 | .setX({1., 2., 3., 4., 5.}) | |||
|
239 | .setValues({100., 200., 300., 400., 500.}) | |||
|
240 | .build() | |||
|
241 | << 6. << true << 5.; | |||
|
242 | QTest::newRow("maxData2") << ScalarBuilder{} | |||
|
243 | .setX({1., 2., 3., 4., 5.}) | |||
|
244 | .setValues({100., 200., 300., 400., 500.}) | |||
|
245 | .build() | |||
|
246 | << 5. << true << 5.; | |||
|
247 | QTest::newRow("maxData3") << ScalarBuilder{} | |||
|
248 | .setX({1., 2., 3., 4., 5.}) | |||
|
249 | .setValues({100., 200., 300., 400., 500.}) | |||
|
250 | .build() | |||
|
251 | << 4.9 << true << 4.; | |||
|
252 | QTest::newRow("maxData4") << ScalarBuilder{} | |||
|
253 | .setX({1., 2., 3., 4., 5.}) | |||
|
254 | .setValues({100., 200., 300., 400., 500.}) | |||
|
255 | .build() | |||
|
256 | << 1.1 << true << 1.; | |||
|
257 | QTest::newRow("maxData5") << ScalarBuilder{} | |||
|
258 | .setX({1., 2., 3., 4., 5.}) | |||
|
259 | .setValues({100., 200., 300., 400., 500.}) | |||
|
260 | .build() | |||
|
261 | << 1. << true << 1.; | |||
|
262 | QTest::newRow("maxData6") << ScalarBuilder{}.setX({}).setValues({}).build() << 1.1 << false | |||
|
263 | << std::numeric_limits<double>::quiet_NaN(); | |||
|
264 | } | |||
|
265 | ||||
|
266 | void TestScalarSeries::testMaxXAxisData() | |||
|
267 | { | |||
|
268 | testMaxXAxisData_t<ScalarSeries>(); | |||
|
269 | } | |||
|
270 | ||||
|
271 | void TestScalarSeries::testPurge_data() | |||
|
272 | { | |||
|
273 | testPurge_struct<ScalarSeries>(); | |||
|
274 | ||||
|
275 | QTest::newRow("purgeScalar") << ScalarBuilder{} | |||
|
276 | .setX({1., 2., 3., 4., 5.}) | |||
|
277 | .setValues({100., 200., 300., 400., 500.}) | |||
|
278 | .build() | |||
|
279 | << 2. << 4. << DataContainer{2., 3., 4.} | |||
|
280 | << std::vector<DataContainer>{{200., 300., 400.}}; | |||
|
281 | QTest::newRow("purgeScalar1 (min/max swap)") << ScalarBuilder{} | |||
|
282 | .setX({1., 2., 3., 4., 5.}) | |||
|
283 | .setValues({100., 200., 300., 400., 500.}) | |||
|
284 | .build() | |||
|
285 | << 4. << 2. << DataContainer{2., 3., 4.} | |||
|
286 | << std::vector<DataContainer>{{200., 300., 400.}}; | |||
|
287 | QTest::newRow("purgeScalar2") << ScalarBuilder{} | |||
|
288 | .setX({1., 2., 3., 4., 5.}) | |||
|
289 | .setValues({100., 200., 300., 400., 500.}) | |||
|
290 | .build() | |||
|
291 | << 0. << 2.5 << DataContainer{1., 2.} | |||
|
292 | << std::vector<DataContainer>{{100., 200.}}; | |||
|
293 | QTest::newRow("purgeScalar3") << ScalarBuilder{} | |||
|
294 | .setX({1., 2., 3., 4., 5.}) | |||
|
295 | .setValues({100., 200., 300., 400., 500.}) | |||
|
296 | .build() | |||
|
297 | << 3.5 << 7. << DataContainer{4., 5.} | |||
|
298 | << std::vector<DataContainer>{{400., 500.}}; | |||
|
299 | QTest::newRow("purgeScalar4") << ScalarBuilder{} | |||
|
300 | .setX({1., 2., 3., 4., 5.}) | |||
|
301 | .setValues({100., 200., 300., 400., 500.}) | |||
|
302 | .build() | |||
|
303 | << 0. << 7. << DataContainer{1., 2., 3., 4., 5.} | |||
|
304 | << std::vector<DataContainer>{{100., 200., 300., 400., 500.}}; | |||
|
305 | QTest::newRow("purgeScalar5") << ScalarBuilder{} | |||
|
306 | .setX({1., 2., 3., 4., 5.}) | |||
|
307 | .setValues({100., 200., 300., 400., 500.}) | |||
|
308 | .build() | |||
|
309 | << 5.5 << 7. << DataContainer{} << std::vector<DataContainer>{{}}; | |||
|
310 | } | |||
|
311 | ||||
|
312 | void TestScalarSeries::testPurge() | |||
|
313 | { | |||
|
314 | testPurge_t<ScalarSeries>(); | |||
|
315 | } | |||
|
316 | ||||
|
317 | void TestScalarSeries::testXAxisRange_data() | |||
|
318 | { | |||
|
319 | testXAxisRange_struct<ScalarSeries>(); | |||
|
320 | ||||
|
321 | QTest::newRow("xAxisRange") << ScalarBuilder{} | |||
|
322 | .setX({1., 2., 3., 4., 5.}) | |||
|
323 | .setValues({100., 200., 300., 400., 500.}) | |||
|
324 | .build() | |||
|
325 | << -1. << 3.2 << DataContainer{1., 2., 3.} | |||
|
326 | << DataContainer{100., 200., 300.}; | |||
|
327 | QTest::newRow("xAxisRange1 (min/max swap)") << ScalarBuilder{} | |||
|
328 | .setX({1., 2., 3., 4., 5.}) | |||
|
329 | .setValues({100., 200., 300., 400., 500.}) | |||
|
330 | .build() | |||
|
331 | << 3.2 << -1. << DataContainer{1., 2., 3.} | |||
|
332 | << DataContainer{100., 200., 300.}; | |||
|
333 | QTest::newRow("xAxisRange2") << ScalarBuilder{} | |||
|
334 | .setX({1., 2., 3., 4., 5.}) | |||
|
335 | .setValues({100., 200., 300., 400., 500.}) | |||
|
336 | .build() | |||
|
337 | << 1. << 4. << DataContainer{1., 2., 3., 4.} | |||
|
338 | << DataContainer{100., 200., 300., 400.}; | |||
|
339 | QTest::newRow("xAxisRange3") << ScalarBuilder{} | |||
|
340 | .setX({1., 2., 3., 4., 5.}) | |||
|
341 | .setValues({100., 200., 300., 400., 500.}) | |||
|
342 | .build() | |||
|
343 | << 1. << 3.9 << DataContainer{1., 2., 3.} | |||
|
344 | << DataContainer{100., 200., 300.}; | |||
|
345 | QTest::newRow("xAxisRange4") << ScalarBuilder{} | |||
|
346 | .setX({1., 2., 3., 4., 5.}) | |||
|
347 | .setValues({100., 200., 300., 400., 500.}) | |||
|
348 | .build() | |||
|
349 | << 0. << 0.9 << DataContainer{} << DataContainer{}; | |||
|
350 | QTest::newRow("xAxisRange5") << ScalarBuilder{} | |||
|
351 | .setX({1., 2., 3., 4., 5.}) | |||
|
352 | .setValues({100., 200., 300., 400., 500.}) | |||
|
353 | .build() | |||
|
354 | << 0. << 1. << DataContainer{1.} << DataContainer{100.}; | |||
|
355 | QTest::newRow("xAxisRange6") << ScalarBuilder{} | |||
|
356 | .setX({1., 2., 3., 4., 5.}) | |||
|
357 | .setValues({100., 200., 300., 400., 500.}) | |||
|
358 | .build() | |||
|
359 | << 2.1 << 6. << DataContainer{3., 4., 5.} | |||
|
360 | << DataContainer{300., 400., 500.}; | |||
|
361 | QTest::newRow("xAxisRange7") << ScalarBuilder{} | |||
|
362 | .setX({1., 2., 3., 4., 5.}) | |||
|
363 | .setValues({100., 200., 300., 400., 500.}) | |||
|
364 | .build() | |||
|
365 | << 6. << 9. << DataContainer{} << DataContainer{}; | |||
|
366 | QTest::newRow("xAxisRange8") << ScalarBuilder{} | |||
|
367 | .setX({1., 2., 3., 4., 5.}) | |||
|
368 | .setValues({100., 200., 300., 400., 500.}) | |||
|
369 | .build() | |||
|
370 | << 5. << 9. << DataContainer{5.} << DataContainer{500.}; | |||
|
371 | } | |||
|
372 | ||||
|
373 | void TestScalarSeries::testXAxisRange() | |||
|
374 | { | |||
|
375 | testXAxisRange_t<ScalarSeries>(); | |||
|
376 | } | |||
|
377 | ||||
|
378 | void TestScalarSeries::testValuesBounds_data() | |||
|
379 | { | |||
|
380 | testValuesBounds_struct<ScalarSeries>(); | |||
|
381 | ||||
|
382 | auto nan = std::numeric_limits<double>::quiet_NaN(); | |||
|
383 | ||||
|
384 | QTest::newRow("scalarBounds1") << ScalarBuilder{} | |||
|
385 | .setX({1., 2., 3., 4., 5.}) | |||
|
386 | .setValues({100., 200., 300., 400., 500.}) | |||
|
387 | .build() | |||
|
388 | << 0. << 6. << true << 100. << 500.; | |||
|
389 | QTest::newRow("scalarBounds2") << ScalarBuilder{} | |||
|
390 | .setX({1., 2., 3., 4., 5.}) | |||
|
391 | .setValues({100., 200., 300., 400., 500.}) | |||
|
392 | .build() | |||
|
393 | << 2. << 4. << true << 200. << 400.; | |||
|
394 | QTest::newRow("scalarBounds3") << ScalarBuilder{} | |||
|
395 | .setX({1., 2., 3., 4., 5.}) | |||
|
396 | .setValues({100., 200., 300., 400., 500.}) | |||
|
397 | .build() | |||
|
398 | << 0. << 0.5 << false << nan << nan; | |||
|
399 | QTest::newRow("scalarBounds4") << ScalarBuilder{} | |||
|
400 | .setX({1., 2., 3., 4., 5.}) | |||
|
401 | .setValues({100., 200., 300., 400., 500.}) | |||
|
402 | .build() | |||
|
403 | << 5.1 << 6. << false << nan << nan; | |||
|
404 | QTest::newRow("scalarBounds5") << ScalarBuilder{}.setX({1.}).setValues({100.}).build() << 0. | |||
|
405 | << 2. << true << 100. << 100.; | |||
|
406 | QTest::newRow("scalarBounds6") << ScalarBuilder{}.setX({}).setValues({}).build() << 0. << 2. | |||
|
407 | << false << nan << nan; | |||
|
408 | ||||
|
409 | // Tests with NaN values: NaN values are not included in min/max search | |||
|
410 | QTest::newRow("scalarBounds7") << ScalarBuilder{} | |||
|
411 | .setX({1., 2., 3., 4., 5.}) | |||
|
412 | .setValues({nan, 200., 300., 400., nan}) | |||
|
413 | .build() | |||
|
414 | << 0. << 6. << true << 200. << 400.; | |||
|
415 | QTest::newRow("scalarBounds8") | |||
|
416 | << ScalarBuilder{}.setX({1., 2., 3., 4., 5.}).setValues({nan, nan, nan, nan, nan}).build() | |||
|
417 | << 0. << 6. << true << nan << nan; | |||
|
418 | } | |||
|
419 | ||||
|
420 | void TestScalarSeries::testValuesBounds() | |||
|
421 | { | |||
|
422 | testValuesBounds_t<ScalarSeries>(); | |||
|
423 | } | |||
|
424 | ||||
|
425 | QTEST_MAIN(TestScalarSeries) | |||
|
426 | #include "TestScalarSeries.moc" |
@@ -0,0 +1,198 | |||||
|
1 | #include "Data/SpectrogramSeries.h" | |||
|
2 | ||||
|
3 | #include "DataSeriesBuilders.h" | |||
|
4 | #include "DataSeriesTestsUtils.h" | |||
|
5 | ||||
|
6 | #include <QObject> | |||
|
7 | #include <QtTest> | |||
|
8 | ||||
|
9 | namespace { | |||
|
10 | ||||
|
11 | // Aliases used to facilitate reading of test inputs | |||
|
12 | using X = DataContainer; | |||
|
13 | using Y = DataContainer; | |||
|
14 | using Values = DataContainer; | |||
|
15 | using Components = std::vector<DataContainer>; | |||
|
16 | ||||
|
17 | } // namespace | |||
|
18 | ||||
|
19 | /** | |||
|
20 | * @brief The TestSpectrogramSeries class defines unit tests on spectrogram series. | |||
|
21 | * | |||
|
22 | * Most of these unit tests use generic tests defined for DataSeries (@sa DataSeriesTestsUtils) | |||
|
23 | */ | |||
|
24 | class TestSpectrogramSeries : public QObject { | |||
|
25 | Q_OBJECT | |||
|
26 | private slots: | |||
|
27 | ||||
|
28 | /// Tests construction of a spectrogram series | |||
|
29 | void testCtor_data(); | |||
|
30 | void testCtor(); | |||
|
31 | ||||
|
32 | /// Tests merge of two spectrogram series | |||
|
33 | void testMerge_data(); | |||
|
34 | void testMerge(); | |||
|
35 | ||||
|
36 | /// Tests get subdata of a spectrogram series | |||
|
37 | void testSubDataSeries_data(); | |||
|
38 | void testSubDataSeries(); | |||
|
39 | }; | |||
|
40 | ||||
|
41 | void TestSpectrogramSeries::testCtor_data() | |||
|
42 | { | |||
|
43 | // x-axis data | |||
|
44 | QTest::addColumn<X>("xAxisData"); | |||
|
45 | // y-axis data | |||
|
46 | QTest::addColumn<Y>("yAxisData"); | |||
|
47 | // values data | |||
|
48 | QTest::addColumn<Values>("valuesData"); | |||
|
49 | ||||
|
50 | // construction expected to be valid | |||
|
51 | QTest::addColumn<bool>("expectOK"); | |||
|
52 | // expected x-axis data (when construction is valid) | |||
|
53 | QTest::addColumn<X>("expectedXAxisData"); | |||
|
54 | // expected components data (when construction is valid) | |||
|
55 | QTest::addColumn<Components>("expectedComponentsData"); | |||
|
56 | ||||
|
57 | QTest::newRow( | |||
|
58 | "invalidData (number of values by component aren't equal to the number of x-axis data)") | |||
|
59 | << X{1., 2., 3., 4., 5.} << Y{1., 2., 3.} << Values{1., 2., 3.} << false << X{} | |||
|
60 | << Components{}; | |||
|
61 | ||||
|
62 | QTest::newRow("invalidData (number of components aren't equal to the number of y-axis data)") | |||
|
63 | << X{1., 2., 3., 4., 5.} << Y{1., 2.} // 2 y-axis data | |||
|
64 | << Values{1., 2., 3., 4., 5.} // 1 component | |||
|
65 | << false << X{} << Components{}; | |||
|
66 | ||||
|
67 | QTest::newRow("sortedData") << X{1., 2., 3., 4., 5.} << Y{1., 2.} // 2 y-axis data | |||
|
68 | << Values{1., 2., 3., 4., 5., 6., 7., 8., 9., 10.} // 2 components | |||
|
69 | << true << X{1., 2., 3., 4., 5.} | |||
|
70 | << Components{{1., 3., 5., 7., 9.}, {2., 4., 6., 8., 10.}}; | |||
|
71 | ||||
|
72 | QTest::newRow("unsortedData") << X{5., 4., 3., 2., 1.} << Y{1., 2.} | |||
|
73 | << Values{1., 2., 3., 4., 5., 6., 7., 8., 9., 10.} << true | |||
|
74 | << X{1., 2., 3., 4., 5.} | |||
|
75 | << Components{{9., 7., 5., 3., 1.}, {10., 8., 6., 4., 2.}}; | |||
|
76 | } | |||
|
77 | ||||
|
78 | void TestSpectrogramSeries::testCtor() | |||
|
79 | { | |||
|
80 | // Creates series | |||
|
81 | QFETCH(X, xAxisData); | |||
|
82 | QFETCH(Y, yAxisData); | |||
|
83 | QFETCH(Values, valuesData); | |||
|
84 | QFETCH(bool, expectOK); | |||
|
85 | ||||
|
86 | if (expectOK) { | |||
|
87 | auto series = SpectrogramBuilder{} | |||
|
88 | .setX(std::move(xAxisData)) | |||
|
89 | .setY(std::move(yAxisData)) | |||
|
90 | .setValues(std::move(valuesData)) | |||
|
91 | .build(); | |||
|
92 | ||||
|
93 | // Validates results | |||
|
94 | QFETCH(X, expectedXAxisData); | |||
|
95 | QFETCH(Components, expectedComponentsData); | |||
|
96 | validateRange(series->cbegin(), series->cend(), expectedXAxisData, expectedComponentsData); | |||
|
97 | } | |||
|
98 | else { | |||
|
99 | QVERIFY_EXCEPTION_THROWN(SpectrogramBuilder{} | |||
|
100 | .setX(std::move(xAxisData)) | |||
|
101 | .setY(std::move(yAxisData)) | |||
|
102 | .setValues(std::move(valuesData)) | |||
|
103 | .build(), | |||
|
104 | std::invalid_argument); | |||
|
105 | } | |||
|
106 | } | |||
|
107 | ||||
|
108 | void TestSpectrogramSeries::testMerge_data() | |||
|
109 | { | |||
|
110 | testMerge_struct<SpectrogramSeries, Components>(); | |||
|
111 | ||||
|
112 | QTest::newRow("sortedMerge") << SpectrogramBuilder{} | |||
|
113 | .setX({1., 2., 3.}) | |||
|
114 | .setY({1., 2.}) | |||
|
115 | .setValues({10., 11., 20., 21., 30., 31}) | |||
|
116 | .build() | |||
|
117 | << SpectrogramBuilder{} | |||
|
118 | .setX({4., 5., 6.}) | |||
|
119 | .setY({1., 2.}) | |||
|
120 | .setValues({40., 41., 50., 51., 60., 61}) | |||
|
121 | .build() | |||
|
122 | << DataContainer{1., 2., 3., 4., 5., 6.} | |||
|
123 | << Components{{10., 20., 30., 40., 50., 60.}, | |||
|
124 | {11., 21., 31., 41., 51., 61}}; | |||
|
125 | ||||
|
126 | QTest::newRow( | |||
|
127 | "unsortedMerge (merge not made because the two data series have different y-axes)") | |||
|
128 | << SpectrogramBuilder{} | |||
|
129 | .setX({4., 5., 6.}) | |||
|
130 | .setY({1., 2.}) | |||
|
131 | .setValues({40., 41., 50., 51., 60., 61}) | |||
|
132 | .build() | |||
|
133 | << SpectrogramBuilder{} | |||
|
134 | .setX({1., 2., 3.}) | |||
|
135 | .setY({3., 4.}) | |||
|
136 | .setValues({10., 11., 20., 21., 30., 31}) | |||
|
137 | .build() | |||
|
138 | << DataContainer{4., 5., 6.} << Components{{40., 50., 60.}, {41., 51., 61}}; | |||
|
139 | ||||
|
140 | QTest::newRow( | |||
|
141 | "unsortedMerge (unsortedMerge (merge is made because the two data series have the same " | |||
|
142 | "y-axis)") | |||
|
143 | << SpectrogramBuilder{} | |||
|
144 | .setX({4., 5., 6.}) | |||
|
145 | .setY({1., 2.}) | |||
|
146 | .setValues({40., 41., 50., 51., 60., 61}) | |||
|
147 | .build() | |||
|
148 | << SpectrogramBuilder{} | |||
|
149 | .setX({1., 2., 3.}) | |||
|
150 | .setY({1., 2.}) | |||
|
151 | .setValues({10., 11., 20., 21., 30., 31}) | |||
|
152 | .build() | |||
|
153 | << DataContainer{1., 2., 3., 4., 5., 6.} | |||
|
154 | << Components{{10., 20., 30., 40., 50., 60.}, {11., 21., 31., 41., 51., 61}}; | |||
|
155 | } | |||
|
156 | ||||
|
157 | void TestSpectrogramSeries::testMerge() | |||
|
158 | { | |||
|
159 | testMerge_t<SpectrogramSeries, Components>(); | |||
|
160 | } | |||
|
161 | ||||
|
162 | void TestSpectrogramSeries::testSubDataSeries_data() | |||
|
163 | { | |||
|
164 | testSubDataSeries_struct<SpectrogramSeries, Components>(); | |||
|
165 | ||||
|
166 | QTest::newRow("subDataSeries (the range includes all data)") | |||
|
167 | << SpectrogramBuilder{} | |||
|
168 | .setX({1., 2., 3.}) | |||
|
169 | .setY({1., 2.}) | |||
|
170 | .setValues({10., 11., 20., 21., 30., 31}) | |||
|
171 | .build() | |||
|
172 | << DateTimeRange{0., 5.} << DataContainer{1., 2., 3.} | |||
|
173 | << Components{{10., 20., 30.}, {11., 21., 31.}}; | |||
|
174 | ||||
|
175 | QTest::newRow("subDataSeries (the range includes no data)") | |||
|
176 | << SpectrogramBuilder{} | |||
|
177 | .setX({1., 2., 3.}) | |||
|
178 | .setY({1., 2.}) | |||
|
179 | .setValues({10., 11., 20., 21., 30., 31}) | |||
|
180 | .build() | |||
|
181 | << DateTimeRange{4., 5.} << DataContainer{} << Components{{}, {}}; | |||
|
182 | ||||
|
183 | QTest::newRow("subDataSeries (the range includes some data)") | |||
|
184 | << SpectrogramBuilder{} | |||
|
185 | .setX({1., 2., 3.}) | |||
|
186 | .setY({1., 2.}) | |||
|
187 | .setValues({10., 11., 20., 21., 30., 31}) | |||
|
188 | .build() | |||
|
189 | << DateTimeRange{1.1, 3} << DataContainer{2., 3.} << Components{{20., 30.}, {21., 31.}}; | |||
|
190 | } | |||
|
191 | ||||
|
192 | void TestSpectrogramSeries::testSubDataSeries() | |||
|
193 | { | |||
|
194 | testSubDataSeries_t<SpectrogramSeries, Components>(); | |||
|
195 | } | |||
|
196 | ||||
|
197 | QTEST_MAIN(TestSpectrogramSeries) | |||
|
198 | #include "TestSpectrogramSeries.moc" |
@@ -0,0 +1,240 | |||||
|
1 | #include "Data/ArrayData.h" | |||
|
2 | #include <QObject> | |||
|
3 | #include <QtTest> | |||
|
4 | ||||
|
5 | using DataContainer = std::vector<double>; | |||
|
6 | using Container = std::vector<DataContainer>; | |||
|
7 | using InputData = QPair<DataContainer, int>; | |||
|
8 | ||||
|
9 | namespace { | |||
|
10 | ||||
|
11 | InputData flatten(const Container &container) | |||
|
12 | { | |||
|
13 | if (container.empty()) { | |||
|
14 | return {}; | |||
|
15 | } | |||
|
16 | ||||
|
17 | // We assume here that each component of the container have the same size | |||
|
18 | auto containerSize = container.size(); | |||
|
19 | auto componentSize = container.front().size(); | |||
|
20 | ||||
|
21 | auto result = DataContainer{}; | |||
|
22 | result.reserve(componentSize * containerSize); | |||
|
23 | ||||
|
24 | for (auto i = 0u; i < componentSize; ++i) { | |||
|
25 | for (auto j = 0u; j < containerSize; ++j) { | |||
|
26 | result.push_back(container.at(j).at(i)); | |||
|
27 | } | |||
|
28 | } | |||
|
29 | ||||
|
30 | return {result, static_cast<int>(containerSize)}; | |||
|
31 | } | |||
|
32 | ||||
|
33 | void verifyArrayData(const ArrayData<2> &arrayData, const Container &expectedData) | |||
|
34 | { | |||
|
35 | auto verifyComponent = [&arrayData](const auto &componentData, const auto &equalFun) { | |||
|
36 | QVERIFY(std::equal(arrayData.cbegin(), arrayData.cend(), componentData.cbegin(), | |||
|
37 | componentData.cend(), | |||
|
38 | [&equalFun](const auto &dataSeriesIt, const auto &expectedValue) { | |||
|
39 | return equalFun(dataSeriesIt, expectedValue); | |||
|
40 | })); | |||
|
41 | }; | |||
|
42 | ||||
|
43 | for (auto i = 0u; i < expectedData.size(); ++i) { | |||
|
44 | verifyComponent(expectedData.at(i), [i](const auto &seriesIt, const auto &value) { | |||
|
45 | return seriesIt.at(i) == value; | |||
|
46 | }); | |||
|
47 | } | |||
|
48 | } | |||
|
49 | ||||
|
50 | } // namespace | |||
|
51 | ||||
|
52 | class TestTwoDimArrayData : public QObject { | |||
|
53 | Q_OBJECT | |||
|
54 | private slots: | |||
|
55 | /// Tests @sa ArrayData ctor | |||
|
56 | void testCtor_data(); | |||
|
57 | void testCtor(); | |||
|
58 | ||||
|
59 | /// Tests @sa ArrayData::add() | |||
|
60 | void testAdd_data(); | |||
|
61 | void testAdd(); | |||
|
62 | ||||
|
63 | /// Tests @sa ArrayData::clear() | |||
|
64 | void testClear_data(); | |||
|
65 | void testClear(); | |||
|
66 | ||||
|
67 | /// Tests @sa ArrayData::size() | |||
|
68 | void testSize_data(); | |||
|
69 | void testSize(); | |||
|
70 | ||||
|
71 | /// Tests @sa ArrayData::sort() | |||
|
72 | void testSort_data(); | |||
|
73 | void testSort(); | |||
|
74 | }; | |||
|
75 | ||||
|
76 | void TestTwoDimArrayData::testCtor_data() | |||
|
77 | { | |||
|
78 | // Test structure | |||
|
79 | QTest::addColumn<InputData>("inputData"); // array data's input | |||
|
80 | QTest::addColumn<bool>("success"); // array data has been successfully constructed | |||
|
81 | QTest::addColumn<Container>("expectedData"); // expected array data (when success) | |||
|
82 | ||||
|
83 | // Test cases | |||
|
84 | QTest::newRow("validInput") << flatten(Container{{1., 2., 3., 4., 5.}, | |||
|
85 | {6., 7., 8., 9., 10.}, | |||
|
86 | {11., 12., 13., 14., 15.}}) | |||
|
87 | << true << Container{{1., 2., 3., 4., 5.}, | |||
|
88 | {6., 7., 8., 9., 10.}, | |||
|
89 | {11., 12., 13., 14., 15.}}; | |||
|
90 | QTest::newRow("invalidInput (invalid data size") << InputData{{1., 2., 3., 4., 5., 6., 7.}, 3} | |||
|
91 | << false << Container{{}, {}, {}}; | |||
|
92 | QTest::newRow("invalidInput (less than two components") | |||
|
93 | << flatten(Container{{1., 2., 3., 4., 5.}}) << false << Container{{}, {}, {}}; | |||
|
94 | } | |||
|
95 | ||||
|
96 | void TestTwoDimArrayData::testCtor() | |||
|
97 | { | |||
|
98 | QFETCH(InputData, inputData); | |||
|
99 | QFETCH(bool, success); | |||
|
100 | ||||
|
101 | if (success) { | |||
|
102 | QFETCH(Container, expectedData); | |||
|
103 | ||||
|
104 | ArrayData<2> arrayData{inputData.first, inputData.second}; | |||
|
105 | verifyArrayData(arrayData, expectedData); | |||
|
106 | } | |||
|
107 | else { | |||
|
108 | QVERIFY_EXCEPTION_THROWN(ArrayData<2>(inputData.first, inputData.second), | |||
|
109 | std::invalid_argument); | |||
|
110 | } | |||
|
111 | } | |||
|
112 | ||||
|
113 | void TestTwoDimArrayData::testAdd_data() | |||
|
114 | { | |||
|
115 | // Test structure | |||
|
116 | QTest::addColumn<InputData>("inputData"); // array's data input | |||
|
117 | QTest::addColumn<InputData>("otherData"); // array data's input to merge with | |||
|
118 | QTest::addColumn<bool>("prepend"); // prepend or append merge | |||
|
119 | QTest::addColumn<Container>("expectedData"); // expected data after merge | |||
|
120 | ||||
|
121 | // Test cases | |||
|
122 | auto inputData = flatten( | |||
|
123 | Container{{1., 2., 3., 4., 5.}, {11., 12., 13., 14., 15.}, {21., 22., 23., 24., 25.}}); | |||
|
124 | ||||
|
125 | auto vectorContainer = flatten(Container{{6., 7., 8.}, {16., 17., 18.}, {26., 27., 28}}); | |||
|
126 | auto tensorContainer = flatten(Container{{6., 7., 8.}, | |||
|
127 | {16., 17., 18.}, | |||
|
128 | {26., 27., 28}, | |||
|
129 | {36., 37., 38.}, | |||
|
130 | {46., 47., 48.}, | |||
|
131 | {56., 57., 58}}); | |||
|
132 | ||||
|
133 | QTest::newRow("appendMerge") << inputData << vectorContainer << false | |||
|
134 | << Container{{1., 2., 3., 4., 5., 6., 7., 8.}, | |||
|
135 | {11., 12., 13., 14., 15., 16., 17., 18.}, | |||
|
136 | {21., 22., 23., 24., 25., 26., 27., 28}}; | |||
|
137 | QTest::newRow("prependMerge") << inputData << vectorContainer << true | |||
|
138 | << Container{{6., 7., 8., 1., 2., 3., 4., 5.}, | |||
|
139 | {16., 17., 18., 11., 12., 13., 14., 15.}, | |||
|
140 | {26., 27., 28, 21., 22., 23., 24., 25.}}; | |||
|
141 | QTest::newRow("invalidMerge") << inputData << tensorContainer << false | |||
|
142 | << Container{{1., 2., 3., 4., 5.}, | |||
|
143 | {11., 12., 13., 14., 15.}, | |||
|
144 | {21., 22., 23., 24., 25.}}; | |||
|
145 | } | |||
|
146 | ||||
|
147 | void TestTwoDimArrayData::testAdd() | |||
|
148 | { | |||
|
149 | QFETCH(InputData, inputData); | |||
|
150 | QFETCH(InputData, otherData); | |||
|
151 | QFETCH(bool, prepend); | |||
|
152 | QFETCH(Container, expectedData); | |||
|
153 | ||||
|
154 | ArrayData<2> arrayData{inputData.first, inputData.second}; | |||
|
155 | ArrayData<2> other{otherData.first, otherData.second}; | |||
|
156 | ||||
|
157 | arrayData.add(other, prepend); | |||
|
158 | ||||
|
159 | verifyArrayData(arrayData, expectedData); | |||
|
160 | } | |||
|
161 | ||||
|
162 | void TestTwoDimArrayData::testClear_data() | |||
|
163 | { | |||
|
164 | // Test structure | |||
|
165 | QTest::addColumn<InputData>("inputData"); // array data's input | |||
|
166 | ||||
|
167 | // Test cases | |||
|
168 | QTest::newRow("data1") << flatten( | |||
|
169 | Container{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}}); | |||
|
170 | } | |||
|
171 | ||||
|
172 | void TestTwoDimArrayData::testClear() | |||
|
173 | { | |||
|
174 | QFETCH(InputData, inputData); | |||
|
175 | ||||
|
176 | ArrayData<2> arrayData{inputData.first, inputData.second}; | |||
|
177 | arrayData.clear(); | |||
|
178 | ||||
|
179 | auto emptyData = Container(inputData.second, DataContainer{}); | |||
|
180 | verifyArrayData(arrayData, emptyData); | |||
|
181 | } | |||
|
182 | ||||
|
183 | void TestTwoDimArrayData::testSize_data() | |||
|
184 | { | |||
|
185 | // Test structure | |||
|
186 | QTest::addColumn<InputData>("inputData"); // array data's input | |||
|
187 | QTest::addColumn<int>("expectedSize"); // expected array data size | |||
|
188 | ||||
|
189 | // Test cases | |||
|
190 | QTest::newRow("data1") << flatten(Container{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}}) << 5; | |||
|
191 | QTest::newRow("data2") << flatten(Container{{1., 2., 3., 4., 5.}, | |||
|
192 | {6., 7., 8., 9., 10.}, | |||
|
193 | {11., 12., 13., 14., 15.}}) | |||
|
194 | << 5; | |||
|
195 | } | |||
|
196 | ||||
|
197 | void TestTwoDimArrayData::testSize() | |||
|
198 | { | |||
|
199 | QFETCH(InputData, inputData); | |||
|
200 | QFETCH(int, expectedSize); | |||
|
201 | ||||
|
202 | ArrayData<2> arrayData{inputData.first, inputData.second}; | |||
|
203 | QVERIFY(arrayData.size() == expectedSize); | |||
|
204 | } | |||
|
205 | ||||
|
206 | void TestTwoDimArrayData::testSort_data() | |||
|
207 | { | |||
|
208 | // Test structure | |||
|
209 | QTest::addColumn<InputData>("inputData"); // array data's input | |||
|
210 | QTest::addColumn<std::vector<int> >("sortPermutation"); // permutation used to sort data | |||
|
211 | QTest::addColumn<Container>("expectedData"); // expected data after sorting | |||
|
212 | ||||
|
213 | // Test cases | |||
|
214 | QTest::newRow("data1") | |||
|
215 | << flatten( | |||
|
216 | Container{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}}) | |||
|
217 | << std::vector<int>{0, 2, 3, 1, 4} | |||
|
218 | << Container{{1., 3., 4., 2., 5.}, {6., 8., 9., 7., 10.}, {11., 13., 14., 12., 15.}}; | |||
|
219 | QTest::newRow("data2") | |||
|
220 | << flatten( | |||
|
221 | Container{{1., 2., 3., 4., 5.}, {6., 7., 8., 9., 10.}, {11., 12., 13., 14., 15.}}) | |||
|
222 | << std::vector<int>{2, 4, 3, 0, 1} | |||
|
223 | << Container{{3., 5., 4., 1., 2.}, {8., 10., 9., 6., 7.}, {13., 15., 14., 11., 12.}}; | |||
|
224 | } | |||
|
225 | ||||
|
226 | void TestTwoDimArrayData::testSort() | |||
|
227 | { | |||
|
228 | QFETCH(InputData, inputData); | |||
|
229 | QFETCH(std::vector<int>, sortPermutation); | |||
|
230 | QFETCH(Container, expectedData); | |||
|
231 | ||||
|
232 | ArrayData<2> arrayData{inputData.first, inputData.second}; | |||
|
233 | auto sortedArrayData = arrayData.sort(sortPermutation); | |||
|
234 | QVERIFY(sortedArrayData != nullptr); | |||
|
235 | ||||
|
236 | verifyArrayData(*sortedArrayData, expectedData); | |||
|
237 | } | |||
|
238 | ||||
|
239 | QTEST_MAIN(TestTwoDimArrayData) | |||
|
240 | #include "TestTwoDimArrayData.moc" |
@@ -0,0 +1,90 | |||||
|
1 | #include "Data/VectorSeries.h" | |||
|
2 | ||||
|
3 | #include "DataSeriesBuilders.h" | |||
|
4 | #include "DataSeriesTestsUtils.h" | |||
|
5 | ||||
|
6 | #include <QObject> | |||
|
7 | #include <QtTest> | |||
|
8 | ||||
|
9 | /** | |||
|
10 | * @brief The TestVectorSeries class defines unit tests on vector series. | |||
|
11 | * | |||
|
12 | * Most of these unit tests use generic tests defined for DataSeries (@sa DataSeriesTestsUtils) | |||
|
13 | */ | |||
|
14 | class TestVectorSeries : public QObject { | |||
|
15 | Q_OBJECT | |||
|
16 | private slots: | |||
|
17 | /// Tests purge of a vector series | |||
|
18 | void testPurge_data(); | |||
|
19 | void testPurge(); | |||
|
20 | ||||
|
21 | /// Tests get values bounds of a vector series | |||
|
22 | void testValuesBounds_data(); | |||
|
23 | void testValuesBounds(); | |||
|
24 | }; | |||
|
25 | ||||
|
26 | void TestVectorSeries::testPurge_data() | |||
|
27 | { | |||
|
28 | testPurge_struct<VectorSeries>(); | |||
|
29 | ||||
|
30 | QTest::newRow("purgeVector") << VectorBuilder{} | |||
|
31 | .setX({1., 2., 3., 4., 5.}) | |||
|
32 | .setXValues({6., 7., 8., 9., 10.}) | |||
|
33 | .setYValues({11., 12., 13., 14., 15.}) | |||
|
34 | .setZValues({16., 17., 18., 19., 20.}) | |||
|
35 | .build() | |||
|
36 | << 2. << 4. << DataContainer{2., 3., 4.} | |||
|
37 | << std::vector<DataContainer>{ | |||
|
38 | {7., 8., 9.}, {12., 13., 14.}, {17., 18., 19.}}; | |||
|
39 | } | |||
|
40 | ||||
|
41 | void TestVectorSeries::testPurge() | |||
|
42 | { | |||
|
43 | testPurge_t<VectorSeries>(); | |||
|
44 | } | |||
|
45 | ||||
|
46 | void TestVectorSeries::testValuesBounds_data() | |||
|
47 | { | |||
|
48 | testValuesBounds_struct<VectorSeries>(); | |||
|
49 | ||||
|
50 | auto nan = std::numeric_limits<double>::quiet_NaN(); | |||
|
51 | ||||
|
52 | QTest::newRow("vectorBounds1") << VectorBuilder{} | |||
|
53 | .setX({1., 2., 3., 4., 5.}) | |||
|
54 | .setXValues({10., 15., 20., 13., 12.}) | |||
|
55 | .setYValues({35., 24., 10., 9., 0.3}) | |||
|
56 | .setZValues({13., 14., 12., 9., 24.}) | |||
|
57 | .build() | |||
|
58 | << 0. << 6. << true << 0.3 << 35.; // min/max in same component | |||
|
59 | QTest::newRow("vectorBounds2") << VectorBuilder{} | |||
|
60 | .setX({1., 2., 3., 4., 5.}) | |||
|
61 | .setXValues({2.3, 15., 20., 13., 12.}) | |||
|
62 | .setYValues({35., 24., 10., 9., 4.}) | |||
|
63 | .setZValues({13., 14., 12., 9., 24.}) | |||
|
64 | .build() | |||
|
65 | << 0. << 6. << true << 2.3 << 35.; // min/max in same entry | |||
|
66 | QTest::newRow("vectorBounds3") << VectorBuilder{} | |||
|
67 | .setX({1., 2., 3., 4., 5.}) | |||
|
68 | .setXValues({2.3, 15., 20., 13., 12.}) | |||
|
69 | .setYValues({35., 24., 10., 9., 4.}) | |||
|
70 | .setZValues({13., 14., 12., 9., 24.}) | |||
|
71 | .build() | |||
|
72 | << 2. << 3. << true << 10. << 24.; | |||
|
73 | ||||
|
74 | // Tests with NaN values: NaN values are not included in min/max search | |||
|
75 | QTest::newRow("vectorBounds4") << VectorBuilder{} | |||
|
76 | .setX({1., 2.}) | |||
|
77 | .setXValues({nan, nan}) | |||
|
78 | .setYValues({nan, nan}) | |||
|
79 | .setZValues({nan, nan}) | |||
|
80 | .build() | |||
|
81 | << 0. << 6. << true << nan << nan; | |||
|
82 | } | |||
|
83 | ||||
|
84 | void TestVectorSeries::testValuesBounds() | |||
|
85 | { | |||
|
86 | testValuesBounds_t<VectorSeries>(); | |||
|
87 | } | |||
|
88 | ||||
|
89 | QTEST_MAIN(TestVectorSeries) | |||
|
90 | #include "TestVectorSeries.moc" |
@@ -0,0 +1,73 | |||||
|
1 | #include "DataSourceItemBuilder.h" | |||
|
2 | ||||
|
3 | DataSourceItemBuilder &DataSourceItemBuilder::root(const QString &name) | |||
|
4 | { | |||
|
5 | m_Root = std::make_shared<DataSourceItem>(DataSourceItemType::NODE, name); | |||
|
6 | m_Items.push(m_Root.get()); | |||
|
7 | return *this; | |||
|
8 | } | |||
|
9 | ||||
|
10 | DataSourceItemBuilder &DataSourceItemBuilder::root(QVariantHash data) | |||
|
11 | { | |||
|
12 | m_Root = std::make_shared<DataSourceItem>(DataSourceItemType::NODE, data); | |||
|
13 | m_Items.push(m_Root.get()); | |||
|
14 | return *this; | |||
|
15 | } | |||
|
16 | ||||
|
17 | DataSourceItemBuilder &DataSourceItemBuilder::node(const QString &name) | |||
|
18 | { | |||
|
19 | return append(DataSourceItemType::NODE, name); | |||
|
20 | } | |||
|
21 | ||||
|
22 | DataSourceItemBuilder &DataSourceItemBuilder::node(QVariantHash data) | |||
|
23 | { | |||
|
24 | return append(DataSourceItemType::NODE, std::move(data)); | |||
|
25 | } | |||
|
26 | ||||
|
27 | DataSourceItemBuilder &DataSourceItemBuilder::product(const QString &name) | |||
|
28 | { | |||
|
29 | return append(DataSourceItemType::PRODUCT, name); | |||
|
30 | } | |||
|
31 | ||||
|
32 | DataSourceItemBuilder &DataSourceItemBuilder::product(QVariantHash data) | |||
|
33 | { | |||
|
34 | return append(DataSourceItemType::PRODUCT, std::move(data)); | |||
|
35 | } | |||
|
36 | ||||
|
37 | DataSourceItemBuilder &DataSourceItemBuilder::component(const QString &name) | |||
|
38 | { | |||
|
39 | return append(DataSourceItemType::COMPONENT, name); | |||
|
40 | } | |||
|
41 | ||||
|
42 | DataSourceItemBuilder &DataSourceItemBuilder::component(QVariantHash data) | |||
|
43 | { | |||
|
44 | return append(DataSourceItemType::COMPONENT, std::move(data)); | |||
|
45 | } | |||
|
46 | ||||
|
47 | DataSourceItemBuilder &DataSourceItemBuilder::end() | |||
|
48 | { | |||
|
49 | m_Items.pop(); | |||
|
50 | return *this; | |||
|
51 | } | |||
|
52 | ||||
|
53 | std::shared_ptr<DataSourceItem> DataSourceItemBuilder::build() | |||
|
54 | { | |||
|
55 | return m_Root; | |||
|
56 | } | |||
|
57 | ||||
|
58 | DataSourceItemBuilder &DataSourceItemBuilder::append(DataSourceItemType type, const QString &name) | |||
|
59 | { | |||
|
60 | append(type, QVariantHash{{DataSourceItem::NAME_DATA_KEY, name}}); | |||
|
61 | return *this; | |||
|
62 | } | |||
|
63 | ||||
|
64 | DataSourceItemBuilder &DataSourceItemBuilder::append(DataSourceItemType type, QVariantHash data) | |||
|
65 | { | |||
|
66 | auto parentItem = m_Items.top(); | |||
|
67 | ||||
|
68 | auto insertIndex = parentItem->childCount(); | |||
|
69 | parentItem->appendChild(std::make_unique<DataSourceItem>(type, std::move(data))); | |||
|
70 | ||||
|
71 | m_Items.push(parentItem->child(insertIndex)); | |||
|
72 | return *this; | |||
|
73 | } |
@@ -0,0 +1,45 | |||||
|
1 | #ifndef SCIQLOP_DATASOURCEITEMBUILDER_H | |||
|
2 | #define SCIQLOP_DATASOURCEITEMBUILDER_H | |||
|
3 | ||||
|
4 | #include <DataSource/DataSourceItem.h> | |||
|
5 | ||||
|
6 | #include <memory> | |||
|
7 | #include <stack> | |||
|
8 | ||||
|
9 | /** | |||
|
10 | * @brief The DataSourceItemBuilder class aims to facilitate the creation of a DataSourceItem for unit tests | |||
|
11 | * @sa DataSourceItem | |||
|
12 | */ | |||
|
13 | class DataSourceItemBuilder { | |||
|
14 | public: | |||
|
15 | /// Inits root item | |||
|
16 | DataSourceItemBuilder & root(const QString &name); | |||
|
17 | DataSourceItemBuilder & root(QVariantHash data); | |||
|
18 | ||||
|
19 | /// Adds node into the current item | |||
|
20 | DataSourceItemBuilder & node(const QString &name); | |||
|
21 | DataSourceItemBuilder & node(QVariantHash data); | |||
|
22 | ||||
|
23 | /// Adds product into the current item | |||
|
24 | DataSourceItemBuilder & product(const QString &name); | |||
|
25 | DataSourceItemBuilder & product(QVariantHash data); | |||
|
26 | ||||
|
27 | /// Adds component into the current item | |||
|
28 | DataSourceItemBuilder & component(const QString &name); | |||
|
29 | DataSourceItemBuilder & component(QVariantHash data); | |||
|
30 | ||||
|
31 | /// Closes the build of the current item | |||
|
32 | DataSourceItemBuilder& end(); | |||
|
33 | ||||
|
34 | /// Creates the DataSourceItem | |||
|
35 | std::shared_ptr<DataSourceItem> build(); | |||
|
36 | ||||
|
37 | private: | |||
|
38 | DataSourceItemBuilder& append(DataSourceItemType type, const QString &name); | |||
|
39 | DataSourceItemBuilder& append(DataSourceItemType type, QVariantHash data); | |||
|
40 | ||||
|
41 | std::shared_ptr<DataSourceItem> m_Root{nullptr}; | |||
|
42 | std::stack<DataSourceItem*> m_Items; | |||
|
43 | }; | |||
|
44 | ||||
|
45 | #endif // SCIQLOP_DATASOURCEITEMBUILDER_H |
@@ -0,0 +1,49 | |||||
|
1 | #include <DataSource/DataSourceController.h> | |||
|
2 | #include <DataSource/DataSourceItem.h> | |||
|
3 | ||||
|
4 | #include <QObject> | |||
|
5 | #include <QtTest> | |||
|
6 | ||||
|
7 | #include <memory> | |||
|
8 | ||||
|
9 | class TestDataSourceController : public QObject { | |||
|
10 | Q_OBJECT | |||
|
11 | private slots: | |||
|
12 | void testRegisterDataSource(); | |||
|
13 | void testSetDataSourceItem(); | |||
|
14 | }; | |||
|
15 | ||||
|
16 | void TestDataSourceController::testRegisterDataSource() | |||
|
17 | { | |||
|
18 | DataSourceController dataSourceController{}; | |||
|
19 | ||||
|
20 | auto uid = dataSourceController.registerDataSource(QStringLiteral("Source1")); | |||
|
21 | QVERIFY(!uid.isNull()); | |||
|
22 | } | |||
|
23 | ||||
|
24 | void TestDataSourceController::testSetDataSourceItem() | |||
|
25 | { | |||
|
26 | DataSourceController dataSourceController{}; | |||
|
27 | ||||
|
28 | // Spy to test controllers' signals | |||
|
29 | QSignalSpy signalSpy{&dataSourceController, SIGNAL(dataSourceItemSet(DataSourceItem *))}; | |||
|
30 | ||||
|
31 | // Create a data source item | |||
|
32 | auto source1Name = QStringLiteral("Source1"); | |||
|
33 | auto source1Item = std::make_unique<DataSourceItem>(DataSourceItemType::PRODUCT, source1Name); | |||
|
34 | ||||
|
35 | // Add data source item to the controller and check that a signal has been emitted after setting | |||
|
36 | // data source item in the controller | |||
|
37 | auto source1Uid = dataSourceController.registerDataSource(source1Name); | |||
|
38 | dataSourceController.setDataSourceItem(source1Uid, std::move(source1Item)); | |||
|
39 | QCOMPARE(signalSpy.count(), 1); | |||
|
40 | ||||
|
41 | // Try to a data source item with an unregistered uid and check that no signal has been emitted | |||
|
42 | auto unregisteredUid = QUuid::createUuid(); | |||
|
43 | dataSourceController.setDataSourceItem( | |||
|
44 | unregisteredUid, std::make_unique<DataSourceItem>(DataSourceItemType::PRODUCT)); | |||
|
45 | QCOMPARE(signalSpy.count(), 1); | |||
|
46 | } | |||
|
47 | ||||
|
48 | QTEST_MAIN(TestDataSourceController) | |||
|
49 | #include "TestDataSourceController.moc" |
@@ -0,0 +1,207 | |||||
|
1 | #include <DataSource/DataSourceItem.h> | |||
|
2 | ||||
|
3 | #include "DataSourceItemBuilder.h" | |||
|
4 | ||||
|
5 | #include <QObject> | |||
|
6 | #include <QtTest> | |||
|
7 | ||||
|
8 | #include <iostream> | |||
|
9 | ||||
|
10 | namespace { | |||
|
11 | ||||
|
12 | void printItem(std::ostream &out, const DataSourceItem &item, int level = 0) | |||
|
13 | { | |||
|
14 | for (auto i = 0; i < level; ++i) { | |||
|
15 | out << " "; | |||
|
16 | } | |||
|
17 | ||||
|
18 | out << item.name().toStdString() << "\n"; | |||
|
19 | ||||
|
20 | for (auto i = 0, count = item.childCount(); i < count; ++i) { | |||
|
21 | printItem(out, *item.child(i), level + 1); | |||
|
22 | } | |||
|
23 | } | |||
|
24 | ||||
|
25 | std::ostream &operator<<(std::ostream &out, const DataSourceItem &item) | |||
|
26 | { | |||
|
27 | printItem(out, item, 0); | |||
|
28 | return out; | |||
|
29 | } | |||
|
30 | ||||
|
31 | } // namespace | |||
|
32 | ||||
|
33 | Q_DECLARE_METATYPE(std::shared_ptr<DataSourceItem>) | |||
|
34 | ||||
|
35 | class TestDataSourceItem : public QObject { | |||
|
36 | Q_OBJECT | |||
|
37 | private slots: | |||
|
38 | void testMerge_data(); | |||
|
39 | void testMerge(); | |||
|
40 | }; | |||
|
41 | ||||
|
42 | void TestDataSourceItem::testMerge_data() | |||
|
43 | { | |||
|
44 | QTest::addColumn<std::shared_ptr<DataSourceItem> >("source"); | |||
|
45 | QTest::addColumn<std::shared_ptr<DataSourceItem> >("dest"); | |||
|
46 | QTest::addColumn<std::shared_ptr<DataSourceItem> >("expectedResult"); | |||
|
47 | ||||
|
48 | QTest::newRow("merge (basic case)") << DataSourceItemBuilder{} | |||
|
49 | .root("A2") | |||
|
50 | .node("- B2") | |||
|
51 | .product("-- P2") | |||
|
52 | .end() // P2 | |||
|
53 | .end() // B2 | |||
|
54 | .end() // A2 | |||
|
55 | .build() | |||
|
56 | << DataSourceItemBuilder{} | |||
|
57 | .root("A1") | |||
|
58 | .node("- B1") | |||
|
59 | .product("-- P1") | |||
|
60 | .end() // P1 | |||
|
61 | .end() // B1 | |||
|
62 | .end() // A1 | |||
|
63 | .build() | |||
|
64 | << DataSourceItemBuilder{} | |||
|
65 | .root("A1") | |||
|
66 | .node("- B1") | |||
|
67 | .product("-- P1") | |||
|
68 | .end() // P1 | |||
|
69 | .end() // B1 | |||
|
70 | .node("- B2") | |||
|
71 | .product("-- P2") | |||
|
72 | .end() // P2 | |||
|
73 | .end() // B2 | |||
|
74 | .end() // A1 | |||
|
75 | .build(); | |||
|
76 | ||||
|
77 | QTest::newRow("merge (some of the source and destination trees are identical)") | |||
|
78 | << DataSourceItemBuilder{} | |||
|
79 | .root("A2") | |||
|
80 | .node("- B1") | |||
|
81 | .node("-- C1") | |||
|
82 | .product("--- P2") | |||
|
83 | .end() // P2 | |||
|
84 | .end() // C1 | |||
|
85 | .node("-- C2") | |||
|
86 | .end() // C2 | |||
|
87 | .end() // B1 | |||
|
88 | .end() // A2 | |||
|
89 | .build() | |||
|
90 | << DataSourceItemBuilder{} | |||
|
91 | .root("A1") | |||
|
92 | .node("- B1") | |||
|
93 | .node("-- C1") | |||
|
94 | .product("--- P1") | |||
|
95 | .end() // P1 | |||
|
96 | .end() // C1 | |||
|
97 | .end() // B1 | |||
|
98 | .end() // A1 | |||
|
99 | .build() | |||
|
100 | << DataSourceItemBuilder{} | |||
|
101 | .root("A1") | |||
|
102 | .node("- B1") | |||
|
103 | .node("-- C1") | |||
|
104 | .product("--- P1") | |||
|
105 | .end() // P1 | |||
|
106 | .product("--- P2") | |||
|
107 | .end() // P2 | |||
|
108 | .end() // C1 | |||
|
109 | .node("-- C2") | |||
|
110 | .end() // C2 | |||
|
111 | .end() // B1 | |||
|
112 | .end() // A1 | |||
|
113 | .build(); | |||
|
114 | ||||
|
115 | QTest::newRow("merge (products with the same name and tree are kept)") | |||
|
116 | << DataSourceItemBuilder{} | |||
|
117 | .root("A2") | |||
|
118 | .node("- B1") | |||
|
119 | .node("-- C1") | |||
|
120 | .product({{"name", "--- P1"}, {"from", "source"}}) | |||
|
121 | .end() // P1 | |||
|
122 | .end() // C1 | |||
|
123 | .end() // B1 | |||
|
124 | .end() // A2 | |||
|
125 | .build() | |||
|
126 | << DataSourceItemBuilder{} | |||
|
127 | .root("A1") | |||
|
128 | .node("- B1") | |||
|
129 | .node("-- C1") | |||
|
130 | .product({{"name", "--- P1"}, {"from", "dest"}}) | |||
|
131 | .end() // P1 | |||
|
132 | .end() // C1 | |||
|
133 | .end() // B1 | |||
|
134 | .end() // A1 | |||
|
135 | .build() | |||
|
136 | << DataSourceItemBuilder{} | |||
|
137 | .root("A1") | |||
|
138 | .node("- B1") | |||
|
139 | .node("-- C1") | |||
|
140 | .product({{"name", "--- P1"}, {"from", "dest"}}) | |||
|
141 | .end() // P1 (dest) | |||
|
142 | .product({{"name", "--- P1"}, {"from", "source"}}) | |||
|
143 | .end() // P1 (source) | |||
|
144 | .end() // C1 | |||
|
145 | .end() // B1 | |||
|
146 | .end() // A1 | |||
|
147 | .build(); | |||
|
148 | ||||
|
149 | QTest::newRow("merge (for same nodes, metadata of dest node are kept)") | |||
|
150 | << DataSourceItemBuilder{} | |||
|
151 | .root("A2") | |||
|
152 | .node("- B1") | |||
|
153 | .node({{"name", "-- C1"}, {"from", "source"}}) | |||
|
154 | .product("--- P2") | |||
|
155 | .end() // P1 | |||
|
156 | .end() // C1 | |||
|
157 | .end() // B1 | |||
|
158 | .end() // A2 | |||
|
159 | .build() | |||
|
160 | << DataSourceItemBuilder{} | |||
|
161 | .root("A1") | |||
|
162 | .node("- B1") | |||
|
163 | .node({{"name", "-- C1"}, {"from", "dest"}}) | |||
|
164 | .product("--- P1") | |||
|
165 | .end() // P1 | |||
|
166 | .end() // C1 | |||
|
167 | .end() // B1 | |||
|
168 | .end() // A1 | |||
|
169 | .build() | |||
|
170 | << DataSourceItemBuilder{} | |||
|
171 | .root("A1") | |||
|
172 | .node("- B1") | |||
|
173 | .node({{"name", "-- C1"}, {"from", "dest"}}) | |||
|
174 | .product("--- P1") | |||
|
175 | .end() // P1 | |||
|
176 | .product("--- P2") | |||
|
177 | .end() // P2 | |||
|
178 | .end() // C1 (dest) | |||
|
179 | .end() // B1 | |||
|
180 | .end() // A1 | |||
|
181 | .build(); | |||
|
182 | } | |||
|
183 | ||||
|
184 | void TestDataSourceItem::testMerge() | |||
|
185 | { | |||
|
186 | QFETCH(std::shared_ptr<DataSourceItem>, source); | |||
|
187 | QFETCH(std::shared_ptr<DataSourceItem>, dest); | |||
|
188 | QFETCH(std::shared_ptr<DataSourceItem>, expectedResult); | |||
|
189 | ||||
|
190 | // Uncomment to print trees | |||
|
191 | // std::cout << "source: \n" << *source << "\n"; | |||
|
192 | // std::cout << "dest: \n" << *dest << "\n"; | |||
|
193 | ||||
|
194 | // Merges source in dest (not taking source root) | |||
|
195 | for (auto i = 0, count = source->childCount(); i < count; ++i) { | |||
|
196 | dest->merge(*source->child(i)); | |||
|
197 | } | |||
|
198 | ||||
|
199 | // Uncomment to print trees | |||
|
200 | // std::cout << "dest after merge: \n" << *dest << "\n"; | |||
|
201 | ||||
|
202 | // Checks merge result | |||
|
203 | QVERIFY(*dest == *expectedResult); | |||
|
204 | } | |||
|
205 | ||||
|
206 | QTEST_MAIN(TestDataSourceItem) | |||
|
207 | #include "TestDataSourceItem.moc" |
@@ -0,0 +1,82 | |||||
|
1 | #include <Network/Downloader.h> | |||
|
2 | #include <QtTest> | |||
|
3 | #include <QObject> | |||
|
4 | ||||
|
5 | ||||
|
6 | class TestDownloader : public QObject | |||
|
7 | ||||
|
8 | { | |||
|
9 | Q_OBJECT | |||
|
10 | public: | |||
|
11 | explicit TestDownloader(QObject *parent = nullptr) : QObject(parent){} | |||
|
12 | signals: | |||
|
13 | ||||
|
14 | private slots: | |||
|
15 | void initTestCase(){} | |||
|
16 | void cleanupTestCase(){} | |||
|
17 | ||||
|
18 | void simpleGet() | |||
|
19 | { | |||
|
20 | auto resp = Downloader::get("https://httpbin.org/user-agent"); | |||
|
21 | QCOMPARE(resp.status_code(), 200); | |||
|
22 | QCOMPARE(resp.data(), QString("{\n \"user-agent\": \"SciQLop 1.0\"\n}\n")); | |||
|
23 | } | |||
|
24 | ||||
|
25 | void simpleAsyncGet() | |||
|
26 | { | |||
|
27 | bool done = false; | |||
|
28 | int status = -1; | |||
|
29 | QByteArray data; | |||
|
30 | auto callback = [&done, &status, &data](QUuid uuid,Response resp) | |||
|
31 | { | |||
|
32 | status = resp.status_code(); | |||
|
33 | done = true; | |||
|
34 | data = resp.data(); | |||
|
35 | }; | |||
|
36 | auto uuid = Downloader::getAsync("http://ovh.net/files/1Mio.dat", callback); | |||
|
37 | QCOMPARE(Downloader::downloadFinished(uuid), false); | |||
|
38 | while (!done) | |||
|
39 | { | |||
|
40 | QCoreApplication::processEvents(); | |||
|
41 | } | |||
|
42 | QCOMPARE(Downloader::downloadFinished(uuid), true); | |||
|
43 | QCOMPARE(status, 200); | |||
|
44 | QCOMPARE(data[0],'\xBA'); | |||
|
45 | QCOMPARE(data[data.length()-1],'\x20'); | |||
|
46 | } | |||
|
47 | ||||
|
48 | void wrongUrl() | |||
|
49 | { | |||
|
50 | auto resp = Downloader::get("https://lpp.polytechniqe2.fr"); | |||
|
51 | QCOMPARE(resp.status_code(), 0); | |||
|
52 | resp = Downloader::get("https://hephaistos.lpp.polytechnique.fr/will_never_exist"); | |||
|
53 | QCOMPARE(resp.status_code(), 404); | |||
|
54 | ||||
|
55 | } | |||
|
56 | ||||
|
57 | void authGet_data() | |||
|
58 | { | |||
|
59 | QTest::addColumn<QString>("url"); | |||
|
60 | QTest::addColumn<int>("code"); | |||
|
61 | ||||
|
62 | QTest::newRow("basic-auth") << "https://httpbin.org/basic-auth/user/passwd" << 200; | |||
|
63 | QTest::newRow("digest-auth") << "https://httpbin.org/digest-auth/auth/user/passwd" << 200; | |||
|
64 | QTest::newRow("hidden-basic-auth") << "https://httpbin.org/hidden-basic-auth/user/passwd" << 404; | |||
|
65 | } | |||
|
66 | ||||
|
67 | void authGet() | |||
|
68 | { | |||
|
69 | QFETCH(QString, url); | |||
|
70 | QFETCH(int, code); | |||
|
71 | auto resp = Downloader::get(url, "user", "passwd"); | |||
|
72 | QCOMPARE(resp.status_code(), code); | |||
|
73 | } | |||
|
74 | ||||
|
75 | private: | |||
|
76 | ||||
|
77 | }; | |||
|
78 | ||||
|
79 | ||||
|
80 | QTEST_MAIN(TestDownloader) | |||
|
81 | ||||
|
82 | #include "TestDownloader.moc" |
@@ -0,0 +1,409 | |||||
|
1 | #include <Variable/Variable.h> | |||
|
2 | ||||
|
3 | #include <Data/ScalarSeries.h> | |||
|
4 | ||||
|
5 | #include <QObject> | |||
|
6 | #include <QtTest> | |||
|
7 | ||||
|
8 | #include <memory> | |||
|
9 | ||||
|
10 | namespace { | |||
|
11 | ||||
|
12 | /// Generates a date in double | |||
|
13 | auto date = [](int year, int month, int day, int hours, int minutes, int seconds) { | |||
|
14 | return DateUtils::secondsSinceEpoch( | |||
|
15 | QDateTime{{year, month, day}, {hours, minutes, seconds}, Qt::UTC}); | |||
|
16 | }; | |||
|
17 | ||||
|
18 | /// Generates a series of test data for a range | |||
|
19 | std::shared_ptr<ScalarSeries> dataSeries(const DateTimeRange &range) | |||
|
20 | { | |||
|
21 | auto xAxisData = std::vector<double>{}; | |||
|
22 | auto valuesData = std::vector<double>{}; | |||
|
23 | ||||
|
24 | auto value = 0; | |||
|
25 | for (auto x = range.m_TStart; x <= range.m_TEnd; ++x, ++value) { | |||
|
26 | xAxisData.push_back(x); | |||
|
27 | valuesData.push_back(value); | |||
|
28 | } | |||
|
29 | ||||
|
30 | return std::make_shared<ScalarSeries>(std::move(xAxisData), std::move(valuesData), Unit{}, | |||
|
31 | Unit{}); | |||
|
32 | } | |||
|
33 | ||||
|
34 | } // namespace | |||
|
35 | ||||
|
36 | Q_DECLARE_METATYPE(std::shared_ptr<ScalarSeries>) | |||
|
37 | ||||
|
38 | class TestVariable : public QObject { | |||
|
39 | Q_OBJECT | |||
|
40 | ||||
|
41 | private slots: | |||
|
42 | void testClone_data(); | |||
|
43 | void testClone(); | |||
|
44 | ||||
|
45 | void testNotInCacheRangeList(); | |||
|
46 | void testInCacheRangeList(); | |||
|
47 | ||||
|
48 | void testNbPoints_data(); | |||
|
49 | void testNbPoints(); | |||
|
50 | ||||
|
51 | void testRealRange_data(); | |||
|
52 | void testRealRange(); | |||
|
53 | }; | |||
|
54 | ||||
|
55 | void TestVariable::testClone_data() | |||
|
56 | { | |||
|
57 | // ////////////// // | |||
|
58 | // Test structure // | |||
|
59 | // ////////////// // | |||
|
60 | ||||
|
61 | QTest::addColumn<QString>("name"); | |||
|
62 | QTest::addColumn<QVariantHash>("metadata"); | |||
|
63 | QTest::addColumn<DateTimeRange>("range"); | |||
|
64 | QTest::addColumn<DateTimeRange>("cacheRange"); | |||
|
65 | QTest::addColumn<std::shared_ptr<ScalarSeries> >("dataSeries"); | |||
|
66 | ||||
|
67 | // ////////// // | |||
|
68 | // Test cases // | |||
|
69 | // ////////// // | |||
|
70 | ||||
|
71 | auto cacheRange = DateTimeRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 13, 0, 0)}; | |||
|
72 | QTest::newRow("clone1") << QStringLiteral("var1") | |||
|
73 | << QVariantHash{{"data1", 1}, {"data2", "abc"}} | |||
|
74 | << DateTimeRange{date(2017, 1, 1, 12, 30, 0), (date(2017, 1, 1, 12, 45, 0))} | |||
|
75 | << cacheRange << dataSeries(cacheRange); | |||
|
76 | } | |||
|
77 | ||||
|
78 | void TestVariable::testClone() | |||
|
79 | { | |||
|
80 | // Creates variable | |||
|
81 | QFETCH(QString, name); | |||
|
82 | QFETCH(QVariantHash, metadata); | |||
|
83 | QFETCH(DateTimeRange, range); | |||
|
84 | QFETCH(DateTimeRange, cacheRange); | |||
|
85 | QFETCH(std::shared_ptr<ScalarSeries>, dataSeries); | |||
|
86 | ||||
|
87 | Variable variable{name, metadata}; | |||
|
88 | variable.setRange(range); | |||
|
89 | variable.setCacheRange(cacheRange); | |||
|
90 | variable.mergeDataSeries(dataSeries); | |||
|
91 | ||||
|
92 | // Clones variable | |||
|
93 | auto clone = variable.clone(); | |||
|
94 | ||||
|
95 | // Checks cloned variable's state | |||
|
96 | QCOMPARE(clone->name(), name); | |||
|
97 | QCOMPARE(clone->metadata(), metadata); | |||
|
98 | QCOMPARE(clone->range(), range); | |||
|
99 | QCOMPARE(clone->cacheRange(), cacheRange); | |||
|
100 | ||||
|
101 | // Compares data series | |||
|
102 | if (dataSeries != nullptr) { | |||
|
103 | QVERIFY(clone->dataSeries() != nullptr); | |||
|
104 | QVERIFY(std::equal(dataSeries->cbegin(), dataSeries->cend(), clone->dataSeries()->cbegin(), | |||
|
105 | clone->dataSeries()->cend(), [](const auto &it1, const auto &it2) { | |||
|
106 | return it1.x() == it2.x() && it1.value() == it2.value(); | |||
|
107 | })); | |||
|
108 | } | |||
|
109 | else { | |||
|
110 | QVERIFY(clone->dataSeries() == nullptr); | |||
|
111 | } | |||
|
112 | } | |||
|
113 | ||||
|
114 | void TestVariable::testNotInCacheRangeList() | |||
|
115 | { | |||
|
116 | auto varRS = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 20, 0}}; | |||
|
117 | auto varRE = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 40, 0}}; | |||
|
118 | ||||
|
119 | auto sqpR = DateTimeRange{DateUtils::secondsSinceEpoch(varRS), DateUtils::secondsSinceEpoch(varRE)}; | |||
|
120 | ||||
|
121 | auto varCRS = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 0, 0}}; | |||
|
122 | auto varCRE = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}}; | |||
|
123 | ||||
|
124 | auto sqpCR | |||
|
125 | = DateTimeRange{DateUtils::secondsSinceEpoch(varCRS), DateUtils::secondsSinceEpoch(varCRE)}; | |||
|
126 | ||||
|
127 | Variable var{"Var test"}; | |||
|
128 | var.setRange(sqpR); | |||
|
129 | var.setCacheRange(sqpCR); | |||
|
130 | ||||
|
131 | // 1: [ts,te] < varTS | |||
|
132 | auto ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}}; | |||
|
133 | auto te = QDateTime{QDate{2017, 01, 01}, QTime{2, 1, 0, 0}}; | |||
|
134 | auto sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
135 | ||||
|
136 | auto notInCach = var.provideNotInCacheRangeList(sqp); | |||
|
137 | ||||
|
138 | QCOMPARE(notInCach.size(), 1); | |||
|
139 | ||||
|
140 | auto notInCachRange = notInCach.first(); | |||
|
141 | ||||
|
142 | QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(ts)); | |||
|
143 | QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(te)); | |||
|
144 | ||||
|
145 | // 2: ts < varTS < te < varTE | |||
|
146 | ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}}; | |||
|
147 | te = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}}; | |||
|
148 | sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
149 | notInCach = var.provideNotInCacheRangeList(sqp); | |||
|
150 | QCOMPARE(notInCach.size(), 1); | |||
|
151 | notInCachRange = notInCach.first(); | |||
|
152 | QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(ts)); | |||
|
153 | QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(varCRS)); | |||
|
154 | ||||
|
155 | // 3: varTS < ts < te < varTE | |||
|
156 | ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 20, 0}}; | |||
|
157 | te = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}}; | |||
|
158 | sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
159 | notInCach = var.provideNotInCacheRangeList(sqp); | |||
|
160 | QCOMPARE(notInCach.size(), 0); | |||
|
161 | ||||
|
162 | ||||
|
163 | // 4: varTS < ts < varTE < te | |||
|
164 | ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 20, 0}}; | |||
|
165 | te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}}; | |||
|
166 | sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
167 | notInCach = var.provideNotInCacheRangeList(sqp); | |||
|
168 | QCOMPARE(notInCach.size(), 1); | |||
|
169 | notInCachRange = notInCach.first(); | |||
|
170 | QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(varCRE)); | |||
|
171 | QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(te)); | |||
|
172 | ||||
|
173 | // 5: varTS < varTE < ts < te | |||
|
174 | ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 20, 0}}; | |||
|
175 | te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}}; | |||
|
176 | sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
177 | notInCach = var.provideNotInCacheRangeList(sqp); | |||
|
178 | QCOMPARE(notInCach.size(), 1); | |||
|
179 | notInCachRange = notInCach.first(); | |||
|
180 | QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(ts)); | |||
|
181 | QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(te)); | |||
|
182 | ||||
|
183 | // 6: ts <varTS < varTE < te | |||
|
184 | ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 1, 0, 0}}; | |||
|
185 | te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}}; | |||
|
186 | sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
187 | notInCach = var.provideNotInCacheRangeList(sqp); | |||
|
188 | QCOMPARE(notInCach.size(), 2); | |||
|
189 | notInCachRange = notInCach.first(); | |||
|
190 | QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(ts)); | |||
|
191 | QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(varCRS)); | |||
|
192 | notInCachRange = notInCach[1]; | |||
|
193 | QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(varCRE)); | |||
|
194 | QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(te)); | |||
|
195 | } | |||
|
196 | ||||
|
197 | ||||
|
198 | void TestVariable::testInCacheRangeList() | |||
|
199 | { | |||
|
200 | auto varRS = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 20, 0}}; | |||
|
201 | auto varRE = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 40, 0}}; | |||
|
202 | ||||
|
203 | auto sqpR = DateTimeRange{DateUtils::secondsSinceEpoch(varRS), DateUtils::secondsSinceEpoch(varRE)}; | |||
|
204 | ||||
|
205 | auto varCRS = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 0, 0}}; | |||
|
206 | auto varCRE = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}}; | |||
|
207 | auto sqpCR | |||
|
208 | = DateTimeRange{DateUtils::secondsSinceEpoch(varCRS), DateUtils::secondsSinceEpoch(varCRE)}; | |||
|
209 | ||||
|
210 | Variable var{"Var test"}; | |||
|
211 | var.setRange(sqpR); | |||
|
212 | var.setCacheRange(sqpCR); | |||
|
213 | ||||
|
214 | // 1: [ts,te] < varTS | |||
|
215 | auto ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}}; | |||
|
216 | auto te = QDateTime{QDate{2017, 01, 01}, QTime{2, 1, 0, 0}}; | |||
|
217 | auto sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
218 | ||||
|
219 | auto notInCach = var.provideInCacheRangeList(sqp); | |||
|
220 | ||||
|
221 | QCOMPARE(notInCach.size(), 0); | |||
|
222 | ||||
|
223 | // 2: ts < varTS < te < varTE | |||
|
224 | ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}}; | |||
|
225 | te = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}}; | |||
|
226 | sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
227 | notInCach = var.provideInCacheRangeList(sqp); | |||
|
228 | QCOMPARE(notInCach.size(), 1); | |||
|
229 | auto notInCachRange = notInCach.first(); | |||
|
230 | QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(varCRS)); | |||
|
231 | QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(te)); | |||
|
232 | ||||
|
233 | // 3: varTS < ts < te < varTE | |||
|
234 | ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 20, 0}}; | |||
|
235 | te = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}}; | |||
|
236 | sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
237 | notInCach = var.provideInCacheRangeList(sqp); | |||
|
238 | QCOMPARE(notInCach.size(), 1); | |||
|
239 | notInCachRange = notInCach.first(); | |||
|
240 | QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(ts)); | |||
|
241 | QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(te)); | |||
|
242 | ||||
|
243 | // 4: varTS < ts < varTE < te | |||
|
244 | ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 20, 0}}; | |||
|
245 | te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}}; | |||
|
246 | sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
247 | notInCach = var.provideInCacheRangeList(sqp); | |||
|
248 | QCOMPARE(notInCach.size(), 1); | |||
|
249 | notInCachRange = notInCach.first(); | |||
|
250 | QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(ts)); | |||
|
251 | QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(varCRE)); | |||
|
252 | ||||
|
253 | // 5: varTS < varTE < ts < te | |||
|
254 | ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 20, 0}}; | |||
|
255 | te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}}; | |||
|
256 | sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
257 | notInCach = var.provideInCacheRangeList(sqp); | |||
|
258 | QCOMPARE(notInCach.size(), 0); | |||
|
259 | ||||
|
260 | // 6: ts <varTS < varTE < te | |||
|
261 | ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 1, 0, 0}}; | |||
|
262 | te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}}; | |||
|
263 | sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
264 | notInCach = var.provideInCacheRangeList(sqp); | |||
|
265 | QCOMPARE(notInCach.size(), 1); | |||
|
266 | notInCachRange = notInCach.first(); | |||
|
267 | QCOMPARE(notInCachRange.m_TStart, DateUtils::secondsSinceEpoch(varCRS)); | |||
|
268 | QCOMPARE(notInCachRange.m_TEnd, DateUtils::secondsSinceEpoch(varCRE)); | |||
|
269 | } | |||
|
270 | ||||
|
271 | namespace { | |||
|
272 | ||||
|
273 | /// Struct used to represent an operation for @sa TestVariable::testNbPoints() | |||
|
274 | struct NbPointsOperation { | |||
|
275 | DateTimeRange m_CacheRange; /// Range to set for the variable | |||
|
276 | std::shared_ptr<ScalarSeries> m_DataSeries; /// Series to merge in the variable | |||
|
277 | int m_ExpectedNbPoints; /// Number of points in the variable expected after operation | |||
|
278 | }; | |||
|
279 | ||||
|
280 | using NbPointsOperations = std::vector<NbPointsOperation>; | |||
|
281 | ||||
|
282 | } // namespace | |||
|
283 | ||||
|
284 | Q_DECLARE_METATYPE(NbPointsOperations) | |||
|
285 | ||||
|
286 | void TestVariable::testNbPoints_data() | |||
|
287 | { | |||
|
288 | // ////////////// // | |||
|
289 | // Test structure // | |||
|
290 | // ////////////// // | |||
|
291 | ||||
|
292 | QTest::addColumn<NbPointsOperations>("operations"); | |||
|
293 | ||||
|
294 | // ////////// // | |||
|
295 | // Test cases // | |||
|
296 | // ////////// // | |||
|
297 | NbPointsOperations operations{}; | |||
|
298 | ||||
|
299 | // Sets cache range (expected nb points = values data) | |||
|
300 | auto cacheRange = DateTimeRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 12, 0, 9)}; | |||
|
301 | operations.push_back({cacheRange, dataSeries(cacheRange), 10}); | |||
|
302 | ||||
|
303 | // Doubles cache but don't add data series (expected nb points don't change) | |||
|
304 | cacheRange = DateTimeRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 12, 0, 19)}; | |||
|
305 | operations.push_back({cacheRange, dataSeries(INVALID_RANGE), 10}); | |||
|
306 | ||||
|
307 | // Doubles cache and data series (expected nb points change) | |||
|
308 | cacheRange = DateTimeRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 12, 0, 19)}; | |||
|
309 | operations.push_back({cacheRange, dataSeries(cacheRange), 20}); | |||
|
310 | ||||
|
311 | // Decreases cache (expected nb points decreases as the series is purged) | |||
|
312 | cacheRange = DateTimeRange{date(2017, 1, 1, 12, 0, 5), date(2017, 1, 1, 12, 0, 9)}; | |||
|
313 | operations.push_back({cacheRange, dataSeries(INVALID_RANGE), 5}); | |||
|
314 | ||||
|
315 | QTest::newRow("nbPoints1") << operations; | |||
|
316 | } | |||
|
317 | ||||
|
318 | void TestVariable::testNbPoints() | |||
|
319 | { | |||
|
320 | // Creates variable | |||
|
321 | Variable variable{"var"}; | |||
|
322 | QCOMPARE(variable.nbPoints(), 0); | |||
|
323 | ||||
|
324 | QFETCH(NbPointsOperations, operations); | |||
|
325 | for (const auto &operation : operations) { | |||
|
326 | // Sets cache range and merge data series | |||
|
327 | variable.setCacheRange(operation.m_CacheRange); | |||
|
328 | if (operation.m_DataSeries != nullptr) { | |||
|
329 | variable.mergeDataSeries(operation.m_DataSeries); | |||
|
330 | } | |||
|
331 | ||||
|
332 | // Checks nb points | |||
|
333 | QCOMPARE(variable.nbPoints(), operation.m_ExpectedNbPoints); | |||
|
334 | } | |||
|
335 | } | |||
|
336 | ||||
|
337 | namespace { | |||
|
338 | ||||
|
339 | /// Struct used to represent a range operation on a variable | |||
|
340 | /// @sa TestVariable::testRealRange() | |||
|
341 | struct RangeOperation { | |||
|
342 | DateTimeRange m_CacheRange; /// Range to set for the variable | |||
|
343 | std::shared_ptr<ScalarSeries> m_DataSeries; /// Series to merge in the variable | |||
|
344 | DateTimeRange m_ExpectedRealRange; /// Real Range expected after operation on the variable | |||
|
345 | }; | |||
|
346 | ||||
|
347 | using RangeOperations = std::vector<RangeOperation>; | |||
|
348 | ||||
|
349 | } // namespace | |||
|
350 | ||||
|
351 | Q_DECLARE_METATYPE(RangeOperations) | |||
|
352 | ||||
|
353 | void TestVariable::testRealRange_data() | |||
|
354 | { | |||
|
355 | // ////////////// // | |||
|
356 | // Test structure // | |||
|
357 | // ////////////// // | |||
|
358 | ||||
|
359 | QTest::addColumn<RangeOperations>("operations"); | |||
|
360 | ||||
|
361 | // ////////// // | |||
|
362 | // Test cases // | |||
|
363 | // ////////// // | |||
|
364 | RangeOperations operations{}; | |||
|
365 | ||||
|
366 | // Inits cache range and data series (expected real range = cache range) | |||
|
367 | auto cacheRange = DateTimeRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 13, 0, 0)}; | |||
|
368 | operations.push_back({cacheRange, dataSeries(cacheRange), cacheRange}); | |||
|
369 | ||||
|
370 | // Changes cache range and updates data series (expected real range = cache range) | |||
|
371 | cacheRange = DateTimeRange{date(2017, 1, 1, 14, 0, 0), date(2017, 1, 1, 15, 0, 0)}; | |||
|
372 | operations.push_back({cacheRange, dataSeries(cacheRange), cacheRange}); | |||
|
373 | ||||
|
374 | // Changes cache range and update data series but with a lower range (expected real range = | |||
|
375 | // data series range) | |||
|
376 | cacheRange = DateTimeRange{date(2017, 1, 1, 12, 0, 0), date(2017, 1, 1, 16, 0, 0)}; | |||
|
377 | auto dataSeriesRange = DateTimeRange{date(2017, 1, 1, 14, 0, 0), date(2017, 1, 1, 15, 0, 0)}; | |||
|
378 | operations.push_back({cacheRange, dataSeries(dataSeriesRange), dataSeriesRange}); | |||
|
379 | ||||
|
380 | // Changes cache range but DON'T update data series (expected real range = cache range | |||
|
381 | // before operation) | |||
|
382 | cacheRange = DateTimeRange{date(2017, 1, 1, 10, 0, 0), date(2017, 1, 1, 17, 0, 0)}; | |||
|
383 | operations.push_back({cacheRange, nullptr, dataSeriesRange}); | |||
|
384 | ||||
|
385 | QTest::newRow("realRange1") << operations; | |||
|
386 | } | |||
|
387 | ||||
|
388 | void TestVariable::testRealRange() | |||
|
389 | { | |||
|
390 | // Creates variable (real range is invalid) | |||
|
391 | Variable variable{"var"}; | |||
|
392 | QCOMPARE(variable.realRange(), INVALID_RANGE); | |||
|
393 | ||||
|
394 | QFETCH(RangeOperations, operations); | |||
|
395 | for (const auto &operation : operations) { | |||
|
396 | // Sets cache range and merge data series | |||
|
397 | variable.setCacheRange(operation.m_CacheRange); | |||
|
398 | if (operation.m_DataSeries != nullptr) { | |||
|
399 | variable.mergeDataSeries(operation.m_DataSeries); | |||
|
400 | } | |||
|
401 | ||||
|
402 | // Checks real range | |||
|
403 | QCOMPARE(variable.realRange(), operation.m_ExpectedRealRange); | |||
|
404 | } | |||
|
405 | } | |||
|
406 | ||||
|
407 | ||||
|
408 | QTEST_MAIN(TestVariable) | |||
|
409 | #include "TestVariable.moc" |
@@ -0,0 +1,333 | |||||
|
1 | #include <Variable/Variable.h> | |||
|
2 | #include <Variable/VariableCacheController.h> | |||
|
3 | ||||
|
4 | #include <QObject> | |||
|
5 | #include <QtTest> | |||
|
6 | ||||
|
7 | #include <memory> | |||
|
8 | ||||
|
9 | class TestVariableCacheController : public QObject { | |||
|
10 | Q_OBJECT | |||
|
11 | ||||
|
12 | private slots: | |||
|
13 | void testProvideNotInCacheDateTimeList(); | |||
|
14 | ||||
|
15 | void testAddDateTime(); | |||
|
16 | }; | |||
|
17 | ||||
|
18 | ||||
|
19 | void TestVariableCacheController::testProvideNotInCacheDateTimeList() | |||
|
20 | { | |||
|
21 | VariableCacheController variableCacheController{}; | |||
|
22 | ||||
|
23 | auto ts0 = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 0, 0}}; | |||
|
24 | auto te0 = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}}; | |||
|
25 | auto sqp0 = DateTimeRange{DateUtils::secondsSinceEpoch(ts0), DateUtils::secondsSinceEpoch(te0)}; | |||
|
26 | ||||
|
27 | auto ts1 = QDateTime{QDate{2017, 01, 01}, QTime{2, 6, 0, 0}}; | |||
|
28 | auto te1 = QDateTime{QDate{2017, 01, 01}, QTime{2, 8, 0, 0}}; | |||
|
29 | auto sqp1 = DateTimeRange{DateUtils::secondsSinceEpoch(ts1), DateUtils::secondsSinceEpoch(te1)}; | |||
|
30 | ||||
|
31 | auto ts2 = QDateTime{QDate{2017, 01, 01}, QTime{2, 18, 0, 0}}; | |||
|
32 | auto te2 = QDateTime{QDate{2017, 01, 01}, QTime{2, 20, 0, 0}}; | |||
|
33 | auto sqp2 = DateTimeRange{DateUtils::secondsSinceEpoch(ts2), DateUtils::secondsSinceEpoch(te2)}; | |||
|
34 | ||||
|
35 | auto var0 = std::make_shared<Variable>(""); | |||
|
36 | var0->setRange(sqp0); | |||
|
37 | ||||
|
38 | variableCacheController.addDateTime(var0, sqp0); | |||
|
39 | variableCacheController.addDateTime(var0, sqp1); | |||
|
40 | variableCacheController.addDateTime(var0, sqp2); | |||
|
41 | ||||
|
42 | // first case [ts,te] < ts0 | |||
|
43 | auto ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}}; | |||
|
44 | auto te = QDateTime{QDate{2017, 01, 01}, QTime{2, 1, 0, 0}}; | |||
|
45 | auto sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
46 | ||||
|
47 | ||||
|
48 | auto notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); | |||
|
49 | ||||
|
50 | QCOMPARE(notInCach.size(), 1); | |||
|
51 | auto notInCacheSqp = notInCach.first(); | |||
|
52 | QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(ts)); | |||
|
53 | QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(te)); | |||
|
54 | ||||
|
55 | ||||
|
56 | // second case ts < ts0 && ts0 < te <= te0 | |||
|
57 | ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}}; | |||
|
58 | te = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}}; | |||
|
59 | sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
60 | ||||
|
61 | ||||
|
62 | notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); | |||
|
63 | ||||
|
64 | QCOMPARE(notInCach.size(), 1); | |||
|
65 | notInCacheSqp = notInCach.first(); | |||
|
66 | QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(ts)); | |||
|
67 | QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(ts0)); | |||
|
68 | ||||
|
69 | // 3th case ts < ts0 && te0 < te <= ts1 | |||
|
70 | ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}}; | |||
|
71 | te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}}; | |||
|
72 | sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
73 | ||||
|
74 | ||||
|
75 | notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); | |||
|
76 | ||||
|
77 | QCOMPARE(notInCach.size(), 2); | |||
|
78 | notInCacheSqp = notInCach.first(); | |||
|
79 | QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(ts)); | |||
|
80 | QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(ts0)); | |||
|
81 | ||||
|
82 | notInCacheSqp = notInCach.at(1); | |||
|
83 | QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(te0)); | |||
|
84 | QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(te)); | |||
|
85 | ||||
|
86 | // 4th case ts < ts0 && ts1 < te <= te1 | |||
|
87 | ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}}; | |||
|
88 | te = QDateTime{QDate{2017, 01, 01}, QTime{2, 7, 0, 0}}; | |||
|
89 | sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
90 | ||||
|
91 | ||||
|
92 | notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); | |||
|
93 | ||||
|
94 | QCOMPARE(notInCach.size(), 2); | |||
|
95 | notInCacheSqp = notInCach.first(); | |||
|
96 | QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(ts)); | |||
|
97 | QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(ts0)); | |||
|
98 | ||||
|
99 | notInCacheSqp = notInCach.at(1); | |||
|
100 | QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(te0)); | |||
|
101 | QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(ts1)); | |||
|
102 | ||||
|
103 | // 5th case ts < ts0 && te3 < te | |||
|
104 | ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 0, 0, 0}}; | |||
|
105 | te = QDateTime{QDate{2017, 01, 01}, QTime{2, 22, 0, 0}}; | |||
|
106 | sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
107 | ||||
|
108 | ||||
|
109 | notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); | |||
|
110 | ||||
|
111 | QCOMPARE(notInCach.size(), 4); | |||
|
112 | notInCacheSqp = notInCach.first(); | |||
|
113 | QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(ts)); | |||
|
114 | QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(ts0)); | |||
|
115 | ||||
|
116 | notInCacheSqp = notInCach.at(1); | |||
|
117 | QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(te0)); | |||
|
118 | QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(ts1)); | |||
|
119 | ||||
|
120 | notInCacheSqp = notInCach.at(2); | |||
|
121 | QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(te1)); | |||
|
122 | QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(ts2)); | |||
|
123 | ||||
|
124 | notInCacheSqp = notInCach.at(3); | |||
|
125 | QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(te2)); | |||
|
126 | QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(te)); | |||
|
127 | ||||
|
128 | ||||
|
129 | // 6th case ts2 < ts | |||
|
130 | ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 45, 0, 0}}; | |||
|
131 | te = QDateTime{QDate{2017, 01, 01}, QTime{2, 47, 0, 0}}; | |||
|
132 | sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
133 | ||||
|
134 | ||||
|
135 | notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); | |||
|
136 | ||||
|
137 | QCOMPARE(notInCach.size(), 1); | |||
|
138 | notInCacheSqp = notInCach.first(); | |||
|
139 | QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(ts)); | |||
|
140 | QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(te)); | |||
|
141 | ||||
|
142 | // 7th case ts = te0 && te < ts1 | |||
|
143 | ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}}; | |||
|
144 | te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}}; | |||
|
145 | sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
146 | ||||
|
147 | ||||
|
148 | notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); | |||
|
149 | ||||
|
150 | QCOMPARE(notInCach.size(), 1); | |||
|
151 | notInCacheSqp = notInCach.first(); | |||
|
152 | QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(te0)); | |||
|
153 | QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(te)); | |||
|
154 | ||||
|
155 | // 8th case ts0 < ts < te0 && te < ts1 | |||
|
156 | ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}}; | |||
|
157 | te = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}}; | |||
|
158 | sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
159 | ||||
|
160 | ||||
|
161 | notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); | |||
|
162 | ||||
|
163 | QCOMPARE(notInCach.size(), 1); | |||
|
164 | notInCacheSqp = notInCach.first(); | |||
|
165 | QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(te0)); | |||
|
166 | QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(te)); | |||
|
167 | ||||
|
168 | // 9th case ts0 < ts < te0 && ts1 < te < te1 | |||
|
169 | ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 30, 0}}; | |||
|
170 | te = QDateTime{QDate{2017, 01, 01}, QTime{2, 7, 0, 0}}; | |||
|
171 | sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
172 | ||||
|
173 | ||||
|
174 | notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); | |||
|
175 | ||||
|
176 | QCOMPARE(notInCach.size(), 1); | |||
|
177 | notInCacheSqp = notInCach.first(); | |||
|
178 | QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(te0)); | |||
|
179 | QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(ts1)); | |||
|
180 | ||||
|
181 | // 10th case te1 < ts < te < ts2 | |||
|
182 | ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 9, 0, 0}}; | |||
|
183 | te = QDateTime{QDate{2017, 01, 01}, QTime{2, 10, 0, 0}}; | |||
|
184 | sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
185 | ||||
|
186 | ||||
|
187 | notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); | |||
|
188 | ||||
|
189 | QCOMPARE(notInCach.size(), 1); | |||
|
190 | notInCacheSqp = notInCach.first(); | |||
|
191 | QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(ts)); | |||
|
192 | QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(te)); | |||
|
193 | ||||
|
194 | // 11th case te0 < ts < ts1 && te3 < te | |||
|
195 | ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}}; | |||
|
196 | te = QDateTime{QDate{2017, 01, 01}, QTime{2, 47, 0, 0}}; | |||
|
197 | sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
198 | ||||
|
199 | ||||
|
200 | notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); | |||
|
201 | ||||
|
202 | QCOMPARE(notInCach.size(), 3); | |||
|
203 | notInCacheSqp = notInCach.first(); | |||
|
204 | QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(ts)); | |||
|
205 | QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(ts1)); | |||
|
206 | ||||
|
207 | notInCacheSqp = notInCach.at(1); | |||
|
208 | QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(te1)); | |||
|
209 | QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(ts2)); | |||
|
210 | ||||
|
211 | notInCacheSqp = notInCach.at(2); | |||
|
212 | QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(te2)); | |||
|
213 | QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(te)); | |||
|
214 | ||||
|
215 | // 12th case te0 < ts < ts1 && te3 < te | |||
|
216 | ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 5, 0, 0}}; | |||
|
217 | te = QDateTime{QDate{2017, 01, 01}, QTime{2, 10, 0, 0}}; | |||
|
218 | sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
219 | ||||
|
220 | notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); | |||
|
221 | ||||
|
222 | QCOMPARE(notInCach.size(), 2); | |||
|
223 | notInCacheSqp = notInCach.first(); | |||
|
224 | QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(ts)); | |||
|
225 | QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(ts1)); | |||
|
226 | ||||
|
227 | notInCacheSqp = notInCach.at(1); | |||
|
228 | QCOMPARE(notInCacheSqp.m_TStart, DateUtils::secondsSinceEpoch(te1)); | |||
|
229 | QCOMPARE(notInCacheSqp.m_TEnd, DateUtils::secondsSinceEpoch(te)); | |||
|
230 | ||||
|
231 | ||||
|
232 | // 12th case ts0 < ts < te0 | |||
|
233 | ts = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 10, 0}}; | |||
|
234 | te = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 50, 0}}; | |||
|
235 | sqp = DateTimeRange{DateUtils::secondsSinceEpoch(ts), DateUtils::secondsSinceEpoch(te)}; | |||
|
236 | ||||
|
237 | notInCach = variableCacheController.provideNotInCacheDateTimeList(var0, sqp); | |||
|
238 | QCOMPARE(notInCach.size(), 0); | |||
|
239 | } | |||
|
240 | ||||
|
241 | ||||
|
242 | void TestVariableCacheController::testAddDateTime() | |||
|
243 | { | |||
|
244 | VariableCacheController variableCacheController{}; | |||
|
245 | ||||
|
246 | auto ts0 = QDateTime{QDate{2017, 01, 01}, QTime{2, 3, 0, 0}}; | |||
|
247 | auto te0 = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}}; | |||
|
248 | auto sqp0 = DateTimeRange{DateUtils::secondsSinceEpoch(ts0), DateUtils::secondsSinceEpoch(te0)}; | |||
|
249 | ||||
|
250 | auto ts1 = QDateTime{QDate{2017, 01, 01}, QTime{2, 6, 0, 0}}; | |||
|
251 | auto te1 = QDateTime{QDate{2017, 01, 01}, QTime{2, 8, 0, 0}}; | |||
|
252 | auto sqp1 = DateTimeRange{DateUtils::secondsSinceEpoch(ts1), DateUtils::secondsSinceEpoch(te1)}; | |||
|
253 | ||||
|
254 | auto ts2 = QDateTime{QDate{2017, 01, 01}, QTime{2, 18, 0, 0}}; | |||
|
255 | auto te2 = QDateTime{QDate{2017, 01, 01}, QTime{2, 20, 0, 0}}; | |||
|
256 | auto sqp2 = DateTimeRange{DateUtils::secondsSinceEpoch(ts2), DateUtils::secondsSinceEpoch(te2)}; | |||
|
257 | ||||
|
258 | auto ts01 = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}}; | |||
|
259 | auto te01 = QDateTime{QDate{2017, 01, 01}, QTime{2, 6, 0, 0}}; | |||
|
260 | auto sqp01 = DateTimeRange{DateUtils::secondsSinceEpoch(ts01), DateUtils::secondsSinceEpoch(te01)}; | |||
|
261 | ||||
|
262 | auto ts3 = QDateTime{QDate{2017, 01, 01}, QTime{2, 14, 0, 0}}; | |||
|
263 | auto te3 = QDateTime{QDate{2017, 01, 01}, QTime{2, 16, 0, 0}}; | |||
|
264 | auto sqp3 = DateTimeRange{DateUtils::secondsSinceEpoch(ts3), DateUtils::secondsSinceEpoch(te3)}; | |||
|
265 | ||||
|
266 | auto ts03 = QDateTime{QDate{2017, 01, 01}, QTime{2, 4, 0, 0}}; | |||
|
267 | auto te03 = QDateTime{QDate{2017, 01, 01}, QTime{2, 22, 0, 0}}; | |||
|
268 | auto sqp03 = DateTimeRange{DateUtils::secondsSinceEpoch(ts03), DateUtils::secondsSinceEpoch(te03)}; | |||
|
269 | ||||
|
270 | ||||
|
271 | auto var0 = std::make_shared<Variable>(""); | |||
|
272 | var0->setRange(sqp0); | |||
|
273 | ||||
|
274 | ||||
|
275 | // First case: add the first interval to the variable :sqp0 | |||
|
276 | variableCacheController.addDateTime(var0, sqp0); | |||
|
277 | auto dateCacheList = variableCacheController.dateCacheList(var0); | |||
|
278 | QCOMPARE(dateCacheList.count(), 1); | |||
|
279 | auto dateCache = dateCacheList.at(0); | |||
|
280 | QCOMPARE(dateCache.m_TStart, DateUtils::secondsSinceEpoch(ts0)); | |||
|
281 | QCOMPARE(dateCache.m_TEnd, DateUtils::secondsSinceEpoch(te0)); | |||
|
282 | ||||
|
283 | // 2nd case: add a second interval : sqp1 > sqp0 | |||
|
284 | variableCacheController.addDateTime(var0, sqp1); | |||
|
285 | dateCacheList = variableCacheController.dateCacheList(var0); | |||
|
286 | QCOMPARE(dateCacheList.count(), 2); | |||
|
287 | dateCache = dateCacheList.at(0); | |||
|
288 | QCOMPARE(dateCache.m_TStart, DateUtils::secondsSinceEpoch(ts0)); | |||
|
289 | QCOMPARE(dateCache.m_TEnd, DateUtils::secondsSinceEpoch(te0)); | |||
|
290 | ||||
|
291 | dateCache = dateCacheList.at(1); | |||
|
292 | QCOMPARE(dateCache.m_TStart, DateUtils::secondsSinceEpoch(ts1)); | |||
|
293 | QCOMPARE(dateCache.m_TEnd, DateUtils::secondsSinceEpoch(te1)); | |||
|
294 | ||||
|
295 | // 3th case: merge sqp0 & sqp1 with sqp01 | |||
|
296 | variableCacheController.addDateTime(var0, sqp01); | |||
|
297 | dateCacheList = variableCacheController.dateCacheList(var0); | |||
|
298 | QCOMPARE(dateCacheList.count(), 1); | |||
|
299 | dateCache = dateCacheList.at(0); | |||
|
300 | QCOMPARE(dateCache.m_TStart, DateUtils::secondsSinceEpoch(ts0)); | |||
|
301 | QCOMPARE(dateCache.m_TEnd, DateUtils::secondsSinceEpoch(te1)); | |||
|
302 | ||||
|
303 | ||||
|
304 | // 4th case: add a second interval : sqp1 > sqp0 | |||
|
305 | variableCacheController.addDateTime(var0, sqp2); | |||
|
306 | variableCacheController.addDateTime(var0, sqp3); | |||
|
307 | dateCacheList = variableCacheController.dateCacheList(var0); | |||
|
308 | QCOMPARE(dateCacheList.count(), 3); | |||
|
309 | dateCache = dateCacheList.at(0); | |||
|
310 | QCOMPARE(dateCache.m_TStart, DateUtils::secondsSinceEpoch(ts0)); | |||
|
311 | QCOMPARE(dateCache.m_TEnd, DateUtils::secondsSinceEpoch(te1)); | |||
|
312 | ||||
|
313 | dateCache = dateCacheList.at(1); | |||
|
314 | QCOMPARE(dateCache.m_TStart, DateUtils::secondsSinceEpoch(ts3)); | |||
|
315 | QCOMPARE(dateCache.m_TEnd, DateUtils::secondsSinceEpoch(te3)); | |||
|
316 | ||||
|
317 | dateCache = dateCacheList.at(2); | |||
|
318 | QCOMPARE(dateCache.m_TStart, DateUtils::secondsSinceEpoch(ts2)); | |||
|
319 | QCOMPARE(dateCache.m_TEnd, DateUtils::secondsSinceEpoch(te2)); | |||
|
320 | ||||
|
321 | ||||
|
322 | // 5th case: merge all interval | |||
|
323 | variableCacheController.addDateTime(var0, sqp03); | |||
|
324 | dateCacheList = variableCacheController.dateCacheList(var0); | |||
|
325 | QCOMPARE(dateCacheList.count(), 1); | |||
|
326 | dateCache = dateCacheList.at(0); | |||
|
327 | QCOMPARE(dateCache.m_TStart, DateUtils::secondsSinceEpoch(ts0)); | |||
|
328 | QCOMPARE(dateCache.m_TEnd, DateUtils::secondsSinceEpoch(te03)); | |||
|
329 | } | |||
|
330 | ||||
|
331 | ||||
|
332 | QTEST_MAIN(TestVariableCacheController) | |||
|
333 | #include "TestVariableCacheController.moc" |
@@ -0,0 +1,74 | |||||
|
1 | #include <QObject> | |||
|
2 | #include <QtTest> | |||
|
3 | ||||
|
4 | #include <Data/IDataProvider.h> | |||
|
5 | #include <Time/TimeController.h> | |||
|
6 | #include <Variable/Variable.h> | |||
|
7 | #include <Variable/VariableController.h> | |||
|
8 | ||||
|
9 | #include <memory> | |||
|
10 | ||||
|
11 | namespace { | |||
|
12 | ||||
|
13 | /// Provider used for the tests | |||
|
14 | class TestProvider : public IDataProvider { | |||
|
15 | std::shared_ptr<IDataProvider> clone() const { return std::make_shared<TestProvider>(); } | |||
|
16 | ||||
|
17 | void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters ¶meters) override | |||
|
18 | { | |||
|
19 | // Does nothing | |||
|
20 | } | |||
|
21 | ||||
|
22 | void requestDataAborting(QUuid acqIdentifier) override | |||
|
23 | { | |||
|
24 | // Does nothing | |||
|
25 | } | |||
|
26 | }; | |||
|
27 | ||||
|
28 | /// Generates a time controller for the tests | |||
|
29 | std::unique_ptr<TimeController> defaultTimeController() | |||
|
30 | { | |||
|
31 | auto timeController = std::make_unique<TimeController>(); | |||
|
32 | ||||
|
33 | QDateTime start{QDate{2017, 01, 01}, QTime{0, 0, 0, 0}}; | |||
|
34 | QDateTime end{QDate{2017, 01, 02}, QTime{0, 0, 0, 0}}; | |||
|
35 | timeController->setDateTimeRange( | |||
|
36 | DateTimeRange{DateUtils::secondsSinceEpoch(start), DateUtils::secondsSinceEpoch(end)}); | |||
|
37 | ||||
|
38 | return timeController; | |||
|
39 | } | |||
|
40 | ||||
|
41 | } // namespace | |||
|
42 | ||||
|
43 | class TestVariableController : public QObject { | |||
|
44 | Q_OBJECT | |||
|
45 | ||||
|
46 | private slots: | |||
|
47 | /// Test removes variable from controller | |||
|
48 | void testDeleteVariable(); | |||
|
49 | }; | |||
|
50 | ||||
|
51 | void TestVariableController::testDeleteVariable() | |||
|
52 | { | |||
|
53 | // Creates variable controller | |||
|
54 | auto timeController = defaultTimeController(); | |||
|
55 | VariableController variableController{}; | |||
|
56 | //variableController.setTimeController(timeController.get()); | |||
|
57 | ||||
|
58 | // Creates a variable from the controller | |||
|
59 | auto variable | |||
|
60 | = variableController.createVariable("variable", {}, std::make_shared<TestProvider>(), timeController->dateTime()); | |||
|
61 | ||||
|
62 | qDebug() << QString::number(variable.use_count()); | |||
|
63 | ||||
|
64 | // Removes the variable from the controller | |||
|
65 | variableController.deleteVariable(variable); | |||
|
66 | ||||
|
67 | // Verifies that the variable has been deleted: this implies that the number of shared_ptr | |||
|
68 | // objects referring to the variable is 1 (the reference of this scope). Otherwise, the deletion | |||
|
69 | // is considered invalid since the variable is still referenced in the controller | |||
|
70 | QVERIFY(variable.use_count() == 1); | |||
|
71 | } | |||
|
72 | ||||
|
73 | QTEST_MAIN(TestVariableController) | |||
|
74 | #include "TestVariableController.moc" |
@@ -0,0 +1,30 | |||||
|
1 | #include <QtTest> | |||
|
2 | #include <QObject> | |||
|
3 | ||||
|
4 | ||||
|
5 | class TestVariableController2 : public QObject | |||
|
6 | ||||
|
7 | { | |||
|
8 | Q_OBJECT | |||
|
9 | public: | |||
|
10 | explicit TestVariableController2(QObject *parent = nullptr) : QObject(parent){} | |||
|
11 | signals: | |||
|
12 | ||||
|
13 | private slots: | |||
|
14 | void initTestCase(){} | |||
|
15 | void cleanupTestCase(){} | |||
|
16 | ||||
|
17 | void test1() | |||
|
18 | { | |||
|
19 | QCOMPARE(1+1, 2); | |||
|
20 | } | |||
|
21 | ||||
|
22 | private: | |||
|
23 | ||||
|
24 | }; | |||
|
25 | ||||
|
26 | ||||
|
27 | QTEST_MAIN(TestVariableController2) | |||
|
28 | ||||
|
29 | #include "TestVariableController2.moc" | |||
|
30 |
This diff has been collapsed as it changes many lines, (508 lines changed) Show them Hide them | |||||
@@ -0,0 +1,508 | |||||
|
1 | #include <QObject> | |||
|
2 | #include <QtTest> | |||
|
3 | ||||
|
4 | #include <memory> | |||
|
5 | ||||
|
6 | #include <Data/DataProviderParameters.h> | |||
|
7 | #include <Data/IDataProvider.h> | |||
|
8 | #include <Data/ScalarSeries.h> | |||
|
9 | #include <Time/TimeController.h> | |||
|
10 | #include <Variable/Variable.h> | |||
|
11 | #include <Variable/VariableController.h> | |||
|
12 | #include <Variable/VariableModel.h> | |||
|
13 | ||||
|
14 | namespace { | |||
|
15 | ||||
|
16 | /// Delay after each operation on the variable before validating it (in ms) | |||
|
17 | const auto OPERATION_DELAY = 100; | |||
|
18 | ||||
|
19 | /** | |||
|
20 | * Generates values according to a range. The value generated for a time t is the number of seconds | |||
|
21 | * of difference between t and a reference value (which is midnight -> 00:00:00) | |||
|
22 | * | |||
|
23 | * Example: For a range between 00:00:10 and 00:00:20, the generated values are | |||
|
24 | * {10,11,12,13,14,15,16,17,18,19,20} | |||
|
25 | */ | |||
|
26 | std::vector<double> values(const DateTimeRange &range) | |||
|
27 | { | |||
|
28 | QTime referenceTime{0, 0}; | |||
|
29 | ||||
|
30 | std::vector<double> result{}; | |||
|
31 | ||||
|
32 | for (auto i = range.m_TStart; i <= range.m_TEnd; ++i) { | |||
|
33 | auto time = DateUtils::dateTime(i).time(); | |||
|
34 | result.push_back(referenceTime.secsTo(time)); | |||
|
35 | } | |||
|
36 | ||||
|
37 | return result; | |||
|
38 | } | |||
|
39 | ||||
|
40 | void validateRanges(VariableController &variableController, | |||
|
41 | const std::map<int, DateTimeRange> &expectedRanges) | |||
|
42 | { | |||
|
43 | for (const auto &expectedRangeEntry : expectedRanges) { | |||
|
44 | auto variableIndex = expectedRangeEntry.first; | |||
|
45 | auto expectedRange = expectedRangeEntry.second; | |||
|
46 | ||||
|
47 | // Gets the variable in the controller | |||
|
48 | auto variable = variableController.variableModel()->variable(variableIndex); | |||
|
49 | ||||
|
50 | // Compares variable's range to the expected range | |||
|
51 | QVERIFY(variable != nullptr); | |||
|
52 | auto range = variable->range(); | |||
|
53 | qInfo() << "range vs expected range" << range << expectedRange; | |||
|
54 | QCOMPARE(range, expectedRange); | |||
|
55 | ||||
|
56 | // Compares variable's data with values expected for its range | |||
|
57 | auto dataSeries = variable->dataSeries(); | |||
|
58 | QVERIFY(dataSeries != nullptr); | |||
|
59 | ||||
|
60 | auto it = dataSeries->xAxisRange(range.m_TStart, range.m_TEnd); | |||
|
61 | auto expectedValues = values(range); | |||
|
62 | qInfo() << std::distance(it.first, it.second) << expectedValues.size(); | |||
|
63 | QVERIFY(std::equal(it.first, it.second, expectedValues.cbegin(), expectedValues.cend(), | |||
|
64 | [](const auto &dataSeriesIt, const auto &expectedValue) { | |||
|
65 | return dataSeriesIt.value() == expectedValue; | |||
|
66 | })); | |||
|
67 | } | |||
|
68 | } | |||
|
69 | ||||
|
70 | /// Provider used for the tests | |||
|
71 | class TestProvider : public IDataProvider { | |||
|
72 | std::shared_ptr<IDataProvider> clone() const { return std::make_shared<TestProvider>(); } | |||
|
73 | ||||
|
74 | void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters ¶meters) override | |||
|
75 | { | |||
|
76 | const auto &ranges = parameters.m_Times; | |||
|
77 | ||||
|
78 | for (const auto &range : ranges) { | |||
|
79 | // Generates data series | |||
|
80 | auto valuesData = values(range); | |||
|
81 | ||||
|
82 | std::vector<double> xAxisData{}; | |||
|
83 | for (auto i = range.m_TStart; i <= range.m_TEnd; ++i) { | |||
|
84 | xAxisData.push_back(i); | |||
|
85 | } | |||
|
86 | ||||
|
87 | auto dataSeries = std::make_shared<ScalarSeries>( | |||
|
88 | std::move(xAxisData), std::move(valuesData), Unit{"t", true}, Unit{}); | |||
|
89 | ||||
|
90 | emit dataProvided(acqIdentifier, dataSeries, range); | |||
|
91 | } | |||
|
92 | } | |||
|
93 | ||||
|
94 | void requestDataAborting(QUuid acqIdentifier) override | |||
|
95 | { | |||
|
96 | // Does nothing | |||
|
97 | } | |||
|
98 | }; | |||
|
99 | ||||
|
100 | /** | |||
|
101 | * Interface representing an operation performed on a variable controller. | |||
|
102 | * This interface is used in tests to apply a set of operations and check the status of the | |||
|
103 | * controller after each operation | |||
|
104 | */ | |||
|
105 | struct IOperation { | |||
|
106 | virtual ~IOperation() = default; | |||
|
107 | /// Executes the operation on the variable controller | |||
|
108 | virtual void exec(VariableController &variableController) const = 0; | |||
|
109 | }; | |||
|
110 | ||||
|
111 | /** | |||
|
112 | *Variable creation operation in the controller | |||
|
113 | */ | |||
|
114 | struct Create : public IOperation { | |||
|
115 | explicit Create(int index, const DateTimeRange &range) : m_Index{index},m_range(range) {} | |||
|
116 | ||||
|
117 | void exec(VariableController &variableController) const override | |||
|
118 | { | |||
|
119 | auto variable = variableController.createVariable(QString::number(m_Index), {}, | |||
|
120 | std::make_unique<TestProvider>(), m_range); | |||
|
121 | } | |||
|
122 | int m_Index; ///< The index of the variable to create in the controller | |||
|
123 | DateTimeRange m_range; | |||
|
124 | }; | |||
|
125 | ||||
|
126 | /** | |||
|
127 | * Variable move/shift operation in the controller | |||
|
128 | */ | |||
|
129 | struct Move : public IOperation { | |||
|
130 | explicit Move(int index, const DateTimeRange &newRange, bool shift = false, int delayMS = 10) | |||
|
131 | : m_Index{index}, m_NewRange{newRange}, m_Shift{shift}, m_DelayMs{delayMS} | |||
|
132 | { | |||
|
133 | } | |||
|
134 | ||||
|
135 | void exec(VariableController &variableController) const override | |||
|
136 | { | |||
|
137 | if (auto variable = variableController.variableModel()->variable(m_Index)) { | |||
|
138 | variableController.onRequestDataLoading({variable}, m_NewRange, !m_Shift); | |||
|
139 | QTest::qWait(m_DelayMs); | |||
|
140 | } | |||
|
141 | } | |||
|
142 | ||||
|
143 | int m_Index; ///< The index of the variable to move | |||
|
144 | DateTimeRange m_NewRange; ///< The new range of the variable | |||
|
145 | bool m_Shift; ///< Performs a shift ( | |||
|
146 | int m_DelayMs; ///< wait the delay after running the request ( | |||
|
147 | }; | |||
|
148 | ||||
|
149 | /** | |||
|
150 | * Variable synchronization/desynchronization operation in the controller | |||
|
151 | */ | |||
|
152 | struct Synchronize : public IOperation { | |||
|
153 | explicit Synchronize(int index, QUuid syncId, bool synchronize = true) | |||
|
154 | : m_Index{index}, m_SyncId{syncId}, m_Synchronize{synchronize} | |||
|
155 | { | |||
|
156 | } | |||
|
157 | ||||
|
158 | void exec(VariableController &variableController) const override | |||
|
159 | { | |||
|
160 | if (auto variable = variableController.variableModel()->variable(m_Index)) { | |||
|
161 | if (m_Synchronize) { | |||
|
162 | variableController.onAddSynchronized(variable, m_SyncId); | |||
|
163 | } | |||
|
164 | else { | |||
|
165 | variableController.desynchronize(variable, m_SyncId); | |||
|
166 | } | |||
|
167 | } | |||
|
168 | } | |||
|
169 | ||||
|
170 | int m_Index; ///< The index of the variable to sync/desync | |||
|
171 | QUuid m_SyncId; ///< The synchronization group of the variable | |||
|
172 | bool m_Synchronize; ///< Performs sync or desync operation | |||
|
173 | }; | |||
|
174 | ||||
|
175 | /** | |||
|
176 | * Test Iteration | |||
|
177 | * | |||
|
178 | * A test iteration includes an operation to be performed, and a set of expected ranges after each | |||
|
179 | * operation. Each range is tested after the operation to ensure that: | |||
|
180 | * - the range of the variable is the expected range | |||
|
181 | * - the data of the variable are those generated for the expected range | |||
|
182 | */ | |||
|
183 | struct Iteration { | |||
|
184 | std::shared_ptr<IOperation> m_Operation; ///< Operation to perform | |||
|
185 | std::map<int, DateTimeRange> m_ExpectedRanges; ///< Expected ranges (by variable index) | |||
|
186 | }; | |||
|
187 | ||||
|
188 | using Iterations = std::vector<Iteration>; | |||
|
189 | ||||
|
190 | } // namespace | |||
|
191 | ||||
|
192 | Q_DECLARE_METATYPE(Iterations) | |||
|
193 | ||||
|
194 | class TestVariableSync : public QObject { | |||
|
195 | Q_OBJECT | |||
|
196 | ||||
|
197 | private slots: | |||
|
198 | void initTestCase() { QSKIP("Temporarily disables TestVariableSync"); } | |||
|
199 | ||||
|
200 | /// Input data for @sa testSync() | |||
|
201 | void testSync_data(); | |||
|
202 | ||||
|
203 | /// Input data for @sa testSyncOneVar() | |||
|
204 | void testSyncOneVar_data(); | |||
|
205 | ||||
|
206 | /// Tests synchronization between variables through several operations | |||
|
207 | void testSync(); | |||
|
208 | ||||
|
209 | /// Tests synchronization between variables through several operations | |||
|
210 | void testSyncOneVar(); | |||
|
211 | }; | |||
|
212 | ||||
|
213 | namespace { | |||
|
214 | ||||
|
215 | void testSyncCase1() | |||
|
216 | { | |||
|
217 | // Id used to synchronize variables in the controller | |||
|
218 | auto syncId = QUuid::createUuid(); | |||
|
219 | ||||
|
220 | /// Generates a range according to a start time and a end time (the date is the same) | |||
|
221 | auto range = [](const QTime &startTime, const QTime &endTime) { | |||
|
222 | return DateTimeRange{DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, startTime, Qt::UTC}), | |||
|
223 | DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, endTime, Qt::UTC})}; | |||
|
224 | }; | |||
|
225 | ||||
|
226 | auto initialRange = range({12, 0}, {13, 0}); | |||
|
227 | ||||
|
228 | Iterations iterations{}; | |||
|
229 | // Creates variables var0, var1 and var2 | |||
|
230 | iterations.push_back({std::make_shared<Create>(0, initialRange), {{0, initialRange}}}); | |||
|
231 | iterations.push_back({std::make_shared<Create>(1, initialRange), {{0, initialRange}, {1, initialRange}}}); | |||
|
232 | iterations.push_back( | |||
|
233 | {std::make_shared<Create>(2, initialRange), {{0, initialRange}, {1, initialRange}, {2, initialRange}}}); | |||
|
234 | ||||
|
235 | // Adds variables into the sync group (ranges don't need to be tested here) | |||
|
236 | iterations.push_back({std::make_shared<Synchronize>(0, syncId)}); | |||
|
237 | iterations.push_back({std::make_shared<Synchronize>(1, syncId)}); | |||
|
238 | iterations.push_back({std::make_shared<Synchronize>(2, syncId)}); | |||
|
239 | ||||
|
240 | // Moves var0: ranges of var0, var1 and var2 change | |||
|
241 | auto newRange = range({12, 30}, {13, 30}); | |||
|
242 | iterations.push_back( | |||
|
243 | {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}}); | |||
|
244 | ||||
|
245 | // Moves var1: ranges of var0, var1 and var2 change | |||
|
246 | newRange = range({13, 0}, {14, 0}); | |||
|
247 | iterations.push_back( | |||
|
248 | {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}}); | |||
|
249 | ||||
|
250 | // Moves var2: ranges of var0, var1 and var2 change | |||
|
251 | newRange = range({13, 30}, {14, 30}); | |||
|
252 | iterations.push_back( | |||
|
253 | {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, newRange}}}); | |||
|
254 | ||||
|
255 | // Desyncs var2 and moves var0: | |||
|
256 | // - ranges of var0 and var1 change | |||
|
257 | // - range of var2 doesn't change anymore | |||
|
258 | auto var2Range = newRange; | |||
|
259 | newRange = range({13, 45}, {14, 45}); | |||
|
260 | iterations.push_back({std::make_shared<Synchronize>(2, syncId, false)}); | |||
|
261 | iterations.push_back( | |||
|
262 | {std::make_shared<Move>(0, newRange), {{0, newRange}, {1, newRange}, {2, var2Range}}}); | |||
|
263 | ||||
|
264 | // Shifts var0: although var1 is synchronized with var0, its range doesn't change | |||
|
265 | auto var1Range = newRange; | |||
|
266 | newRange = range({14, 45}, {15, 45}); | |||
|
267 | iterations.push_back({std::make_shared<Move>(0, newRange, true), | |||
|
268 | {{0, newRange}, {1, var1Range}, {2, var2Range}}}); | |||
|
269 | ||||
|
270 | // Moves var0 through several operations: | |||
|
271 | // - range of var0 changes | |||
|
272 | // - range or var1 changes according to the previous shift (one hour) | |||
|
273 | auto moveVar0 = [&iterations](const auto &var0NewRange, const auto &var1ExpectedRange) { | |||
|
274 | iterations.push_back( | |||
|
275 | {std::make_shared<Move>(0, var0NewRange), {{0, var0NewRange}, {1, var1ExpectedRange}}}); | |||
|
276 | }; | |||
|
277 | ||||
|
278 | // Pan left | |||
|
279 | moveVar0(range({14, 30}, {15, 30}), range({13, 30}, {14, 30})); | |||
|
280 | // Pan right | |||
|
281 | moveVar0(range({16, 0}, {17, 0}), range({15, 0}, {16, 0})); | |||
|
282 | // Zoom in | |||
|
283 | moveVar0(range({16, 30}, {16, 45}), range({15, 30}, {15, 45})); | |||
|
284 | // Zoom out | |||
|
285 | moveVar0(range({16, 15}, {17, 0}), range({15, 15}, {16, 0})); | |||
|
286 | ||||
|
287 | QTest::newRow("sync1") << syncId << initialRange << std::move(iterations) << 200; | |||
|
288 | } | |||
|
289 | ||||
|
290 | void testSyncCase2() | |||
|
291 | { | |||
|
292 | // Id used to synchronize variables in the controller | |||
|
293 | auto syncId = QUuid::createUuid(); | |||
|
294 | ||||
|
295 | /// Generates a range according to a start time and a end time (the date is the same) | |||
|
296 | auto dateTime = [](int year, int month, int day, int hours, int minutes, int seconds) { | |||
|
297 | return DateUtils::secondsSinceEpoch( | |||
|
298 | QDateTime{{year, month, day}, QTime{hours, minutes, seconds}, Qt::UTC}); | |||
|
299 | }; | |||
|
300 | ||||
|
301 | auto initialRange = DateTimeRange{dateTime(2017, 1, 1, 12, 0, 0), dateTime(2017, 1, 1, 13, 0, 0)}; | |||
|
302 | ||||
|
303 | Iterations iterations{}; | |||
|
304 | // Creates variables var0 and var1 | |||
|
305 | iterations.push_back({std::make_shared<Create>(0, initialRange), {{0, initialRange}}}); | |||
|
306 | iterations.push_back({std::make_shared<Create>(1, initialRange), {{0, initialRange}, {1, initialRange}}}); | |||
|
307 | ||||
|
308 | // Adds variables into the sync group (ranges don't need to be tested here) | |||
|
309 | iterations.push_back({std::make_shared<Synchronize>(0, syncId)}); | |||
|
310 | iterations.push_back({std::make_shared<Synchronize>(1, syncId)}); | |||
|
311 | ||||
|
312 | ||||
|
313 | // Moves var0 through several operations: | |||
|
314 | // - range of var0 changes | |||
|
315 | // - range or var1 changes according to the previous shift (one hour) | |||
|
316 | auto moveVar0 = [&iterations](const auto &var0NewRange) { | |||
|
317 | iterations.push_back( | |||
|
318 | {std::make_shared<Move>(0, var0NewRange), {{0, var0NewRange}, {1, var0NewRange}}}); | |||
|
319 | }; | |||
|
320 | moveVar0(DateTimeRange{dateTime(2017, 1, 1, 12, 0, 0), dateTime(2017, 1, 1, 13, 0, 0)}); | |||
|
321 | moveVar0(DateTimeRange{dateTime(2017, 1, 1, 14, 0, 0), dateTime(2017, 1, 1, 15, 0, 0)}); | |||
|
322 | moveVar0(DateTimeRange{dateTime(2017, 1, 1, 8, 0, 0), dateTime(2017, 1, 1, 9, 0, 0)}); | |||
|
323 | // moveVar0(SqpRange{dateTime(2017, 1, 1, 7, 30, 0), dateTime(2017, 1, 1, 9, 30, 0)}); | |||
|
324 | moveVar0(DateTimeRange{dateTime(2017, 1, 1, 2, 0, 0), dateTime(2017, 1, 1, 4, 0, 0)}); | |||
|
325 | moveVar0(DateTimeRange{dateTime(2017, 1, 1, 6, 0, 0), dateTime(2017, 1, 1, 8, 0, 0)}); | |||
|
326 | ||||
|
327 | moveVar0(DateTimeRange{dateTime(2017, 1, 10, 6, 0, 0), dateTime(2017, 1, 15, 8, 0, 0)}); | |||
|
328 | moveVar0(DateTimeRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 1, 25, 8, 0, 0)}); | |||
|
329 | moveVar0(DateTimeRange{dateTime(2017, 1, 2, 6, 0, 0), dateTime(2017, 1, 8, 8, 0, 0)}); | |||
|
330 | ||||
|
331 | moveVar0(DateTimeRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)}); | |||
|
332 | moveVar0(DateTimeRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)}); | |||
|
333 | moveVar0(DateTimeRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)}); | |||
|
334 | moveVar0(DateTimeRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)}); | |||
|
335 | moveVar0(DateTimeRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)}); | |||
|
336 | moveVar0(DateTimeRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)}); | |||
|
337 | moveVar0(DateTimeRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)}); | |||
|
338 | moveVar0(DateTimeRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)}); | |||
|
339 | moveVar0(DateTimeRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)}); | |||
|
340 | moveVar0(DateTimeRange{dateTime(2017, 4, 10, 6, 0, 0), dateTime(2017, 6, 15, 8, 0, 0)}); | |||
|
341 | moveVar0(DateTimeRange{dateTime(2017, 1, 17, 6, 0, 0), dateTime(2017, 2, 25, 8, 0, 0)}); | |||
|
342 | moveVar0(DateTimeRange{dateTime(2017, 7, 2, 6, 0, 0), dateTime(2017, 10, 8, 8, 0, 0)}); | |||
|
343 | ||||
|
344 | ||||
|
345 | QTest::newRow("sync2") << syncId << initialRange << iterations << 4000; | |||
|
346 | // QTest::newRow("sync3") << syncId << initialRange << iterations << 5000; | |||
|
347 | } | |||
|
348 | ||||
|
349 | void testSyncOnVarCase1() | |||
|
350 | { | |||
|
351 | // Id used to synchronize variables in the controller | |||
|
352 | auto syncId = QUuid::createUuid(); | |||
|
353 | ||||
|
354 | /// Generates a range according to a start time and a end time (the date is the same) | |||
|
355 | auto range = [](const QTime &startTime, const QTime &endTime) { | |||
|
356 | return DateTimeRange{DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, startTime, Qt::UTC}), | |||
|
357 | DateUtils::secondsSinceEpoch(QDateTime{{2017, 1, 1}, endTime, Qt::UTC})}; | |||
|
358 | }; | |||
|
359 | ||||
|
360 | auto initialRange = range({12, 0}, {13, 0}); | |||
|
361 | ||||
|
362 | Iterations creations{}; | |||
|
363 | // Creates variables var0, var1 and var2 | |||
|
364 | creations.push_back({std::make_shared<Create>(0, initialRange), {{0, initialRange}}}); | |||
|
365 | ||||
|
366 | Iterations synchronization{}; | |||
|
367 | // Adds variables into the sync group (ranges don't need to be tested here) | |||
|
368 | synchronization.push_back({std::make_shared<Synchronize>(0, syncId)}); | |||
|
369 | ||||
|
370 | Iterations iterations{}; | |||
|
371 | ||||
|
372 | // Moves var0 through several operations | |||
|
373 | auto moveOp = [&iterations](const auto &requestedRange, const auto &expectedRange, auto delay) { | |||
|
374 | iterations.push_back( | |||
|
375 | {std::make_shared<Move>(0, requestedRange, true, delay), {{0, expectedRange}}}); | |||
|
376 | }; | |||
|
377 | ||||
|
378 | // we assume here 300 ms is enough to finsh a operation | |||
|
379 | int delayToFinish = 300; | |||
|
380 | // jump to right, let's the operation time to finish | |||
|
381 | moveOp(range({14, 30}, {15, 30}), range({14, 30}, {15, 30}), delayToFinish); | |||
|
382 | // pan to right, let's the operation time to finish | |||
|
383 | moveOp(range({14, 45}, {15, 45}), range({14, 45}, {15, 45}), delayToFinish); | |||
|
384 | // jump to left, let's the operation time to finish | |||
|
385 | moveOp(range({03, 30}, {04, 30}), range({03, 30}, {04, 30}), delayToFinish); | |||
|
386 | // Pan to left, let's the operation time to finish | |||
|
387 | moveOp(range({03, 10}, {04, 10}), range({03, 10}, {04, 10}), delayToFinish); | |||
|
388 | // Zoom in, let's the operation time to finish | |||
|
389 | moveOp(range({03, 30}, {04, 00}), range({03, 30}, {04, 00}), delayToFinish); | |||
|
390 | // Zoom out left, let's the operation time to finish | |||
|
391 | moveOp(range({01, 10}, {18, 10}), range({01, 10}, {18, 10}), delayToFinish); | |||
|
392 | // Go back to initial range | |||
|
393 | moveOp(initialRange, initialRange, delayToFinish); | |||
|
394 | ||||
|
395 | ||||
|
396 | // jump to right, let's the operation time to finish | |||
|
397 | // moveOp(range({14, 30}, {15, 30}), initialRange, delayToFinish); | |||
|
398 | // Zoom out left, let's the operation time to finish | |||
|
399 | moveOp(range({01, 10}, {18, 10}), initialRange, delayToFinish); | |||
|
400 | // Go back to initial range | |||
|
401 | moveOp(initialRange, initialRange, 300); | |||
|
402 | ||||
|
403 | QTest::newRow("syncOnVarCase1") << syncId << initialRange << std::move(creations) | |||
|
404 | << std::move(iterations); | |||
|
405 | } | |||
|
406 | } | |||
|
407 | ||||
|
408 | void TestVariableSync::testSync_data() | |||
|
409 | { | |||
|
410 | // ////////////// // | |||
|
411 | // Test structure // | |||
|
412 | // ////////////// // | |||
|
413 | ||||
|
414 | QTest::addColumn<QUuid>("syncId"); | |||
|
415 | QTest::addColumn<DateTimeRange>("initialRange"); | |||
|
416 | QTest::addColumn<Iterations>("iterations"); | |||
|
417 | QTest::addColumn<int>("operationDelay"); | |||
|
418 | ||||
|
419 | // ////////// // | |||
|
420 | // Test cases // | |||
|
421 | // ////////// // | |||
|
422 | ||||
|
423 | testSyncCase1(); | |||
|
424 | testSyncCase2(); | |||
|
425 | } | |||
|
426 | ||||
|
427 | void TestVariableSync::testSyncOneVar_data() | |||
|
428 | { | |||
|
429 | // ////////////// // | |||
|
430 | // Test structure // | |||
|
431 | // ////////////// // | |||
|
432 | ||||
|
433 | QTest::addColumn<QUuid>("syncId"); | |||
|
434 | QTest::addColumn<DateTimeRange>("initialRange"); | |||
|
435 | QTest::addColumn<Iterations>("creations"); | |||
|
436 | QTest::addColumn<Iterations>("iterations"); | |||
|
437 | ||||
|
438 | // ////////// // | |||
|
439 | // Test cases // | |||
|
440 | // ////////// // | |||
|
441 | ||||
|
442 | testSyncOnVarCase1(); | |||
|
443 | } | |||
|
444 | ||||
|
445 | void TestVariableSync::testSync() | |||
|
446 | { | |||
|
447 | // Inits controllers | |||
|
448 | TimeController timeController{}; | |||
|
449 | VariableController variableController{}; | |||
|
450 | //variableController.setTimeController(&timeController); | |||
|
451 | ||||
|
452 | QFETCH(QUuid, syncId); | |||
|
453 | QFETCH(DateTimeRange, initialRange); | |||
|
454 | timeController.setDateTimeRange(initialRange); | |||
|
455 | ||||
|
456 | // Synchronization group used | |||
|
457 | variableController.onAddSynchronizationGroupId(syncId); | |||
|
458 | ||||
|
459 | // For each iteration: | |||
|
460 | // - execute operation | |||
|
461 | // - compare the variables' state to the expected states | |||
|
462 | QFETCH(Iterations, iterations); | |||
|
463 | QFETCH(int, operationDelay); | |||
|
464 | for (const auto &iteration : iterations) { | |||
|
465 | iteration.m_Operation->exec(variableController); | |||
|
466 | QTest::qWait(operationDelay); | |||
|
467 | ||||
|
468 | validateRanges(variableController, iteration.m_ExpectedRanges); | |||
|
469 | } | |||
|
470 | } | |||
|
471 | ||||
|
472 | void TestVariableSync::testSyncOneVar() | |||
|
473 | { | |||
|
474 | // Inits controllers | |||
|
475 | TimeController timeController{}; | |||
|
476 | VariableController variableController{}; | |||
|
477 | //variableController.setTimeController(&timeController); | |||
|
478 | ||||
|
479 | QFETCH(QUuid, syncId); | |||
|
480 | QFETCH(DateTimeRange, initialRange); | |||
|
481 | timeController.setDateTimeRange(initialRange); | |||
|
482 | ||||
|
483 | // Synchronization group used | |||
|
484 | variableController.onAddSynchronizationGroupId(syncId); | |||
|
485 | ||||
|
486 | // For each iteration: | |||
|
487 | // - execute operation | |||
|
488 | // - compare the variables' state to the expected states | |||
|
489 | QFETCH(Iterations, iterations); | |||
|
490 | QFETCH(Iterations, creations); | |||
|
491 | ||||
|
492 | for (const auto &creation : creations) { | |||
|
493 | creation.m_Operation->exec(variableController); | |||
|
494 | QTest::qWait(300); | |||
|
495 | } | |||
|
496 | ||||
|
497 | for (const auto &iteration : iterations) { | |||
|
498 | iteration.m_Operation->exec(variableController); | |||
|
499 | } | |||
|
500 | ||||
|
501 | if (!iterations.empty()) { | |||
|
502 | validateRanges(variableController, iterations.back().m_ExpectedRanges); | |||
|
503 | } | |||
|
504 | } | |||
|
505 | ||||
|
506 | QTEST_MAIN(TestVariableSync) | |||
|
507 | ||||
|
508 | #include "TestVariableSync.moc" |
@@ -0,0 +1,36 | |||||
|
1 | ||||
|
2 | ||||
|
3 | tests = [ | |||
|
4 | [['Common/TestStringUtils.cpp'],'test_string_utils','StringUtils test'], | |||
|
5 | [['Data/TestScalarSeries.cpp'],'test_scalar','ScalarSeries test'], | |||
|
6 | [['Data/TestSpectrogramSeries.cpp'],'test_spectrogram','SpectrogramSeries test'], | |||
|
7 | [['Data/TestVectorSeries.cpp'],'test_vector','VectorSeries test'], | |||
|
8 | [['Data/TestOneDimArrayData.cpp'],'test_1d','One Dim Array test'], | |||
|
9 | [['Data/TestOptionalAxis.cpp'],'test_optional_axis','OptionalAxis test'], | |||
|
10 | [['Data/TestTwoDimArrayData.cpp'],'test_2d','Two Dim Array test'], | |||
|
11 | [['Data/TestDataSeriesUtils.cpp'],'test_dataseries_util','Data series utils test'], | |||
|
12 | [['DataSource/TestDataSourceController.cpp'],'test_data_source','DataSourceController test'], | |||
|
13 | [['DataSource/TestDataSourceItem.cpp'],'test_data_source_item','DataSourceItem test'], | |||
|
14 | [['Variable/TestVariableCacheController.cpp'],'test_variable_cache','VariableCacheController test'], | |||
|
15 | [['Variable/TestVariable.cpp'],'test_variable','Variable test'], | |||
|
16 | [['Variable/TestVariableSync.cpp'],'test_variable_sync','Variable synchronization test'] | |||
|
17 | ] | |||
|
18 | ||||
|
19 | amdatest_sources = [ | |||
|
20 | 'Data/DataSeriesBuilders.h', | |||
|
21 | 'Data/DataSeriesBuilders.cpp', | |||
|
22 | 'Data/DataSeriesTestsUtils.h', | |||
|
23 | 'Data/DataSeriesTestsUtils.cpp', | |||
|
24 | 'DataSource/DataSourceItemBuilder.h', | |||
|
25 | 'DataSource/DataSourceItemBuilder.cpp' | |||
|
26 | ] | |||
|
27 | ||||
|
28 | foreach unit_test : tests | |||
|
29 | test_moc_files = qt5.preprocess(moc_sources : unit_test[0]) | |||
|
30 | test_exe = executable(unit_test[1],unit_test[0] , test_moc_files, | |||
|
31 | dependencies : [sciqlop_core, qt5test], | |||
|
32 | cpp_args : ['-DCORE_TESTS_RESOURCES_DIR="'+meson.current_source_dir()+'/../tests-resources"'], | |||
|
33 | sources : [amdatest_sources]) | |||
|
34 | test(unit_test[2], test_exe, args: ['-teamcity', '-o', '@0@.teamcity.txt'.format(unit_test[1])]) | |||
|
35 | endforeach | |||
|
36 |
General Comments 0
You need to be logged in to leave comments.
Login now