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

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

Към профила на Димитър Димитров

Резултати

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

Код

require 'bigdecimal'
require 'bigdecimal/util'
class ExchangeRate
class Unknown < RuntimeError
end
def initialize
@rates = {}
end
def set(from_currency, to_currency, rate)
return if from_currency == to_currency
@rates[tuple(from_currency, to_currency)] = rate
@rates[tuple(to_currency, from_currency)] = 1.to_d / rate
end
def get(from_currency, to_currency)
return 1.to_d if from_currency == to_currency
@rates[tuple(from_currency, to_currency)]
end
def convert(from_currency, to_currency, amount)
rate = get(from_currency, to_currency)
raise Unknown, "Cannot convert from #{from_currency} to #{to_currency}" unless rate
amount * rate
end
private
def tuple(a, b)
:"#{a}-#{b}"
end
end
class Money
class IncompatibleCurrencies < RuntimeError
end
include Comparable
attr_reader :amount, :currency
def initialize(amount, currency)
@amount, @currency = amount, currency
end
def in(new_currency, exchange_rate)
new_amount = exchange_rate.convert(currency, new_currency, amount)
Money.new new_amount, new_currency
end
def *(other)
apply_numeric :*, other
end
def /(other)
apply_numeric :/, other
end
def +(money)
apply_monetary :+, money
end
def -(money)
apply_monetary :-, money
end
def ==(money)
apply_comparison :==, money
end
def <=>(money)
apply_comparison :<=>, money
end
def to_s
"#{'%.2f' % amount} #{currency}"
end
private
def apply_comparison(operation, argument)
raise ArgumentError, "Comparing Money with #{argument.class}" unless argument.kind_of?(Money)
raise IncompatibleCurrencies unless argument.currency == currency
amount.public_send(operation, argument.amount)
end
def apply_numeric(operation, argument)
if argument.kind_of?(Numeric)
Money.new amount.public_send(operation, argument), currency
else
raise ArgumentError
end
end
def apply_monetary(operation, argument)
if argument.kind_of?(Money)
raise IncompatibleCurrencies unless argument.currency == currency
Money.new amount.public_send(operation, argument.amount), currency
else
raise ArgumentError
end
end
end

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

...............................................

Finished in 0.05757 seconds
47 examples, 0 failures

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

Димитър обнови решението на 10.01.2013 03:09 (преди над 11 години)

+require 'bigdecimal'
+require 'bigdecimal/util'
+
+class ExchangeRate
+ class Unknown < RuntimeError
+ end
+
+ def initialize
+ @rates = {}
+ end
+
+ def set(from_currency, to_currency, rate)
+ return if from_currency == to_currency
+
+ @rates[tuple(from_currency, to_currency)] = rate
+ @rates[tuple(to_currency, from_currency)] = 1.to_d / rate
+ end
+
+ def get(from_currency, to_currency)
+ return 1.to_d if from_currency == to_currency
+ @rates[tuple(from_currency, to_currency)]
+ end
+
+ def convert(from_currency, to_currency, amount)
+ rate = get(from_currency, to_currency)
+ raise Unknown, "Cannot convert from #{from_currency} to #{to_currency}" unless rate
+
+ amount * rate
+ end
+
+ private
+
+ def tuple(a, b)
+ :"#{a}-#{b}"
+ end
+end
+
+class Money
+ class IncompatibleCurrencies < RuntimeError
+ end
+
+ include Comparable
+ attr_reader :amount, :currency
+
+ def initialize(amount, currency)
+ @amount, @currency = amount, currency
+ end
+
+ def in(new_currency, exchange_rate)
+ new_amount = exchange_rate.convert(currency, new_currency, amount)
+ Money.new new_amount, new_currency
+ end
+
+ def *(other)
+ apply_numeric :*, other
+ end
+
+ def /(other)
+ apply_numeric :/, other
+ end
+
+ def +(money)
+ apply_monetary :+, money
+ end
+
+ def -(money)
+ apply_monetary :-, money
+ end
+
+ def ==(money)
+ apply_comparison :==, money
+ end
+
+ def <=>(money)
+ apply_comparison :<=>, money
+ end
+
+ def to_s
+ "#{'%.2f' % amount} #{currency}"
+ end
+
+ private
+
+ def apply_comparison(operation, argument)
+ raise ArgumentError, "Comparing Money with #{argument.class}" unless argument.kind_of?(Money)
+ raise IncompatibleCurrencies unless argument.currency == currency
+
+ amount.public_send(operation, argument.amount)
+ end
+
+ def apply_numeric(operation, argument)
+ if argument.kind_of?(Numeric)
+ Money.new amount.public_send(operation, argument), currency
+ else
+ raise ArgumentError
+ end
+ end
+
+ def apply_monetary(operation, argument)
+ if argument.kind_of?(Money)
+ raise IncompatibleCurrencies unless argument.currency == currency
+ Money.new amount.public_send(operation, argument.amount), currency
+ else
+ raise ArgumentError
+ end
+ end
+end