Formula Kuasa Berbasikal

Asas Matematik Metrik Bike Analytics

Panduan Pelaksanaan

Halaman ini menyediakan formula salin-tampal dan kaedah pengiraan langkah demi langkah untuk semua metrik Bike Analytics. Gunakan ini untuk pelaksanaan tersuai, pengesahan, atau pemahaman yang lebih mendalam tentang latihan berasaskan kuasa.

⚠️ Nota Pelaksanaan

  • Semua nilai kuasa dalam watt (W), masa dalam saat kecuali dinyatakan sebaliknya
  • FTP dan CP adalah ambang khusus individu—tiada nilai universal
  • Sentiasa sahkan input untuk julat yang munasabah (0-2000W biasa)
  • Kendalikan kes tepi (pembahagian dengan sifar, kuasa negatif)
  • Data kuasa memerlukan selang rakaman 1 saat untuk ketepatan

Metrik Prestasi Teras

1. Skor Tekanan Latihan (TSS)

Formula:

TSS = (durasi_saat × NP × IF) / (FTP × 3600) × 100
di mana IF = NP / FTP

Contoh Kerja:

Senario: Tunggangan 2 jam, NP = 235W, FTP = 250W

  1. Kira IF: IF = 235 / 250 = 0.94
  2. Durasi dalam saat: 2 jam × 3600 = 7200 saat
  3. TSS = (7200 × 235 × 0.94) / (250 × 3600) × 100
  4. TSS = 1,590,720 / 900,000 × 100 = 176.7 TSS

Tafsiran: Tunggangan latihan keras (>150 TSS), jangkaan pemulihan 2-3 hari

Pelaksanaan JavaScript:

function calculateTSS(durationSeconds, normalizedPower, ftp) {
  const intensityFactor = normalizedPower / ftp;
  const tss = (durationSeconds * normalizedPower * intensityFactor) / (ftp * 3600) * 100;
  return Math.round(tss);
}

// Contoh penggunaan:
const tss = calculateTSS(7200, 235, 250);
// Mengembalikan: 177

2. Kuasa Ternormal (NP)

Algoritma (purata bergerak 30 saat):

1. Kira purata kuasa bergerak 30 saat untuk keseluruhan tunggangan
2. Naikkan setiap nilai 30-saat kepada kuasa ke-4
3. Ambil purata semua nilai ^4 ini
4. Ambil punca kuasa ke-4 purata tersebut
NP = ⁴√(purata [30s_avg^4])

Mengapa Kuasa ke-4?

Hubungan kuartik (kuasa ke-4) mencerminkan kos fisiologi bukan linear bagi usaha berubah-ubah. Tunggangan dengan lonjakan dan pemulihan menelan lebih banyak tenaga daripada kuasa yang stabil pada purata yang sama.

Contoh:

  • Tunggangan stabil: 200W selama 1 jam → NP = 200W, Purata = 200W
  • Tunggangan berubah: Berselang-seli 300W/100W → Purata = 200W, NP = 225W

Purata kuasa sama, tetapi tunggangan berubah mempunyai NP 12% lebih tinggi disebabkan kos fisiologi lonjakan

Pelaksanaan JavaScript:

function calculateNormalizedPower(powerData) {
  // powerData adalah array nilai kuasa 1-saat

  // Langkah 1: Kira purata bergerak 30-saat
  const rollingAvgs = [];
  for (let i = 29; i < powerData.length; i++) {
    const window = powerData.slice(i - 29, i + 1);
    const avg = window.reduce((sum, p) => sum + p, 0) / 30;
    rollingAvgs.push(avg);
  }

  // Langkah 2: Naikkan ke kuasa ke-4
  const powered = rollingAvgs.map(p => Math.pow(p, 4));

  // Langkah 3: Purata kuasa ke-4
  const avgPowered = powered.reduce((sum, p) => sum + p, 0) / powered.length;

  // Langkah 4: Ambil punca kuasa ke-4
  const np = Math.pow(avgPowered, 0.25);

  return Math.round(np);
}

// Contoh penggunaan:
const powerData = [/* array kuasa 1-saat */];
const np = calculateNormalizedPower(powerData);
// Mengembalikan: NP dalam watt

3. Faktor Intensiti (IF)

Formula:

IF = NP / FTP

Julat Tafsiran:

