@golemio/pid 6.4.0 → 6.4.1-dev.3054859807

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 (89) hide show
  1. package/db/example/00_clear_test_data.sql +1 -0
  2. package/db/example/24_jis_delayed_segments.sql +142 -0
  3. package/db/migrations/postgresql/20261027100000-jis-delayed-segments.js +16 -0
  4. package/db/migrations/postgresql/sqls/20250127134438-departure-additional-indexes-down.sql +20 -2
  5. package/db/migrations/postgresql/sqls/20261027100000-jis-delayed-segments-down.sql +17 -0
  6. package/db/migrations/postgresql/sqls/20261027100000-jis-delayed-segments-up.sql +42 -0
  7. package/dist/integration-engine/jis/datasources/JISDelayedSegmentsDataSourceFactory.d.ts +9 -0
  8. package/dist/integration-engine/jis/datasources/JISDelayedSegmentsDataSourceFactory.js +54 -0
  9. package/dist/integration-engine/jis/datasources/JISDelayedSegmentsDataSourceFactory.js.map +1 -0
  10. package/dist/integration-engine/jis/ioc/Di.js +10 -0
  11. package/dist/integration-engine/jis/ioc/Di.js.map +1 -1
  12. package/dist/integration-engine/jis/ioc/JISContainerToken.d.ts +5 -0
  13. package/dist/integration-engine/jis/ioc/JISContainerToken.js +5 -0
  14. package/dist/integration-engine/jis/ioc/JISContainerToken.js.map +1 -1
  15. package/dist/integration-engine/jis/repositories/JISDelayedSegmentEnrichmentRepository.d.ts +14 -0
  16. package/dist/integration-engine/jis/repositories/JISDelayedSegmentEnrichmentRepository.js +69 -0
  17. package/dist/integration-engine/jis/repositories/JISDelayedSegmentEnrichmentRepository.js.map +1 -0
  18. package/dist/integration-engine/jis/repositories/JISDelayedSegmentsRepository.d.ts +23 -0
  19. package/dist/integration-engine/jis/repositories/JISDelayedSegmentsRepository.js +73 -0
  20. package/dist/integration-engine/jis/repositories/JISDelayedSegmentsRepository.js.map +1 -0
  21. package/dist/integration-engine/jis/repositories/helpers/JISDelayedSegmentEnrichmentQuery.d.ts +13 -0
  22. package/dist/integration-engine/jis/repositories/helpers/JISDelayedSegmentEnrichmentQuery.js +266 -0
  23. package/dist/integration-engine/jis/repositories/helpers/JISDelayedSegmentEnrichmentQuery.js.map +1 -0
  24. package/dist/integration-engine/jis/repositories/interfaces/IJISDelayedSegmentEnrichmentParams.d.ts +23 -0
  25. package/dist/integration-engine/jis/repositories/interfaces/IJISDelayedSegmentEnrichmentParams.js +2 -0
  26. package/dist/integration-engine/jis/repositories/interfaces/IJISDelayedSegmentEnrichmentParams.js.map +1 -0
  27. package/dist/integration-engine/jis/services/JISDelayedSegmentsDataService.d.ts +38 -0
  28. package/dist/integration-engine/jis/services/JISDelayedSegmentsDataService.js +174 -0
  29. package/dist/integration-engine/jis/services/JISDelayedSegmentsDataService.js.map +1 -0
  30. package/dist/integration-engine/jis/workers/JISWorker.js +1 -0
  31. package/dist/integration-engine/jis/workers/JISWorker.js.map +1 -1
  32. package/dist/integration-engine/jis/workers/tasks/RefreshDelayedSegmentsTask.d.ts +15 -0
  33. package/dist/integration-engine/jis/workers/tasks/RefreshDelayedSegmentsTask.js +55 -0
  34. package/dist/integration-engine/jis/workers/tasks/RefreshDelayedSegmentsTask.js.map +1 -0
  35. package/dist/integration-engine/vehicle-positions/workers/runs/helpers/TramMessageFilter.d.ts +2 -0
  36. package/dist/integration-engine/vehicle-positions/workers/runs/helpers/TramMessageFilter.js +16 -0
  37. package/dist/integration-engine/vehicle-positions/workers/runs/helpers/TramMessageFilter.js.map +1 -1
  38. package/dist/output-gateway/jis/controllers/v1/V1DelayedSegmentsController.d.ts +9 -0
  39. package/dist/output-gateway/jis/controllers/v1/V1DelayedSegmentsController.js +54 -0
  40. package/dist/output-gateway/jis/controllers/v1/V1DelayedSegmentsController.js.map +1 -0
  41. package/dist/output-gateway/jis/data-access/JISDelayedSegmentsRepository.d.ts +14 -0
  42. package/dist/output-gateway/jis/data-access/JISDelayedSegmentsRepository.js +56 -0
  43. package/dist/output-gateway/jis/data-access/JISDelayedSegmentsRepository.js.map +1 -0
  44. package/dist/output-gateway/jis/domain/IJISDelayedSegmentDto.d.ts +12 -0
  45. package/dist/output-gateway/jis/domain/IJISDelayedSegmentDto.js +2 -0
  46. package/dist/output-gateway/jis/domain/IJISDelayedSegmentDto.js.map +1 -0
  47. package/dist/output-gateway/jis/dto/interfaces/IDelayedSegmentsQueryDto.d.ts +5 -0
  48. package/dist/output-gateway/jis/dto/interfaces/IDelayedSegmentsQueryDto.js +2 -0
  49. package/dist/output-gateway/jis/dto/interfaces/IDelayedSegmentsQueryDto.js.map +1 -0
  50. package/dist/output-gateway/jis/helpers/JISDelayedSegmentInfoPanelStopsFilter.d.ts +8 -0
  51. package/dist/output-gateway/jis/helpers/JISDelayedSegmentInfoPanelStopsFilter.js +13 -0
  52. package/dist/output-gateway/jis/helpers/JISDelayedSegmentInfoPanelStopsFilter.js.map +1 -0
  53. package/dist/output-gateway/jis/ioc/Di.js +6 -0
  54. package/dist/output-gateway/jis/ioc/Di.js.map +1 -1
  55. package/dist/output-gateway/jis/ioc/OgJisToken.d.ts +3 -0
  56. package/dist/output-gateway/jis/ioc/OgJisToken.js +3 -0
  57. package/dist/output-gateway/jis/ioc/OgJisToken.js.map +1 -1
  58. package/dist/output-gateway/jis/routers/v1/V1JISRouter.d.ts +2 -0
  59. package/dist/output-gateway/jis/routers/v1/V1JISRouter.js +9 -0
  60. package/dist/output-gateway/jis/routers/v1/V1JISRouter.js.map +1 -1
  61. package/dist/output-gateway/jis/transformations/JISDelayedSegmentsTransformation.d.ts +7 -0
  62. package/dist/output-gateway/jis/transformations/JISDelayedSegmentsTransformation.js +32 -0
  63. package/dist/output-gateway/jis/transformations/JISDelayedSegmentsTransformation.js.map +1 -0
  64. package/dist/schema-definitions/jis/datasources/MapaPidDelayShapesJsonSchema.d.ts +3 -0
  65. package/dist/schema-definitions/jis/datasources/MapaPidDelayShapesJsonSchema.js +16 -0
  66. package/dist/schema-definitions/jis/datasources/MapaPidDelayShapesJsonSchema.js.map +1 -0
  67. package/dist/schema-definitions/jis/datasources/interfaces/IMapaPidDelayShape.d.ts +10 -0
  68. package/dist/schema-definitions/jis/datasources/interfaces/IMapaPidDelayShape.js +2 -0
  69. package/dist/schema-definitions/jis/datasources/interfaces/IMapaPidDelayShape.js.map +1 -0
  70. package/dist/schema-definitions/jis/datasources/interfaces/index.d.ts +1 -0
  71. package/dist/schema-definitions/jis/datasources/interfaces/index.js +1 -0
  72. package/dist/schema-definitions/jis/datasources/interfaces/index.js.map +1 -1
  73. package/dist/schema-definitions/jis/models/JISDelayedSegmentsModel.d.ts +24 -0
  74. package/dist/schema-definitions/jis/models/JISDelayedSegmentsModel.js +138 -0
  75. package/dist/schema-definitions/jis/models/JISDelayedSegmentsModel.js.map +1 -0
  76. package/dist/schema-definitions/jis/models/interfaces/IJISDelayedSegment.d.ts +44 -0
  77. package/dist/schema-definitions/jis/models/interfaces/IJISDelayedSegment.js +2 -0
  78. package/dist/schema-definitions/jis/models/interfaces/IJISDelayedSegment.js.map +1 -0
  79. package/dist/schema-definitions/jis/models/interfaces/index.d.ts +1 -0
  80. package/dist/schema-definitions/jis/models/interfaces/index.js +1 -0
  81. package/dist/schema-definitions/jis/models/interfaces/index.js.map +1 -1
  82. package/docs/assets/pid_jis_erd.png +0 -0
  83. package/docs/asyncapi.yaml +15 -0
  84. package/docs/implementation_documentation.md +56 -0
  85. package/docs/index.md +1 -0
  86. package/docs/jis/delayed-segments.md +241 -0
  87. package/docs/jis/index.md +9 -0
  88. package/docs/openapi-output.yaml +176 -0
  89. package/package.json +2 -2
