| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 |
- /**
- * 配速:每公里用时(秒)
- * 支持 390、6:30、6'30"、6′30″、3"00"(分+秒直引号)
- */
- const MANUAL_PACE_MIN_SEC = 180 // 3'00"/km
- const MANUAL_PACE_MAX_SEC = 600 // 10'00"/km
- function parsePaceToSecPerKm(input) {
- if (input === '' || input === null || input === undefined) {
- throw new Error('缺少配速')
- }
- const s = String(input).trim()
- if (/^\d+(\.\d+)?$/.test(s)) {
- const n = parseFloat(s)
- if (n < 10) {
- throw new Error('纯数字配速表示每公里秒数,例如 390 表示 6:30/km')
- }
- return n
- }
- const colon = s.match(/^(\d+)[::](\d{1,2}(?:\.\d+)?)$/)
- if (colon) {
- return parseInt(colon[1], 10) * 60 + parseFloat(colon[2])
- }
- const quote = s.match(/^(\d+)['′『](\d{1,2}(?:\.\d+)?)[""″』]?$/)
- if (quote) {
- return parseInt(quote[1], 10) * 60 + parseFloat(quote[2])
- }
- const weirdQuote = s.match(/^(\d+)"(\d{2})"$/)
- if (weirdQuote) {
- return parseInt(weirdQuote[1], 10) * 60 + parseInt(weirdQuote[2], 10)
- }
- throw new Error(`无法解析配速「${s}」,请使用 5:30、5'30" 或每公里秒数如 330`)
- }
- function clampManualPaceSec(sec) {
- const n = Number(sec)
- if (!Number.isFinite(n)) {
- throw new Error('配速无效')
- }
- if (n < MANUAL_PACE_MIN_SEC || n > MANUAL_PACE_MAX_SEC) {
- throw new Error(`单次乐跑配速需在 3:00–10:00 /km(${MANUAL_PACE_MIN_SEC}–${MANUAL_PACE_MAX_SEC} 秒/公里)`)
- }
- return n
- }
- /** 自动乐跑:闭区间随机秒/公里 */
- function randomPaceSecPerKm(minSec, maxSec) {
- const lo = Math.max(120, Math.min(minSec, maxSec))
- const hi = Math.max(lo, Math.max(minSec, maxSec))
- return Math.round(lo + Math.random() * (hi - lo))
- }
- module.exports = {
- parsePaceToSecPerKm,
- clampManualPaceSec,
- randomPaceSecPerKm,
- MANUAL_PACE_MIN_SEC,
- MANUAL_PACE_MAX_SEC
- }
|