minotor 1.0.0

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 (131) hide show
  1. package/.cspell.json +43 -0
  2. package/.czrc +3 -0
  3. package/.editorconfig +10 -0
  4. package/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
  5. package/.github/ISSUE_TEMPLATE/config.yml +5 -0
  6. package/.github/ISSUE_TEMPLATE/feature_request.md +29 -0
  7. package/.github/PULL_REQUEST_TEMPLATE.md +4 -0
  8. package/.github/workflows/minotor.yml +85 -0
  9. package/.prettierrc +7 -0
  10. package/.releaserc.json +27 -0
  11. package/CHANGELOG.md +6 -0
  12. package/LICENSE +21 -0
  13. package/README.md +166 -0
  14. package/dist/bundle.cjs.js +16507 -0
  15. package/dist/bundle.cjs.js.map +1 -0
  16. package/dist/bundle.esm.js +16496 -0
  17. package/dist/bundle.esm.js.map +1 -0
  18. package/dist/bundle.umd.js +2 -0
  19. package/dist/bundle.umd.js.map +1 -0
  20. package/dist/cli/__tests__/minotor.test.d.ts +1 -0
  21. package/dist/cli/minotor.d.ts +5 -0
  22. package/dist/cli/repl.d.ts +1 -0
  23. package/dist/cli/utils.d.ts +3 -0
  24. package/dist/cli.mjs +20504 -0
  25. package/dist/cli.mjs.map +1 -0
  26. package/dist/gtfs/__tests__/parser.test.d.ts +1 -0
  27. package/dist/gtfs/__tests__/routes.test.d.ts +1 -0
  28. package/dist/gtfs/__tests__/services.test.d.ts +1 -0
  29. package/dist/gtfs/__tests__/stops.test.d.ts +1 -0
  30. package/dist/gtfs/__tests__/time.test.d.ts +1 -0
  31. package/dist/gtfs/__tests__/transfers.test.d.ts +1 -0
  32. package/dist/gtfs/__tests__/trips.test.d.ts +1 -0
  33. package/dist/gtfs/__tests__/utils.test.d.ts +1 -0
  34. package/dist/gtfs/parser.d.ts +34 -0
  35. package/dist/gtfs/profiles/__tests__/ch.test.d.ts +1 -0
  36. package/dist/gtfs/profiles/ch.d.ts +2 -0
  37. package/dist/gtfs/profiles/standard.d.ts +2 -0
  38. package/dist/gtfs/routes.d.ts +11 -0
  39. package/dist/gtfs/services.d.ts +19 -0
  40. package/dist/gtfs/stops.d.ts +20 -0
  41. package/dist/gtfs/time.d.ts +17 -0
  42. package/dist/gtfs/transfers.d.ts +22 -0
  43. package/dist/gtfs/trips.d.ts +26 -0
  44. package/dist/gtfs/utils.d.ts +21 -0
  45. package/dist/index.d.ts +11 -0
  46. package/dist/routing/__tests__/router.test.d.ts +1 -0
  47. package/dist/routing/plotter.d.ts +11 -0
  48. package/dist/routing/query.d.ts +35 -0
  49. package/dist/routing/result.d.ts +28 -0
  50. package/dist/routing/route.d.ts +25 -0
  51. package/dist/routing/router.d.ts +33 -0
  52. package/dist/stops/__tests__/io.test.d.ts +1 -0
  53. package/dist/stops/__tests__/stopFinder.test.d.ts +1 -0
  54. package/dist/stops/i18n.d.ts +10 -0
  55. package/dist/stops/io.d.ts +4 -0
  56. package/dist/stops/proto/stops.d.ts +53 -0
  57. package/dist/stops/stops.d.ts +16 -0
  58. package/dist/stops/stopsIndex.d.ts +52 -0
  59. package/dist/timetable/__tests__/io.test.d.ts +1 -0
  60. package/dist/timetable/__tests__/timetable.test.d.ts +1 -0
  61. package/dist/timetable/duration.d.ts +51 -0
  62. package/dist/timetable/io.d.ts +8 -0
  63. package/dist/timetable/proto/timetable.d.ts +122 -0
  64. package/dist/timetable/time.d.ts +98 -0
  65. package/dist/timetable/timetable.d.ts +82 -0
  66. package/dist/umdIndex.d.ts +9 -0
  67. package/eslint.config.mjs +52 -0
  68. package/package.json +109 -0
  69. package/rollup.config.js +44 -0
  70. package/src/cli/__tests__/minotor.test.ts +23 -0
  71. package/src/cli/minotor.ts +112 -0
  72. package/src/cli/repl.ts +200 -0
  73. package/src/cli/utils.ts +36 -0
  74. package/src/gtfs/__tests__/parser.test.ts +591 -0
  75. package/src/gtfs/__tests__/resources/sample-feed/agency.txt +2 -0
  76. package/src/gtfs/__tests__/resources/sample-feed/calendar.txt +3 -0
  77. package/src/gtfs/__tests__/resources/sample-feed/calendar_dates.txt +2 -0
  78. package/src/gtfs/__tests__/resources/sample-feed/fare_attributes.txt +3 -0
  79. package/src/gtfs/__tests__/resources/sample-feed/fare_rules.txt +5 -0
  80. package/src/gtfs/__tests__/resources/sample-feed/frequencies.txt +12 -0
  81. package/src/gtfs/__tests__/resources/sample-feed/routes.txt +6 -0
  82. package/src/gtfs/__tests__/resources/sample-feed/sample-feed.zip +0 -0
  83. package/src/gtfs/__tests__/resources/sample-feed/shapes.txt +1 -0
  84. package/src/gtfs/__tests__/resources/sample-feed/stop_times.txt +34 -0
  85. package/src/gtfs/__tests__/resources/sample-feed/stops.txt +10 -0
  86. package/src/gtfs/__tests__/resources/sample-feed/trips.txt +13 -0
  87. package/src/gtfs/__tests__/resources/sample-feed.zip +0 -0
  88. package/src/gtfs/__tests__/routes.test.ts +63 -0
  89. package/src/gtfs/__tests__/services.test.ts +209 -0
  90. package/src/gtfs/__tests__/stops.test.ts +177 -0
  91. package/src/gtfs/__tests__/time.test.ts +27 -0
  92. package/src/gtfs/__tests__/transfers.test.ts +117 -0
  93. package/src/gtfs/__tests__/trips.test.ts +463 -0
  94. package/src/gtfs/__tests__/utils.test.ts +13 -0
  95. package/src/gtfs/parser.ts +154 -0
  96. package/src/gtfs/profiles/__tests__/ch.test.ts +43 -0
  97. package/src/gtfs/profiles/ch.ts +70 -0
  98. package/src/gtfs/profiles/standard.ts +39 -0
  99. package/src/gtfs/routes.ts +48 -0
  100. package/src/gtfs/services.ts +98 -0
  101. package/src/gtfs/stops.ts +112 -0
  102. package/src/gtfs/time.ts +33 -0
  103. package/src/gtfs/transfers.ts +102 -0
  104. package/src/gtfs/trips.ts +228 -0
  105. package/src/gtfs/utils.ts +42 -0
  106. package/src/index.ts +28 -0
  107. package/src/routing/__tests__/router.test.ts +760 -0
  108. package/src/routing/plotter.ts +70 -0
  109. package/src/routing/query.ts +74 -0
  110. package/src/routing/result.ts +108 -0
  111. package/src/routing/route.ts +94 -0
  112. package/src/routing/router.ts +262 -0
  113. package/src/stops/__tests__/io.test.ts +43 -0
  114. package/src/stops/__tests__/stopFinder.test.ts +185 -0
  115. package/src/stops/i18n.ts +40 -0
  116. package/src/stops/io.ts +94 -0
  117. package/src/stops/proto/stops.proto +26 -0
  118. package/src/stops/proto/stops.ts +445 -0
  119. package/src/stops/stops.ts +24 -0
  120. package/src/stops/stopsIndex.ts +151 -0
  121. package/src/timetable/__tests__/io.test.ts +175 -0
  122. package/src/timetable/__tests__/timetable.test.ts +180 -0
  123. package/src/timetable/duration.ts +85 -0
  124. package/src/timetable/io.ts +265 -0
  125. package/src/timetable/proto/timetable.proto +76 -0
  126. package/src/timetable/proto/timetable.ts +1304 -0
  127. package/src/timetable/time.ts +192 -0
  128. package/src/timetable/timetable.ts +286 -0
  129. package/src/umdIndex.ts +14 -0
  130. package/tsconfig.build.json +4 -0
  131. package/tsconfig.json +21 -0
