Решение на Шеста задача от Петър Костов

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

Към профила на Петър Костов

Резултати

  • 6 точки от тестове
  • 0 бонус точки
  • 6 точки общо
  • 44 успешни тест(а)
  • 3 неуспешни тест(а)

Код

require 'bigdecimal'
require 'bigdecimal/util'
class ExchangeRateRow
attr_accessor :from, :to, :rate
def initialize(from_currency, to_currency, rate)
@from = from_currency
@to = to_currency
@rate = rate
end
def match?(from_currency, to_currency)
(from_currency == @from and to_currency == @to) or
(from_currency == @to and to_currency == @from)
end
def rate(from_currency, to_currency)
if from_currency == @from and to_currency == @to
@rate
else
'1'.to_d / @rate
end
end
end
class ExchangeRate
def initialize
@rate_rows = []
end
def set(from_currency, to_currency, rate)
rate_row = find_rate from_currency, to_currency
if rate_row == nil
@rate_rows << ExchangeRateRow.new(from_currency, to_currency, rate)
else
rate_row.from, rate_row.to, rate_row.rate = from_currency, to_currency, rate
end
end
def get(from_currency, to_currency)
return 1 if from_currency == to_currency
rate_row = find_rate from_currency, to_currency
if rate_row == nil
nil
else
rate_row.rate from_currency, to_currency
end
end
def convert(from_currency, to_currency, amount)
rate = get from_currency, to_currency
if rate == nil
raise Unknown
else
amount * rate
end
end
class Unknown < RuntimeError
end
private
def find_rate(from_currency, to_currency)
@rate_rows.find { |row| row.match? from_currency, to_currency }
end
end
class Money
include Comparable
attr_reader :amount, :currency
def initialize(amount, currency)
@amount, @currency = amount, currency
end
def to_s
@amount.to_s('2F') + " " + @currency.to_s
end
def in(currency, exchange_rate)
new_currency_amount = exchange_rate.convert @currency, currency, @amount
Money.new new_currency_amount, currency
end
def *(number)
check_for_numeric number
Money.new @amount * number.to_d, @currency
end
def /(number)
check_for_numeric number
Money.new @amount / number.to_d, @currency
end
def -(money)
check_for_money money
Money.new @amount - money.amount, @currency
end
def +(money)
check_for_money money
Money.new @amount + money.amount, @currency
end
def <=>(other)
check_for_money other
@currency <=> other.currency
end
def ==(other)
check_for_money other
@currency == other.currency
end
class IncompatibleCurrencies < RuntimeError
end
private
def check_for_numeric(argumet)
raise ArgumentError unless argumet.is_a? Numeric
end
def check_for_money(argumet)
raise ArgumentError unless argumet.is_a? Money
raise IncompatibleCurrencies unless @currency == argumet.currency
end
end

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

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

Failures:

  1) Money has a custom to_s representation
     Failure/Error: Money.new('12.1'.to_d, :USD).to_s.should eq '12.10 USD'
       
       expected: "12.10 USD"
            got: "12.1 USD"
       
       (compared using ==)
     # /tmp/d20130203-23049-1oel5g7/spec.rb:90:in `block (2 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) Money comparison works when currencies are the same
     Failure/Error: (a <= b).should be_false
       expected: false value
            got: true
     # /tmp/d20130203-23049-1oel5g7/spec.rb:173: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 comparison works for equality when currencies are the same
     Failure/Error: (Money.new('12.45'.to_d, :BGN) == Money.new('12.451'.to_d, :BGN)).should be_false
       expected: false value
            got: true
     # /tmp/d20130203-23049-1oel5g7/spec.rb:190: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)>'

Finished in 0.05709 seconds
47 examples, 3 failures

Failed examples:

rspec /tmp/d20130203-23049-1oel5g7/spec.rb:88 # Money has a custom to_s representation
rspec /tmp/d20130203-23049-1oel5g7/spec.rb:168 # Money comparison works when currencies are the same
rspec /tmp/d20130203-23049-1oel5g7/spec.rb:188 # Money comparison works for equality when currencies are the same

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

Петър обнови решението на 16.01.2013 00:27 (преди около 12 години)

+require 'bigdecimal'
+require 'bigdecimal/util'
+
+class ExchangeRateRow
+ attr_accessor :from, :to, :rate
+
+ def initialize(from_currency, to_currency, rate)
+ @from = from_currency
+ @to = to_currency
+ @rate = rate
+ end
+
+ def match?(from_currency, to_currency)
+ (from_currency == @from and to_currency == @to) or
+ (from_currency == @to and to_currency == @from)
+ end
+
+ def rate(from_currency, to_currency)
+ if from_currency == @from and to_currency == @to
+ @rate
+ else
+ '1'.to_d / @rate
+ end
+ end
+end
+
+class ExchangeRate
+ def initialize
+ @rate_rows = []
+ end
+
+ def set(from_currency, to_currency, rate)
+ rate_row = find_rate from_currency, to_currency
+
+ if rate_row == nil
+ @rate_rows << ExchangeRateRow.new(from_currency, to_currency, rate)
+ else
+ rate_row.from, rate_row.to, rate_row.rate = from_currency, to_currency, rate
+ end
+ end
+
+ def get(from_currency, to_currency)
+ return 1 if from_currency == to_currency
+
+ rate_row = find_rate from_currency, to_currency
+
+ if rate_row == nil
+ nil
+ else
+ rate_row.rate from_currency, to_currency
+ end
+ end
+
+ def convert(from_currency, to_currency, amount)
+ rate = get from_currency, to_currency
+
+ if rate == nil
+ raise Unknown
+ else
+ amount * rate
+ end
+ end
+
+ class Unknown < RuntimeError
+ end
+
+ private
+
+ def find_rate(from_currency, to_currency)
+ @rate_rows.find { |row| row.match? from_currency, to_currency }
+ end
+end
+
+class Money
+ include Comparable
+ attr_reader :amount, :currency
+
+ def initialize(amount, currency)
+ @amount, @currency = amount, currency
+ end
+
+ def to_s
+ @amount.to_s('2F') + " " + @currency.to_s
+ end
+
+ def in(currency, exchange_rate)
+ new_currency_amount = exchange_rate.convert @currency, currency, @amount
+ Money.new new_currency_amount, currency
+ end
+
+ def *(number)
+ check_for_numeric number
+ Money.new @amount * number.to_d, @currency
+ end
+
+ def /(number)
+ check_for_numeric number
+ Money.new @amount / number.to_d, @currency
+ end
+
+ def -(money)
+ check_for_money money
+ Money.new @amount - money.amount, @currency
+ end
+
+ def +(money)
+ check_for_money money
+ Money.new @amount + money.amount, @currency
+ end
+
+ def <=>(other)
+ check_for_money other
+ @currency <=> other.currency
+ end
+
+ def ==(other)
+ check_for_money other
+ @currency == other.currency
+ end
+
+ class IncompatibleCurrencies < RuntimeError
+ end
+
+ private
+ def check_for_numeric(argumet)
+ raise ArgumentError unless argumet.is_a? Numeric
+ end
+
+ def check_for_money(argumet)
+ raise ArgumentError unless argumet.is_a? Money
+ raise IncompatibleCurrencies unless @currency == argumet.currency
+ end
+end