@golemio/rush-hour-aggregation 1.0.0-dev.520603218

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.
Files changed (110) hide show
  1. package/LICENSE +11 -0
  2. package/README.md +47 -0
  3. package/db/migrations/postgresql/.config.json +3 -0
  4. package/db/migrations/postgresql/20220405102916-prahaZasekanaAggregation.js +53 -0
  5. package/db/migrations/postgresql/package.json +3 -0
  6. package/db/migrations/postgresql/sqls/20220405102916-prahaZasekanaAggregation-down.sql +6 -0
  7. package/db/migrations/postgresql/sqls/20220405102916-prahaZasekanaAggregation-up.sql +64 -0
  8. package/db/migrations/postgresql/sqls/package.json +3 -0
  9. package/dist/index.d.ts +1 -0
  10. package/dist/index.js +25 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/integration-engine/AggregationWorker.d.ts +16 -0
  13. package/dist/integration-engine/AggregationWorker.js +83 -0
  14. package/dist/integration-engine/AggregationWorker.js.map +1 -0
  15. package/dist/integration-engine/WorkerHelper.d.ts +9 -0
  16. package/dist/integration-engine/WorkerHelper.js +52 -0
  17. package/dist/integration-engine/WorkerHelper.js.map +1 -0
  18. package/dist/integration-engine/business/AggregationTask.d.ts +11 -0
  19. package/dist/integration-engine/business/AggregationTask.js +18 -0
  20. package/dist/integration-engine/business/AggregationTask.js.map +1 -0
  21. package/dist/integration-engine/business/interfaces/IAggregationTask.d.ts +6 -0
  22. package/dist/integration-engine/business/interfaces/IAggregationTask.js +3 -0
  23. package/dist/integration-engine/business/interfaces/IAggregationTask.js.map +1 -0
  24. package/dist/integration-engine/dataAccess/AggregationRepository.d.ts +13 -0
  25. package/dist/integration-engine/dataAccess/AggregationRepository.js +60 -0
  26. package/dist/integration-engine/dataAccess/AggregationRepository.js.map +1 -0
  27. package/dist/integration-engine/dataAccess/FcdEventsRepository.d.ts +6 -0
  28. package/dist/integration-engine/dataAccess/FcdEventsRepository.js +38 -0
  29. package/dist/integration-engine/dataAccess/FcdEventsRepository.js.map +1 -0
  30. package/dist/integration-engine/dataAccess/NdicEventRepository.d.ts +6 -0
  31. package/dist/integration-engine/dataAccess/NdicEventRepository.js +38 -0
  32. package/dist/integration-engine/dataAccess/NdicEventRepository.js.map +1 -0
  33. package/dist/integration-engine/dataAccess/TskEventsRepository.d.ts +6 -0
  34. package/dist/integration-engine/dataAccess/TskEventsRepository.js +38 -0
  35. package/dist/integration-engine/dataAccess/TskEventsRepository.js.map +1 -0
  36. package/dist/integration-engine/dataAccess/WazeJamsRepository.d.ts +6 -0
  37. package/dist/integration-engine/dataAccess/WazeJamsRepository.js +40 -0
  38. package/dist/integration-engine/dataAccess/WazeJamsRepository.js.map +1 -0
  39. package/dist/integration-engine/dataAccess/WazeReconstructionsRepository.d.ts +6 -0
  40. package/dist/integration-engine/dataAccess/WazeReconstructionsRepository.js +38 -0
  41. package/dist/integration-engine/dataAccess/WazeReconstructionsRepository.js.map +1 -0
  42. package/dist/integration-engine/index.d.ts +2 -0
  43. package/dist/integration-engine/index.js +16 -0
  44. package/dist/integration-engine/index.js.map +1 -0
  45. package/dist/integration-engine/queueDefinitions.d.ts +3 -0
  46. package/dist/integration-engine/queueDefinitions.js +25 -0
  47. package/dist/integration-engine/queueDefinitions.js.map +1 -0
  48. package/dist/integration-engine/service/AggregationFactory.d.ts +7 -0
  49. package/dist/integration-engine/service/AggregationFactory.js +30 -0
  50. package/dist/integration-engine/service/AggregationFactory.js.map +1 -0
  51. package/dist/integration-engine/service/aggregators/AbstractAggregator.d.ts +8 -0
  52. package/dist/integration-engine/service/aggregators/AbstractAggregator.js +27 -0
  53. package/dist/integration-engine/service/aggregators/AbstractAggregator.js.map +1 -0
  54. package/dist/integration-engine/service/aggregators/FcdEventsAggregator.d.ts +12 -0
  55. package/dist/integration-engine/service/aggregators/FcdEventsAggregator.js +50 -0
  56. package/dist/integration-engine/service/aggregators/FcdEventsAggregator.js.map +1 -0
  57. package/dist/integration-engine/service/aggregators/NdicEventsAggregator.d.ts +11 -0
  58. package/dist/integration-engine/service/aggregators/NdicEventsAggregator.js +57 -0
  59. package/dist/integration-engine/service/aggregators/NdicEventsAggregator.js.map +1 -0
  60. package/dist/integration-engine/service/aggregators/TskEventsAggregator.d.ts +11 -0
  61. package/dist/integration-engine/service/aggregators/TskEventsAggregator.js +49 -0
  62. package/dist/integration-engine/service/aggregators/TskEventsAggregator.js.map +1 -0
  63. package/dist/integration-engine/service/aggregators/WazeJamsAggregator.d.ts +10 -0
  64. package/dist/integration-engine/service/aggregators/WazeJamsAggregator.js +50 -0
  65. package/dist/integration-engine/service/aggregators/WazeJamsAggregator.js.map +1 -0
  66. package/dist/integration-engine/service/aggregators/WazeReconstructionsAggregator.d.ts +10 -0
  67. package/dist/integration-engine/service/aggregators/WazeReconstructionsAggregator.js +49 -0
  68. package/dist/integration-engine/service/aggregators/WazeReconstructionsAggregator.js.map +1 -0
  69. package/dist/schema-definitions/helpers/AggregationTaskType.d.ts +7 -0
  70. package/dist/schema-definitions/helpers/AggregationTaskType.js +12 -0
  71. package/dist/schema-definitions/helpers/AggregationTaskType.js.map +1 -0
  72. package/dist/schema-definitions/sequelize-models/FcdEvents.d.ts +14 -0
  73. package/dist/schema-definitions/sequelize-models/FcdEvents.js +33 -0
  74. package/dist/schema-definitions/sequelize-models/FcdEvents.js.map +1 -0
  75. package/dist/schema-definitions/sequelize-models/NdicEvent.d.ts +20 -0
  76. package/dist/schema-definitions/sequelize-models/NdicEvent.js +44 -0
  77. package/dist/schema-definitions/sequelize-models/NdicEvent.js.map +1 -0
  78. package/dist/schema-definitions/sequelize-models/PrahaZasekanaInfo.d.ts +10 -0
  79. package/dist/schema-definitions/sequelize-models/PrahaZasekanaInfo.js +15 -0
  80. package/dist/schema-definitions/sequelize-models/PrahaZasekanaInfo.js.map +1 -0
  81. package/dist/schema-definitions/sequelize-models/TskEvent.d.ts +12 -0
  82. package/dist/schema-definitions/sequelize-models/TskEvent.js +31 -0
  83. package/dist/schema-definitions/sequelize-models/TskEvent.js.map +1 -0
  84. package/dist/schema-definitions/sequelize-models/WazeJams.d.ts +14 -0
  85. package/dist/schema-definitions/sequelize-models/WazeJams.js +35 -0
  86. package/dist/schema-definitions/sequelize-models/WazeJams.js.map +1 -0
  87. package/dist/schema-definitions/sequelize-models/WazeReconstructions.d.ts +13 -0
  88. package/dist/schema-definitions/sequelize-models/WazeReconstructions.js +33 -0
  89. package/dist/schema-definitions/sequelize-models/WazeReconstructions.js.map +1 -0
  90. package/dist/schema-definitions/sequelize-models/interfaces/IFcdEvent.d.ts +8 -0
  91. package/dist/schema-definitions/sequelize-models/interfaces/IFcdEvent.js +3 -0
  92. package/dist/schema-definitions/sequelize-models/interfaces/IFcdEvent.js.map +1 -0
  93. package/dist/schema-definitions/sequelize-models/interfaces/INdicEvent.d.ts +15 -0
  94. package/dist/schema-definitions/sequelize-models/interfaces/INdicEvent.js +3 -0
  95. package/dist/schema-definitions/sequelize-models/interfaces/INdicEvent.js.map +1 -0
  96. package/dist/schema-definitions/sequelize-models/interfaces/ITskEvent.d.ts +7 -0
  97. package/dist/schema-definitions/sequelize-models/interfaces/ITskEvent.js +3 -0
  98. package/dist/schema-definitions/sequelize-models/interfaces/ITskEvent.js.map +1 -0
  99. package/dist/schema-definitions/sequelize-models/interfaces/IWazeJams.d.ts +9 -0
  100. package/dist/schema-definitions/sequelize-models/interfaces/IWazeJams.js +3 -0
  101. package/dist/schema-definitions/sequelize-models/interfaces/IWazeJams.js.map +1 -0
  102. package/dist/schema-definitions/sequelize-models/interfaces/IWazeReconstructions.d.ts +8 -0
  103. package/dist/schema-definitions/sequelize-models/interfaces/IWazeReconstructions.js +3 -0
  104. package/dist/schema-definitions/sequelize-models/interfaces/IWazeReconstructions.js.map +1 -0
  105. package/package.json +63 -0
  106. package/templates/sqlQueries/FcdEvents.sql +19 -0
  107. package/templates/sqlQueries/NdicEventsFull.sql +85 -0
  108. package/templates/sqlQueries/TskEvents.sql +98 -0
  109. package/templates/sqlQueries/WazeJamsAggregation.sql +27 -0
  110. package/templates/sqlQueries/WazeReconstructionsAggregation.sql +27 -0
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@golemio/rush-hour-aggregation",
3
+ "version": "1.0.0-dev.520603218",
4
+ "description": "Rush hour data agregation for Praha Zasekana project",
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
+ "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'",
12
+ "test-debug": "run-s 'test --inspect-brk=9230'",
13
+ "code-coverage": "nyc run-s 'test -r source-map-support/register'",
14
+ "generate-docs": "typedoc --out docs/typedoc src",
15
+ "lint": "eslint \"{src,test}/**/*.ts\""
16
+ },
17
+ "keywords": [
18
+ "golemio"
19
+ ],
20
+ "author": "Operator ICT, a.s.",
21
+ "license": "MIT",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "https://gitlab.com/operator-ict/golemio/code/modules/rush-hour-aggregation"
25
+ },
26
+ "devDependencies": {
27
+ "@commitlint/cli": "^11.0.0",
28
+ "@commitlint/config-conventional": "^11.0.0",
29
+ "@golemio/cli": "1.2.1",
30
+ "@golemio/core": "1.2.7-dev.520392044",
31
+ "@golemio/eslint-config": "^1.1.0",
32
+ "@types/amqplib": "^0.5.17",
33
+ "@types/chai": "4.2.3",
34
+ "@types/chai-as-promised": "7.1.2",
35
+ "@types/geojson": "^7946.0.8",
36
+ "@types/mocha": "^9.1.0",
37
+ "@types/node": "^14.14.20",
38
+ "@types/sinon": "^9.0.10",
39
+ "@zerollup/ts-transform-paths": "^1.7.18",
40
+ "chai": "4.2.0",
41
+ "chai-as-promised": "7.1.1",
42
+ "cross-env": "^7.0.3",
43
+ "dotenv": "^16.0.0",
44
+ "eslint": "^8.1.1",
45
+ "husky": "^7.0.4",
46
+ "mocha": "^9.1.2",
47
+ "npm-run-all": "^4.1.5",
48
+ "nyc": "^15.1.0",
49
+ "prettier": "^2.5.1",
50
+ "pretty-quick": "^3.1.3",
51
+ "rimraf": "^3.0.2",
52
+ "sinon": "^9.2.3",
53
+ "source-map-support": "0.5.19",
54
+ "ts-node": "^9.1.1",
55
+ "ttypescript": "^1.5.13",
56
+ "typedoc": "^0.22.15",
57
+ "typescript": "4.4.4"
58
+ },
59
+ "peerDependencies": {
60
+ "@golemio/core": "^1.0.0"
61
+ },
62
+ "dependencies": {}
63
+ }
@@ -0,0 +1,19 @@
1
+ select
2
+ a.source_identification,
3
+ date_part('epoch'::text, date_trunc('minute'::text, a.measurement_or_calculation_time)) * 1000::double precision as measured_at,
4
+ g.oriented_route,
5
+ a.traffic_level,
6
+ json_build_object(
7
+ 'data_quality', a.data_quality,
8
+ 'input_values', a.input_values,
9
+ 'average_vehicle_speed', a.average_vehicle_speed,
10
+ 'travel_time', a.travel_time,
11
+ 'free_flow_travel_time', a.free_flow_travel_time,
12
+ 'free_flow_speed', a.free_flow_speed
13
+ ) as properties
14
+ from
15
+ fcd_traff_params_part a
16
+ join praha_zasekana.fcd_geos_90 g on
17
+ a.source_identification::text = g.source_identification::text
18
+ where
19
+ a.measurement_or_calculation_time between $from and $to
@@ -0,0 +1,85 @@
1
+ select
2
+ t.situation_id,
3
+ t.situation_record_type,
4
+ t.situation_version_time,
5
+ t.measured_at,
6
+ t.geom as geom_origin,
7
+ st_centroid(t.geom) as geom_centroid,
8
+ st_startpoint(t.geom) as geom_startpoint,
9
+ st_endpoint(t.geom) as geom_endpoint,
10
+ t.situation_urgency,
11
+ case
12
+ when t.situation_record_type::text = 'AbnormalTraffic'::text then 'ndic_congestion'::text
13
+ when t.situation_record_type::text = 'Accident'::text then 'ndic_accident'::text
14
+ when t.situation_record_type::text = 'CarParks'::text then 'ndic_parkandride'::text
15
+ when t.situation_record_type::text = 'ConstructionWorks'::text then 'ndic_reconstruction'::text
16
+ when t.situation_record_type::text = 'DisturbanceActivity'::text then 'ndic_congestion'::text
17
+ when t.situation_record_type::text = 'GeneralObstruction'::text then
18
+ case
19
+ when regexp_match(t.general_public_comment, 'nehoda'::text) is not null then 'ndic_accident'::text
20
+ else 'ndic_warning'::text
21
+ end
22
+ when t.situation_record_type::text = 'MaintenanceWorks'::text then 'ndic_reconstruction'::text
23
+ when t.situation_record_type::text = 'RoadOrCarriagewayOrLaneManagement'::text then 'ndic_reconstruction'::text
24
+ when t.situation_record_type::text = 'WeatherRelatedRoadConditions'::text then 'ndic_weather'::text
25
+ else 'ndic_warning'::text
26
+ end as geom_symbol_iconimage,
27
+ case
28
+ when t.situation_record_type::text = 'AbnormalTraffic'::text then 'ndic_line_arrowed'::text
29
+ when t.situation_record_type::text = 'DisturbanceActivity'::text then 'ndic_line_arrowed'::text
30
+ else 'ndic_line_simple'::text
31
+ end as geom_line_pattern,
32
+ json_build_object(
33
+ 'gs', t.gs,
34
+ 'general_public_comment', t.general_public_comment,
35
+ 'situation_version', t.situation_version,
36
+ 'situation_id', t.situation_id,
37
+ 'situation_record_type', t.situation_record_type,
38
+ 'situation_record_creation_time', t.situation_record_creation_time,
39
+ 'situation_version_time', t.situation_version_time,
40
+ 'situation_urgency', t.situation_urgency,
41
+ 'source', t.source,
42
+ 'geom_length_m', round(st_length(t.geom::geography))
43
+ ) as properties
44
+ from
45
+ (
46
+ select
47
+ (date_part('epoch'::text, gs.gs) * 1000::double precision)::bigint as measured_at,
48
+ gs.gs,
49
+ nti.general_public_comment,
50
+ nti.situation_version,
51
+ nti.situation_id,
52
+ nti.situation_record_type,
53
+ nti.situation_record_creation_time,
54
+ nti.situation_version_time,
55
+ nti.situation_urgency,
56
+ nti.source,
57
+ st_transform(st_setsrid(st_makeline(st_point(((((nti.global_network_linear -> 'startPoint'::text) -> 'sjtskPointCoordinates'::text) ->> 'sjtskX'::text)::numeric)::double precision,
58
+ ((((nti.global_network_linear -> 'startPoint'::text) -> 'sjtskPointCoordinates'::text) ->> 'sjtskY'::text)::numeric)::double precision),
59
+ st_point(((((nti.global_network_linear -> 'endPoint'::text) -> 'sjtskPointCoordinates'::text) ->> 'sjtskX'::text)::numeric)::double precision,
60
+ ((((nti.global_network_linear -> 'endPoint'::text) -> 'sjtskPointCoordinates'::text) ->> 'sjtskY'::text)::numeric)::double precision)),
61
+ 5514),
62
+ 4326) as geom
63
+ from
64
+ (select
65
+ gs_1.gs
66
+ from
67
+ generate_series(
68
+ to_timestamp(((date_part('epoch'::text, (timestamp with time zone :from)) / (60 * 30)::double precision)::bigint * 60 * 30)::double precision),
69
+ to_timestamp(((date_part('epoch'::text, (timestamp with time zone :to)) / (60 * 30)::double precision)::bigint * 60 * 30)::double precision),
70
+ '00:30:00'::interval) gs_1(gs)
71
+ ) gs
72
+ join ndic_traffic_info nti on
73
+ gs.gs >= nti.validity_overall_start_time
74
+ and gs.gs <= nti.validity_overall_end_time
75
+ and nti.situation_version::text = ((
76
+ select
77
+ max(nti2.situation_version::text) as max
78
+ from
79
+ ndic_traffic_info nti2
80
+ where
81
+ nti2.situation_id::text = nti.situation_id::text
82
+ and nti2.situation_record_type::text = nti.situation_record_type::text
83
+ and nti2.situation_version::text = nti.situation_version::text
84
+ and nti2.source::text = nti.source::text
85
+ and nti.situation_version_time <= gs.gs))) t
@@ -0,0 +1,98 @@
1
+ select
2
+ agg.measured_at,
3
+ agg.geom,
4
+ agg.sum,
5
+ json_build_object(
6
+ 'sum', agg.sum,
7
+ 'street', agg.street,
8
+ 'related_details', agg.related_details
9
+ ) as properties
10
+ from (
11
+ with kalendar as (
12
+ select
13
+ a.a
14
+ from
15
+ generate_series(
16
+ DATE_TRUNC('minute',(timestamp with time zone :from)) - make_interval(mins => mod(EXTRACT(mins FROM timestamp with time zone :from)::integer, 5)::integer),
17
+ DATE_TRUNC('minute',(timestamp with time zone :to)),
18
+ '00:05:00'::interval
19
+ ) a(a)
20
+ ),
21
+ ciselnik as (
22
+ select distinct
23
+ tsk_std.latitude,
24
+ tsk_std.longitude,
25
+ ((tsk_std.street::text || '('::text) || tsk_std.segment::text) || ')'::text as lokace,
26
+ st_setsrid(st_makepoint(tsk_std.longitude, tsk_std.latitude), 4326) as geom
27
+ from
28
+ tsk_std
29
+ where
30
+ tsk_std.latitude is not null and tsk_std.longitude is not null
31
+ ),
32
+ sdata as (
33
+ select
34
+ kalendar_1.a as time_5min,
35
+ tsk_std.latitude,
36
+ tsk_std.longitude,
37
+ mes.detector_id,
38
+ mes.class_id,
39
+ mes.measurement_type,
40
+ mes.value
41
+ from
42
+ kalendar kalendar_1
43
+ cross join tsk_std
44
+ left join (
45
+ select
46
+ measured_from,
47
+ measured_to,
48
+ detector_id,
49
+ class_id,
50
+ measurement_type,
51
+ value
52
+ from tsk_std_measurements
53
+ where
54
+ measured_from >= (date_part('epoch'::text, (timestamp with time zone :from))::bigint * 1000)
55
+ and measured_to <= (date_part('epoch'::text, (timestamp with time zone :to))::bigint * 1000)
56
+ ) mes on
57
+ (date_part('epoch'::text, kalendar_1.a)::bigint * 1000) >= mes.measured_from
58
+ and (date_part('epoch'::text, kalendar_1.a)::bigint * 1000) <= mes.measured_to
59
+ and tsk_std.id::text = mes.detector_id::text
60
+ where
61
+ tsk_std.latitude is not null
62
+ and tsk_std.longitude is not null
63
+ ) select
64
+ date_part('epoch'::text, kalendar.a::timestamp without time zone) * 1000::double precision as measured_at,
65
+ ciselnik.geom,
66
+ case
67
+ when sum(
68
+ case
69
+ when sdata.measurement_type::text = 'count'::text and sdata.class_id = 1 and sdata.value is not null then 1
70
+ else 0
71
+ end) = 0 then null::bigint
72
+ else sum(
73
+ case
74
+ when sdata.measurement_type::text = 'count'::text and sdata.class_id = 1 then sdata.value
75
+ else 0
76
+ end)
77
+ end as sum,
78
+ ciselnik.lokace as street,
79
+ coalesce(jsonb_agg(json_build_object('detector_id', sdata.detector_id, 'measurement_type', sdata.measurement_type, 'class_id', sdata.class_id, 'class_type', cls.class_type, 'value', sdata.value)) filter (where sdata.value is not null), '[]'::jsonb) as related_details
80
+ from
81
+ ciselnik
82
+ cross join kalendar
83
+ left join sdata on
84
+ ciselnik.latitude = sdata.latitude
85
+ and ciselnik.longitude = sdata.longitude
86
+ and kalendar.a = sdata.time_5min
87
+ and sdata.value is not null
88
+ left join tsk_std_class_types cls on
89
+ cls.id = sdata.class_id
90
+ group by
91
+ ciselnik.latitude,
92
+ ciselnik.longitude,
93
+ ciselnik.lokace,
94
+ kalendar.a,
95
+ ciselnik.geom
96
+ order by
97
+ ciselnik.lokace
98
+ ) agg
@@ -0,0 +1,27 @@
1
+ select
2
+ w.id,
3
+ (round(w.downloaded_at::numeric / 120000.0) * 120000::numeric)::bigint as measured_at,
4
+ st_geomfromtext(concat('LINESTRING(', regexp_replace(replace(w.line::text, ', "y"'::text, ' '::text), '[{"xy:\[\]}]'::text, ''::text, 'g'::text), ')'),
5
+ 4326) as geom_origin,
6
+ st_startpoint(st_geomfromtext(concat('LINESTRING(', regexp_replace(replace(w.line::text, ', "y"'::text, ' '::text), '[{"xy:\[\]}]'::text, ''::text, 'g'::text), ')'),
7
+ 4326)) as geom_startpoint,
8
+ concat('level', w.level) as traffic_level,
9
+ json_build_object(
10
+ 'uuid', w.uuid,
11
+ 'average_vehicle_speed', round(w.speed_kmh::double precision)::integer
12
+ ) as properties
13
+ from
14
+ (
15
+ select
16
+ wazeccp_jams.id,
17
+ wazeccp_jams.downloaded_at,
18
+ wazeccp_jams.line,
19
+ wazeccp_jams.level,
20
+ wazeccp_jams.uuid,
21
+ wazeccp_jams.speed_kmh
22
+ from
23
+ wazeccp_jams
24
+ where wazeccp_jams.downloaded_at between $from and $to
25
+ ) w
26
+ where
27
+ w.level <> 5
@@ -0,0 +1,27 @@
1
+ select
2
+ w.id,
3
+ (round(w.downloaded_at::numeric / 120000.0) * 120000::numeric)::bigint as measured_at,
4
+ st_geomfromtext(concat('LINESTRING(', regexp_replace(replace(w.line::text, ', "y"'::text, ' '::text), '[{"xy:\[\]}]'::text, ''::text, 'g'::text), ')'),
5
+ 4326) as geom_origin,
6
+ st_startpoint(st_geomfromtext(concat('LINESTRING(', regexp_replace(replace(w.line::text, ', "y"'::text, ' '::text), '[{"xy:\[\]}]'::text, ''::text, 'g'::text), ')'),
7
+ 4326)) as geom_startpoint,
8
+ json_build_object(
9
+ 'uuid', w.uuid,
10
+ 'average_vehicle_speed', round(w.speed_kmh::double precision)::integer,
11
+ 'traffic_level', concat('level', w.level)
12
+ ) as properties
13
+ from
14
+ (
15
+ select
16
+ wazeccp_jams.id,
17
+ wazeccp_jams.downloaded_at,
18
+ wazeccp_jams.line,
19
+ wazeccp_jams.level,
20
+ wazeccp_jams.uuid,
21
+ wazeccp_jams.speed_kmh
22
+ from
23
+ wazeccp_jams
24
+ where
25
+ wazeccp_jams.downloaded_at between $from and $to) w
26
+ where
27
+ w.level = 5