herokuapp deployment |
master |
develop |
---|---|---|
The backend is running on a Herokuapp Free Dyno at: https://reliability-score.herokuapp.com/
The backend of Reliability Score project adds reliability information on top of the iRail API. We use 4 years of historical delay information from Infrabel to determine the reliability of a train. By performing statistics on the data, we can help commuters to plan their future journeys with the train.
To run the scripts and server in this repository, you need at least Python 3.6 or newer. Go to Python.org to install it for your system. You also need some packages, the best way to do this is within a virtual environment. You can install pipenv
by running pip install pipenv
(depending on your Python installation, you may need to run this command with admin/root permissions). You can then install the required packages by running pipenv install
in this repository and activate the virtual environment with pipenv shell
. Now you should be able to run all the scripts in this repository.
As soon as you have a virtual environment shell, you can start the server by running the following command: ./app.py
The source code on the master
branch is automatically deployed to our Herokuapp server.
Travis-CI is also used to make sure that the build doesn't break. Thanks to these tools, we can deploy our backend at all times.
Our API uses the iRail API (https://docs.irail.be) to provide clients the necessary routing information. On top of this data, we use pre-generated JSON files which contain statistical information about a vehicle and the stations of its route.
This information is integrated into the API JSON data and used by our frontend application (https://github.com/oSoc19/reliability-score-frontend) to show how reliable your connection is.
To start the API server, activate the virtual environment like mentioned above and run ./app.py
. You can set the PORT environment variable to change the port of the server (default port is 3000).
We have a single resource available at /connections?from={departureStation}&to={arrivalStation}&time={time}&date={date}×el={arrival or departure}
.
In comparison to the iRail API documentation, all of the arguments are required. In case an argument is missing, a HTTP 400: Bad request
is returned.
- from: The name of the departure station, for example:
Vilvoorde
. - to: The name of the arrival station, for example:
Brugge
. - time: The time of the arrival or departure, for example:
0945
for 9h45 in the morning. - date: The date of the arrival or departure, for example:
220719
for 22 Jul 2019. - timesel: Use the provided
time
anddate
parameters as to arrive at or to depart from. The possible values are:departure
orarrival
.
Besides the iRail API data (see the documentation of the iRail API for more information), we added 2 properties to the response:
- reliability_graph: Contains the frequency of the delays for a vehicle at a certain station. The graph contains 16 buckets:
- Bucket 0: Negative delays (trains that departed earlier than planned).
- Bucket 1: On time or a delay < 1 min.
- Bucket 2-15: Bucket number indicates the border, for example bucket 7: all delays between 6 and 7 min.
- Bucket 16: > 15 min. delay
- reliability_transfer_time: Uses the highest probable delays of a via connection to calculate the time (in seconds) a commuter has to transfer between 2 trains at the via station. It's comparable to the
timeBetween
property of the iRail API, except that we use the statistical information to find out if there's a big chance to miss a transfer.
Response:
{
"version": "1.1",
"timestamp": "1563787414",
"connection": [
{
"id": "0",
"departure": {
"delay": "0",
"station": "Diegem",
"stationinfo": {
"locationX": "4.442774",
"locationY": "50.890478",
"id": "BE.NMBS.008811213",
"@id": "http://irail.be/stations/NMBS/008811213",
"standardname": "Diegem",
"name": "Diegem"
},
"time": "1563778260",
"vehicle": "BE.NMBS.IC1930",
"platform": "?",
"platforminfo": {
"name": "?",
"normal": "1"
},
"canceled": "1",
"departureConnection": "http://irail.be/connections/8811213/20190722/IC1930",
"direction": {
"name": "Tournai"
},
"left": "0",
"walking": "0",
"occupancy": {
"@id": "http://api.irail.be/terms/unknown",
"name": "unknown"
},
"reliability": {
"0": 2.5,
"1": 25.2,
"2": 31.4,
"3": 15.7,
"4": 10.7,
"5": 5.7,
"6": 1.3,
"7": 3.1,
"8": 1.9,
"9": 0.6,
"10": 0.6,
"11": 0,
"12": 0,
"13": 0,
"14": 0,
"15": 0,
"16": 1.3
}
},
"arrival": {
"delay": "0",
"station": "Brugge",
"stationinfo": {
"locationX": "3.216726",
"locationY": "51.197226",
"id": "BE.NMBS.008891009",
"@id": "http://irail.be/stations/NMBS/008891009",
"standardname": "Brugge",
"name": "Brugge"
},
"time": "1563784140",
"vehicle": "BE.NMBS.IC2830",
"platform": "9",
"platforminfo": {
"name": "9",
"normal": "1"
},
"canceled": "0",
"direction": {
"name": "Oostende"
},
"arrived": "0",
"walking": "0",
"reliability": {
"0": 27.6,
"1": 26.4,
"2": 15.5,
"3": 8.6,
"4": 6.3,
"5": 2.3,
"6": 4,
"7": 4,
"8": 1.1,
"9": 1.1,
"10": 1.1,
"11": 0.6,
"12": 0,
"13": 0,
"14": 0,
"15": 0,
"16": 1.1
}
},
"duration": "5880",
"remarks": {
"number": "2",
"remark": [
{
"id": "0",
"code": "SNCB_2090_HINT",
"description": "The original, planned timetable of this trip has been replaced by a new one due to a redirection. Based upon the new timetable, the connection cannot be guaranteed. Consult the overview for an alternative trip."
},
{
"id": "1",
"code": "SNCB_2090_HINT",
"description": "The original, planned timetable of this trip has been replaced by a new one due to a redirection. Based upon the new timetable, the connection cannot be guaranteed. Consult the overview for an alternative trip."
}
]
},
"vias": {
"number": "1",
"via": [
{
"id": "0",
"arrival": {
"time": "1563779400",
"platform": "15",
"platforminfo": {
"name": "15",
"normal": "1"
},
"isExtraStop": "0",
"delay": "0",
"canceled": "0",
"arrived": "0",
"walking": "0",
"direction": {
"name": "Tournai"
},
"vehicle": "BE.NMBS.IC1930",
"departureConnection": "http://irail.be/connections/8814001/20190722/IC1930"
},
"departure": {
"time": "1563780480",
"platform": "8",
"platforminfo": {
"name": "8",
"normal": "1"
},
"isExtraStop": "0",
"delay": "0",
"canceled": "0",
"left": "0",
"walking": "0",
"direction": {
"name": "Oostende"
},
"vehicle": "BE.NMBS.IC2830",
"departureConnection": "http://irail.be/connections/8814001/20190722/IC2830",
"occupancy": {
"@id": "http://api.irail.be/terms/unknown",
"name": "unknown"
}
},
"timeBetween": "1080",
"station": "Brussels-South/Brussels-Midi",
"stationinfo": {
"locationX": "4.336531",
"locationY": "50.835707",
"id": "BE.NMBS.008814001",
"@id": "http://irail.be/stations/NMBS/008814001",
"name": "Brussels-South/Brussels-Midi",
"standardname": "Brussel-Zuid/Bruxelles-Midi"
},
"vehicle": "BE.NMBS.IC1930",
"direction": {
"name": "Tournai"
}
}
]
},
"occupancy": {
"@id": "http://api.irail.be/terms/unknown",
"name": "unknown"
}
}
]
}
💡 For example purposes, we only show a single route in this example above. In reality, several routes are returned by the backend.
See the ml
folder.
In this projects, we use 3 different of scripts.
These scripts are used to parse and use the raw data from [https://opendata.infrabel.be/pages/home/](Infrabel Open Data portal).
The results of the scripts are available in the data
folder.
The source code and documentation of these scripts can be found in the scripts
folder.
The scripts in spreadsheets
transform the Excel files from Infrabel into an open format (CSV).
All the Excel files are converted to CSV files by date. The script also generates a single CSV file of the complete data set (full.csv
)
The station_uris
script allows us to match the Infrabel station names with the iRail station URIs.
Using this information, we can connect the Infrabel delay information with the right NMBS/SNCB station in the iRail API.
Our 3rd script csv_splitter
splits the data into smaller pieces (CSV files) by year and vehicle ID.
After the splitting, we calculate the average delay, median delay and the variance using the Infrabel data.
This information is stored in a JSON file and used directly by the API.