Speedrun Split Time & Pace Calculator

ANALife Services AuthorityNational Calculator Authority›Speedrun Split Time & Pace Calculator

.calc-container { max-width: 640px; margin: 2rem 0; padding: 1.5rem; background: #fff; border: 1px solid #ddd; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.06); font-family: system-ui, -apple-system, sans-serif; } .calc-container h3 { font-family: Georgia, serif; font-size: 1.15rem; color: #1a1a1a; margin-bottom: 1rem; padding-bottom: 0.5rem; border-bottom: 2px solid var(--ac, #3d5a80); } .calc-row { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 0.75rem; flex-wrap: wrap; } .calc-row label { min-width: 160px; font-size: 0.9rem; color: #333; font-weight: 500; } .calc-row input[type="number"], .calc-row select { flex: 1; min-width: 120px; max-width: 200px; padding: 0.5rem 0.6rem; border: 1px solid #ccc; border-radius: 4px; font-size: 0.9rem; font-family: system-ui, sans-serif; color: #1a1a1a; background: #fafaf8; } .calc-row input:focus, .calc-row select:focus { outline: none; border-color: var(--ac, #3d5a80); box-shadow: 0 0 0 2px rgba(26,74,138,0.12); } .calc-row .unit { font-size: 0.82rem; color: #888; min-width: 30px; } .calc-btn { display: inline-block; margin-top: 0.5rem; padding: 0.55rem 1.5rem; background: var(--ac, #3d5a80); color: #fff; border: none; border-radius: 4px; font-size: 0.9rem; font-weight: 600; cursor: pointer; font-family: system-ui, sans-serif; } .calc-btn:hover { opacity: 0.9; } .calc-result { margin-top: 1.25rem; padding: 1rem 1.25rem; background: #f0f6fc; border-left: 3px solid var(--ac, #3d5a80); border-radius: 0 6px 6px 0; display: none; } .calc-result.visible { display: block; } .calc-result-label { font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.06em; color: #666; margin-bottom: 0.25rem; } .calc-result-value { font-size: 1.6rem; font-weight: 700; color: var(--ac, #3d5a80); } .calc-result-detail { font-size: 0.85rem; color: #555; margin-top: 0.5rem; line-height: 1.5; } .calc-note { margin-top: 1rem; font-size: 0.8rem; color: #888; font-style: italic; } .calc-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; margin-top: 0.75rem; } .calc-grid-item { padding: 0.6rem 0.8rem; background: #f8f9fa; border-radius: 4px; border: 1px solid #eee; } .calc-grid-item .label { font-size: 0.75rem; color: #888; text-transform: uppercase; letter-spacing: 0.04em; } .calc-grid-item .value { font-size: 1.1rem; font-weight: 600; color: #1a1a1a; } @media (max-width: 720px) { .calc-row { flex-direction: column; align-items: flex-start; gap: 0.3rem; } .calc-row label { min-width: auto; } .calc-row input[type="number"], .calc-row select { max-width: 100%; width: 100%; } .calc-grid { grid-template-columns: 1fr; } } .calc-chart { margin: 1rem 0; text-align: center; } .calc-chart svg { max-width: 100%; height: auto; } .calc-chart-legend { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.6rem 1.2rem; margin-top: 0.6rem; font-size: 0.8rem; color: #555; } .calc-chart-legend span { display: inline-flex; align-items: center; gap: 0.3rem; } .calc-chart-legend i { display: inline-block; width: 10px; height: 10px; border-radius: 2px; font-style: normal; } .calc-related { max-width: 640px; margin: 2rem 0 1rem; padding: 1.25rem 1.5rem; background: #f8f9fa; border: 1px solid #e8e8e8; border-radius: 8px; } .calc-related h3 { font-family: Georgia, serif; font-size: 1rem; color: #1a1a1a; margin: 0 0 0.75rem; padding-bottom: 0.4rem; border-bottom: 2px solid var(--ac, #3d5a80); } .calc-related-list { list-style: none; padding: 0; margin: 0 0 0.75rem; display: grid; grid-template-columns: 1fr 1fr; gap: 0.4rem 1.5rem; } .calc-related-list li a { font-size: 0.88rem; color: var(--ac, #3d5a80); text-decoration: none; } .calc-related-list li a:hover { text-decoration: underline; } .calc-browse-all { margin: 0.5rem 0 0; font-size: 0.9rem; font-weight: 600; } .calc-browse-all a { color: var(--ac, #3d5a80); text-decoration: none; } .calc-browse-all a:hover { text-decoration: underline; } @media (max-width: 720px) { .calc-related-list { grid-template-columns: 1fr; } }

Speedrun Split Time & Pace Calculator

Calculate split times, segment pace, time saves, and projected finish time for speedruns.

Total Number of Segments/Splits

Personal Best (PB) Total Time (HH:MM:SS)

Number of Splits Completed So Far

Elapsed Time at Last Split (HH:MM:SS)

Calculate Fill in your split data and click Calculate.

// Parse HH:MM:SS or MM:SS or SS into total seconds function speParseTime(str) { if (!str || str.trim() === "") return null; str = str.trim(); const parts = str.split(":").map(p => parseFloat(p)); if (parts.some(isNaN)) return null; if (parts.length === 3) return parts[0]3600 + parts[1]60 + parts[2]; if (parts.length === 2) return parts[0]*60 + parts[1]; if (parts.length === 1) return parts[0]; return null; }

// Format seconds to HH:MM:SS.mmm function speFormatTime(totalSeconds, showMs=false) { if (totalSeconds === null || isNaN(totalSeconds)) return "N/A"; const sign = totalSeconds 0 ? h + ":" : ""; const mStr = h > 0 ? String(m).padStart(2,"0") + ":" : (m > 0 ? m + ":" : ""); const sStr = (h > 0 || m > 0) ? String(sInt).padStart(2,"0") : String(sInt); if (showMs && ms > 0) return sign + hStr + mStr + sStr + "." + String(ms).padStart(3,"0"); return sign + hStr + mStr + sStr; }

function speFormatDiff(diff) { if (diff === null || isNaN(diff)) return "N/A"; const sign = diff { const idx = row.dataset.idx; existing[idx] = { name: row.querySelector(".spe-split-name").value, pb: row.querySelector(".spe-split-pb").value, best: row.querySelector(".spe-split-best").value, current: row.querySelector(".spe-split-current").value }; }); container.innerHTML = ""; const defaultNames = ["Intro","Early Game","Mid Game","Late Game","Final Boss","Segment 6","Segment 7","Segment 8","Segment 9","Segment 10"]; const defaultPBs = ["0:05:30","0:18:20","0:22:15","0:19:40","0:18:00","0:10:00","0:10:00","0:10:00","0:10:00","0:10:00"]; const defaultBests = ["0:05:10","0:17:50","0:21:40","0:19:00","0:17:20","0:09:30","0:09:30","0:09:30","0:09:30","0:09:30"]; const defaultCurrent = ["0:05:20","0:22:50","","","","","","","",""]; for (let i = 0; i Split \${i+1}

Segment Name

PB Split Time

Best Possible

Current Run Split

`; container.appendChild(div); } }

function speCalc() { const resultDiv = document.getElementById("spe_result"); const n = parseInt(document.getElementById("spe_total_segments").value); const pbTotalStr = document.getElementById("spe_pb_total").value; const completedStr = document.getElementById("spe_completed_splits").value; const elapsedStr = document.getElementById("spe_elapsed_time").value;

// Validation if (!n || n 50) { resultDiv.innerHTML = 'Please enter a valid number of segments (1–50).'; return; } const pbTotal = speParseTime(pbTotalStr); if (pbTotal === null || pbTotal Please enter a valid PB total time (e.g. 1:23:45).'; return; } const completed = parseInt(completedStr) || 0; if (completed n) { resultDiv.innerHTML = 'Completed splits must be between 0 and total segments.'; return; } const elapsed = speParseTime(elapsedStr); if (completed > 0 && (elapsed === null || elapsed Please enter a valid elapsed time for completed splits.'; return; }

// Collect split data const rows = document.querySelectorAll(".spe-split-row"); const splits = []; let pbSumCheck = 0; let bestSumTotal = 0; for (let i = 0; i Please enter a valid PB split time for Split \${i+1}.`; return; } pbSumCheck += pbSplit; bestSumTotal += (bestSplit !== null ? bestSplit : pbSplit); splits.push({ name, pbSplit, bestSplit, currentSplit }); }

