mirror of
https://github.com/skoelle/mvg-departures.git
synced 2026-09-18 02:40:25 +00:00
update README.md
This commit is contained in:
@@ -102,3 +102,41 @@ https://www.mvg.de/api/bgw-pt/v3/departures?globalId=de:09162:910&limit=10&trans
|
|||||||
| `/` | HTML-Ansicht, mobile-optimiert, Auto-Refresh alle 60s |
|
| `/` | HTML-Ansicht, mobile-optimiert, Auto-Refresh alle 60s |
|
||||||
| `/api/departures` | JSON-Liste aller gefilterten Abfahrten |
|
| `/api/departures` | JSON-Liste aller gefilterten Abfahrten |
|
||||||
| `/healthz` | Healthcheck fuer Docker/Watchtower |
|
| `/healthz` | Healthcheck fuer Docker/Watchtower |
|
||||||
|
|
||||||
|
## Projektstruktur
|
||||||
|
|
||||||
|
```
|
||||||
|
mvg-departures/
|
||||||
|
├── app/
|
||||||
|
│ ├── main.py # FastAPI-App, Endpunkte, Caching
|
||||||
|
│ ├── config.py # Config-Loader (YAML → Dataclasses)
|
||||||
|
│ └── templates/
|
||||||
|
│ └── index.html # Jinja2-Template (Mobile-UI)
|
||||||
|
├── config.yaml # Stationskonfiguration
|
||||||
|
├── requirements.txt # Python-Dependencies
|
||||||
|
├── Dockerfile
|
||||||
|
└── .github/workflows/
|
||||||
|
└── build.yml # CI/CD: Docker-Build + GHCR-Push
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tech-Stack
|
||||||
|
|
||||||
|
- **Runtime**: Python 3.12
|
||||||
|
- **Framework**: FastAPI + Uvicorn
|
||||||
|
- **Templating**: Jinja2 (server-seitig)
|
||||||
|
- **MVG-API**: `mvg` Python-Client (oeffentlich, kein Auth noetig)
|
||||||
|
- **Config**: YAML via `pyyaml`
|
||||||
|
- **Container**: Docker (python:3.12-slim)
|
||||||
|
|
||||||
|
## Caching
|
||||||
|
|
||||||
|
- **Station-ID**: In-memory Dict, lifetime=Session (loest Station-Namen auf)
|
||||||
|
- **Abfahrten**: In-memory Dict, TTL=`cache_seconds` (Default: 20s) pro Station+Typ
|
||||||
|
- Keine Persistenz → Neustart = Cache-Verlust
|
||||||
|
|
||||||
|
## Einschraenkungen
|
||||||
|
|
||||||
|
- Kein WebSocket/Live-Updates (nur periodischer Meta-Refresh)
|
||||||
|
- Keine Datenbank (nur In-Memory)
|
||||||
|
- Kein Test-Framework vorhanden
|
||||||
|
- Ein `config.yaml` pro Deployment (kein Multi-Tenancy)
|
||||||
|
|||||||
+13
-13
@@ -13,16 +13,16 @@
|
|||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
||||||
background: #111417;
|
background: #111417;
|
||||||
color: #eaeaea;
|
color: #eaeaea;
|
||||||
font-size: 15px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 16px;
|
font-size: 24px;
|
||||||
margin: 4px 0 10px 4px;
|
margin: 4px 0 10px 4px;
|
||||||
color: #9aa5b1;
|
color: #9aa5b1;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
.updated {
|
.updated {
|
||||||
font-size: 11px;
|
font-size: 14px;
|
||||||
color: #6b7280;
|
color: #6b7280;
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
@@ -34,18 +34,18 @@
|
|||||||
border-bottom: 1px solid #23272d;
|
border-bottom: 1px solid #23272d;
|
||||||
}
|
}
|
||||||
td {
|
td {
|
||||||
padding: 8px 4px;
|
padding: 12px 6px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
.icon {
|
.icon {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 26px;
|
width: 32px;
|
||||||
height: 26px;
|
height: 32px;
|
||||||
line-height: 26px;
|
line-height: 32px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 13px;
|
font-size: 16px;
|
||||||
color: #111417;
|
color: #111417;
|
||||||
}
|
}
|
||||||
.icon-U { background: #005ca9; color: #fff; }
|
.icon-U { background: #005ca9; color: #fff; }
|
||||||
@@ -54,21 +54,21 @@
|
|||||||
.icon-B { background: #55545a; color: #fff; }
|
.icon-B { background: #55545a; color: #fff; }
|
||||||
.line {
|
.line {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 14px;
|
font-size: 18px;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
.station {
|
.station {
|
||||||
font-size: 11px;
|
font-size: 14px;
|
||||||
color: #6b7280;
|
color: #6b7280;
|
||||||
}
|
}
|
||||||
.destination {
|
.destination {
|
||||||
font-size: 14px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
.time {
|
.time {
|
||||||
text-align: right;
|
text-align: center;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 15px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
.delay {
|
.delay {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|||||||
Reference in New Issue
Block a user