Илиян обнови решението на 12.01.2013 18:50 (преди около 12 години)
+require 'bigdecimal'
+require 'bigdecimal/util'
+
+class ExchangeRate
+ def initialize()
+ @exchange_courses = {}
+ #@exchange_courses = Hash.new { |hash, key| hash[key] = Hash.new }
+ end
+
+ def set(from_currency, to_currency, rate)
+ @exchange_courses[from_currency]||={} #
+ @exchange_courses[to_currency]||={} #
+ @exchange_courses[from_currency][to_currency] = rate
+ @exchange_courses[to_currency][from_currency] = 1.to_d / rate
+ end
+
+ def get(from_currency, to_currency)
+ return 1.to_d if from_currency == to_currency
+ return nil if @exchange_courses[from_currency].nil? #
+ @exchange_courses[from_currency][to_currency]
+ end
+
+ def convert(from_currency, to_currency, amount)
+ rate = get(from_currency, to_currency)
+
+ raise Unknown.new() if rate.nil?
+
+ rate * amount
+ end
+
+ class Unknown < RuntimeError
+ end
+end
+
+class Money
+ include Comparable
+
+ attr_reader :amount, :currency
+
+ def initialize(amount, currency)
+ @amount = amount
+ @currency = currency
+ end
+
+ def to_s
+ "%.02f %s" % [amount, currency.to_s]
+ end
+
+ def in(currency, exchange_rate)
+ Money.new exchange_rate.convert(self.currency, currency, amount), currency
+ end
+
+ def *(number)
+ expect_kind_of Numeric, number
+
+ Money.new amount * number, currency
+ end
+
+ def /(number)
+ expect_kind_of Numeric, number
+
+ Money.new amount / number, currency
+ end
+
+ def +(other)
+ #expect_kind_of other, self.class
+ expect_same_class_like other and expect_same_currency_like other
+
+ Money.new amount + other.amount, currency
+ end
+
+ def -(other)
+ #expect_kind_of other, self.class
+ expect_same_class_like other and expect_same_currency_like other
+
+ Money.new amount - other.amount, currency
+ end
+
+ def <=>(other)
+ #expect_kind_of other, self.class
+ expect_same_class_like other and expect_same_currency_like other
+
+ if amount < other.amount then -1
+ elsif amount > other.amount then 1
+ elsif amount == other.amount then 0
+ else nil
+ end
+ end
+
+ private
+
+ def expect_kind_of(klass, other)
+ raise ArgumentError if not other.kind_of? klass
+ true
+ end
+
+ def expect_same_class_like(other)
+ raise ArgumentError if not instance_of? other.class
+ true
+ end
+
+ def expect_same_currency_like(other)
+ raise IncompatibleCurrencies if currency != other.currency
+ true
+ end
+
+ class IncompatibleCurrencies
+ end
+end