Julat IF Tahap Usaha Contoh Latihan
< 0.75 Pemulihan / Mudah Tunggangan pemulihan aktif, Zon 1-2
0.75 - 0.85 Daya Tahan Tunggangan stabil jauh, asas aerobik
0.85 - 0.95 Tempo Latihan sweet spot, interval tempo
0.95 - 1.05 Ambang Interval FTP, usaha ujian masa
1.05 - 1.15 VO₂max Interval 5-minit, perlumbaan kriterium
> 1.15 Anaerobik Pecutan pendek, serangan, letusan MTB

Pengiraan Contoh:

Senario: NP = 235W, FTP = 250W

IF = 235 / 250 = 0.94

Tafsiran: Usaha tempo tinggi / sub-ambang, mampan untuk 2-3 jam

function calculateIF(normalizedPower, ftp) {
  return (normalizedPower / ftp).toFixed(2);
}

// Contoh:
const if_value = calculateIF(235, 250);
// Mengembalikan: 0.94

4. Indeks Kebolehubahan (VI)

Formula:

VI = NP / Kuasa Purata

Tafsiran Mengikut Disiplin:

Disiplin VI Biasa Maksud
TT Jalan Raya / Usaha Stabil 1.00 - 1.05 Kuasa sangat konsisten, pacing optimum
Perlumbaan Jalan Raya 1.05 - 1.10 Beberapa lonjakan, secara amnya stabil
Kriterium 1.10 - 1.20 Pecutan dan serangan yang kerap
Basikal Gunung XC 1.15 - 1.30+ Sangat berubah, lonjakan berterusan

Pengiraan Contoh:

Perlumbaan Jalan Raya: NP = 240W, Kuasa Purata = 230W

VI = 240 / 230 = 1.04 (pacing stabil)

Perlumbaan MTB: NP = 285W, Kuasa Purata = 235W

VI = 285 / 235 = 1.21 (sangat berubah, usaha letusan)

function calculateVI(normalizedPower, averagePower) {
  return (normalizedPower / averagePower).toFixed(2);
}

// Contoh:
const vi_road = calculateVI(240, 230);  // Mengembalikan: 1.04
const vi_mtb = calculateVI(285, 235);   // Mengembalikan: 1.21

Kuasa Kritikal & W' (Kapasiti Anaerobik)

5. Kuasa Kritikal (CP) - Model Linear

Formula:

Masa = W' / (Kuasa - CP)
Disusun Semula: Kuasa × Masa = CP × Masa + W'

Pengiraan daripada Pelbagai Usaha:

Memerlukan 2-4 usaha maksimum pada durasi berbeza (cth., 3, 5, 12, 20 minit)

Data Contoh:

Durasi Kuasa (W) Jumlah Kerja (kJ)
3 min (180s) 400W 72 kJ
5 min (300s) 365W 109.5 kJ
12 min (720s) 310W 223.2 kJ
20 min (1200s) 285W 342 kJ

Menggunakan regresi linear (Kerja = CP × Masa + W'):

  • CP = 270W (kecerunan garis regresi)
  • W' = 18.5 kJ (pintasan-y)

Pelaksanaan JavaScript:

function calculateCP_Linear(efforts) {
  // efforts = [{duration: seconds, power: watts}, ...]

  const times = efforts.map(e => e.duration);
  const work = efforts.map(e => e.power * e.duration / 1000); // kJ

  // Regresi linear: work = CP * time + W'
  const n = efforts.length;
  const sumT = times.reduce((a, b) => a + b, 0);
  const sumW = work.reduce((a, b) => a + b, 0);
  const sumTW = times.reduce((sum, t, i) => sum + t * work[i], 0);
  const sumTT = times.reduce((sum, t) => sum + t * t, 0);

  const CP = (n * sumTW - sumT * sumW) / (n * sumTT - sumT * sumT);
  const Wprime = (sumW - CP * sumT) / n;

  return {
    CP: Math.round(CP * 10) / 10,      // watt
    Wprime: Math.round(Wprime * 10) / 10  // kJ
  };
}

// Contoh penggunaan:
const efforts = [
  {duration: 180, power: 400},
  {duration: 300, power: 365},
  {duration: 720, power: 310},
  {duration: 1200, power: 285}
];

const result = calculateCP_Linear(efforts);
// Mengembalikan: { CP: 270.0, Wprime: 18.5 }

6. Imbangan W' (W'bal) - Model Persamaan Pembezaan

Formula:

Perbelanjaan (apabila P > CP):
W'exp(t) = ∫(P(t) - CP) dt
Pemulihan (apabila P < CP):
W'rec(t) = W' × (1 - e^(-t/τ))
di mana τ = 546 × e^(-0.01 × ΔCP) + 316
dan ΔCP = (CP - P(t))

Contoh Dunia Sebenar:

