Skip to content

Latest commit

Β 

History

30 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸƒ Runner Tools

Pure client-side exercise science algorithms, running pace formulas, and track utilities with zero dependencies. Built for runners, coaches, and sports data hackers.

License: MIT TypeScript CI


Live Demo

Experience these algorithms live in action on the web:


Highlights

  • Pure & Zero Dependencies: 100% pure TypeScript formulas with zero runtime dependencies. Runs anywhere: Node.js (dual ESM and CommonJS with full .d.ts / .d.cts), browsers, Bun, Deno, and Cloudflare Workers.
  • Scientifically Grounded: Implements Daniels & Gilbert's oxygen consumption models, Riegel's endurance power laws, Karvonen heart rate reserve equations, and World Masters Athletics (WMA) road standards.
  • Built-in i18n & Extensible: Multilingual support with hierarchical locale fallback (exact tag $\to$ base language $\to$ English default) and deep custom dictionary merging.
  • Strict Null Safety: Clear contracts where invalid, unphysiological, or unsolvable inputs return null instead of throwing or generating NaN.
  • No Silent Clamping: Discontinuous boundary cases and out-of-domain offsets are explicitly exposed rather than clamped silently.
  • Local File Conversion: Read FIT, GPX, TCX, KML and CSV; export all five plus GeoJSON. A standalone Web Worker keeps decoding, editing and encoding off the browser's UI thread, without CDN parser imports or file uploads.
  • Honest Track Comparison: Align tracks on overlapping timestamps or explicitly labeled route progress, interpolate mismatched sampling rates, and keep measured device distance separate from GPS-derived estimates.
  • Deterministic Interactive Tools: Audio scheduling follows the Web Audio clock, strength intervals follow monotonic elapsed time, and race-week calendar output is testable and locale-aware.

Installation

# npm
npm install @slow-bloom/runner-tools

# pnpm
pnpm add @slow-bloom/runner-tools

# yarn
yarn add @slow-bloom/runner-tools

Or directly via CDN in HTML:

<script src="https://cdn.jsdelivr.net/npm/@slow-bloom/runner-tools@0.2.0/dist/runner-tools.global.js"></script>
<script>
  const result = RunnerTools.calculateVDOT({ distanceMeters: 5000, timeSeconds: 1200 });
  if (result) {
    console.log('VDOT:', result.vdotFormatted); // "49.8"
  }
</script>

The browser bundle and dist/runner-tools.worker.js are supported distribution artifacts. Host both on the same origin when using createFileConverterClient; the worker installs a message handler and should not be imported into application code as a regular module.


Quickstart

import {
  calculateVDOT,
  predictRaceTime,
  calculateHeartRateZones,
  solvePace,
  parseGPX,
  serializeToTCX,
  analyzeTrack,
  createCadenceMetronome,
  createStrengthTimer,
  createRaceWeekPlan,
} from '@slow-bloom/runner-tools';

// 1. Calculate Daniels VDOT & training paces
const vdot = calculateVDOT({ distanceMeters: 5000, timeSeconds: 1200 });
console.log('Easy Pace:', vdot?.zones.E.lowPaceFormatted); // "5'03\""

// 2. Predict marathon finish time from a 10K
const marathonSecs = predictRaceTime(10000, 2700, 42195, 1.06); // ~12421s (3:27:01)

// 3. Calculate Karvonen Heart Rate Reserve (HRR) zones
const hr = calculateHeartRateZones({ method: 'karvonen', maxHR: 190, restingHR: 55 });
console.log('Zone 2:', hr?.zones[1].bpmFormatted); // "137 - 150 bpm"

// 4. Solve pace from distance and duration
const pace = solvePace({ distance: 10, timeSeconds: 2700, unit: 'km' });
console.log('Pace:', pace?.paceFormatted); // "4'30\""

// 5. Parse GPX and export as Garmin TCX
const activity = parseGPX(gpxContent);
const tcxContent = serializeToTCX(activity);

// 6. Analyze GPS distance without treating it as ground truth
const track = analyzeTrack(activity);

Modules & Documentation

