Решение на Шеста задача от Петко Борджуков

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

Към профила на Петко Борджуков

Резултати

  • 4 точки от тестове
  • 0 бонус точки
  • 4 точки общо
  • 34 успешни тест(а)
  • 13 неуспешни тест(а)

Код

require 'bigdecimal'
require 'bigdecimal/util'
class ExchangeRate
class ExchangeRateUnknown < RuntimeError
end
def initialize
@rates = {}
end
def set(from_currency, to_currency, rate)
@rates[from_currency] = {to_currency => rate.to_d, from_currency => 1.to_d}
@rates[to_currency] = {from_currency => 1/(rate.to_d), to_currency => 1.to_d}
end
def get(from_currency, to_currency)
raise ExchangeRateUnknown unless @rates.include? from_currency and @rates.include? to_currency
@rates[from_currency][to_currency]
end
def convert(from_currency, to_currency, amount)
amount.to_d * get(from_currency, to_currency)
end
end
class Money
attr_reader :amount, :currency
class IncompatibleCurrencies < StandardError
end
def initialize(amount, currency)
@amount, @currency = amount.to_d, currency
end
def to_s
"%.2f %s" % [@amount, @currency]
end
def in(other_currency, exchange_rate)
converted_amount = exchange_rate.convert @currency, other_currency, @amount
Money.new converted_amount, other_currency
end
undef_method :==, :equal?, :!=
def method_missing(method, *args, &block)
if %w(<=> == equal? < > <= >= !=).include? method.to_s
enforce_comparisson_conditions_for args.first
@amount.send method, args.first.amount
else super
end
end
def *(multiplier)
enforce_multiplication_conditions_for multiplier
Money.new @amount * multiplier.to_d, @currency
end
def /(denominator)
self * (1 / denominator.to_d)
end
def +(addend)
enforce_addition_conditions_for addend
case addend
when Numeric then Money.new @amount + addend.to_d, @currency
when Money then self + addend.amount
end
end
def -@
Money.new(-@amount, @currency)
end
def -(subtrahend)
self + (-subtrahend)
end
private
def enforce_multiplication_conditions_for(object)
raise ArgumentError unless object.is_a? Numeric
end
def enforce_addition_conditions_for(object)
raise ArgumentError unless object.is_a? Numeric or object.kind_of? Money
raise IncompatibleCurrencies if object.kind_of? Money and object.currency != @currency
end
def enforce_comparisson_conditions_for(object)
raise ArgumentError unless object.kind_of? Money
raise IncompatibleCurrencies unless object.currency == @currency
end
end

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

....F..F.F..F....FF..FFF..F...F.FF.............

Failures:

  1) ExchangeRate#get returns nil for non-existing rates
     Failure/Error: rate.get(:EUR, :BGN).should be_nil
     ExchangeRate::ExchangeRateUnknown:
       ExchangeRate::ExchangeRateUnknown
     # /tmp/d20130203-23049-654za3/solution.rb:18:in `get'
     # /tmp/d20130203-23049-654za3/spec.rb:31: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) ExchangeRate#get always returns 1 as the exchange rate between two identical currencies
     Failure/Error: rate.get(:JPY, :JPY).should eq 1.to_d
     ExchangeRate::ExchangeRateUnknown:
       ExchangeRate::ExchangeRateUnknown
     # /tmp/d20130203-23049-654za3/solution.rb:18:in `get'
     # /tmp/d20130203-23049-654za3/spec.rb:45: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)>'

  3) ExchangeRate#convert raises an ExchangeRate::Unknown exception when the rate is not defined
     Failure/Error: end.to raise_error(ExchangeRate::Unknown)
     NameError:
       uninitialized constant ExchangeRate::Unknown
     # /tmp/d20130203-23049-654za3/spec.rb:58: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)>'

  4) ExchangeRate#convert works for identical currencies without defining any rates
     Failure/Error: rate.convert(:JPY, :JPY, 123.to_d).should eq 123.to_d
     ExchangeRate::ExchangeRateUnknown:
       ExchangeRate::ExchangeRateUnknown
     # /tmp/d20130203-23049-654za3/solution.rb:18:in `get'
     # /tmp/d20130203-23049-654za3/solution.rb:23:in `convert'
     # /tmp/d20130203-23049-654za3/spec.rb:72: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)>'

  5) Money convertion does not change the amount if the same currency is passed
     Failure/Error: Money.new(5.to_d, :EUR).in(:EUR, ExchangeRate.new).amount.should eq 5.to_d
     ExchangeRate::ExchangeRateUnknown:
       ExchangeRate::ExchangeRateUnknown
     # /tmp/d20130203-23049-654za3/solution.rb:18:in `get'
     # /tmp/d20130203-23049-654za3/solution.rb:23:in `convert'
     # /tmp/d20130203-23049-654za3/solution.rb:42:in `in'
     # /tmp/d20130203-23049-654za3/spec.rb:107: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)>'

  6) Money convertion raises an ExchangeRate::Unknown exception for unknown rates
     Failure/Error: end.to raise_error(ExchangeRate::Unknown)
     NameError:
       uninitialized constant ExchangeRate::Unknown
     # /tmp/d20130203-23049-654za3/spec.rb:113: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)>'

  7) Money arithmetic allows / with a numeric
     Failure/Error: result.amount.should eq bucks.amount.public_send(operation, numeric)
       
       expected: #<BigDecimal:93a0364,'0.1190476190 47619048E0',18(36)>
            got: #<BigDecimal:93a03f0,'0.1190476190 4761905E0',18(45)>
       
       (compared using ==)
     # /tmp/d20130203-23049-654za3/spec.rb:125: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)>'

  8) Money arithmetic / with money objects raises an ArgumentError
     Failure/Error: expect do
       expected ArgumentError, got #<NoMethodError: undefined method `to_d' for 5.00 USD:Money>
     # /tmp/d20130203-23049-654za3/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)>'

  9) Money arithmetic + with numeric objects raises an ArgumentError
     Failure/Error: expect do
       expected ArgumentError but nothing was raised
     # /tmp/d20130203-23049-654za3/spec.rb:137: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)>'

  10) Money arithmetic - with numeric objects raises an ArgumentError
     Failure/Error: expect do
       expected ArgumentError but nothing was raised
     # /tmp/d20130203-23049-654za3/spec.rb:137: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)>'

  11) Money arithmetic - with other objects raises an ArgumentError
     Failure/Error: expect do
       expected ArgumentError, got #<NoMethodError: undefined method `-@' for "foobar":String>
     # /tmp/d20130203-23049-654za3/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)>'

  12) Money arithmetic / with other objects raises an ArgumentError
     Failure/Error: expect do
       expected ArgumentError but nothing was raised
     # /tmp/d20130203-23049-654za3/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)>'

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

Failed examples:

rspec /tmp/d20130203-23049-654za3/spec.rb:30 # ExchangeRate#get returns nil for non-existing rates
rspec /tmp/d20130203-23049-654za3/spec.rb:44 # ExchangeRate#get always returns 1 as the exchange rate between two identical currencies
rspec /tmp/d20130203-23049-654za3/spec.rb:55 # ExchangeRate#convert raises an ExchangeRate::Unknown exception when the rate is not defined
rspec /tmp/d20130203-23049-654za3/spec.rb:71 # ExchangeRate#convert works for identical currencies without defining any rates
rspec /tmp/d20130203-23049-654za3/spec.rb:106 # Money convertion does not change the amount if the same currency is passed
rspec /tmp/d20130203-23049-654za3/spec.rb:110 # Money convertion raises an ExchangeRate::Unknown exception for unknown rates
rspec /tmp/d20130203-23049-654za3/spec.rb:119 # Money arithmetic allows / with a numeric
rspec /tmp/d20130203-23049-654za3/spec.rb:128 # Money arithmetic / with money objects raises an ArgumentError
rspec /tmp/d20130203-23049-654za3/spec.rb:136 # Money arithmetic + with numeric objects raises an ArgumentError
rspec /tmp/d20130203-23049-654za3/spec.rb:136 # Money arithmetic - with numeric objects raises an ArgumentError
rspec /tmp/d20130203-23049-654za3/spec.rb:159 # Money arithmetic - with other objects raises an ArgumentError
rspec /tmp/d20130203-23049-654za3/spec.rb:159 # Money arithmetic / with other objects raises an ArgumentError
rspec /tmp/d20130203-23049-654za3/spec.rb:168 # Money comparison works when currencies are the same