Spesifikasi Penunggang: CP = 270W, W' = 18.5 kJ

Senario 1 - Serangan Keras:

  • Penunggang melonjak ke 400W selama 30 saat
  • Perbelanjaan W': (400 - 270) × 30 = 3,900 J = 3.9 kJ
  • W'bal tingal: 18.5 - 3.9 = 14.6 kJ

Senario 2 - Pemulihan:

  • Selepas serangan, turun ke 200W (70W di bawah CP) selama 2 minit
  • ΔCP = 270 - 200 = 70W
  • τ = 546 × e^(-0.01 × 70) + 316 = 588 saat
  • Pemulihan dalam 120s: 18.5 × (1 - e^(-120/588)) = 3.5 kJ pulih
  • W'bal Baharu: 14.6 + 3.5 = 18.1 kJ

Pelaksanaan JavaScript:

function calculateWbalance(powerData, CP, Wprime) {
  // powerData = array of {time: seconds, power: watts}
  let wbal = Wprime * 1000; // Tukar ke joule
  const wbalHistory = [];

  for (let i = 1; i < powerData.length; i++) {
    const dt = powerData[i].time - powerData[i-1].time;
    const power = powerData[i].power;

    if (power > CP) {
      // Perbelanjaan di atas CP
      const expenditure = (power - CP) * dt;
      wbal -= expenditure;
    } else {
      // Pemulihan di bawah CP
      const deltaCP = CP - power;
      const tau = 546 * Math.exp(-0.01 * deltaCP) + 316;
      const recovery = (Wprime * 1000 - wbal) * (1 - Math.exp(-dt / tau));
      wbal += recovery;
    }

    // Pastikan W'bal tidak melebihi maks atau menjadi negatif
    wbal = Math.max(0, Math.min(wbal, Wprime * 1000));

    wbalHistory.push({
      time: powerData[i].time,
      wbal: wbal / 1000, // kJ
      percent: (wbal / (Wprime * 1000)) * 100
    });
  }

  return wbalHistory;
}

// Contoh penggunaan:
const powerData = [
  {time: 0, power: 200},
  {time: 1, power: 210},
  // ... baki data tunggangan
];

const wbalHistory = calculateWbalance(powerData, 270, 18.5);
// Mengembalikan array nilai W'bal sepanjang masa

Carta Pengurusan Prestasi (PMC)

7. Pengiraan CTL, ATL, TSB

Formula (Purata Bergerak Wajaran Eksponen):

CTL_hari_ini = CTL_semalam + (TSS_hari_ini - CTL_semalam) / 42
ATL_hari_ini = ATL_semalam + (TSS_hari_ini - ATL_semalam) / 7
TSB_hari_ini = CTL_semalam - ATL_semalam

Definisi Metrik:

  • CTL (Beban Latihan Kronik): Purata wajaran eksponen 42-hari - mewakili kecergasan
  • ATL (Beban Latihan Akut): Purata wajaran eksponen 7-hari - mewakili keletihan
  • TSB (Imbangan Tekanan Latihan): Bentuk = Kecergasan - Keletihan

Contoh Kerja (Blok Latihan 7-Hari):

Hari TSS CTL ATL TSB Status
Isnin 100 75.0 80.0 -5.0 Latihan
Selasa 50 74.4 75.7 -1.3 Pemulihan
Rabu 120 75.5 82.0 -6.5 Latihan Keras
Khamis 0 73.7 70.3 +3.4 Hari Rehat
Jumaat 80 73.8 71.7 +2.1 Sederhana
Sabtu 150 75.6 82.9 -7.3 Tunggangan Jauh
Ahad 40 74.8 76.8 -2.0 Pemulihan

Tafsiran TSB:

Julat TSB Status Tindakan
< -30 Risiko Tinggi Amaran latihan berlebihan - kurangkan beban
-30 hingga -10 Latihan Keras Membina kecergasan, pantau pemulihan
-10 hingga +5 Optimum Zon latihan biasa
+5 hingga +15 Sedia Berlumba Bentuk puncak - berlumba hujung minggu ini
> +25 Penurunan Latihan Kehilangan kecergasan - tingkatkan beban

Pelaksanaan JavaScript:

function calculatePMC(workouts) {
  // workouts = [{date: "YYYY-MM-DD", tss: number}, ...]
  let ctl = 0, atl = 0;
  const results = [];

  workouts.forEach(workout => {
    // Kemaskini CTL (pemalar masa 42-hari)
    ctl = ctl + (workout.tss - ctl) / 42;

    // Kemaskini ATL (pemalar masa 7-hari)
    atl = atl + (workout.tss - atl) / 7;

    // Kira TSB (CTL semalam - ATL hari ini untuk pengiraan tradisional)
    // Untuk kesederhanaan di sini menggunakan nilai semasa
    const tsb = 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,
      status: getTSBStatus(tsb)
    });
  });

  return results;
}