Detailed mathematical derivations, physiological domains, and complete API specifications are documented in dedicated guides:

Module Category Scientific Model / Basis Documentation
vdot Formula Daniels-Gilbert oxygen power equation & E/M/T/I/R training paces docs/formulas/vdot.md
race-predictor Formula Peter Riegel's endurance power law ($T_2 = T_1 \cdot (D_2/D_1)^b$) docs/formulas/race-predictor.md
heart-rate-zones Formula Karvonen (HRR), %MaxHR, and Joe Friel 5-zone LTHR models docs/formulas/heart-rate-zones.md
age-grading Formula World Masters Athletics (WMA) 2020 road standards & scoring tiers docs/formulas/age-grading.md
running-efficiency Formula Vertical Ratio (VR), Duty Factor (DF), and Aerobic Efficiency Factor (EF) docs/formulas/running-efficiency.md
pace Formula 3-way pace/time/distance solver, unit conversions & split tables docs/formulas/pace.md
weekly-mileage Formula 10% progression rule, ACWR recovery periodization & deload cycles docs/formulas/weekly-mileage.md
files Tool FIT, GPX, TCX, KML and CSV parsing, GeoJSON export, cropping, merging, GPS redaction and local Web Worker conversion docs/files/running-file-converter.md
track-analysis Tool Recorded-vs-GPS provenance, timestamp/progress alignment, interpolation, split and drift indicators docs/files/track-analysis.md
race-week Planner Localized race-week template, pacing/fueling timeline and RFC 5545 calendar export docs/formulas/race-week.md
audio Tool Cadence target/tap tempo, cancellable Web Audio metronome, WAV and optional MP3 export docs/audio/cadence-metronome.md
timers Tool Workout schema/presets, timeline, elapsed-time strength state machine and cue adapter docs/timers/strength-timer.md
i18n Guide Custom dictionaries, locale registration, and fallback resolution docs/guides/i18n-and-customization.md

Operating Ranges & Principles

All algorithms conform to strict physiological domains:

Module Input Boundaries Return Contract on Out-of-Domain
VDOT Distance: 400 m – 200 km; Time: 30 s – 100 h; VDOT: 15 – 85 Returns null
Race Predictor Base/Target Distance > 0 m; Exponent: 1.00 – 1.30 Returns null
Heart Rate Zones Max HR: 80 – 240 bpm; Resting HR: 30 – 120 bpm (Max > Rest) Returns null
Age Grading Age: 5 – 100 years; Standard road distances (5K, 10K, Half, Full) Returns null
Running Efficiency Cadence: 100 – 260 spm; GCT: 100 – 500 ms; Duty Factor < 50% Returns null for invalid components
Pace Solver Distance: 0.01 – 10,000; Pace: 60 – 3600 s/unit; Exactly 2 defined fields Returns null
Weekly Mileage Volume: 1 – 500 units; Max Weekly Increase: 1% – 50% Returns null
Track Analysis 2+ GPS points; comparison samples: 2–10,001 Throws FileConversionError
Race Week Standard 5K/10K/Half/Marathon; volume: 1–500; frequency: 2–7 Returns null
Cadence Audio 120–210 spm; export: 1–900 s; WAV: 8–192 kHz Throws CadenceAudioError
Strength Timer 1–100 exercises; rounds: 1–10; import: ≀1 MiB Throws StrengthTimerError

Contributing

We welcome community contributions, sports science peer reviews, and bug reports! Please review CONTRIBUTING.md for local development workflows and test guidelines.

# Run unit tests
npm test

# Verify type definitions
npm run typecheck

# Build dual bundle & browser distribution
npm run build

# Verify the packed ESM, CommonJS, and TypeScript consumer entry points
npm run test:package

# Measure coverage
npm run test:coverage

# In the Apex Run collection checkout, build and copy the browser bundles,
# source maps and license into both ../website/apexrun and ../website/apexrun-zh
npm run sync:website

License

MIT License Β© 2026 Slowbloom Studio

About

πŸƒ Pure TypeScript running science algorithms, pace formulas, and track utilities with zero dependencies.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages