Compare commits
No commits in common. "214a950ac22b70da43a9e4cc823be0bc53d6ebfe" and "b2e557b095c228362248120220f24f5f86bf3c7c" have entirely different histories.
214a950ac2
...
b2e557b095
33
AGENTS.md
33
AGENTS.md
|
|
@ -1,33 +0,0 @@
|
||||||
# MOP Skills 🐙
|
|
||||||
|
|
||||||
This repository contains a collection of specialized **Claude Skills**. These skills extend Claude's capabilities with domain-specific knowledge, workflows, and automated reporting.
|
|
||||||
|
|
||||||
## Repository Structure
|
|
||||||
|
|
||||||
```
|
|
||||||
.
|
|
||||||
├── AGENTS.md # This file (purpose and overview)
|
|
||||||
├── skills/ # Dedicated directory for individual skills
|
|
||||||
│ ├── nerd-report/ # Personal report generator for Moritz Graf
|
|
||||||
│ └── skill-creator/ # Toolkit for creating and validating new skills
|
|
||||||
└── ...
|
|
||||||
```
|
|
||||||
|
|
||||||
## Available Skills
|
|
||||||
|
|
||||||
### [nerd-report](skills/nerd-report/SKILL.md)
|
|
||||||
A professional "Octobot Journalist" that generates daily, weekly, and monthly reports for Moritz Graf.
|
|
||||||
- **Topics:** IT News, GCP, AI (Anthropic/OpenAI), Hacker News, Regensburg Local News.
|
|
||||||
- **Special Features:** Monday catch-up, Drill-down ("Tell me more"), Gardening (Hochbeet), Supermarket Shopping Guide.
|
|
||||||
|
|
||||||
### [skill-creator](skills/skill-creator/SKILL.md)
|
|
||||||
Guidelines and scripts to help developers build high-quality, token-efficient Claude skills.
|
|
||||||
|
|
||||||
## How to use
|
|
||||||
Add individual skill directories to your Claude context. Each skill is self-contained within its directory and driven by its `SKILL.md` file.
|
|
||||||
|
|
||||||
## Creating New Skills
|
|
||||||
Use the templates and scripts in `skills/skill-creator` to bootstrap new skills:
|
|
||||||
```bash
|
|
||||||
python3 skills/skill-creator/scripts/init_skill.py <name> --path skills/
|
|
||||||
```
|
|
||||||
Binary file not shown.
|
|
@ -1,45 +0,0 @@
|
||||||
---
|
|
||||||
name: rvv-regensburg
|
|
||||||
description: Real-time public transport information for Regensburg (RVV). Provides departures, stop finding, and journey planning via direct API access. Use when the user asks for bus/train departures in Regensburg or needs to find a connection within the city.
|
|
||||||
---
|
|
||||||
|
|
||||||
# 🚌 RVV Regensburg
|
|
||||||
|
|
||||||
Access real-time public transport data for the Regensburg transport network (RVV) using the Mentz EFA API.
|
|
||||||
|
|
||||||
## 🚀 Quick Usage
|
|
||||||
|
|
||||||
Use the provided `scripts/rvv_query.py` to interact with the API. Always try to find the correct Stop ID first if you don't have it.
|
|
||||||
|
|
||||||
### 1. Find a Stop ID
|
|
||||||
If you only have a name like "Hauptbahnhof", find its global Stop ID (e.g., `de:09362:11000`):
|
|
||||||
```bash
|
|
||||||
./scripts/rvv_query.py stop "Hauptbahnhof"
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Get Next Departures
|
|
||||||
To see what's leaving a stop soon (using its Stop ID):
|
|
||||||
```bash
|
|
||||||
./scripts/rvv_query.py departures "de:09362:11010" --count 5
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Plan a Journey
|
|
||||||
To find connections between two Stop IDs:
|
|
||||||
```bash
|
|
||||||
./scripts/rvv_query.py trip "de:09362:11010" "de:09362:11000"
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🛠️ API Details (Advanced)
|
|
||||||
If `rvv_query.py` is not sufficient, you can use `curl` directly. The base URL is `https://efa.rvv.de/efa/`.
|
|
||||||
|
|
||||||
**Endpoints:**
|
|
||||||
- `XML_STOPFINDER_REQUEST`: Resolve names to IDs.
|
|
||||||
- `XML_DM_REQUEST`: Departure board.
|
|
||||||
- `XML_TRIP_REQUEST2`: Connection search.
|
|
||||||
|
|
||||||
Always include `outputFormat=rapidJSON` and `version=10.5.17.3` in your requests for the best experience.
|
|
||||||
|
|
||||||
## 💡 Tips
|
|
||||||
- **Real-time:** The API provides real-time data by default (`useRealtime=1`). Look for `rt_time` in the script output.
|
|
||||||
- **Global IDs:** Prefer the global ID format (e.g., `de:09362:XXXXX`) for better accuracy.
|
|
||||||
- **Regensburg Focus:** When searching for stops, include "Regensburg" in the name to avoid matches in other cities (e.g., "Hauptbahnhof" -> "Regensburg, Hauptbahnhof").
|
|
||||||
|
|
@ -1,130 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import requests
|
|
||||||
import json
|
|
||||||
import argparse
|
|
||||||
import sys
|
|
||||||
|
|
||||||
BASE_URL = "https://efa.rvv.de/efa/"
|
|
||||||
VERSION = "10.5.17.3"
|
|
||||||
|
|
||||||
def query_stop(name):
|
|
||||||
params = {
|
|
||||||
"name_sf": name,
|
|
||||||
"outputFormat": "rapidJSON",
|
|
||||||
"type_sf": "any",
|
|
||||||
"locationInfoActive": "1",
|
|
||||||
"version": VERSION
|
|
||||||
}
|
|
||||||
response = requests.get(f"{BASE_URL}XML_STOPFINDER_REQUEST", params=params)
|
|
||||||
return response.json()
|
|
||||||
|
|
||||||
def query_departures(stop_id, count=10):
|
|
||||||
params = {
|
|
||||||
"name_dm": stop_id,
|
|
||||||
"type_dm": "stop",
|
|
||||||
"outputFormat": "rapidJSON",
|
|
||||||
"itdDateTimeDepArr": "dep",
|
|
||||||
"useRealtime": "1",
|
|
||||||
"mode": "direct",
|
|
||||||
"depSequence": count,
|
|
||||||
"version": VERSION
|
|
||||||
}
|
|
||||||
response = requests.get(f"{BASE_URL}XML_DM_REQUEST", params=params)
|
|
||||||
return response.json()
|
|
||||||
|
|
||||||
def query_trip(origin_id, destination_id, count=4):
|
|
||||||
params = {
|
|
||||||
"name_origin": origin_id,
|
|
||||||
"type_origin": "stop",
|
|
||||||
"name_destination": destination_id,
|
|
||||||
"type_destination": "stop",
|
|
||||||
"outputFormat": "rapidJSON",
|
|
||||||
"itdTripDateTimeDepArr": "dep",
|
|
||||||
"calcNumberOfTrips": count,
|
|
||||||
"useRealtime": "1",
|
|
||||||
"mode": "direct",
|
|
||||||
"version": VERSION
|
|
||||||
}
|
|
||||||
response = requests.get(f"{BASE_URL}XML_TRIP_REQUEST2", params=params)
|
|
||||||
return response.json()
|
|
||||||
|
|
||||||
def main():
|
|
||||||
parser = argparse.ArgumentParser(description="Query RVV Regensburg API")
|
|
||||||
subparsers = parser.add_subparsers(dest="command", help="Command to run")
|
|
||||||
|
|
||||||
# Stop Finder
|
|
||||||
stop_parser = subparsers.add_parser("stop", help="Find a stop ID")
|
|
||||||
stop_parser.add_argument("name", help="Name of the stop")
|
|
||||||
|
|
||||||
# Departure Monitor
|
|
||||||
dep_parser = subparsers.add_parser("departures", help="Get departures for a stop")
|
|
||||||
dep_parser.add_argument("stop_id", help="Stop ID (e.g., de:09362:11010)")
|
|
||||||
dep_parser.add_argument("--count", type=int, default=10, help="Number of departures")
|
|
||||||
|
|
||||||
# Trip Planning
|
|
||||||
trip_parser = subparsers.add_parser("trip", help="Plan a trip between two stops")
|
|
||||||
trip_parser.add_argument("origin_id", help="Origin Stop ID")
|
|
||||||
trip_parser.add_argument("destination_id", help="Destination Stop ID")
|
|
||||||
trip_parser.add_argument("--count", type=int, default=4, help="Number of trips")
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
if args.command == "stop":
|
|
||||||
result = query_stop(args.name)
|
|
||||||
points = result.get("locations", [])
|
|
||||||
output = []
|
|
||||||
for p in points:
|
|
||||||
if p.get("type") == "stop":
|
|
||||||
output.append({
|
|
||||||
"id": p["id"],
|
|
||||||
"stopId": p.get("properties", {}).get("stopId") or p.get("id"),
|
|
||||||
"name": p["name"]
|
|
||||||
})
|
|
||||||
print(json.dumps(output, indent=2, ensure_ascii=False))
|
|
||||||
elif args.command == "departures":
|
|
||||||
result = query_departures(args.stop_id, args.count)
|
|
||||||
# EFA rapidJSON uses 'stopEvents' for departures
|
|
||||||
stop_events = result.get("stopEvents", [])
|
|
||||||
output = []
|
|
||||||
for event in stop_events:
|
|
||||||
transport = event.get("transportation", {})
|
|
||||||
departure_time = event.get("departureTimePlanned")
|
|
||||||
departure_time_rt = event.get("departureTimeEstimated")
|
|
||||||
output.append({
|
|
||||||
"line": transport.get("number"),
|
|
||||||
"direction": transport.get("destination", {}).get("name"),
|
|
||||||
"base_time": departure_time[11:16] if departure_time else None,
|
|
||||||
"rt_time": departure_time_rt[11:16] if departure_time_rt else None,
|
|
||||||
"delay": event.get("delay", 0)
|
|
||||||
})
|
|
||||||
print(json.dumps(output, indent=2, ensure_ascii=False))
|
|
||||||
elif args.command == "trip":
|
|
||||||
result = query_trip(args.origin_id, args.destination_id, args.count)
|
|
||||||
# EFA rapidJSON uses 'journeys' for trips
|
|
||||||
journeys = result.get("journeys", [])
|
|
||||||
output = []
|
|
||||||
for j in journeys:
|
|
||||||
legs = j.get("legs", [])
|
|
||||||
trip_info = {
|
|
||||||
"legs": []
|
|
||||||
}
|
|
||||||
for leg in legs:
|
|
||||||
origin = leg.get("origin", {})
|
|
||||||
dest = leg.get("destination", {})
|
|
||||||
transport = leg.get("transportation", {})
|
|
||||||
trip_info["legs"].append({
|
|
||||||
"from": origin.get("name"),
|
|
||||||
"to": dest.get("name"),
|
|
||||||
"line": transport.get("number"),
|
|
||||||
"dep_planned": origin.get("departureTimePlanned", "")[11:16],
|
|
||||||
"dep_est": origin.get("departureTimeEstimated", "")[11:16],
|
|
||||||
"arr_planned": dest.get("arrivalTimePlanned", "")[11:16],
|
|
||||||
"arr_est": dest.get("arrivalTimeEstimated", "")[11:16]
|
|
||||||
})
|
|
||||||
output.append(trip_info)
|
|
||||||
print(json.dumps(output, indent=2, ensure_ascii=False))
|
|
||||||
else:
|
|
||||||
parser.print_help()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
Loading…
Reference in New Issue