{"id":44635552,"url":"https://github.com/0jonjo/calcpace","last_synced_at":"2026-04-19T00:16:21.807Z","repository":{"id":177685959,"uuid":"450163819","full_name":"0jonjo/calcpace","owner":"0jonjo","description":"Calcpace is a Ruby gem designed for calculations related to distance, speed and time. The gem also supports conversion to 42 different units of distance and velocity, including metric, nautical and imperial units.","archived":false,"fork":false,"pushed_at":"2025-11-08T12:48:31.000Z","size":151,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-03T21:13:49.305Z","etag":null,"topics":["distance-calculation","gem","gems","minitest","ruby","running","tdd","time-calculation"],"latest_commit_sha":null,"homepage":"https://rubygems.org/gems/calcpace","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/0jonjo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-01-20T16:02:46.000Z","updated_at":"2025-11-08T12:48:35.000Z","dependencies_parsed_at":"2024-05-13T19:30:30.721Z","dependency_job_id":"49c794cc-81d5-4d21-b652-5e11bc9b7962","html_url":"https://github.com/0jonjo/calcpace","commit_stats":null,"previous_names":["0jonjo/calcpace"],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/0jonjo/calcpace","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0jonjo%2Fcalcpace","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0jonjo%2Fcalcpace/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0jonjo%2Fcalcpace/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0jonjo%2Fcalcpace/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/0jonjo","download_url":"https://codeload.github.com/0jonjo/calcpace/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0jonjo%2Fcalcpace/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29449218,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-14T15:52:44.973Z","status":"ssl_error","status_checked_at":"2026-02-14T15:52:11.208Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["distance-calculation","gem","gems","minitest","ruby","running","tdd","time-calculation"],"created_at":"2026-02-14T17:22:23.088Z","updated_at":"2026-04-19T00:16:20.828Z","avatar_url":"https://github.com/0jonjo.png","language":"Ruby","readme":"# Calcpace [![Gem Version](https://d25lcipzij17d.cloudfront.net/badge.svg?id=rb\u0026r=r\u0026ts=1683906897\u0026type=6e\u0026v=1.9.3\u0026x2=0)](https://badge.fury.io/rb/calcpace)\n\nA Ruby gem for running and cycling calculations: pace, time, distance, unit conversions, race predictions, GPS track analysis, and VO2max estimation.\n\n## Installation\n\n```ruby\ngem 'calcpace', '~\u003e 1.9'\n```\n\n## Usage\n\n```ruby\nrequire 'calcpace'\ncalc = Calcpace.new\n```\n\n---\n\n### Basic Calculations\n\n```ruby\ncalc.velocity(3625, 12275)          # =\u003e 3.386  (distance / time)\ncalc.pace(3665, 12)                 # =\u003e 305.4  (time / distance)\ncalc.time(210, 12)                  # =\u003e 2520.0 (pace × distance)\ncalc.distance(9660, 120)            # =\u003e 80.5   (velocity × time)\n\n# Clocktime input/output (HH:MM:SS or MM:SS)\ncalc.clock_pace('01:00:00', 10)     # =\u003e \"00:06:00\"\ncalc.clock_time('00:05:31', 12.6)   # =\u003e \"01:09:30\"\ncalc.checked_distance('01:21:32', '00:06:27') # =\u003e 12.64\n```\n\n---\n\n### Unit Conversions\n\n30+ units supported. String or symbol format:\n\n```ruby\ncalc.convert(10, :km_to_mi)         # =\u003e 6.21371\ncalc.convert(10, 'mi to km')        # =\u003e 16.0934\ncalc.convert(1, :m_s_to_km_h)       # =\u003e 3.6\n\n# Chain conversions\ncalc.convert_chain(1, [:km_to_mi, :mi_to_feet])  # =\u003e 3280.84\n```\n\nSee all units: `calc.list_all`, `calc.list_distance`, `calc.list_speed`.\n\n---\n\n### Pace Conversions\n\n```ruby\ncalc.pace_km_to_mi('05:00')   # =\u003e \"00:08:02\"\ncalc.pace_mi_to_km('08:00')   # =\u003e \"00:04:58\"\n```\n\n---\n\n### Race Pace \u0026 Time\n\n```ruby\ncalc.race_time_clock('05:00', 'marathon')          # =\u003e \"03:30:58\"\ncalc.race_pace_clock('04:00:00', 'marathon')       # =\u003e \"00:05:41\"\ncalc.list_races  # =\u003e { '5k' =\u003e 5.0, '10k' =\u003e 10.0, 'half_marathon' =\u003e 21.0975, 'marathon' =\u003e 42.195, '100k' =\u003e 100.0, ... }\n```\n\n---\n\n### Race Splits\n\n```ruby\n# Even pace — default\ncalc.race_splits('half_marathon', target_time: '01:30:00', split_distance: '5k')\n# =\u003e [\"00:21:20\", \"00:42:40\", \"01:03:59\", \"01:25:19\", \"01:30:00\"]\n\n# Strategies: :even (default), :negative (second half faster), :positive (first half faster)\ncalc.race_splits('10k', target_time: '00:40:00', split_distance: '5k', strategy: :negative)\n# =\u003e [\"00:20:48\", \"00:40:00\"]\n```\n\n---\n\n### Race Time Predictions\n\n**Riegel formula** (`T2 = T1 × (D2/D1)^1.06`):\n\n```ruby\ncalc.predict_time_clock('5k', '00:20:00', 'marathon')   # =\u003e \"03:11:49\"\ncalc.predict_pace_clock('5k', '00:20:00', 'marathon')   # =\u003e \"00:04:32\"\ncalc.equivalent_performance('10k', '00:42:00', '5k')\n# =\u003e { time: 1209.0, time_clock: \"00:20:09\", pace: 241.8, pace_clock: \"00:04:02\" }\n```\n\n**Cameron formula** (exponential correction — tends to be more conservative from short distances):\n\n```ruby\ncalc.predict_time_cameron_clock('10k', '00:42:00', 'marathon')  # =\u003e \"02:57:46\"\ncalc.predict_pace_cameron_clock('10k', '00:42:00', 'marathon')  # =\u003e \"00:04:13\"\n```\n\n---\n\n### GPS Track Analysis\n\nAccepts an array of hashes with `:lat`, `:lon`, and optionally `:ele` (metres) and `:time` (`Time`):\n\n```ruby\npoints = [\n  { lat: -23.5505, lon: -46.6333, ele: 760.0, time: Time.parse('2024-01-01 07:00:00') },\n  { lat: -23.5510, lon: -46.6400, ele: 765.0, time: Time.parse('2024-01-01 07:05:00') },\n  { lat: -23.5520, lon: -46.6480, ele: 758.0, time: Time.parse('2024-01-01 07:10:00') },\n]\n\ncalc.haversine_distance(-23.5505, -46.6333, -23.5510, -46.6340)  # =\u003e 0.089 km\ncalc.track_distance(points)    # =\u003e 0.87 km\ncalc.elevation_gain(points)    # =\u003e { gain: 5.0, loss: 7.0 }\ncalc.track_splits(points, 1.0) # =\u003e [{ km: 1, elapsed: 312, pace: \"05:12\" }, ...]\n```\n\n**Haversine formula** — great-circle distance on a sphere (R = 6,371 km). Accuracy: ~0.3% of GPS/WGS84. Best for running and cycling distances; not for geodetic surveying.\n\n---\n\n### VO2max Estimation\n\nEstimate aerobic fitness from a race result using the **Daniels \u0026 Gilbert formula** (1979):\n\n```ruby\ncalc.estimate_vo2max(10.0, '00:40:00')   # =\u003e 51.9 ml/kg/min\ncalc.estimate_vo2max(42.195, '03:30:00') # =\u003e 44.8\ncalc.estimate_vo2max(5.0, 2400)          # also accepts total seconds\n\ncalc.vo2max_label(51.9)  # =\u003e \"Very Good\"\n```\n\n| VO2max (ml/kg/min) | Level     |\n|--------------------|-----------|\n| ≥ 70               | Elite     |\n| 60–69              | Excellent |\n| 50–59              | Very Good |\n| 40–49              | Good      |\n| 30–39              | Fair      |\n| \u003c 30               | Beginner  |\n\n**Formula:**\n```\nvelocity (m/min) = distance_m / time_min\nVO2              = −4.60 + 0.182258·v + 0.000104·v²\n%VO2max          = 0.8 + 0.1894393·e^(−0.012778·t) + 0.2989558·e^(−0.1932605·t)\nVO2max           = VO2 / %VO2max\n```\n\nAccuracy: ±3–5 ml/kg/min vs. laboratory testing. Best with efforts between **5 and 60 minutes** at near-maximal pace.\n\n---\n\n### Other Utilities\n\n```ruby\ncalc.convert_to_seconds('01:00:00')  # =\u003e 3600\ncalc.convert_to_clocktime(3600)      # =\u003e \"01:00:00\"\ncalc.check_time('01:00:00')          # =\u003e nil (valid)\n```\n\n---\n\n### Errors\n\nAll errors inherit from `Calcpace::Error`:\n\n- `Calcpace::NonPositiveInputError` — numeric input is zero or negative\n- `Calcpace::InvalidTimeFormatError` — time string not in `HH:MM:SS` or `MM:SS` format\n\n---\n\n### Testing\n\n```bash\nbundle exec rake\n```\n\nRequires Ruby \u003e= 3.2.0.\n\n## Contributing\n\nClone the repo and submit a pull request. Please include tests.\n\n## License\n\n[MIT License](https://opensource.org/licenses/MIT)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0jonjo%2Fcalcpace","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F0jonjo%2Fcalcpace","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0jonjo%2Fcalcpace/lists"}