История (3 версии и 2 коментара)

Петко обнови решението на 13.01.2013 14:27 (преди над 11 години)

+require 'bigdecimal'
+require 'bigdecimal/util'
+
+class ExchangeRate
+ class ExchangeRateUnknown < RuntimeError
+ end
+
+ def initialize
+ @rates = {}
+ end
+
+ def set(from_currency, to_currency, rate)
+ @rates[from_currency] = {to_currency => rate.to_d, from_currency => 1.to_d}
+ @rates[to_currency] = {to_currency => 1/(rate.to_d), to_currency => 1.to_d}
+ end
+
+ def get(from_currency, to_currency)
+ raise ExchangeRateUnknown unless @rates.include? from_currency and @rates.include? to_currency
+ @rates[from_currency][to_currency]
+ end
+
+ def convert(from_currency, to_currency, amount)
+ amount.to_d * get(from_currency, to_currency)
+ end
+end
+
+class Money
+ attr_reader :amount, :currency
+
+ class IncompatibleCurrencies < StandardError
+ end
+
+ def initialize(amount, currency)
+ @amount, @currency = amount.to_d, currency
+ end
+
+ def to_s
+ "%.2f %s" % [@amount, @currency]
+ end
+
+ def in(other_currency, exchange_rate)
+ converted_amount = exchange_rate.convert @currency, other_currency, @amount
+ Money.new converted_amount, other_currency
+ end
+
+ undef_method :==, :equal?, :!=
+ def method_missing(method, *args, &block)
+ if %w(<=> == equal? < > <= >= !=).include? method.to_s
+ raise ArgumentError unless args.first.kind_of? Money
+ raise IncompatibleCurrencies unless args.first.currency == @currency
+ @amount.send method, args.first.amount
+ end
+ end
+
+ def *(multiplier)
+ raise ArgumentError unless multiplier.is_a? Numeric
+ Money.new @amount * multiplier.to_d, @currency
+ end
+
+ def /(denominator)
+ self * (1 / denominator.to_d)
+ end
+
+ def +(addend)
+ if addend.is_a? Numeric then add_numeric addend
+ elsif addend.kind_of? Money then add_money addend
+ else raise ArgumentError
+ end
+ end
+
+ def -@
+ Money.new(-@amount, @currency)
+ end
+
+ def -(subtrahend)
+ self + (-subtrahend)
+ end
+
+ private
+ def add_numeric(addend)
+ Money.new @amount + addend.to_d, @currency
+ end
+
+ def add_money(addend)
+ raise IncompatibleCurrencies unless @currency == addend.currency
+ add_numeric addend.amount
+ end
+end

Петко обнови решението на 13.01.2013 14:53 (преди над 11 години)

