Живко обнови решението на 16.01.2013 13:43 (преди около 12 години)
+require 'bigdecimal'
+require 'bigdecimal/util'
+
+class ExchangeRate
+ class Unknown < RuntimeError
+ end
+
+ def initialize
+ @rates = {}
+ end
+
+ def set(from_currency, to_currency, rate)
+ @rates[to_currency] ||= {}
+ @rates[to_currency][from_currency] = 1 / rate
+ @rates[from_currency] ||= {}
+ @rates[from_currency][to_currency] = rate
+ end
+
+ def get(from_currency, to_currency)
+ if from_currency == to_currency
+ 1
+ elsif @rates.include? from_currency and @rates[from_currency].include? to_currency
+ @rates[from_currency][to_currency]
+ else
+ nil
+ end
+ end
+
+ def convert(from_currency, to_currency, amount)
+ rate = get(from_currency, to_currency)
+ if rate
+ rate * amount
+ else
+ raise ExchangeRate::Unknown, "unknown currency #{from_currency} or #{to_currency}"
+ end
+ end
+
+ private
+end
+
+class Money
+ attr_reader :amount, :currency
+
+ def initialize(amount, currency)
+ @amount, @currency = amount, currency
+ end
+
+ def to_s
+ "#{"%.2f" % @amount} #@currency"
+ end
+
+ def in(new_currency, exchange_rate)
+ exchange_rate.convert @currency, new_currency, @amount
+ end
+
+ def *(other)
+ if other.is_a? Money
+ if @currency == other.currency
+ Money.new @amount * other.amount, @currency
+ else
+ raise Money::IncompatibleCurrencies
+ end
+ else
+ Money.new @amount * other, @currency
+ end
+ end
+
+ def <=>(other)
+ if other.is_a? Money
+ if @currency == other.currency
+ @amount <=> other.amount
+ else
+ raise Money::IncompatibleCurrencies
+ end
+ else
+ raise ArgumentError
+ end
+ end
+
+ def ==(other)
+ if other.is_a? Money
+ if @currency == other.currency
+ @amount == other.amount
+ else
+ raise Money::IncompatibleCurrencies
+ end
+ else
+ raise ArgumentError
+ end
+ end
+end