Румен обнови решението на 13.01.2013 18:52 (преди около 12 години)
+require 'bigdecimal'
+require 'bigdecimal/util'
+
+class ExchangeRate
+ class Unknown < RuntimeError
+ end
+
+ def initialize()
+ @currencies = {}
+ end
+
+ def set(from_currency, to_currency, rate)
+ @currencies[get_from_to_key(from_currency, to_currency)] = rate
+ @currencies[get_to_from_key(to_currency, from_currency)] = 1.to_d / rate
+ end
+
+ def get(from_currency, to_currency)
+ if from_currency == to_currency then 1
+ else @currencies[get_from_to_key(from_currency, to_currency)]
+ end
+ end
+
+ def convert(from_currency, to_currency, amount)
+ if get(from_currency, to_currency) == nil then raise Unknown
+ else get(from_currency, to_currency) * amount
+ end
+ end
+
+ private
+
+ def get_from_to_key(from_currency, to_currency)
+ "#{from_currency.to_s}->#{to_currency}"
+ end
+
+ def get_to_from_key(to_currency, from_currency)
+ "#{to_currency.to_s}->#{from_currency}"
+ end
+end
+
+class Money
+ include Comparable
+
+ class IncompatibleCurrencies < RuntimeError
+ end
+
+ def initialize(amount, currency)
+ @amount = amount
+ @currency = currency
+ end
+
+ def amount
+ @amount
+ end
+
+ def currency
+ @currency
+ end
+
+ def to_s
+ "#{"%.2f" % @amount} #{@currency.to_s}"
+ end
+
+ def in(currency, exchange_rate)
+ Money.new exchange_rate.convert(@currency, currency, @amount), currency
+ end
+
+ def *(other)
+ if other.is_a? Numeric then Money.new @amount * other, @currency
+ elsif validate(other) then Money.new @amount * other.amount, @currency
+ else nil
+ end
+ end
+
+ def /(other)
+ if (other.is_a? Money) == false then Money.new @amount / other, @currency
+ elsif validate(other) then Money.new @amount / other.amount, @currency
+ else nil
+ end
+ end
+
+ def +(other)
+ if validate(other) then Money.new @amount + other.amount, @currency
+ else nil
+ end
+ end
+
+ def -(other)
+ if validate(other) then Money.new @amount - other.amount, @currency
+ else nil
+ end
+ end
+
+ def <=>(other)
+ @amount <=> other.amount if validate(other)
+ end
+
+ private
+
+ def validate(other)
+ if !(other.is_a? Money) then raise ArgumentError
+ elsif @currency != other.currency then raise IncompatibleCurrencies
+ else true
+ end
+ end
+end