require 'bigdecimal'
require 'bigdecimal/util'
class ExchangeRate
class ExchangeRateUnknown < RuntimeError
end
def initialize
@rates = {}
end
def set(from_currency, to_currency, rate)
@rates[from_currency] = {to_currency => rate.to_d, from_currency => 1.to_d}
@rates[to_currency] = {to_currency => 1/(rate.to_d), to_currency => 1.to_d}
end
def get(from_currency, to_currency)
raise ExchangeRateUnknown unless @rates.include? from_currency and @rates.include? to_currency
@rates[from_currency][to_currency]
end
def convert(from_currency, to_currency, amount)
amount.to_d * get(from_currency, to_currency)
end
end
class Money
attr_reader :amount, :currency
class IncompatibleCurrencies < StandardError
end
def initialize(amount, currency)
@amount, @currency = amount.to_d, currency
end
def to_s
"%.2f %s" % [@amount, @currency]
end
def in(other_currency, exchange_rate)
converted_amount = exchange_rate.convert @currency, other_currency, @amount
Money.new converted_amount, other_currency
end
undef_method :==, :equal?, :!=
def method_missing(method, *args, &block)
if %w(<=> == equal? < > <= >= !=).include? method.to_s
- raise ArgumentError unless args.first.kind_of? Money
- raise IncompatibleCurrencies unless args.first.currency == @currency
+ enforce_comparisson_conditions_for args.first
@amount.send method, args.first.amount
+ else super
end
end
def *(multiplier)
- raise ArgumentError unless multiplier.is_a? Numeric
+ enforce_multiplication_conditions_for multiplier
Money.new @amount * multiplier.to_d, @currency
end
def /(denominator)
self * (1 / denominator.to_d)
end
def +(addend)
- if addend.is_a? Numeric then add_numeric addend
- elsif addend.kind_of? Money then add_money addend
- else raise ArgumentError
+ enforce_addition_conditions_for addend
+ case addend
+ when Numeric then Money.new @amount + addend.to_d, @currency
+ when Money then self + addend.amount
end
end
def -@
Money.new(-@amount, @currency)
end
def -(subtrahend)
self + (-subtrahend)
end
private
- def add_numeric(addend)
- Money.new @amount + addend.to_d, @currency
+
+ def enforce_multiplication_conditions_for(object)
+ raise ArgumentError unless object.is_a? Numeric
end
- def add_money(addend)
- raise IncompatibleCurrencies unless @currency == addend.currency
- add_numeric addend.amount
+ def enforce_addition_conditions_for(object)
+ raise ArgumentError unless object.is_a? Numeric or object.kind_of? Money
+ raise IncompatibleCurrencies if object.kind_of? Money and object.currency != @currency
+ end
+
+ def enforce_comparisson_conditions_for(object)
+ raise ArgumentError unless object.kind_of? Money
+ raise IncompatibleCurrencies unless object.currency == @currency
end
end

Петко обнови решението на 13.01.2013 15:51 (преди над 11 години)

require 'bigdecimal'
require 'bigdecimal/util'
class ExchangeRate
class ExchangeRateUnknown < RuntimeError
end
def initialize
@rates = {}
end
def set(from_currency, to_currency, rate)
@rates[from_currency] = {to_currency => rate.to_d, from_currency => 1.to_d}
- @rates[to_currency] = {to_currency => 1/(rate.to_d), to_currency => 1.to_d}
+ @rates[to_currency] = {from_currency => 1/(rate.to_d), to_currency => 1.to_d}
end
def get(from_currency, to_currency)
raise ExchangeRateUnknown unless @rates.include? from_currency and @rates.include? to_currency
@rates[from_currency][to_currency]
end
def convert(from_currency, to_currency, amount)
amount.to_d * get(from_currency, to_currency)
end
end
class Money
attr_reader :amount, :currency
class IncompatibleCurrencies < StandardError
end
def initialize(amount, currency)
@amount, @currency = amount.to_d, currency
end
def to_s
"%.2f %s" % [@amount, @currency]
end
def in(other_currency, exchange_rate)
converted_amount = exchange_rate.convert @currency, other_currency, @amount
Money.new converted_amount, other_currency
end
undef_method :==, :equal?, :!=
def method_missing(method, *args, &block)
if %w(<=> == equal? < > <= >= !=).include? method.to_s
enforce_comparisson_conditions_for args.first
@amount.send method, args.first.amount
else super
end
end
def *(multiplier)
enforce_multiplication_conditions_for multiplier
Money.new @amount * multiplier.to_d, @currency
end
def /(denominator)
self * (1 / denominator.to_d)
end
def +(addend)
enforce_addition_conditions_for addend
case addend
when Numeric then Money.new @amount + addend.to_d, @currency
when Money then self + addend.amount
end
end
def -@
Money.new(-@amount, @currency)
end
def -(subtrahend)
self + (-subtrahend)
end
private
def enforce_multiplication_conditions_for(object)
raise ArgumentError unless object.is_a? Numeric
end
def enforce_addition_conditions_for(object)
raise ArgumentError unless object.is_a? Numeric or object.kind_of? Money
raise IncompatibleCurrencies if object.kind_of? Money and object.currency != @currency
end
def enforce_comparisson_conditions_for(object)
raise ArgumentError unless object.kind_of? Money
raise IncompatibleCurrencies unless object.currency == @currency
end
end