Teknikal na Sanggunian at mga Pormula

Kumpletong Matematikong Implementasyon

Gabay sa Implementasyon

Ang pahinang ito ay nagbibigay ng mga pormula na maaaring kopyahin at hakbang-hakbang na pamamaraan sa pagkalkula para sa lahat ng Run Analytics metrics. Gamitin ang mga ito para sa custom na implementasyon, beripikasyon, o mas malalim na pag-unawa.

⚠️ Mga Tala sa Implementasyon

  • Ang lahat ng oras ay dapat i-convert sa segundo para sa mga kalkulasyon
  • Ang pace sa pagtakbo ay kabaligtaran (mas mataas na % = mas mabagal na pace)
  • Laging i-validate ang mga input para sa makatwirang saklaw
  • Pangasiwaan ang mga edge case (dibisyon sa zero, negatibong halaga)

Pangunahing Sukatan ng Pagganap

Critical Run Speed (CRS)

Pormula:

CRS (m/s) = (D₂ - D₁) / (T₂ - T₁)
CRS Pace/100m (segundo) = (T₄₀₀ - T₂₀₀) / 2

🧪 Interactive na Kalkulador - Subukan ang Pormula

CRS Pace bawat 100m:
1:49
Mga hakbang sa kalkulasyon:
CRS (m/s) = (400 - 200) / (368 - 150) = 0.917 m/s
Pace/100m = 100 / 0.917 = 109 segundo = 1:49

Implementasyon sa JavaScript:

function calculateCRS(distance1, time1, distance2, time2) {
  // I-convert ang oras sa segundo kung kinakailangan
  const t1 = typeof time1 === 'string' ? timeToSeconds(time1) : time1;
  const t2 = typeof time2 === 'string' ? timeToSeconds(time2) : time2;

  // Kalkulahin ang CRS sa m/s
  const css_ms = (distance2 - distance1) / (t2 - t1);

  // Kalkulahin ang pace bawat 100m sa segundo
  const pace_per_100m = 100 / css_ms;

  // I-convert sa format na 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')}`
  };
}

// Halimbawa ng paggamit:
const result = calculateCRS(200, 150, 400, 368);
// Ibinabalik: { css_ms: 0.917, pace_seconds: 109, pace_formatted: "1:49" }

Run Training Stress Score (sTSS)

Kumpletong Pormula:

sTSS = (IF³) × Tagal (oras) × 100
IF = NSS / FTP
NSS = Kabuuang Distansya / Kabuuang Oras (m/min)

🧪 Interactive na Kalkulador - Subukan ang Pormula

Nakalkuladong sTSS:
55
Mga hakbang sa kalkulasyon:
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

Implementasyon sa JavaScript:

function calculateSTSS(distance, timeMinutes, ftpMetersPerMin) {
  // Kalkulahin ang Normalized Run Speed
  const nss = distance / timeMinutes;

  // Kalkulahin ang Intensity Factor
  const intensityFactor = nss / ftpMetersPerMin;

  // Kalkulahin ang oras
  const hours = timeMinutes / 60;

  // Kalkulahin ang sTSS gamit ang cubed intensity factor
  const stss = Math.pow(intensityFactor, 3) * hours * 100;

  return Math.round(stss);
}

// Halimbawa ng paggamit:
const stss = calculateSTSS(3000, 55, 64.5);
// Ibinabalik: 55

// Helper: I-convert ang CRS sa FTP
function cssToFTP(cssPacePer100mSeconds) {
  // FTP sa m/min = 100m / (pace sa minuto)
  return 100 / (cssPacePer100mSeconds / 60);
}

// Halimbawa: CRS na 1:33 (93 segundo)
const ftp = cssToFTP(93); // Ibinabalik: 64.5 m/min

Kahusayan sa Pagtakbo

Pormula:

Kahusayan sa Pagtakbo = Oras bawat Kilometro (segundo) + Bilang ng Hakbang
Kahusayan sa Pagtakbo₂₅ = (Oras × 25/Haba ng Track) + (Hakbang × 25/Haba ng Track)

🧪 Interactive na Kalkulador - Subukan ang Pormula

Iskor ng Kahusayan sa Pagtakbo:
35
Kalkulasyon:
Kahusayan sa Pagtakbo = 20s + 15 hakbang = 35

Implementasyon sa JavaScript:

function calculateRunning Efficiency(timeSeconds, strideCount) {
  return timeSeconds + strideCount;
}

function calculateNormalizedRunning Efficiency(timeSeconds, strideCount, trackLength) {
  const normalizedTime = timeSeconds * (25 / trackLength);
  const normalizedStrides = strideCount * (25 / trackLength);
  return normalizedTime + normalizedStrides;
}