@@ -0,0 +1,241 @@
1
+ # Zpožděné úseky – podklad pro automatické infotexty
2
+
3
+ Stránka popisuje, jak datová platforma Golemio připravuje pro VYMI podklad pro automatické infotexty o zpožděných úsecích sítě PID ([vymi-general#365](https://gitlab.com/operator-ict/golemio/jis/vymi-alerts/vymi-general/-/work_items/365)): záměr, architekturu řešení, algoritmus zpracování, datový model, výstupní API, výkon, konfiguraci, provoz, známá omezení a klíčová rozhodnutí. Stručný přehled pro odběratele je v [index.md](./index.md#zpožděné-úseky--podklad-pro-automatické-infotexty-get-v1jisdelayed-segments), technické údaje workeru a endpointu v [implementační dokumentaci](../implementation_documentation.md#task-refreshdelayedsegmentstask).
4
+
5
+ ## Záměr
6
+
7
+ Při velkém zpoždění na úseku sítě (typicky kolona nebo nehoda) mají cestující na odjezdových tabulích dostat informaci, že spoje určitých linek v daném místě nabírají zpoždění. Dispečeři ROPID takové infotexty dnes zadávají ručně. Cílem je, aby je VYMI navrhovalo nebo zakládalo automaticky.
8
+
9
+ Zpožděné úseky již počítá webová [Mapa PID](https://mapa.pid.cz/) z poloh vozidel Golemia, samotná informace o úseku ale pro infotext nestačí. Je třeba vědět, které linky úsekem jezdí a na kterých zastávkách s odjezdovými tabulemi má smysl infotext zobrazit. Odpovědnosti jsou proto rozděleny takto:
10
+
11
+ | Kdo | Odpovědnost |
12
+ | --- | --- |
13
+ | Mapa PID | detekce zpožděných úseků a odhad zpoždění |
14
+ | Golemio (modul pid) | pravidelné stažení úseků, obohacení o GTFS data (zastávky úseku, dotčené linky, zastávky s tabulemi a jejich vzdálenost od úseku), uložení a poskytnutí přes interní API |
15
+ | VYMI | párování úseků v čase, rozhodnutí o vzniku, úpravě a ukončení události a infotextů, jejich text a výběr tabulí |
16
+
17
+ Golemio tedy nerozhoduje o infotextech, poskytuje jen fakta potřebná k rozhodnutí. VYMI si úseky stahuje každých 5 minut a zakládá z nich interní události s infotexty jménem uživatele `OICT_Robot`; ve zkušebním provozu jen u úseků poblíž testovacích zastávek (Vozovna Střešovice B 876/2, U Památníku B 789/2) a za přepínačem v konfiguraci, podrobně viz [dokumentace VYMI](https://gitlab.com/operator-ict/golemio/jis/vymi-alerts/vymi-alerts-backend/-/blob/master/docs/delayed-segments.md). Rozhraní je navrženo nezávisle na zdroji úseků (viz [Kontrakt API](#kontrakt-api)), aby šlo zdroj v budoucnu vyměnit nebo doplnit bez změny pro VYMI.
18
+
19
+ ## Architektura
20
+
21
+ ```mermaid
22
+ flowchart LR
23
+ mapa["Mapa PID<br/>(detekce zpožděných úseků)"]
24
+ cron["Cron Tasks<br/>(každých 5 minut)"]
25
+ rabbit[("RabbitMQ<br/>vehicle-positions.jis.refreshDelayedSegments")]
26
+ ie["VP Integration Engine<br/>RefreshDelayedSegmentsTask"]
27
+ pg[("PostgreSQL<br/>jis_delayed_segments<br/>+ GTFS tabulky")]
28
+ og["VP Output Gateway<br/>GET /v1/jis/delayed-segments"]
29
+ proxy["Access Proxy<br/>(interní role)"]
30
+ vymi["VYMI<br/>(automatické infotexty)"]
31
+
32
+ cron --> rabbit --> ie
33
+ mapa -. "HTTP JSON" .-> ie
34
+ ie <--> pg
35
+ pg -. "čtení" .-> og
36
+ vymi -. "HTTP JSON" .-> proxy -.-> og
37
+ ```
38
+
39
+ Plná šipka znamená aktivní posílání, přerušovaná stahování příjemcem. Integration Engine si úseky z Mapy PID stahuje, obohacuje je dotazem nad GTFS daty ve stejné databázi a výsledek ukládá do tabulky `jis_delayed_segments`. Output Gateway tabulku jen čte. VYMI si data stahuje z interního endpointu, přístup je omezen rolí v Access Proxy.
40
+
41
+ Průběh jednoho běhu:
42
+
43
+ ```mermaid
44
+ sequenceDiagram
45
+ participant cron as Cron Tasks
46
+ participant task as RefreshDelayedSegmentsTask
47
+ participant db as PostgreSQL
48
+ participant mapa as Mapa PID
49
+
50
+ cron->>task: zpráva do fronty (každých 5 minut)
51
+ task->>task: detectedAt = čas stažení
52
+ task->>mapa: POST bez vozidel a tvarů úseků
53
+ mapa-->>task: zpožděné úseky celé sítě
54
+ task->>task: filtr podle zpoždění, převod krajních zastávek na ASW id
55
+ task->>db: úseky s obohacením mladším než TTL
56
+ db-->>task: znovupoužitelná obohacení
57
+ task->>db: obohacení ostatních úseků (jeden dotaz pro všechny)
58
+ db-->>task: zastávky, linky, zastávky s tabulemi
59
+ task->>db: v transakci upsert všech úseků a smazání nedetekovaných
60
+ ```
61
+
62
+ ## Zdroj dat: Mapa PID
63
+
64
+ Mapa PID počítá zpožděné úseky průběžně z poloh vozidel. Úsek vzniká sloučením navazujících zpožděných mezizastávkových úseků, jeho odhadované zpoždění (`expected_delay`, v sekundách) je součtem zpoždění sloučených částí. Úseky se proto v čase prodlužují, zkracují a štěpí.
65
+
66
+ Golemio volá interní endpoint webové Mapy PID (adresa je jen v konfiguraci, `module.pid.jis.delayedSegments.url`). Endpoint vrací zpožděné úseky vždy pro celou síť bez ohledu na zobrazenou oblast mapy. Požadavek proto posílá prázdnou oblast (`bounds`) a vypnuté tvary úseků (`show_delay_sections: false`), aby odpověď neobsahovala vozidla ani geometrie a byla co nejmenší. Z odpovědi se používá jen pole `delay_shapes`, validované schématem [MapaPidDelayShapesJsonSchema](../../src/schema-definitions/jis/datasources/MapaPidDelayShapesJsonSchema.ts). Krajní zastávky úseku jsou v něm identifikované stop id ve formátu Mapy PID (např. `U1347Z2`, železniční body `T…`).
67
+
68
+ Endpoint není veřejné API. Úpravy na straně Mapy PID nejsou v naší moci, řešení proto pracuje s jeho současným chováním (viz [Známá omezení](#známá-omezení-a-rizika)).
69
+
70
+ ## Zpracování
71
+
72
+ Zpracování obstarává [RefreshDelayedSegmentsTask](../../src/integration-engine/jis/workers/tasks/RefreshDelayedSegmentsTask.ts) a [JISDelayedSegmentsDataService](../../src/integration-engine/jis/services/JISDelayedSegmentsDataService.ts):
73
+
74
+ 1. **Čas detekce.** Před stažením se zaznamená `detectedAt`. Všechny úseky jednoho běhu mají stejný čas poslední detekce a od něj se počítá i časové okno obohacení.
75
+ 2. **Stažení.** Chyba stažení nebo neplatná odpověď ukončí běh chybou a uložené úseky zůstanou beze změny. Prázdný seznam úseků je platná odpověď a uložené úseky smaže.
76
+ 3. **Filtr podle zpoždění.** Úseky se zpožděním pod `minDelaySeconds` (výchozí 300 s) se zahodí. VYMI si minimum zvyšuje parametrem `minDelaySeconds` endpointu (viz [Kontrakt API](#kontrakt-api)).
77
+ 4. **Krajní zastávky na ASW id.** Stop id Mapy PID se převede na ASW id (`uzel/sloupek`, např. `U1347Z2` → `1347/2`). Z ASW id krajních zastávek se skládá `id` úseku `{uzel}/{sloupek}-{uzel}/{sloupek}`. Úseky, jejichž krajní zastávky ASW id nemají (železniční body `T…`), se zahodí.
78
+ 5. **Obohacení.** Všechny úseky se v každém běhu obohatí jedním dotazem (viz [Obohacení](#obohacení)), každé `id` jen jednou. Obohacené úseky by šly pro optimalizaci cachovat, ale v prvotní implementaci to bylo prozatím vynecháno (bude-li v budoucnu potřeba, lze najít hotovou implementaci v Git historii).
79
+ 6. **Vyřazení a duplicity.** Úsek se zahodí, pokud jeho krajní zastávky v GTFS neexistují, pokud ho v časovém okně žádný spoj neprojíždí celý (viz [Známá omezení](#známá-omezení-a-rizika)) nebo pokud nemá dotčené linky. Vyřazené úseky se počítají podle důvodu. Varianty stop id jedné fyzické zastávky mohou vést na stejné `id`; z duplicit se ponechá úsek s největším zpožděním.
80
+ 7. **Uložení.** V jedné transakci se všechny úseky upsertují (`updated_at = detectedAt`, `created_at` zůstává z první detekce) a úseky, které v běhu nebyly, se smažou. Úsek, který se později znovu objeví, začíná s novým `created_at`, stejně jako úsek se změněným `id`; `first_detected_at` je proto začátek aktuální nepřerušené detekce.
81
+
82
+ ## Obohacení
83
+
84
+ Obohacení odvozuje z GTFS dat (předpočítané odjezdy `ropidgtfs_precomputed_departures`, spoje, zastávky a presety odjezdových tabulí) tři údaje. Počítá je dotaz [JISDelayedSegmentEnrichmentQuery](../../src/integration-engine/jis/repositories/helpers/JISDelayedSegmentEnrichmentQuery.ts) najednou pro všechny úseky běhu. Uvažují se jen odjezdy v okně ± `routeTimeWindowMinutes` (výchozí 120 min) od `detectedAt` a jen pravidelné spoje (`exceptional = 0`; výjimečné spoje jsou jednorázové spoje na konkrétní den, např. náhradní doprava). Okno zasahuje i do minulosti, protože zpožděný spoj s odjezdem plánovaným dříve může být v úseku ještě teď (spoj plánovaný na 13:00 může úsekem projíždět ve 13:45).
85
+
86
+ **Párování podle ASW id.** Jedna fyzická zastávka může mít v GTFS více stop id (zónové a dočasné varianty, např. `U9904Z1P` a `U9904Z1`), presety tabulí přitom bývají přiřazené jen k jedné z nich. Zastávky se proto všude párují podle ASW id, nikoli podle GTFS stop id.
87
+
88
+ ### Zastávky úseku
89
+
90
+ Zastávky mezi krajními zastávkami (včetně nich) na spojích, které v časovém okně projíždějí celý úsek, sloučené podle ASW id a seřazené podél úseku. Pořadí určuje relativní poloha zastávky na spoji (0 na začátku úseku, 1 na konci), nejmenší ze všech spojů, aby se spoje vynechávající některé zastávky (např. rychlík A→D a zastávkový spoj A→B→C→D) shodly na krajních zastávkách. Pokud dvě větve úseku řadí společnou zastávku různě daleko od začátku, může být pořadí zastávek mezi větvemi přeházené; párování ve VYMI pořadí nepoužívá. Úsek, kterým v okně žádný spoj celý neprojíždí, nemá zastávky ani dotčené linky a zahodí se. Zastávku úseku reprezentuje abecedně první GTFS stop id ze všech jejích variant, nejen z těch, které obsluhují spoje v okně, aby se id mezi běhy neměnilo (VYMI podle něj páruje úseky). Zastávky bez ASW id (např. železniční body `T…`) mezi zastávky úseku nepatří.
91
+
92
+ ### Dotčené linky
93
+
94
+ Linky, jejichž spoj v časovém okně projede alespoň jeden mezizastávkový úsek mezi dvěma zastávkami úseku, a to ve směru úseku. Směr se neurčuje z pořadí zastávek úseku, ale z dvojic zastávek, které některý spoj jedoucí celým úsekem navštíví v tomto pořadí; platí tak i pro větve, které společnou zastávku řadí různě. Spoj tedy nemusí jet celým úsekem. Linka, která úseku jen dotkne krajní zastávkou nebo jede opačným směrem, dotčená není.
95
+
96
+ ### Zastávky s tabulemi a jejich vzdálenost
97
+
98
+ Zastávky s presetem odjezdové tabule na dotčených spojích do vzdálenosti `maxInfoPanelDistanceStops` (výchozí 5) zastávek od úseku. Pro každou zastávku se uvádí seznam presetů a pro každou dotčenou linku vzdálenost od úseku ve stanicích se znaménkem:
99
+
100
+ ```text
101
+ spoj linky X: P0 ─ P1 ─ P2 ─ [A ─ B ─ C ─ D] ─ N1
102
+ vzdálenost: -3 -2 -1 0 0 0 0 +1
103
+ ```
104
+
105
+ Záporná vzdálenost je před úsekem (tabule, kde cestující nastupují do spojů, které teprve úsekem pojedou), nula v úseku, kladná za úsekem. Pokud spoje jedné linky dávají různé vzdálenosti (např. různé trasy), ponechá se ta nejbližší k úseku. Které tabule dostanou infotext, rozhoduje VYMI: rozsah vzdáleností (výchozí −2 až +2 zastávky) posílá v parametrech `minDistanceStops` a `maxDistanceStops` endpointu a dostane jen tabule v něm.
106
+
107
+ **Vzdálenost jako rozdíl `stop_sequence`.** Vzdálenost se počítá jako rozdíl pořadí zastávky ve spoji (`stop_sequence`) od první, resp. poslední zastávky spoje na úseku. To předpokládá souvislé číslování zastávek spoje, což platí pro všechny spoje PID (ověřeno na všech 127 635 spojodnech produkčních dat v říjnu 2026). Pokud by číslování mezeru mělo, vzdálenost se zvětší o její délku a tabule může vypadnout z limitu. Přesné pořadí by vyžadovalo seřadit všechny zastávky všech dotčených spojů, což byla nejdražší část dotazu (viz [Výkon](#výkon)).
108
+
109
+ ## Datový model
110
+
111
+ Tabulka `jis_delayed_segments` (migrace `20261027100000-jis-delayed-segments`), jeden řádek na aktuálně detekovaný úsek:
112
+
113
+ | Sloupec | Typ | Popis |
114
+ | --- | --- | --- |
115
+ | `id` | `text` | složené z ASW id krajních zastávek `{uzel}/{sloupek}-{uzel}/{sloupek}` |
116
+ | `external_from_stop_id`, `external_to_stop_id` | `varchar(50)` | krajní zastávky ve formátu zdroje, pro dohledání problémů |
117
+ | `from_stop_id`, `from_stop_name`, `to_stop_id`, `to_stop_name` | `varchar(50)`, `text` | krajní zastávky jako GTFS zastávky |
118
+ | `expected_delay_seconds` | `integer` | odhadované zpoždění úseku |
119
+ | `stops`, `routes`, `info_panel_stops` | `jsonb` | obohacení, struktura odpovídá API |
120
+ | `created_at`, `updated_at` | `timestamptz` | začátek aktuální nepřerušené detekce úseku a poslední detekce |
121
+
122
+ Databázové schéma záměrně nezmiňuje Mapu PID, zdroj je v komentářích sloupců popsán obecně. Úseky se uchovávají jen dokud jsou v posledním úspěšně staženém seznamu.
123
+
124
+ Pro obohacení byl index `ropidgtfs_precomputed_departures (stop_id)` nahrazen indexem `(stop_id, departure_datetime)`, který stejně dobře slouží dotazům jen podle zastávky (např. odjezdové tabule). Tabulka předpočítaných odjezdů se při každém importu GTFS vytváří znovu jako `LIKE … including all`, index se tedy přenáší automaticky. Názvy indexů se ale při importech mění, migrace proto index hledá podle sloupců, ne podle názvu, a skončí chybou, pokud takový index není právě jeden. Migrace nový index nejdříve vytvoří a starý smaže až na konci: smazání drží výhradní zámek tabulky až do konce migrace a při opačném pořadí by odjezdové tabule čekaly po celou dobu stavby indexu (na produkčních datech ~3 s).
125
+
126
+ ## Kontrakt API
127
+
128
+ `GET /v1/jis/delayed-segments` (Output Gateway, tag `⚠ JIS (v1) - internal`) vrací uložené úseky seřazené od největšího zpoždění. Volitelné parametry je zužují:
129
+
130
+ - `minDelaySeconds` – jen úseky se zpožděním alespoň takovým,
131
+ - `minDistanceStops`, `maxDistanceStops` – u zastávek s tabulemi jen linky se vzdáleností (`distance_stops`) v tomto rozsahu včetně; zastávky bez takové linky se vynechají.
132
+
133
+ Parametry mohou data jen zúžit: úseky se zpožděním pod `minDelaySeconds` a tabule dál než `maxInfoPanelDistanceStops` z konfigurace Integration Engine se vůbec neukládají. Filtrovat v Output Gateway místo ve VYMI znamená, že VYMI nestahuje data, která by zahodilo, a nastavení filtrů zůstává na jednom místě ve VYMI. Schéma je v [openapi-output.yaml](../openapi-output.yaml) (`JISDelayedSegment`). Odpověď je cachovaná 5 s (`s-maxage=5, stale-while-revalidate=5`).
134
+
135
+ ```json
136
+ {
137
+ "id": "9903/1-9906/1",
138
+ "from_stop": { "id": "U9903Z1P", "name": "Zastávka A" },
139
+ "to_stop": { "id": "U9906Z1P", "name": "Zastávka D" },
140
+ "expected_delay_seconds": 900,
141
+ "first_detected_at": "2026-10-27T08:50:00.000Z",
142
+ "last_detected_at": "2026-10-27T09:00:00.000Z",
143
+ "stops": [{ "id": "U9903Z1P", "name": "Zastávka A" }, "…"],
144
+ "routes": [{ "id": "L9901", "short_name": "9901", "type": 3 }],
145
+ "info_panel_stops": [
146
+ {
147
+ "stop": { "id": "U9901Z1P", "name": "Zastávka P1" },
148
+ "preset_route_names": ["preset-p1"],
149
+ "routes": [{ "id": "L9901", "distance_stops": -2 }]
150
+ }
151
+ ]
152
+ }
153
+ ```
154
+
155
+ Zásady kontraktu:
156
+
157
+ - **Nezávislost na zdroji.** API neobsahuje nic specifického pro Mapu PID (ani její stop id), všechny zastávky a linky jsou GTFS entity. Zdroj úseků lze vyměnit bez změny kontraktu.
158
+ - **`id` není stabilní identifikace.** Úseky v čase rostou, zkracují se a štěpí, `id` se tím mění. VYMI páruje úseky mezi běhy podle `stops`: úsek pokračuje sledovanou kongesci, pokud s ní sdílí alespoň dvě zastávky (dvojice 1:1, větší překryv dřív). Zastávky jsou GTFS stop id abecedně první ze všech variant zastávky v GTFS, nezávisle na tom, které varianty obsluhují spoje v časovém okně; id se tak změní jen se změnou zastávek v GTFS (např. přibude varianta řazená dřív), a i pak jedna změněná zastávka párování podle dvou společných zastávek nerozbije.
159
+ - **Id zastávky s tabulí je id varianty s presetem.** `info_panel_stops[].stop.id` je varianta, ke které je přiřazen preset, a může se lišit od id stejné zastávky ve `stops`. Tabuli v úseku poznáte podle `distance_stops` = 0, ne podle shody id se `stops`.
160
+ - **Aktuálnost podle `last_detected_at`.** Při výpadku zdroje se úseky nemažou. VYMI drží událost platnou do `last_detected_at` + 15 minut (nastavitelné) a při každé další detekci ji prodlouží; když se `last_detected_at` přestane posouvat, událost sama vyprší.
161
+
162
+ ## Výkon
163
+
164
+ Obohacení byla věnována pozornost, protože běží každých 5 minut nad produkční databází. Měřeno v říjnu 2026 na snímku produkčních dat (2,5 mil. předpočítaných odjezdů), čas dotazu včetně plánování:
165
+
166
+ | Varianta | 13 úseků | 40 úseků |
167
+ | --- | --- | --- |
168
+ | první verze, dotaz pro každý úsek | až 13 s na úsek | – |
169
+ | dotaz pro každý úsek po optimalizacích | 0,45 s | 1,2 s |
170
+ | jeden dotaz pro všechny úseky | 0,12 s | 0,25 s |
171
+ | současný stav | 0,06–0,08 s | 0,11–0,13 s |
172
+
173
+ Kontrola směru přes dvojice zastávek přidala ~5–8 %: na stejném snímku 93 → 99 ms pro 13 úseků a 184 → 199 ms pro 40 úseků (medián 7 běhů).
174
+
175
+ Hlavní kroky:
176
+
177
+ - **Párování presetů přes malou množinu.** ASW id zastávek nejsou indexovaná, párování všech zastávek dotčených spojů proti všem GTFS zastávkám trvalo sekundy. Dotaz páruje jen proti zastávkám s presetem a jejich variantám.
178
+ - **Jeden dotaz pro všechny úseky.** Plánování (~10 ms) a sdílené části (presety, zastávky) se platí jednou za běh, ne za úsek.
179
+ - **Odolnost vůči odhadům plánovače.** Plánovač u mezivýsledků (CTE) podhodnocuje počty řádků o dva až tři řády a volí vnořené smyčky. Spojení, kde to vedlo k milionům porovnání, nahrazuje vyhledání v malých mapách (`jsonb`) zastávek úseku a dvojic zastávek ve směru úseku.
180
+ - **Vzdálenost z `stop_sequence`** místo řazení všech zastávek všech dotčených spojů (viz výše).
181
+ - **Index `(stop_id, departure_datetime)`** zrychlí hledání odjezdů ze zastávek v časovém okně.
182
+
183
+ JIT kompilace PostgreSQL by dotaz jen zpomalila: samotná kompilace plánu trvá ~3 s. Odhadovaná cena dotazu (~7 000) je sice hluboko pod výchozím `jit_above_cost` (100 000, nastaveno na rabínu i produkci v říjnu 2026), na rozdíl od prototypu, kterému vypnutí JIT na produkci zrychlilo dotaz zhruba desetkrát. Dotaz přesto běží v transakci s `SET LOCAL jit = off`, aby změna odhadu nebo nastavení nemohla běh zpomalit o sekundy. Nastavení platí jen pro tuto transakci.
184
+
185
+ ## Konfigurace
186
+
187
+ Klíče modulu pid v konfiguraci Integration Engine:
188
+
189
+ | Klíč | Výchozí hodnota | Význam |
190
+ | --- | --- | --- |
191
+ | `module.pid.jis.delayedSegments.url` | – (povinný) | adresa endpointu Mapy PID; záměrně jen v konfiguraci nasazení |
192
+ | `module.pid.jis.delayedSegments.minDelaySeconds` | `300` | minimální zpoždění úseku |
193
+ | `module.pid.jis.delayedSegments.routeTimeWindowMinutes` | `120` | časové okno odjezdů pro obohacení (± od detekce) |
194
+ | `module.pid.jis.delayedSegments.maxInfoPanelDistanceStops` | `5` | maximální vzdálenost zastávky s tabulí od úseku |
195
+
196
+ ## Provoz
197
+
198
+ - **Spouštění:** cron `cron.vehicle-positions.jis.refreshDelayedSegments`, `0 */5 * * * *` (rabín i produkce), fronta `vehicle-positions.jis.refreshDelayedSegments` s TTL 4 minuty (zprávy starší než další běh propadnou). VYMI si úseky stahuje o dvě minuty později (minuta 2, 7, 12, …), aby četl data právě dokončeného běhu; při změně času spouštění je třeba posunout i VYMI.
199
+ - **Předpoklady nasazení:** nastavený `module.pid.jis.delayedSegments.url`, záznam v Cron Tasks a role v Access Proxy pro přístup VYMI k endpointu.
200
+ - **Logování:** každý běh loguje (úroveň info) počet převzatých a nově spočítaných obohacení, počet uložených úseků a počty vyřazených úseků podle důvodu (pod minimálním zpožděním, bez ASW id, krajní zastávky mimo GTFS, úsek neprojíždí celý žádný spoj, bez dotčených linek). Jednotlivé vyřazené úseky se logují jen na úrovni debug, protože se opakují každých 5 minut po celou dobu zpoždění.
201
+ - **Chyby:** chyba stažení, validace nebo databáze ukončí běh chybou a uložená data zůstanou beze změny. Další běh proběhne normálně.
202
+ - **Chybějící jízdní řády:** pokud běh vyřadí všechny úseky s důvodem `no trip runs the whole segment`, pravděpodobně chybí předpočítané odjezdy pro aktuální čas (`ropidgtfs_precomputed_departures`, např. po neúspěšném importu GTFS). Úseky se pak neuloží a VYMI je nedostane.
203
+
204
+ ## Známá omezení a rizika
205
+
206
+ - **Zaseknutý výpočet Mapy PID nelze rozpoznat.** Odpověď neobsahuje čas výpočtu úseků. Pokud Mapa PID přestane úseky přepočítávat, vrací poslední stav (až 24 hodin) a ten se jeví jako aktuální. Změnu na straně Mapy PID nelze zajistit, riziko je pro zkušební provoz přijaté.
207
+ - **Úseky sloučené přes různé linky se zahodí.** Mapa PID slučuje navazující zpožděné mezizastávkové úseky podle zastávek bez ohledu na linku (úsek A→B jedné linky s úsekem B→C jiné linky). Pokud takový sloučený úsek celý neprojíždí žádný spoj, nelze určit jeho zastávky ani linky a úsek se zahodí. Zpoždění tak může zůstat bez infotextu. Počet těchto úseků je v logu každého běhu (`no trip runs the whole segment`). Řešením by bylo rozdělit úsek na části projížděné jednotlivými spoji; zda je to potřeba, ukáže zkušební provoz.
208
+ - **Mezery v `stop_sequence`** by zvětšily vzdálenosti tabulí (viz [Obohacení](#zastávky-s-tabulemi-a-jejich-vzdálenost)).
209
+ - **Úseky přes železniční body** (krajní zastávka `T…` bez ASW id) se nezpracují.
210
+ - **Chybějící název zastávky nebo linky** v GTFS datech by neprošel validací a běh by skončil chybou; data zůstanou z předchozího běhu.
211
+ - **Souběžné běhy** (např. při zdržení fronty) mohou v krajním případě přepsat novější data staršími, další běh je opraví.
212
+
213
+ ## Klíčová rozhodnutí
214
+
215
+ | Rozhodnutí | Důvod |
216
+ | --- | --- |
217
+ | Golemio úseky jen obohacuje, o infotextech rozhoduje VYMI | oddělení faktů od pravidel provozu; VYMI vlastní infotexty i jejich životní cyklus |
218
+ | `id` z ASW id krajních zastávek, ale bez stability; párování podle `stops` | Mapa PID úseky slučuje a štěpí, stabilní identita úseku neexistuje |
219
+ | API nezávislé na zdroji, data zdroje jen v DB (`external_*`) | algoritmus Mapy PID se může změnit, zdroj může být vyměněn |
220
+ | Bez nových časových sloupců pro detekci, `created_at` / `updated_at` | první a poslední detekce přirozeně odpovídají vložení a aktualizaci řádku |
221
+ | Neúspěšný běh nemění data, platnost řeší VYMI podle `last_detected_at` | výpadek zdroje nemá smazat informaci o probíhajícím zpoždění |
222
+ | Minimální zpoždění a rozsah vzdáleností tabulí určuje VYMI parametry endpointu, filtruje Output Gateway | jde o provozní rozhodnutí VYMI, Golemio ale posílá jen relevantní data; konfigurace Integration Engine jen omezuje, co se obohacuje a ukládá; testovací zastávky zůstávají filtrem ve VYMI |
223
+ | Vzdálenost tabulí se znaménkem, nejbližší za linku | VYMI rozliší tabule před úsekem, v úseku a za ním |
224
+ | Jedna tabulka s `jsonb` sloupci | data se vždy čtou celá a vyměňují celá, normalizace by nic nepřinesla |
225
+ | Vzdálenost z `stop_sequence` | výkon (viz [Výkon](#výkon)); kompromis je zdokumentovaný výše |
226
+ | Obohacení v každém běhu, bez cache | znovupoužití obohacení přetrvávajících úseků šetřilo jen desetiny sekundy za běh (v listopadu 2026 ~0,1–0,3 s na snímku produkčních dat, ~0,3–0,9 s na rabínu pro 13–40 úseků), za cenu až 30 minut starých zastávek, linek a tabulí po změně jízdních řádů, presetů nebo přechodu mezi denním a nočním provozem |
227
+ | Adresa Mapy PID jen v konfiguraci | endpoint je veřejně dostupný, ale není určen k širokému použití |
228
+
229
+ ## Zdrojový kód a testy
230
+
231
+ | Část | Soubor |
232
+ | --- | --- |
233
+ | datový zdroj | [JISDelayedSegmentsDataSourceFactory](../../src/integration-engine/jis/datasources/JISDelayedSegmentsDataSourceFactory.ts) |
234
+ | task | [RefreshDelayedSegmentsTask](../../src/integration-engine/jis/workers/tasks/RefreshDelayedSegmentsTask.ts) |
235
+ | zpracování | [JISDelayedSegmentsDataService](../../src/integration-engine/jis/services/JISDelayedSegmentsDataService.ts) |
236
+ | obohacení | [JISDelayedSegmentEnrichmentRepository](../../src/integration-engine/jis/repositories/JISDelayedSegmentEnrichmentRepository.ts), [JISDelayedSegmentEnrichmentQuery](../../src/integration-engine/jis/repositories/helpers/JISDelayedSegmentEnrichmentQuery.ts) |
237
+ | uložení | [JISDelayedSegmentsRepository (IE)](../../src/integration-engine/jis/repositories/JISDelayedSegmentsRepository.ts), [JISDelayedSegmentsModel](../../src/schema-definitions/jis/models/JISDelayedSegmentsModel.ts) |
238
+ | výstup | [V1DelayedSegmentsController](../../src/output-gateway/jis/controllers/v1/V1DelayedSegmentsController.ts), [JISDelayedSegmentsTransformation](../../src/output-gateway/jis/transformations/JISDelayedSegmentsTransformation.ts) |
239
+ | migrace | [20261027100000-jis-delayed-segments](../../db/migrations/postgresql/sqls/20261027100000-jis-delayed-segments-up.sql) |
240
+ | testovací data | [24_jis_delayed_segments.sql](../../db/example/24_jis_delayed_segments.sql) – syntetický koridor s linkami, které úsek projíždějí celý, částečně, jen se ho dotknou, jsou výjimečné, jedou mimo časové okno nebo mají mezeru v `stop_sequence` |
241
+ | testy | `test/integration-engine/jis/**/*DelayedSegment*`, `test/output-gateway/jis/**/*DelayedSegments*` |
package/docs/jis/index.md CHANGED
@@ -306,3 +306,12 @@ Experimentální feed pro e-paper displeje, generovaný stejným taskem. Obsahuj
306
306
 
307
307
  - `/v2/pid/departureboards`, `/v3/pid/transferboards` a `/v3/pid/infotexts` čtou infotexty z PostgreSQL; u odjezdových tabulí s parametrem `preset` se vrací jen infotexty navázané na daný preset (`jis_infotexts_presets.route_name`);
308
308
  - `/v4/pid/transferboards` čte infotexty z Redis cache `jisCache:*`.
309
+
310
+ ### Zpožděné úseky — podklad pro automatické infotexty (`GET /v1/jis/delayed-segments`)
311
+
312
+ Endpoint je interní a slouží VYMI k automatickému vytváření interních událostí a infotextů o zpožděných úsecích ([vymi-general#365](https://gitlab.com/operator-ict/golemio/jis/vymi-alerts/vymi-general/-/work_items/365)). Úseky detekuje Mapa PID, Golemio je stahuje, obohacuje a poskytuje, VYMI rozhoduje, zda a jak vytvořit událost/infotext. Záměr, architekturu, algoritmus, výkon a rozhodnutí podrobně popisuje stránka [Zpožděné úseky](./delayed-segments.md).
313
+
314
+ Úseky každých 5 minut stahuje `RefreshDelayedSegmentsTask` z Mapy PID a obohacuje je o zastávky úseku, dotčené linky a zastávky s panely včetně jejich vzdálenosti od úseku (viz [Zpracování](./delayed-segments.md#zpracování) a [implementační dokumentace](../implementation_documentation.md#task-refreshdelayedsegmentstask)). Pro VYMI platí:
315
+ - úseky v čase rostou a zmenšují se (Mapa PID slučuje navazující zpožděné mezizastávkové úseky), `id` proto není stabilní identifikace; VYMI úseky páruje podle `stops` (alespoň dvě společné zastávky);
316
+ - při chybě stažení zůstávají uložené úseky beze změny a nemažou se; VYMI proto drží událost platnou do `last_detected_at` + 15 minut a nechá ji vypršet, když se `last_detected_at` přestane posouvat; Mapa PID navíc neposílá čas výpočtu úseků, takže zaseknutý výpočet na její straně nelze rozpoznat;
317
+ - minimální zpoždění úseku (`minDelaySeconds`) a rozsah vzdáleností zastávek s panely od úseku (`minDistanceStops`, `maxDistanceStops`) si VYMI určuje parametry endpointu.
@@ -2346,6 +2346,63 @@ paths:
2346
2346
  $ref: "#/components/responses/BadRequestError"
2347
2347
  401:
2348
2348
  $ref: "#/components/responses/UnauthorizedError"
2349
+ /v1/jis/delayed-segments:
2350
+ get:
2351
+ tags:
2352
+ - ⚠ JIS (v1) - internal
2353
+ summary: Get all currently detected delayed segments
2354
+ description: |
2355
+ Returns segments of the network with a significant delay, detected by Mapa PID and enriched with GTFS data:
2356
+ stops of the segment, affected routes and nearby stops with info panels. Refreshed every 5 minutes.
2357
+
2358
+ A segment is a directed corridor of stops. Its `id` is derived from its endpoints; as segments may grow or shrink
2359
+ between refreshes, consumers should match segments by their stops rather than by `id`.
2360
+
2361
+ If fetching the segments fails, the last known segments are kept and their `last_detected_at` stops advancing,
2362
+ so consumers should judge freshness by `last_detected_at`. This does not cover the detection itself stalling:
2363
+ the source provides no time of its calculation, so a stalled detection keeps being fetched and
2364
+ `last_detected_at` keeps advancing.
2365
+
2366
+ Only segments with a delay of at least 5 minutes and info panel stops at most 5 stops from the segment are
2367
+ detected; the query parameters can only narrow them down further.
2368
+ parameters:
2369
+ - name: minDelaySeconds
2370
+ in: query
2371
+ required: false
2372
+ schema:
2373
+ type: integer
2374
+ minimum: 0
2375
+ example: 600
2376
+ description: Minimum `expected_delay_seconds` of the returned segments.
2377
+ - name: minDistanceStops
2378
+ in: query
2379
+ required: false
2380
+ schema:
2381
+ type: integer
2382
+ example: -2
2383
+ description: |
2384
+ Minimum `distance_stops` of info panel stop routes. Routes outside the range given by `minDistanceStops`
2385
+ and `maxDistanceStops` are left out, and so are info panel stops left without a route.
2386
+ - name: maxDistanceStops
2387
+ in: query
2388
+ required: false
2389
+ schema:
2390
+ type: integer
2391
+ example: 2
2392
+ description: Maximum `distance_stops` of info panel stop routes, see `minDistanceStops`.
2393
+ responses:
2394
+ 200:
2395
+ description: OK
2396
+ content:
2397
+ application/json:
2398
+ schema:
2399
+ type: array
2400
+ items:
2401
+ $ref: "#/components/schemas/JISDelayedSegment"
2402
+ 400:
2403
+ $ref: "#/components/responses/BadRequestError"
2404
+ 401:
2405
+ $ref: "#/components/responses/UnauthorizedError"
2349
2406
 
2350
2407
 
2351
2408
  components:
@@ -4897,3 +4954,122 @@ components:
4897
4954
  format: date-time
4898
4955
  example: "2024-02-29T12:22:20.958Z"
4899
4956
  description: Timestamp from when the event was created in VYMI
4957
+ JISDelayedSegmentStop:
4958
+ type: object
4959
+ required:
4960
+ - id
4961
+ - name
4962
+ properties:
4963
+ id:
4964
+ type: string
4965
+ example: U1234Z1P
4966
+ description: GTFS stop id
4967
+ name:
4968
+ type: string
4969
+ example: Vozovna Střešovice
4970
+ JISDelayedSegment:
4971
+ type: object
4972
+ required:
4973
+ - id
4974
+ - from_stop
4975
+ - to_stop
4976
+ - expected_delay_seconds
4977
+ - first_detected_at
4978
+ - last_detected_at
4979
+ - stops
4980
+ - routes
4981
+ - info_panel_stops
4982
+ properties:
4983
+ id:
4984
+ type: string
4985
+ example: 1234/1-5678/2
4986
+ description: Identifier of the segment derived from its endpoints
4987
+ from_stop:
4988
+ $ref: "#/components/schemas/JISDelayedSegmentStop"
4989
+ to_stop:
4990
+ $ref: "#/components/schemas/JISDelayedSegmentStop"
4991
+ expected_delay_seconds:
4992
+ type: integer
4993
+ example: 900
4994
+ description: Expected additional delay of a vehicle passing the whole segment
4995
+ first_detected_at:
4996
+ type: string
4997
+ format: date-time
4998
+ example: "2026-10-27T08:50:00.000Z"
4999
+ description: |
5000
+ Start of the current continuous detection of the segment; resets when the segment is missing from a successful
5001
+ refresh or its `id` changes
5002
+ last_detected_at:
5003
+ type: string
5004
+ format: date-time
5005
+ example: "2026-10-27T09:00:00.000Z"
5006
+ description: Time of the last detection of the segment
5007
+ stops:
5008
+ type: array
5009
+ description: |
5010
+ Stops of the segment, including its endpoints, ordered along the segment. A stop with several GTFS stop ids
5011
+ (variants) is represented by the alphabetically first of them, so its id stays the same between refreshes
5012
+ unless the GTFS stops change.
5013
+ items:
5014
+ $ref: "#/components/schemas/JISDelayedSegmentStop"
5015
+ routes:
5016
+ type: array
5017
+ description: |
5018
+ Routes with a regular trip travelling at least one hop of the segment within the configured time window
5019
+ (default 2 hours) before or after the detection
5020
+ items:
5021
+ type: object
5022
+ required:
5023
+ - id
5024
+ - short_name
5025
+ - type
5026
+ properties:
5027
+ id:
5028
+ type: string
5029
+ example: L119
5030
+ description: GTFS route id
5031
+ short_name:
5032
+ type: string
5033
+ example: "119"
5034
+ type:
5035
+ type: integer
5036
+ example: 3
5037
+ description: GTFS route type
5038
+ info_panel_stops:
5039
+ type: array
5040
+ description: |
5041
+ Stops with an info panel (departure preset) in or near the segment along the affected routes. The stop id
5042
+ is the variant the preset is assigned to, so it may differ from the id of the same stop in `stops`; a stop
5043
+ inside the segment is recognized by `distance_stops` 0.
5044
+ items:
5045
+ type: object
5046
+ required:
5047
+ - stop
5048
+ - preset_route_names
5049
+ - routes
5050
+ properties:
5051
+ stop:
5052
+ $ref: "#/components/schemas/JISDelayedSegmentStop"
5053
+ preset_route_names:
5054
+ type: array
5055
+ description: Route names of the departure presets assigned to the stop
5056
+ items:
5057
+ type: string
5058
+ example: bustec-vozovna_strasovice-876_2
5059
+ routes:
5060
+ type: array
5061
+ description: Affected routes passing the stop
5062
+ items:
5063
+ type: object
5064
+ required:
5065
+ - id
5066
+ - distance_stops
5067
+ properties:
5068
+ id:
5069
+ type: string
5070
+ example: L119
5071
+ description: GTFS route id
5072
+ distance_stops:
5073
+ type: integer
5074
+ example: -2
5075
+ description: Distance of the stop from the segment in stops along the route (negative before the segment, 0 inside, positive after it)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@golemio/pid",
3
- "version": "6.4.0",
3
+ "version": "6.4.1-dev.3054859807",
4
4
  "description": "Golemio PID Module",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -123,7 +123,7 @@
123
123
  "@golemio/core": "^4.0.1-dev.2 || ^4.0.1"
124
124
  },
125
125
  "dependencies": {
126
- "@golemio/ovapi-gtfs-realtime-bindings": "1.4.1",
126
+ "@golemio/ovapi-gtfs-realtime-bindings": "1.4.1-dev.2464451735",
127
127
  "@turf/turf": "^6.5.0",
128
128
  "cheap-ruler": "^3.0.2",
129
129
  "csv-parser": "^3.0.0",