// ── Core Calculations ──────────────────────────────────────────────────────

// 1. PB cumulative splits (running totals) let pbCumulative = []; let cum = 0; for (let i = 0; i 0 ? (elapsed !== null ? elapsed : currentSplitSum) : 0;

// 6. Time ahead/behind PB at current split const timeDiff = completed > 0 ? (currentTime - pbCumAtCompleted) : 0; // negative = ahead

// 7. Projected finish time (current pace projection) // Method: current_time + sum of PB splits for remaining segments let remainingPBSum = 0; for (let i = completed; i 0 ? currentTime + remainingPBSum : pbTotal;

// 8. Projected finish with best possible remaining let remainingBestSum = 0; for (let i = completed; i 0 ? currentTime + remainingBestSum : bpt;

// 9. Pace ratio (current pace vs PB pace) const paceRatio = completed > 0 && pbCumAtCompleted > 0 ? currentTime / pbCumAtCompleted : 1.0;

// 10. Pace-adjusted projected finish const paceAdjustedFinish = completed > 0 ? paceRatio * pbTotal : pbTotal;

// 11. Per-split analysis for completed splits
let splitRows = "";
for (let i = 0; i \${speFormatDiff(segDiff)}`
`+\${speFormatTime(segDiff)}`;
cumStatus = cumDiff \${speFormatDiff(cumDiff)}`
`+\${speFormatTime(cumDiff)}`; } else if (i No data'; cumStatus = 'No data'; } else { segStatus = 'Pending'; cumStatus = 'Pending'; }

const bestDisplay = s.bestSplit !== null ? speFormatTime(s.bestSplit) : "—"; const timeSave = s.bestSplit !== null ? (s.pbSplit - s.bestSplit) : 0; const timeSaveDisplay = timeSave > 0 ? `\${speFormatTime(timeSave)}` : "—";

splitRows += `

\${s.name} \${speFormatTime(s.pbSplit)} \${speFormatTime(pbCum)} \${bestDisplay} \${timeSaveDisplay} \${currentSplitDisplay} \${currentCumDisplay} \${segStatus} \${cumStatus}

`; }

