def calculate_price_of_credits(credits)
case credits
when 1..5000
(credits * 0.01)
when 5001..10000
(5000 * 0.01) + ((credits - 5000) * 0.008)
when 10001..25000
(5000 * 0.01) + (5000 * 0.008) + ((credits - 10000) * 0.007)
when 25001..50000
(5000 * 0.01) + (5000 * 0.008) + (15000 * 0.007) + ((credits - 25000) * 0.006)
when 50001..(1.0/0) # hack na zwrocenie obiektu Infinity
(5000 * 0.01) + (5000 * 0.008) + (15000 * 0.007) + (25000 * 0.006) + ((credits - 50000) * 0.005)
end
end
Refactorings
No refactoring yet !
Jeremy Weiskotten
March 7, 2008, March 07, 2008 21:21, permalink
Here's a refactoring with a unit test.
def calculate_price_of_credits(credits)
rates = [ 0.005, 0.006, 0.007, 0.008, 0.01 ]
tiers = [ 50000, 25000, 10000, 5000, 0 ]
price = 0
tiers.each_with_index do |tier, index|
if credits > tier
price += (rates[index] * (credits - tier))
credits = tier
end
end
price
end
class CreditTest < Test::Unit::TestCase
def test_calc
assert_equal 0.01, calculate_price_of_credits(1)
assert_equal 50, calculate_price_of_credits(5000)
assert_equal 50.008, calculate_price_of_credits(5001)
assert_equal 90.0, calculate_price_of_credits(10000)
assert_equal 90.007, calculate_price_of_credits(10001)
assert_equal 195.0, calculate_price_of_credits(25000)
assert_equal 195.006, calculate_price_of_credits(25001)
assert_equal 345.0, calculate_price_of_credits(50000)
assert_equal 345.005, calculate_price_of_credits(50001)
assert_equal 595.0, calculate_price_of_credits(100000)
end
end
Ryan Bates
March 7, 2008, March 07, 2008 21:53, permalink
Instead of hard coding the numbers you could move this to a database table. One column could be the tier (0, 5000, 10000, etc.) and another be the rate (0.01, 0.008, etc.). This way it will be easier to change if you ever need to. Also, if you're using Rails, this will give you a nice ActiveRecord model to move the logic into.
Jeremy Weiskotten
March 8, 2008, March 08, 2008 01:30, permalink
A slightly more condensed version... This also allows you to pass in the tier/rate structure, and could pretty easily be adapted to use an ActiveRecord model instead as Ryan suggested. (Love the Railscasts!)
def calculate_price_of_credits(credits, rates=nil)
rates ||= [ [50000, 0.005], [25000, 0.006], [10000, 0.007], [5000, 0.008], [0, 0.01] ]
price = 0
rates.each do |tier, rate|
if credits > tier
price += (rate * (credits - tier))
credits = tier
end
end
price
end
very uglish method, please help