This repository has been archived by the owner on Jun 9, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: RaenonX <[email protected]>
- Loading branch information
Showing
31 changed files
with
1,025 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
name: Madison Metro Sim - CI Tests | ||
|
||
on: [ push ] | ||
|
||
jobs: | ||
pytest: | ||
name: Run tests | ||
|
||
runs-on: ${{ matrix.os }} | ||
|
||
strategy: | ||
matrix: | ||
os: [ macos-latest, windows-latest ] | ||
|
||
continue-on-error: true | ||
|
||
steps: | ||
- uses: actions/checkout@v2 | ||
|
||
- uses: actions/setup-python@v2 | ||
with: | ||
python-version: '3.8' | ||
|
||
- name: Install required packages | ||
run: | | ||
pip install -r requirements.txt | ||
- name: Install pytest | ||
run: | | ||
pip install pytest | ||
- name: Run tests | ||
run: | | ||
pytest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
name: Madison Metro Sim - CQA | ||
|
||
on: [ push ] | ||
|
||
jobs: | ||
cqa: | ||
name: CQA | ||
|
||
runs-on: ${{ matrix.os }} | ||
|
||
strategy: | ||
matrix: | ||
os: [ macos-latest, windows-latest ] | ||
|
||
continue-on-error: true | ||
|
||
steps: | ||
- uses: actions/checkout@v2 | ||
|
||
- uses: actions/setup-python@v2 | ||
with: | ||
python-version: '3.8' | ||
|
||
- name: Install required packages | ||
run: | | ||
pip install -r requirements.txt | ||
- name: Install CQA checkers | ||
run: | | ||
pip install pylint pydocstyle | ||
- name: pylint checks | ||
run: | | ||
pylint msnmetrosim | ||
- name: pydocstyle checks | ||
run: | | ||
pydocstyle msnmetrosim --count |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
[pydocstyle] | ||
ignore = | ||
# Public method missing docstring - `pylint` will check if there's really missing the docstring | ||
D102, | ||
# Magic method missing docstring - no need for it | ||
D105, | ||
# __init__ missing docstring - optional. add details to class docstring | ||
D107, | ||
# Blank line required before docstring - mutually exclusive to D204 | ||
D203, | ||
# Multi-line docstring summary should start at the first line - mutually exclusive to D213 | ||
D212, | ||
# Section underline is over-indented | ||
D215, | ||
# First line should be in imperative mood | ||
D401, | ||
# First word of the docstring should not be This | ||
D404, | ||
# Section name should end with a newline | ||
D406, | ||
# Missing dashed underline after section | ||
D407, | ||
# Section underline should be in the line following the section’s name | ||
D408, | ||
# Section underline should match the length of its name | ||
D409, | ||
# No blank lines allowed between a section header and its content | ||
D412, | ||
# Missing blank line after last section | ||
D413 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
[FORMAT] | ||
|
||
max-line-length=119 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,17 @@ | ||
import csv | ||
import time | ||
|
||
import folium | ||
from msnmetrosim.views import generate_92_wkd_routes_and_stops | ||
|
||
|
||
def main(): | ||
m = folium.Map(location=[43.080171, -89.380797]) | ||
print("Generating map object...") | ||
folium_map = generate_92_wkd_routes_and_stops() | ||
|
||
# Read csv | ||
|
||
with open("data/mmt_gtfs/stops.csv", "r") as stops: | ||
csv_reader = csv.reader(stops, delimiter=",") | ||
next(csv_reader, None) # Dump header | ||
|
||
for row in csv_reader: | ||
lat = float(row[4]) | ||
lon = float(row[5]) | ||
|
||
name = f"#{row[0]} - {row[2]}" | ||
|
||
folium.Circle((lat, lon), 0.5, popup=name).add_to(m) | ||
|
||
m.save("map.html") | ||
print("Exporting HTML...") | ||
folium_map.save("map.html") | ||
|
||
|
||
if __name__ == '__main__': | ||
_start = time.time() | ||
main() | ||
print(f"Time spent: {(time.time() - _start) * 1000:.3f} ms") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
"""Main code of the Madison Metro Simulator.""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
"""Various data controllers. Loaded and parsed data will be stored into these controllers for use.""" | ||
from .route import MMTRouteDataController | ||
from .shape import MMTShapeDataController, ShapeIdNotFoundError | ||
from .stop import MMTStopDataController | ||
from .trip import MMTTripDataController |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
""" | ||
Controller of the MMT GTFS route data. | ||
The complete MMT GTFS dataset can be downloaded here: | ||
http://transitdata.cityofmadison.com/GTFS/mmt_gtfs.zip | ||
""" | ||
import csv | ||
from typing import List, Dict | ||
|
||
from msnmetrosim.models import MMTRoute | ||
|
||
__all__ = ("MMTRouteDataController", "RouteIdNotFoundError") | ||
|
||
|
||
class RouteIdNotFoundError(KeyError): | ||
"""Raised if the given route ID is not found in the loaded data.""" | ||
|
||
def __init__(self, route_id: int): | ||
super().__init__(f"Data of route ID <{route_id}> not found") | ||
|
||
|
||
class MMTRouteDataController: | ||
"""MMT route data controller.""" | ||
|
||
def _init_dict_by_rid(self, route: MMTRoute): | ||
# This assumes that `route_id` in the original data is unique | ||
self._dict_by_rid[route.route_id] = route | ||
|
||
def __init__(self, routes: List[MMTRoute]): | ||
self._dict_by_rid: Dict[int, MMTRoute] = {} | ||
|
||
# Create a dict with route ID as key and route data entry as value | ||
for route in routes: | ||
self._init_dict_by_rid(route) | ||
|
||
def get_route_by_route_id(self, route_id: int) -> MMTRoute: | ||
""" | ||
Get a :class:`MMTRoute` by ``route_id``. | ||
:raise ServiceIdNotFoundError: if `route_id` is not in the loaded data | ||
""" | ||
if route_id not in self._dict_by_rid: | ||
raise RouteIdNotFoundError(route_id) | ||
|
||
return self._dict_by_rid[route_id] | ||
|
||
@staticmethod | ||
def load_from_file(file_path: str): | ||
""" | ||
Load the route data from route data file. | ||
This file should be a csv with the following schema: | ||
( | ||
route_id, | ||
service_id, | ||
agency_id, | ||
route_short_name, | ||
route_long_name, | ||
route_service_name, | ||
route_desc, | ||
route_type, | ||
route_url, | ||
route_color, | ||
route_text_color, | ||
bikes_allowed | ||
) | ||
This file could be found in the MMT GTFS dataset with the name ``routes.csv``. | ||
""" | ||
routes = [] | ||
|
||
with open(file_path, "r") as routes_file: | ||
csv_reader = csv.reader(routes_file, delimiter=",") | ||
next(csv_reader, None) # Dump header | ||
|
||
for row in csv_reader: | ||
routes.append(MMTRoute.parse_from_row(row)) | ||
|
||
return MMTRouteDataController(routes) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
""" | ||
Controller of the MMT GTFS shape data. | ||
The complete MMT GTFS dataset can be downloaded here: | ||
http://transitdata.cityofmadison.com/GTFS/mmt_gtfs.zip | ||
""" | ||
import csv | ||
from typing import List, Dict, Tuple | ||
|
||
from msnmetrosim.models import MMTShape | ||
|
||
__all__ = ("MMTShapeDataController", "ShapeIdNotFoundError") | ||
|
||
|
||
class ShapeIdNotFoundError(KeyError): | ||
"""Raised if the given shape ID is not found in the loaded data.""" | ||
|
||
def __init__(self, shape_id: int): | ||
super().__init__(f"Data of shape ID <{shape_id}> not found") | ||
|
||
|
||
class MMTShapeDataController: | ||
"""MMT shape data controller.""" | ||
|
||
def _init_dict_by_id(self, shape: MMTShape): | ||
sid = shape.shape_id | ||
|
||
if sid not in self._dict_by_id: | ||
self._dict_by_id[sid] = [] | ||
|
||
self._dict_by_id[sid].append(shape) | ||
|
||
def __init__(self, shapes: List[MMTShape]): | ||
""" | ||
Initializes the shape data controller. | ||
Data in ``shapes`` should be pre-processed as following, or the functions may misbehave. | ||
GROUP BY shape_id, shape_pt_sequence ASC | ||
:param shapes: list of shape data | ||
""" | ||
self._dict_by_id: Dict[int, List[MMTShape]] = {} | ||
|
||
# Create a dict with ID as key and shape data entry as value | ||
for shape in shapes: | ||
self._init_dict_by_id(shape) | ||
|
||
def get_shape_coords_by_id(self, shape_id: int) -> List[Tuple[float, float]]: | ||
""" | ||
Get a list of :class:`MMTShapes` by ``shape_id``. | ||
:raise ShapeIdNotFoundError: if `shape_id` is not in the loaded data | ||
""" | ||
if shape_id not in self._dict_by_id: | ||
raise ShapeIdNotFoundError(shape_id) | ||
|
||
return [shape.coordinate for shape in self._dict_by_id[shape_id]] | ||
|
||
@staticmethod | ||
def load_from_file(file_path: str): | ||
""" | ||
Load the shape data from shape data file. | ||
This file should be a csv with the following schema: | ||
(shape_id, shape_code, shape_pt_lat, shape_pt_lon, shape_pt_sequence, shape_dist_traveled) | ||
This file could be found in the MMT GTFS dataset with the name ``shapes.csv``. | ||
""" | ||
shapes = [] | ||
|
||
with open(file_path, "r") as shapes_file: | ||
csv_reader = csv.reader(shapes_file, delimiter=",") | ||
next(csv_reader, None) # Dump header | ||
|
||
for row in csv_reader: | ||
shapes.append(MMTShape.parse_from_row(row)) | ||
|
||
return MMTShapeDataController(shapes) |
Oops, something went wrong.