Решение на Шеста задача от Илиян Бобев

Обратно към всички решения

Към профила на Илиян Бобев

Резултати

  • 5 точки от тестове
  • 0 бонус точки
  • 5 точки общо
  • 39 успешни тест(а)
  • 8 неуспешни тест(а)

Код

require 'bigdecimal'
require 'bigdecimal/util'
class ExchangeRate
class Unknown < RuntimeError
end
attr_accessor :rates
def initialize
@rates={}
end
def key(from_currency, to_currency)
from_currency.to_s + to_currency.to_s
end
def set(from_currency, to_currency, rate)
@rates[key(from_currency, to_currency)] = rate
@rates[key(to_currency, from_currency)] = 1/rate #BigDecimal.new (1/rate)
end
def get(from_currency, to_currency)
@rates[key(from_currency, to_currency)]
end
def convert(from_currency, to_currency, amount)
if not @rates.key?(key(from_currency,to_currency)) and from_currency != to_currency then
raise ExchangeRate::Unknown
elsif from_currency == to_currency then
amount
else
amount*get(from_currency, to_currency)
end
end
end
class Money
include Comparable
class IncompatibleCurrencies < ArgumentError
end
attr_accessor :amount, :currency
def initialize(amount, currency)
@amount = amount
@currency = currency
end
def to_s
result = @amount.to_f.round(2).to_s
if result[-2] == '.' then
result += '0'
end
result + ' ' + @currency.to_s
end
def in(currency, exchange_rate)
Money.new exchange_rate.convert(@currency, currency, @amount), currency
end
def *(other)
Money.new @amount*other, @currency
end
def /(other)
Money.new @amount/other, @currency
end
def +(other)
if other.class != Money then raise ArgumentError end
if other.currency != @currency then raise Money::IncompatibleCurrencies end
Money.new @amount + other.amount, @currency
end
def -(other)
if other.class != Money then raise ArgumentError end
if other.currency != @currency then raise Money::IncompatibleCurrencies end
Money.new @amount - other.amount, @currency
end
def <=>(other)
if other.class != Money then raise ArgumentError end
if other.currency != @currency then raise Money::IncompatibleCurrencies end
@amount <=> other.amount
end
end

Лог от изпълнението

.......FF...........F.F........FF....FF........

Failures:

  1) ExchangeRate#get always returns 1 as the exchange rate between two identical currencies
     Failure/Error: rate.get(:JPY, :JPY).should eq 1.to_d
       
       expected: #<BigDecimal:9c1aae4,'0.1E1',9(36)>
            got: nil
       
       (compared using ==)
     # /tmp/d20130203-23049-1b29n6/spec.rb:45:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  2) ExchangeRate#get does not allow changing the exchange rate between two identical currencies
     Failure/Error: rate.get(:EUR, :EUR).should eq 1.to_d
       
       expected: #<BigDecimal:9c1d6f4,'0.1E1',9(36)>
            got: #<BigDecimal:9c1d8fc,'0.5E0',9(36)>
       
       (compared using ==)
     # /tmp/d20130203-23049-1b29n6/spec.rb:50:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  3) Money arithmetic * with money objects raises an ArgumentError
     Failure/Error: expect do
       expected ArgumentError, got #<TypeError: Money can't be coerced into BigDecimal>
     # /tmp/d20130203-23049-1b29n6/spec.rb:129:in `block (4 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  4) Money arithmetic / with money objects raises an ArgumentError
     Failure/Error: expect do
       expected ArgumentError, got #<TypeError: Money can't be coerced into BigDecimal>
     # /tmp/d20130203-23049-1b29n6/spec.rb:129:in `block (4 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  5) Money arithmetic * with other objects raises an ArgumentError
     Failure/Error: expect do
       expected ArgumentError, got #<TypeError: String can't be coerced into BigDecimal>
     # /tmp/d20130203-23049-1b29n6/spec.rb:160:in `block (4 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  6) Money arithmetic / with other objects raises an ArgumentError
     Failure/Error: expect do
       expected ArgumentError, got #<TypeError: String can't be coerced into BigDecimal>
     # /tmp/d20130203-23049-1b29n6/spec.rb:160:in `block (4 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  7) Money comparison with == raises ArgumentError when comparing with other objects
     Failure/Error: expect do
       expected ArgumentError but nothing was raised
     # /tmp/d20130203-23049-1b29n6/spec.rb:195:in `block (4 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  8) Money comparison with == raises IncompatibleCurrencies when currencies differ
     Failure/Error: expect do
       expected Money::IncompatibleCurrencies but nothing was raised
     # /tmp/d20130203-23049-1b29n6/spec.rb:201:in `block (4 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.0587 seconds
