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

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

Към профила на Георги Гърдев

Резултати

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

Код

require 'bigdecimal'
require 'bigdecimal/util'
class Rate
attr_accessor :rate
def initialize(from, to, rate)
@currencies = [] << from << to
@rate = rate
end
def is_between?(first, second)
@currencies.include? first and @currencies.include? second
end
def convert(currency, amount)
if @currencies[0] == currency
@rate * amount
elsif @currencies[1] == currency
(1 / @rate) * amount
end
end
def get_rate(from, to)
return false unless is_between?(from, to)
@currencies[0] == from ? @rate : 1 / @rate
end
end
class ExchangeRate
def initialize
@rates = []
end
def set(from, to, rate)
return nil if from == to
if find_rate(from, to).nil? then @rates << Rate.new(from, to, rate)
else find_rate(from, to).rate = rate
end
end
def get(from, to)
return 1.to_d if from == to
rate = find_rate(from, to)
rate.nil? ? rate : rate.get_rate(from, to)
end
def convert(from, to, amount)
return amount if from == to
rate = find_rate(from, to)
raise Unknown if rate.nil?
rate.convert(from, amount)
end
private
def find_rate(from, to)
@rates.each { |rate| return rate if rate.is_between?(from, to) }
nil
end
class Unknown < RuntimeError
end
end
class Money
attr_accessor :amount, :currency
def initialize(amount, currency)
@amount, @currency = amount, currency
end
def to_s
"#{"%.2f" % amount.to_f} #{currency.to_s}"
end
def *(other)
if other.kind_of? Numeric
Money.new (@amount * other), @currency
end
end
def /(other)
if other.kind_of? Numeric
Money.new (@amount / other), @currency
end
end
def ==(other)
type_check(other)
@amount == other.amount
end
def method_missing(method, *args)
p "here"
type_check(args[0]) if [:+, :-, :<=>, :<, :<=, :>, :>=].include? method
if [:+, :-].include?(method) then Money.new @amount.send(method, args[0].amount), @currency
elsif [:<=>, :<, :<=, :>, :>=].include?(method) then @amount.send(method, args[0].amount)
else super
end
end
def in(new_currency, exchange_rate)
new_amount = exchange_rate.convert(@currency, new_currency, @amount)
Money.new new_amount.to_d, new_currency
end
private
def type_check(other)
raise ArgumentError if other.class != self.class
raise IncompatibleCurrencies if currency != other.currency
end
class IncompatibleCurrencies < Exception
end
end

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

...F................F.F"here"
."here"
."here"
."here"
."here"
."here"
."here"
."here"
.FF"here"
"here"
F....."here"
."here"
."here"
."here"
."here"
."here"
."here"
."here"
.

Failures:

  1) ExchangeRate#set sets the exchange rate in both directions
     Failure/Error: rate.get(:EUR, :BGN).should eq '1.25'.to_d
       
       expected: #<BigDecimal:9013930,'0.125E1',18(18)>
            got: #<BigDecimal:9013a5c,'0.8E0',9(18)>
       
       (compared using ==)
     # /tmp/d20130203-23049-1wxio1t/spec.rb:25: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)>'

  2) Money arithmetic * with money objects raises an ArgumentError
     Failure/Error: expect do
       expected ArgumentError but nothing was raised
     # /tmp/d20130203-23049-1wxio1t/spec.rb:129:in `block (4 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 arithmetic / with money objects raises an ArgumentError
     Failure/Error: expect do
       expected ArgumentError but nothing was raised
     # /tmp/d20130203-23049-1wxio1t/spec.rb:129:in `block (4 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)>'

  4) Money arithmetic * with other objects raises an ArgumentError
     Failure/Error: expect do
       expected ArgumentError but nothing was raised
     # /tmp/d20130203-23049-1wxio1t/spec.rb:160:in `block (4 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)>'

  5) Money arithmetic / with other objects raises an ArgumentError
     Failure/Error: expect do
       expected ArgumentError but nothing was raised
     # /tmp/d20130203-23049-1wxio1t/spec.rb:160:in `block (4 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)>'

  6) Money comparison works when currencies are the same
     Failure/Error: (a <=> b).should eq 1
       
       expected: 1
            got: nil
       
       (compared using ==)
     # /tmp/d20130203-23049-1wxio1t/spec.rb:174: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.07818 seconds
