From c3b6258e8a07a697ebd5093da836c060a3af907f Mon Sep 17 00:00:00 2001 From: acid Date: Thu, 26 Sep 2024 11:20:37 +0100 Subject: [PATCH] Initial commit --- .gitignore | 209 ++++++++++++++++++++++++++++++++++++++++++++++ delays.csv | 15 ++++ last_bus_times.py | 82 ++++++++++++++++++ requirements.txt | 16 ++++ 4 files changed, 322 insertions(+) create mode 100644 .gitignore create mode 100644 delays.csv create mode 100644 last_bus_times.py create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a57ebcd --- /dev/null +++ b/.gitignore @@ -0,0 +1,209 @@ +# Created by https://www.toptal.com/developers/gitignore/api/venv,python,visualstudiocode +# Edit at https://www.toptal.com/developers/gitignore?templates=venv,python,visualstudiocode + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +### Python Patch ### +# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration +poetry.toml + +# ruff +.ruff_cache/ + +# LSP config files +pyrightconfig.json + +### venv ### +# Virtualenv +# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ +[Bb]in +[Ii]nclude +[Ll]ib +[Ll]ib64 +[Ll]ocal +[Ss]cripts +pyvenv.cfg +pip-selfcheck.json + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +# End of https://www.toptal.com/developers/gitignore/api/venv,python,visualstudiocode +delays.html +delays.png \ No newline at end of file diff --git a/delays.csv b/delays.csv new file mode 100644 index 0000000..a81b6a7 --- /dev/null +++ b/delays.csv @@ -0,0 +1,15 @@ +Date,Minutes Late +2024-09-12,60 +2024-09-13,0 +2024-09-14,2 +2024-09-15,0 +2024-09-16,0 +2024-09-17,0 +2024-09-18,3 +2024-09-19,1 +2024-09-20,0 +2024-09-21,60 +2024-09-22,0 +2024-09-23,1 +2024-09-24,0 +2024-09-25,1 \ No newline at end of file diff --git a/last_bus_times.py b/last_bus_times.py new file mode 100644 index 0000000..d862469 --- /dev/null +++ b/last_bus_times.py @@ -0,0 +1,82 @@ +import requests +import re +import datetime +import pytz +from datetime import datetime, timedelta +import csv +import pandas as pd +import numpy as np +from plotly_calplot import calplot +import plotly + + +date_format = "%Y-%m-%d" +yesterday = datetime.today() - timedelta(days=1) +yesterday = yesterday.strftime(date_format) +delay_csv = "delays.csv" + + +def get_delay(date_string: str) -> int: + """ + Calculates the delay in minutes between the last bus departure time and the target time. + + Args: + date_string (str): The date in the format 'YYYY-MM-DD'. + + Returns: + int: The delay in minutes. + """ + + vehicles = requests.get( + f"https://bustimes.org/services/632-wigan-bus-station-bus-station/vehicles?date={date_string}").text + last_joruney = re.findall( + r'\#journeys\/(\d+)">([\d\:]+)<\/a>\s+<\/td>\s+Chorley Town Centre', + vehicles, + )[-1] + + if last_joruney[1] != "23:20" and last_joruney[1] != "22:45": + print(f"No last bus at 23:20 or 22:45, last bus was at {last_joruney[1]}") + return 60 + else: + journey_info = requests.get( + f"https://bustimes.org/services/75994/journeys/{last_joruney[0]}.json").json() + station_departure = journey_info["stops"][0]["actual_departure_time"] + + departure_time = datetime.fromisoformat(station_departure.replace("Z", "+00:00")).astimezone(pytz.timezone("UTC")) + target_time = datetime.strptime(date_string + " " + last_joruney[1], "%Y-%m-%d %H:%M").astimezone(pytz.timezone("Europe/London")) + + return int((departure_time - target_time).total_seconds() / 60) + + +def output_csv(): + # Check if the file exists + try: + with open(delay_csv, "r") as file: + reader = csv.reader(file) + for row in reader: + if row[0] == yesterday: + break + else: + # Add a new entry for yesterday + with open(delay_csv, "a", newline="") as file: + writer = csv.writer(file) + writer.writerow([yesterday, get_delay(yesterday)]) + except FileNotFoundError: + # Create a new file and add the entry for yesterday + with open(delay_csv, "w", newline="") as file: + writer = csv.writer(file) + writer.writerow(["Date", "Minutes Late"]) + writer.writerow([yesterday, get_delay(yesterday)]) + +def make_plot(): + df = pd.read_csv(delay_csv) + df["Date"] = pd.to_datetime(df["Date"]) + + fig = calplot(df, x="Date", y="Minutes Late", dark_theme=True, colorscale=[(0, "green"), (0.1, "yellow"), (1, "red")]) + fig.write_image("delays.png") + plotly.offline.plot(fig, filename="delays.html") + + +if __name__ == "__main__": + output_csv() + make_plot() \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..d1b3435 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,16 @@ +certifi==2024.8.30 +charset-normalizer==3.3.2 +idna==3.10 +kaleido==0.2.1 +numpy==1.26.4 +packaging==24.1 +pandas==2.2.3 +plotly==5.24.1 +plotly_calplot==0.1.20 +python-dateutil==2.9.0.post0 +pytz==2023.4 +requests==2.32.3 +six==1.16.0 +tenacity==9.0.0 +tzdata==2024.2 +urllib3==2.2.3