Giter Club home page Giter Club logo

bus-sg's Introduction

๐ŸšŒ Singapore Bus Routes

A project to get a list of bus stops, servies, and related data for the app NextBus SG.

Made with Flutter PRs Welcome GitHub used by

This data is used for the app NextBus SG.

๐ŸŽ’ Features

  • List of all bus services and their respective routes and stops
    • Bus service type (2-way, 1-way, or loop)
  • List of all bus stops and metadata including name, road, coordinates, and respective buses
    • Exta metadata such as route length and route time/duration
  • MRT stations for bus stops
  • College bus stops
    • NUS
    • NTU

To add college bus stops, we will have to add all shuttles. However, some bus stops don't have codes, so we'll have to think of ways to create IDs. One idea: Internal buses can be "N" followed by 4 digits (ex: First stop is N0001). Similary, premium stops with no IDs can be of the format PXXXX.

Getting the data

Most of the magic happens in bus.py. This file contains the following important functions:

  1. get_services
  2. get_stops_for_each_service
  3. get_all_stops
  4. combine_stops_and_services

1. get_services

This function scrapes LTG and returns a list of all bus services.

Nothing complex.

2. get_stops_for_each_service

This function takes a list of services and returns all the routes as a dictionary/object.

All the bus stops and information about routes come from LTG.

This function returns a dictionary with the keys being bus services (as strings). The dictionaries have the following key/values:

  1. loop: True or False depending on if the bus route is a loop or not. For example, bus 222 and 228 have loop routes. (When loop is True, type is '1')
  2. routes: A list of routes.
    • name: The route's name.
    • stops: A list of stops in the route
  3. type: The route type. '0' if it's a loop; '1' if it's a 1-way route; and '2' is it's a 2-way route. (Most services have 2-way routes)

More data will be added soon:

  • MRT stations connections (see function 5)
  • Route length
  • ...

Example:

get_stops_for_each_service(['14', '15']) => { 
  '14': { 
    'routes': [ 
      { 
        'name': 'Bedok Int โ†’ Clementi Int',
        'stops': [ 
          '84009',
          ...
        ],
      },
      { 
        'name': 'Clementi Int โ†’ Bedok Int',
        'stops': [ 
          '17009',
          ...
        ],
      }
    ],
    "type": '1'
  },
  { '15': { .. } }
}

3. get_all_stops

This function makes use of LTA's DataMall API for Bus Stops. I thought I could do without LTA's API for bus stops, but it's the only source for the longitude and latitude (coordinates) of the bus stops.

This function returns a dictionary with they keys being bus stop codes.

{
  code: {
    code,
    name,
    road,
    coords
  },
  ...
}

TODO: Find MRT stations (if any). This may require a separate function after function 4.

4. combine_stops_and_services

This function takes in 2 parameters:

  1. services_stops_dict: The output of get_stops_for_each_service (function 2).
  2. all_stops_dict: The output of get_all_stops (function 3).

services_stops_dict has a structure of bus service to routes (see example above).

all_stops_dict is a dictionary of all bus stops with the key being the bus stop code.

5. MRT.get_stations

Collecting MRT stations and a list of bus stops near them happens in mrt.py. get_stations works similarly to get_services (function 1). It scrapes LTG for MRT stations.

There's one more function (MRT.get_station_bus_stops) to get the bus stops for the station. It returns a list of of bus stop codes.

MRT.get_stations returns a dictionary with MRT station reference IDs as the keys. Note that each reference ID has it's own dictionary, so interchange stations will be in the dictionary twice. Dhoby Ghaut will be there thrice.

{
  ref: {
    name,
    refs,
    bus_stops
  }
}

refs and bus_stops are lists. The list refs contains ref (the key) and reference IDs of the station on other lines.

This dictionary does store repeats.

NOTE: As of now, future MRT stations abd lines have been removed (te, je, ...). This is because the LTG data is incomplete, so it's causing some repeats and dirty data.

6. add_mrt_data

Add MRT data to combined_stops_and_services_dict (the dictionary returned from combine_stops_and_services, function 4).

It's all come together in this structure:

{
  code: {
    code,
    name,
    road,
    coords: {
      lat, 
      lon
    },
    services: [ ... ],
    mrt_stations: [ ... ]
  }
}

๐Ÿ“‘ Data sources

I'd also like to add cheeaun/busrouter-sg here. While it wasn't a data source, it was really helpful.

โ“ How do I use this?

See the files in the "output/data" directory. More details coming soon.

Known issues

  1. Some stations in the stations list on LTS don't have all stations refs complete. For example, see Marina Bay Financial (a bus stop). The TE line is mentioned even though it is not on the main list, causing duplicates.

bus-sg's People

Contributors

ninest avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

bus-sg's Issues

Bus stops not in LTA DataMall API?

Error with 22579 at ew27
Error with 65211 at ne17
Error with 22579 at js8

bus.py, at Bus().add_mrt_data()

These bus stops come from LTG but don't seem to come from LTA.

Issues with future MRT stations

The object for Marina Bay Financial CTR (Bus stop 03391) has the following listed as MRT stations:

[
  "ce2",
  "ns27"
],
[
  "ce2",
  "ns27",
  "te20"
],
[
  "dt17"
]

The 2 MRT stations it is near are Marina Bay (NS27, CE2, TE20) and Bayfront (DT17). However, there is a repeat of Marina Bay, the second of which does NOT have the ref for TE20.

This is because the LTG page for NSL hasn't yet updated the refs for TE as it's hasn't been build:

image

(No TE20 with Marina Bay)

image

Can fix manually.

Find nearest MRT stations

At least for interchanges. This can be done be searching for all bus stops which end with "int". Note that some names may be shortened (Bt = Bukit).

For all other bus stops that are near stations, Land Transport Guru can be used. Under the "Bus" heading, the bus stop codes can be scrapped.

Example for Bedok: https://landtransportguru.net/bedok-station/

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.