Zum Inhalt springen
dan felser @felsr
Sport KI 13

Dein eigenes Strava Premium

1 Claude Code öffnen — nicht die App, der Prompt holt Daten und baut eine Datei  2 Prompt reinhauen  3 sagen, womit du aufzeichnest — den Rest fragt er dich.

Du baust mir aus den Rohdaten meiner eigenen Uhr die Analyse-Schicht, fuer die ich
bei Strava bisher bezahle: Belastung je Einheit, Fitness und Frische ueber die
Saison, meine echten Zonen, meine Bestleistungen - und eine Coach-Analyse, die
einen Befund nennt statt einer Zahlenwand.

Du arbeitest Schritt fuer Schritt. Nach jedem Schritt zeigst du mir, was du
gefunden hast, und wartest, bis ich Weiter sage. Du ueberspringst nichts, du baust
die Seite nicht vor Schritt 6, und du erfindest keine Zahl, die du nicht aus einer
Datei gelesen hast. Wenn du eine Bestaetigung fuer einen Befehl brauchst, frag
einfach - ich sage dann Ja.


SCHRITT 1 - WELCHE UHR TRAEGST DU

Frag mich zuerst, mit welchem Geraet ich aufzeichne. Danach richtet sich alles.

Es gibt zwei Wege, und der Unterschied ist gross genug, dass ich ihn kennen
sollte, bevor wir anfangen:

  LIVE-ANBINDUNG (nur Garmin). Du holst die Daten selbst und jederzeit neu. Damit
  gibt es alle vier Bildschirme, und die Seite laesst sich nach jedem Lauf mit
  einem Befehl neu rechnen.

  DATEI-EXPORT (alle anderen: Apple Watch, COROS, Polar, Suunto, Fitbit, Samsung,
  Wahoo). Ich exportiere einmal, du liest die Dateien. Damit gibt es dasselbe,
  aber der Bestand ist so alt wie mein letzter Export. Sag mir das, bevor du
  anfaengst, nicht am Ende.

Sieh dann nach, ob hier oder in meinem Benutzerordner schon Daten liegen: ein
Ordner garmin, eine data.json, ein Apple-Health-Export, ein Strava-Datenexport,
FIT- oder TCX-Dateien, eine activities.csv.

Wenn ja, sag mir den Zeitraum und DREI Anzahlen getrennt: wie viele Einheiten hast
du insgesamt, wie viele davon haben eine Pulsreihe, und wie viele haben eine
Tempo- oder Distanzreihe. Diese drei Zahlen sind fast nie gleich, und sie
entscheiden alles, was danach kommt.


SCHRITT 2 - DIE DATEN HOLEN

Nimm genau den Weg fuer mein Geraet. Alle Klickwege sind vom Herbst 2026; findest
du den Menuepunkt nicht, such in den Einstellungen nach Export und sag mir, was du
stattdessen siehst.

GARMIN - Live-Anbindung, der beste Weg

  Richte eine Synchronisierung ein, die eine lokale Datei schreibt. Nimm das
  Python-Paket garminconnect.

  Frag mich nach meiner Mailadresse. Das Passwort tippe ich selbst in eine
  Eingabeaufforderung - du schreibst es in keine Datei, gibst es nicht aus und
  legst es in keine Umgebungsvariable. Lies es mit getpass. Kommt eine
  Zwei-Faktor-Abfrage, fragst du mich nach dem Code. Der Login braucht ein echtes
  Terminal; laeuft er bei dir nicht, gib mir den Befehl zum Selbsteintippen,
  statt es anders zu versuchen.

  Hol 12 Monate Aktivitaeten. Fuer jede Einheit brauchst du drei Ebenen, und die
  liegen an drei verschiedenen Stellen:

    LISTE      die Uebersicht mit Datum, Sportart, Distanz, Dauer, Puls,
               Hoehenmetern - und, wichtig, den Sekunden je Herzfrequenzzone.
               Die stehen im Rohblock der Liste, nicht in einem eigenen Abruf.

    RUNDEN     die Splits je Einheit. Da stehen Kadenz, Bodenkontaktzeit,
               vertikale Bewegung, Schrittlaenge, Leistung und das
               steigungsbereinigte Tempo drin - alles, was die Rundenansicht
               eines Bezahlabos zeigt.

    PUNKTE     die eigentliche Punktreihe, Sekunde fuer Sekunde. Das ist der
               Detail-Abruf einer einzelnen Aktivitaet.

  ACHTUNG, hier steckt die Falle: Der Detail-Abruf dampft lange Einheiten
  standardmaessig auf rund 2000 Punkte ein. Eine Einheit ueber zwei Stunden kommt
  dann fuenffach ausgeduennt zurueck, und du merkst es nicht, weil die Kurve
  trotzdem glatt aussieht. Setz die Punktzahl deshalb mindestens auf die Dauer der
  Einheit in Sekunden, und pruef danach nach: Anzahl der zurueckgegebenen Punkte
  gegen Dauer in Sekunden. Weichen sie mehr als 5 Prozent ab, sag es mir.

  Sieh dir die Antwort des ersten Detail-Abrufs EINMAL vollstaendig an, bevor du
  irgendein Feld benutzt. Die Punktreihen kommen als Liste von Werten mit einer
  getrennten Beschreibung, welche Spalte was ist. Lies diese Beschreibung aus und
  bau die Zuordnung daraus - schreib keine Feldnamen hin, die du nicht in der
  Antwort gesehen hast. Sag mir, welche Groessen du gefunden hast: Zeit, Distanz,
  Puls, Tempo, Hoehe, Kadenz, Leistung, Temperatur.

  Braucht die Punktreihe zu viele Abrufe oder fehlt eine Groesse, gibt es den
  verlustfreien Weg: den Aktivitaets-Download als FIT oder TCX. Da steht jeder
  Datensatz drin, so wie die Uhr ihn geschrieben hat.

  Hol ausserdem, weil wir das in Schritt 4 und 5 brauchen:
    - Schwellenpuls und Schwellentempo aus dem Biometrie-Abruf
    - meine persoenlichen Rekorde
    - meine Rennzeit-Vorhersagen
    - meine VO2max-Reihe
    - Ruhepuls je Tag

  Nur lesen. Es wird nie etwas in mein Konto zurueckgeschrieben.

  IN DER BIBLIOTHEK HEISSEN DIE AUFRUFE SO (Stand garminconnect 0.3.2). Pruef die
  Namen einmal gegen die installierte Fassung, statt dich blind darauf zu verlassen:

    get_activities(start, limit)              die Liste, mit hrTimeInZone_1..5
                                              und activityTrainingLoad im Rohblock
    get_activity_splits(activity_id)          die Runden
    get_activity_details(activity_id,         die PUNKTREIHE. maxchart mindestens
                         maxchart, maxpoly)   auf die Dauer in Sekunden setzen,
                                              Voreinstellung ist 2000
    download_activity(activity_id, dl_fmt)    verlustfrei, dl_fmt ORIGINAL, TCX,
                                              GPX, KML oder CSV
    get_activity_hr_in_timezones(activity_id) Sekunden je Herzfrequenzzone
    get_lactate_threshold(latest=True)        Schwellenpuls und Schwellentempo
    get_personal_record()                     die gefuehrten Rekorde
    get_race_predictions()                    die Vorhersagen des Geraets
    get_max_metrics(cdate)                    VO2max
    get_rhr_day(cdate)                        Ruhepuls
    get_user_profile()                        das Profil. Sieh hier nach dem
                                              hinterlegten Maximalpuls und den
                                              Zonengrenzen - beides ist nicht
                                              dokumentiert, also einmal ausdrucken
                                              und nachsehen, was wirklich drinsteht

  Findest du einen Namen nicht, such in der installierten Bibliothek danach und sag
  mir, wie er dort heisst. Rate keinen Endpunkt.

APPLE WATCH - und alles, was nach Apple Health synchronisiert

  Health-App, oben rechts aufs Profilbild, ganz unten Alle Gesundheitsdaten
  exportieren. Das erzeugt eine ZIP mit einer export.xml und, wichtig fuer uns,
  einem Ordner workout-routes mit GPX-Dateien.

  Die XML ist gross, oft mehrere hundert Megabyte. Du liest sie NICHT als Ganzes
  ein. Schreib ein Skript, das die Datei streamend durchgeht und nur das
  heraushol, was wir brauchen: die Workouts, die Herzfrequenz-Datensaetze, den
  Ruhepuls und VO2max. Danach wirf den Rest weg.

  Die Punktreihe entsteht hier aus zwei Quellen: Puls aus den
  Herzfrequenz-Datensaetzen im Zeitfenster des Workouts, Tempo und Distanz aus der
  GPX-Spur desselben Workouts. Ordne beides ueber den Zeitstempel zu und sag mir,
  bei wie vielen Einheiten das geklappt hat.

  Achtung: Apples Herzfrequenz kommt in unregelmaessigen Abstaenden, nicht jede
  Sekunde. Rechne nicht so, als waere jeder Datensatz eine Sekunde - gewichte
  jeden Wert mit dem Abstand zum naechsten.

COROS, POLAR, SUUNTO, WAHOO, FITBIT, SAMSUNG

  Alle koennen FIT- oder TCX-Dateien ausgeben, entweder je Einheit oder als
  Sammelexport aus dem Web-Konto. Frag mich, welches Format ich bekommen habe, und
  lies es mit einer FIT- oder TCX-Bibliothek. In beiden Formaten steht die
  Punktreihe vollstaendig drin; das ist der beste Fall, den es gibt.

  Findest du den Export nicht, geht auch der Umweg ueber Apple Health, wenn die
  App dorthin schreibt.

DER WEG UEBER STRAVA SELBST - fuer mein Archiv

  Wenn ich meine gesamte Historie mitnehmen will, hol ich sie mir einmal bei
  Strava ab: Einstellungen, Mein Konto, Eine Kopie deiner Daten herunterladen. Das
  kommt als ZIP per Mail und enthaelt eine activities.csv plus die
  Originaldateien meiner Einheiten als FIT oder GPX.

  Das ist ausdruecklich KEIN Abo-Weg und kein Anschluss an Stravas Schnittstelle.
  Es ist mein eigener Datenexport, und er funktioniert auch mit einem kostenlosen
  Konto. Die Originaldateien darin sind dieselbe Punktreihe wie oben.

  Sag mir, wenn die CSV Spalten enthaelt, die du sonst nirgends findest - und sag
  mir genauso deutlich, welche Strava-Werte darin NICHT vorkommen, weil sie erst
  auf deren Servern entstehen.


SCHRITT 3 - IN DEN ROHBLOCK SCHAUEN, BEVOR DU EINEM FELD GLAUBST

Bevor du eine einzige Zahl rechnest, druck mir fuer EINE Einheit meiner Wahl den
kompletten Rohblock aus - Liste, Runden und die ersten 30 Punkte der Punktreihe.

Dann pruef vier Dinge und sag mir das Ergebnis:

1. Einheiten. Ist Tempo in Meter je Sekunde oder in Minuten je Kilometer? Ist die
   Distanz in Metern oder Kilometern? Rechne einen Wert von Hand nach und
   vergleich ihn mit dem, was in der Liste steht. Eine Verwechslung hier faellt
   spaeter nicht mehr auf, weil alle Zahlen konsistent falsch sind.

2. Zeit gegen Bewegungszeit. Die beiden gehen bei jedem Lauf mit Ampeln
   auseinander. Sag mir, mit welcher du rechnest und warum. Fuer Belastung ist es
   die Bewegungszeit, fuer Bestleistungen die verstrichene Zeit im Fenster.

3. Luecken in der Pulsreihe. Zaehl die Sekunden ohne Pulswert je Einheit. Ueber 5
   Prozent: nenn die Einheit mit Datum. Ein Gurt, der zwei Minuten aussetzt,
   macht aus einem harten Intervall eine lockere Einheit.

4. Die Sekunden je Herzfrequenzzone aus der Liste gegen die Dauer. Die Summe muss
   ungefaehr die Dauer ergeben. Tut sie das, sind es Sekunden; ergibt sie
   ungefaehr 100, sind es Prozent. Rate das nicht, rechne es nach.


