Techninė informacija ir formulės
Išsamus matematinis įgyvendinimas
Įgyvendinimo vadovas
Šiame puslapyje pateikiamos paruoštos formulės ir nuoseklūs skaičiavimo metodai visoms „Swim Analytics“ metrikoms. Naudokite juos savo skaičiavimams, jų patikrinimui ar gilesniam supratimui.
⚠️ Įgyvendinimo pastabos
- Visi laikai skaičiavimams turi būti paversti sekundėmis
- Plaukimo tempas yra atvirkštinis (didesnis % = lėtesnis tempas)
- Visada tikrinkite, ar įvesties duomenys yra loginėse ribose
- Numatykite išimtinius atvejus (dalyba iš nulio, neigiamos reikšmės)
Pagrindinės rezultatų metrikos
Kritinis plaukimo greitis (CSS)
Formulė:
CSS (m/s) = (D₂ - D₁) / (T₂ - T₁)
CSS tempas/100m (sekundėmis) = (T₄₀₀ - T₂₀₀) / 2
🧪 Interaktyvi skaičiuoklė – išbandykite formulę
CSS tempas 100 metrų:
1:49
Skaičiavimo žingsniai:
CSS (m/s) = (400 - 200) / (368 - 150) = 0.917 m/s
Tempas/100m = 100 / 0.917 = 109 sekundės = 1:49
CSS (m/s) = (400 - 200) / (368 - 150) = 0.917 m/s
Tempas/100m = 100 / 0.917 = 109 sekundės = 1:49
JavaScript įgyvendinimas:
function calculateCSS(distance1, time1, distance2, time2) {
// Jei reikia, paverčiame laiką sekundėmis
const t1 = typeof time1 === 'string' ? timeToSeconds(time1) : time1;
const t2 = typeof time2 === 'string' ? timeToSeconds(time2) : time2;
// Skaičiuojame CSS m/s
const css_ms = (distance2 - distance1) / (t2 - t1);
// Skaičiuojame tempą 100m sekundėmis
const pace_per_100m = 100 / css_ms;
// Konvertuojame į mm:ss formatą
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')}`
};
}
// Pavyzdys:
const result = calculateCSS(200, 150, 400, 368);
// Grąžina: { css_ms: 0.917, pace_seconds: 109, pace_formatted: "1:49" }
Plaukimo treniruočių streso balas (sTSS)
Išsami formulė:
sTSS = (IF³) × Trukmė (valandomis) × 100
IF = NSS / FTP
NSS = Visas atstumas / Visas laikas (m/min)
🧪 Interaktyvi skaičiuoklė – išbandykite formulę
Apskaičiuotas sTSS:
55
Skaičiavimo žingsniai:
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
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
JavaScript įgyvendinimas:
function calculateSTSS(distance, timeMinutes, ftpMetersPerMin) {
// Skaičiuojame normalizuotą plaukimo greitį
const nss = distance / timeMinutes;
// Skaičiuojame intensyvumo faktorių
const intensityFactor = nss / ftpMetersPerMin;
// Skaičiuojame valandas
const hours = timeMinutes / 60;
// Skaičiuojame sTSS naudodami intensyvumo faktoriun pakeltą kūbu
const stss = Math.pow(intensityFactor, 3) * hours * 100;
return Math.round(stss);
}
// Pavyzdys:
const stss = calculateSTSS(3000, 55, 64.5);
// Grąžina: 55
// Pagalbinė funkcija: konvertuojame CSS į slenkstį (FTP)
function cssToFTP(cssPacePer100mSeconds) {
// FTP m/min = 100m / (tempas minutėmis)
return 100 / (cssPacePer100mSeconds / 60);
}
// Pavyzdys: CSS 1:33 (93 sekundės)
const ftp = cssToFTP(93); // Grąžina: 64.5 m/min
SWOLF
Formulė:
SWOLF = Rato laikas (sekundėmis) + Grybšnių skaičius
SWOLF₂₅ = (Laikas × 25/Baseino ilgis) + (Grybšniai × 25/Baseino ilgis)
🧪 Interaktyvi skaičiuoklė – išbandykite formulę
SWOLF balas:
35
Skaičiavimas:
SWOLF = 20s + 15 grybšnių = 35
SWOLF = 20s + 15 grybšnių = 35
JavaScript įgyvendinimas:
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;
}
// Pavyzdys:
const swolf = calculateSWOLF(20, 15);
// Grąžina: 35
const swolf50m = calculateNormalizedSWOLF(40, 30, 50);
// Grąžina: 35 (normalizuota į 25m baseiną)
Grybšnių mechanika
Grybšnių dažnis (SR)
Formulė:
SR = 60 / Ciklo laikas (sekundėmis)
SR = (Grybšnių skaičius / Laikas sekundėmis) × 60
🧪 Interaktyvi skaičiuoklė – išbandykite formulę
Grybšnių dažnis (SPM):
72
Skaičiavimas:
SR = (30 / 25) × 60 = 72 SPM
SR = (30 / 25) × 60 = 72 SPM
JavaScript įgyvendinimas:
function calculateStrokeRate(strokeCount, timeSeconds) {
return (strokeCount / timeSeconds) * 60;
}
// Pavyzdys:
const sr = calculateStrokeRate(30, 25);
// Grąžina: 72 SPM
Atstumas per grybšnį (DPS)
Formulė:
DPS = Atstumas / Grybšnių skaičius
DPS = Atstumas / (SR / 60)
JavaScript įgyvendinimas:
function calculateDPS(distance, strokeCount, pushoffDistance = 0) {
const effectiveDistance = distance - pushoffDistance;
return effectiveDistance / strokeCount;
}
// Pavyzdys (25m baseinas, 5m atsispyrimas):
const dps = calculateDPS(25, 12, 5);
// Grąžina: 1.67 m/grybšnis
// Keliems ratams:
const dps100m = calculateDPS(100, 48, 4 * 5);
// Grąžina: 1.67 m/grybšnis (4 ratai × 5m atsispyrimas)
Greitis skaičiuojant iš SR ir DPS
Formulė:
Greitis (m/s) = (SR / 60) × DPS
JavaScript įgyvendinimas:
function calculateVelocity(strokeRate, dps) {
return (strokeRate / 60) * dps;
}
// Pavyzdys:
const velocity = calculateVelocity(70, 1.6);
// Grąžina: 1.87 m/s
Grybšnių indeksas (SI)
Formulė:
SI = Greitis (m/s) × DPS (m/grybšnis)
JavaScript įgyvendinimas:
function calculateStrokeIndex(velocity, dps) {
return velocity * dps;
}
// Pavyzdys:
const si = calculateStrokeIndex(1.5, 1.7);
// Grąžina: 2.55
Rezultatų valdymo grafikas (PMC)
CTL, ATL, TSB skaičiavimai
Formulės:
CTL šiandien = CTL vakar + (TSS šiandien - CTL vakar) × (1/42)
ATL šiandien = ATL vakar + (TSS šiandien - ATL vakar) × (1/7)
TSB = CTL vakar - ATL vakar
JavaScript įgyvendinimas:
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;
}
// Skaičiuojame PMC treniruočių serijai
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;
}
// Pavyzdys:
const workouts = [
{ date: '2025-01-01', tss: 50 },
{ date: '2025-01-02', tss: 60 },
{ date: '2025-01-03', tss: 45 },
// ... daugiau treniruočių
];
const pmc = calculatePMC(workouts);
// Grąžina masyvą su CTL, ATL, TSB reikšmėmis kiekvienai dienai
Pažangūs skaičiavimai
CSS skaičiavimas iš kelių atstumų (regresijos metodas)
JavaScript įgyvendinimas:
function calculateCSSRegression(distances, times) {
// Tiesinė regresija: 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, // Kritinis plaukimo greitis (m/s)
anaerobic_capacity: intercept // Anaerobinio atstumo talpa (m)
};
}
// Pavyzdys su keliais kontroliniais atstumais:
const distances = [100, 200, 400, 800];
const times = [65, 150, 340, 720]; // sekundėmis
const result = calculateCSSRegression(distances, times);
// Grąžina: { css: 1.18, anaerobic_capacity: 15.3 }
Intensyvumo faktorius skaičiuojant pagal tempą
JavaScript įgyvendinimas:
function calculateIntensityFactor(actualPace100m, thresholdPace100m) {
// Paverčiame tempą į greitį (m/s)
const actualSpeed = 100 / actualPace100m;
const thresholdSpeed = 100 / thresholdPace100m;
return actualSpeed / thresholdSpeed;
}
// Pavyzdys:
const if_value = calculateIntensityFactor(110, 93);
// Grąžina: 0.845 (plaukiama 84,5% slenksčio greičio)
Tempo nuoseklumo analizė
JavaScript įgyvendinimas:
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 ? "Puikus" :
coefficientOfVariation < 10 ? "Geras" :
coefficientOfVariation < 15 ? "Vidutinis" : "Kintantis"
};
}
// Pavyzdys:
const laps = [
{ distance: 100, time: 70 },
{ distance: 100, time: 72 },
{ distance: 100, time: 71 },
// ...
];
const analysis = analyzePaceConsistency(laps);
// Grąžina: { avgPace: 1.41, stdDev: 0.02, coefficientOfVariation: 1.4, consistency: "Puikus" }
Nuovargio nustatymas pagal grybšnių skaičių
JavaScript įgyvendinimas:
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 ? "Minimalus" :
strokeCountIncrease < 10 ? "Vidutinis" :
strokeCountIncrease < 20 ? "Didelis" : "Labai didelis"
};
}
// Pavyzdys:
const laps = [
{ strokeCount: 14 }, { strokeCount: 14 }, { strokeCount: 15 },
{ strokeCount: 15 }, { strokeCount: 16 }, { strokeCount: 16 },
{ strokeCount: 17 }, { strokeCount: 18 }, { strokeCount: 18 }
];
const fatigue = detectFatigue(laps);
// Grąžina: { firstThirdAvg: 14.3, lastThirdAvg: 17.7, percentIncrease: 23.8, fatigueLevel: "Labai didelis" }
Duomenų patikra
Treniruotės duomenų kokybės tikrinimas
JavaScript įgyvendinimas:
function validateWorkoutData(workout) {
const issues = [];
// Tikriname, ar tempas yra loginėse ribose (1:00-5:00 per 100m)
const avgPace = (workout.totalTime / workout.totalDistance) * 100;
if (avgPace < 60 || avgPace > 300) {
issues.push(`Neįprastas vidutinis tempas: ${Math.round(avgPace)}s per 100m`);
}
// Tikriname grybšnių skaičių (10-50 per 25m)
const avgStrokesPer25m = (workout.totalStrokes / workout.totalDistance) * 25;
if (avgStrokesPer25m < 10 || avgStrokesPer25m > 50) {
issues.push(`Neįprastas grybšnių skaičius: ${Math.round(avgStrokesPer25m)} per 25m`);
}
// Tikriname grybšnių dažnį (30-150 SPM)
const avgSR = calculateStrokeRate(workout.totalStrokes, workout.totalTime);
if (avgSR < 30 || avgSR > 150) {
issues.push(`Neįprastas grybšnių dažnis: ${Math.round(avgSR)} SPM`);
}
// Tikriname, ar nėra dingusių ratų (dideli laiko tarpai)
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) { // 5 minučių tarpas
issues.push(`Aptiktas didelis tarpas tarp ${i} ir ${i+1} rato`);
}
}
}
return {
isValid: issues.length === 0,
issues: issues
};
}