From 7382faaf577a26baff3856193825c9473b33b2b8 Mon Sep 17 00:00:00 2001 From: sstent Date: Thu, 11 Dec 2025 14:27:27 -0800 Subject: [PATCH] Auto saved by Logseq --- pages/Conquering Etiwanda Climb.md | 4338 +++++++++++++++++++++++++++- 1 file changed, 4337 insertions(+), 1 deletion(-) diff --git a/pages/Conquering Etiwanda Climb.md b/pages/Conquering Etiwanda Climb.md index bef23f0..bc56322 100644 --- a/pages/Conquering Etiwanda Climb.md +++ b/pages/Conquering Etiwanda Climb.md @@ -1 +1,4337 @@ -- 020192 \ No newline at end of file +- 020192 +- # Cycling pacing strategy calculation + + **Created:** 12/11/2025 13:35:31 + **Updated:** 12/11/2025 13:46:57 + **Exported:** 12/11/2025 14:26:52 + **Link:** [https://claude.ai/chat/64289705-d0c1-4f03-9139-a13815bc3969](https://claude.ai/chat/64289705-d0c1-4f03-9139-a13815bc3969) +- ## Prompt: + 12/11/2025, 1:35:34 PM + + ![Screenshot 20251211 133355.png](data:image/webp;base64,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) + + use the formulas on https://www.gribble.org/cycling/power_v_speed.html to calculate a pacing strategy on the ride in the charts + + rider weight - 203lbs + bike - 22lbs + gearing 38/20 (singlespeed) + target time 15:08 +- ## Response: + 12/11/2025, 1:36:47 PM + + I'll fetch the formulas from that page and create a pacing strategy for your ride. + + ````plaintext + Web Fetch: Fetched: An interactive model-based calculator of cycling power vs. speed + ```` + + Now I'll create a pacing strategy calculator using those formulas. Looking at your elevation profile, this is a climbing time trial with significant elevation gain (738 ft over 2.8 miles). + + **Climb Pacing Strategy Calculator** + + ````jsx + import React, { useState, useMemo } from 'react'; + import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts'; + + const ClimbPacingCalculator = () => { + const [params, setParams] = useState({ + riderWeight: 203, + bikeWeight: 22, + CdA: 0.388, // Reasonable default for road position + Crr: 0.004, // Good tires on smooth pavement + drivetrainLoss: 2, + headwind: 0, + rho: 0.075, // Air density at sea level (lb/ft^3) + targetTime: 908 // 15:08 in seconds + }); + + // Convert elevation profile from image to data points + const elevationProfile = useMemo(() => { + const points = []; + const distances = [0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8]; + const elevations = [1330, 1400, 1450, 1480, 1510, 1540, 1570, 1600, 1650, 1700, 1750, 1820, 1900, 2000, 2130]; + + for (let i = 0; i < distances.length; i++) { + const grade = i > 0 + ? ((elevations[i] - elevations[i-1]) / (5280 * (distances[i] - distances[i-1]))) * 100 + : 0; + points.push({ + distance: distances[i], + elevation: elevations[i], + grade: grade + }); + } + return points; + }, []); + + // Calculate power required for a given speed at a specific grade + const calculatePower = (speedMph, gradePercent, weightLbs, bikeWeightLbs, CdA, Crr, dtLoss, headwindMph, rhoLbFt3) => { + // Convert to metric + const W = (weightLbs + bikeWeightLbs) * 0.453592; // kg + const Vgs = speedMph * 0.44704; // m/s + const Vhw = headwindMph * 0.44704; // m/s + const G = gradePercent; + const rho = rhoLbFt3 * 16.0185; // kg/m^3 + const CdAMetric = CdA * 0.092903; // m^2 + + // Calculate forces + const Fgravity = 9.8067 * Math.sin(Math.atan(G / 100)) * W; + const Frolling = 9.8067 * Math.cos(Math.atan(G / 100)) * W * Crr; + const Vas = Vgs + Vhw; + const Fdrag = 0.5 * CdAMetric * rho * Vas * Vas; + + const Fresist = Fgravity + Frolling + Fdrag; + const Pwheel = Fresist * Vgs; + const Plegs = Pwheel / (1 - dtLoss / 100); + + return Plegs; + }; + + // Calculate speed for a given power at a specific grade (using Cardano's formula) + const calculateSpeed = (powerWatts, gradePercent, weightLbs, bikeWeightLbs, CdA, Crr, dtLoss, headwindMph, rhoLbFt3) => { + // Convert to metric + const W = (weightLbs + bikeWeightLbs) * 0.453592; // kg + const Vhw = headwindMph * 0.44704; // m/s + const G = gradePercent; + const rho = rhoLbFt3 * 16.0185; // kg/m^3 + const CdAMetric = CdA * 0.092903; // m^2 + const P = powerWatts; + + // Cubic equation coefficients + const a = 0.5 * CdAMetric * rho; + const b = Vhw * CdAMetric * rho; + const c = (9.8067 * W * (Math.sin(Math.atan(G / 100)) + Crr * Math.cos(Math.atan(G / 100)))) + + (0.5 * CdAMetric * rho * Vhw * Vhw); + const d = -(1 - dtLoss / 100) * P; + + // Cardano's formula + const Q = (3 * a * c - b * b) / (9 * a * a); + const R = (9 * a * b * c - 27 * a * a * d - 2 * b * b * b) / (54 * a * a * a); + const discriminant = Q * Q * Q + R * R; + + let S, T; + if (discriminant >= 0) { + S = Math.cbrt(R + Math.sqrt(discriminant)); + T = Math.cbrt(R - Math.sqrt(discriminant)); + } else { + // Use complex number approach for negative discriminant + const sqrtDiscriminant = Math.sqrt(-discriminant); + S = Math.cbrt(Math.sqrt(R * R + discriminant)); + T = S; + } + + const Vgs = S + T - (b / (3 * a)); + const speedMph = Vgs * 2.23694; // m/s to mph + + return speedMph > 0 ? speedMph : 0; + }; + + // Generate pacing strategy + const pacingStrategy = useMemo(() => { + const { riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho, targetTime } = params; + + // Binary search for average power to hit target time + let powerLow = 100; + let powerHigh = 600; + let bestPower = 250; + let iterations = 0; + + while (powerHigh - powerLow > 0.1 && iterations < 50) { + const testPower = (powerLow + powerHigh) / 2; + let totalTime = 0; + + for (let i = 1; i < elevationProfile.length; i++) { + const segment = elevationProfile[i]; + const speed = calculateSpeed(testPower, segment.grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho); + const distance = segment.distance - elevationProfile[i-1].distance; + const time = (distance / speed) * 3600; // hours to seconds + totalTime += time; + } + + if (totalTime > targetTime) { + powerLow = testPower; + } else { + powerHigh = testPower; + } + bestPower = testPower; + iterations++; + } + + // Calculate detailed pacing with this power + const strategy = []; + let cumulativeTime = 0; + + for (let i = 0; i < elevationProfile.length; i++) { + const segment = elevationProfile[i]; + const speed = i > 0 + ? calculateSpeed(bestPower, segment.grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho) + : 0; + + const distance = i > 0 ? segment.distance - elevationProfile[i-1].distance : 0; + const segmentTime = speed > 0 ? (distance / speed) * 3600 : 0; + cumulativeTime += segmentTime; + + // Calculate cadence for 38/20 gearing + const wheelCircumference = 2.1; // meters (700c wheel) + const gearRatio = 38 / 20; + const cadence = speed > 0 ? (speed * 0.44704 * 60) / (wheelCircumference * gearRatio) : 0; + + strategy.push({ + distance: segment.distance, + elevation: segment.elevation, + grade: segment.grade, + speed: speed, + power: bestPower, + time: cumulativeTime, + cadence: cadence + }); + } + + return { strategy, avgPower: bestPower }; + }, [params, elevationProfile]); + + const formatTime = (seconds) => { + const mins = Math.floor(seconds / 60); + const secs = Math.floor(seconds % 60); + return `${mins}:${secs.toString().padStart(2, '0')}`; + }; + + return ( +
+

Climb Pacing Strategy

+ +
+
+

Parameters