SCHRITT 4 - MEINE ECHTEN ZONEN, BEVOR IRGENDETWAS BEWERTET WIRD

Das ist der Schritt, den fast jede Auswertung ueberspringt, und er entscheidet
ueber jede Zahl danach.

MAXIMALPULS

  Hol den Wert aus meinem Profil, und stell ihm den hoechsten Puls gegenueber, der
  in den letzten zwoelf Monaten tatsaechlich aufgezeichnet wurde. Nimm dafuer die
  Punktreihen, nicht die Zusammenfassungen, und wirf einzelne Ausreisser raus:
  Ein Wert gilt nur, wenn er mindestens 10 Sekunden am Stueck gehalten wurde.

  Dann sag mir eines von drei Dingen:

    Der Profilwert liegt UEBER dem gemessenen Maximum. Dann rechnet jede
    prozentbasierte Zone gegen einen Puls, den ich nie erreicht habe, und jede
    Einheit landet zu tief. Sag mir die Differenz in Schlaegen und in Prozent,
    und sag mir, wie viele meiner Einheiten mit dem gemessenen Maximum in eine
    hoehere Zone rutschen wuerden.

    Der Profilwert liegt UNTER dem gemessenen Maximum. Dann ist er veraltet oder
    zu vorsichtig gesetzt. Rechne mit dem gemessenen Wert weiter und sag es mir.

    Beide liegen dicht beieinander. Dann ist alles in Ordnung, und du sagst mir
    das in einem Satz.

    Im Profil steht GAR KEIN Maximalpuls. Das ist haeufiger, als man denkt: Bei
    Garmin liefern weder der Profil- noch der Einstellungs-Abruf zuverlaessig
    einen Wert, auch wenn die Uhr selbst mit einem rechnet. Dann sagst du mir das
    in einem Satz, rechnest mit dem gemessenen Maximum weiter und schreibst auf
    die Seite, dass es eine Untergrenze ist. Du erfindest keinen Profilwert und du
    setzt nicht still 220 minus Alter ein.

  Wichtig: Ein gemessenes Maximum aus einer Reihe ohne Wettkampf ist eine
  UNTERGRENZE, keine Messung. Wer nie voll ausgefahren ist, hat seinen Maximalpuls
  nicht gesehen. Schreib das so auf die Seite, statt eine Zahl zu behaupten.

  Die Formel 220 minus Alter benutzt du nicht als Wahrheit. Rechne sie zum
  Vergleich mit aus und schreib die Abweichung zu meinem gemessenen Wert dazu -
  ueber Menschen streut diese Formel um rund 12 Schlaege, also eine halbe Zone.

SCHWELLE

  Wenn es einen gemessenen Schwellenpuls und ein Schwellentempo gibt, sind das die
  besseren Anker als Prozente vom Maximum. Nimm sie, wenn sie da sind, und sag mir
  ihren Messstand - ein Schwellenwert von vor einem Jahr beschreibt einen anderen
  Menschen.

  Baue die Pulszonen dann so:
    Zone 1  bis 85 Prozent der Schwelle
    Zone 2  85 bis 89
    Zone 3  90 bis 94
    Zone 4  95 bis 99
    Zone 5  ab 100

  Gibt es keinen Schwellenwert, nimm Prozente vom gemessenen Maximum und schreib
  auf die Seite, dass die Zonen abgeleitet sind, nicht gemessen.

TEMPOZONEN

  Leite meine Trainingstempi aus meiner besten Wettkampfleistung der letzten
  18 Monate ab, nicht aus einem Durchschnitt. Nimm die Daniels-Systematik: aus
  Distanz und Zeit den VDOT, daraus die fuenf Tempobereiche - locker, Marathon,
  Schwelle, Intervall, Wiederholung. Schreib die Ableitung hin.

  Ist meine beste Leistung aelter als 18 Monate, sag mir das und setz sie mit
  einem Abschlag an. Eine 24 Monate alte Bestzeit ist kein aktuelles Tempo.

  Vergleich am Ende meine tatsaechlich gelaufenen Tempi mit diesen Bereichen: Wie
  viel Prozent meiner Kilometer lagen wirklich im lockeren Bereich? Die Antwort
  auf diese eine Frage ist bei den meisten Laeufern der ganze Trainingsbefund.

Zeig mir die fertige Zonentabelle - Puls und Tempo nebeneinander - und warte auf
mein Weiter, bevor du rechnest.


SCHRITT 5 - DIE VIER RECHNUNGEN, HINGESCHRIEBEN

Jede Formel kommt spaeter woertlich auf die Seite. Wenn du eine aenderst, aendert
sich der Abdruck mit.

BELASTUNG JE EINHEIT

  Grundlage ist TRIMPexp nach Banister, gerechnet auf der PUNKTREIHE, nicht auf
  dem Durchschnittspuls. Das ist der ganze Unterschied: Ein Intervalltraining mit
  Durchschnittspuls 150 und ein lockerer Dauerlauf mit Durchschnittspuls 150 sind
  nicht dieselbe Einheit, und nur die Punktreihe weiss das.

    Fuer jede Sekunde i mit Puls HF_i:
      hr_i  = (HF_i minus Ruhepuls) geteilt durch (Maximalpuls minus Ruhepuls)
      w_i   = hr_i mal 0,64 mal e hoch (1,92 mal hr_i)      Maenner
      w_i   = hr_i mal 0,86 mal e hoch (1,67 mal hr_i)      Frauen
      TRIMP = Summe ueber alle Sekunden von w_i, geteilt durch 60

  Werte unter 0 oder ueber 1 fuer hr_i deckelst du auf 0 und 1 und meldest, wie
  oft das vorkam.

  Danach auf eine Skala von 0 bis 100, aber mit MEINEM Anker:

      Anker      = 95. Perzentil meiner Tages-TRIMP-Werte an Tagen mit Aktivitaet,
                   mindestens aber 40
      Belastung  = 100 mal TRIMP geteilt durch Anker, gedeckelt bei 100

  Der Anker ist persoenlich, weil eine feste fremde Zahl bei einem trainierten
  Menschen regelmaessig Werte ueber der eigenen Obergrenze erzeugt.

  Du deckelst NICHT bei 100. Ein 95. Perzentil heisst per Konstruktion, dass rund
  jeder zwanzigste aktive Tag darueber liegt - ein Deckel wuerde genau die Tage
  unsichtbar machen, die der Grund fuer die Zahl sind. Ueber 100 heisst schlicht:
  haerter als dein uebliches Maximum. Nur wenn MEHR ALS ZEHN PROZENT der aktiven
  Tage ueber 100 liegen, stimmt der Anker nicht - dann sag es mir, statt
  weiterzurechnen.

  Fehlt die Pulsreihe einer Einheit ganz, rechnest du KEINE Belastung. Du schreibst
  die Einheit mit ihrer Dauer auf die Seite und markierst sie als ohne Puls. Eine
  Einheit ohne Puls ist nicht eine Einheit mit Belastung null.