const aheadBehind = timeDiff \${speFormatDiff(timeDiff)} (Ahead of PB)`
`+\${speFormatTime(timeDiff)} (Behind PB)`;
const projVsPB = projectedFinish - pbTotal;
const projStatus = projVsPB \${speFormatDiff(projVsPB)} vs PB`
`+\${speFormatTime(projVsPB)} vs PB`;
const paceAdjVsPB = paceAdjustedFinish - pbTotal;
const paceAdjStatus = paceAdjVsPB \${speFormatDiff(paceAdjVsPB)} vs PB`
`+\${speFormatTime(paceAdjVsPB)} vs PB`;

resultDiv.innerHTML = ` ### 📊 Speedrun Analysis

Personal Best \${speFormatTime(pbTotal)}

Best Possible Time \${speFormatTime(bpt)} Save: \${speFormatTime(timeSaveAvailable)}

Current Time (\${completed}/\${n} splits) \${completed > 0 ? speFormatTime(currentTime) : "—"} \${completed > 0 ? aheadBehind : "Run not started"}

Pace Ratio \${completed > 0 ? (paceRatio*100).toFixed(2)+"%" : "—"} \${paceRatio 1 ? "Slower than PB pace" : "On PB pace"}

Projected Finish (PB Pace Remaining) \${completed > 0 ? speFormatTime(projectedFinish) : speFormatTime(pbTotal)} \${completed > 0 ? projStatus : "—"}

Projected Finish (Best Remaining) \${completed > 0 ? speFormatTime(projectedBestFinish) : speFormatTime(bpt)} Best-case scenario

Pace-Adjusted Projected Finish \${completed > 0 ? speFormatTime(paceAdjustedFinish) : "—"} \${completed > 0 ? paceAdjStatus : "—"}

Remaining Segments \${n - completed} of \${n} PB time remaining: \${speFormatTime(remainingPBSum)}

#### Split-by-Split Breakdown

Segment PB Split PB Cumul. Best Split Time Save Current Split Current Cumul. Seg Δ Cumul. Δ

\${splitRows}

Δ = difference vs PB. Green = ahead, Red = behind. Cumul. = cumulative (running total) time.

`; }

// Initialize on load speGenerateSplits();

#### Formulas Used

Best Possible Time (BPT): BPT = Σ best_spliti for all i = 1…n

Time Save Available: Time Save = PB_total − BPT

Segment Delta (Δ): Δseg,i = current_spliti − pb_spliti  (negative = faster)

Cumulative Delta: Δcum,i = Σ current_splitj − Σ pb_splitj for j = 1…i

Projected Finish (PB Pace Remaining): Projected = elapsed_time + Σ pb_spliti for i = (completed+1)…n

Projected Finish (Best Remaining): Projected_best = elapsed_time + Σ best_spliti for i = (completed+1)…n

Pace Ratio: Pace Ratio = elapsed_time / Σ pb_spliti for i = 1…completed

Pace-Adjusted Projected Finish: Pace_Adjusted = Pace_Ratio × PB_total

#### Assumptions & References

More Calculators

Read Next

Cocktail Recipe Scaler ANA › Life Services Authority › National Calculator Authority › Cocktail Recipe Scaler .calc-container { max-width: 640px;...

Study Time Planner Authority Network America › Life Services Authority › National Calculator Authority .calc-container { max-width: 640px;...

References