function getTSBStatus(tsb) {
  if (tsb < -30) return "Risiko Tinggi";
  if (tsb < -10) return "Latihan Keras";
  if (tsb < 5) return "Optimum";
  if (tsb < 15) return "Sedia Berlumba";
  return "Penurunan Latihan";
}

// Contoh penggunaan:
const workouts = [
  {date: "2025-01-01", tss: 100},
  {date: "2025-01-02", tss: 50},
  {date: "2025-01-03", tss: 120},
  // ... lebih banyak latihan
];

const pmc = calculatePMC(workouts);
// Mengembalikan array dengan CTL, ATL, TSB untuk setiap hari

Nisbah Kuasa-ke-Berat & Metrik Mendaki

8. Nisbah Kuasa-ke-Berat

Formula:

W/kg = Kuasa (watt) / Jisim Badan (kg)

Penanda Aras W/kg FTP:

Tahap W/kg Lelaki W/kg Wanita Kategori
Rekreasi 2.5 - 3.5 2.0 - 3.0 Penunggang kecergasan
Kompetitif 3.5 - 4.5 3.0 - 4.0 Kat 3-4, pelumba kumpulan umur
Lanjutan 4.5 - 5.5 4.0 - 5.0 Kat 1-2, amatur kuat
Amatur Elit 5.5 - 6.0 5.0 - 5.5 Tahap kebangsaan
Profesional 6.0 - 7.0+ 5.5 - 6.5+ Jelajah Dunia, GC Jelajah Besar

Pengiraan Contoh:

Senario: Penunggang dengan FTP = 275W, jisim badan = 70kg

W/kg = 275 / 70 = 3.93 W/kg

Tafsiran: Tahap kompetitif, berkemampuan dalam perlumbaan berbukit

function calculateWattsPerKg(power, bodyMassKg) {
  return (power / bodyMassKg).toFixed(2);
}

// Contoh:
const wpkg = calculateWattsPerKg(275, 70);
// Mengembalikan: 3.93

9. VAM (Velocità Ascensionale Media)

Formula:

VAM (m/j) = Kenaikan Ketinggian (m) / Masa (jam)

Penanda Aras VAM:

VAM (m/j) Tahap Contoh
600 - 900 Rekreasi Penunggang kelab di pendakian tempatan
900 - 1200 Kompetitif Amatur baik di Alpe d'Huez
1200 - 1500 Amatur Elit Pendaki tahap kebangsaan
1500 - 1800 Profesional Domestique Jelajah Dunia
> 1800 Pemenang Jelajah Besar Pogačar, Vingegaard di pendakian utama

Pengiraan Contoh:

Senario: Pendakian Alpe d'Huez

  • Kenaikan ketinggian: 1100 meter
  • Masa: 55 minit = 0.917 jam
  • VAM = 1100 / 0.917 = 1200 m/j

Tafsiran: Prestasi mendaki tahap kompetitif

function calculateVAM(elevationGainMeters, timeMinutes) {
  const hours = timeMinutes / 60;
  return Math.round(elevationGainMeters / hours);
}

// Contoh:
const vam = calculateVAM(1100, 55);
// Mengembalikan: 1200 m/j

10. Anggaran VAM ke W/kg

Formula:

W/kg ≈ VAM (m/j) / 100 / (Kecerunan% + 3)

Pengiraan Contoh:

Senario: Pendakian dengan kecerunan purata 8%, VAM = 1200 m/j

W/kg = 1200 / 100 / (8 + 3)

W/kg = 12 / 11 = 4.36 W/kg

Semak silang: Dengan penunggang 70kg → 305W kuasa mampan semasa mendaki

function estimateWkgFromVAM(vam, gradientPercent) {
  return (vam / 100 / (gradientPercent + 3)).toFixed(2);
}

// Contoh:
const wkg = estimateWkgFromVAM(1200, 8);
// Mengembalikan: 4.36

Persamaan Kuasa Aerodinamik

11. Keperluan Kuasa Keseluruhan

Formula Lengkap:

P = P_graviti + P_golekan + P_seretan + P_kinetik
P = (g·m·v·sin(θ)) + (g·m·v·Crr·cos(θ)) + (0.5·CdA·ρ·v³) + (m·a·v)