Referensi Teknis & Formula
Implementasi Matematika Lengkap
Panduan Implementasi
Halaman ini menyediakan formula siap pakai dan metode perhitungan langkah demi langkah untuk semua metrik Run Analytics. Gunakan ini untuk implementasi kustom, verifikasi, atau pemahaman yang lebih mendalam.
⚠️ Catatan Implementasi
- Semua waktu harus dikonversi ke detik untuk perhitungan
- Perhitungan rTSS menggunakan Intensity Factor kuadrat (IF²)
- Selalu validasi input untuk rentang yang wajar
- Tangani kasus ekstrem (pembagian dengan nol, nilai negatif)
Metrik Performa Inti
Kecepatan Lari Kritis (CRS)
Formula:
CRS (m/s) = (D₂ - D₁) / (T₂ - T₁)
Pace CRS (mnt/km) = 16.667 / CRS (m/s)
🧪 Kalkulator Interaktif - Uji Formulanya
Pace CRS (mnt/km):
4:17
Langkah perhitungan:
CRS (m/s) = (3600 - 1200) / (900 - 270) = 3.81 m/s
Pace (mnt/km) = 1000 / 3.81 = 262 detik = 4:22
CRS (m/s) = (3600 - 1200) / (900 - 270) = 3.81 m/s
Pace (mnt/km) = 1000 / 3.81 = 262 detik = 4:22
Implementasi JavaScript:
function calculateCRS(distance1, time1, distance2, time2) {
// Konversi waktu ke detik
const t1 = typeof time1 === 'string' ? timeToSeconds(time1) : time1;
const t2 = typeof time2 === 'string' ? timeToSeconds(time2) : time2;
// Hitung kecepatan CRS dalam m/s
const crs_ms = (distance2 - distance1) / (t2 - t1);
// Hitung pace per km dalam detik
const pace_per_km = 1000 / crs_ms;
// Konversi ke format mm:ss
const minutes = Math.floor(pace_per_km / 60);
const seconds = Math.round(pace_per_km % 60);
return {
velocity_ms: crs_ms,
pace_seconds: pace_per_km,
pace_formatted: `${minutes}:${seconds.toString().padStart(2, '0')}`
};
}Skor Stres Lari (rTSS)
Formula Lengkap:
rTSS = (IF²) × Durasi (jam) × 100
IF = NSS / Kecepatan Ambang
NSS = Total Jarak / Total Waktu (m/mnt)
🧪 Kalkulator Interaktif - Uji Formulanya
Hasil Perhitungan rTSS:
31
Langkah perhitungan:
NSS = 5000m / 25mnt = 200 m/mnt
FTP = 1000 / (255/60) = 235.3 m/mnt
IF = 200 / 235.3 = 0.850
rTSS = 0.850² × (25/60) × 100 = 31
NSS = 5000m / 25mnt = 200 m/mnt
FTP = 1000 / (255/60) = 235.3 m/mnt
IF = 200 / 235.3 = 0.850
rTSS = 0.850² × (25/60) × 100 = 31
Implementasi JavaScript:
function calculateRTSS(distance, timeMinutes, ftpMetersPerMin) {
// Hitung Kecepatan Lari Normal (NSS)
const nss = distance / timeMinutes;
// Hitung Faktor Intensitas (IF)
const intensityFactor = nss / ftpMetersPerMin;
// Hitung jam
const hours = timeMinutes / 60;
// Hitung rTSS menggunakan kuadrat faktor intensitas
const rtss = Math.pow(intensityFactor, 2) * hours * 100;
return Math.round(rtss);
}
// Contoh penggunaan:
const rtss = calculateRTSS(3000, 55, 64.5);
// Mengembalikan: 65
// Pembantu: Konversi Pace CRS ke Kecepatan Lari (m/mnt)
function crsPaceToSpeed(crsPacePerKmSeconds) {
// Kecepatan dalam m/mnt = 1000m / (pace dalam menit)
return 1000 / (crsPacePerKmSeconds / 60);
}
// Contoh: CRS 4:15 (255 detik)
const speed = crsPaceToSpeed(255); // Mengembalikan: 235.3 m/mntEfisiensi Biomekanik: Rasio Vertikal
Formula:
Rasio Vertikal (%) = (Osilasi Vertikal ÷ Panjang Langkah) × 100
🧪 Kalkulator Interaktif - Uji Formulanya
Rasio Vertikal:
7.4%
Perhitungan:
Rasio Vertikal = (8.5 / 115) × 100 = 7.4%
Rasio Vertikal = (8.5 / 115) × 100 = 7.4%
Implementasi JavaScript:
function calculateVerticalRatio(oscillationCm, strideLengthCm) {
return (oscillationCm / strideLengthCm) * 100;
}
function calculateEfficiencyFactor(paceMetersPerMin, avgHeartRate) {
return paceMetersPerMin / avgHeartRate;
}Berlari Mekanika Langkah
Frekuensi Langkah (SR)
Formula:
SR = 60 / Waktu Siklus (detik)
SR = (Jumlah Langkah / Waktu dalam detik) × 60
🧪 Kalkulator Interaktif - Uji Formulanya
Kadens (SPM):
180
Perhitungan:
Kadens = (180 / 60) × 60 = 180 SPM
Kadens = (180 / 60) × 60 = 180 SPM
Implementasi JavaScript:
function calculateCadence(stepCount, timeSeconds) {
return (stepCount / timeSeconds) * 60;
}
// Contoh:
const spm = calculateCadence(180, 60);
// Mengembalikan: 180 SPMPanjang Langkah
Formula:
Panjang Langkah = Jarak / (Jumlah Langkah / 2)
Panjang Langkah = Kecepatan / (Kadens / 120)
Implementasi JavaScript:
function calculateStrideLength(distanceMeters, stepCount) {
// Panjang langkah adalah jarak / jumlah pasangan langkah (kiri+kanan)
return distanceMeters / (stepCount / 2);
}
// Contoh (1000m, 800 langkah):
const strideLength = calculateStrideLength(1000, 800);
// Mengembalikan: 2.50 meter per langkahKecepatan dari SR dan DPS
Formula:
Kecepatan (m/s) = (SR / 60) × DPS
Implementasi JavaScript:
function calculateVelocity(strideRate, dps) {
return (strideRate / 60) * dps;
}
// Contoh:
const velocity = calculateVelocity(70, 1.6);
// Mengembalikan: 1.87 m/sIndeks Langkah (SI)
Formula:
SI = Kecepatan (m/s) × DPS (m/langkah)
Implementasi JavaScript:
function calculateStrideIndex(velocity, dps) {
return velocity * dps;
}
// Contoh:
const si = calculateStrideIndex(1.5, 1.7);
// Mengembalikan: 2.55Grafik Manajemen Performa (PMC) untuk Berlari
Perhitungan CTL, ATL, TSB
Formula:
CTL hari ini = CTL kemarin + (TSS hari ini - CTL kemarin) × (1/42)
ATL hari ini = ATL kemarin + (TSS hari ini - ATL kemarin) × (1/7)
TSB = CTL kemarin - ATL kemarin
Implementasi 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;
}
// Hitung PMC untuk serangkaian latihan
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;
}
// Contoh penggunaan:
const workouts = [
{ date: '2025-01-01', tss: 50 },
{ date: '2025-01-02', tss: 60 },
{ date: '2025-01-03', tss: 45 },
// ... latihan lainnya
];
const pmc = calculatePMC(workouts);
// Mengembalikan array dengan CTL, ATL, TSB untuk setiap hariPerhitungan Lanjutan
CRS dari Beberapa Jarak (Metode Regresi)
Implementasi JavaScript:
function calculateCRSRegression(distances, times) {
// Regresi linear: jarak = a + b*waktu
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 {
crs: slope, // Kecepatan lari kritis (m/s)
anaerobic_capacity: intercept // Kapasitas jarak anaerobik (m)
};
}
// Contoh dengan beberapa jarak pengujian:
const distances = [100, 200, 400, 800];
const times = [65, 150, 340, 720]; // dalam detik
const result = calculateCRSRegression(distances, times);
// Mengembalikan: { crs: 1.18, anaerobic_capacity: 15.3 }Faktor Intensitas dari Pace
Implementasi JavaScript:
function calculateIntensityFactor(actualPaceMinKm, thresholdPaceMinKm) {
// Konversi string pace "mm:ss" ke detik jika perlu
const actualSecs = typeof actualPaceMinKm === 'string' ? timeToSeconds(actualPaceMinKm) : actualPaceMinKm;
const thresholdSecs = typeof thresholdPaceMinKm === 'string' ? timeToSeconds(thresholdPaceMinKm) : thresholdPaceMinKm;
// IF adalah Pace Ambang / Pace Aktual (pace lebih cepat = nilai detik lebih kecil)
return thresholdSecs / actualSecs;
}
// Contoh:
const if_value = calculateIntensityFactor("4:45", "4:15");
// Mengembalikan: 0.895 (berlari pada 89.5% dari ambang)Analisis Konsistensi Pace
Implementasi 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 ? "Sangat Baik" :
coefficientOfVariation < 10 ? "Baik" :
coefficientOfVariation < 15 ? "Cukup" : "Bervariasi"
};
}
// Contoh:
const segments = [
{ distance: 100, time: 70 },
{ distance: 100, time: 72 },
{ distance: 100, time: 71 },
// ...
];
const analysis = analyzePaceConsistency(segments);
// Mengembalikan: { avgPace: 1.41, stdDev: 0.02, coefficientOfVariation: 1.4, consistency: "Sangat Baik" }Deteksi Kelelehan dari Efisiensi Langkah
Implementasi JavaScript:
function detectFatigue(segments) {
// Bandingkan Rasio Vertikal segmen pertama dan terakhir
const firstSegment = segments[0];
const lastSegment = segments[segments.length - 1];
const ratioIncrease = lastSegment.verticalRatio - firstSegment.verticalRatio;
return {
startRatio: firstSegment.verticalRatio,
endRatio: lastSegment.verticalRatio,
increase: Math.round(ratioIncrease * 10) / 10,
fatigueLevel: ratioIncrease < 0.2 ? "Minimal" :
ratioIncrease < 0.5 ? "Sedang" :
ratioIncrease < 1.0 ? "Signifikan" : "Parah"
};
}
// Contoh:
const segments = [
{ verticalRatio: 7.2 }, { verticalRatio: 7.3 }, { verticalRatio: 8.1 }
];
const fatigue = detectFatigue(segments);
// Mengembalikan: { startRatio: 7.2, endRatio: 8.1, increase: 0.9, fatigueLevel: "Signifikan" }Validasi Data
Pemeriksaan Kualitas Data Latihan
Implementasi JavaScript:
function validateWorkoutData(workout) {
const issues = [];
// Periksa rentang pace yang wajar (3:00-8:00 per km)
const avgPaceSecs = workout.totalTime / (workout.totalDistance / 1000);
if (avgPaceSecs < 180 || avgPaceSecs > 480) {
issues.push(`Pace rata-rata tidak biasa: ${Math.round(avgPaceSecs)} dtk per km`);
}
// Periksa Rasio Vertikal yang wajar (4% - 15%)
if (workout.avgVerticalRatio < 4 || workout.avgVerticalRatio > 15) {
issues.push(`Rasio Vertikal tidak biasa: ${workout.avgVerticalRatio}%`);
}
// Periksa kadens yang wajar (120-220 SPM)
const avgCadence = calculateCadence(workout.totalSteps, workout.totalTime);
if (avgCadence < 120 || avgCadence > 220) {
issues.push(`Kadens tidak biasa: ${Math.round(avgCadence)} SPM`);
}
// Periksa segmen yang hilang (celah waktu)
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) { // Celah 5 menit
issues.push(`Terdeteksi celah besar antara segmen ${i} dan ${i+1}`);
}
}
}
return {
isValid: issues.length === 0,
issues
};
}
// Contoh:
const workout = {
totalDistance: 2000,
totalTime: 1800, // 30 menit
totalStrides: 800,
segments: [/* data kilometer */]
};
const validation = validateWorkoutData(workout);
// Mengembalikan: { isValid: true, issues: [] }Fungsi Pembantu
Utilitas Konversi Waktu
Implementasi JavaScript:
// Konversi mm:ss ke detik
function timeToSeconds(timeString) {
const parts = timeString.split(':');
return parseInt(parts[0]) * 60 + parseInt(parts[1]);
}
// Konversi detik ke mm:ss
function secondsToTime(seconds) {
const minutes = Math.floor(seconds / 60);
const secs = Math.round(seconds % 60);
return `${minutes}:${secs.toString().padStart(2, '0')}`;
}