47 examples, 8 failures

Failed examples:

rspec /tmp/d20130203-23049-1b29n6/spec.rb:44 # ExchangeRate#get always returns 1 as the exchange rate between two identical currencies
rspec /tmp/d20130203-23049-1b29n6/spec.rb:48 # ExchangeRate#get does not allow changing the exchange rate between two identical currencies
rspec /tmp/d20130203-23049-1b29n6/spec.rb:128 # Money arithmetic * with money objects raises an ArgumentError
rspec /tmp/d20130203-23049-1b29n6/spec.rb:128 # Money arithmetic / with money objects raises an ArgumentError
rspec /tmp/d20130203-23049-1b29n6/spec.rb:159 # Money arithmetic * with other objects raises an ArgumentError
rspec /tmp/d20130203-23049-1b29n6/spec.rb:159 # Money arithmetic / with other objects raises an ArgumentError
rspec /tmp/d20130203-23049-1b29n6/spec.rb:194 # Money comparison with == raises ArgumentError when comparing with other objects
rspec /tmp/d20130203-23049-1b29n6/spec.rb:200 # Money comparison with == raises IncompatibleCurrencies when currencies differ

История (1 версия и 0 коментара)

Илиян обнови решението на 15.01.2013 20:25 (преди около 12 години)

+require 'bigdecimal'
+require 'bigdecimal/util'
+
+class ExchangeRate
+ class Unknown < RuntimeError
+ end
+
+ attr_accessor :rates
+
+ def initialize
+ @rates={}
+ end
+
+ def key(from_currency, to_currency)
+ from_currency.to_s + to_currency.to_s
+ end
+
+ def set(from_currency, to_currency, rate)
+ @rates[key(from_currency, to_currency)] = rate
+ @rates[key(to_currency, from_currency)] = 1/rate #BigDecimal.new (1/rate)
+ end
+
+ def get(from_currency, to_currency)
+ @rates[key(from_currency, to_currency)]
+ end
+
+ def convert(from_currency, to_currency, amount)
+ if not @rates.key?(key(from_currency,to_currency)) and from_currency != to_currency then
+ raise ExchangeRate::Unknown
+ elsif from_currency == to_currency then
+ amount
+ else
+ amount*get(from_currency, to_currency)
+ end
+ end
+end
+
+class Money
+ include Comparable
+
+ class IncompatibleCurrencies < ArgumentError
+ end
+
+ attr_accessor :amount, :currency
+
+ def initialize(amount, currency)
+ @amount = amount
+ @currency = currency
+ end
+
+ def to_s
+ result = @amount.to_f.round(2).to_s
+ if result[-2] == '.' then
+ result += '0'
+ end
+ result + ' ' + @currency.to_s
+ end
+
+ def in(currency, exchange_rate)
+ Money.new exchange_rate.convert(@currency, currency, @amount), currency
+ end
+
+ def *(other)
+ Money.new @amount*other, @currency
+ end
+
+ def /(other)
+ Money.new @amount/other, @currency
+ end
+
+ def +(other)
+ if other.class != Money then raise ArgumentError end
+ if other.currency != @currency then raise Money::IncompatibleCurrencies end
+ Money.new @amount + other.amount, @currency
+ end
+
+ def -(other)
+ if other.class != Money then raise ArgumentError end
+ if other.currency != @currency then raise Money::IncompatibleCurrencies end
+ Money.new @amount - other.amount, @currency
+ end
+
+ def <=>(other)
+ if other.class != Money then raise ArgumentError end
+ if other.currency != @currency then raise Money::IncompatibleCurrencies end
+ @amount <=> other.amount
+ end
+end