47 examples, 6 failures

Failed examples:

rspec /tmp/d20130203-23049-1wxio1t/spec.rb:21 # ExchangeRate#set sets the exchange rate in both directions
rspec /tmp/d20130203-23049-1wxio1t/spec.rb:128 # Money arithmetic * with money objects raises an ArgumentError
rspec /tmp/d20130203-23049-1wxio1t/spec.rb:128 # Money arithmetic / with money objects raises an ArgumentError
rspec /tmp/d20130203-23049-1wxio1t/spec.rb:159 # Money arithmetic * with other objects raises an ArgumentError
rspec /tmp/d20130203-23049-1wxio1t/spec.rb:159 # Money arithmetic / with other objects raises an ArgumentError
rspec /tmp/d20130203-23049-1wxio1t/spec.rb:168 # Money comparison works when currencies are the same

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

Георги обнови решението на 15.01.2013 00:38 (преди около 12 години)

+require 'bigdecimal'
+require 'bigdecimal/util'
+
+class Rate
+ attr_accessor :rate
+
+ def initialize(from, to, rate)
+ @currencies = [] << from << to
+ @rate = rate
+ end
+
+ def is_between?(first, second)
+ @currencies.include? first and @currencies.include? second
+ end
+
+ def convert(currency, amount)
+ if @currencies[0] == currency
+ @rate * amount
+ elsif @currencies[1] == currency
+ (1 / @rate) * amount
+ end
+ end
+
+ def get_rate(from, to)
+ return false unless is_between?(from, to)
+ @currencies[0] == from ? @rate : 1 / @rate
+ end
+end
+
+class ExchangeRate
+ def initialize
+ @rates = []
+ end
+
+ def set(from, to, rate)
+ return nil if from == to
+ if find_rate(from, to).nil? then @rates << Rate.new(from, to, rate)
+ else find_rate(from, to).rate = rate
+ end
+ end
+
+ def get(from, to)
+ return 1.to_d if from == to
+ rate = find_rate(from, to)
+ rate.nil? ? rate : rate.get_rate(from, to)
+ end
+
+ def convert(from, to, amount)
+ return amount if from == to
+ rate = find_rate(from, to)
+ raise Unknown if rate.nil?
+ rate.convert(from, amount)
+ end
+
+ private
+
+ def find_rate(from, to)
+ @rates.each { |rate| return rate if rate.is_between?(from, to) }
+ nil
+ end
+
+ class Unknown < RuntimeError
+ end
+end
+
+class Money
+ attr_accessor :amount, :currency
+
+ def initialize(amount, currency)
+ @amount, @currency = amount, currency
+ end
+
+ def to_s
+ "#{"%.2f" % amount.to_f} #{currency.to_s}"
+ end
+
+ def *(other)
+ if other.kind_of? Numeric
+ Money.new (@amount * other), @currency
+ end
+ end
+
+ def /(other)
+ if other.kind_of? Numeric
+ Money.new (@amount / other), @currency
+ end
+ end
+
+ def ==(other)
+ type_check(other)
+
+ @amount == other.amount
+ end
+
+ def method_missing(method, *args)
+ p "here"
+ type_check(args[0]) if [:+, :-, :<=>, :<, :<=, :>, :>=].include? method
+
+ if [:+, :-].include?(method) then Money.new @amount.send(method, args[0].amount), @currency
+ elsif [:<=>, :<, :<=, :>, :>=].include?(method) then @amount.send(method, args[0].amount)
+ else super
+ end
+ end
+
+ def in(new_currency, exchange_rate)
+ new_amount = exchange_rate.convert(@currency, new_currency, @amount)
+ Money.new new_amount.to_d, new_currency
+ end
+
+ private
+
+ def type_check(other)
+ raise ArgumentError if other.class != self.class
+ raise IncompatibleCurrencies if currency != other.currency
+ end
+
+ class IncompatibleCurrencies < Exception
+ end
+end