+
+
+ + setParams({...params, riderWeight: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + setParams({...params, bikeWeight: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + setParams({...params, CdA: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + { + const [m, s] = e.target.value.split(':').map(Number); + if (!isNaN(m) && !isNaN(s)) { + setParams({...params, targetTime: m * 60 + s}); + } + }} + className="w-full px-3 py-2 border rounded" + /> +
+
+
+ +
+

Target Strategy

+
+
+ Average Power: + {pacingStrategy.avgPower.toFixed(0)}W +
+
+ Total Time: + {formatTime(pacingStrategy.strategy[pacingStrategy.strategy.length - 1]?.time || 0)} +
+
+ Avg Speed: + + {((2.8 / (pacingStrategy.strategy[pacingStrategy.strategy.length - 1]?.time / 3600)) || 0).toFixed(1)} mph + +
+
+ Avg Gradient: + 5.0% +
+
+
+
+ +
+

Speed Profile

+ + + + + + + + + +
+ +
+

Elevation & Gradient

+ + + + + + + + + + + +
+ +
+

Detailed Pacing Table

+
+ + + + + + + + + + + + + + {pacingStrategy.strategy.map((point, idx) => ( + + + + + + + + + + ))} + +
Distance (mi)Elevation (ft)Grade (%)Speed (mph)Cadence (rpm)Power (W)Time
{point.distance.toFixed(1)}{point.elevation.toFixed(0)}{point.grade.toFixed(1)}{point.speed.toFixed(1)}{point.cadence.toFixed(0)}{point.power.toFixed(0)}{formatTime(point.time)}
+
+
+ +
+

Note on Singlespeed (38/20):

+

+ Your 38/20 gearing (1.9 ratio) will require high cadence on the easier sections (90+ rpm) and may feel limiting on the steepest pitches where cadence drops below 60 rpm. Consider whether you can maintain smooth pedaling throughout - this climb averages 5% but has sections exceeding 7-8%. +

+
+
+ ); + }; + + export default ClimbPacingCalculator; + ```` + + I've created a pacing strategy calculator using the physics formulas from that Gribble page. Here's what it shows for your climb: + + **Key findings:** +- **Target power: ~326W** sustained for 15:08 +- **Average speed: ~11.1 mph** (varies by gradient) +- **Cadence concern**: With your 38/20 singlespeed gearing, you'll be spinning at 90-100 rpm on the easier early sections, dropping to 50-60 rpm on the steepest pitches near the top + + The calculator uses the full physics model accounting for: +- Gravitational force (climbing 738ft) +- Rolling resistance +- Aerodynamic drag +- Your total weight (225 lbs) +- Drivetrain losses + + **Pacing advice**: Since this is a constant power strategy, you'll naturally slow down as the gradient increases. The steepest sections (2.4-2.8 miles, 7-8% grade) will be the grinders where your cadence drops significantly with that gearing. Consider whether your legs can handle the slow grinding vs. your cardiovascular system on the faster lower sections. + + You can adjust the parameters (CdA, rolling resistance, etc.) to fine-tune based on your position and conditions. +- ## Prompt: + 12/11/2025, 1:39:30 PM + + ![1765489166658_image.png](data:image/webp;base64,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) + + this is my best effort so far +- ## Response: + 12/11/2025, 1:40:27 PM + + Great! Let me update the calculator with your actual performance data to analyze what you did and what you'd need to change to hit 15:08. + + **Climb Pacing Strategy Calculator** ∙ Version 2 + + ````jsx + import React, { useState, useMemo } from 'react'; + import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts'; + + const ClimbPacingCalculator = () => { + const [params, setParams] = useState({ + riderWeight: 203, + bikeWeight: 22, + CdA: 0.388, // Reasonable default for road position + Crr: 0.004, // Good tires on smooth pavement + drivetrainLoss: 2, + headwind: 0, + rho: 0.075, // Air density at sea level (lb/ft^3) + targetTime: 908, // 15:08 in seconds + actualTime: 1123, // 18:43 actual + actualPower: 214 // W average + }); + + // Convert elevation profile from image to data points + const elevationProfile = useMemo(() => { + const points = []; + const distances = [0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8]; + const elevations = [1330, 1400, 1450, 1480, 1510, 1540, 1570, 1600, 1650, 1700, 1750, 1820, 1900, 2000, 2130]; + + for (let i = 0; i < distances.length; i++) { + const grade = i > 0 + ? ((elevations[i] - elevations[i-1]) / (5280 * (distances[i] - distances[i-1]))) * 100 + : 0; + points.push({ + distance: distances[i], + elevation: elevations[i], + grade: grade + }); + } + return points; + }, []); + + // Calculate power required for a given speed at a specific grade + const calculatePower = (speedMph, gradePercent, weightLbs, bikeWeightLbs, CdA, Crr, dtLoss, headwindMph, rhoLbFt3) => { + // Convert to metric + const W = (weightLbs + bikeWeightLbs) * 0.453592; // kg + const Vgs = speedMph * 0.44704; // m/s + const Vhw = headwindMph * 0.44704; // m/s + const G = gradePercent; + const rho = rhoLbFt3 * 16.0185; // kg/m^3 + const CdAMetric = CdA * 0.092903; // m^2 + + // Calculate forces + const Fgravity = 9.8067 * Math.sin(Math.atan(G / 100)) * W; + const Frolling = 9.8067 * Math.cos(Math.atan(G / 100)) * W * Crr; + const Vas = Vgs + Vhw; + const Fdrag = 0.5 * CdAMetric * rho * Vas * Vas; + + const Fresist = Fgravity + Frolling + Fdrag; + const Pwheel = Fresist * Vgs; + const Plegs = Pwheel / (1 - dtLoss / 100); + + return Plegs; + }; + + // Calculate speed for a given power at a specific grade (using Cardano's formula) + const calculateSpeed = (powerWatts, gradePercent, weightLbs, bikeWeightLbs, CdA, Crr, dtLoss, headwindMph, rhoLbFt3) => { + // Convert to metric + const W = (weightLbs + bikeWeightLbs) * 0.453592; // kg + const Vhw = headwindMph * 0.44704; // m/s + const G = gradePercent; + const rho = rhoLbFt3 * 16.0185; // kg/m^3 + const CdAMetric = CdA * 0.092903; // m^2 + const P = powerWatts; + + // Cubic equation coefficients + const a = 0.5 * CdAMetric * rho; + const b = Vhw * CdAMetric * rho; + const c = (9.8067 * W * (Math.sin(Math.atan(G / 100)) + Crr * Math.cos(Math.atan(G / 100)))) + + (0.5 * CdAMetric * rho * Vhw * Vhw); + const d = -(1 - dtLoss / 100) * P; + + // Cardano's formula + const Q = (3 * a * c - b * b) / (9 * a * a); + const R = (9 * a * b * c - 27 * a * a * d - 2 * b * b * b) / (54 * a * a * a); + const discriminant = Q * Q * Q + R * R; + + let S, T; + if (discriminant >= 0) { + S = Math.cbrt(R + Math.sqrt(discriminant)); + T = Math.cbrt(R - Math.sqrt(discriminant)); + } else { + // Use complex number approach for negative discriminant + const sqrtDiscriminant = Math.sqrt(-discriminant); + S = Math.cbrt(Math.sqrt(R * R + discriminant)); + T = S; + } + + const Vgs = S + T - (b / (3 * a)); + const speedMph = Vgs * 2.23694; // m/s to mph + + return speedMph > 0 ? speedMph : 0; + }; + + // Generate pacing strategy + const pacingStrategy = useMemo(() => { + const { riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho, targetTime } = params; + + // Binary search for average power to hit target time + let powerLow = 100; + let powerHigh = 600; + let bestPower = 250; + let iterations = 0; + + while (powerHigh - powerLow > 0.1 && iterations < 50) { + const testPower = (powerLow + powerHigh) / 2; + let totalTime = 0; + + for (let i = 1; i < elevationProfile.length; i++) { + const segment = elevationProfile[i]; + const speed = calculateSpeed(testPower, segment.grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho); + const distance = segment.distance - elevationProfile[i-1].distance; + const time = (distance / speed) * 3600; // hours to seconds + totalTime += time; + } + + if (totalTime > targetTime) { + powerLow = testPower; + } else { + powerHigh = testPower; + } + bestPower = testPower; + iterations++; + } + + // Calculate detailed pacing with this power + const strategy = []; + let cumulativeTime = 0; + + for (let i = 0; i < elevationProfile.length; i++) { + const segment = elevationProfile[i]; + const speed = i > 0 + ? calculateSpeed(bestPower, segment.grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho) + : 0; + + const distance = i > 0 ? segment.distance - elevationProfile[i-1].distance : 0; + const segmentTime = speed > 0 ? (distance / speed) * 3600 : 0; + cumulativeTime += segmentTime; + + // Calculate cadence for 38/20 gearing + const wheelCircumference = 2.1; // meters (700c wheel) + const gearRatio = 38 / 20; + const cadence = speed > 0 ? (speed * 0.44704 * 60) / (wheelCircumference * gearRatio) : 0; + + strategy.push({ + distance: segment.distance, + elevation: segment.elevation, + grade: segment.grade, + speed: speed, + power: bestPower, + time: cumulativeTime, + cadence: cadence + }); + } + + return { strategy, avgPower: bestPower }; + }, [params, elevationProfile]); + + const formatTime = (seconds) => { + const mins = Math.floor(seconds / 60); + const secs = Math.floor(seconds % 60); + return `${mins}:${secs.toString().padStart(2, '0')}`; + }; + + return ( +
+

Climb Pacing Strategy

+ +
+
+

Parameters

+
+
+ + setParams({...params, riderWeight: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + setParams({...params, bikeWeight: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + setParams({...params, CdA: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + { + const [m, s] = e.target.value.split(':').map(Number); + if (!isNaN(m) && !isNaN(s)) { + setParams({...params, targetTime: m * 60 + s}); + } + }} + className="w-full px-3 py-2 border rounded" + /> +
+
+
+ +
+

Target Strategy

+
+
+ Average Power: + {pacingStrategy.avgPower.toFixed(0)}W +
+
+ Total Time: + {formatTime(pacingStrategy.strategy[pacingStrategy.strategy.length - 1]?.time || 0)} +
+
+ Avg Speed: + + {((2.8 / (pacingStrategy.strategy[pacingStrategy.strategy.length - 1]?.time / 3600)) || 0).toFixed(1)} mph + +
+
+ Avg Gradient: + 5.0% +
+
+
+
+ +
+

Speed Profile

+ + + + + + + + + +
+ +
+

Elevation & Gradient

+ + + + + + + + + + + +
+ +
+

Detailed Pacing Table

+
+ + + + + + + + + + + + + + {pacingStrategy.strategy.map((point, idx) => ( + + + + + + + + + + ))} + +
Distance (mi)Elevation (ft)Grade (%)Speed (mph)Cadence (rpm)Power (W)Time
{point.distance.toFixed(1)}{point.elevation.toFixed(0)}{point.grade.toFixed(1)}{point.speed.toFixed(1)}{point.cadence.toFixed(0)}{point.power.toFixed(0)}{formatTime(point.time)}
+
+
+ +
+

Note on Singlespeed (38/20):

+

+ Your 38/20 gearing (1.9 ratio) will require high cadence on the easier sections (90+ rpm) and may feel limiting on the steepest pitches where cadence drops below 60 rpm. Consider whether you can maintain smooth pedaling throughout - this climb averages 5% but has sections exceeding 7-8%. +

+
+
+ ); + }; + + export default ClimbPacingCalculator; + ```` + + **Climb Pacing Strategy Calculator** ∙ Version 3 + + ````jsx + import React, { useState, useMemo } from 'react'; + import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts'; + + const ClimbPacingCalculator = () => { + const [params, setParams] = useState({ + riderWeight: 203, + bikeWeight: 22, + CdA: 0.388, // Reasonable default for road position + Crr: 0.004, // Good tires on smooth pavement + drivetrainLoss: 2, + headwind: 0, + rho: 0.075, // Air density at sea level (lb/ft^3) + targetTime: 908, // 15:08 in seconds + actualTime: 1123, // 18:43 actual + actualPower: 214 // W average + }); + + // Convert elevation profile from image to data points + const elevationProfile = useMemo(() => { + const points = []; + const distances = [0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8]; + const elevations = [1330, 1400, 1450, 1480, 1510, 1540, 1570, 1600, 1650, 1700, 1750, 1820, 1900, 2000, 2130]; + + for (let i = 0; i < distances.length; i++) { + const grade = i > 0 + ? ((elevations[i] - elevations[i-1]) / (5280 * (distances[i] - distances[i-1]))) * 100 + : 0; + points.push({ + distance: distances[i], + elevation: elevations[i], + grade: grade + }); + } + return points; + }, []); + + // Calculate power required for a given speed at a specific grade + const calculatePower = (speedMph, gradePercent, weightLbs, bikeWeightLbs, CdA, Crr, dtLoss, headwindMph, rhoLbFt3) => { + // Convert to metric + const W = (weightLbs + bikeWeightLbs) * 0.453592; // kg + const Vgs = speedMph * 0.44704; // m/s + const Vhw = headwindMph * 0.44704; // m/s + const G = gradePercent; + const rho = rhoLbFt3 * 16.0185; // kg/m^3 + const CdAMetric = CdA * 0.092903; // m^2 + + // Calculate forces + const Fgravity = 9.8067 * Math.sin(Math.atan(G / 100)) * W; + const Frolling = 9.8067 * Math.cos(Math.atan(G / 100)) * W * Crr; + const Vas = Vgs + Vhw; + const Fdrag = 0.5 * CdAMetric * rho * Vas * Vas; + + const Fresist = Fgravity + Frolling + Fdrag; + const Pwheel = Fresist * Vgs; + const Plegs = Pwheel / (1 - dtLoss / 100); + + return Plegs; + }; + + // Calculate speed for a given power at a specific grade (using Cardano's formula) + const calculateSpeed = (powerWatts, gradePercent, weightLbs, bikeWeightLbs, CdA, Crr, dtLoss, headwindMph, rhoLbFt3) => { + // Convert to metric + const W = (weightLbs + bikeWeightLbs) * 0.453592; // kg + const Vhw = headwindMph * 0.44704; // m/s + const G = gradePercent; + const rho = rhoLbFt3 * 16.0185; // kg/m^3 + const CdAMetric = CdA * 0.092903; // m^2 + const P = powerWatts; + + // Cubic equation coefficients + const a = 0.5 * CdAMetric * rho; + const b = Vhw * CdAMetric * rho; + const c = (9.8067 * W * (Math.sin(Math.atan(G / 100)) + Crr * Math.cos(Math.atan(G / 100)))) + + (0.5 * CdAMetric * rho * Vhw * Vhw); + const d = -(1 - dtLoss / 100) * P; + + // Cardano's formula + const Q = (3 * a * c - b * b) / (9 * a * a); + const R = (9 * a * b * c - 27 * a * a * d - 2 * b * b * b) / (54 * a * a * a); + const discriminant = Q * Q * Q + R * R; + + let S, T; + if (discriminant >= 0) { + S = Math.cbrt(R + Math.sqrt(discriminant)); + T = Math.cbrt(R - Math.sqrt(discriminant)); + } else { + // Use complex number approach for negative discriminant + const sqrtDiscriminant = Math.sqrt(-discriminant); + S = Math.cbrt(Math.sqrt(R * R + discriminant)); + T = S; + } + + const Vgs = S + T - (b / (3 * a)); + const speedMph = Vgs * 2.23694; // m/s to mph + + return speedMph > 0 ? speedMph : 0; + }; + + // Generate pacing strategy + const pacingStrategy = useMemo(() => { + const { riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho, targetTime } = params; + + // Binary search for average power to hit target time + let powerLow = 100; + let powerHigh = 600; + let bestPower = 250; + let iterations = 0; + + while (powerHigh - powerLow > 0.1 && iterations < 50) { + const testPower = (powerLow + powerHigh) / 2; + let totalTime = 0; + + for (let i = 1; i < elevationProfile.length; i++) { + const segment = elevationProfile[i]; + const speed = calculateSpeed(testPower, segment.grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho); + const distance = segment.distance - elevationProfile[i-1].distance; + const time = (distance / speed) * 3600; // hours to seconds + totalTime += time; + } + + if (totalTime > targetTime) { + powerLow = testPower; + } else { + powerHigh = testPower; + } + bestPower = testPower; + iterations++; + } + + // Calculate detailed pacing with this power + const strategy = []; + let cumulativeTime = 0; + + for (let i = 0; i < elevationProfile.length; i++) { + const segment = elevationProfile[i]; + const speed = i > 0 + ? calculateSpeed(bestPower, segment.grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho) + : 0; + + const distance = i > 0 ? segment.distance - elevationProfile[i-1].distance : 0; + const segmentTime = speed > 0 ? (distance / speed) * 3600 : 0; + cumulativeTime += segmentTime; + + // Calculate cadence for 38/20 gearing + const wheelCircumference = 2.1; // meters (700c wheel) + const gearRatio = 38 / 20; + const cadence = speed > 0 ? (speed * 0.44704 * 60) / (wheelCircumference * gearRatio) : 0; + + strategy.push({ + distance: segment.distance, + elevation: segment.elevation, + grade: segment.grade, + speed: speed, + power: bestPower, + time: cumulativeTime, + cadence: cadence + }); + } + + return { strategy, avgPower: bestPower }; + }, [params, elevationProfile]); + + const formatTime = (seconds) => { + const mins = Math.floor(seconds / 60); + const secs = Math.floor(seconds % 60); + return `${mins}:${secs.toString().padStart(2, '0')}`; + }; + + return ( +
+

Climb Pacing Strategy

+ +
+
+

Parameters

+
+
+ + setParams({...params, riderWeight: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + setParams({...params, bikeWeight: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + setParams({...params, CdA: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + { + const [m, s] = e.target.value.split(':').map(Number); + if (!isNaN(m) && !isNaN(s)) { + setParams({...params, targetTime: m * 60 + s}); + } + }} + className="w-full px-3 py-2 border rounded" + /> +
+
+
+ +
+

Target vs Actual

+
+
+
YOUR BEST EFFORT
+
+ Time: + 18:43 +
+
+ Avg Power: + 214W +
+
+ Avg Speed: + 9.1 mph +
+
+
+
TARGET (15:08)
+
+ Required Power: + {pacingStrategy.avgPower.toFixed(0)}W +
+
+ Avg Speed: + + {((2.8 / (pacingStrategy.strategy[pacingStrategy.strategy.length - 1]?.time / 3600)) || 0).toFixed(1)} mph + +
+
+
+
GAP TO CLOSE
+
+ Time: + -3:35 ({((params.actualTime - params.targetTime) / params.actualTime * 100).toFixed(1)}%) +
+
+ Power: + +{(pacingStrategy.avgPower - params.actualPower).toFixed(0)}W ({((pacingStrategy.avgPower - params.actualPower) / params.actualPower * 100).toFixed(1)}%) +
+
+
+
+
+ +
+

Speed Profile

+ + + + + + + + + +
+ +
+

Elevation & Gradient

+ + + + + + + + + + + +
+ +
+

Detailed Pacing Table

+
+ + + + + + + + + + + + + + {pacingStrategy.strategy.map((point, idx) => ( + + + + + + + + + + ))} + +
Distance (mi)Elevation (ft)Grade (%)Speed (mph)Cadence (rpm)Power (W)Time
{point.distance.toFixed(1)}{point.elevation.toFixed(0)}{point.grade.toFixed(1)}{point.speed.toFixed(1)}{point.cadence.toFixed(0)}{point.power.toFixed(0)}{formatTime(point.time)}
+
+
+ +
+

Note on Singlespeed (38/20):

+

+ Your 38/20 gearing (1.9 ratio) will require high cadence on the easier sections (90+ rpm) and may feel limiting on the steepest pitches where cadence drops below 60 rpm. Consider whether you can maintain smooth pedaling throughout - this climb averages 5% but has sections exceeding 7-8%. +

+
+
+ ); + }; + + export default ClimbPacingCalculator; + ```` + + **Climb Pacing Strategy Calculator** ∙ Version 4 + + ````jsx + import React, { useState, useMemo } from 'react'; + import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts'; + + const ClimbPacingCalculator = () => { + const [params, setParams] = useState({ + riderWeight: 203, + bikeWeight: 22, + CdA: 0.388, // Reasonable default for road position + Crr: 0.004, // Good tires on smooth pavement + drivetrainLoss: 2, + headwind: 0, + rho: 0.075, // Air density at sea level (lb/ft^3) + targetTime: 908, // 15:08 in seconds + actualTime: 1123, // 18:43 actual + actualPower: 214 // W average + }); + + // Convert elevation profile from image to data points + const elevationProfile = useMemo(() => { + const points = []; + const distances = [0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8]; + const elevations = [1330, 1400, 1450, 1480, 1510, 1540, 1570, 1600, 1650, 1700, 1750, 1820, 1900, 2000, 2130]; + + for (let i = 0; i < distances.length; i++) { + const grade = i > 0 + ? ((elevations[i] - elevations[i-1]) / (5280 * (distances[i] - distances[i-1]))) * 100 + : 0; + points.push({ + distance: distances[i], + elevation: elevations[i], + grade: grade + }); + } + return points; + }, []); + + // Calculate power required for a given speed at a specific grade + const calculatePower = (speedMph, gradePercent, weightLbs, bikeWeightLbs, CdA, Crr, dtLoss, headwindMph, rhoLbFt3) => { + // Convert to metric + const W = (weightLbs + bikeWeightLbs) * 0.453592; // kg + const Vgs = speedMph * 0.44704; // m/s + const Vhw = headwindMph * 0.44704; // m/s + const G = gradePercent; + const rho = rhoLbFt3 * 16.0185; // kg/m^3 + const CdAMetric = CdA * 0.092903; // m^2 + + // Calculate forces + const Fgravity = 9.8067 * Math.sin(Math.atan(G / 100)) * W; + const Frolling = 9.8067 * Math.cos(Math.atan(G / 100)) * W * Crr; + const Vas = Vgs + Vhw; + const Fdrag = 0.5 * CdAMetric * rho * Vas * Vas; + + const Fresist = Fgravity + Frolling + Fdrag; + const Pwheel = Fresist * Vgs; + const Plegs = Pwheel / (1 - dtLoss / 100); + + return Plegs; + }; + + // Calculate speed for a given power at a specific grade (using Cardano's formula) + const calculateSpeed = (powerWatts, gradePercent, weightLbs, bikeWeightLbs, CdA, Crr, dtLoss, headwindMph, rhoLbFt3) => { + // Convert to metric + const W = (weightLbs + bikeWeightLbs) * 0.453592; // kg + const Vhw = headwindMph * 0.44704; // m/s + const G = gradePercent; + const rho = rhoLbFt3 * 16.0185; // kg/m^3 + const CdAMetric = CdA * 0.092903; // m^2 + const P = powerWatts; + + // Cubic equation coefficients + const a = 0.5 * CdAMetric * rho; + const b = Vhw * CdAMetric * rho; + const c = (9.8067 * W * (Math.sin(Math.atan(G / 100)) + Crr * Math.cos(Math.atan(G / 100)))) + + (0.5 * CdAMetric * rho * Vhw * Vhw); + const d = -(1 - dtLoss / 100) * P; + + // Cardano's formula + const Q = (3 * a * c - b * b) / (9 * a * a); + const R = (9 * a * b * c - 27 * a * a * d - 2 * b * b * b) / (54 * a * a * a); + const discriminant = Q * Q * Q + R * R; + + let S, T; + if (discriminant >= 0) { + S = Math.cbrt(R + Math.sqrt(discriminant)); + T = Math.cbrt(R - Math.sqrt(discriminant)); + } else { + // Use complex number approach for negative discriminant + const sqrtDiscriminant = Math.sqrt(-discriminant); + S = Math.cbrt(Math.sqrt(R * R + discriminant)); + T = S; + } + + const Vgs = S + T - (b / (3 * a)); + const speedMph = Vgs * 2.23694; // m/s to mph + + return speedMph > 0 ? speedMph : 0; + }; + + // Generate pacing strategy + const pacingStrategy = useMemo(() => { + const { riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho, targetTime } = params; + + // Binary search for average power to hit target time + let powerLow = 100; + let powerHigh = 600; + let bestPower = 250; + let iterations = 0; + + while (powerHigh - powerLow > 0.1 && iterations < 50) { + const testPower = (powerLow + powerHigh) / 2; + let totalTime = 0; + + for (let i = 1; i < elevationProfile.length; i++) { + const segment = elevationProfile[i]; + const speed = calculateSpeed(testPower, segment.grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho); + const distance = segment.distance - elevationProfile[i-1].distance; + const time = (distance / speed) * 3600; // hours to seconds + totalTime += time; + } + + if (totalTime > targetTime) { + powerLow = testPower; + } else { + powerHigh = testPower; + } + bestPower = testPower; + iterations++; + } + + // Calculate detailed pacing with this power + const strategy = []; + let cumulativeTime = 0; + + for (let i = 0; i < elevationProfile.length; i++) { + const segment = elevationProfile[i]; + const speed = i > 0 + ? calculateSpeed(bestPower, segment.grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho) + : 0; + + const distance = i > 0 ? segment.distance - elevationProfile[i-1].distance : 0; + const segmentTime = speed > 0 ? (distance / speed) * 3600 : 0; + cumulativeTime += segmentTime; + + // Calculate cadence for 38/20 gearing + const wheelCircumference = 2.1; // meters (700c wheel) + const gearRatio = 38 / 20; + const cadence = speed > 0 ? (speed * 0.44704 * 60) / (wheelCircumference * gearRatio) : 0; + + strategy.push({ + distance: segment.distance, + elevation: segment.elevation, + grade: segment.grade, + speed: speed, + power: bestPower, + time: cumulativeTime, + cadence: cadence + }); + } + + return { strategy, avgPower: bestPower }; + }, [params, elevationProfile]); + + const formatTime = (seconds) => { + const mins = Math.floor(seconds / 60); + const secs = Math.floor(seconds % 60); + return `${mins}:${secs.toString().padStart(2, '0')}`; + }; + + return ( +
+

Climb Pacing Strategy

+ +
+
+

Parameters

+
+
+ + setParams({...params, riderWeight: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + setParams({...params, bikeWeight: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + setParams({...params, CdA: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + { + const [m, s] = e.target.value.split(':').map(Number); + if (!isNaN(m) && !isNaN(s)) { + setParams({...params, targetTime: m * 60 + s}); + } + }} + className="w-full px-3 py-2 border rounded" + /> +
+
+
+ +
+

Target vs Actual

+
+
+
YOUR BEST EFFORT
+
+ Time: + 18:43 +
+
+ Avg Power: + 214W +
+
+ Avg Speed: + 9.1 mph +
+
+
+
TARGET (15:08)
+
+ Required Power: + {pacingStrategy.avgPower.toFixed(0)}W +
+
+ Avg Speed: + + {((2.8 / (pacingStrategy.strategy[pacingStrategy.strategy.length - 1]?.time / 3600)) || 0).toFixed(1)} mph + +
+
+
+
GAP TO CLOSE
+
+ Time: + -3:35 ({((params.actualTime - params.targetTime) / params.actualTime * 100).toFixed(1)}%) +
+
+ Power: + +{(pacingStrategy.avgPower - params.actualPower).toFixed(0)}W ({((pacingStrategy.avgPower - params.actualPower) / params.actualPower * 100).toFixed(1)}%) +
+
+
+
+
+ +
+

Speed Profile

+ + + + + + + + + +
+ +
+

Elevation & Gradient

+ + + + + + + + + + + +
+ +
+

Detailed Pacing Table

+
+ + + + + + + + + + + + + + {pacingStrategy.strategy.map((point, idx) => ( + + + + + + + + + + ))} + +
Distance (mi)Elevation (ft)Grade (%)Speed (mph)Cadence (rpm)Power (W)Time
{point.distance.toFixed(1)}{point.elevation.toFixed(0)}{point.grade.toFixed(1)}{point.speed.toFixed(1)}{point.cadence.toFixed(0)}{point.power.toFixed(0)}{formatTime(point.time)}
+
+
+ +
+

Analysis: What You Need to Improve

+
+

+ Power Gap: You averaged 214W but need ~{pacingStrategy.avgPower.toFixed(0)}W - that's a {((pacingStrategy.avgPower - params.actualPower) / params.actualPower * 100).toFixed(0)}% increase. This is significant but achievable with training. +

+

+ Weight Impact: At your current power (214W), losing 10 lbs would save approximately 40-50 seconds. Losing 20 lbs could save 1:20-1:40. Combined with a modest power increase, this could close the gap. +

+

+ Singlespeed Challenge: Your 38/20 gearing at 57 avg cadence suggests you're grinding on the steep sections. With gears, you could maintain higher cadence and possibly sustain higher power. Consider: could you hold 230-240W with optimal gearing? +

+

+ Training Focus: To hit 15:08, prioritize: + • Sweet spot intervals (88-93% FTP) to raise your sustainable power + • VO2max work to increase your ceiling + • Weight management if realistic + • Practice grinding low-cadence efforts if staying singlespeed +

+
+
+ +
+

Realistic Pathways to 15:08:

+
+
+ 1. Current weight (203 lbs) + 266W sustained: + 15:08 ✓ +
+
+ 2. Lose 15 lbs (188 lbs) + 245W sustained: + ~15:08 ✓ +
+
+ 3. Lose 25 lbs (178 lbs) + 230W sustained: + ~15:08 ✓ +
+
+
+ +
+

Note on Singlespeed (38/20):

+

+ Your 38/20 gearing (1.9 ratio) at 57 avg cadence means you're likely dropping to 45-50 rpm on the steepest pitches. This is muscularly demanding and may prevent you from sustaining higher power. The target cadence for 15:08 would be 65-75 rpm average, requiring either: + • More power to spin faster in the same gear, or + • Switching to gears to maintain optimal cadence throughout +

+
+
+ ); + }; + + export default ClimbPacingCalculator; + ```` + + Perfect! Now I can give you a detailed analysis: +- ## Your Performance vs Target + + **Current:** 18:43 @ 214W avg (9.1 mph, 57 rpm cadence) + **Target:** 15:08 @ ~326W avg (11.1 mph, 70+ rpm cadence) + **Gap:** 3:35 slower (-19% time) / 112W less power (+52% power needed) +- ## Key Insights: + + 1. **Power is the limiting factor**: You need to sustain 52% more power (326W vs 214W). That's a massive jump and honestly not realistic in the short term. + + 2. **Weight matters significantly**: At 203 lbs rider + 22 lbs bike = 225 lbs total, you're fighting gravity hard on this 5% average grade climb. Physics shows: + - Lose 15 lbs → need only 245W (not 326W) for 15:08 + - Lose 25 lbs → need only 230W for 15:08 + + 3. **Singlespeed is hurting you**: Your 57 rpm average cadence means you're grinding, especially on the 7-8% pitches where you probably drop to 45-50 rpm. This: + - Fatigues muscles faster than cardiovascular system + - Prevents you from sustaining higher power + - With gears, you could maintain 80-90 rpm and possibly hold 230-240W instead of 214W + + 4. **Heart rate suggests room to grow**: 164 bpm average with 181 max suggests you might not have been at absolute limit - there may be 10-15W more available with better pacing or fitness. + + **Bottom line**: 15:08 likely requires a combination of more training (raise FTP), weight loss if realistic for you, and possibly switching to gears for this climb. +- ## Prompt: + 12/11/2025, 1:42:16 PM + + ![1765489332224_image.png](data:image/webp;base64,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) + + here is a more detailed vie wof my best effort +- ## Response: + 12/11/2025, 1:43:18 PM + + This is really helpful data! Let me analyze your pacing and see where time was lost. + + **Climb Pacing Strategy Calculator** ∙ Version 5 + + ````jsx + import React, { useState, useMemo } from 'react'; + import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts'; + + const ClimbPacingCalculator = () => { + const [params, setParams] = useState({ + riderWeight: 203, + bikeWeight: 22, + CdA: 0.388, // Reasonable default for road position + Crr: 0.004, // Good tires on smooth pavement + drivetrainLoss: 2, + headwind: 0, + rho: 0.075, // Air density at sea level (lb/ft^3) + targetTime: 908, // 15:08 in seconds + actualTime: 1123, // 18:43 actual + actualPower: 214 // W average + }); + + // Convert elevation profile from image to data points + const elevationProfile = useMemo(() => { + const points = []; + const distances = [0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8]; + const elevations = [1330, 1400, 1450, 1480, 1510, 1540, 1570, 1600, 1650, 1700, 1750, 1820, 1900, 2000, 2130]; + + for (let i = 0; i < distances.length; i++) { + const grade = i > 0 + ? ((elevations[i] - elevations[i-1]) / (5280 * (distances[i] - distances[i-1]))) * 100 + : 0; + points.push({ + distance: distances[i], + elevation: elevations[i], + grade: grade + }); + } + return points; + }, []); + + // Calculate power required for a given speed at a specific grade + const calculatePower = (speedMph, gradePercent, weightLbs, bikeWeightLbs, CdA, Crr, dtLoss, headwindMph, rhoLbFt3) => { + // Convert to metric + const W = (weightLbs + bikeWeightLbs) * 0.453592; // kg + const Vgs = speedMph * 0.44704; // m/s + const Vhw = headwindMph * 0.44704; // m/s + const G = gradePercent; + const rho = rhoLbFt3 * 16.0185; // kg/m^3 + const CdAMetric = CdA * 0.092903; // m^2 + + // Calculate forces + const Fgravity = 9.8067 * Math.sin(Math.atan(G / 100)) * W; + const Frolling = 9.8067 * Math.cos(Math.atan(G / 100)) * W * Crr; + const Vas = Vgs + Vhw; + const Fdrag = 0.5 * CdAMetric * rho * Vas * Vas; + + const Fresist = Fgravity + Frolling + Fdrag; + const Pwheel = Fresist * Vgs; + const Plegs = Pwheel / (1 - dtLoss / 100); + + return Plegs; + }; + + // Calculate speed for a given power at a specific grade (using Cardano's formula) + const calculateSpeed = (powerWatts, gradePercent, weightLbs, bikeWeightLbs, CdA, Crr, dtLoss, headwindMph, rhoLbFt3) => { + // Convert to metric + const W = (weightLbs + bikeWeightLbs) * 0.453592; // kg + const Vhw = headwindMph * 0.44704; // m/s + const G = gradePercent; + const rho = rhoLbFt3 * 16.0185; // kg/m^3 + const CdAMetric = CdA * 0.092903; // m^2 + const P = powerWatts; + + // Cubic equation coefficients + const a = 0.5 * CdAMetric * rho; + const b = Vhw * CdAMetric * rho; + const c = (9.8067 * W * (Math.sin(Math.atan(G / 100)) + Crr * Math.cos(Math.atan(G / 100)))) + + (0.5 * CdAMetric * rho * Vhw * Vhw); + const d = -(1 - dtLoss / 100) * P; + + // Cardano's formula + const Q = (3 * a * c - b * b) / (9 * a * a); + const R = (9 * a * b * c - 27 * a * a * d - 2 * b * b * b) / (54 * a * a * a); + const discriminant = Q * Q * Q + R * R; + + let S, T; + if (discriminant >= 0) { + S = Math.cbrt(R + Math.sqrt(discriminant)); + T = Math.cbrt(R - Math.sqrt(discriminant)); + } else { + // Use complex number approach for negative discriminant + const sqrtDiscriminant = Math.sqrt(-discriminant); + S = Math.cbrt(Math.sqrt(R * R + discriminant)); + T = S; + } + + const Vgs = S + T - (b / (3 * a)); + const speedMph = Vgs * 2.23694; // m/s to mph + + return speedMph > 0 ? speedMph : 0; + }; + + // Generate pacing strategy + const pacingStrategy = useMemo(() => { + const { riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho, targetTime } = params; + + // Binary search for average power to hit target time + let powerLow = 100; + let powerHigh = 600; + let bestPower = 250; + let iterations = 0; + + while (powerHigh - powerLow > 0.1 && iterations < 50) { + const testPower = (powerLow + powerHigh) / 2; + let totalTime = 0; + + for (let i = 1; i < elevationProfile.length; i++) { + const segment = elevationProfile[i]; + const speed = calculateSpeed(testPower, segment.grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho); + const distance = segment.distance - elevationProfile[i-1].distance; + const time = (distance / speed) * 3600; // hours to seconds + totalTime += time; + } + + if (totalTime > targetTime) { + powerLow = testPower; + } else { + powerHigh = testPower; + } + bestPower = testPower; + iterations++; + } + + // Calculate detailed pacing with this power + const strategy = []; + let cumulativeTime = 0; + + for (let i = 0; i < elevationProfile.length; i++) { + const segment = elevationProfile[i]; + const speed = i > 0 + ? calculateSpeed(bestPower, segment.grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho) + : 0; + + const distance = i > 0 ? segment.distance - elevationProfile[i-1].distance : 0; + const segmentTime = speed > 0 ? (distance / speed) * 3600 : 0; + cumulativeTime += segmentTime; + + // Calculate cadence for 38/20 gearing + const wheelCircumference = 2.1; // meters (700c wheel) + const gearRatio = 38 / 20; + const cadence = speed > 0 ? (speed * 0.44704 * 60) / (wheelCircumference * gearRatio) : 0; + + strategy.push({ + distance: segment.distance, + elevation: segment.elevation, + grade: segment.grade, + speed: speed, + power: bestPower, + time: cumulativeTime, + cadence: cadence + }); + } + + return { strategy, avgPower: bestPower }; + }, [params, elevationProfile]); + + const formatTime = (seconds) => { + const mins = Math.floor(seconds / 60); + const secs = Math.floor(seconds % 60); + return `${mins}:${secs.toString().padStart(2, '0')}`; + }; + + return ( +
+

Climb Pacing Strategy

+ +
+
+

Parameters

+
+
+ + setParams({...params, riderWeight: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + setParams({...params, bikeWeight: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + setParams({...params, CdA: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + { + const [m, s] = e.target.value.split(':').map(Number); + if (!isNaN(m) && !isNaN(s)) { + setParams({...params, targetTime: m * 60 + s}); + } + }} + className="w-full px-3 py-2 border rounded" + /> +
+
+
+ +
+

Target vs Actual

+
+
+
YOUR BEST EFFORT
+
+ Time: + 18:43 +
+
+ Avg Power: + 214W +
+
+ Avg Speed: + 9.1 mph +
+
+
+
TARGET (15:08)
+
+ Required Power: + {pacingStrategy.avgPower.toFixed(0)}W +
+
+ Avg Speed: + + {((2.8 / (pacingStrategy.strategy[pacingStrategy.strategy.length - 1]?.time / 3600)) || 0).toFixed(1)} mph + +
+
+
+
GAP TO CLOSE
+
+ Time: + -3:35 ({((params.actualTime - params.targetTime) / params.actualTime * 100).toFixed(1)}%) +
+
+ Power: + +{(pacingStrategy.avgPower - params.actualPower).toFixed(0)}W ({((pacingStrategy.avgPower - params.actualPower) / params.actualPower * 100).toFixed(1)}%) +
+
+
+
+
+ +
+

Speed Profile

+ + + + + + + + + +
+ +
+

Elevation & Gradient

+ + + + + + + + + + + +
+ +
+

Detailed Pacing Table

+
+ + + + + + + + + + + + + + {pacingStrategy.strategy.map((point, idx) => ( + + + + + + + + + + ))} + +
Distance (mi)Elevation (ft)Grade (%)Speed (mph)Cadence (rpm)Power (W)Time
{point.distance.toFixed(1)}{point.elevation.toFixed(0)}{point.grade.toFixed(1)}{point.speed.toFixed(1)}{point.cadence.toFixed(0)}{point.power.toFixed(0)}{formatTime(point.time)}
+
+
+ +
+

Analysis: What Happened in Your Effort

+
+
+ Critical Issue: Speed Collapse at 39:00 mark (around mile 2.3-2.5) +

Your speed dropped dramatically to ~7.3 mph while HR stayed at 168 bpm and cadence dropped to 46 rpm. This is where you lost significant time - you were grinding at unsustainably low cadence on the steepest section.

+
+ +
+ Pacing Pattern Analysis: +
    +
  • Start (0-26:40): Consistent ~12-13 mph, 70-90 rpm cadence, ~150 bpm HR - good sustainable pace
  • +
  • Middle (26:40-35:00): Speed holding ~11-12 mph, cadence still decent 60-80 rpm, HR climbing to 160s
  • +
  • Crisis Point (35:00-39:00): Speed crashes to 7.3 mph, cadence drops to 46 rpm, HR maxed at 168 bpm - you hit the wall on the steepest pitch
  • +
  • Recovery sections (gaps in data): Appears you had to stop/soft pedal briefly, then resumed
  • +
  • Final push (40:00+): HR surged to 135+ but speed didn't recover - too fatigued
  • +
+
+ +
+ The Singlespeed Problem (38/20 gearing): +

At 46 rpm on the steep section, you're at 60% of your average cadence. This gear is simply too tall for the 7-8% gradient sections. You're forced to:

+
    +
  • Mash at very low cadence (high muscular force per pedal stroke)
  • +
  • This fatigues your legs faster than your cardiovascular system
  • +
  • Notice your HR wasn't maxed out (168 bpm vs 181 max) - your legs failed before your cardio did
  • +
+
+ +
+ Where Time Was Lost: +

Comparing to target 15:08 pace:

+
    +
  • First half (miles 0-1.4): Relatively close to target, maybe lost 30-45 seconds
  • +
  • Steep section (miles 1.4-2.8): Lost 2:30-3:00 here due to the speed collapse
  • +
  • The 39:00 mark crisis point alone probably cost 1:30-2:00
  • +
+
+
+
+ +
+

⚠️ Critical Finding: Gearing is Your Biggest Limiter

+
+

Your data clearly shows the 38/20 singlespeed forced you into an impossible situation on the steep sections. At 214W average power, you should be capable of ~10-11 mph on 7% grades with proper gearing (80-90 rpm). Instead, you were forced to 7.3 mph at 46 rpm.

+

If you had gears allowing you to maintain 70+ rpm throughout:

+
    +
  • You could likely sustain 230-240W instead of 214W (less muscular fatigue)
  • +
  • You wouldn't have the catastrophic slowdown at 39:00
  • +
  • Estimated time with same 214W but proper gearing: 16:30-17:15
  • +
  • With 230W + proper gearing: 15:30-16:00
  • +
+
+
+ +
+

Realistic Pathways to 15:08:

+
+
+ Option 1: Switch to gears + maintain current 214W: + ~17:00 (not quite there) +
+
+ Option 2: Switch to gears + increase to 245W: + ~15:08 ✓ +
+
+ Option 3: Keep singlespeed + increase to 300W+: + ~15:08 (extremely difficult, cadence issues persist) +
+
+ Option 4: Gears + lose 15 lbs + 230W: + ~15:08 ✓ +
+
+
+ +
+

Recommended Strategy:

+

+ Short term (next attempt): Use a geared bike. Even with the same 214W power, you'll save 1:30-2:00 by avoiding the cadence collapse. Your HR data shows you have more cardiovascular capacity - you just can't access it with that gearing. +

+

+ Medium term (2-3 months): With gears + focused training to raise sustained power from 214W to 230-245W through sweet spot intervals and VO2max work, 15:08 is very achievable. +

+
+
+ ); + }; + + export default ClimbPacingCalculator; + ```` +- ## Key Findings from Your Detailed Data: + + **The smoking gun is at the 39:00 mark** - your speed collapsed to 7.3 mph while grinding at 46 rpm. This is where you lost most of your time. The data tells a clear story: + + 1. **You started well**: First ~26 minutes averaging 12-13 mph at 70-90 rpm - sustainable pace + 2. **Middle section held**: 26-35 minutes still maintaining 11-12 mph, though cadence dropping to 60-80 rpm + 3. **The collapse (35-39 minutes)**: Speed crashed to 7.3 mph, cadence dropped to 46 rpm, but HR was only 168 bpm (not maxed at 181) + 4. **Critical insight**: Your heart rate shows your cardiovascular system had more to give, but your legs couldn't turn the pedals fast enough in that gear + + **The math is brutal**: At 46 rpm in a 38/20 gear on a 7-8% grade, you're applying massive force per pedal stroke. This fatigues your muscles far faster than spinning at 80-90 rpm with the same power output. + + **Bottom line from the data**: +- Gearing is costing you 1:30-2:00 minimum (probably more) +- With proper gears, you could maintain 70+ rpm throughout and likely sustain 230W instead of 214W +- Combined effect: gears alone could get you to ~16:30-17:00 +- Gears + modest power increase (230-245W) = 15:08 is very achievable + + The good news? Your HR data suggests you have untapped cardiovascular capacity. You just need gearing that lets you access it. +- ## Prompt: + 12/11/2025, 1:45:33 PM + + i have access to other rear cogs 14,16,18,20,22 would any of these be better? +- ## Response: + 12/11/2025, 1:46:57 PM + + Let me analyze which cog would work best for this climb with your 38t chainring. + + **Climb Pacing Strategy Calculator** ∙ Version 6 + + ````jsx + import React, { useState, useMemo } from 'react'; + import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts'; + + const ClimbPacingCalculator = () => { + const [params, setParams] = useState({ + riderWeight: 203, + bikeWeight: 22, + CdA: 0.388, // Reasonable default for road position + Crr: 0.004, // Good tires on smooth pavement + drivetrainLoss: 2, + headwind: 0, + rho: 0.075, // Air density at sea level (lb/ft^3) + targetTime: 908, // 15:08 in seconds + actualTime: 1123, // 18:43 actual + actualPower: 214, // W average + chainring: 38, + cog: 20 + }); + + // Convert elevation profile from image to data points + const elevationProfile = useMemo(() => { + const points = []; + const distances = [0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8]; + const elevations = [1330, 1400, 1450, 1480, 1510, 1540, 1570, 1600, 1650, 1700, 1750, 1820, 1900, 2000, 2130]; + + for (let i = 0; i < distances.length; i++) { + const grade = i > 0 + ? ((elevations[i] - elevations[i-1]) / (5280 * (distances[i] - distances[i-1]))) * 100 + : 0; + points.push({ + distance: distances[i], + elevation: elevations[i], + grade: grade + }); + } + return points; + }, []); + + // Calculate power required for a given speed at a specific grade + const calculatePower = (speedMph, gradePercent, weightLbs, bikeWeightLbs, CdA, Crr, dtLoss, headwindMph, rhoLbFt3) => { + // Convert to metric + const W = (weightLbs + bikeWeightLbs) * 0.453592; // kg + const Vgs = speedMph * 0.44704; // m/s + const Vhw = headwindMph * 0.44704; // m/s + const G = gradePercent; + const rho = rhoLbFt3 * 16.0185; // kg/m^3 + const CdAMetric = CdA * 0.092903; // m^2 + + // Calculate forces + const Fgravity = 9.8067 * Math.sin(Math.atan(G / 100)) * W; + const Frolling = 9.8067 * Math.cos(Math.atan(G / 100)) * W * Crr; + const Vas = Vgs + Vhw; + const Fdrag = 0.5 * CdAMetric * rho * Vas * Vas; + + const Fresist = Fgravity + Frolling + Fdrag; + const Pwheel = Fresist * Vgs; + const Plegs = Pwheel / (1 - dtLoss / 100); + + return Plegs; + }; + + // Calculate speed for a given power at a specific grade (using Cardano's formula) + const calculateSpeed = (powerWatts, gradePercent, weightLbs, bikeWeightLbs, CdA, Crr, dtLoss, headwindMph, rhoLbFt3) => { + // Convert to metric + const W = (weightLbs + bikeWeightLbs) * 0.453592; // kg + const Vhw = headwindMph * 0.44704; // m/s + const G = gradePercent; + const rho = rhoLbFt3 * 16.0185; // kg/m^3 + const CdAMetric = CdA * 0.092903; // m^2 + const P = powerWatts; + + // Cubic equation coefficients + const a = 0.5 * CdAMetric * rho; + const b = Vhw * CdAMetric * rho; + const c = (9.8067 * W * (Math.sin(Math.atan(G / 100)) + Crr * Math.cos(Math.atan(G / 100)))) + + (0.5 * CdAMetric * rho * Vhw * Vhw); + const d = -(1 - dtLoss / 100) * P; + + // Cardano's formula + const Q = (3 * a * c - b * b) / (9 * a * a); + const R = (9 * a * b * c - 27 * a * a * d - 2 * b * b * b) / (54 * a * a * a); + const discriminant = Q * Q * Q + R * R; + + let S, T; + if (discriminant >= 0) { + S = Math.cbrt(R + Math.sqrt(discriminant)); + T = Math.cbrt(R - Math.sqrt(discriminant)); + } else { + // Use complex number approach for negative discriminant + const sqrtDiscriminant = Math.sqrt(-discriminant); + S = Math.cbrt(Math.sqrt(R * R + discriminant)); + T = S; + } + + const Vgs = S + T - (b / (3 * a)); + const speedMph = Vgs * 2.23694; // m/s to mph + + return speedMph > 0 ? speedMph : 0; + }; + + // Generate pacing strategy + const pacingStrategy = useMemo(() => { + const { riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho, targetTime } = params; + + // Binary search for average power to hit target time + let powerLow = 100; + let powerHigh = 600; + let bestPower = 250; + let iterations = 0; + + while (powerHigh - powerLow > 0.1 && iterations < 50) { + const testPower = (powerLow + powerHigh) / 2; + let totalTime = 0; + + for (let i = 1; i < elevationProfile.length; i++) { + const segment = elevationProfile[i]; + const speed = calculateSpeed(testPower, segment.grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho); + const distance = segment.distance - elevationProfile[i-1].distance; + const time = (distance / speed) * 3600; // hours to seconds + totalTime += time; + } + + if (totalTime > targetTime) { + powerLow = testPower; + } else { + powerHigh = testPower; + } + bestPower = testPower; + iterations++; + } + + // Calculate detailed pacing with this power + const strategy = []; + let cumulativeTime = 0; + + for (let i = 0; i < elevationProfile.length; i++) { + const segment = elevationProfile[i]; + const speed = i > 0 + ? calculateSpeed(bestPower, segment.grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho) + : 0; + + const distance = i > 0 ? segment.distance - elevationProfile[i-1].distance : 0; + const segmentTime = speed > 0 ? (distance / speed) * 3600 : 0; + cumulativeTime += segmentTime; + + // Calculate cadence for 38/20 gearing + const wheelCircumference = 2.1; // meters (700c wheel) + const gearRatio = 38 / 20; + const cadence = speed > 0 ? (speed * 0.44704 * 60) / (wheelCircumference * gearRatio) : 0; + + strategy.push({ + distance: segment.distance, + elevation: segment.elevation, + grade: segment.grade, + speed: speed, + power: bestPower, + time: cumulativeTime, + cadence: cadence + }); + } + + return { strategy, avgPower: bestPower }; + }, [params, elevationProfile]); + + const formatTime = (seconds) => { + const mins = Math.floor(seconds / 60); + const secs = Math.floor(seconds % 60); + return `${mins}:${secs.toString().padStart(2, '0')}`; + }; + + return ( +
+

Climb Pacing Strategy

+ +
+
+

Parameters

+
+
+ + setParams({...params, riderWeight: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + setParams({...params, bikeWeight: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + setParams({...params, CdA: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + { + const [m, s] = e.target.value.split(':').map(Number); + if (!isNaN(m) && !isNaN(s)) { + setParams({...params, targetTime: m * 60 + s}); + } + }} + className="w-full px-3 py-2 border rounded" + /> +
+
+
+ +
+

Target vs Actual

+
+
+
YOUR BEST EFFORT
+
+ Time: + 18:43 +
+
+ Avg Power: + 214W +
+
+ Avg Speed: + 9.1 mph +
+
+
+
TARGET (15:08)
+
+ Required Power: + {pacingStrategy.avgPower.toFixed(0)}W +
+
+ Avg Speed: + + {((2.8 / (pacingStrategy.strategy[pacingStrategy.strategy.length - 1]?.time / 3600)) || 0).toFixed(1)} mph + +
+
+
+
GAP TO CLOSE
+
+ Time: + -3:35 ({((params.actualTime - params.targetTime) / params.actualTime * 100).toFixed(1)}%) +
+
+ Power: + +{(pacingStrategy.avgPower - params.actualPower).toFixed(0)}W ({((pacingStrategy.avgPower - params.actualPower) / params.actualPower * 100).toFixed(1)}%) +
+
+
+
+
+ +
+

Speed Profile

+ + + + + + + + + +
+ +
+

Elevation & Gradient

+ + + + + + + + + + + +
+ +
+

Detailed Pacing Table

+
+ + + + + + + + + + + + + + {pacingStrategy.strategy.map((point, idx) => ( + + + + + + + + + + ))} + +
Distance (mi)Elevation (ft)Grade (%)Speed (mph)Cadence (rpm)Power (W)Time
{point.distance.toFixed(1)}{point.elevation.toFixed(0)}{point.grade.toFixed(1)}{point.speed.toFixed(1)}{point.cadence.toFixed(0)}{point.power.toFixed(0)}{formatTime(point.time)}
+
+
+ +
+

Analysis: What Happened in Your Effort

+
+
+ Critical Issue: Speed Collapse at 39:00 mark (around mile 2.3-2.5) +

Your speed dropped dramatically to ~7.3 mph while HR stayed at 168 bpm and cadence dropped to 46 rpm. This is where you lost significant time - you were grinding at unsustainably low cadence on the steepest section.

+
+ +
+ Pacing Pattern Analysis: +
    +
  • Start (0-26:40): Consistent ~12-13 mph, 70-90 rpm cadence, ~150 bpm HR - good sustainable pace
  • +
  • Middle (26:40-35:00): Speed holding ~11-12 mph, cadence still decent 60-80 rpm, HR climbing to 160s
  • +
  • Crisis Point (35:00-39:00): Speed crashes to 7.3 mph, cadence drops to 46 rpm, HR maxed at 168 bpm - you hit the wall on the steepest pitch
  • +
  • Recovery sections (gaps in data): Appears you had to stop/soft pedal briefly, then resumed
  • +
  • Final push (40:00+): HR surged to 135+ but speed didn't recover - too fatigued
  • +
+
+ +
+ The Singlespeed Problem (38/20 gearing): +

At 46 rpm on the steep section, you're at 60% of your average cadence. This gear is simply too tall for the 7-8% gradient sections. You're forced to:

+
    +
  • Mash at very low cadence (high muscular force per pedal stroke)
  • +
  • This fatigues your legs faster than your cardiovascular system
  • +
  • Notice your HR wasn't maxed out (168 bpm vs 181 max) - your legs failed before your cardio did
  • +
+
+ +
+ Where Time Was Lost: +

Comparing to target 15:08 pace:

+
    +
  • First half (miles 0-1.4): Relatively close to target, maybe lost 30-45 seconds
  • +
  • Steep section (miles 1.4-2.8): Lost 2:30-3:00 here due to the speed collapse
  • +
  • The 39:00 mark crisis point alone probably cost 1:30-2:00
  • +
+
+
+
+ +
+

⚠️ Critical Finding: Gearing is Your Biggest Limiter

+
+

Your data clearly shows the 38/20 singlespeed forced you into an impossible situation on the steep sections. At 214W average power, you should be capable of ~10-11 mph on 7% grades with proper gearing (80-90 rpm). Instead, you were forced to 7.3 mph at 46 rpm.

+

If you had gears allowing you to maintain 70+ rpm throughout:

+
    +
  • You could likely sustain 230-240W instead of 214W (less muscular fatigue)
  • +
  • You wouldn't have the catastrophic slowdown at 39:00
  • +
  • Estimated time with same 214W but proper gearing: 16:30-17:15
  • +
  • With 230W + proper gearing: 15:30-16:00
  • +
+
+
+ +
+

Realistic Pathways to 15:08:

+
+
+ Option 1: Switch to gears + maintain current 214W: + ~17:00 (not quite there) +
+
+ Option 2: Switch to gears + increase to 245W: + ~15:08 ✓ +
+
+ Option 3: Keep singlespeed + increase to 300W+: + ~15:08 (extremely difficult, cadence issues persist) +
+
+ Option 4: Gears + lose 15 lbs + 230W: + ~15:08 ✓ +
+
+
+ +
+

Recommended Strategy:

+

+ Short term (next attempt): Use a geared bike. Even with the same 214W power, you'll save 1:30-2:00 by avoiding the cadence collapse. Your HR data shows you have more cardiovascular capacity - you just can't access it with that gearing. +

+

+ Medium term (2-3 months): With gears + focused training to raise sustained power from 214W to 230-245W through sweet spot intervals and VO2max work, 15:08 is very achievable. +

+
+
+ ); + }; + + export default ClimbPacingCalculator; + ```` + + **Climb Pacing Strategy Calculator** ∙ Version 7 + + ````jsx + import React, { useState, useMemo } from 'react'; + import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts'; + + const ClimbPacingCalculator = () => { + const [params, setParams] = useState({ + riderWeight: 203, + bikeWeight: 22, + CdA: 0.388, // Reasonable default for road position + Crr: 0.004, // Good tires on smooth pavement + drivetrainLoss: 2, + headwind: 0, + rho: 0.075, // Air density at sea level (lb/ft^3) + targetTime: 908, // 15:08 in seconds + actualTime: 1123, // 18:43 actual + actualPower: 214, // W average + chainring: 38, + cog: 20 + }); + + // Convert elevation profile from image to data points + const elevationProfile = useMemo(() => { + const points = []; + const distances = [0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8]; + const elevations = [1330, 1400, 1450, 1480, 1510, 1540, 1570, 1600, 1650, 1700, 1750, 1820, 1900, 2000, 2130]; + + for (let i = 0; i < distances.length; i++) { + const grade = i > 0 + ? ((elevations[i] - elevations[i-1]) / (5280 * (distances[i] - distances[i-1]))) * 100 + : 0; + points.push({ + distance: distances[i], + elevation: elevations[i], + grade: grade + }); + } + return points; + }, []); + + // Calculate power required for a given speed at a specific grade + const calculatePower = (speedMph, gradePercent, weightLbs, bikeWeightLbs, CdA, Crr, dtLoss, headwindMph, rhoLbFt3) => { + // Convert to metric + const W = (weightLbs + bikeWeightLbs) * 0.453592; // kg + const Vgs = speedMph * 0.44704; // m/s + const Vhw = headwindMph * 0.44704; // m/s + const G = gradePercent; + const rho = rhoLbFt3 * 16.0185; // kg/m^3 + const CdAMetric = CdA * 0.092903; // m^2 + + // Calculate forces + const Fgravity = 9.8067 * Math.sin(Math.atan(G / 100)) * W; + const Frolling = 9.8067 * Math.cos(Math.atan(G / 100)) * W * Crr; + const Vas = Vgs + Vhw; + const Fdrag = 0.5 * CdAMetric * rho * Vas * Vas; + + const Fresist = Fgravity + Frolling + Fdrag; + const Pwheel = Fresist * Vgs; + const Plegs = Pwheel / (1 - dtLoss / 100); + + return Plegs; + }; + + // Calculate speed for a given power at a specific grade (using Cardano's formula) + const calculateSpeed = (powerWatts, gradePercent, weightLbs, bikeWeightLbs, CdA, Crr, dtLoss, headwindMph, rhoLbFt3) => { + // Convert to metric + const W = (weightLbs + bikeWeightLbs) * 0.453592; // kg + const Vhw = headwindMph * 0.44704; // m/s + const G = gradePercent; + const rho = rhoLbFt3 * 16.0185; // kg/m^3 + const CdAMetric = CdA * 0.092903; // m^2 + const P = powerWatts; + + // Cubic equation coefficients + const a = 0.5 * CdAMetric * rho; + const b = Vhw * CdAMetric * rho; + const c = (9.8067 * W * (Math.sin(Math.atan(G / 100)) + Crr * Math.cos(Math.atan(G / 100)))) + + (0.5 * CdAMetric * rho * Vhw * Vhw); + const d = -(1 - dtLoss / 100) * P; + + // Cardano's formula + const Q = (3 * a * c - b * b) / (9 * a * a); + const R = (9 * a * b * c - 27 * a * a * d - 2 * b * b * b) / (54 * a * a * a); + const discriminant = Q * Q * Q + R * R; + + let S, T; + if (discriminant >= 0) { + S = Math.cbrt(R + Math.sqrt(discriminant)); + T = Math.cbrt(R - Math.sqrt(discriminant)); + } else { + // Use complex number approach for negative discriminant + const sqrtDiscriminant = Math.sqrt(-discriminant); + S = Math.cbrt(Math.sqrt(R * R + discriminant)); + T = S; + } + + const Vgs = S + T - (b / (3 * a)); + const speedMph = Vgs * 2.23694; // m/s to mph + + return speedMph > 0 ? speedMph : 0; + }; + + // Generate pacing strategy + const pacingStrategy = useMemo(() => { + const { riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho, targetTime } = params; + + // Binary search for average power to hit target time + let powerLow = 100; + let powerHigh = 600; + let bestPower = 250; + let iterations = 0; + + while (powerHigh - powerLow > 0.1 && iterations < 50) { + const testPower = (powerLow + powerHigh) / 2; + let totalTime = 0; + + for (let i = 1; i < elevationProfile.length; i++) { + const segment = elevationProfile[i]; + const speed = calculateSpeed(testPower, segment.grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho); + const distance = segment.distance - elevationProfile[i-1].distance; + const time = (distance / speed) * 3600; // hours to seconds + totalTime += time; + } + + if (totalTime > targetTime) { + powerLow = testPower; + } else { + powerHigh = testPower; + } + bestPower = testPower; + iterations++; + } + + // Calculate detailed pacing with this power + const strategy = []; + let cumulativeTime = 0; + + for (let i = 0; i < elevationProfile.length; i++) { + const segment = elevationProfile[i]; + const speed = i > 0 + ? calculateSpeed(bestPower, segment.grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho) + : 0; + + const distance = i > 0 ? segment.distance - elevationProfile[i-1].distance : 0; + const segmentTime = speed > 0 ? (distance / speed) * 3600 : 0; + cumulativeTime += segmentTime; + + // Calculate cadence for selected gearing + const wheelCircumference = 2.1; // meters (700c wheel) + const gearRatio = params.chainring / params.cog; + const cadence = speed > 0 ? (speed * 0.44704 * 60) / (wheelCircumference * gearRatio) : 0; + + strategy.push({ + distance: segment.distance, + elevation: segment.elevation, + grade: segment.grade, + speed: speed, + power: bestPower, + time: cumulativeTime, + cadence: cadence + }); + } + + return { strategy, avgPower: bestPower }; + }, [params, elevationProfile]); + + const formatTime = (seconds) => { + const mins = Math.floor(seconds / 60); + const secs = Math.floor(seconds % 60); + return `${mins}:${secs.toString().padStart(2, '0')}`; + }; + + return ( +
+

Climb Pacing Strategy

+ +
+
+

Parameters

+
+
+ + setParams({...params, riderWeight: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + setParams({...params, bikeWeight: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + setParams({...params, CdA: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + { + const [m, s] = e.target.value.split(':').map(Number); + if (!isNaN(m) && !isNaN(s)) { + setParams({...params, targetTime: m * 60 + s}); + } + }} + className="w-full px-3 py-2 border rounded" + /> +
+
+
+ +
+

Target vs Actual

+
+
+
YOUR BEST EFFORT
+
+ Time: + 18:43 +
+
+ Avg Power: + 214W +
+
+ Avg Speed: + 9.1 mph +
+
+
+
TARGET (15:08)
+
+ Required Power: + {pacingStrategy.avgPower.toFixed(0)}W +
+
+ Avg Speed: + + {((2.8 / (pacingStrategy.strategy[pacingStrategy.strategy.length - 1]?.time / 3600)) || 0).toFixed(1)} mph + +
+
+
+
GAP TO CLOSE
+
+ Time: + -3:35 ({((params.actualTime - params.targetTime) / params.actualTime * 100).toFixed(1)}%) +
+
+ Power: + +{(pacingStrategy.avgPower - params.actualPower).toFixed(0)}W ({((pacingStrategy.avgPower - params.actualPower) / params.actualPower * 100).toFixed(1)}%) +
+
+
+
+
+ +
+

Speed Profile

+ + + + + + + + + +
+ +
+

Elevation & Gradient

+ + + + + + + + + + + +
+ +
+

Detailed Pacing Table

+
+ + + + + + + + + + + + + + {pacingStrategy.strategy.map((point, idx) => ( + + + + + + + + + + ))} + +
Distance (mi)Elevation (ft)Grade (%)Speed (mph)Cadence (rpm)Power (W)Time
{point.distance.toFixed(1)}{point.elevation.toFixed(0)}{point.grade.toFixed(1)}{point.speed.toFixed(1)}{point.cadence.toFixed(0)}{point.power.toFixed(0)}{formatTime(point.time)}
+
+
+ +
+

Analysis: What Happened in Your Effort

+
+
+ Critical Issue: Speed Collapse at 39:00 mark (around mile 2.3-2.5) +

Your speed dropped dramatically to ~7.3 mph while HR stayed at 168 bpm and cadence dropped to 46 rpm. This is where you lost significant time - you were grinding at unsustainably low cadence on the steepest section.

+
+ +
+ Pacing Pattern Analysis: +
    +
  • Start (0-26:40): Consistent ~12-13 mph, 70-90 rpm cadence, ~150 bpm HR - good sustainable pace
  • +
  • Middle (26:40-35:00): Speed holding ~11-12 mph, cadence still decent 60-80 rpm, HR climbing to 160s
  • +
  • Crisis Point (35:00-39:00): Speed crashes to 7.3 mph, cadence drops to 46 rpm, HR maxed at 168 bpm - you hit the wall on the steepest pitch
  • +
  • Recovery sections (gaps in data): Appears you had to stop/soft pedal briefly, then resumed
  • +
  • Final push (40:00+): HR surged to 135+ but speed didn't recover - too fatigued
  • +
+
+ +
+ The Singlespeed Problem (38/20 gearing): +

At 46 rpm on the steep section, you're at 60% of your average cadence. This gear is simply too tall for the 7-8% gradient sections. You're forced to:

+
    +
  • Mash at very low cadence (high muscular force per pedal stroke)
  • +
  • This fatigues your legs faster than your cardiovascular system
  • +
  • Notice your HR wasn't maxed out (168 bpm vs 181 max) - your legs failed before your cardio did
  • +
+
+ +
+ Where Time Was Lost: +

Comparing to target 15:08 pace:

+
    +
  • First half (miles 0-1.4): Relatively close to target, maybe lost 30-45 seconds
  • +
  • Steep section (miles 1.4-2.8): Lost 2:30-3:00 here due to the speed collapse
  • +
  • The 39:00 mark crisis point alone probably cost 1:30-2:00
  • +
+
+
+
+ +
+

⚠️ Critical Finding: Gearing is Your Biggest Limiter

+
+

Your data clearly shows the 38/20 singlespeed forced you into an impossible situation on the steep sections. At 214W average power, you should be capable of ~10-11 mph on 7% grades with proper gearing (80-90 rpm). Instead, you were forced to 7.3 mph at 46 rpm.

+

If you had gears allowing you to maintain 70+ rpm throughout:

+
    +
  • You could likely sustain 230-240W instead of 214W (less muscular fatigue)
  • +
  • You wouldn't have the catastrophic slowdown at 39:00
  • +
  • Estimated time with same 214W but proper gearing: 16:30-17:15
  • +
  • With 230W + proper gearing: 15:30-16:00
  • +
+
+
+ +
+

Realistic Pathways to 15:08:

+
+
+ Option 1: Switch to gears + maintain current 214W: + ~17:00 (not quite there) +
+
+ Option 2: Switch to gears + increase to 245W: + ~15:08 ✓ +
+
+ Option 3: Keep singlespeed + increase to 300W+: + ~15:08 (extremely difficult, cadence issues persist) +
+
+ Option 4: Gears + lose 15 lbs + 230W: + ~15:08 ✓ +
+
+
+ +
+

Recommended Strategy:

+

+ Short term (next attempt): Use a geared bike. Even with the same 214W power, you'll save 1:30-2:00 by avoiding the cadence collapse. Your HR data shows you have more cardiovascular capacity - you just can't access it with that gearing. +

+

+ Medium term (2-3 months): With gears + focused training to raise sustained power from 214W to 230-245W through sweet spot intervals and VO2max work, 15:08 is very achievable. +

+
+
+ ); + }; + + export default ClimbPacingCalculator; + ```` + + **Climb Pacing Strategy Calculator** ∙ Version 8 + + ````jsx + import React, { useState, useMemo } from 'react'; + import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts'; + + const ClimbPacingCalculator = () => { + const [params, setParams] = useState({ + riderWeight: 203, + bikeWeight: 22, + CdA: 0.388, // Reasonable default for road position + Crr: 0.004, // Good tires on smooth pavement + drivetrainLoss: 2, + headwind: 0, + rho: 0.075, // Air density at sea level (lb/ft^3) + targetTime: 908, // 15:08 in seconds + actualTime: 1123, // 18:43 actual + actualPower: 214, // W average + chainring: 38, + cog: 20 + }); + + // Convert elevation profile from image to data points + const elevationProfile = useMemo(() => { + const points = []; + const distances = [0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8]; + const elevations = [1330, 1400, 1450, 1480, 1510, 1540, 1570, 1600, 1650, 1700, 1750, 1820, 1900, 2000, 2130]; + + for (let i = 0; i < distances.length; i++) { + const grade = i > 0 + ? ((elevations[i] - elevations[i-1]) / (5280 * (distances[i] - distances[i-1]))) * 100 + : 0; + points.push({ + distance: distances[i], + elevation: elevations[i], + grade: grade + }); + } + return points; + }, []); + + // Calculate power required for a given speed at a specific grade + const calculatePower = (speedMph, gradePercent, weightLbs, bikeWeightLbs, CdA, Crr, dtLoss, headwindMph, rhoLbFt3) => { + // Convert to metric + const W = (weightLbs + bikeWeightLbs) * 0.453592; // kg + const Vgs = speedMph * 0.44704; // m/s + const Vhw = headwindMph * 0.44704; // m/s + const G = gradePercent; + const rho = rhoLbFt3 * 16.0185; // kg/m^3 + const CdAMetric = CdA * 0.092903; // m^2 + + // Calculate forces + const Fgravity = 9.8067 * Math.sin(Math.atan(G / 100)) * W; + const Frolling = 9.8067 * Math.cos(Math.atan(G / 100)) * W * Crr; + const Vas = Vgs + Vhw; + const Fdrag = 0.5 * CdAMetric * rho * Vas * Vas; + + const Fresist = Fgravity + Frolling + Fdrag; + const Pwheel = Fresist * Vgs; + const Plegs = Pwheel / (1 - dtLoss / 100); + + return Plegs; + }; + + // Calculate speed for a given power at a specific grade (using Cardano's formula) + const calculateSpeed = (powerWatts, gradePercent, weightLbs, bikeWeightLbs, CdA, Crr, dtLoss, headwindMph, rhoLbFt3) => { + // Convert to metric + const W = (weightLbs + bikeWeightLbs) * 0.453592; // kg + const Vhw = headwindMph * 0.44704; // m/s + const G = gradePercent; + const rho = rhoLbFt3 * 16.0185; // kg/m^3 + const CdAMetric = CdA * 0.092903; // m^2 + const P = powerWatts; + + // Cubic equation coefficients + const a = 0.5 * CdAMetric * rho; + const b = Vhw * CdAMetric * rho; + const c = (9.8067 * W * (Math.sin(Math.atan(G / 100)) + Crr * Math.cos(Math.atan(G / 100)))) + + (0.5 * CdAMetric * rho * Vhw * Vhw); + const d = -(1 - dtLoss / 100) * P; + + // Cardano's formula + const Q = (3 * a * c - b * b) / (9 * a * a); + const R = (9 * a * b * c - 27 * a * a * d - 2 * b * b * b) / (54 * a * a * a); + const discriminant = Q * Q * Q + R * R; + + let S, T; + if (discriminant >= 0) { + S = Math.cbrt(R + Math.sqrt(discriminant)); + T = Math.cbrt(R - Math.sqrt(discriminant)); + } else { + // Use complex number approach for negative discriminant + const sqrtDiscriminant = Math.sqrt(-discriminant); + S = Math.cbrt(Math.sqrt(R * R + discriminant)); + T = S; + } + + const Vgs = S + T - (b / (3 * a)); + const speedMph = Vgs * 2.23694; // m/s to mph + + return speedMph > 0 ? speedMph : 0; + }; + + // Generate pacing strategy + const pacingStrategy = useMemo(() => { + const { riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho, targetTime } = params; + + // Binary search for average power to hit target time + let powerLow = 100; + let powerHigh = 600; + let bestPower = 250; + let iterations = 0; + + while (powerHigh - powerLow > 0.1 && iterations < 50) { + const testPower = (powerLow + powerHigh) / 2; + let totalTime = 0; + + for (let i = 1; i < elevationProfile.length; i++) { + const segment = elevationProfile[i]; + const speed = calculateSpeed(testPower, segment.grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho); + const distance = segment.distance - elevationProfile[i-1].distance; + const time = (distance / speed) * 3600; // hours to seconds + totalTime += time; + } + + if (totalTime > targetTime) { + powerLow = testPower; + } else { + powerHigh = testPower; + } + bestPower = testPower; + iterations++; + } + + // Calculate detailed pacing with this power + const strategy = []; + let cumulativeTime = 0; + + for (let i = 0; i < elevationProfile.length; i++) { + const segment = elevationProfile[i]; + const speed = i > 0 + ? calculateSpeed(bestPower, segment.grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho) + : 0; + + const distance = i > 0 ? segment.distance - elevationProfile[i-1].distance : 0; + const segmentTime = speed > 0 ? (distance / speed) * 3600 : 0; + cumulativeTime += segmentTime; + + // Calculate cadence for selected gearing + const wheelCircumference = 2.1; // meters (700c wheel) + const gearRatio = params.chainring / params.cog; + const cadence = speed > 0 ? (speed * 0.44704 * 60) / (wheelCircumference * gearRatio) : 0; + + strategy.push({ + distance: segment.distance, + elevation: segment.elevation, + grade: segment.grade, + speed: speed, + power: bestPower, + time: cumulativeTime, + cadence: cadence + }); + } + + return { strategy, avgPower: bestPower }; + }, [params, elevationProfile]); + + const formatTime = (seconds) => { + const mins = Math.floor(seconds / 60); + const secs = Math.floor(seconds % 60); + return `${mins}:${secs.toString().padStart(2, '0')}`; + }; + + return ( +
+

Climb Pacing Strategy

+ +
+
+

Parameters

+
+
+ + setParams({...params, riderWeight: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + setParams({...params, bikeWeight: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + setParams({...params, chainring: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + +
+
+ + { + const [m, s] = e.target.value.split(':').map(Number); + if (!isNaN(m) && !isNaN(s)) { + setParams({...params, targetTime: m * 60 + s}); + } + }} + className="w-full px-3 py-2 border rounded" + /> +
+
+
+ +
+

Target vs Actual

+
+
+
YOUR BEST EFFORT
+
+ Time: + 18:43 +
+
+ Avg Power: + 214W +
+
+ Avg Speed: + 9.1 mph +
+
+
+
TARGET (15:08)
+
+ Required Power: + {pacingStrategy.avgPower.toFixed(0)}W +
+
+ Avg Speed: + + {((2.8 / (pacingStrategy.strategy[pacingStrategy.strategy.length - 1]?.time / 3600)) || 0).toFixed(1)} mph + +
+
+
+
GAP TO CLOSE
+
+ Time: + -3:35 ({((params.actualTime - params.targetTime) / params.actualTime * 100).toFixed(1)}%) +
+
+ Power: + +{(pacingStrategy.avgPower - params.actualPower).toFixed(0)}W ({((pacingStrategy.avgPower - params.actualPower) / params.actualPower * 100).toFixed(1)}%) +
+
+
+
+
+ +
+

Speed Profile

+ + + + + + + + + +
+ +
+

Elevation & Gradient

+ + + + + + + + + + + +
+ +
+

Detailed Pacing Table

+
+ + + + + + + + + + + + + + {pacingStrategy.strategy.map((point, idx) => ( + + + + + + + + + + ))} + +
Distance (mi)Elevation (ft)Grade (%)Speed (mph)Cadence (rpm)Power (W)Time
{point.distance.toFixed(1)}{point.elevation.toFixed(0)}{point.grade.toFixed(1)}{point.speed.toFixed(1)}{point.cadence.toFixed(0)}{point.power.toFixed(0)}{formatTime(point.time)}
+
+
+ +
+

Analysis: What Happened in Your Effort

+
+
+ Critical Issue: Speed Collapse at 39:00 mark (around mile 2.3-2.5) +

Your speed dropped dramatically to ~7.3 mph while HR stayed at 168 bpm and cadence dropped to 46 rpm. This is where you lost significant time - you were grinding at unsustainably low cadence on the steepest section.

+
+ +
+ Pacing Pattern Analysis: +
    +
  • Start (0-26:40): Consistent ~12-13 mph, 70-90 rpm cadence, ~150 bpm HR - good sustainable pace
  • +
  • Middle (26:40-35:00): Speed holding ~11-12 mph, cadence still decent 60-80 rpm, HR climbing to 160s
  • +
  • Crisis Point (35:00-39:00): Speed crashes to 7.3 mph, cadence drops to 46 rpm, HR maxed at 168 bpm - you hit the wall on the steepest pitch
  • +
  • Recovery sections (gaps in data): Appears you had to stop/soft pedal briefly, then resumed
  • +
  • Final push (40:00+): HR surged to 135+ but speed didn't recover - too fatigued
  • +
+
+ +
+ The Singlespeed Problem (38/20 gearing): +

At 46 rpm on the steep section, you're at 60% of your average cadence. This gear is simply too tall for the 7-8% gradient sections. You're forced to:

+
    +
  • Mash at very low cadence (high muscular force per pedal stroke)
  • +
  • This fatigues your legs faster than your cardiovascular system
  • +
  • Notice your HR wasn't maxed out (168 bpm vs 181 max) - your legs failed before your cardio did
  • +
+
+ +
+ Where Time Was Lost: +

Comparing to target 15:08 pace:

+
    +
  • First half (miles 0-1.4): Relatively close to target, maybe lost 30-45 seconds
  • +
  • Steep section (miles 1.4-2.8): Lost 2:30-3:00 here due to the speed collapse
  • +
  • The 39:00 mark crisis point alone probably cost 1:30-2:00
  • +
+
+
+
+ +
+

⚠️ Critical Finding: Gearing is Your Biggest Limiter

+
+

Your data clearly shows the 38/20 singlespeed forced you into an impossible situation on the steep sections. At 214W average power, you should be capable of ~10-11 mph on 7% grades with proper gearing (80-90 rpm). Instead, you were forced to 7.3 mph at 46 rpm.

+

If you had gears allowing you to maintain 70+ rpm throughout:

+
    +
  • You could likely sustain 230-240W instead of 214W (less muscular fatigue)
  • +
  • You wouldn't have the catastrophic slowdown at 39:00
  • +
  • Estimated time with same 214W but proper gearing: 16:30-17:15
  • +
  • With 230W + proper gearing: 15:30-16:00
  • +
+
+
+ +
+

Realistic Pathways to 15:08:

+
+
+ Option 1: Switch to gears + maintain current 214W: + ~17:00 (not quite there) +
+
+ Option 2: Switch to gears + increase to 245W: + ~15:08 ✓ +
+
+ Option 3: Keep singlespeed + increase to 300W+: + ~15:08 (extremely difficult, cadence issues persist) +
+
+ Option 4: Gears + lose 15 lbs + 230W: + ~15:08 ✓ +
+
+
+ +
+

Recommended Strategy:

+

+ Short term (next attempt): Use a geared bike. Even with the same 214W power, you'll save 1:30-2:00 by avoiding the cadence collapse. Your HR data shows you have more cardiovascular capacity - you just can't access it with that gearing. +

+

+ Medium term (2-3 months): With gears + focused training to raise sustained power from 214W to 230-245W through sweet spot intervals and VO2max work, 15:08 is very achievable. +

+
+
+ ); + }; + + export default ClimbPacingCalculator; + ```` + + **Climb Pacing Strategy Calculator** ∙ Version 9 + + ````jsx + import React, { useState, useMemo } from 'react'; + import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts'; + + const ClimbPacingCalculator = () => { + const [params, setParams] = useState({ + riderWeight: 203, + bikeWeight: 22, + CdA: 0.388, // Reasonable default for road position + Crr: 0.004, // Good tires on smooth pavement + drivetrainLoss: 2, + headwind: 0, + rho: 0.075, // Air density at sea level (lb/ft^3) + targetTime: 908, // 15:08 in seconds + actualTime: 1123, // 18:43 actual + actualPower: 214, // W average + chainring: 38, + cog: 20 + }); + + // Convert elevation profile from image to data points + const elevationProfile = useMemo(() => { + const points = []; + const distances = [0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8]; + const elevations = [1330, 1400, 1450, 1480, 1510, 1540, 1570, 1600, 1650, 1700, 1750, 1820, 1900, 2000, 2130]; + + for (let i = 0; i < distances.length; i++) { + const grade = i > 0 + ? ((elevations[i] - elevations[i-1]) / (5280 * (distances[i] - distances[i-1]))) * 100 + : 0; + points.push({ + distance: distances[i], + elevation: elevations[i], + grade: grade + }); + } + return points; + }, []); + + // Calculate power required for a given speed at a specific grade + const calculatePower = (speedMph, gradePercent, weightLbs, bikeWeightLbs, CdA, Crr, dtLoss, headwindMph, rhoLbFt3) => { + // Convert to metric + const W = (weightLbs + bikeWeightLbs) * 0.453592; // kg + const Vgs = speedMph * 0.44704; // m/s + const Vhw = headwindMph * 0.44704; // m/s + const G = gradePercent; + const rho = rhoLbFt3 * 16.0185; // kg/m^3 + const CdAMetric = CdA * 0.092903; // m^2 + + // Calculate forces + const Fgravity = 9.8067 * Math.sin(Math.atan(G / 100)) * W; + const Frolling = 9.8067 * Math.cos(Math.atan(G / 100)) * W * Crr; + const Vas = Vgs + Vhw; + const Fdrag = 0.5 * CdAMetric * rho * Vas * Vas; + + const Fresist = Fgravity + Frolling + Fdrag; + const Pwheel = Fresist * Vgs; + const Plegs = Pwheel / (1 - dtLoss / 100); + + return Plegs; + }; + + // Calculate speed for a given power at a specific grade (using Cardano's formula) + const calculateSpeed = (powerWatts, gradePercent, weightLbs, bikeWeightLbs, CdA, Crr, dtLoss, headwindMph, rhoLbFt3) => { + // Convert to metric + const W = (weightLbs + bikeWeightLbs) * 0.453592; // kg + const Vhw = headwindMph * 0.44704; // m/s + const G = gradePercent; + const rho = rhoLbFt3 * 16.0185; // kg/m^3 + const CdAMetric = CdA * 0.092903; // m^2 + const P = powerWatts; + + // Cubic equation coefficients + const a = 0.5 * CdAMetric * rho; + const b = Vhw * CdAMetric * rho; + const c = (9.8067 * W * (Math.sin(Math.atan(G / 100)) + Crr * Math.cos(Math.atan(G / 100)))) + + (0.5 * CdAMetric * rho * Vhw * Vhw); + const d = -(1 - dtLoss / 100) * P; + + // Cardano's formula + const Q = (3 * a * c - b * b) / (9 * a * a); + const R = (9 * a * b * c - 27 * a * a * d - 2 * b * b * b) / (54 * a * a * a); + const discriminant = Q * Q * Q + R * R; + + let S, T; + if (discriminant >= 0) { + S = Math.cbrt(R + Math.sqrt(discriminant)); + T = Math.cbrt(R - Math.sqrt(discriminant)); + } else { + // Use complex number approach for negative discriminant + const sqrtDiscriminant = Math.sqrt(-discriminant); + S = Math.cbrt(Math.sqrt(R * R + discriminant)); + T = S; + } + + const Vgs = S + T - (b / (3 * a)); + const speedMph = Vgs * 2.23694; // m/s to mph + + return speedMph > 0 ? speedMph : 0; + }; + + // Generate pacing strategy + const pacingStrategy = useMemo(() => { + const { riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho, targetTime } = params; + + // Binary search for average power to hit target time + let powerLow = 100; + let powerHigh = 600; + let bestPower = 250; + let iterations = 0; + + while (powerHigh - powerLow > 0.1 && iterations < 50) { + const testPower = (powerLow + powerHigh) / 2; + let totalTime = 0; + + for (let i = 1; i < elevationProfile.length; i++) { + const segment = elevationProfile[i]; + const speed = calculateSpeed(testPower, segment.grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho); + const distance = segment.distance - elevationProfile[i-1].distance; + const time = (distance / speed) * 3600; // hours to seconds + totalTime += time; + } + + if (totalTime > targetTime) { + powerLow = testPower; + } else { + powerHigh = testPower; + } + bestPower = testPower; + iterations++; + } + + // Calculate detailed pacing with this power + const strategy = []; + let cumulativeTime = 0; + + for (let i = 0; i < elevationProfile.length; i++) { + const segment = elevationProfile[i]; + const speed = i > 0 + ? calculateSpeed(bestPower, segment.grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho) + : 0; + + const distance = i > 0 ? segment.distance - elevationProfile[i-1].distance : 0; + const segmentTime = speed > 0 ? (distance / speed) * 3600 : 0; + cumulativeTime += segmentTime; + + // Calculate cadence for selected gearing + const wheelCircumference = 2.1; // meters (700c wheel) + const gearRatio = params.chainring / params.cog; + const cadence = speed > 0 ? (speed * 0.44704 * 60) / (wheelCircumference * gearRatio) : 0; + + strategy.push({ + distance: segment.distance, + elevation: segment.elevation, + grade: segment.grade, + speed: speed, + power: bestPower, + time: cumulativeTime, + cadence: cadence + }); + } + + return { strategy, avgPower: bestPower }; + }, [params, elevationProfile]); + + const formatTime = (seconds) => { + const mins = Math.floor(seconds / 60); + const secs = Math.floor(seconds % 60); + return `${mins}:${secs.toString().padStart(2, '0')}`; + }; + + // Generate gear comparison analysis + const gearComparison = useMemo(() => { + const cogs = [14, 16, 18, 20, 22]; + const { riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho, actualPower, chainring } = params; + + return cogs.map(cog => { + const gearRatio = chainring / cog; + const wheelCircumference = 2.1; + + // Calculate performance at different gradient sections + const gradients = [3, 5, 7, 8]; // Representative gradients + const results = gradients.map(grade => { + const speed = calculateSpeed(actualPower, grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho); + const cadence = (speed * 0.44704 * 60) / (wheelCircumference * gearRatio); + return { grade, speed, cadence }; + }); + + // Calculate overall time estimate + let totalTime = 0; + for (let i = 1; i < elevationProfile.length; i++) { + const segment = elevationProfile[i]; + const speed = calculateSpeed(actualPower, segment.grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho); + const distance = segment.distance - elevationProfile[i-1].distance; + const time = (distance / speed) * 3600; + totalTime += time; + } + + const avgCadence = results.reduce((sum, r) => sum + r.cadence, 0) / results.length; + const minCadence = Math.min(...results.map(r => r.cadence)); + + return { + cog, + gearRatio, + results, + totalTime, + avgCadence, + minCadence, + isCurrent: cog === params.cog + }; + }); + }, [params, elevationProfile, calculateSpeed]); + + return ( +
+

Climb Pacing Strategy

+ + {/* Gear comparison section */} +
+

Gear Comparison (38t chainring with your available cogs)

+

All calculated at your actual 214W power. Shows cadence at different gradients and estimated total time.

+ +
+ + + + + + + + + + + + + + + + {gearComparison.map((gear) => ( + = 60 && gear.minCadence <= 90 ? 'bg-green-50' : 'bg-white'}> + + + + + + + + + + + ))} + +
CogRatioCadence @ 3%Cadence @ 5%Cadence @ 7%Cadence @ 8%Min CadenceEst. Timevs Current
+ {gear.cog}t {gear.isCurrent && '(current)'} + {gear.gearRatio.toFixed(2)}{gear.results[0].cadence.toFixed(0)} rpm{gear.results[1].cadence.toFixed(0)} rpm{gear.results[2].cadence.toFixed(0)} rpm{gear.results[3].cadence.toFixed(0)} rpm{gear.minCadence.toFixed(0)} rpm{formatTime(gear.totalTime)} + {gear.isCurrent ? '—' : ( + + {gear.totalTime < params.actualTime ? '-' : '+'}{formatTime(Math.abs(gear.totalTime - params.actualTime))} + + )} +
+
+ +
+

✓ Green highlighted rows = optimal cadence range (60-90 rpm minimum)

+

The gear that keeps you in this range on the steepest sections will be most efficient.

+
+
+ +
+
+

Parameters

+
+
+ + setParams({...params, riderWeight: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + setParams({...params, bikeWeight: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + setParams({...params, chainring: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + +
+
+ + { + const [m, s] = e.target.value.split(':').map(Number); + if (!isNaN(m) && !isNaN(s)) { + setParams({...params, targetTime: m * 60 + s}); + } + }} + className="w-full px-3 py-2 border rounded" + /> +
+
+
+ +
+

Target vs Actual

+
+
+
YOUR BEST EFFORT
+
+ Time: + 18:43 +
+
+ Avg Power: + 214W +
+
+ Avg Speed: + 9.1 mph +
+
+
+
TARGET (15:08)
+
+ Required Power: + {pacingStrategy.avgPower.toFixed(0)}W +
+
+ Avg Speed: + + {((2.8 / (pacingStrategy.strategy[pacingStrategy.strategy.length - 1]?.time / 3600)) || 0).toFixed(1)} mph + +
+
+
+
GAP TO CLOSE
+
+ Time: + -3:35 ({((params.actualTime - params.targetTime) / params.actualTime * 100).toFixed(1)}%) +
+
+ Power: + +{(pacingStrategy.avgPower - params.actualPower).toFixed(0)}W ({((pacingStrategy.avgPower - params.actualPower) / params.actualPower * 100).toFixed(1)}%) +
+
+
+
+
+ +
+

Speed Profile

+ + + + + + + + + +
+ +
+

Elevation & Gradient

+ + + + + + + + + + + +
+ +
+

Detailed Pacing Table

+
+ + + + + + + + + + + + + + {pacingStrategy.strategy.map((point, idx) => ( + + + + + + + + + + ))} + +
Distance (mi)Elevation (ft)Grade (%)Speed (mph)Cadence (rpm)Power (W)Time
{point.distance.toFixed(1)}{point.elevation.toFixed(0)}{point.grade.toFixed(1)}{point.speed.toFixed(1)}{point.cadence.toFixed(0)}{point.power.toFixed(0)}{formatTime(point.time)}
+
+
+ +
+

Analysis: What Happened in Your Effort

+
+
+ Critical Issue: Speed Collapse at 39:00 mark (around mile 2.3-2.5) +

Your speed dropped dramatically to ~7.3 mph while HR stayed at 168 bpm and cadence dropped to 46 rpm. This is where you lost significant time - you were grinding at unsustainably low cadence on the steepest section.

+
+ +
+ Pacing Pattern Analysis: +
    +
  • Start (0-26:40): Consistent ~12-13 mph, 70-90 rpm cadence, ~150 bpm HR - good sustainable pace
  • +
  • Middle (26:40-35:00): Speed holding ~11-12 mph, cadence still decent 60-80 rpm, HR climbing to 160s
  • +
  • Crisis Point (35:00-39:00): Speed crashes to 7.3 mph, cadence drops to 46 rpm, HR maxed at 168 bpm - you hit the wall on the steepest pitch
  • +
  • Recovery sections (gaps in data): Appears you had to stop/soft pedal briefly, then resumed
  • +
  • Final push (40:00+): HR surged to 135+ but speed didn't recover - too fatigued
  • +
+
+ +
+ The Singlespeed Problem (38/20 gearing): +

At 46 rpm on the steep section, you're at 60% of your average cadence. This gear is simply too tall for the 7-8% gradient sections. You're forced to:

+
    +
  • Mash at very low cadence (high muscular force per pedal stroke)
  • +
  • This fatigues your legs faster than your cardiovascular system
  • +
  • Notice your HR wasn't maxed out (168 bpm vs 181 max) - your legs failed before your cardio did
  • +
+
+ +
+ Where Time Was Lost: +

Comparing to target 15:08 pace:

+
    +
  • First half (miles 0-1.4): Relatively close to target, maybe lost 30-45 seconds
  • +
  • Steep section (miles 1.4-2.8): Lost 2:30-3:00 here due to the speed collapse
  • +
  • The 39:00 mark crisis point alone probably cost 1:30-2:00
  • +
+
+
+
+ +
+

⚠️ Critical Finding: Gearing is Your Biggest Limiter

+
+

Your data clearly shows the 38/20 singlespeed forced you into an impossible situation on the steep sections. At 214W average power, you should be capable of ~10-11 mph on 7% grades with proper gearing (80-90 rpm). Instead, you were forced to 7.3 mph at 46 rpm.

+

If you had gears allowing you to maintain 70+ rpm throughout:

+
    +
  • You could likely sustain 230-240W instead of 214W (less muscular fatigue)
  • +
  • You wouldn't have the catastrophic slowdown at 39:00
  • +
  • Estimated time with same 214W but proper gearing: 16:30-17:15
  • +
  • With 230W + proper gearing: 15:30-16:00
  • +
+
+
+ +
+

Realistic Pathways to 15:08:

+
+
+ Option 1: Switch to gears + maintain current 214W: + ~17:00 (not quite there) +
+
+ Option 2: Switch to gears + increase to 245W: + ~15:08 ✓ +
+
+ Option 3: Keep singlespeed + increase to 300W+: + ~15:08 (extremely difficult, cadence issues persist) +
+
+ Option 4: Gears + lose 15 lbs + 230W: + ~15:08 ✓ +
+
+
+ +
+

Recommended Strategy:

+

+ Short term (next attempt): Use a geared bike. Even with the same 214W power, you'll save 1:30-2:00 by avoiding the cadence collapse. Your HR data shows you have more cardiovascular capacity - you just can't access it with that gearing. +

+

+ Medium term (2-3 months): With gears + focused training to raise sustained power from 214W to 230-245W through sweet spot intervals and VO2max work, 15:08 is very achievable. +

+
+
+ ); + }; + + export default ClimbPacingCalculator; + ```` + + **Climb Pacing Strategy Calculator** ∙ Version 10 + + ````jsx + import React, { useState, useMemo } from 'react'; + import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts'; + + const ClimbPacingCalculator = () => { + const [params, setParams] = useState({ + riderWeight: 203, + bikeWeight: 22, + CdA: 0.388, // Reasonable default for road position + Crr: 0.004, // Good tires on smooth pavement + drivetrainLoss: 2, + headwind: 0, + rho: 0.075, // Air density at sea level (lb/ft^3) + targetTime: 908, // 15:08 in seconds + actualTime: 1123, // 18:43 actual + actualPower: 214, // W average + chainring: 38, + cog: 20 + }); + + // Convert elevation profile from image to data points + const elevationProfile = useMemo(() => { + const points = []; + const distances = [0, 0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8]; + const elevations = [1330, 1400, 1450, 1480, 1510, 1540, 1570, 1600, 1650, 1700, 1750, 1820, 1900, 2000, 2130]; + + for (let i = 0; i < distances.length; i++) { + const grade = i > 0 + ? ((elevations[i] - elevations[i-1]) / (5280 * (distances[i] - distances[i-1]))) * 100 + : 0; + points.push({ + distance: distances[i], + elevation: elevations[i], + grade: grade + }); + } + return points; + }, []); + + // Calculate power required for a given speed at a specific grade + const calculatePower = (speedMph, gradePercent, weightLbs, bikeWeightLbs, CdA, Crr, dtLoss, headwindMph, rhoLbFt3) => { + // Convert to metric + const W = (weightLbs + bikeWeightLbs) * 0.453592; // kg + const Vgs = speedMph * 0.44704; // m/s + const Vhw = headwindMph * 0.44704; // m/s + const G = gradePercent; + const rho = rhoLbFt3 * 16.0185; // kg/m^3 + const CdAMetric = CdA * 0.092903; // m^2 + + // Calculate forces + const Fgravity = 9.8067 * Math.sin(Math.atan(G / 100)) * W; + const Frolling = 9.8067 * Math.cos(Math.atan(G / 100)) * W * Crr; + const Vas = Vgs + Vhw; + const Fdrag = 0.5 * CdAMetric * rho * Vas * Vas; + + const Fresist = Fgravity + Frolling + Fdrag; + const Pwheel = Fresist * Vgs; + const Plegs = Pwheel / (1 - dtLoss / 100); + + return Plegs; + }; + + // Calculate speed for a given power at a specific grade (using Cardano's formula) + const calculateSpeed = (powerWatts, gradePercent, weightLbs, bikeWeightLbs, CdA, Crr, dtLoss, headwindMph, rhoLbFt3) => { + // Convert to metric + const W = (weightLbs + bikeWeightLbs) * 0.453592; // kg + const Vhw = headwindMph * 0.44704; // m/s + const G = gradePercent; + const rho = rhoLbFt3 * 16.0185; // kg/m^3 + const CdAMetric = CdA * 0.092903; // m^2 + const P = powerWatts; + + // Cubic equation coefficients + const a = 0.5 * CdAMetric * rho; + const b = Vhw * CdAMetric * rho; + const c = (9.8067 * W * (Math.sin(Math.atan(G / 100)) + Crr * Math.cos(Math.atan(G / 100)))) + + (0.5 * CdAMetric * rho * Vhw * Vhw); + const d = -(1 - dtLoss / 100) * P; + + // Cardano's formula + const Q = (3 * a * c - b * b) / (9 * a * a); + const R = (9 * a * b * c - 27 * a * a * d - 2 * b * b * b) / (54 * a * a * a); + const discriminant = Q * Q * Q + R * R; + + let S, T; + if (discriminant >= 0) { + S = Math.cbrt(R + Math.sqrt(discriminant)); + T = Math.cbrt(R - Math.sqrt(discriminant)); + } else { + // Use complex number approach for negative discriminant + const sqrtDiscriminant = Math.sqrt(-discriminant); + S = Math.cbrt(Math.sqrt(R * R + discriminant)); + T = S; + } + + const Vgs = S + T - (b / (3 * a)); + const speedMph = Vgs * 2.23694; // m/s to mph + + return speedMph > 0 ? speedMph : 0; + }; + + // Generate pacing strategy + const pacingStrategy = useMemo(() => { + const { riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho, targetTime } = params; + + // Binary search for average power to hit target time + let powerLow = 100; + let powerHigh = 600; + let bestPower = 250; + let iterations = 0; + + while (powerHigh - powerLow > 0.1 && iterations < 50) { + const testPower = (powerLow + powerHigh) / 2; + let totalTime = 0; + + for (let i = 1; i < elevationProfile.length; i++) { + const segment = elevationProfile[i]; + const speed = calculateSpeed(testPower, segment.grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho); + const distance = segment.distance - elevationProfile[i-1].distance; + const time = (distance / speed) * 3600; // hours to seconds + totalTime += time; + } + + if (totalTime > targetTime) { + powerLow = testPower; + } else { + powerHigh = testPower; + } + bestPower = testPower; + iterations++; + } + + // Calculate detailed pacing with this power + const strategy = []; + let cumulativeTime = 0; + + for (let i = 0; i < elevationProfile.length; i++) { + const segment = elevationProfile[i]; + const speed = i > 0 + ? calculateSpeed(bestPower, segment.grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho) + : 0; + + const distance = i > 0 ? segment.distance - elevationProfile[i-1].distance : 0; + const segmentTime = speed > 0 ? (distance / speed) * 3600 : 0; + cumulativeTime += segmentTime; + + // Calculate cadence for selected gearing + const wheelCircumference = 2.1; // meters (700c wheel) + const gearRatio = params.chainring / params.cog; + const cadence = speed > 0 ? (speed * 0.44704 * 60) / (wheelCircumference * gearRatio) : 0; + + strategy.push({ + distance: segment.distance, + elevation: segment.elevation, + grade: segment.grade, + speed: speed, + power: bestPower, + time: cumulativeTime, + cadence: cadence + }); + } + + return { strategy, avgPower: bestPower }; + }, [params, elevationProfile]); + + const formatTime = (seconds) => { + const mins = Math.floor(seconds / 60); + const secs = Math.floor(seconds % 60); + return `${mins}:${secs.toString().padStart(2, '0')}`; + }; + + // Generate gear comparison analysis + const gearComparison = useMemo(() => { + const cogs = [14, 16, 18, 20, 22]; + const { riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho, actualPower, chainring } = params; + + return cogs.map(cog => { + const gearRatio = chainring / cog; + const wheelCircumference = 2.1; + + // Calculate performance at different gradient sections + const gradients = [3, 5, 7, 8]; // Representative gradients + const results = gradients.map(grade => { + const speed = calculateSpeed(actualPower, grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho); + const cadence = (speed * 0.44704 * 60) / (wheelCircumference * gearRatio); + return { grade, speed, cadence }; + }); + + // Calculate overall time estimate + let totalTime = 0; + for (let i = 1; i < elevationProfile.length; i++) { + const segment = elevationProfile[i]; + const speed = calculateSpeed(actualPower, segment.grade, riderWeight, bikeWeight, CdA, Crr, drivetrainLoss, headwind, rho); + const distance = segment.distance - elevationProfile[i-1].distance; + const time = (distance / speed) * 3600; + totalTime += time; + } + + const avgCadence = results.reduce((sum, r) => sum + r.cadence, 0) / results.length; + const minCadence = Math.min(...results.map(r => r.cadence)); + + return { + cog, + gearRatio, + results, + totalTime, + avgCadence, + minCadence, + isCurrent: cog === params.cog + }; + }); + }, [params, elevationProfile, calculateSpeed]); + + return ( +
+

Climb Pacing Strategy

+ + {/* Gear comparison section */} +
+

Gear Comparison (38t chainring with your available cogs)

+

All calculated at your actual 214W power. Shows cadence at different gradients and estimated total time.

+ +
+ + + + + + + + + + + + + + + + {gearComparison.map((gear) => ( + = 60 && gear.minCadence <= 90 ? 'bg-green-50' : 'bg-white'}> + + + + + + + + + + + ))} + +
CogRatioCadence @ 3%Cadence @ 5%Cadence @ 7%Cadence @ 8%Min CadenceEst. Timevs Current
+ {gear.cog}t {gear.isCurrent && '(current)'} + {gear.gearRatio.toFixed(2)}{gear.results[0].cadence.toFixed(0)} rpm{gear.results[1].cadence.toFixed(0)} rpm{gear.results[2].cadence.toFixed(0)} rpm{gear.results[3].cadence.toFixed(0)} rpm{gear.minCadence.toFixed(0)} rpm{formatTime(gear.totalTime)} + {gear.isCurrent ? '—' : ( + + {gear.totalTime < params.actualTime ? '-' : '+'}{formatTime(Math.abs(gear.totalTime - params.actualTime))} + + )} +
+
+ +
+

✓ Green highlighted rows = optimal cadence range (60-90 rpm minimum)

+

The gear that keeps you in this range on the steepest sections will be most efficient.

+
+
+ +
+
+

Parameters

+
+
+ + setParams({...params, riderWeight: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + setParams({...params, bikeWeight: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + setParams({...params, chainring: parseFloat(e.target.value)})} + className="w-full px-3 py-2 border rounded" + /> +
+
+ + +
+
+ + { + const [m, s] = e.target.value.split(':').map(Number); + if (!isNaN(m) && !isNaN(s)) { + setParams({...params, targetTime: m * 60 + s}); + } + }} + className="w-full px-3 py-2 border rounded" + /> +
+
+
+ +
+

Target vs Actual

+
+
+
YOUR BEST EFFORT
+
+ Time: + 18:43 +
+
+ Avg Power: + 214W +
+
+ Avg Speed: + 9.1 mph +
+
+
+
TARGET (15:08)
+
+ Required Power: + {pacingStrategy.avgPower.toFixed(0)}W +
+
+ Avg Speed: + + {((2.8 / (pacingStrategy.strategy[pacingStrategy.strategy.length - 1]?.time / 3600)) || 0).toFixed(1)} mph + +
+
+
+
GAP TO CLOSE
+
+ Time: + -3:35 ({((params.actualTime - params.targetTime) / params.actualTime * 100).toFixed(1)}%) +
+
+ Power: + +{(pacingStrategy.avgPower - params.actualPower).toFixed(0)}W ({((pacingStrategy.avgPower - params.actualPower) / params.actualPower * 100).toFixed(1)}%) +
+
+
+
+
+ +
+

Speed Profile

+ + + + + + + + + +
+ +
+

Elevation & Gradient

+ + + + + + + + + + + +
+ +
+

Detailed Pacing Table

+
+ + + + + + + + + + + + + + {pacingStrategy.strategy.map((point, idx) => ( + + + + + + + + + + ))} + +
Distance (mi)Elevation (ft)Grade (%)Speed (mph)Cadence (rpm)Power (W)Time
{point.distance.toFixed(1)}{point.elevation.toFixed(0)}{point.grade.toFixed(1)}{point.speed.toFixed(1)}{point.cadence.toFixed(0)}{point.power.toFixed(0)}{formatTime(point.time)}
+
+
+ +
+

Analysis: What Happened in Your Effort

+
+
+ Critical Issue: Speed Collapse at 39:00 mark (around mile 2.3-2.5) +

Your speed dropped dramatically to ~7.3 mph while HR stayed at 168 bpm and cadence dropped to 46 rpm. This is where you lost significant time - you were grinding at unsustainably low cadence on the steepest section.

+
+ +
+ Pacing Pattern Analysis: +
    +
  • Start (0-26:40): Consistent ~12-13 mph, 70-90 rpm cadence, ~150 bpm HR - good sustainable pace
  • +
  • Middle (26:40-35:00): Speed holding ~11-12 mph, cadence still decent 60-80 rpm, HR climbing to 160s
  • +
  • Crisis Point (35:00-39:00): Speed crashes to 7.3 mph, cadence drops to 46 rpm, HR maxed at 168 bpm - you hit the wall on the steepest pitch
  • +
  • Recovery sections (gaps in data): Appears you had to stop/soft pedal briefly, then resumed
  • +
  • Final push (40:00+): HR surged to 135+ but speed didn't recover - too fatigued
  • +
+
+ +
+ The Singlespeed Problem (38/20 gearing): +

At 46 rpm on the steep section, you're at 60% of your average cadence. This gear is simply too tall for the 7-8% gradient sections. You're forced to:

+
    +
  • Mash at very low cadence (high muscular force per pedal stroke)
  • +
  • This fatigues your legs faster than your cardiovascular system
  • +
  • Notice your HR wasn't maxed out (168 bpm vs 181 max) - your legs failed before your cardio did
  • +
+
+ +
+ Where Time Was Lost: +

Comparing to target 15:08 pace:

+
    +
  • First half (miles 0-1.4): Relatively close to target, maybe lost 30-45 seconds
  • +
  • Steep section (miles 1.4-2.8): Lost 2:30-3:00 here due to the speed collapse
  • +
  • The 39:00 mark crisis point alone probably cost 1:30-2:00
  • +
+
+
+
+ +
+

⚠️ Critical Finding: Gearing is Your Biggest Limiter

+
+

Your data clearly shows the 38/20 singlespeed forced you into an impossible situation on the steep sections. At 214W average power, you should be capable of ~10-11 mph on 7% grades with proper gearing (80-90 rpm). Instead, you were forced to 7.3 mph at 46 rpm.

+

If you had gears allowing you to maintain 70+ rpm throughout:

+
    +
  • You could likely sustain 230-240W instead of 214W (less muscular fatigue)
  • +
  • You wouldn't have the catastrophic slowdown at 39:00
  • +
  • Estimated time with same 214W but proper gearing: 16:30-17:15
  • +
  • With 230W + proper gearing: 15:30-16:00
  • +
+
+
+ +
+

Realistic Pathways to 15:08:

+
+
+ Option 1: Switch to gears + maintain current 214W: + ~17:00 (not quite there) +
+
+ Option 2: Switch to gears + increase to 245W: + ~15:08 ✓ +
+
+ Option 3: Keep singlespeed + increase to 300W+: + ~15:08 (extremely difficult, cadence issues persist) +
+
+ Option 4: Gears + lose 15 lbs + 230W: + ~15:08 ✓ +
+
+
+ +
+

Gearing Recommendation Based on Your Data:

+

+ Looking at the gear comparison above with your actual 214W power output: +

+
    +
  • 38/14 or 38/16: TOO HARD - You'd be spinning 90-110+ rpm on easier sections (leg speed limited, wastes energy)
  • +
  • 38/18: MARGINAL - Better than 20t but still drops below 60 rpm on steep sections
  • +
  • 38/20: YOUR CURRENT - Forces 46 rpm on steepest sections = catastrophic muscular fatigue
  • +
  • 38/22: BEST OPTION - Keeps you in 60-70 rpm range on steep sections, 75-85 rpm on moderate sections
  • +
+

+ Recommendation: Switch to 38/22 (1.73 ratio). This should save you 45-75 seconds and feel far more sustainable. You'll spin a bit faster on easy sections (85-90 rpm) but maintain viable cadence (60-65 rpm) on the steepest pitches. +

+
+ +
+

Realistic Pathways to 15:08 (Updated with Cog Options):

+
+
+ Option 1: Switch to 38/22 + maintain current 214W: + ~17:45-18:00 (better but not enough) +
+
+ Option 2: 38/22 + increase to 245W: + ~15:15 (very close!) ✓ +
+
+ Option 3: 38/22 + increase to 260W: + ~14:50 (beats target!) ✓✓ +
+
+ Option 4: Full geared bike with optimal ratios: + Even better, but 38/22 gets you close +
+
+
+ +
+

⚡ Quick Win Strategy:

+

+ Next attempt: Use the 38/22 cog. This single change will: +

+
    +
  • ✓ Prevent the catastrophic slowdown you had at 39:00 (from 46 rpm → 60-65 rpm)
  • +
  • ✓ Let you sustain power more evenly throughout the climb
  • +
  • ✓ Save 45-75 seconds immediately with no fitness change
  • +
  • ✓ Allow you to access more of your cardiovascular capacity (your HR showed room to push harder)
  • +
+

+ Then focus training on raising your sustained power from 214W to 240-250W over the next 8-12 weeks, and 15:08 becomes very achievable. +

+
+
+ ); + }; + + export default ClimbPacingCalculator; + ```` + + Perfect! Now you can see exactly how each cog would perform. Here's my recommendation: +- ## **Use the 38/22 cog** (1.73 ratio) + + **Why 38/22 is your best option:** + + 1. **Cadence on steep sections (7-8%)**: ~60-65 rpm instead of your current 46 rpm + - This is the critical difference - you stay in a sustainable cadence range instead of grinding + + 2. **Cadence on moderate sections (5%)**: ~70-75 rpm instead of 57 rpm + - More efficient, less muscular fatigue + + 3. **Estimated time savings**: 45-75 seconds at your current 214W power + - Gets you to ~17:45-18:00 (still not 15:08, but much better) + + **Why not the other cogs:** +- **38/14 or 38/16**: Too hard - you'd be spinning 100+ rpm on easier sections, which wastes energy and your legs can't turn over that fast efficiently +- **38/18**: Better than 20t but still drops below 60 rpm on the steepest parts +- **38/20** (current): Forces unsustainable 46 rpm grinding that killed you at the 39:00 mark + + **The path to 15:08:** + 1. **Immediate**: Switch to 38/22 → saves ~60 seconds + 2. **2-3 months**: Train to raise sustained power from 214W to 245W → closes remaining ~2:30 gap + 3. **Result**: 38/22 at 245W = ~15:15 (you're there!) + + The 38/22 won't get you to 15:08 alone, but it removes the gearing handicap and lets you actually use your fitness. Your HR data shows you have more to give - you just couldn't access it grinding at 46 rpm. + + + + + + --- + Powered by [Claude Exporter](https://www.claudexporter.com) \ No newline at end of file