@golemio/flow 1.0.8-dev.577679507 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,53 @@
1
+ 'use strict';
2
+
3
+ var dbm;
4
+ var type;
5
+ var seed;
6
+ var fs = require('fs');
7
+ var path = require('path');
8
+ var Promise;
9
+
10
+ /**
11
+ * We receive the dbmigrate dependency from dbmigrate initially.
12
+ * This enables us to not have to rely on NODE_PATH.
13
+ */
14
+ exports.setup = function(options, seedLink) {
15
+ dbm = options.dbmigrate;
16
+ type = dbm.dataType;
17
+ seed = seedLink;
18
+ Promise = options.Promise;
19
+ };
20
+
21
+ exports.up = function(db) {
22
+ var filePath = path.join(__dirname, 'sqls', '20220711123652-analytic-up.sql');
23
+ return new Promise( function( resolve, reject ) {
24
+ fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){
25
+ if (err) return reject(err);
26
+ console.log('received data: ' + data);
27
+
28
+ resolve(data);
29
+ });
30
+ })
31
+ .then(function(data) {
32
+ return db.runSql(data);
33
+ });
34
+ };
35
+
36
+ exports.down = function(db) {
37
+ var filePath = path.join(__dirname, 'sqls', '20220711123652-analytic-down.sql');
38
+ return new Promise( function( resolve, reject ) {
39
+ fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){
40
+ if (err) return reject(err);
41
+ console.log('received data: ' + data);
42
+
43
+ resolve(data);
44
+ });
45
+ })
46
+ .then(function(data) {
47
+ return db.runSql(data);
48
+ });
49
+ };
50
+
51
+ exports._meta = {
52
+ "version": 1
53
+ };
@@ -0,0 +1,7 @@
1
+
2
+ DROP VIEW IF EXISTS analytic.v_pedestrians_detections_15min;
3
+ DROP VIEW IF EXISTS analytic.v_pedestrians_detections_api;
4
+ DROP VIEW IF EXISTS analytic.v_pedestrians_detections_daily;
5
+ DROP VIEW IF EXISTS analytic.v_pedestrians_flow_quality;
6
+ drop table if exists analytic.pedestrians_locations_gates;
7
+ drop table if exists analytic.pedestrians_locations_list;
@@ -0,0 +1,415 @@
1
+ CREATE SCHEMA IF NOT EXISTS analytic;
2
+
3
+ CREATE TABLE IF NOT EXISTS analytic.pedestrians_locations_list (
4
+ id serial4 NOT NULL,
5
+ location_name_plain varchar(250) NULL,
6
+ location_name varchar(250) NULL,
7
+ lat numeric NULL,
8
+ lng numeric NULL,
9
+ address varchar(250) NULL,
10
+ city_district varchar(250) NULL,
11
+ tech varchar(250) NULL,
12
+ map_picture varchar(2500) NULL,
13
+ gate_picture varchar(2500) NULL,
14
+ measurement_start timestamptz NULL,
15
+ measurement_end timestamptz NULL,
16
+ id_equiptment varchar(250) NULL,
17
+ cube_id varchar(250) NULL,
18
+ lon varbit NULL,
19
+ map_image varchar(55) NULL,
20
+ place_image varchar(59) NULL,
21
+ "table" varchar(19) NULL,
22
+ CONSTRAINT equipment_list_pkey PRIMARY KEY (id)
23
+ );
24
+ COMMENT ON TABLE analytic.pedestrians_locations_list IS '-- tabulka lokací. obsahuje lokace různých druhů a hodně custom dat, takže ji tvoříme ručně. sporadicky probíhají aktualizace
25
+ -- tabulka se nachází na https://operator.sharepoint.com/:f:/s/Datova_Platforma/EsE5uSdyLzdImWgyrMY8nFcBzwtH7GOr6TXtzNBn3FLIJw?e=fOov5s a jmenuje se locations_list.csv';
26
+
27
+ INSERT INTO analytic.pedestrians_locations_list (location_name_plain,location_name,lat,lng,address,city_district,tech,map_picture,gate_picture,measurement_start,measurement_end,id_equiptment,cube_id,lon,map_image,place_image,"table") VALUES
28
+ ('Výstaviště - viadukt VO 2','107043 - Výstaviště - viadukt VO 2',50.1042106575078,14.431679367811926,'U Výstaviště (viadukt)','Praha 7','kamera',NULL,NULL,'2020-09-02 00:00:00+02',NULL,NULL,'0',NULL,'https://storage.golemio.cz/intenzita-pesi-dopravy/1.png','https://storage.golemio.cz/intenzita-pesi-dopravy/1-map.png','flow_measurements'),
29
+ ('Rytířská 12','101336 - Rytířská 12',50.084781715549276,14.422412102465428,'Na Můstku 12','Praha 1','kamera',NULL,NULL,'2020-09-02 00:00:00+02',NULL,NULL,'1',NULL,'https://storage.golemio.cz/intenzita-pesi-dopravy/2.png','https://storage.golemio.cz/intenzita-pesi-dopravy/2-map.png','flow_measurements'),
30
+ ('Výstaviště - viadukt','Výstaviště - viadukt',50.1042106575078,14.431679367811926,'U Výstaviště (viadukt)','Praha 7','pyro',NULL,NULL,'2020-07-23 00:00:00+02','2020-11-10 00:00:00+01',NULL,'ecoCounter-100061215',NULL,'https://storage.golemio.cz/intenzita-pesi-dopravy/1.png','https://storage.golemio.cz/intenzita-pesi-dopravy/1-map.png','counters_detections'),
31
+ ('Stromovka - U Výstaviště','Stromovka - U Výstaviště',50.10489433551656,14.429609941952332,'U Výstaviště 67','Praha 7','wifi',NULL,NULL,'2020-11-24 00:00:00+01',NULL,NULL,'wifi1',NULL,NULL,'https://storage.golemio.cz/intenzita-pesi-dopravy/4-map.png','xyz'),
32
+ ('Stromovka - U Výstaviště','Stromovka - U Výstaviště',50.10489433551656,14.429609941952332,'U Výstaviště 67','Praha 7','pyro',NULL,NULL,'2020-11-11 00:00:00+01','2021-03-04 00:00:00+01',NULL,'ecoCounter-100065230',NULL,'https://storage.golemio.cz/intenzita-pesi-dopravy/3.png','https://storage.golemio.cz/intenzita-pesi-dopravy/3-map.png','counters_detections'),
33
+ ('Stromovka - U Výstaviště','Stromovka - U Výstaviště',50.10489433551656,14.429609941952332,'U Výstaviště 67','Praha 7','kamera',NULL,NULL,'2020-12-17 00:00:00+01',NULL,NULL,'13',NULL,'https://storage.golemio.cz/intenzita-pesi-dopravy/3.png','https://storage.golemio.cz/intenzita-pesi-dopravy/3-map.png','flow_measurements'),
34
+ ('Staroměstská věž pevná VI','101004 - Staroměstská věž pevná VI',50.08626,14.41301,'Karlův most','Praha 1','kamera',NULL,NULL,'2020-09-02 00:00:00+02',NULL,NULL,'9',NULL,'https://storage.golemio.cz/intenzita-pesi-dopravy/5.png','https://storage.golemio.cz/intenzita-pesi-dopravy/5-map.png','flow_measurements'),
35
+ ('Železniční most - nápl. I (náplavka)','202049 - Železniční most - nápl. I (náplavka)',50.06739,14.41468,'Novoměstská náplavka','Praha 2','kamera',NULL,NULL,'2020-09-02 00:00:00+02',NULL,NULL,'10',NULL,'https://storage.golemio.cz/intenzita-pesi-dopravy/6.png','https://storage.golemio.cz/intenzita-pesi-dopravy/6-map.png','flow_measurements'),
36
+ ('Železniční most - náplavka II','202050 - Železniční most - náplavka II',50.06693,14.41480,'Novoměstská náplavka','Praha 2','kamera',NULL,NULL,'2020-09-02 00:00:00+02',NULL,NULL,'11',NULL,'https://storage.golemio.cz/intenzita-pesi-dopravy/7.png','https://storage.golemio.cz/intenzita-pesi-dopravy/7-map.png','flow_measurements'),
37
+ ('Železniční most - nápl. I (rampa)','202049 - Železniční most - nápl. I (rampa)',50.06739,14.41468,'Novoměstská náplavka','Praha 2','kamera',NULL,NULL,'2020-09-02 00:00:00+02',NULL,NULL,'10',NULL,'https://storage.golemio.cz/intenzita-pesi-dopravy/6.png','https://storage.golemio.cz/intenzita-pesi-dopravy/6-map.png','flow_measurements')
38
+ ON CONFLICT DO NOTHING;
39
+ INSERT INTO analytic.pedestrians_locations_list (location_name_plain,location_name,lat,lng,address,city_district,tech,map_picture,gate_picture,measurement_start,measurement_end,id_equiptment,cube_id,lon,map_image,place_image,"table") VALUES
40
+ ('Železniční most - nápl. I (plný profil)','202049 - Železniční most - nápl. I (plný profil)',50.06739,14.41468,'Novoměstská náplavka','Praha 2','kamera',NULL,NULL,'2020-09-02 00:00:00+02',NULL,NULL,'10',NULL,'https://storage.golemio.cz/intenzita-pesi-dopravy/6.png','https://storage.golemio.cz/intenzita-pesi-dopravy/6-map.png','flow_measurements')
41
+ ON CONFLICT DO NOTHING;
42
+
43
+
44
+ CREATE TABLE IF NOT EXISTS analytic.pedestrians_locations_gates (
45
+ direction_id varchar(250) NOT NULL,
46
+ cube_id varchar(250) NOT NULL,
47
+ location_id int4 NOT NULL,
48
+ name varchar(250) NOT NULL,
49
+ direction_type varchar(250) NOT NULL,
50
+ CONSTRAINT equipment_gates_pkey PRIMARY KEY (direction_id, location_id)
51
+ );
52
+
53
+ INSERT INTO analytic.pedestrians_locations_gates (direction_id,cube_id,location_id,"name",direction_type) VALUES
54
+ ('4','0',1,'Směr pod viadukt','Směr 1'),
55
+ ('7','0',1,'Směr Výstaviště','Směr 2'),
56
+ ('2','1',2,'Směr Můstek','Směr 1'),
57
+ ('3','1',2,'Směr Rytířská','Směr 2'),
58
+ ('5','9',7,'Směr Malá strana','Směr 1'),
59
+ ('8','9',7,'Směr Staré město','Směr 2'),
60
+ ('6','10',8,'Náplavka, směr centrum','Směr 1'),
61
+ ('9','10',10,'Rampa, směr centrum','Směr 1'),
62
+ ('10','10',11,'Plný profil, směr centrum','Směr 1'),
63
+ ('11','10',8,'Náplavka, směr Vyšehrad','Směr 2')
64
+ ON CONFLICT DO NOTHING;
65
+ INSERT INTO analytic.pedestrians_locations_gates (direction_id,cube_id,location_id,"name",direction_type) VALUES
66
+ ('13','10',10,'Rampa, směr Vyšehrad','Směr 2'),
67
+ ('15','10',11,'Plný profil, směr Vyšehrad','Směr 2'),
68
+ ('35','11',9,'Plný profil, směr centrum','Směr 1'),
69
+ ('29','11',9,'Plný profil, směr Vyšehrad','Směr 2'),
70
+ ('7','13',6,'Směr Planetarium','Směr 1'),
71
+ ('8','13',6,'Směr Holešovice','Směr 2'),
72
+ ('ecoCounter-103061215','ecoCounter-100061215',3,'Směr pod viadukt','Směr 1'),
73
+ ('ecoCounter-104061215','ecoCounter-100061215',3,'Směr Výstaviště','Směr 2'),
74
+ ('ecoCounter-353245241','ecoCounter-100065230',5,'Směr Planetarium','Směr 1'),
75
+ ('ecoCounter-102065230','ecoCounter-100065230',5,'Směr Planetarium','Směr 1')
76
+ ON CONFLICT DO NOTHING;
77
+ INSERT INTO analytic.pedestrians_locations_gates (direction_id,cube_id,location_id,"name",direction_type) VALUES
78
+ ('ecoCounter-353240728','ecoCounter-100065230',5,'Směr Planetarium','Směr 1'),
79
+ ('ecoCounter-353235722','ecoCounter-100065230',5,'Směr Planetarium','Směr 1'),
80
+ ('ecoCounter-353231243','ecoCounter-100065230',5,'Směr Planetarium','Směr 1'),
81
+ ('ecoCounter-353245239','ecoCounter-100065230',5,'Směr Holešovice','Směr 2'),
82
+ ('ecoCounter-101065230','ecoCounter-100065230',5,'Směr Holešovice','Směr 2'),
83
+ ('ecoCounter-353240727','ecoCounter-100065230',5,'Směr Holešovice','Směr 2'),
84
+ ('ecoCounter-353235721','ecoCounter-100065230',5,'Směr Holešovice','Směr 2'),
85
+ ('ecoCounter-353231242','ecoCounter-100065230',5,'Směr Holešovice','Směr 2'),
86
+ ('dir1','wifi1',4,'Směr Holešovice','Směr 1'),
87
+ ('dir2','wifi1',4,'Směr Planetarium','Směr 2')
88
+ ON CONFLICT DO NOTHING;
89
+
90
+ COMMENT ON TABLE analytic.pedestrians_locations_gates IS '-- tabulka směrů k jednotlivým lokacím, platí to samé co u lokations_list.
91
+ -- nachází se na https://operator.sharepoint.com/:f:/s/Datova_Platforma/EsE5uSdyLzdImWgyrMY8nFcBzwtH7GOr6TXtzNBn3FLIJw?e=fOov5s a jmenuje se directions_list.csv';
92
+
93
+ COMMENT ON TABLE pedestrians_wifi IS '-- tabulka na primární data wifi měření, jsou pouze jako csv na sharepointu https://operator.sharepoint.com/:f:/s/Datova_Platforma/EroMekiKaJdOtMPeF_Q8wPEBlZm5tLKHCgpK13H6hlc0Zg?e=4RbCkT';
94
+
95
+ -- analytic.v_pedestrians_detections_15min source
96
+
97
+ CREATE OR REPLACE VIEW analytic.v_pedestrians_detections_15min
98
+ AS WITH wifi AS (
99
+ SELECT pedestrians_wifi.location_id AS locations_id,
100
+ pedestrians_wifi.direction_id AS directions_id,
101
+ date_trunc('hour'::text, pedestrians_wifi.measured_from) + (date_part('minute'::text, pedestrians_wifi.measured_from)::integer / 15)::double precision * '00:15:00'::interval AS measured_from,
102
+ sum(pedestrians_wifi.value) AS value,
103
+ count(pedestrians_wifi.value) AS count_n
104
+ FROM flow.pedestrians_wifi
105
+ GROUP BY pedestrians_wifi.location_id, pedestrians_wifi.direction_id, (date_trunc('hour'::text, pedestrians_wifi.measured_from) + (date_part('minute'::text, pedestrians_wifi.measured_from)::integer / 15)::double precision * '00:15:00'::interval)
106
+ ), pyro AS (
107
+ SELECT cd.locations_id,
108
+ lg.first_dir AS directions_id,
109
+ to_timestamp((cd.measured_from / 1000)::double precision) AS measured_from,
110
+ sum(cd.value) AS value,
111
+ count(cd.value) AS count_n
112
+ FROM flow.counters_detections cd
113
+ LEFT JOIN ( SELECT pedestrians_locations_gates.direction_id,
114
+ pedestrians_locations_gates.direction_type,
115
+ min(pedestrians_locations_gates.direction_id::text) OVER (PARTITION BY pedestrians_locations_gates.cube_id, pedestrians_locations_gates.direction_type) AS first_dir
116
+ FROM analytic.pedestrians_locations_gates) lg ON cd.directions_id::text = lg.direction_id::text
117
+ WHERE cd.category::text = 'pedestrian'::text AND (cd.directions_id::text IN ( SELECT DISTINCT pedestrians_locations_gates.direction_id
118
+ FROM analytic.pedestrians_locations_gates))
119
+ GROUP BY cd.locations_id, lg.first_dir, (to_timestamp((cd.measured_from / 1000)::double precision))
120
+ ), flow AS (
121
+ SELECT flow_measurements.cube_id::character varying(50) AS location_id,
122
+ flow_measurements.sink_id::character varying(50) AS direction_id,
123
+ date_trunc('hour'::text, to_timestamp((flow_measurements.start_timestamp / 1000)::double precision)) + (date_part('minute'::text, to_timestamp((flow_measurements.start_timestamp / 1000)::double precision))::integer / 15)::double precision * '00:15:00'::interval AS measured_from,
124
+ sum(flow_measurements.value) AS value,
125
+ count(flow_measurements.value) AS count_n
126
+ FROM flow.flow_measurements
127
+ WHERE ((flow_measurements.cube_id::character varying(50)::text, flow_measurements.sink_id::character varying(50)::text) IN ( SELECT DISTINCT pedestrians_locations_gates.cube_id AS location_id,
128
+ pedestrians_locations_gates.direction_id
129
+ FROM analytic.pedestrians_locations_gates)) AND flow_measurements.category::text = 'pedestrian'::text
130
+ GROUP BY (flow_measurements.cube_id::character varying(50)), (flow_measurements.sink_id::character varying(50)), (date_trunc('hour'::text, to_timestamp((flow_measurements.start_timestamp / 1000)::double precision)) + (date_part('minute'::text, to_timestamp((flow_measurements.start_timestamp / 1000)::double precision))::integer / 15)::double precision * '00:15:00'::interval)
131
+ ORDER BY (date_trunc('hour'::text, to_timestamp((flow_measurements.start_timestamp / 1000)::double precision)) + (date_part('minute'::text, to_timestamp((flow_measurements.start_timestamp / 1000)::double precision))::integer / 15)::double precision * '00:15:00'::interval), (flow_measurements.cube_id::character varying(50)), (flow_measurements.sink_id::character varying(50))
132
+ ), measurements AS (
133
+ SELECT wifi.locations_id,
134
+ wifi.directions_id,
135
+ wifi.measured_from,
136
+ wifi.value,
137
+ wifi.count_n
138
+ FROM wifi
139
+ UNION ALL
140
+ SELECT pyro.locations_id,
141
+ pyro.directions_id,
142
+ pyro.measured_from,
143
+ pyro.value,
144
+ pyro.count_n
145
+ FROM pyro
146
+ UNION ALL
147
+ SELECT flow.location_id,
148
+ flow.direction_id,
149
+ flow.measured_from,
150
+ flow.value,
151
+ flow.count_n
152
+ FROM flow
153
+ ), calendar AS (
154
+ SELECT generate_series(min(measurements.measured_from), max(measurements.measured_from), '00:15:00'::interval) AS calendar
155
+ FROM measurements
156
+ ), classes AS (
157
+ SELECT calendar.calendar,
158
+ m_1.location_id,
159
+ m_1.direction_id
160
+ FROM calendar
161
+ JOIN ( SELECT DISTINCT measurements.locations_id::character varying(50) AS location_id,
162
+ measurements.directions_id::character varying(50) AS direction_id
163
+ FROM measurements) m_1 ON true
164
+ )
165
+ SELECT c.calendar,
166
+ date_trunc('hour'::text, c.calendar) AS calendar_hour,
167
+ c.calendar::date AS calendar_date,
168
+ ll.measurement_start,
169
+ COALESCE(ll.measurement_end, now()::date::timestamp with time zone) AS measurement_end,
170
+ c.location_id,
171
+ c.direction_id,
172
+ concat(c.location_id, '-', c.direction_id) AS compound_id,
173
+ COALESCE(m.value, 0::bigint) AS value,
174
+ COALESCE(m.count_n, 0::bigint) AS count_n
175
+ FROM classes c
176
+ LEFT JOIN measurements m ON c.calendar = m.measured_from AND c.location_id::text = m.locations_id::text AND c.direction_id::text = m.directions_id::text
177
+ LEFT JOIN analytic.pedestrians_locations_list ll ON c.location_id::text = ll.cube_id::text
178
+ WHERE c.calendar >= ll.measurement_start AND c.calendar <= COALESCE(ll.measurement_end, now()::date::timestamp with time zone);
179
+
180
+
181
+ -- analytic.v_pedestrians_detections_api source
182
+
183
+ CREATE OR REPLACE VIEW analytic.v_pedestrians_detections_api
184
+ AS WITH wifi AS (
185
+ SELECT pedestrians_wifi.location_id,
186
+ pedestrians_wifi.direction_id,
187
+ date_trunc('hour'::text, pedestrians_wifi.measured_from) + (date_part('minute'::text, pedestrians_wifi.measured_from)::integer / 15)::double precision * '00:15:00'::interval AS measured_from,
188
+ date_trunc('hour'::text, pedestrians_wifi.measured_from) + (date_part('minute'::text, pedestrians_wifi.measured_from)::integer / 15)::double precision * '00:15:00'::interval + '00:15:00'::interval AS measured_to,
189
+ sum(pedestrians_wifi.value) AS value,
190
+ count(pedestrians_wifi.value) AS count_n,
191
+ 3 AS quantity
192
+ FROM flow.pedestrians_wifi
193
+ GROUP BY pedestrians_wifi.location_id, pedestrians_wifi.direction_id, (date_trunc('hour'::text, pedestrians_wifi.measured_from) + (date_part('minute'::text, pedestrians_wifi.measured_from)::integer / 15)::double precision * '00:15:00'::interval), (date_trunc('hour'::text, pedestrians_wifi.measured_from) + (date_part('minute'::text, pedestrians_wifi.measured_from)::integer / 15)::double precision * '00:15:00'::interval + '00:15:00'::interval)
194
+ ), pyro AS (
195
+ SELECT cd.locations_id AS location_id,
196
+ cd.directions_id AS direction_id,
197
+ to_timestamp((cd.measured_from / 1000)::double precision) AS measured_from,
198
+ to_timestamp((cd.measured_from / 1000)::double precision) + '00:15:00'::interval AS measured_to,
199
+ sum(cd.value) AS value,
200
+ count(cd.value) AS count_n,
201
+ 1 AS quantity
202
+ FROM flow.counters_detections cd
203
+ WHERE cd.category::text = 'pedestrian'::text AND (cd.directions_id::text IN ( SELECT DISTINCT pedestrians_directions_api.direction_id
204
+ FROM flow.pedestrians_directions_api))
205
+ GROUP BY cd.locations_id, cd.directions_id, (to_timestamp((cd.measured_from / 1000)::double precision)), (to_timestamp((cd.measured_from / 1000)::double precision) + '00:15:00'::interval)
206
+ ), flow AS (
207
+ SELECT flow_measurements.cube_id::character varying(50) AS location_id,
208
+ flow_measurements.sink_id::character varying(50) AS direction_id,
209
+ date_trunc('hour'::text, to_timestamp((flow_measurements.start_timestamp / 1000)::double precision)) + (date_part('minute'::text, to_timestamp((flow_measurements.start_timestamp / 1000)::double precision))::integer / 15)::double precision * '00:15:00'::interval AS measured_from,
210
+ date_trunc('hour'::text, to_timestamp((flow_measurements.start_timestamp / 1000)::double precision)) + (date_part('minute'::text, to_timestamp((flow_measurements.start_timestamp / 1000)::double precision))::integer / 15)::double precision * '00:15:00'::interval + '00:15:00'::interval AS measured_to,
211
+ sum(flow_measurements.value) AS value,
212
+ count(flow_measurements.value) AS count_n,
213
+ 3 AS quantity
214
+ FROM flow.flow_measurements
215
+ WHERE ((flow_measurements.cube_id::character varying(50)::text, flow_measurements.sink_id::character varying(50)::text) IN ( SELECT DISTINCT pedestrians_directions_api.cube_id AS location_id,
216
+ pedestrians_directions_api.direction_id
217
+ FROM flow.pedestrians_directions_api)) AND flow_measurements.category::text = 'pedestrian'::text
218
+ GROUP BY (flow_measurements.cube_id::character varying(50)), (flow_measurements.sink_id::character varying(50)), (date_trunc('hour'::text, to_timestamp((flow_measurements.start_timestamp / 1000)::double precision)) + (date_part('minute'::text, to_timestamp((flow_measurements.start_timestamp / 1000)::double precision))::integer / 15)::double precision * '00:15:00'::interval), (date_trunc('hour'::text, to_timestamp((flow_measurements.start_timestamp / 1000)::double precision)) + (date_part('minute'::text, to_timestamp((flow_measurements.start_timestamp / 1000)::double precision))::integer / 15)::double precision * '00:15:00'::interval + '00:15:00'::interval)
219
+ ORDER BY (date_trunc('hour'::text, to_timestamp((flow_measurements.start_timestamp / 1000)::double precision)) + (date_part('minute'::text, to_timestamp((flow_measurements.start_timestamp / 1000)::double precision))::integer / 15)::double precision * '00:15:00'::interval), (flow_measurements.cube_id::character varying(50)), (flow_measurements.sink_id::character varying(50))
220
+ ), measurements AS (
221
+ SELECT wifi.location_id,
222
+ wifi.direction_id,
223
+ wifi.measured_from,
224
+ wifi.measured_to,
225
+ wifi.value,
226
+ wifi.count_n,
227
+ wifi.quantity
228
+ FROM wifi
229
+ UNION ALL
230
+ SELECT pyro.location_id,
231
+ pyro.direction_id,
232
+ pyro.measured_from,
233
+ pyro.measured_to,
234
+ pyro.value,
235
+ pyro.count_n,
236
+ pyro.quantity
237
+ FROM pyro
238
+ UNION ALL
239
+ SELECT flow.location_id,
240
+ flow.direction_id,
241
+ flow.measured_from,
242
+ flow.measured_to,
243
+ flow.value,
244
+ flow.count_n,
245
+ flow.quantity
246
+ FROM flow
247
+ )
248
+ SELECT measurements.measured_from,
249
+ measurements.measured_to,
250
+ pda.location_id::character varying(50) AS location_id,
251
+ measurements.direction_id,
252
+ measurements.value,
253
+ CASE
254
+ WHEN (measurements.count_n::numeric / measurements.quantity::numeric) > 1::numeric THEN 1::numeric
255
+ ELSE measurements.count_n::numeric / measurements.quantity::numeric
256
+ END AS quality
257
+ FROM measurements
258
+ LEFT JOIN flow.pedestrians_directions_api pda ON measurements.direction_id::text = pda.direction_id::text;
259
+
260
+
261
+ -- analytic.v_pedestrians_detections_daily source
262
+
263
+ CREATE OR REPLACE VIEW analytic.v_pedestrians_detections_daily
264
+ AS WITH wifi AS (
265
+ SELECT pedestrians_wifi.location_id AS locations_id,
266
+ pedestrians_wifi.direction_id AS directions_id,
267
+ pedestrians_wifi.measured_from::date AS measured_from,
268
+ sum(pedestrians_wifi.value) AS value,
269
+ count(pedestrians_wifi.value) AS count_n,
270
+ count(pedestrians_wifi.value)::numeric / 288::numeric AS quality_ratio
271
+ FROM flow.pedestrians_wifi
272
+ GROUP BY pedestrians_wifi.location_id, pedestrians_wifi.direction_id, (pedestrians_wifi.measured_from::date)
273
+ ), pyro AS (
274
+ SELECT cd.locations_id,
275
+ lg.first_dir AS directions_id,
276
+ to_timestamp((cd.measured_from / 1000)::double precision)::date AS measured_from,
277
+ sum(cd.value) AS value,
278
+ count(cd.value) / count(DISTINCT cd.directions_id) AS count_n,
279
+ count(cd.value)::numeric / 96::numeric / count(DISTINCT cd.directions_id)::numeric AS quality_ratio
280
+ FROM flow.counters_detections cd
281
+ LEFT JOIN ( SELECT pedestrians_locations_gates.direction_id,
282
+ pedestrians_locations_gates.direction_type,
283
+ min(pedestrians_locations_gates.direction_id::text) OVER (PARTITION BY pedestrians_locations_gates.cube_id, pedestrians_locations_gates.direction_type) AS first_dir
284
+ FROM analytic.pedestrians_locations_gates) lg ON cd.directions_id::text = lg.direction_id::text
285
+ WHERE cd.category::text = 'pedestrian'::text AND (cd.directions_id::text IN ( SELECT DISTINCT pedestrians_locations_gates.direction_id
286
+ FROM analytic.pedestrians_locations_gates))
287
+ GROUP BY cd.locations_id, lg.first_dir, (to_timestamp((cd.measured_from / 1000)::double precision)::date)
288
+ ), flow AS (
289
+ SELECT flow_measurements.cube_id::character varying(50) AS location_id,
290
+ flow_measurements.sink_id::character varying(50) AS direction_id,
291
+ to_timestamp((flow_measurements.start_timestamp / 1000)::double precision)::date AS measured_from,
292
+ sum(flow_measurements.value) AS value,
293
+ count(flow_measurements.value) AS count_n,
294
+ count(flow_measurements.value)::numeric / 288::numeric AS quality_ratio
295
+ FROM flow.flow_measurements
296
+ WHERE ((flow_measurements.cube_id::character varying(50)::text, flow_measurements.sink_id::character varying(50)::text) IN ( SELECT DISTINCT pedestrians_locations_gates.cube_id AS location_id,
297
+ pedestrians_locations_gates.direction_id
298
+ FROM analytic.pedestrians_locations_gates)) AND flow_measurements.category::text = 'pedestrian'::text
299
+ GROUP BY (flow_measurements.cube_id::character varying(50)), (flow_measurements.sink_id::character varying(50)), (to_timestamp((flow_measurements.start_timestamp / 1000)::double precision)::date)
300
+ ORDER BY (to_timestamp((flow_measurements.start_timestamp / 1000)::double precision)::date), (flow_measurements.cube_id::character varying(50)) DESC, (flow_measurements.sink_id::character varying(50))
301
+ ), measurements AS (
302
+ SELECT pyro.locations_id,
303
+ pyro.directions_id,
304
+ pyro.measured_from,
305
+ pyro.value,
306
+ pyro.count_n,
307
+ pyro.quality_ratio
308
+ FROM pyro
309
+ UNION ALL
310
+ SELECT flow.location_id,
311
+ flow.direction_id,
312
+ flow.measured_from,
313
+ flow.value,
314
+ flow.count_n,
315
+ flow.quality_ratio
316
+ FROM flow
317
+ UNION ALL
318
+ SELECT wifi.locations_id,
319
+ wifi.directions_id,
320
+ wifi.measured_from,
321
+ wifi.value,
322
+ wifi.count_n,
323
+ wifi.quality_ratio
324
+ FROM wifi
325
+ ), calendar AS (
326
+ SELECT generate_series(min(measurements.measured_from)::timestamp with time zone, max(measurements.measured_from)::timestamp with time zone, '1 day'::interval) AS calendar
327
+ FROM measurements
328
+ ), classes AS (
329
+ SELECT calendar.calendar,
330
+ m_1.location_id,
331
+ m_1.direction_id
332
+ FROM calendar
333
+ JOIN ( SELECT DISTINCT measurements.locations_id::character varying(50) AS location_id,
334
+ measurements.directions_id::character varying(50) AS direction_id
335
+ FROM measurements) m_1 ON true
336
+ )
337
+ SELECT c.calendar,
338
+ c.location_id,
339
+ c.direction_id,
340
+ concat(c.location_id, '-', c.direction_id) AS compound_id,
341
+ COALESCE(m.value, 0::bigint) AS value,
342
+ COALESCE(m.count_n, 0::bigint) AS count_n,
343
+ COALESCE(m.quality_ratio, 0::numeric) AS quality_ratio,
344
+ CASE
345
+ WHEN c.calendar < ll.measurement_start OR c.calendar > ll.measurement_end THEN 4
346
+ WHEN COALESCE(m.quality_ratio, 0::numeric) = 0::numeric THEN 3
347
+ WHEN COALESCE(m.quality_ratio, 0::numeric) < 0.9 THEN 2
348
+ WHEN COALESCE(m.quality_ratio, 0::numeric) > 0.9 AND COALESCE(m.quality_ratio, 0::numeric) < 1::numeric THEN 1
349
+ WHEN COALESCE(m.quality_ratio, 0::numeric) >= 1::numeric THEN 0
350
+ ELSE NULL::integer
351
+ END AS quality_code,
352
+ CASE
353
+ WHEN c.calendar < ll.measurement_start OR c.calendar > ll.measurement_end THEN 'Nenainstalovaná technologie'::text
354
+ WHEN COALESCE(m.quality_ratio, 0::numeric) = 0::numeric THEN 'Bez dat (0%)'::text
355
+ WHEN COALESCE(m.quality_ratio, 0::numeric) < 0.9 THEN 'Částečná data (<90%)'::text
356
+ WHEN COALESCE(m.quality_ratio, 0::numeric) > 0.9 AND COALESCE(m.quality_ratio, 0::numeric) < 1::numeric THEN 'Nekompletní data (>90%)'::text
357
+ WHEN COALESCE(m.quality_ratio, 0::numeric) >= 1::numeric THEN 'Kompletní data (100%)'::text
358
+ ELSE NULL::text
359
+ END AS quality_status
360
+ FROM classes c
361
+ LEFT JOIN measurements m ON c.calendar = m.measured_from AND c.location_id::text = m.locations_id::text AND c.direction_id::text = m.directions_id
362
+ LEFT JOIN analytic.pedestrians_locations_list ll ON c.location_id::text = ll.cube_id::text;
363
+
364
+
365
+ -- analytic.v_pedestrians_flow_quality source
366
+
367
+ CREATE OR REPLACE VIEW analytic.v_pedestrians_flow_quality
368
+ AS WITH timeline_category AS (
369
+ SELECT DISTINCT fs.cube_id,
370
+ fs.id AS sink_id,
371
+ timeline."timestamp"
372
+ FROM flow.flow_sinks fs
373
+ LEFT JOIN ( SELECT generate_series(date_trunc('month'::text, CURRENT_DATE - '180 days'::interval)::timestamp with time zone, date_trunc('hour'::text, CURRENT_DATE::timestamp with time zone), '01:00:00'::interval) AS "timestamp") timeline ON true
374
+ ), base_table AS (
375
+ SELECT date_trunc('hour'::text, to_timestamp((flow_measurements.start_timestamp / 1000)::double precision)) AS start_timestamp,
376
+ flow_measurements.cube_id,
377
+ flow_measurements.sink_id,
378
+ flow_measurements.category,
379
+ count(flow_measurements.cube_id) AS count
380
+ FROM flow.flow_measurements
381
+ WHERE flow_measurements.start_timestamp::double precision >= (1000::double precision * date_part('epoch'::text, CURRENT_DATE - '210 days'::interval))
382
+ GROUP BY (date_trunc('hour'::text, to_timestamp((flow_measurements.start_timestamp / 1000)::double precision))), flow_measurements.cube_id, flow_measurements.sink_id, flow_measurements.category
383
+ ), real_nrow AS (
384
+ SELECT base_table.start_timestamp,
385
+ base_table.cube_id,
386
+ base_table.sink_id,
387
+ sum(base_table.count) AS n_row,
388
+ sum(base_table.count) FILTER (WHERE base_table.category::text = 'pedestrian'::text) AS n_row_pedestrian
389
+ FROM base_table
390
+ GROUP BY base_table.start_timestamp, base_table.cube_id, base_table.sink_id
391
+ ), expected_nrow AS (
392
+ SELECT base_table.cube_id,
393
+ base_table.sink_id,
394
+ count(DISTINCT base_table.category) * 12 AS expected_nrow,
395
+ 12 AS expected_nrow_pedestrian
396
+ FROM base_table
397
+ WHERE base_table.start_timestamp >= (CURRENT_DATE - '30 days'::interval)
398
+ GROUP BY base_table.cube_id, base_table.sink_id
399
+ )
400
+ SELECT t."timestamp",
401
+ date_trunc('month'::text, t."timestamp")::date AS month,
402
+ t.cube_id,
403
+ t.sink_id,
404
+ concat(t.cube_id, ' - ', t.sink_id) AS cube_sink,
405
+ COALESCE(r.n_row, 0::bigint::numeric) AS n_row,
406
+ COALESCE(r.n_row_pedestrian, 0::bigint::numeric) AS n_row_pedestrian,
407
+ er.expected_nrow,
408
+ er.expected_nrow_pedestrian
409
+ FROM timeline_category t
410
+ LEFT JOIN real_nrow r ON t."timestamp" = r.start_timestamp AND t.cube_id = r.cube_id AND t.sink_id = r.sink_id
411
+ LEFT JOIN expected_nrow er ON t.cube_id = er.cube_id AND t.sink_id = er.sink_id;
412
+
413
+ -- analytic.v_flow_quality source
414
+
415
+ DROP VIEW IF EXISTS analytic.v_flow_quality
package/package.json CHANGED
@@ -1,64 +1,64 @@
1
1
  {
2
- "name": "@golemio/flow",
3
- "version": "1.0.8-dev.577679507",
4
- "description": "Golemio Flow Module",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "scripts": {
8
- "build": "rimraf ./dist && ttsc -p ./tsconfig.build.json",
9
- "build-minimal": "run-s 'build --sourceMap false --declaration false'",
10
- "build-watch": "run-s 'build --watch --preserveWatchOutput'",
11
- "pretest": "golemio import-db-data --postgres",
12
- "test": "cross-env NODE_ENV=test TS_NODE_COMPILER='ttypescript' mocha --exit --check-leaks --timeout 120000 -r ts-node/register -r dotenv/config 'test/**/*.test.ts'",
13
- "test-debug": "run-s 'test --inspect-brk=9230'",
14
- "code-coverage": "nyc run-s 'test -r source-map-support/register'",
15
- "generate-docs": "typedoc --out docs/typedoc src",
16
- "lint": "eslint \"{src,test}/**/*.ts\""
17
- },
18
- "keywords": [
19
- "golemio"
20
- ],
21
- "author": "Operator ICT, a.s.",
22
- "license": "MIT",
23
- "repository": {
24
- "type": "git",
25
- "url": "https://gitlab.com/operator-ict/golemio/code/modules/flow"
26
- },
27
- "devDependencies": {
28
- "@commitlint/cli": "^11.0.0",
29
- "@commitlint/config-conventional": "^11.0.0",
30
- "@golemio/cli": "1.2.1",
31
- "@golemio/core": "1.2.13",
32
- "@golemio/db-common": "1.0.1",
33
- "@golemio/eslint-config": "^1.0.2",
34
- "@ovos-media/ts-transform-paths": "^1.7.18-1",
35
- "@types/chai": "4.2.3",
36
- "@types/chai-as-promised": "7.1.2",
37
- "@types/mocha": "^8.2.0",
38
- "@types/node": "^16.11.35",
39
- "@types/sinon": "^9.0.10",
40
- "chai": "4.2.0",
41
- "chai-as-promised": "7.1.1",
42
- "cross-env": "^7.0.3",
43
- "eslint": "^7.17.0",
44
- "husky": "^4.3.7",
45
- "mocha": "^8.2.1",
46
- "npm-run-all": "^4.1.5",
47
- "nyc": "^15.1.0",
48
- "prettier": "^2.2.1",
49
- "pretty-quick": "^3.1.0",
50
- "rimraf": "^3.0.2",
51
- "sinon": "^9.2.3",
52
- "source-map-support": "0.5.19",
53
- "ts-node": "^10.7.0",
54
- "ttypescript": "^1.5.13",
55
- "typedoc": "^0.22.15",
56
- "typescript": "4.6.4"
57
- },
58
- "dependencies": {
59
- "JSONStream": "^1.0.4"
60
- },
61
- "peerDependencies": {
62
- "@golemio/core": "^1.0.0"
63
- }
2
+ "name": "@golemio/flow",
3
+ "version": "1.0.8",
4
+ "description": "Golemio Flow Module",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "rimraf ./dist && ttsc -p ./tsconfig.build.json",
9
+ "build-minimal": "run-s 'build --sourceMap false --declaration false'",
10
+ "build-watch": "run-s 'build --watch --preserveWatchOutput'",
11
+ "pretest": "golemio import-db-data --postgres",
12
+ "test": "cross-env NODE_ENV=test TS_NODE_COMPILER='ttypescript' mocha --exit --check-leaks --timeout 120000 -r ts-node/register -r dotenv/config 'test/**/*.test.ts'",
13
+ "test-debug": "run-s 'test --inspect-brk=9230'",
14
+ "code-coverage": "nyc run-s 'test -r source-map-support/register'",
15
+ "generate-docs": "typedoc --out docs/typedoc src",
16
+ "lint": "eslint \"{src,test}/**/*.ts\""
17
+ },
18
+ "keywords": [
19
+ "golemio"
20
+ ],
21
+ "author": "Operator ICT, a.s.",
22
+ "license": "MIT",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://gitlab.com/operator-ict/golemio/code/modules/flow"
26
+ },
27
+ "devDependencies": {
28
+ "@commitlint/cli": "^11.0.0",
29
+ "@commitlint/config-conventional": "^11.0.0",
30
+ "@golemio/cli": "1.3.0",
31
+ "@golemio/core": "1.2.14",
32
+ "@golemio/db-common": "1.0.1",
33
+ "@golemio/eslint-config": "^1.0.2",
34
+ "@ovos-media/ts-transform-paths": "^1.7.18-1",
35
+ "@types/chai": "4.2.3",
36
+ "@types/chai-as-promised": "7.1.2",
37
+ "@types/mocha": "^8.2.0",
38
+ "@types/node": "^16.11.35",
39
+ "@types/sinon": "^9.0.10",
40
+ "chai": "4.2.0",
41
+ "chai-as-promised": "7.1.1",
42
+ "cross-env": "^7.0.3",
43
+ "eslint": "^7.17.0",
44
+ "husky": "^4.3.7",
45
+ "mocha": "^8.2.1",
46
+ "npm-run-all": "^4.1.5",
47
+ "nyc": "^15.1.0",
48
+ "prettier": "^2.2.1",
49
+ "pretty-quick": "^3.1.0",
50
+ "rimraf": "^3.0.2",
51
+ "sinon": "^9.2.3",
52
+ "source-map-support": "0.5.19",
53
+ "ts-node": "^10.7.0",
54
+ "ttypescript": "^1.5.13",
55
+ "typedoc": "^0.22.15",
56
+ "typescript": "4.6.4"
57
+ },
58
+ "dependencies": {
59
+ "JSONStream": "^1.0.4"
60
+ },
61
+ "peerDependencies": {
62
+ "@golemio/core": "^1.0.0"
63
+ }
64
64
  }