WAS DEIN GERAET SCHON RECHNET - ERST NACHSEHEN, DANN NACHBAUEN

  Bevor du eine eigene Zahl an die Stelle einer fremden setzt, sieh nach, ob mein
  Geraet sie schon liefert. Garmin fuehrt zum Beispiel eine eigene Trainingslast je
  Einheit, einen Trainingszustand, eine VO2max-Reihe und Rennzeit-Vorhersagen. Die
  liegen im Rohblock und kosten nichts extra.

  Regel: Was das Geraet liefert, uebernimmst du und schreibst dazu, dass es vom
  Geraet kommt. Was es nicht liefert, rechnest du selbst und schreibst die Formel
  hin. Nie beides fuer dieselbe Groesse ohne Kennzeichnung.

  Und stell sie einander gegenueber: Wenn die Trainingslast des Geraets und meine
  eigene Belastung ueber 30 Tage nahezu dasselbe sagen, sag mir das - dann brauche
  ich die eigene Rechnung fuer diese eine Groesse gar nicht, und das ist ein
  besseres Ergebnis als eine zweite Zahl daneben. Sagen sie etwas anderes, zeig mir
  die drei groessten Abweicher mit Datum.

FITNESS, ERMUEDUNG, FRISCHE

  Aus der Tagesbelastung drei exponentiell geglaettete Reihen:

      Fitness heute   = Fitness gestern  plus (Last heute minus Fitness gestern)
                        geteilt durch 42
      Ermuedung heute = Ermuedung gestern plus (Last heute minus Ermuedung gestern)
                        geteilt durch 7
      Frische heute   = Fitness gestern minus Ermuedung gestern

  Tage ohne Aktivitaet gehen mit Last null ein - das ist der Punkt der Rechnung.

  Zwei Dinge schreibst du dazu, sonst zeigt die Kurve etwas anderes,
  als sie behauptet:

    Die ersten 42 Tage der Reihe sind Einschwingen, kein Zustand. Markier sie auf
    der Kurve als solche.

    Fehlende Aufzeichnung ist NICHT Ruhe. Wenn ich auf dem Rad einen anderen
    Computer benutze oder ohne Uhr laufe, sieht die Reihe eine Pause, die es nicht
    gab. Zaehl die Tage ohne jede Aufzeichnung und schreib die Zahl auf die Seite.

  Sag mir ausserdem klar: Diese Zahlen haben dieselbe FORM wie die eines
  Bezahlanbieters, aber nicht dieselbe Skala. Sie sind untereinander vergleichbar,
  nicht mit deren Werten. Wer beides nebeneinanderlegt, vergleicht zwei
  Fremdsprachen.

BESTLEISTUNGEN UND VORHERSAGE

  Rechne meine Bestleistungen selbst aus der Punktreihe, mit einem gleitenden
  Fenster ueber die Distanzreihe: die schnellsten 400 m, 1 km, 5 km, 10 km,
  10 Meilen, Halbmarathon, Marathon - je mit Datum und Einheit. Das ist genau das,
  was eine Punktreihe kann und eine Zusammenfassung nicht.

  Stell sie den Rekorden gegenueber, die mein Geraetehersteller fuehrt. Weichen sie
  ab, nenn die Differenz und den wahrscheinlichen Grund, statt eine Seite fuer
  richtig zu erklaeren.

  Vorhersage fuer eine Zieldistanz, auf zwei Wegen, und beide zeigst du mir:

      Riegel:   Zielzeit = Bestzeit mal (Zieldistanz geteilt durch Bestdistanz)
                hoch 1,06
      Daniels:  ueber den VDOT aus Schritt 4

  Liegen die beiden mehr als 2 Prozent auseinander, ist das kein Fehler, sondern
  die ehrliche Spanne. Schreib beide hin.

  Riegel ueber grosse Distanzspruenge ist unzuverlaessig. Rechne nie von 400 m auf
  Marathon und sag mir, wenn der Sprung mehr als das Achtfache betraegt.

DIE COACH-ANALYSE

  Kein Bericht, keine Zahlenwand. Genau EIN Befund, der aus meinen Daten am
  staerksten belegt ist - nicht der interessanteste, der belegteste.

  Pruef mindestens diese Verdaechtigen gegen die Zahlen:

    Alles im mittleren Tempo. Die lockeren Laeufe zu schnell, die harten zu lasch.
    Beleg ueber den Anteil der Kilometer je Tempozone aus Schritt 4.
    Immer dieselbe Runde. Gleiche Distanz, gleiches Tempo, Woche fuer Woche.
    Kein langer Lauf, oder einer, der im Verhaeltnis zur Woche zu kurz bleibt.
    Umfangsspruenge ueber 30 Prozent gegen die Vorwoche, besonders mit Loch danach.
    Keine ruhige Woche in einem Block von vier.
    Frische dauerhaft unter minus 20 - Ermuedung, die nie abgebaut wird.
    Harte Einheiten ohne Zweck: viele Wettkampftempi, nichts, was auf ein Ziel
    zulaeuft.

  Zaehl Radfahren, Wandern und Kraft getrennt mit. Das ist Belastung, aber es ist
  kein Laufumfang - wirf beides nie in einen Topf, sonst erklaerst du mir eine
  100-Kilometer-Woche, die ich auf dem Rad hatte.

  Sag den Befund dann so:
    1. Ein Satz, der ihn benennt. Ohne Vorrede.
    2. Drei Zahlen aus meinem Archiv, die ihn belegen, jede mit Datum.
    3. Eine Sache, die ich in der naechsten Woche anders mache. Konkret, mit
       Tempo und Dauer.

  Wenn die Daten fuer keinen Befund reichen, sagst du genau das. Ein erfundener
  Befund ist schlimmer als keiner.


