Skip to content

Commit

Permalink
32 embed the calculation options bigdecimal and others in the creatio…
Browse files Browse the repository at this point in the history
…n of the calcpace object (#33)

* Add bigdecimal to the object of the Calcpace class

* Remove round and add option to convert distance using float

* Create convert to miles and km methods

* Update Readme to v 1.2.0 features
  • Loading branch information
0jonjo authored Aug 10, 2024
1 parent ecc0e2b commit 7e66c4a
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 52 deletions.
45 changes: 30 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Calcpace [![Gem Version](https://d25lcipzij17d.cloudfront.net/badge.svg?id=rb&r=r&ts=1683906897&type=6e&v=1.1.1&x2=0)](https://badge.fury.io/rb/calcpace)
# Calcpace [![Gem Version](https://d25lcipzij17d.cloudfront.net/badge.svg?id=rb&r=r&ts=1683906897&type=6e&v=1.2.0&x2=0)](https://badge.fury.io/rb/calcpace)

Calcpace is a Ruby gem that helps with calculations related to running/cycling activities or general purposes involving distance and time. It can calculate pace, total time, and distance, accepting time in seconds or HH:MM:SS format. It also converts distances between miles and kilometers. The results are provided in a readable format, with times in HH:MM:SS or seconds and distances in X.X format. To prevent precision problems, the gem supports BigDecimal to handle the calculations, if you need, and always returns data using the same distance unit (kilometers or miles) that was used as input.

Expand All @@ -7,7 +7,7 @@ Calcpace is a Ruby gem that helps with calculations related to running/cycling a
### Add to your Gemfile

```ruby
gem 'calcpace', '~> 1.1.1'
gem 'calcpace', '~> 1.2.0'
```

Then run bundle install.
Expand All @@ -20,19 +20,29 @@ gem install calcpace

### Usage

Before calculate or convert any value, you must create a new instance of Calcpace. When you call a method, it checks the digits of the time or distance to ensure that they are in the correct format. The gem always returns data using the same distance unit (kilometers or miles) that was used as input.
Before calculate or convert any value, you must create a new instance of Calcpace. When you call a method, it checks the digits of the time or distance to ensure that they are in the correct format. The gem always returns data using the same distance unit (kilometers or miles) that was used as input. If you want to use BigDecimal to handle the calculations, you can pass true as a parameter when creating a new instance of Calcpace. Like this:

```ruby
require 'calcpace'

calculate = Calcpace.new
calculate_bigdecimal = Calcpace.new(true)
another_way_to_use_bigdecimal = Calcpace.new(bigdecimal: true)
```

### Calculate Pace

To calculate pace, provide the total time (in HH:MM:SS format) and distance (in X.X format, representing kilometers or miles). You can use the method `pace` or `pace_seconds`. If you want an extra precision in the calculations, you can pass true as parameter to the method `pace_seconds` and receive result in BigDecimal.

```ruby
calculate = Calcpace.new
calculate.pace('01:00:00', 12) # => "00:05:00"
calculate.pace('string', 12) # It must be a time (RuntimeError)
calculate.pace('01:00:00', 12) # => "00:05:00"
calculate.pace_seconds('01:00:00', 12) # => 300
calculate.pace_seconds('01:37:21', 12.3, true) # => 0.474878048780487804878048780487804878049e3
calculate.pace_seconds('01:37:21', 12.3) # => 474.8780487804878
calculate_bigdecimal = Calcpace.new(true)
calculate_bigdecimal.pace_seconds('01:37:21', 12.3) # => 0.474878048780487804878048780487804878049e3

```

### Calculate Total Time
Expand All @@ -41,10 +51,11 @@ To calculate total time, provide the pace (in HH:MM:SS format) and distance (in

```ruby
calculate = Calcpace.new
calculate.total_time('00:05:00', 12) # => "01:00:00"
calculate.total_time('00:05:00', 'string') # It must be a XX:XX:XX time (RuntimeError)
calculate.total_time('00:05:00', 12) # => "01:00:00"
calculate.total_time_seconds('01:37:21', 12.3) # => 71844.3
calculate.total_time_seconds('01:37:21', 12.3, true) # => 0.718443902439024390243902439024390243902e5
calculate_bigdecimal = Calcpace.new(true)
calculate_bigdecimal.total_time_seconds('01:37:21', 12.3) # => 0.718443902439024390243902439024390243902e5
```

### Calculate Distance
Expand All @@ -53,21 +64,25 @@ To calculate distance, provide the running time (in HH:MM:SS format) and pace (i

```ruby
calculate = Calcpace.new
calculate.distance('01:37:21', '00:06:17') # => 15.0
calculate.distance('01:37:21', '00:06:17', true) # => 0.15493368700265251989389920424403183024e2
calculate.distance('01:37:21', 'string') # It must be a time (RuntimeError)
calculate.distance('01:37:21', '00:06:17') # => 15.0
calculate_bigdecimal = Calcpace.new(true)
calculate_bigdecimal.distance('01:37:21', '00:06:17') # => 0.15493368700265251989389920424403183024e2
```

### Convert Distances

To convert distances, provide the distance and the unit of measurement (either 'km' for kilometers or 'mi' for miles). If want to change the default round of the result (2), you can pass a second parameter to the method.
To convert distances, use one of the two methods: `convert_to_km` or `convert_to_miles`. If want to change the round the result you can use the Ruby method `round` passing the number of decimal places you want. If you need to use BigDecimal to handle the calculations, you can pass true as parameter when creating a new instance of Calcpace.

```ruby
converter = Calcpace.new
converter.convert(10, 'km') # => 6.21
converter.convert(10, 'km', 1) # => 6.2
converter.convert_distance(10, 'mi') # => 16.09
converter.convert(10, 'mi', 3) # => 16.093
converter = Calcpace.new
converter.convert_to_miles('string') # => It must be a X.X positive number (RuntimeError)
converter.convert_to_km(10) # => 16.0934
converter.convert_to_km(10).round(1) # => 16.1
converter.convert_to_miles(10) # => 6.21371
converter_bigdecimal = Calcpace.new(bigdecimal = true)
converter_bigdecimal.convert_to_miles(118.32) # => 0.7352061672e2
converter_bigdecimal.convert_to_km(118.32) # => 0.1904171088e3
```

### Obtain the seconds of a time OR convert seconds to a time
Expand Down
4 changes: 2 additions & 2 deletions calcpace.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

Gem::Specification.new do |s|
s.name = 'calcpace'
s.version = '1.1.1'
s.version = '1.2.0'
s.summary = 'Calcpace: calculate time, distance, pace, velocity and convert distances in an easy and precise way.'
s.description = 'Calcpace is a Ruby gem that helps with calculations related to running/cycling activities or general purposes involving distance and time. It can calculate pace, total time, and distance. It also converts distances between miles and kilometers and check formats of time and distance. The results are provided in a readable format, with times in HH:MM:SS or seconds and distances in X.X format. If you need, the gem supports BigDecimal to handle the calculations, '
s.description = 'Calcpace is a Ruby gem that helps with calculations related to running/cycling activities or general purposes involving distance and time. It can calculate pace, total time, and distance. It also converts distances between miles and kilometers and check formats of time and distance. The results are provided in a readable format, with times in HH:MM:SS or seconds and distances in X.X format. If you need, the gem supports BigDecimal to handle the calculations with more precision.'
s.authors = ['Joao Gilberto Saraiva']
s.email = 'joaogilberto@tuta.io'
s.files = ['lib/calcpace.rb', 'lib/calcpace/calculator.rb', 'lib/calcpace/checker.rb', 'lib/calcpace/converter.rb']
Expand Down
6 changes: 5 additions & 1 deletion lib/calcpace.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,9 @@ class Calcpace
include Checker
include Converter

def initialize; end
attr_reader :bigdecimal

def initialize(bigdecimal = false)
@bigdecimal = bigdecimal
end
end
16 changes: 8 additions & 8 deletions lib/calcpace/calculator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,31 @@
require 'bigdecimal'

module Calculator
def pace(time, distance, bigdecimal = false)
pace_in_seconds = pace_seconds(time, distance, bigdecimal)
def pace(time, distance)
pace_in_seconds = pace_seconds(time, distance)
convert_to_clocktime(pace_in_seconds)
end

def pace_seconds(time, distance, bigdecimal = false)
def pace_seconds(time, distance)
check_time(time)
check_distance(distance)
seconds = convert_to_seconds(time)
bigdecimal ? seconds / BigDecimal(distance.to_s) : seconds / distance
end

def total_time(pace, distance, bigdecimal = false)
total_time_in_seconds = total_time_seconds(pace, distance, bigdecimal)
def total_time(pace, distance)
total_time_in_seconds = total_time_seconds(pace, distance)
convert_to_clocktime(total_time_in_seconds)
end

def total_time_seconds(pace, distance, bigdecimal = false)
def total_time_seconds(pace, distance)
check_time(pace)
check_distance(distance)
pace_seconds = convert_to_seconds(pace)
bigdecimal ? pace_seconds * BigDecimal(distance.to_s) : pace_seconds * distance
@bigdecimal ? pace_seconds * BigDecimal(distance.to_s) : pace_seconds * distance
end

def distance(time, pace, bigdecimal = false)
def distance(time, pace)
check_time(time)
check_time(pace)
if bigdecimal
Expand Down
31 changes: 21 additions & 10 deletions lib/calcpace/converter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
require 'bigdecimal'

module Converter
KM_TO_MI = BigDecimal('0.621371')
MI_TO_KM = BigDecimal('1.60934')
KM_TO_MI_BIGDECIMAL = BigDecimal('0.621371')
KM_TO_MI = 0.621371
MI_TO_KM_BIGDECIMAL = BigDecimal('1.60934')
MI_TO_KM = 1.60934

def to_seconds(time)
check_time(time)
Expand All @@ -16,11 +18,18 @@ def to_clocktime(seconds)
convert_to_clocktime(seconds)
end

def convert(distance, unit, round_limit = 2)
def convert_to_miles(distance)
convert(distance, 'mi')
end

def convert_to_km(distance)
convert(distance, 'km')
end

def convert(distance, unit)
check_distance(distance)
check_unit(unit)
check_integer(round_limit)
convert_the_distance(BigDecimal(distance.to_s), unit, round_limit)
bigdecimal ? distance_to_convert = BigDecimal(distance.to_s) : distance_to_convert = distance
convert_the_distance(distance_to_convert, unit)
end

def convert_to_seconds(time)
Expand All @@ -33,12 +42,14 @@ def convert_to_clocktime(seconds)
Time.at(seconds.to_i).utc.strftime(format)
end

def convert_the_distance(distance, unit, round_limit = 2)
def convert_the_distance(distance, unit)
case unit
when 'km'
(distance * KM_TO_MI).round(round_limit)
when 'mi'
(distance * MI_TO_KM).round(round_limit)
bigdecimal ? km_to_mi = KM_TO_MI_BIGDECIMAL : km_to_mi = KM_TO_MI
(distance * km_to_mi)
when 'km'
bigdecimal ? mi_to_km = MI_TO_KM_BIGDECIMAL : mi_to_km = MI_TO_KM
(distance * mi_to_km)
end
end
end
15 changes: 10 additions & 5 deletions test/calcpace/test_calculator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
class TestCalculator < Minitest::Test
def setup
@checker = Calcpace.new
@checker_bigdecimal = Calcpace.new(bigdecimal = true)
end

def test_pace
Expand All @@ -18,20 +19,24 @@ def test_pace
assert_equal '00:07:54', @checker.pace('01:37:21', 12.3)
end

def test_pace_with_bigdecimal_precision
assert_equal '00:07:54', @checker_bigdecimal.pace('01:37:21', 12.3)
end

def test_pace_without_bigdecimal_precision
assert_equal '00:07:54', @checker.pace('01:37:21', 12.3, false)
assert_equal '00:07:54', @checker.pace('01:37:21', 12.3)
end

def test_pace_seconds
assert_raises(RuntimeError) { @checker.pace_seconds('', 10) }
assert_raises(RuntimeError) { @checker.pace_seconds('invalid', 10) }
assert_raises(RuntimeError) { @checker.pace_seconds('00:00:00', 0) }
assert_raises(RuntimeError) { @checker.pace_seconds('00:00:00', -1) }
assert_equal BigDecimal('474.8780487804878'), @checker.pace_seconds('01:37:21', 12.3)
assert_equal 474.8780487804878, @checker.pace_seconds('01:37:21', 12.3)
end

def test_pace_seconds_with_bigdecimal_precision
assert_equal BigDecimal('0.474878048780487804878048780487804878049e3'), @checker.pace_seconds('01:37:21', 12.3, true)
assert_equal BigDecimal('0.474878048780487804878048780487804878049e3'), @checker_bigdecimal.pace_seconds('01:37:21', 12.3)
end

def test_total_time
Expand All @@ -52,7 +57,7 @@ def test_total_time_seconds
end

def test_total_time_seconds_with_bigdecimal_precision
assert_equal BigDecimal('0.718443e5'), @checker.total_time_seconds('01:37:21', 12.3, true)
assert_equal BigDecimal('0.718443e5'), @checker_bigdecimal.total_time_seconds('01:37:21', 12.3)
end

def test_distance
Expand All @@ -63,6 +68,6 @@ def test_distance
end

def test_distance_with_bigdecimal_precision
assert_equal BigDecimal('0.15493368700265251989389920424403183024e2'), @checker.distance('01:37:21', '00:06:17', true)
assert_equal BigDecimal('0.15493368700265251989389920424403183024e2'), @checker_bigdecimal.distance('01:37:21', '00:06:17')
end
end
31 changes: 20 additions & 11 deletions test/calcpace/test_converter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
class TestConverter < Minitest::Test
def setup
@checker = Calcpace.new
@checker_bigdecimal = Calcpace.new(bigdecimal = true)
end

def test_convert_to_seconds
Expand All @@ -30,20 +31,28 @@ def test_to_clocktime
end

def test_convert_the_distance
assert_equal 6.21, @checker.convert_the_distance(10, 'km')
assert_equal 6.2, @checker.convert_the_distance(10, 'km', 1)
assert_equal 6.214, @checker.convert_the_distance(10, 'km', 3)
assert_equal 16.09, @checker.convert_the_distance(10, 'mi')
assert_equal 6.21, @checker.convert_the_distance(10, 'mi').round(2)
assert_equal 6.2, @checker.convert_the_distance(10, 'mi').round(1)
assert_equal 6.214, @checker.convert_the_distance(10, 'mi').round(3)
assert_equal 16.09, @checker.convert_the_distance(10, 'km').round(2)
end

def test_convert_the_distance_with_bigdecimal_precision
assert_equal BigDecimal('6.21371'), @checker_bigdecimal.convert_the_distance(10, 'mi')
end

def test_convert
assert_equal 6.21, @checker.convert(10, 'km')
assert_equal 16.09, @checker.convert(10, 'mi')
assert_equal 6.2, @checker.convert(10, 'km', 1)
assert_raises(RuntimeError) { @checker.convert(10, 'invalid') }
assert_equal 6.21, @checker.convert(10, 'mi').round(2)
assert_equal 16.09, @checker.convert(10, 'km').round(2)
assert_equal 6.2, @checker.convert(10, 'mi').round(1)
assert_raises(RuntimeError) { @checker.convert(-1, 'km') }
assert_raises(RuntimeError) { @checker.convert(10, 'km', -2) }
assert_raises(RuntimeError) { @checker.convert(10, 'km', 0) }
assert_raises(RuntimeError) { @checker.convert(10, 'km', 'invalid') }
end

def test_convert_to_miles
assert_equal 6.21, @checker.convert_to_miles(10).round(2)
end

def test_convert_to_km
assert_equal 16.09, @checker.convert_to_km(10).round(2)
end
end

0 comments on commit 7e66c4a

Please sign in to comment.