// Halimbawa:
const swolf = calculateRunning Efficiency(20, 15);
// Ibinabalik: 35

const swolf50m = calculateNormalizedRunning Efficiency(40, 30, 50);
// Ibinabalik: 35 (normalized sa 25m)

Mekanika ng Hakbang

Stride Rate (SR)

Pormula:

SR = 60 / Oras ng Cycle (segundo)
SR = (Bilang ng Hakbang / Oras sa segundo) × 60

🧪 Interactive na Kalkulador - Subukan ang Pormula

Stride Rate (SPM):
72
Kalkulasyon:
SR = (30 / 25) × 60 = 72 SPM

Implementasyon sa JavaScript:

function calculateStrideRate(strideCount, timeSeconds) {
  return (strideCount / timeSeconds) * 60;
}

// Halimbawa:
const sr = calculateStrideRate(30, 25);
// Ibinabalik: 72 SPM

Distansya bawat Hakbang (DPS)

Pormula:

DPS = Distansya / Bilang ng Hakbang
DPS = Distansya / (SR / 60)

Implementasyon sa JavaScript:

function calculateDPS(distance, strideCount, pushoffDistance = 0) {
  const effectiveDistance = distance - pushoffDistance;
  return effectiveDistance / strideCount;
}

// Halimbawa (25m track, 5m push-off):
const dps = calculateDPS(25, 12, 5);
// Ibinabalik: 1.67 m/hakbang

// Para sa maraming segment:
const dps100m = calculateDPS(100, 48, 4 * 5);
// Ibinabalik: 1.67 m/hakbang (4 segment × 5m push-off)

Bilis mula sa SR at DPS

Pormula:

Bilis (m/s) = (SR / 60) × DPS

Implementasyon sa JavaScript:

function calculateVelocity(strideRate, dps) {
  return (strideRate / 60) * dps;
}

// Halimbawa:
const velocity = calculateVelocity(70, 1.6);
// Ibinabalik: 1.87 m/s

Stride Index (SI)

Pormula:

SI = Bilis (m/s) × DPS (m/hakbang)

Implementasyon sa JavaScript:

function calculateStrideIndex(velocity, dps) {
  return velocity * dps;
}

// Halimbawa:
const si = calculateStrideIndex(1.5, 1.7);
// Ibinabalik: 2.55

Performance Management Chart (PMC)

Mga Kalkulasyon ng CTL, ATL, TSB

Mga Pormula:

CTL ngayon = CTL kahapon + (TSS ngayon - CTL kahapon) × (1/42)
ATL ngayon = ATL kahapon + (TSS ngayon - ATL kahapon) × (1/7)
TSB = CTL kahapon - ATL kahapon

Implementasyon sa 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;
}

// Kalkulahin ang PMC para sa serye ng mga workout
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;
}

// Halimbawa ng paggamit:
const workouts = [
  { date: '2025-01-01', tss: 50 },
  { date: '2025-01-02', tss: 60 },
  { date: '2025-01-03', tss: 45 },
  // ... higit pang mga workout
];

const pmc = calculatePMC(workouts);
// Ibinabalik ang array na may CTL, ATL, TSB para sa bawat araw

Mga Advanced na Kalkulasyon

CRS mula sa Maraming Distansya (Pamamaraang Regression)

Implementasyon sa JavaScript:

function calculateCRSRegression(distances, times) {
  // Linear regression: distance = a + b*time
  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, // Critical running velocity (m/s)
    anaerobic_capacity: intercept // Anaerobic distance capacity (m)
  };
}

// Halimbawa na may maraming test distance:
const distances = [100, 200, 400, 800];
const times = [65, 150, 340, 720]; // sa segundo
const result = calculateCRSRegression(distances, times);
// Ibinabalik: { css: 1.18, anaerobic_capacity: 15.3 }

Intensity Factor mula sa Pace

Implementasyon sa JavaScript:

function calculateIntensityFactor(actualPace100m, thresholdPace100m) {
  // I-convert ang pace sa bilis (m/s)
  const actualSpeed = 100 / actualPace100m;
  const thresholdSpeed = 100 / thresholdPace100m;
  return actualSpeed / thresholdSpeed;
}

// Halimbawa:
const if_value = calculateIntensityFactor(110, 93);
// Ibinabalik: 0.845 (tumatakbo sa 84.5% ng threshold)

Pagsusuri ng Consistency ng Pace

Implementasyon sa 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 ? "Napakahusay" :
                 coefficientOfVariation < 10 ? "Mahusay" :
                 coefficientOfVariation < 15 ? "Katamtaman" : "Pabagu-bago"
  };
}

// Halimbawa:
const segments = [
  { distance: 100, time: 70 },
  { distance: 100, time: 72 },
  { distance: 100, time: 71 },
  // ...
];
const analysis = analyzePaceConsistency(segments);
// Ibinabalik: { avgPace: 1.41, stdDev: 0.02, coefficientOfVariation: 1.4, consistency: "Napakahusay" }

Pagtuklas ng Pagod mula sa Bilang ng Hakbang

Implementasyon sa 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 ? "Kaunti" :
                  strideCountIncrease < 10 ? "Katamtaman" :
                  strideCountIncrease < 20 ? "Makabuluhan" : "Matindi"
  };
}

// Halimbawa:
const segments = [
  { strideCount: 14 }, { strideCount: 14 }, { strideCount: 15 },
  { strideCount: 15 }, { strideCount: 16 }, { strideCount: 16 },
  { strideCount: 17 }, { strideCount: 18 }, { strideCount: 18 }
];
const fatigue = detectFatigue(segments);
// Ibinabalik: { firstThirdAvg: 14.3, lastThirdAvg: 17.7, percentIncrease: 23.8, fatigueLevel: "Matindi" }

Pagpapatunay ng Data

Pagsusuri ng Kalidad ng Data ng Workout

Implementasyon sa JavaScript:

function validateWorkoutData(workout) {
  const issues = [];

  // Suriin ang makatwirang saklaw ng pace (1:00-5:00 bawat 100m)
  const avgPace = (workout.totalTime / workout.totalDistance) * 100;
  if (avgPace < 60 || avgPace > 300) {
    issues.push(`Hindi pangkaraniwang average pace: ${Math.round(avgPace)}s bawat 100m`);
  }

  // Suriin ang makatwirang bilang ng hakbang (10-50 bawat 25m)
  const avgStridesPer25m = (workout.totalStrides / workout.totalDistance) * 25;
  if (avgStridesPer25m < 10 || avgStridesPer25m > 50) {
    issues.push(`Hindi pangkaraniwang bilang ng hakbang: ${Math.round(avgStridesPer25m)} bawat 25m`);
  }

  // Suriin ang makatwirang stride rate (30-150 SPM)
  const avgSR = calculateStrideRate(workout.totalStrides, workout.totalTime);
  if (avgSR < 30 || avgSR > 150) {
    issues.push(`Hindi pangkaraniwang stride rate: ${Math.round(avgSR)} SPM`);
  }

  // Suriin ang mga nawawalang segment (mga puwang sa oras)
  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 minutong puwang
        issues.push(`Malaking puwang na natukoy sa pagitan ng segment ${i} at ${i+1}`);
      }
    }
  }

  return {
    isValid: issues.length === 0,
    issues
  };
}

// Halimbawa:
const workout = {
  totalDistance: 2000,
  totalTime: 1800, // 30 minuto
  totalStrides: 800,
  segments: [/* data ng kilometro */]
};
const validation = validateWorkoutData(workout);
// Ibinabalik: { isValid: true, issues: [] }

Mga Helper Function

Mga Utility para sa Konbersyon ng Oras

Implementasyon sa JavaScript:

// I-convert ang mm:ss sa segundo
function timeToSeconds(timeString) {
  const parts = timeString.split(':');
  return parseInt(parts[0]) * 60 + parseInt(parts[1]);
}

// I-convert ang segundo sa mm:ss
function secondsToTime(seconds) {
  const minutes = Math.floor(seconds / 60);
  const secs = Math.round(seconds % 60);
  return `${minutes}:${secs.toString().padStart(2, '0')}`;
}

// I-convert ang segundo sa 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')}`;
}

// Mga halimbawa:
timeToSeconds("1:33"); // Ibinabalik: 93
secondsToTime(93); // Ibinabalik: "1:33"
secondsToTimeDetailed(3665); // Ibinabalik: "1:01:05"

Mga Mapagkukunan para sa Implementasyon

Ang lahat ng pormula sa pahinang ito ay handang gamitin sa produksyon at napatunayan laban sa siyentipikong literatura. Gamitin ang mga ito para sa custom na analytics tool, beripikasyon, o mas malalim na pag-unawa ng mga kalkulasyon sa pagganap sa pagtakbo.

💡 Pinakamahusay na Gawi

  • I-validate ang mga input: Suriin ang makatwirang saklaw bago magkalkula
  • Pangasiwaan ang mga edge case: Dibisyon sa zero, negatibong halaga, null na data
  • I-round nang naaayon: CTL/ATL/TSB sa 1 decimal, sTSS sa integer
  • Mag-imbak ng precision: Panatilihin ang buong precision sa database, i-round para sa display
  • Subukan nang lubusan: Gamitin ang kilalang mabuting data upang beripikahin ang mga kalkulasyon