SCHRITT 6 - DIE SEITE BAUEN

Eine einzige, selbsttragende HTML-Datei. Kein Build, keine Pakete, kein Server,
keine Schrift und kein Skript von einem fremden Rechner. Ich mache sie im Browser
auf.

Die Daten werden in die Datei eingebettet, nicht nachgeladen. Eine lokal
geoeffnete Datei darf kein JSON per fetch holen, und das scheitert lautlos.

DAS GRUNDMUSTER - EINE SPALTE, UND ALLES ENTSTEHT DURCH TIPPEN

  Eine Spalte, hoechstens 720 Pixel breit, mittig, mit 20 Pixel Luft zum Rand.
  Kein Seitenmenue, keine Reiter, kein Kachelraster. Die Seite ist eine Folge von
  Abschnitten, die ich scrolle.

  In Ruhe zeigt jeder Abschnitt EINE Aussage: eine grosse Zahl oder einen Satz,
  dazu hoechstens eine Zeichnung und eine Zeile, die weiterfuehrt. Keine Tabelle,
  kein Achsenkreuz, keine Legende, keine Fussnote, solange ich nicht frage.

  Jede Zahl ist antippbar und klappt ihren Rechenweg darunter auf: die Formel in
  fester Schrittweite, darunter die Eingaben mit meinen Werten, darunter ein Satz
  in normaler Sprache, was dabei herauskommt. Je Abschnitt bleibt hoechstens eine
  Klappe offen, eine neue schliesst die vorige, die Taste Escape schliesst alle.

  Was aufklappt, schiebt den Rest der Seite nach unten statt ihn zu verdecken:
  eine Rasterzeile, die von 0fr auf 1fr waechst. Kein Fenster, das sich ueber die
  Seite legt.

  Antippbare Zahlen tragen ein kleines Winkelzeichen hinter der Beschriftung.

  DIE SEITE ERKLAERT SICH NICHT SELBST. Keine Bildunterschrift, die eine
  Zeichnung erlaeutert. Keine Zeile, die mir sagt, dass ich tippen kann. Kein
  Schlussabsatz darueber, was die Seite ist und was sie nicht ist. Beschriften
  ja, erklaeren nein: wo eine Zeichnung zwei Spuren zeigt, steht darunter eine
  Legende aus zwei Woertern mit farbigem Punkt, kein Satz. Alles, was begruendet,
  steht in einer Klappe.

  Eine schmale Kopfzeile ueber allem: links ein kleines gezeichnetes Zeichen und
  der Name der Seite, rechts klein und grau die Anzahl der Einheiten und der
  Stand mit Datum. Sonst nichts.

DIE ABSCHNITTE, IN DIESER REIHENFOLGE

  Jeder Abschnitt ausser dem ersten traegt eine kleine graue
  Versalien-Ueberschrift, die nur ihn benennt: Fitness, Wochenbelastung, Zonen,
  Bestleistungen, Diese Woche. Kein Zusatz, keine Einordnung, kein Hinweis
  darauf, was davon anderswo Geld kostet.

1) DER LETZTE LAUF
  In Ruhe: der Name der Einheit als grosse Zeile, darunter klein das Datum und
  ein kurzer Begriff fuer die Art der Einheit - gerechnet aus ihrer Zonenverteilung gegen
  MEINE Zonen aus Schritt 4, nie gegen die des Geraets.

  Darunter die Belastung als sehr grosse, eingefaerbte Zahl auf eigener Flaeche,
  die Beschriftung klein darunter. Sie ist die einzige eingefaerbte Zahl im
  Abschnitt. Darunter eine Reihe aus drei ruhigen Kacheln: Distanz, Tempo, Puls -
  grosse Zahl, Einheit direkt dahinter in deutlich kleinerer Schrift,
  Beschriftung klein und grau darunter.

  Darunter die Einheit als Zeichnung: Puls als Linie in der Akzentfarbe, Tempo
  als graue Flaeche dahinter, beide geglaettet, ohne Achsenkreuz. Darunter die
  Legende aus zwei Woertern.

  Aufgeklappt: bei der Belastung die TRIMP-Formel mit meinen Eingaben und dem
  Anker aus Schritt 5; beim Tempo die Splits je Kilometer samt GAP daneben; beim
  Puls der Mittelwert, der hoechste gehaltene Wert, die Zeit ab Zone 3 und der
  ganze Satz, warum die Einheit so eingeordnet wurde.

  GAP ist das steigungsbereinigte Tempo:

      GAP  = Tempo mal C(0) geteilt durch C(i)
      C(i) = 155,4 i^5 - 30,4 i^4 - 43,3 i^3 + 46,3 i^2 + 19,5 i + 3,6

  i ist die Steigung des Abschnitts, C die Energiekosten je Meter nach Minetti
  2002. Bergauf wird GAP schneller als das gemessene Tempo, bergab langsamer.
  Ohne Hoehenreihe laesst du GAP weg, statt es mit dem Tempo zu fuellen.

2) FITNESS
  In Ruhe: die Fitness als grosse Zahl, daneben in der Beschriftung die
  Veraenderung ueber sieben Tage in Worten. Darunter die Kurve ueber zwoelf
  Monate, und zwar nur sie:
    die Fitnesslinie in der Akzentfarbe, die Flaeche darunter in sehr hellem Grau
    eine gestrichelte Waagerechte auf Hoehe des heutigen Werts
    der heutige Punkt gefuellt
    rechts davon gestrichelt, was die Formel tut, wenn ab heute nichts mehr
      dazukommt - nenn es genau so und nicht Vorhersage meiner Form
    unter der Zeichenflaeche eine Navigatorleiste: ein duenner grauer Balken je
      Tag, Hoehe gleich Tagesbelastung
    Monatsnamen klein darunter
  Eine Zeile fuehrt weiter: "Ermuedung und Frische zeigen".

  Aufgeklappt: die drei Werte Fitness, Ermuedung, Frische mit ihren Formeln, dazu
  die beiden Saetze aus Schritt 5 ueber Einschwingen und fehlende Aufzeichnung.
  Bei der Ermuedung ist ein Anstieg kein Erfolg - faerb ihn nicht gruen.

3) WOCHENBELASTUNG
  In Ruhe: links sieben schmale graue Balken, einer je Wochentag der laufenden
  Woche, mit den Anfangsbuchstaben darunter. Rechts die Wochensumme als sehr
  grosse eingefaerbte Zahl, darunter die Statuszeile - drei Zustaende, und der
  Bezug bin immer ICH, nie eine fremde Norm:
      ueber dem Band    mehr als 1,18 mal der Schnitt der drei Wochen davor
      im Band           dazwischen
      unter dem Band    weniger als 0,82 mal dieser Schnitt

  Darunter zwoelf Wochen nebeneinander: ein hellgraues Band, dessen Hoehe je
  Woche aus dem Schnitt der drei Wochen davor kommt, je Woche ein kleiner hohler
  Kreis auf Hoehe ihrer Summe, die laufende Woche als senkrechte Linie mit
  gefuelltem Punkt in der Statusfarbe. Vier Datumsmarken darunter, mehr nicht.
  Eine Zeile fuehrt weiter: "Wie das Band entsteht".

  Aufgeklappt: die Rechnung fuer Summe und Band mit meinen Werten, dazu der Satz,
  der den Zustand dieser Woche begruendet.

4) ZONEN
  In Ruhe: ein Satz als Ueberschrift, der das Ergebnis nennt - zum Beispiel
  "75 Prozent deiner Zeit liegen unten". Darunter fuenf Balken, je Zone einer:
  links die Marke Z1 bis Z5, dann der Balken, rechts die Zeit. Alle Balken
  beginnen an derselben Nulllinie, die laengste Zone fuellt die Bahn, eine Zone
  mit null Sekunden bekommt gar keinen Balken. Kein Name, kein Bereich, kein
  Prozentwert.

  Die Balken wachsen von null auf ihre Laenge, sobald der Abschnitt ins Bild
  kommt, gestaffelt von oben nach unten.

  Aufgeklappt ueber "Zonen, Grenzen und Tempo": ueber welchen Zeitraum und gegen
  welche Zonen gerechnet wurde, dieselben fuenf Zonen als volle Zeilen mit Name,
  Bereich, Zeit und Prozent, darunter die sechs Tempozonen in derselben Form,
  darunter worauf die Grenzen beruhen - Schwellenpuls oder Prozent vom gemessenen
  Maximum, beim Tempo der VDOT und dass steigungsbereinigt gerechnet wurde - und
  das Ergebnis der Maximalpuls-Pruefung aus Schritt 4 in ganzen Saetzen.

  Fuenf Pulszonen in EINEM Farbton als Rampe von blass nach gesaettigt, sechs
  Tempozonen in einem ANDEREN Farbton, dieselbe Rampe. Der Farbton sagt, welche
  Groesse gemeint ist, die Helligkeit, wie hart.

5) DIE COACH-ANALYSE
  Eine eigene Karte. Kopfzeile: ein kleines rundes Zeichen in der Akzentfarbe,
  daneben der Name, daneben klein und grau in Versalien, woher sie kommt.
  Darunter zwei Saetze Fliesstext, gross genug zum Lesen, OHNE Zahlen. Darunter
  ein Knopf ueber die volle Breite in der ausgeblassten Akzentfarbe, Schrift in
  der Akzentfarbe: "Mehr dazu".

  Aufgeklappt stehen dort der Befundsatz fett, der Absatz dazu, die drei
  Belegzahlen mit Datum und der eine Satz, was ich diese Woche anders mache.

6) BESTLEISTUNGEN
  In Ruhe: drei bis vier Zeilen, je Zeile ein kleines Emblem, das du selbst
  zeichnest, dann fett die Strecke, dahinter die Zeit in Klammern. Nimm die
  laengsten Strecken, fuer die es eine Bestleistung gibt. Eine Zeile fuehrt
  weiter: "Alle Strecken und die Vorhersage".

  Aufgeklappt: die volle Tabelle aus Schritt 5 mit Strecke, Zeit, Tempo und
  Datum, darunter die Vorhersage mit drei Spalten - Riegel, Daniels und, wenn das
  Geraet eine liefert, "dein Geraet" - und der Satz, dass die Spanne zwischen zwei
  Rechenwegen keine Panne ist, sondern die ehrliche Spanne.

7) DIESE WOCHE
  In Ruhe: die Laufkilometer der laufenden Woche als grosse Zahl, darunter klein
  die Summe ueber zwoelf Monate. Darunter sieben Blasen, eine Spalte je Tag: je
  Einheit eine Blase, Flaeche nach Dauer, der Wert IN der Blase, der Wochentag
  klein darunter. Die Blasen aller Tage stehen in einem Feld gleicher Hoehe,
  damit die Wochentage auf einer Linie liegen. Ein Tag ohne Einheit bekommt einen
  leeren gestrichelten Kreis. Laufen und anderer Sport haben verschiedene Farben;
  Rad, Kraft und Wandern zaehlen mit, aber nie als Laufkilometer. Eine Zeile
  fuehrt weiter: "Sieben Wochen davor".

  Aufgeklappt: dieselben Blasenwochen fuer die sieben Wochen davor, neueste oben,
  je Woche der Zeitraum und die Laufkilometer darueber.

Danach endet die Seite. Kein Schlussabsatz, keine Quellenzeile, kein Impressum.
Den Ehrlichkeitscheck aus Schritt 7 baust du nicht auf die Seite, den druckst du
mir in den Chat.

BEWEGUNG - LEISE, SCHNELL, EINMAL

  Abschnitte treten auf, wenn sie ins Bild kommen, nicht beim Laden: gleichzeitig
  ein kurzer Weg von unten und ein Aufblenden. Die Feder ist kritisch gedaempft
  und in 0,45 bis 0,55 Sekunden am Ziel, die Deckkraft laeuft voraus und ist nach
  0,30 Sekunden fertig. Teile innerhalb eines Abschnitts staffelst du um 0,11
  Sekunden.

  Ueberschwingen darf hoechstens ein Gegenstand je Abschnitt, und nur einer mit
  Schwung: hier das Blatt der Coach-Analyse. Alles andere kommt ohne Nachwippen
  zur Ruhe. Was verschwindet, geht denselben Weg rueckwaerts, kuerzer, in 0,30
  Sekunden.

  Was ich antippe, antwortet im Klickframe: der Gegenstand geht kurz auf 98,5
  Prozent und in etwa 0,15 Sekunden zurueck, nicht erst beim Loslassen.

  Grosse Zahlen zaehlen beim Auftritt einmal hoch, hoechstens 0,6 Sekunden lang,
  mit auslaufender Kurve. Der Endwert ist auf die Stelle genau derselbe wie der,
  der ohne Bewegung dasteht.

  Nichts bewegt sich dauerhaft. Keine Schleife, kein Pulsieren, kein wandernder
  Hintergrund.

  Fragt der Rechner nach reduzierter Bewegung (prefers-reduced-motion), zeigst du
  alles sofort und fertig: keine Auftritte, keine Hochlaeufe, keine wachsenden
  Balken. Die Seite muss in diesem Zustand vollstaendig lesbar sein.

  Dazu ein Merkmal am html-Element, mit dem ich die Seite einfrieren kann:
  data-stand="voll" zeigt alle Abschnitte fertig aufgetreten, data-stand="alles"
  oeffnet zusaetzlich jede Klappe.

  Das Skript dafuer steht in der Datei selbst und ist klein: ein
  IntersectionObserver fuer die Auftritte, ein Klickverhalten fuer die Klappen,
  die Druckantwort, die Hochlaeufe. Keine Bibliothek.

DESIGNVORGABEN - BITTE GENAU SO

  Die Seite ist dunkel. Nicht abgedunkelt hell, sondern von vorn dunkel gedacht:
  echtes Schwarz als Grund, die Karten eine Spur darueber, damit sie schweben.

  Grund      #000000, Karten #121214, Flaechen in Karten #1C1C1E
  Linien     rgba(255,255,255,.10), 1 Pixel, keine Schatten
  Schrift    #F5F5F7, zweite Ebene #AEAEB4, dritte #79797F
  Akzent     genau ein warmer Ton, zum Beispiel #D97757 - Zeichen, weiterfuehrende
             Zeilen, Fitnesslinie, Pulsspur, heutiger Punkt. Der Coach-Knopf ist
             damit nur getoent (rgba(217,119,87,.14)), nicht gefuellt.
  Belastung  eigene Skala von blassem Lila ueber gesaettigtes Violett nach Rot:
             0 = #AD9FF6, 45 = #AF3CFE, 100 = #BE0C0F, dazwischen linear gemischt
  Pulszonen  Rampe in Rot:  #8C6B60 #A97463 #C2705A #DA5E3F #F04B34
  Tempozonen Rampe in Blau: #55707F #5C8199 #6494B4 #6FA7CA #84BBDD #9CCDEB
  Blasen     Laufen #6FBF2A mit dunkler Schrift darin, anderer Sport #48484C
  Radius     18 Pixel fuer Karten, 14 fuer Klappen, rund fuer Blasen
  Schrift    system-ui, dann Helvetica Neue, dann Arial
  Grade      grosse Zahlen 44 bis 64 Pixel, Zeilenhoehe 1,05, Laufweite -0,03 em;
             Ueberschriften 26 Pixel bei -0,028 em; Fliesstext 16 Pixel bei
             normaler Laufweite; Versalien-Ueberschriften 11,5 Pixel mit
             0,12 em Sperrung. Ziffern immer mit gleicher Breite
             (font-variant-numeric: tabular-nums).

  Farbe traegt Bedeutung, nicht Dekoration: die Belastungsskala, die Zonenrampen
  und der Akzent sind Information. Sonst bleibt alles grau.

  Leg alle Farben als CSS-Variablen an, den Akzent an genau einer Stelle. Bau
  denselben Satz Variablen auch hell und schalt ihn ueber ein Merkmal am
  html-Element:

  hell       Grund #FBFBFD, Karten #FFFFFF, Flaechen #F2F2F4, Linien #EBEBEF,
             Schrift #111113 / #5C5C63 / #9A9AA2, Akzent #F24E1E
             Pulszonen  #F6C9C0 #EFA294 #E4776A #D9412B #A8180C
             Tempozonen #CBDDF0 #A3C4E5 #79A8D6 #4E85C1 #2A5FA0 #17406F
             Blasen Laufen #7ED321, anderer Sport #C7C7CC

  Die beiden Rampensaetze sind nicht ineinander umrechenbar. Eine helle Rampe auf
  Schwarz abgedunkelt ergibt einen Z1-Balken, der sich mit 1,6 zu 1 von seiner
  eigenen Spur abhebt - unsichtbar, und zwar ausgerechnet bei der groessten Zone.
  Jeder Balken kommt gegen seine Flaeche auf mindestens 3 zu 1. Rechne das nach.
  Die Grauleiter ist streng neutral: Rot, Gruen und Blau sind in jedem Grauton
  gleich.

  Alle Diagramme zeichnest du als SVG-Pfade aus den echten Punkten, ohne
  Bibliothek.

  Pruef jede Text-auf-Grund-Kombination auf mindestens 4,5 zu 1 Kontrast und
  schreib mir die gerechneten Werte hin. Nicht schaetzen.

  Jede Zahl auf dem Schirm laesst sich auf ein Feld aus Schritt 3 oder eine Formel
  aus Schritt 5 zurueckfuehren. Ist etwas geschaetzt, steht das dran.

  Bau KEINE fremde Marke nach. Die Anordnung einer Trainingsseite und die Form
  eines Diagramms gehoeren niemandem - ein Logo, eine Wortmarke, ein
  Markenfarbwert, ein abgeschriebener Textbaustein und ein nachgezeichnetes
  Symbol gehoeren schon jemandem. Also: gleiche Bauteile, eigene Werte, eigene
  Woerter, eigene Zeichnung.


SCHRITT 7 - DER EHRLICHKEITSCHECK

Bevor du mir sagst, dass es fertig ist, lass das hier laufen und druck die
Ergebnisse:

1. Anzahl Einheiten insgesamt, mit Pulsreihe, mit Distanzreihe. Drei Zahlen.
2. Die Punktdichte: Punkte je Einheit gegen Dauer in Sekunden, als Verhaeltnis,
   fuer die fuenf laengsten Einheiten. Liegt es unter 0,95, ist die Reihe
   ausgeduennt und die Belastung zu glatt.
3. Sekunden ohne Pulswert je Einheit, alle ueber 5 Prozent mit Datum.
4. Profil-Maximalpuls gegen gemessenes Maximum, mit der Differenz.
5. Die Verteilung der Belastung ueber alle Tage: wie viele Tage ueber 100 liegen,
   und wie hoch der hoechste Tag war. Rund fuenf Prozent ueber 100 ist richtig so.
   Mehr als zehn Prozent heisst, der Anker stimmt nicht.
6. Tage ohne jede Aufzeichnung, gezaehlt. Miss dabei nicht Ruhe mit fehlender
   Aufzeichnung gleich.
7. Der Anteil meiner Kilometer im lockeren Tempobereich, als eine Zahl.
8. Meine eigenen Bestleistungen gegen die des Herstellers, je Distanz, mit
   Differenz.


SCHRITT 8 - EINE GEWOHNHEIT, KEIN EINMALEFFEKT

Gib mir einen Befehl, der die Synchronisierung neu laufen laesst und die Seite neu
baut. Er holt nur die Einheiten, die seit dem letzten Lauf dazugekommen sind, und
rechnet die Reihen fort - kein Vollabzug.

Sag mir, wohin er gehoert, damit er nach jedem Training laeuft. Unter macOS ein
LaunchAgent, unter Linux cron oder ein systemd-Timer, unter Windows die
Aufgabenplanung.

Sei dabei ehrlich zu mir: Die Seite aktualisiert sich nicht von selbst, sie wird
neu gerechnet, wenn dieser Befehl laeuft. Wenn er einmal die Woche laeuft, ist die
Seite einmal die Woche aktuell.

Zwei Dinge, die dabei schiefgehen: Ein Auftrag, der eine Shell startet, bekommt
unter macOS in meinem Dokumentenordner keine Rechte - ruf das Python der
virtuellen Umgebung direkt auf. Und leg eine Ignorierliste an, die Token,
Gesundheitsdaten, Logs und die virtuelle Umgebung ausschliesst, falls ich den
Ordner je versioniere.


WAS DU NICHT TUST

Du erfindest keine Zahl. Fehlt ein Wert, steht da, dass er fehlt.

Du benutzt keinen Durchschnittspuls, wo eine Punktreihe vorliegt. Der Durchschnitt
ist der Grund, warum Intervalle und Dauerlaeufe gleich aussehen.

Du baust keinen Schalter ein, mit dem sich ein Wert von Hand setzen laesst. Was
gerechnet wird, wird gerechnet.

Du deckelst die Belastung nicht bei 100, damit die Verteilung ordentlich aussieht.
Ein harter Tag ueber 100 ist ein harter Tag, kein Fehler - erst eine Haeufung
zeigt, dass der Anker nicht stimmt.

Du faerbst nichts gruen, weil es schoener aussieht, und nichts rot, weil es
eindrucksvoller ist.

Du gibst mir keine medizinische Einschaetzung. Du bist kein Arzt und tust auch
nicht so. Wenn dir etwas auffaellt, das eine Abklaerung verdient - Brustschmerz,
Puls, der bei lockerem Tempo nicht runtergeht, Schwindel -, sagst du mir das in
einem Satz und schickst mich zu einem Menschen.

Du schreibst nichts in mein Strava- oder Garmin-Konto zurueck. Nur lesen.


WAS DAS NICHT ERSETZT

Sag mir das am Ende ehrlich zurueck, ich will es lieber wissen:

- Segment-Bestenlisten, Local Legend, Herausforderungen, Beacon, Routenplanung,
  Heatmaps und die ganze soziale Schicht bleiben da, wo sie sind. Ersetzt wird die
  Auswertung, nicht das Netzwerk. Mein kostenloses Konto bleibt bestehen.
- Diese Zahlen sind MEINE, nicht ihre. Die Bausteine sind belegt - TRIMPexp ist
  publiziert, die exponentielle Glaettung ueber 42 und 7 Tage ist ein alter,
  offen beschriebener Ansatz -, die Zusammensetzung darueber ist eine begruendete
  Nachbildung. Kein Anbieter legt seine Version offen. Deshalb kann niemand
  behaupten, das hier sei dieselbe Zahl. Der Unterschied ist ein anderer: du
  kannst hier jeden Schritt nachlesen und mir widersprechen.
- Ein Modell, das aus zwei geglaetteten Reihen einen Formzustand ableitet, weiss
  nichts von Schlaf, Stress, Krankheit, Hitze oder dem Leben zwischen den
  Einheiten. Es sagt, wie viel du trainiert hast, nicht wie es dir geht.
- Die Dateien bleiben auf meinem Rechner. Die Werte, die wir hier im Chat
  besprechen, nicht - das laeuft ueber ein Rechenzentrum. Wenn mir das zu weit
  geht, sag es mir jetzt und nicht hinterher.

—
Dieser Prompt ist Folge 13 von 100 aus "Sport KI" von Dan Felser.
Instagram: @felsr — alle Prompts der Reihe: felsr.com
Der Prompt kostet nichts. Wenn er dir was bringt: folg mir auf @felsr — dort kommt jede Folge zuerst. Kostenlose Trainingspläne
20 Pläne, 5 km bis Marathon — ohne E-Mail, ohne Konto
Alle Prompts der Reihe
Sport KI — 100 Folgen, jede Woche ein Tool aus meinem Training