Referensi Teknis & Rumus
Implementasi Matematika Lengkap
Panduan Implementasi
Halaman ini menyediakan rumus yang dapat disalin-tempel dan metode penghitungan langkah-demi-langkah untuk semua metrik Analitik Renang. Gunakan ini untuk implementasi khusus, verifikasi, atau pemahaman yang lebih mendalam.
⚠️ Catatan Implementasi
- Semua waktu harus dikonversi ke detik untuk penghitungan
- Pace renang bersifat inversi (persentase yang lebih tinggi = pace yang lebih lambat)
- Selalu validasi masukan untuk rentang yang wajar
- Tangani kasus khusus (pembagian dengan nol, nilai negatif)
Metrik Performa Utama
Kecepatan Renang Kritis (CSS)
Rumus:
CSS (m/s) = (D₂ - D₁) / (T₂ - T₁)
Pace CSS/100m (detik) = (T₄₀₀ - T₂₀₀) / 2
🧪 Kalkulator Interaktif - Uji Rumusnya
Pace CSS per 100m:
1:49
Langkah penghitungan:
CSS (m/s) = (400 - 200) / (368 - 150) = 0,917 m/s
Pace/100m = 100 / 0,917 = 109 detik = 1:49
CSS (m/s) = (400 - 200) / (368 - 150) = 0,917 m/s
Pace/100m = 100 / 0,917 = 109 detik = 1:49
Implementasi JavaScript:
function calculateCSS(distance1, time1, distance2, time2) {
// Ubah waktu ke detik jika diperlukan
const t1 = typeof time1 === 'string' ? timeToSeconds(time1) : time1;
const t2 = typeof time2 === 'string' ? timeToSeconds(time2) : time2;
// Hitung CSS dalam m/s
const css_ms = (distance2 - distance1) / (t2 - t1);
// Hitung pace per 100m dalam detik
const pace_per_100m = 100 / css_ms;
// Konversi ke format 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')}`
};
}
// Contoh penggunaan:
const result = calculateCSS(200, 150, 400, 368);
// Hasil: { css_ms: 0.917, pace_seconds: 109, pace_formatted: "1:49" }
Skor Stres Latihan Renang (sTSS)
Rumus Lengkap:
sTSS = (IF³) × Durasi (jam) × 100
IF = NSS / FTP
NSS = Jarak Total / Waktu Total (m/menit)
🧪 Kalkulator Interaktif - Uji Rumusnya
Hasil sTSS:
55
Langkah penghitungan:
NSS = 3000m / 55menit = 54,5 m/menit
FTP = 100 / (93/60) = 64,5 m/menit
IF = 54,5 / 64,5 = 0,845
sTSS = 0,845³ × (55/60) × 100 = 55
NSS = 3000m / 55menit = 54,5 m/menit
FTP = 100 / (93/60) = 64,5 m/menit
IF = 54,5 / 64,5 = 0,845
sTSS = 0,845³ × (55/60) × 100 = 55
Implementasi JavaScript:
function calculateSTSS(distance, timeMinutes, ftpMetersPerMin) {
// Hitung Kecepatan Renang yang Dinormalisasi (NSS)
const nss = distance / timeMinutes;
// Hitung Faktor Intensitas (IF)
const intensityFactor = nss / ftpMetersPerMin;
// Hitung jam
const hours = timeMinutes / 60;
// Hitung sTSS menggunakan faktor intensitas pangkat tiga
const stss = Math.pow(intensityFactor, 3) * hours * 100;
return Math.round(stss);
}
// Contoh penggunaan:
const stss = calculateSTSS(3000, 55, 64.5);
// Hasil: 55
// Pembantu: Konversi CSS ke FTP
function cssToFTP(cssPacePer100mSeconds) {
// FTP dalam m/menit = 100m / (pace dalam menit)
return 100 / (cssPacePer100mSeconds / 60);
}
// Contoh: CSS 1:33 (93 detik)
const ftp = cssToFTP(93); // Hasil: 64.5 m/menit
SWOLF
Rumus:
SWOLF = Waktu Lintas (detik) + Jumlah Ayunan
SWOLF₂₅ = (Waktu × 25/Panjang Kolam) + (Ayunan × 25/Panjang Kolam)
🧪 Kalkulator Interaktif - Uji Rumusnya
Skor SWOLF:
35
Penghitungan:
SWOLF = 20 detik + 15 ayunan = 35
SWOLF = 20 detik + 15 ayunan = 35
Implementasi JavaScript:
function calculateSWOLF(timeSeconds, strokeCount) {
return timeSeconds + strokeCount;
}
function calculateNormalizedSWOLF(timeSeconds, strokeCount, poolLength) {
const normalizedTime = timeSeconds * (25 / poolLength);
const normalizedStrokes = strokeCount * (25 / poolLength);
return normalizedTime + normalizedStrokes;
}
// Contoh:
const swolf = calculateSWOLF(20, 15);
// Hasil: 35
const swolf50m = calculateNormalizedSWOLF(40, 30, 50);
// Hasil: 35 (dinormalisasi ke 25m)
Mekanika Ayunan
Laju Ayunan (SR)
Rumus:
SR = 60 / Waktu Siklus (detik)
SR = (Jumlah Ayunan / Waktu dalam detik) × 60
🧪 Kalkulator Interaktif - Uji Rumusnya
Laju Ayunan (SPM):
72
Penghitungan:
SR = (30 / 25) × 60 = 72 SPM
SR = (30 / 25) × 60 = 72 SPM
Implementasi JavaScript:
function calculateStrokeRate(strokeCount, timeSeconds) {
return (strokeCount / timeSeconds) * 60;
}
// Contoh:
const sr = calculateStrokeRate(30, 25);
// Hasil: 72 SPM
Jarak Per Ayunan (DPS)
Rumus:
DPS = Jarak / Jumlah Ayunan
DPS = Jarak / (SR / 60)
Implementasi JavaScript:
function calculateDPS(distance, strokeCount, pushoffDistance = 0) {
const effectiveDistance = distance - pushoffDistance;
return effectiveDistance / strokeCount;
}
// Contoh (kolam 25m, dorongan dinding 5m):
const dps = calculateDPS(25, 12, 5);
// Hasil: 1.67 m/ayunan
// Untuk beberapa lintasan:
const dps100m = calculateDPS(100, 48, 4 * 5);
// Hasil: 1.67 m/ayunan (4 lintasan × 5m dorongan dinding)
Kecepatan dari SR dan DPS
Rumus:
Kecepatan (m/s) = (SR / 60) × DPS
Implementasi JavaScript:
function calculateVelocity(strokeRate, dps) {
return (strokeRate / 60) * dps;
}
// Contoh:
const velocity = calculateVelocity(70, 1.6);
// Hasil: 1.87 m/s
Indeks Ayunan (SI)
Rumus:
SI = Kecepatan (m/s) × DPS (m/ayunan)
Implementasi JavaScript:
function calculateStrokeIndex(velocity, dps) {
return velocity * dps;
}
// Contoh:
const si = calculateStrokeIndex(1.5, 1.7);
// Hasil: 2.55
Grafik Manajemen Performa (PMC)
Penghitungan CTL, ATL, TSB
Rumus:
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 rangkaian 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 hari
Penghitungan Tingkat Lanjut
CSS dari Berbagai Jarak (Metode Regresi)
Implementasi JavaScript:
function calculateCSSRegression(distances, times) {
// Regresi linier: 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 {
css: slope, // Kecepatan renang kritis (m/s)
anaerobic_capacity: intercept // Kapasitas jarak anaerobik (m)
};
}
// Contoh dengan beberapa jarak tes:
const distances = [100, 200, 400, 800];
const times = [65, 150, 340, 720]; // dalam detik
const result = calculateCSSRegression(distances, times);
// Hasil: { css: 1.18, anaerobic_capacity: 15.3 }
Faktor Intensitas dari Pace
Implementasi JavaScript:
function calculateIntensityFactor(actualPace100m, thresholdPace100m) {
// Konversi pace ke kecepatan (m/s)
const actualSpeed = 100 / actualPace100m;
const thresholdSpeed = 100 / thresholdPace100m;
return actualSpeed / thresholdSpeed;
}
// Contoh:
const if_value = calculateIntensityFactor(110, 93);
// Hasil: 0.845 (berenang pada 84,5% dari ambang batas)
Analisis Konsistensi Pace
Implementasi JavaScript:
function analyzePaceConsistency(laps) {
const paces = laps.map(lap => lap.distance / lap.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 ? "Sempurna" :
coefficientOfVariation < 10 ? "Bagus" :
coefficientOfVariation < 15 ? "Moderata" : "Bervariasi"
};
}
// Contoh:
const laps = [
{ distance: 100, time: 70 },
{ distance: 100, time: 72 },
{ distance: 100, time: 71 },
// ...
];
const analysis = analyzePaceConsistency(laps);
// Hasil: { avgPace: 1.41, stdDev: 0.02, coefficientOfVariation: 1.4, consistency: "Sempurna" }
Deteksi Kelelahan dari Jumlah Ayunan
Implementasi JavaScript:
function detectFatigue(laps) {
const firstThird = laps.slice(0, Math.floor(laps.length/3));
const lastThird = laps.slice(-Math.floor(laps.length/3));
const firstThirdAvg = firstThird.reduce((sum, lap) =>
sum + lap.strokeCount, 0) / firstThird.length;
const lastThirdAvg = lastThird.reduce((sum, lap) =>
sum + lap.strokeCount, 0) / lastThird.length;
const strokeCountIncrease = ((lastThirdAvg - firstThirdAvg) / firstThirdAvg) * 100;
return {
firstThirdAvg: Math.round(firstThirdAvg * 10) / 10,
lastThirdAvg: Math.round(lastThirdAvg * 10) / 10,
percentIncrease: Math.round(strokeCountIncrease * 10) / 10,
fatigueLevel: strokeCountIncrease < 5 ? "Minimal" :
strokeCountIncrease < 10 ? "Moderat" :
strokeCountIncrease < 20 ? "Signifikan" : "Parah"
};
}
// Contoh:
const laps = [
{ strokeCount: 14 }, { strokeCount: 14 }, { strokeCount: 15 },
{ strokeCount: 15 }, { strokeCount: 16 }, { strokeCount: 16 },
{ strokeCount: 17 }, { strokeCount: 18 }, { strokeCount: 18 }
];
const fatigue = detectFatigue(laps);
// Hasil: { firstThirdAvg: 14.3, lastThirdAvg: 17.7, percentIncrease: 23.8, fatigueLevel: "Parah" }
Validasi Data
Pemeriksaan Kualitas Data Latihan
Implementasi JavaScript:
function validateWorkoutData(workout) {
const issues = [];
// Periksa rentang pace yang wajar (1:00-5:00 per 100m)
const avgPace = (workout.totalTime / workout.totalDistance) * 100;
if (avgPace < 60 || avgPace > 300) {
issues.push(`Pace rata-rata tidak wajar: ${Math.round(avgPace)} detik per 100m`);
}
// Periksa jumlah ayunan yang wajar (10-50 per 25m)
const avgStrokesPer25m = (workout.totalStrokes / workout.totalDistance) * 25;
if (avgStrokesPer25m < 10 || avgStrokesPer25m > 50) {
issues.push(`Jumlah ayunan tidak wajar: ${Math.round(avgStrokesPer25m)} per 25m`);
}
// Periksa laju ayunan yang wajar (30-150 SPM)
const avgSR = calculateStrokeRate(workout.totalStrokes, workout.totalTime);
if (avgSR < 30 || avgSR > 150) {
issues.push(`Laju ayunan tidak wajar: ${Math.round(avgSR)} SPM`);
}
// Periksa lintasan yang hilang (celah waktu)
if (workout.laps && workout.laps.length > 1) {
for (let i = 1; i < workout.laps.length; i++) {
const gap = workout.laps[i].startTime -
(workout.laps[i-1].startTime + workout.laps[i-1].duration);
if (gap > 300) { // Celah 5 menit
issues.push(`Celah besar terdeteksi di antara lintasan ${i} dan ${i+1}`);
}
}
}
return {
isValid: issues.length === 0,
issues
};
}
// Contoh:
const workout = {
totalDistance: 2000,
totalTime: 1800, // 30 menit
totalStrokes: 800,
laps: [/* data lintasan */]
};
const validation = validateWorkoutData(workout);
// Hasil: { isValid: true, issues: [] }
Fungsi Pembantu (*Helper Functions*)
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')}`;
}
// Konversi detik ke 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')}`;
}
// Contoh:
timeToSeconds("1:33"); // Hasil: 93
secondsToTime(93); // Hasil: "1:33"
secondsToTimeDetailed(3665); // Hasil: "1:01:05"
Sumber Daya Implementasi
Semua rumus di halaman ini siap digunakan untuk produksi dan telah divalidasi dengan literatur ilmiah. Gunakan rumus ini untuk alat analitik khusus, verifikasi, atau pemahaman yang lebih mendalam tentang penghitungan performa renang.
💡 Praktik Terbaik
- Validasi masukan: Periksa rentang yang wajar sebelum menghitung
- Tangani kasus khusus: Pembagian dengan nol, nilai negatif, data kosong
- Pembulatan yang sesuai: CTL/ATL/TSB ke 1 desimal, sTSS ke bilangan bulat
- Simpan presisi: Pertahankan presisi penuh dalam basis data, bulatkan hanya untuk tampilan
- Uji secara menyeluruh: Gunakan data yang valid untuk memverifikasi penghitungan