commit 68deb2301d0e7c314a5c23ef6d0d1884054d086c Author: Helios Agent Date: Mon Feb 23 01:19:50 2026 +0100 Initial commit for helios-fitx diff --git a/README.md b/README.md new file mode 100644 index 0000000..24deeab --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# Helios FitX Skill + +Checks occupancy (Auslastung) and forecasts for FitX studios. +Uses unofficial FitX API. + +## Usage + +```bash +python3 fitx.py +``` + +Example: +```bash +python3 fitx.py tierpark +``` + +## Setup + +Requires `requests` library: +```bash +pip install requests +``` + +## Output + +Returns JSON with current occupancy percentage and forecast data. diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 0000000..14ec866 --- /dev/null +++ b/SKILL.md @@ -0,0 +1,46 @@ +--- +name: fitx +description: Check FitX gym occupancy - live utilization and weekly forecast for any FitX studio. +--- + +# FitX Auslastung + +Zeigt die aktuelle und prognostizierte Auslastung von FitX Studios. + +## Script + +```bash +python3 skills/fitx/fitx.py [URL] +``` + +- Ohne URL: Default ist *Berlin-Tierpark* +- Mit URL: beliebiges FitX Studio + +## Moritz' Studios + +- *Standard:* Berlin-Tierpark → `https://www.fitx.de/fitnessstudios/berlin-tierpark` +- *Bei Familie in Rostock:* Rostock-Südstadt → `https://www.fitx.de/fitnessstudios/rostock-suedstadt` +- Andere Studios: URL von fitx.de holen (Format: `https://www.fitx.de/fitnessstudios/`) + +## Output + +JSON mit: +- `studio`: Name des Studios +- `live_utilization_today`: Stundenweise Live-Auslastung (Werte 0-100, nur bis aktuelle Stunde gefüllt) +- `forecast_week_data`: Prognose pro Wochentag, stundenweise (0-100) + +## Interpretation + +- 0-20: sehr leer +- 20-40: wenig los +- 40-60: moderat +- 60-80: voll +- 80-100: sehr voll + +## Antwort-Regeln + +- Immer angeben von welchem Studio die Daten sind +- Live-Wert der aktuellen Stunde hervorheben +- Wenn Moritz fragt "ist das Gym voll?" → aktuelle Live-Auslastung + Empfehlung +- Vergleich mit Forecast möglich ("normalerweise ist es um X Uhr so voll, heute ist es ruhiger/voller") +- Wenn kein Studio angegeben: Berlin-Tierpark verwenden (außer Kontext deutet auf Rostock) diff --git a/fitx.py b/fitx.py new file mode 100644 index 0000000..1b8cb4a --- /dev/null +++ b/fitx.py @@ -0,0 +1,66 @@ +import requests +from bs4 import BeautifulSoup +import json +import sys + + +def fetch_fitx_occupancy(studio_url): + headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' + } + + response = requests.get(studio_url, headers=headers) + + soup = BeautifulSoup(response.content, 'html.parser') + + # The data is hidden in a section tag with class 'studio_graph' + graph_section = soup.find('section', class_='studio_graph') + + if not graph_section: + print("Could not find graph section. Check URL or website structure.") + return + + # Extracting raw JSON strings from attributes + visitor_data_raw = graph_section.get('data-visitordata') + current_day_raw = graph_section.get('data-current-day-data') + + # Parsing JSON + # visitor_data is usually 7 arrays (Mon-Sun), each containing 24 integers (0h-23h) + forecast_data = json.loads(visitor_data_raw) + + # current_day_data is an array of integers for the hours passed so far today + live_data = json.loads(current_day_raw) + + studio_name = soup.find('h1', class_='studio_hero__headline').get_text(strip=True) + + # Helper function to map values to time strings + def map_to_times(data_list): + return {f"{i:02d}:00": value for i, value in enumerate(data_list)} + + week_days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] + + # Create the forecast dictionary with time keys + forecast_with_times = {} + for i, day in enumerate(week_days): + forecast_with_times[day] = map_to_times(forecast_data[i]) + + result = { + "studio": studio_name, + "live_utilization_today": map_to_times(live_data), + "forecast_week_data": forecast_with_times + } + + return result + + +if __name__ == "__main__": + # URL defaults to Berlin Tierpark, but can be overridden via command line + target_url = "https://www.fitx.de/fitnessstudios/berlin-tierpark" + + if len(sys.argv) > 1: + target_url = sys.argv[1] + + data = fetch_fitx_occupancy(target_url) + + if data: + print(json.dumps(data, indent=2, ensure_ascii=False))