Created
July 9, 2011 08:55
-
-
Save anonymous/1073449 to your computer and use it in GitHub Desktop.
TDDBC TOKYO 1.5 VendingMachine
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
class Drink | |
attr_accessor :name, :price | |
def initialize(name, price) | |
self.name = name | |
self.price = price | |
end | |
end | |
class Money | |
attr_reader :value | |
end | |
[10, 50, 100, 500, 1000].each do |v| | |
klass = Class.new(Money) do | |
define_method :initialize do | |
@value = v | |
end | |
define_method :to_s do | |
"Money" + v.to_s | |
end | |
end | |
Kernel.const_set "Money#{v}", klass.new | |
end | |
class VendingMachine | |
attr_reader :amount, :sales, :charges | |
def initialize | |
@sales = 0 | |
@amount = 0 | |
cola = Drink.new "コーラ", 120 | |
redbull = Drink.new "レッドブル", 200 | |
water = Drink.new "水", 100 | |
@drink = {1 => cola, 2 => redbull, 3 => water} | |
@stock = {1 => 5, 2 => 5, 3 => 5} | |
@charges = { | |
Money10 => 10, | |
Money50 => 10, | |
Money100 => 10, | |
Money500 => 10, | |
Money1000 => 5, | |
} | |
end | |
def count_stock(id) | |
@stock[id] || 0 | |
end | |
def receive(money) | |
if money.is_a? Money | |
@amount += money.value | |
else | |
raise "変なもんいれんな" | |
end | |
ret = [] | |
@charges[money] += 1 | |
@drink.each do |id,drink| | |
if @amount >= drink.price | |
ret.push id | |
end | |
end | |
ret | |
end | |
def sell(id) | |
if @amount < @drink[id].price | |
raise "買えません" | |
end | |
if count_stock(id) <= 0 | |
raise "売り切れです" | |
end | |
oturi = @amount - @drink[id].price | |
needed = {} | |
[1000,500,100,50,10].each do |m| | |
needed[Kernel.const_get "Money#{m}"] = oturi / m | |
oturi %= m | |
end | |
if needed.any? {|k,v| v > @charges[k]} | |
raise "お釣りがありません" | |
end | |
needed.each do |k,v| | |
@charges[k] -= v | |
end | |
@sales += @drink[id].price | |
@stock[id] -= 1 | |
@amount = 0 | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
$LOAD_PATH.unshift File.dirname(__FILE__) | |
require 'vending_machine' | |
describe VendingMachine do | |
def buy_cola(just = nil) | |
if just | |
@vm.receive(Money100) | |
@vm.receive(Money10) | |
@vm.receive(Money10) | |
else | |
@vm.receive(Money500) | |
end | |
@vm.sell(1) | |
end | |
before do | |
@vm = VendingMachine.new | |
end | |
describe '#receive' do | |
context '千円札を投入すると' do | |
it '合計金額が千円' do | |
@vm.receive(Money1000) | |
@vm.amount.should == 1000 | |
end | |
it 'コーラ, レッドブル, 水が買えることを示す' do | |
@vm.receive(Money1000).should == [1, 2, 3] | |
end | |
end | |
[Money10, Money50, Money100, Money500].each do |coin| | |
context "#{coin.value}円玉を投入すると" do | |
it "合計金額が#{coin.value}円" do | |
@vm.receive(coin) | |
@vm.amount.should == coin.value | |
end | |
end | |
end | |
context '二千円札を投入すると' do | |
it 'RuntimeError が発生する' do | |
expect{@vm.receive('二千円札')}.to raise_error(RuntimeError, "変なもんいれんな") | |
end | |
end | |
context '千円札と100円玉を投入すると' do | |
it '合計金額が1100円' do | |
@vm.receive(Money1000) | |
@vm.receive(Money100) | |
@vm.amount.should == 1100 | |
end | |
end | |
context '100円玉を投入すると' do | |
it '水しか買えないことを示す' do | |
@vm.receive(Money100).should == [3] | |
end | |
end | |
context '120円を投入すると' do | |
it '水とコーラが買えることを示す' do | |
@vm.receive(Money100).should == [3] | |
@vm.receive(Money10).should == [3] | |
@vm.receive(Money10).should == [1,3] | |
end | |
end | |
end | |
describe '#count_stock' do | |
it 'コーラの在庫を返す' do | |
@vm.count_stock(1).should == 5 | |
end | |
it 'レッドブルの在庫を返す' do | |
@vm.count_stock(2).should == 5 | |
end | |
it '水の在庫を返す' do | |
@vm.count_stock(3).should == 5 | |
end | |
end | |
describe '#sell' do | |
context 'id=1 を指定すると' do | |
before do | |
buy_cola | |
end | |
it 'コーラの在庫が減る' do | |
@vm.count_stock(1).should == 4 | |
end | |
it 'おつりが返るので残金は0' do | |
@vm.amount.should == 0 | |
end | |
end | |
context "id=2 を指定すると" do | |
it "レッドブルの在庫が減る" do | |
@vm.receive(Money500) | |
@vm.sell(2) | |
@vm.count_stock(2).should == 4 | |
end | |
end | |
context '金額が足りない場合' do | |
it 'RuntimeError が発生する' do | |
@vm.receive(Money50) | |
expect{@vm.sell(1)}.to raise_error(RuntimeError, "買えません") | |
end | |
end | |
context "コーラの在庫がない場合" do | |
before do | |
5.times{ buy_cola(true) } | |
end | |
it "RuntimeError が発生する" do | |
expect{buy_cola}.to raise_error(RuntimeError, "売り切れです") | |
end | |
end | |
end | |
describe "#sales" do | |
context 'コーラを二本買った場合' do | |
before do | |
2.times { buy_cola } | |
end | |
it '売り上げ合計金額を返す' do | |
@vm.sales.should == 240 | |
end | |
end | |
end | |
describe "#charges" do | |
it "千円札5枚、硬貨はそれぞれ10枚保持している" do | |
@vm.charges.should == { | |
Money10 => 10, | |
Money50 => 10, | |
Money100 => 10, | |
Money500 => 10, | |
Money1000 => 5, | |
} | |
end | |
context "100円玉を投入すると" do | |
it "100円玉が11枚になる" do | |
@vm.receive Money100 | |
@vm.charges.should == { | |
Money10 => 10, | |
Money50 => 10, | |
Money100 => 11, | |
Money500 => 10, | |
Money1000 => 5, | |
} | |
end | |
end | |
context "500円玉を投入してコーラを買うと" do | |
it "おつり分が減る" do | |
buy_cola | |
@vm.charges.should == { | |
Money10 => 7, | |
Money50 => 9, | |
Money100 => 7, | |
Money500 => 11, | |
Money1000 => 5, | |
} | |
end | |
end | |
context "10円玉の残りが1枚で500円玉でコーラを買うと" do | |
before do | |
3.times{buy_cola} | |
end | |
it "おつりがないので RuntimeError" do | |
expect{buy_cola}.to raise_error(RuntimeError, "お釣りがありません") | |
@vm.count_stock(1).should == 2 | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment