Tham khảo Kỹ thuật & Công thức
Triển khai Toán học Hoàn chỉnh
Hướng dẫn Triển khai
Trang này cung cấp các công thức có thể sao chép và các phương pháp tính toán từng bước cho tất cả các chỉ số Run Analytics. Sử dụng chúng cho các triển khai tùy chỉnh, xác minh hoặc hiểu sâu hơn về các tính toán.
⚠️ Lưu ý Triển khai
- Tất cả thời gian nên được chuyển đổi sang giây để tính toán
- Tính toán rTSS sử dụng Hệ số Cường độ bình phương (IF²)
- Luôn xác thực đầu vào cho các phạm vi hợp lý
- Xử lý các trường hợp biên (chia cho 0, giá trị âm)
Các Chỉ số Hiệu suất Cốt lõi
Tốc độ Chạy tới hạn (CRS)
Công thức:
CRS (m/s) = (D₂ - D₁) / (T₂ - T₁)
Pace CRS (phút/km) = 16.667 / CRS (m/s)
🧪 Máy tính Tương tác - Thử nghiệm Công thức
Pace CRS (phút/km):
4:17
Các bước tính toán:
CRS (m/s) = (3600 - 1200) / (900 - 270) = 3.81 m/s
Pace (phút/km) = 1000 / 3.81 = 262 giây = 4:22
CRS (m/s) = (3600 - 1200) / (900 - 270) = 3.81 m/s
Pace (phút/km) = 1000 / 3.81 = 262 giây = 4:22
Triển khai JavaScript:
function calculateCRS(distance1, time1, distance2, time2) {
// Chuyển đổi thời gian sang giây
const t1 = typeof time1 === 'string' ? timeToSeconds(time1) : time1;
const t2 = typeof time2 === 'string' ? timeToSeconds(time2) : time2;
// Tính toán vận tốc CRS bằng m/s
const crs_ms = (distance2 - distance1) / (t2 - t1);
// Tính toán pace mỗi km bằng giây
const pace_per_km = 1000 / crs_ms;
// Chuyển đổi sang định dạng 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')}`
};
}Điểm Căng thẳng Chạy bộ (rTSS)
Công thức Hoàn chỉnh:
rTSS = (IF²) × Thời lượng (giờ) × 100
IF = NSS / Tốc độ Ngưỡng
NSS = Tổng Quãng đường / Tổng Thời gian (m/phút)
🧪 Máy tính Tương tác - Thử nghiệm Công thức
rTSS Tính toán:
31
Các bước tính toán:
NSS = 5000m / 25phút = 200 m/phút
FTP = 1000 / (255/60) = 235.3 m/phút
IF = 200 / 235.3 = 0.850
rTSS = 0.850² × (25/60) × 100 = 31
NSS = 5000m / 25phút = 200 m/phút
FTP = 1000 / (255/60) = 235.3 m/phút
IF = 200 / 235.3 = 0.850
rTSS = 0.850² × (25/60) × 100 = 31
Triển khai JavaScript:
function calculateRTSS(distance, timeMinutes, ftpMetersPerMin) {
// Tính Tốc độ Chạy Chuẩn hóa (Normalized Run Speed)
const nss = distance / timeMinutes;
// Tính Hệ số Cường độ (Intensity Factor)
const intensityFactor = nss / ftpMetersPerMin;
// Tính giờ
const hours = timeMinutes / 60;
// Tính rTSS sử dụng hệ số cường độ bình phương
const rtss = Math.pow(intensityFactor, 2) * hours * 100;
return Math.round(rtss);
}
// Ví dụ sử dụng:
const rtss = calculateRTSS(3000, 55, 64.5);
// Trả về: 65
// Helper: Chuyển đổi Pace CRS sang Tốc độ Chạy (m/phút)
function crsPaceToSpeed(crsPacePerKmSeconds) {
// Tốc độ m/phút = 1000m / (pace tính bằng phút)
return 1000 / (crsPacePerKmSeconds / 60);
}
// Ví dụ: CRS là 4:15 (255 giây)
const speed = crsPaceToSpeed(255); // Trả về: 235.3 m/phútHiệu quả Cơ sinh học: Tỷ lệ Dọc
Công thức:
Tỷ lệ Dọc (%) = (Dao động Dọc ÷ Chiều dài Sải bước) × 100
🧪 Máy tính Tương tác - Thử nghiệm Công thức
Tỷ lệ Dọc:
7.4%
Tính toán:
Tỷ lệ Dọc = (8.5 / 115) × 100 = 7.4%
Tỷ lệ Dọc = (8.5 / 115) × 100 = 7.4%
Triển khai JavaScript:
function calculateVerticalRatio(oscillationCm, strideLengthCm) {
return (oscillationCm / strideLengthCm) * 100;
}
function calculateEfficiencyFactor(paceMetersPerMin, avgHeartRate) {
return paceMetersPerMin / avgHeartRate;
}Đang chạy Cơ học Sải bước
Tần suất Sải bước (SR)
Công thức:
SR = 60 / Thời gian Chu kỳ (giây)
SR = (Số bước / Thời gian tính bằng giây) × 60
🧪 Máy tính Tương tác - Thử nghiệm Công thức
Nhịp bước (SPM):
180
Tính toán:
Nhịp bước = (180 / 60) × 60 = 180 SPM
Nhịp bước = (180 / 60) × 60 = 180 SPM
Triển khai JavaScript:
function calculateCadence(stepCount, timeSeconds) {
return (stepCount / timeSeconds) * 60;
}
// Ví dụ:
const spm = calculateCadence(180, 60);
// Trả về: 180 SPMChiều dài Sải bước
Công thức:
Chiều dài Sải bước = Quãng đường / (Số bước / 2)
Chiều dài Sải bước = Vận tốc / (Nhịp bước / 120)
Triển khai JavaScript:
function calculateStrideLength(distanceMeters, stepCount) {
// Chiều dài sải bước là quãng đường / số cặp sải bước (trái+phải)
return distanceMeters / (stepCount / 2);
}
// Ví dụ (1000m, 800 bước):
const strideLength = calculateStrideLength(1000, 800);
// Trả về: 2.50 mét mỗi sải bướcVận tốc từ SR và DPS
Công thức:
Vận tốc (m/s) = (SR / 60) × DPS
Triển khai JavaScript:
function calculateVelocity(strideRate, dps) {
return (strideRate / 60) * dps;
}
// Ví dụ:
const velocity = calculateVelocity(70, 1.6);
// Trả về: 1.87 m/sChỉ số Sải bước (SI)
Công thức:
SI = Vận tốc (m/s) × DPS (m/sải)
Triển khai JavaScript:
function calculateStrideIndex(velocity, dps) {
return velocity * dps;
}
// Ví dụ:
const si = calculateStrideIndex(1.5, 1.7);
// Trả về: 2.55Biểu đồ Quản lý Hiệu suất (PMC) để chạy
Tính toán CTL, ATL, TSB
Công thức:
CTL hôm nay = CTL hôm qua + (TSS hôm nay - CTL hôm qua) × (1/42)
ATL hôm nay = ATL hôm qua + (TSS hôm nay - ATL hôm qua) × (1/7)
TSB = CTL hôm qua - ATL hôm qua
Triển khai 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;
}
// Tính PMC cho chuỗi bài tập
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;
}
// Ví dụ sử dụng:
const workouts = [
{ date: '2025-01-01', tss: 50 },
{ date: '2025-01-02', tss: 60 },
{ date: '2025-01-03', tss: 45 },
// ... các bài tập khác
];
const pmc = calculatePMC(workouts);
// Trả về mảng với CTL, ATL, TSB cho mỗi ngàyTính toán Nâng cao
CRS từ Nhiều Quãng đường (Phương pháp Hồi quy)
Triển khai JavaScript:
function calculateCRSRegression(distances, times) {
// Hồi quy tuyến tính: 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 {
crs: slope, // Vận tốc chạy tới hạn (m/s)
anaerobic_capacity: intercept // Năng lực yếm khí (m)
};
}
// Ví dụ với nhiều quãng đường kiểm tra:
const distances = [100, 200, 400, 800];
const times = [65, 150, 340, 720]; // bằng giây
const result = calculateCRSRegression(distances, times);
// Trả về: { crs: 1.18, anaerobic_capacity: 15.3 }Hệ số Cường độ từ Pace
Triển khai JavaScript:
function calculateIntensityFactor(actualPaceMinKm, thresholdPaceMinKm) {
// Chuyển đổi chuỗi pace "mm:ss" sang giây nếu cần
const actualSecs = typeof actualPaceMinKm === 'string' ? timeToSeconds(actualPaceMinKm) : actualPaceMinKm;
const thresholdSecs = typeof thresholdPaceMinKm === 'string' ? timeToSeconds(thresholdPaceMinKm) : thresholdPaceMinKm;
// IF là Tốc độ Ngưỡng / Tốc độ Thực tế (pace nhanh hơn = giá trị giây nhỏ hơn)
return thresholdSecs / actualSecs;
}
// Ví dụ:
const if_value = calculateIntensityFactor("4:45", "4:15");
// Trả về: 0.895 (chạy ở 89.5% ngưỡng)Phân tích Tính Nhất quán của Pace
Triển khai 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 ? "Xuất sắc" :
coefficientOfVariation < 10 ? "Tốt" :
coefficientOfVariation < 15 ? "Trung bình" : "Biến động"
};
}
// Ví dụ:
const segments = [
{ distance: 100, time: 70 },
{ distance: 100, time: 72 },
{ distance: 100, time: 71 },
// ...
];
const analysis = analyzePaceConsistency(segments);
// Trả về: { avgPace: 1.41, stdDev: 0.02, coefficientOfVariation: 1.4, consistency: "Xuất sắc" }Phát hiện Mệt mỏi từ Hiệu quả Sải bước
Triển khai JavaScript:
function detectFatigue(segments) {
// So sánh Tỷ lệ Dọc của đoạn đầu và đoạn cuối
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 ? "Tối thiểu" :
ratioIncrease < 0.5 ? "Trung bình" :
ratioIncrease < 1.0 ? "Đáng kể" : "Nghiêm trọng"
};
}
// Ví dụ:
const segments = [
{ verticalRatio: 7.2 }, { verticalRatio: 7.3 }, { verticalRatio: 8.1 }
];
const fatigue = detectFatigue(segments);
// Trả về: { startRatio: 7.2, endRatio: 8.1, increase: 0.9, fatigueLevel: "Đáng kể" }Xác thực Dữ liệu
Kiểm tra Chất lượng Dữ liệu Bài tập
Triển khai JavaScript:
function validateWorkoutData(workout) {
const issues = [];
// Kiểm tra phạm vi pace hợp lý (3:00-8:00 mỗi km)
const avgPaceSecs = workout.totalTime / (workout.totalDistance / 1000);
if (avgPaceSecs < 180 || avgPaceSecs > 480) {
issues.push(`Pace trung bình bất thường: ${Math.round(avgPaceSecs)}s mỗi km`);
}
// Kiểm tra Tỷ lệ Dọc hợp lý (4% - 15%)
if (workout.avgVerticalRatio < 4 || workout.avgVerticalRatio > 15) {
issues.push(`Tỷ lệ Dọc bất thường: ${workout.avgVerticalRatio}%`);
}
// Kiểm tra nhịp bước hợp lý (120-220 SPM)
const avgCadence = calculateCadence(workout.totalSteps, workout.totalTime);
if (avgCadence < 120 || avgCadence > 220) {
issues.push(`Nhịp bước bất thường: ${Math.round(avgCadence)} SPM`);
}
// Kiểm tra các đoạn bị thiếu (khoảng trống thời gian)
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) { // khoảng trống 5 phút
issues.push(`Phát hiện khoảng trống lớn giữa các đoạn ${i} và ${i+1}`);
}
}
}
return {
isValid: issues.length === 0,
issues
};
}
// Ví dụ:
const workout = {
totalDistance: 2000,
totalTime: 1800, // 30 phút
totalStrides: 800,
segments: [/* dữ liệu km */]
};
const validation = validateWorkoutData(workout);
// Trả về: { isValid: true, issues: [] }Hàm Hỗ trợ
Tiện ích Chuyển đổi Thời gian
Triển khai JavaScript:
// Chuyển đổi mm:ss sang giây
function timeToSeconds(timeString) {
const parts = timeString.split(':');
return parseInt(parts[0]) * 60 + parseInt(parts[1]);
}
// Chuyển đổi giây sang mm:ss
function secondsToTime(seconds) {
const minutes = Math.floor(seconds / 60);
const secs = Math.round(seconds % 60);
return `${minutes}:${secs.toString().padStart(2, '0')}`;
}
// Chuyển đổi giây sang 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')}`;
}
// Ví dụ:
timeToSeconds("1:33"); // Trả về: 93
secondsToTime(93); // Trả về: "1:33"
secondsToTimeDetailed(3665); // Trả về: "1:01:05"Tài nguyên Triển khai
Tất cả các công thức trên trang này đều sẵn sàng cho sản xuất và được xác thực dựa trên tài liệu khoa học. Sử dụng chúng cho các công cụ phân tích tùy chỉnh, xác minh hoặc hiểu sâu hơn về các tính toán hiệu suất chạy bộ.
💡 Thực hành Tốt nhất
- Xác thực đầu vào: Kiểm tra các phạm vi hợp lý trước khi tính toán
- Xử lý trường hợp biên: Chia cho 0, giá trị âm, dữ liệu null
- Làm tròn phù hợp: CTL/ATL/TSB đến 1 chữ số thập phân, rTSS đến số nguyên
- Lưu trữ độ chính xác: Giữ độ chính xác đầy đủ trong cơ sở dữ liệu, làm tròn để hiển thị
- Kiểm tra kỹ lưỡng: Sử dụng dữ liệu tốt đã biết để xác minh tính toán