package/.cspell.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "version": "0.2",
3
+ "language": "en",
4
+ "words": [
5
+ "Minotor",
6
+ "gtfs",
7
+ "minotor",
8
+ "luxon",
9
+ "Gtfs",
10
+ "GTFS",
11
+ "Tilleul",
12
+ "Cathédrale",
13
+ "tcrqn",
14
+ "tcrqo",
15
+ "lswfbh",
16
+ "Neuveville",
17
+ "Cathedrale",
18
+ "bufbuild",
19
+ "protoc",
20
+ "geokdbush",
21
+ "kdbush",
22
+ "slimsearch",
23
+ "geospatial",
24
+ "NeTEx",
25
+ "Ksfdp",
26
+ "Tsvg",
27
+ "Landquart",
28
+ "Davos",
29
+ "moleson",
30
+ "Klosters",
31
+ "Engadin"
32
+ ],
33
+ "flagWords": [],
34
+ "ignorePaths": [
35
+ "package.json",
36
+ "package-lock.json",
37
+ "yarn.lock",
38
+ "tsconfig.json",
39
+ "node_modules/**",
40
+ "src/gtfs/__tests__/gtfs.test.ts",
41
+ "parser.test.ts"
42
+ ]
43
+ }
package/.czrc ADDED
@@ -0,0 +1,3 @@
1
+ {
2
+ "path": "./node_modules/@ryansonshine/cz-conventional-changelog"
3
+ }
package/.editorconfig ADDED
@@ -0,0 +1,10 @@
1
+ root = true
2
+
3
+ [*]
4
+ end_of_line = lf
5
+ insert_final_newline = true
6
+
7
+ [*.ts,*.tsx]
8
+ indent_style = space
9
+ indent_size = 2
10
+ quote_type = single
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: Bug report
3
+ about: Create a report to help us improve @aubrio/minotor
4
+ title: ''
5
+ labels: 'bug'
6
+ assignees: ''
7
+ ---
8
+
9
+ **Describe the bug**
10
+ A clear and concise description of the bug.
11
+
12
+ **To Reproduce**
13
+ Steps to reproduce the behavior:
14
+
15
+ 1.
16
+ 2.
17
+ 3.
18
+
19
+ **Expected behavior**
20
+ A clear and concise description of what you expected to happen.
21
+
22
+ **Screenshots**
23
+ If applicable, add screenshots to help explain your problem.
24
+
25
+ **Environment**
26
+
27
+ - OS version:
28
+ - Node version / Browser version:
29
+ - Minotor Version:
30
+
31
+ **Additional context**
32
+ Add any other context about the problem here.
@@ -0,0 +1,5 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: GitHub Discussions
4
+ url: https://github.com/aubryio/minotor/discussions
5
+ about: To discuss topics which are not suited for being discussed in issues
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: Feature Request
3
+ about: Suggest a new feature or enhancement for @aubrio/minotor
4
+ title: ''
5
+ labels: 'enhancement'
6
+ assignees: ''
7
+ ---
8
+
9
+ ## Feature Request
10
+
11
+ ### Description
12
+
13
+ A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
14
+
15
+ ### Proposed Solution
16
+
17
+ A clear and concise description of what you want to happen.
18
+
19
+ ### Alternatives Considered
20
+
21
+ A clear and concise description of any alternative solutions or features you've considered.
22
+
23
+ ### Additional Context
24
+
25
+ Add any other context or screenshots about the feature request here.
26
+
27
+ ### Related Issues
28
+
29
+ If applicable, add links to existing issues or discussions that are related to this feature request.
@@ -0,0 +1,4 @@
1
+ Fixes # (issue)
2
+
3
+ Please provide a concise description of your changes, and the motivation for making them.
4
+ If relevant, include links to related issues or pull requests.
@@ -0,0 +1,85 @@
1
+ name: minotor
2
+
3
+ on: [push]
4
+
5
+ env:
6
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
7
+
8
+ jobs:
9
+ format:
10
+ name: 💅 Prettier
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v3
14
+ - uses: actions/setup-node@v3
15
+ - uses: bahmutov/npm-install@v1
16
+ - name: 💅 Prettier
17
+ run: npm run format:check
18
+
19
+ lint:
20
+ name: 🔍 ESLint
21
+ runs-on: ubuntu-latest
22
+ steps:
23
+ - uses: actions/checkout@v3
24
+ - uses: actions/setup-node@v3
25
+ - uses: bahmutov/npm-install@v1
26
+ - name: ⬣ ESLint
27
+ run: npm run lint:check
28
+
29
+ audit:
30
+ name: 🛡️ Audit
31
+ runs-on: ubuntu-latest
32
+ steps:
33
+ - uses: actions/checkout@v3
34
+ - uses: actions/setup-node@v3
35
+ - name: 🛡️ Audit
36
+ run: npm audit --audit-level=high
37
+
38
+ spell:
39
+ name: 🔠 Spellcheck
40
+ runs-on: ubuntu-latest
41
+ steps:
42
+ - uses: actions/checkout@v3
43
+ - uses: actions/setup-node@v3
44
+ - uses: bahmutov/npm-install@v1
45
+ - name: 🈸 Spellcheck
46
+ run: npm run spell:check
47
+
48
+ type:
49
+ name: ʦ Typecheck
50
+ runs-on: ubuntu-latest
51
+ steps:
52
+ - uses: actions/checkout@v3
53
+ - uses: actions/setup-node@v3
54
+ - uses: bahmutov/npm-install@v1
55
+ - name: ʦ Typecheck
56
+ run: npm run type:check
57
+
58
+ test:
59
+ name: ⚡ Tests
60
+ runs-on: ubuntu-latest
61
+ steps:
62
+ - uses: actions/checkout@v3
63
+ - uses: actions/setup-node@v3
64
+ with:
65
+ node-version: '21.1.0'
66
+ - uses: bahmutov/npm-install@v1
67
+ - name: ⚡ Tests
68
+ run: npm run test:coverage
69
+
70
+ build-and-release:
71
+ name: 🚀 Build & release
72
+ needs: [format, lint, audit, spell, type, test]
73
+ runs-on: ubuntu-latest
74
+ steps:
75
+ - uses: actions/checkout@v3
76
+ - uses: actions/setup-node@v3
77
+ - uses: bahmutov/npm-install@v1
78
+ - uses: arduino/setup-protoc@v3
79
+ - name: 🔨 Build
80
+ run: npm run build
81
+ - name: 🚀 Release
82
+ env:
83
+ GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
84
+ NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
85
+ run: npm run semantic-release
package/.prettierrc ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "singleQuote": true,
3
+ "semi": true,
4
+ "printWidth": 80,
5
+ "tabWidth": 2,
6
+ "useTabs": false
7
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "branches": [
3
+ "main",
4
+ {
5
+ "name": "beta",
6
+ "prerelease": true
7
+ },
8
+ {
9
+ "name": "alpha",
10
+ "prerelease": true
11
+ }
12
+ ],
13
+ "repositoryUrl": "https://github.com/aubryio/minotor.git",
14
+ "plugins": [
15
+ "@semantic-release/commit-analyzer",
16
+ "@semantic-release/release-notes-generator",
17
+ "@semantic-release/changelog",
18
+ "@semantic-release/npm",
19
+ [
20
+ "@semantic-release/github",
21
+ {
22
+ "successComment": false,
23
+ "failTitle": false
24
+ }
25
+ ]
26
+ ]
27
+ }
package/CHANGELOG.md ADDED
@@ -0,0 +1,6 @@
1
+ # 1.0.0 (2025-02-02)
2
+
3
+
4
+ ### Features
5
+
6
+ * prototype GTFS parser, stop index and Raptor router. ([912cc7d](https://github.com/aubryio/minotor/commit/912cc7d822bfa2e08260074ecb05e8777d36dc4d))
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-2025 Aubry Cholleton
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,166 @@
1
+ # Minotor
2
+
3
+ ![GitHub Workflow Status](https://github.com/aubryio/minotor/actions/workflows/minotor.yml/badge.svg?branch=main)
4
+
5
+ A lightweight and easy to use public transit router primarily targeting client-side usage for research, data visualization, dynamic web and mobile apps.
6
+
7
+ Unlike most transit planners out there, **minotor** allows to store all the transit data for a given day in memory on the client, allowing for fast runtime queries using only local data.
8
+ This is particularly useful for highly dynamic applications or complex visualizations for research purposes where the user needs to query the data in real-time.
9
+ Privacy-conscious applications where the user does not want to share their location data with a server can also benefit from this model.
10
+
11
+ The transit router and the stops index of **minotor** can run in the browser, on react-native or in a Node.js environment.
12
+ Transit data (GTFS) parsing runs on Node.js, and the resulting data is serialized as a protobuf binary that can be loaded from the router.
13
+
14
+ ## Features
15
+
16
+ - GTFS feed parsing (standard and extended)
17
+ - Geographic and textual stops search
18
+ - Transit routing from origin(s) stop(s) to destination(s) stop(s) at a given time
19
+ - Computation for arrival times at all stops given a destination and start time
20
+
21
+ ### Tested GTFS feeds
22
+
23
+ | Feed | Parsing time | Timetable Size for a Day (Compressed) |
24
+ | ------------------------------------------------------------------------------------------ | ------------ | ------------------------------------- |
25
+ | [Swiss GTFS feed](https://data.opentransportdata.swiss/en/dataset/timetable-2025-gtfs2020) | ~2 minutes | 44 MB (9MB) |
26
+
27
+ ## Get started
28
+
29
+ ### Installation
30
+
31
+ `npm i minotor`
32
+
33
+ ### Typescript API Usage example
34
+
35
+ #### GTFS Feed parsing (Node.js only)
36
+
37
+ ```
38
+ import { GtfsParser, chGtfsProfile } from 'minotor';
39
+
40
+ const parser = new GtfsParser('gtfs-feed.zip', chGtfsProfile);
41
+ const { timetable, stopsIndex } = await parser.parse(new Date());
42
+ ```
43
+
44
+ Note that this operation can take a few minutes for large GTFS feeds.
45
+ See comments in the code for more options.
46
+
47
+ #### Stop Search (Browser or Node.js)
48
+
49
+ ```
50
+ const origins = stopsIndex.findStopsByName('Fribourg');
51
+ const destinations = stopsIndex.findStopsByName('Moles'); // Partial name search
52
+ ```
53
+
54
+ Query stops by ID:
55
+
56
+ `const stopFromId = stopsIndex.findStopById('8592374:0:A');`
57
+
58
+ Or by location:
59
+
60
+ `const nearbyStops = stopsIndex.findStopsByLocation(46.80314924, 7.1510478, 5, 0.5);`
61
+
62
+ #### Routing (Browser or Node.js)
63
+
64
+ ```
65
+ import { Query, Router, Time } from 'minotor';
66
+
67
+ const router = new Router(timetable, stopsIndex);
68
+
69
+ const query = new Query.Builder()
70
+ .from('Parent8504100')
71
+ .to('Parent8504748')
72
+ .departureTime(Time.fromHMS(8,0,0))
73
+ .maxTransfers(5)
74
+ .build();
75
+ const result = router.route(query);
76
+ ```
77
+
78
+ Get the route between origin and the closest destination (optionally provide another destination stop than the one in the query, the resulting route will be found if it's reachable before the first query destination reached).
79
+
80
+ `const bestRoute = result.bestRoute();`
81
+
82
+ Get the arrival time to any stop (optionally provide the max number of transfers if you're interested in a lower one than the one provided in the query).
83
+ This time will be correct for any stop reachable before the first query destination reached.
84
+
85
+ `const arrivalTime = result.arrivalAt(toStop.id);`
86
+
87
+ ### CLI Usage example
88
+
89
+ Parse GTFS data for a day and output the timetable and stops index (`minotor parse-gtfs -h` for more options):
90
+
91
+ `minotor parse-gtfs gtfs_feed.zip`
92
+
93
+ Note that this operation can take a few minutes for very large GTFS feeds.
94
+ Without extra parameters it saves the timetable and stopsIndex for the current day in `/tmp` as binary protobufs.
95
+
96
+ Run the REPL to query the router or the stop index (`minotor repl -h` for more options):
97
+
98
+ `minotor repl`
99
+
100
+ Search stops (`minotor> .find -h for more options`):
101
+
102
+ `minotor> .find moleson`
103
+
104
+ Query routes (`minotor> .route -h for more options`):
105
+
106
+ `minotor> .route from fribourg to moleson at 08:00`
107
+
108
+ ## Development
109
+
110
+ ### Debugging
111
+
112
+ It is possible to plot the router graph to debug the algorithm:
113
+
114
+ `minotor repl`
115
+
116
+ `minotor> .plot from <stationId> to <stationId> at <HH:mm> [with <N> transfers] [to <graph.dot>]`
117
+
118
+ `dot -Ksfdp -Tsvg graph.dot -o graph.svg `
119
+
120
+ ### Build
121
+
122
+ Make sure you have a working node setup as well as a protobuf compiler.
123
+
124
+ - `build`: builds the project in the `dist/` directory
125
+ - `clean`: removes the `dist/` directory
126
+
127
+ ### Tests
128
+
129
+ - `test`: runs test runner
130
+ - `test:coverage`: runs test runner with coverage reports
131
+
132
+ ### Formatting & linting
133
+
134
+ - `lint`: ESLint with automatic fixing
135
+ - `format`: Prettier with automatic fixing
136
+ - `spell:check`: Spell checker
137
+
138
+ ### Releasing
139
+
140
+ - `cz`: generates a valid git commit message (See [Commitizen](https://github.com/commitizen/cz-cli))
141
+
142
+ Releases are automatically published to npm when merging to the `main` or `beta` (pre-release) branch.
143
+
144
+ ## Known issues
145
+
146
+ ### \[Work in Progress\] Train splits in Switzerland
147
+
148
+ In the swiss GTFS feed, some transfers are missing for proper handling of trains that splits in two and diverge route at a given station.
149
+ They are modeled as 2 routes, one covering the full route of the first variant and the other covering the route for the other variant but only from the split station (on the platforms where the part of train splitting is located) to the destination.
150
+ The challenge is that no transfer indicates that it's possible to continue from the platform where the train arrives to the part of the platform where the other part of the train splits and continues on the other route.
151
+ This is for example the case with the train starting from Landquart splitting in Klosters to reach lower Engadin or Davos. A transfer between 8509068:0:3 and 8509068:0:3AB is missing to understand that it's possible to continue on the way to Davos.
152
+ While these transfers should ideally be handled at a route/trip level (the swiss feed contains only stop level transfers for now), artificially adding transfers between a station platform and its corresponding "sub-platforms" would be enough to tackle the issue in a minimal way.
153
+
154
+ ## Roadmap
155
+
156
+ The project is under active development. Here are some of the features that are planned:
157
+
158
+ - Documentation website and examples
159
+ - Load multiple GTFS archives at once
160
+ - Range queries
161
+ - Transfer preferences
162
+ - Support for exporting a calendar range as opposed to a single day
163
+ - Support for GTFS `frequencies.txt`
164
+ - Support for more types of transfers
165
+ - NeTEx support
166
+ - RT-GTFS Support