Terrain Difficulty Model
RaceCraft uses a sophisticated terrain difficulty system that models how different trail surfaces and technical features affect running pace. Unlike simple time penalties, terrain difficulty is implemented as a local, immediate efficiency penalty that affects segment speed without altering fatigue accumulation.
Overview
The terrain model recognises that technical terrain slows runners down independently of fitness or fatigue. A fresh runner on rocky terrain will be slower than on smooth trail, and a fatigued runner on rocky terrain will experience the same terrain-induced slowdown plus their fatigue penalty.
Key Principles
- Terrain affects speed, not fatigue: Terrain difficulty multiplies segment time but does NOT affect when fatigue kicks in or how fast it accumulates
- Separate from gradient: Terrain and elevation changes are independent factors - steep smooth trail is different from flat technical trail
- Skill-dependent: Technical skill reduces terrain penalties, representing experienced trail runners' ability to navigate obstacles efficiently
- Gradient-scaled: Terrain effects amplify on steeper grades (both up and down)
- Descent-weighted: Terrain impacts descents more than climbs (braking and foot placement are more critical downhill)
Terrain Efficiency Factor (TEF)
The core of the model is the Terrain Efficiency Factor (TEF), a multiplier applied to segment time:
segment_time = base_time × terrain_factor × fatigue_multiplier
Where: - base_time: Time to cover segment based on Z2 pace and elevation adjustments - terrain_factor: TEF from terrain model (≥ 1.0) - fatigue_multiplier: Separate fatigue penalty based on cumulative effort
Terrain Types and Baseline Factors
RaceCraft includes 7 terrain types with scientifically-derived baseline multipliers:
| Terrain Type | Factor | Description | Example |
|---|---|---|---|
| Road/Track | 0.95× | Paved or groomed surfaces | Roads, athletics tracks |
| Smooth Trail | 1.00× | Ideal baseline trail | Well-maintained singletrack, fire roads |
| Dirt Road | 1.05× | Unpaved roads, double track | Jeep trails, dirt roads |
| Rocky Runnable | 1.15× | Rocky but continuously runnable | Alpine trails with rock gardens |
| Technical Trail | 1.33× | Roots, rocks requiring care | Typical technical singletrack |
| Very Technical | 1.65× | Hands-on-knees terrain | Steep rock sections, major obstacles |
| Scrambling | 2.00× | Unstable footing, route-finding | Talus fields, boulder scrambles |
Factor Interpretation
A terrain factor of 1.33× means the terrain makes you 33% slower compared to smooth trail at the same gradient and effort level. For example: - Smooth trail at 6:00/km → Technical trail at 7:58/km - This is before gradient effects or skill adjustments
Gradient Scaling
Terrain effects become more pronounced on steeper terrain. The model applies gradient scaling:
effective_terrain_factor = terrain_factor × (1 + γ × |gradient|)
Where: - γ (gamma): Gradient scaling coefficient = 1.25 - gradient: Net grade as decimal (e.g., 0.10 = 10% grade)
Example
Technical trail (base factor 1.33×) on 10% grade:
effective_factor = 1.33 × (1 + 1.25 × 0.10)
= 1.33 × 1.125
= 1.496×
The terrain penalty increases from 33% to 49.6% due to the steep grade.
Rationale
Steeper terrain amplifies technical difficulty because: - Uphill: Harder to maintain line, more precise foot placement needed - Downhill: Greater braking forces, more consequence for missteps - Both: Reduced margin for error increases time cost of obstacles
Climb vs Descent Differential
Terrain affects descents more severely than climbs:
- Descents: 100% terrain effect
- Climbs: 70% terrain effect
This reflects the reality that: - Descending technical terrain requires constant braking and precise foot placement - Ascending technical terrain allows more careful, deliberate movement - Downhill speed amplifies consequences of mistakes
Example
Very technical terrain (1.65× base factor): - On descent: Full 1.65× penalty applied - On climb: Only 1.455× penalty (70% effect)
The formula:
if is_descent:
direction_adjusted = 1 + (scaled_factor - 1) × 1.0
else: # climb
direction_adjusted = 1 + (scaled_factor - 1) × 0.7
Technical Skill Adjustment
Athletes with better technical skills navigate difficult terrain faster. The skill parameter ranges from 0 (novice) to 1 (expert):
skill_adjusted_factor = 1 + (direction_adjusted_factor - 1) × (1 - skill)
Skill Levels
| Skill Level | Value | Terrain Penalty | Description |
|---|---|---|---|
| Novice | 0.0 | 100% | New to trail running |
| Beginner | 0.25 | 75% | Some trail experience |
| Intermediate | 0.5 | 50% | Regular trail runner |
| Advanced | 0.75 | 25% | Experienced technical runner |
| Expert | 1.0 | 0% | Elite mountain/trail runner |
Example
Technical trail (1.33× base) with intermediate skill (0.5):
adjusted_factor = 1 + (1.33 - 1) × (1 - 0.5)
= 1 + 0.33 × 0.5
= 1.165×
The runner experiences only 16.5% slowdown instead of 33% due to their technical proficiency.
Interpretation
An expert trail runner (skill = 1.0) on technical terrain runs at the same pace as if it were smooth trail - they've mastered the technique so well that terrain no longer slows them down. Meanwhile, a novice (skill = 0.0) experiences the full terrain penalty.
Complete Calculation Flow
The full terrain efficiency factor calculation combines all components:
Step 1: Base Terrain Factor
Select terrain type → get base factor (e.g., Technical Trail = 1.33×)
Step 2: Gradient Scaling
scaled_factor = base_factor × (1 + γ × |gradient|)
Step 3: Descent/Climb Adjustment
if elevation_loss > elevation_gain:
direction_factor = 1 + (scaled_factor - 1) × 1.0 # descent
else:
direction_factor = 1 + (scaled_factor - 1) × 0.7 # climb
Step 4: Skill Adjustment
final_factor = 1 + (direction_factor - 1) × (1 - skill_level)
Step 5: Apply to Segment Time
adjusted_time = base_segment_time × final_factor × fatigue_multiplier
Worked Example
Scenario: Technical trail segment - Distance: 5 km - Net elevation: -200m (descent) - Average gradient: -4% - Base pace: 6:00/km (no elevation) - After elevation adjustment: 5:30/km (downhill benefit) - Skill level: Intermediate (0.5) - No fatigue yet (multiplier = 1.0)
Calculation:
Base terrain factor: Technical Trail = 1.33×
Gradient scaling:
scaled = 1.33 × (1 + 1.25 × 0.04) = 1.33 × 1.05 = 1.397×Descent adjustment (100% effect):
direction = 1 + (1.397 - 1) × 1.0 = 1.397×Skill adjustment (intermediate):
final = 1 + (1.397 - 1) × (1 - 0.5) = 1 + 0.397 × 0.5 = 1.198×Apply to segment:
base_time = 5 km × 5:30/km = 27:30 terrain_adjusted = 27:30 × 1.198 = 32:57 final_pace = 32:57 / 5 km = 6:35/km
Result: Despite the downhill advantage (5:30/km elevation-adjusted pace), the technical terrain slows the runner to 6:35/km - slower than their flat pace. A novice runner would be at 7:28/km on the same segment.
Integration with Fatigue Model
The terrain system operates independently of the fatigue model:
Fatigue Calculations (Unchanged)
effort_km = distance + ascent/100 + descent/200
cumulative_effort += segment_effort
if cumulative_effort > FOP:
fatigue_multiplier = 1 + α × ((E - FOP) / FOP)^β
Combined Effect
final_pace = base_pace × terrain_factor × fatigue_multiplier
Key Point: Terrain difficulty does NOT: - Change when fatigue starts (FOP remains the same) - Affect how fast fatigue accumulates (effort calculation unchanged) - Compound with fatigue exponentially (multipliers are independent)
A runner with 30% terrain penalty and 20% fatigue penalty experiences:
1.30 × 1.20 = 1.56× total slowdown (56% slower than base)
NOT: 50% slower (30% + 20%)
Usage Guidelines
Choosing Terrain Type
Consider the predominant surface and technical demands of each segment:
- Road/Track: Almost entirely paved, no obstacles
- Smooth Trail: Well-maintained, minimal obstacles, good footing
- Dirt Road: Unpaved but wide, minimal technical features
- Rocky Runnable: Rocks/roots present but continuous running possible
- Technical Trail: Frequent obstacles requiring focus and adjustment
- Very Technical: Regular need to use hands, careful foot placement
- Scrambling: Route-finding, boulder hopping, significant exposure
Setting Skill Level
Be honest about technical ability:
- Novice: First trail race, limited technical experience
- Beginner: 1-2 years trail running, comfortable on moderate terrain
- Intermediate: Regular trail racer, confident on most technical terrain
- Advanced: Experienced mountain runner, rarely slowed by terrain
- Expert: Elite level, technical sections are not a limiting factor
Tips for Accuracy
- Be conservative early in plan development: Overestimate terrain difficulty for unfamiliar courses
- Adjust after reconnaissance: Update terrain types after course preview
- Consider conditions: Wet/muddy conditions may warrant upgrading terrain type
- Segment appropriately: Break course into segments with similar terrain characteristics
- Don't overthink it: Small errors in terrain type have minimal impact on overall plan
Model Validation and Tuning
The terrain factors are derived from: - Field data from trail running studies - Analysis of professional endurance athlete splits - Comparison of road vs trail pace ratios - Trail running community feedback
Adjusting Parameters (Advanced)
If you need to tune the model for your specific conditions, the key parameters in app.py are:
TERRAIN_FACTORS = {
'road': 0.95,
'smooth_trail': 1.0,
'dirt_road': 1.05,
'rocky_runnable': 1.15,
'technical': 1.325,
'very_technical': 1.65,
'scrambling': 2.0
}
TERRAIN_GRADIENT_GAMMA = 1.25 # How much gradient amplifies terrain
TERRAIN_CLIMB_FACTOR = 0.7 # Terrain effect on climbs (0.0-1.0)
TERRAIN_DESCENT_FACTOR = 1.0 # Terrain effect on descents (0.0-1.0)
Comparison to Old System
The previous system used simple time additions: - Easy (road): -10 seconds/km - Normal: 0 seconds/km - Difficult: +10s/km uphill, +20s/km downhill
Limitations of old system: - Fixed penalties regardless of gradient - No skill adjustment - Only 3 categories - Inconsistent with fatigue model
New system advantages: - Multiplicative (scales with pace and fatigue) - Gradient-aware - Skill-adjustable - 7 detailed terrain types - Mathematically consistent with other penalties - Better represents real-world running biomechanics
See Also
- Fatigue Model Documentation - Understanding cumulative effort and fatigue onset
- Main README - General application usage and features
References
The terrain model is based on research and practical experience in: - Mountain and trail running physiology - Trail running pace analysis - Biomechanical studies of running on varied surfaces - Elite athlete training and racing data
For questions or suggestions about the terrain model, please open an issue on the project repository.