Dokumentacja techniczna i formuły
Kompletna implementacja matematyczna
Przewodnik implementacji
Ta strona zawiera formuły gotowe do skopiowania oraz metodologie krok po kroku dla wszystkich wskaźników Run Analytics. Użyj ich do własnych implementacji, weryfikacji lub głębszego zrozumienia.
⚠️ Uwagi dotyczące implementacji
- Wszystkie czasy powinny być konwertowane na sekundy do obliczeń
- Tempo biegu jest odwrotne (wyższy % = wolniejsze tempo)
- Zawsze sprawdzaj poprawność danych wejściowych pod kątem rozsądnych zakresów
- Obsługuj przypadki skrajne (dzielenie przez zero, wartości ujemne)
Podstawowe wskaźniki wydajności
Krytyczna prędkość biegowa (CRS)
Formuła:
CRS (m/s) = (D₂ - D₁) / (T₂ - T₁)
Tempo CRS/100m (sekundy) = (T₄₀₀ - T₂₀₀) / 2
🧪 Interaktywny kalkulator - Przetestuj formułę
Tempo CRS na 100m:
1:49
Kroki obliczeń:
CRS (m/s) = (400 - 200) / (368 - 150) = 0.917 m/s
Tempo/100m = 100 / 0.917 = 109 sekund = 1:49
CRS (m/s) = (400 - 200) / (368 - 150) = 0.917 m/s
Tempo/100m = 100 / 0.917 = 109 sekund = 1:49
Implementacja JavaScript:
function calculateCRS(distance1, time1, distance2, time2) {
// Konwertuj czasy na sekundy, jeśli potrzeba
const t1 = typeof time1 === 'string' ? timeToSeconds(time1) : time1;
const t2 = typeof time2 === 'string' ? timeToSeconds(time2) : time2;
// Oblicz CRS w m/s
const css_ms = (distance2 - distance1) / (t2 - t1);
// Oblicz tempo na 100m w sekundach
const pace_per_100m = 100 / css_ms;
// Konwertuj do formatu mm:ss
const minutes = Math.floor(pace_per_100m / 60);
const seconds = Math.round(pace_per_100m % 60);
return {
css_ms: css_ms,
pace_seconds: pace_per_100m,
pace_formatted: `${minutes}:${seconds.toString().padStart(2, '0')}`
};
}
// Przykład użycia:
const result = calculateCRS(200, 150, 400, 368);
// Zwraca: { css_ms: 0.917, pace_seconds: 109, pace_formatted: "1:49" }
Wynik obciążenia treningowego (sTSS)
Pełna formuła:
sTSS = (IF³) × Czas trwania (godziny) × 100
IF = NSS / FTP
NSS = Całkowity dystans / Całkowity czas (m/min)
🧪 Interaktywny kalkulator - Przetestuj formułę
Obliczone sTSS:
55
Kroki obliczeń:
NSS = 3000m / 55min = 54.5 m/min
FTP = 100 / (93/60) = 64.5 m/min
IF = 54.5 / 64.5 = 0.845
sTSS = 0.845³ × (55/60) × 100 = 55
NSS = 3000m / 55min = 54.5 m/min
FTP = 100 / (93/60) = 64.5 m/min
IF = 54.5 / 64.5 = 0.845
sTSS = 0.845³ × (55/60) × 100 = 55
Implementacja JavaScript:
function calculateSTSS(distance, timeMinutes, ftpMetersPerMin) {
// Oblicz znormalizowaną prędkość biegu
const nss = distance / timeMinutes;
// Oblicz współczynnik intensywności
const intensityFactor = nss / ftpMetersPerMin;
// Oblicz godziny
const hours = timeMinutes / 60;
// Oblicz sTSS używając współczynnika intensywności do sześcianu
const stss = Math.pow(intensityFactor, 3) * hours * 100;
return Math.round(stss);
}
// Przykład użycia:
const stss = calculateSTSS(3000, 55, 64.5);
// Zwraca: 55
// Funkcja pomocnicza: Konwertuj CRS na FTP
function cssToFTP(cssPacePer100mSeconds) {
// FTP w m/min = 100m / (tempo w minutach)
return 100 / (cssPacePer100mSeconds / 60);
}
// Przykład: CRS 1:33 (93 sekundy)
const ftp = cssToFTP(93); // Zwraca: 64.5 m/min
Efektywność biegu
Formuła:
Efektywność biegu = Czas kilometra (sekundy) + Liczba kroków
Efektywność biegu₂₅ = (Czas × 25/Długość trasy) + (Kroki × 25/Długość trasy)
🧪 Interaktywny kalkulator - Przetestuj formułę
Wynik efektywności biegu:
35
Obliczenia:
Efektywność biegu = 20s + 15 kroków = 35
Efektywność biegu = 20s + 15 kroków = 35
Implementacja JavaScript:
function calculateRunningEfficiency(timeSeconds, strideCount) {
return timeSeconds + strideCount;
}
function calculateNormalizedRunningEfficiency(timeSeconds, strideCount, trackLength) {
const normalizedTime = timeSeconds * (25 / trackLength);
const normalizedStrides = strideCount * (25 / trackLength);
return normalizedTime + normalizedStrides;
}
// Przykład:
const swolf = calculateRunningEfficiency(20, 15);
// Zwraca: 35
const swolf50m = calculateNormalizedRunningEfficiency(40, 30, 50);
// Zwraca: 35 (znormalizowane do 25m)
Mechanika kroków
Częstotliwość kroków (SR)
Formuła:
SR = 60 / Czas cyklu (sekundy)
SR = (Liczba kroków / Czas w sekundach) × 60
🧪 Interaktywny kalkulator - Przetestuj formułę
Częstotliwość kroków (SPM):
72
Obliczenia:
SR = (30 / 25) × 60 = 72 SPM
SR = (30 / 25) × 60 = 72 SPM
Implementacja JavaScript:
function calculateStrideRate(strideCount, timeSeconds) {
return (strideCount / timeSeconds) * 60;
}
// Przykład:
const sr = calculateStrideRate(30, 25);
// Zwraca: 72 SPM
Dystans na krok (DPS)
Formuła:
DPS = Dystans / Liczba kroków
DPS = Dystans / (SR / 60)
Implementacja JavaScript:
function calculateDPS(distance, strideCount, pushoffDistance = 0) {
const effectiveDistance = distance - pushoffDistance;
return effectiveDistance / strideCount;
}
// Przykład (trasa 25m, 5m odbicia):
const dps = calculateDPS(25, 12, 5);
// Zwraca: 1.67 m/krok
// Dla wielu segmentów:
const dps100m = calculateDPS(100, 48, 4 * 5);
// Zwraca: 1.67 m/krok (4 segmenty × 5m odbicia)
Prędkość z SR i DPS
Formuła:
Prędkość (m/s) = (SR / 60) × DPS
Implementacja JavaScript:
function calculateVelocity(strideRate, dps) {
return (strideRate / 60) * dps;
}
// Przykład:
const velocity = calculateVelocity(70, 1.6);
// Zwraca: 1.87 m/s
Wskaźnik kroku (SI)
Formuła:
SI = Prędkość (m/s) × DPS (m/krok)
Implementacja JavaScript:
function calculateStrideIndex(velocity, dps) {
return velocity * dps;
}
// Przykład:
const si = calculateStrideIndex(1.5, 1.7);
// Zwraca: 2.55
Wykres zarządzania wydajnością (PMC)
Obliczenia CTL, ATL, TSB
Formuły:
CTL dzisiaj = CTL wczoraj + (TSS dzisiaj - CTL wczoraj) × (1/42)
ATL dzisiaj = ATL wczoraj + (TSS dzisiaj - ATL wczoraj) × (1/7)
TSB = CTL wczoraj - ATL wczoraj
Implementacja JavaScript:
function updateCTL(previousCTL, todayTSS) {
return previousCTL + (todayTSS - previousCTL) * (1/42);
}
function updateATL(previousATL, todayTSS) {
return previousATL + (todayTSS - previousATL) * (1/7);
}
function calculateTSB(yesterdayCTL, yesterdayATL) {
return yesterdayCTL - yesterdayATL;
}
// Oblicz PMC dla serii treningów
function calculatePMC(workouts) {
let ctl = 0, atl = 0;
const results = [];
workouts.forEach(workout => {
ctl = updateCTL(ctl, workout.tss);
atl = updateATL(atl, workout.tss);
const tsb = calculateTSB(ctl, atl);
results.push({
date: workout.date,
tss: workout.tss,
ctl: Math.round(ctl * 10) / 10,
atl: Math.round(atl * 10) / 10,
tsb: Math.round(tsb * 10) / 10
});
});
return results;
}
// Przykład użycia:
const workouts = [
{ date: '2025-01-01', tss: 50 },
{ date: '2025-01-02', tss: 60 },
{ date: '2025-01-03', tss: 45 },
// ... więcej treningów
];
const pmc = calculatePMC(workouts);
// Zwraca tablicę z CTL, ATL, TSB dla każdego dnia
Zaawansowane obliczenia
CRS z wielu dystansów (metoda regresji)
Implementacja JavaScript:
function calculateCRSRegression(distances, times) {
// Regresja liniowa: dystans = a + b*czas
const n = distances.length;
const sumX = times.reduce((a, b) => a + b, 0);
const sumY = distances.reduce((a, b) => a + b, 0);
const sumXY = times.reduce((sum, x, i) => sum + x * distances[i], 0);
const sumXX = times.reduce((sum, x) => sum + x * x, 0);
const slope = (n * sumXY - sumX * sumY) / (n * sumXX - sumX * sumX);
const intercept = (sumY - slope * sumX) / n;
return {
css: slope, // Krytyczna prędkość biegowa (m/s)
anaerobic_capacity: intercept // Beztlenowa pojemność dystansowa (m)
};
}
// Przykład z wieloma dystansami testowymi:
const distances = [100, 200, 400, 800];
const times = [65, 150, 340, 720]; // w sekundach
const result = calculateCRSRegression(distances, times);
// Zwraca: { css: 1.18, anaerobic_capacity: 15.3 }
Współczynnik intensywności z tempa
Implementacja JavaScript:
function calculateIntensityFactor(actualPace100m, thresholdPace100m) {
// Konwertuj tempo na prędkość (m/s)
const actualSpeed = 100 / actualPace100m;
const thresholdSpeed = 100 / thresholdPace100m;
return actualSpeed / thresholdSpeed;
}
// Przykład:
const if_value = calculateIntensityFactor(110, 93);
// Zwraca: 0.845 (bieg na 84.5% progu)
Analiza równości tempa
Implementacja JavaScript:
function analyzePaceConsistency(segments) {
const paces = segments.map(kilometer => kilometer.distance / kilometer.time);
const avgPace = paces.reduce((a, b) => a + b) / paces.length;
const variance = paces.reduce((sum, pace) =>
sum + Math.pow(pace - avgPace, 2), 0) / paces.length;
const stdDev = Math.sqrt(variance);
const coefficientOfVariation = (stdDev / avgPace) * 100;
return {
avgPace,
stdDev,
coefficientOfVariation,
consistency: coefficientOfVariation < 5 ? "Doskonała" :
coefficientOfVariation < 10 ? "Dobra" :
coefficientOfVariation < 15 ? "Umiarkowana" : "Zmienna"
};
}
// Przykład:
const segments = [
{ distance: 100, time: 70 },
{ distance: 100, time: 72 },
{ distance: 100, time: 71 },
// ...
];
const analysis = analyzePaceConsistency(segments);
// Zwraca: { avgPace: 1.41, stdDev: 0.02, coefficientOfVariation: 1.4, consistency: "Doskonała" }
Wykrywanie zmęczenia na podstawie liczby kroków
Implementacja JavaScript:
function detectFatigue(segments) {
const firstThird = segments.slice(0, Math.floor(segments.length/3));
const lastThird = segments.slice(-Math.floor(segments.length/3));
const firstThirdAvg = firstThird.reduce((sum, kilometer) =>
sum + kilometer.strideCount, 0) / firstThird.length;
const lastThirdAvg = lastThird.reduce((sum, kilometer) =>
sum + kilometer.strideCount, 0) / lastThird.length;
const strideCountIncrease = ((lastThirdAvg - firstThirdAvg) / firstThirdAvg) * 100;
return {
firstThirdAvg: Math.round(firstThirdAvg * 10) / 10,
lastThirdAvg: Math.round(lastThirdAvg * 10) / 10,
percentIncrease: Math.round(strideCountIncrease * 10) / 10,
fatigueLevel: strideCountIncrease < 5 ? "Minimalne" :
strideCountIncrease < 10 ? "Umiarkowane" :
strideCountIncrease < 20 ? "Znaczne" : "Ciężkie"
};
}
// Przykład:
const segments = [
{ strideCount: 14 }, { strideCount: 14 }, { strideCount: 15 },
{ strideCount: 15 }, { strideCount: 16 }, { strideCount: 16 },
{ strideCount: 17 }, { strideCount: 18 }, { strideCount: 18 }
];
const fatigue = detectFatigue(segments);
// Zwraca: { firstThirdAvg: 14.3, lastThirdAvg: 17.7, percentIncrease: 23.8, fatigueLevel: "Ciężkie" }
Walidacja danych
Kontrole jakości danych treningowych
Implementacja JavaScript:
function validateWorkoutData(workout) {
const issues = [];
// Sprawdź rozsądne zakresy tempa (1:00-5:00 na 100m)
const avgPace = (workout.totalTime / workout.totalDistance) * 100;
if (avgPace < 60 || avgPace > 300) {
issues.push(`Nietypowe średnie tempo: ${Math.round(avgPace)}s na 100m`);
}
// Sprawdź rozsądną liczbę kroków (10-50 na 25m)
const avgStridesPer25m = (workout.totalStrides / workout.totalDistance) * 25;
if (avgStridesPer25m < 10 || avgStridesPer25m > 50) {
issues.push(`Nietypowa liczba kroków: ${Math.round(avgStridesPer25m)} na 25m`);
}
// Sprawdź rozsądną częstotliwość kroków (30-150 SPM)
const avgSR = calculateStrideRate(workout.totalStrides, workout.totalTime);
if (avgSR < 30 || avgSR > 150) {
issues.push(`Nietypowa częstotliwość kroków: ${Math.round(avgSR)} SPM`);
}
// Sprawdź brakujące segmenty (przerwy w czasie)
if (workout.segments && workout.segments.length > 1) {
for (let i = 1; i < workout.segments.length; i++) {
const gap = workout.segments[i].startTime -
(workout.segments[i-1].startTime + workout.segments[i-1].duration);
if (gap > 300) { // 5-minutowa przerwa
issues.push(`Wykryto dużą przerwę między segmentami ${i} i ${i+1}`);
}
}
}
return {
isValid: issues.length === 0,
issues
};
}
// Przykład:
const workout = {
totalDistance: 2000,
totalTime: 1800, // 30 minut
totalStrides: 800,
segments: [/* dane kilometrów */]
};
const validation = validateWorkoutData(workout);
// Zwraca: { isValid: true, issues: [] }
Funkcje pomocnicze
Narzędzia konwersji czasu
Implementacja JavaScript:
// Konwertuj mm:ss na sekundy
function timeToSeconds(timeString) {
const parts = timeString.split(':');
return parseInt(parts[0]) * 60 + parseInt(parts[1]);
}
// Konwertuj sekundy na mm:ss
function secondsToTime(seconds) {
const minutes = Math.floor(seconds / 60);
const secs = Math.round(seconds % 60);
return `${minutes}:${secs.toString().padStart(2, '0')}`;
}
// Konwertuj sekundy na hh:mm:ss
function secondsToTimeDetailed(seconds) {
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const secs = Math.round(seconds % 60);
return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
}
// Przykłady:
timeToSeconds("1:33"); // Zwraca: 93
secondsToTime(93); // Zwraca: "1:33"
secondsToTimeDetailed(3665); // Zwraca: "1:01:05"
Zasoby implementacji
Wszystkie formuły na tej stronie są gotowe do produkcji i zwalidowane względem literatury naukowej. Użyj ich do tworzenia własnych narzędzi analitycznych, weryfikacji lub głębszego zrozumienia obliczeń wydajności biegowej.
💡 Najlepsze praktyki
- Waliduj dane wejściowe: Sprawdź rozsądne zakresy przed obliczeniami
- Obsługuj przypadki skrajne: Dzielenie przez zero, wartości ujemne, brak danych
- Zaokrąglaj odpowiednio: CTL/ATL/TSB do 1 miejsca po przecinku, sTSS do liczby całkowitej
- Przechowuj precyzję: Zachowaj pełną precyzję w bazie danych, zaokrąglaj tylko do wyświetlania
- Testuj dokładnie: Użyj sprawdzonych danych do weryfikacji obliczeń