Created
October 24, 2011 18:08
-
-
Save tmtm/1309682 to your computer and use it in GitHub Desktop.
TDDBC Nagano 0.1
This file contains hidden or 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 VendingMachine | |
attr_reader :total_money | |
class Drink | |
@hash = {} | |
attr_reader :id, :price | |
def initialize(id, price) | |
@id, @price = id, price | |
end | |
def self.add(drink) | |
@hash[drink.id] = drink | |
end | |
def self.by_id(id) | |
@hash[id] | |
end | |
def self.list | |
@hash.values | |
end | |
end | |
COLA = Drink.new('cola', 120) | |
Drink.add(COLA) | |
def initialize | |
@total_money = 0 | |
@total_sales = 0 | |
@stock = { | |
'cola' => 5 | |
} | |
@cache_stock = { | |
10 => 10, | |
50 => 10, | |
100 => 10, | |
500 => 10, | |
1000 => 5, | |
} | |
end | |
def input(money) | |
unless [10, 50, 100, 500, 1000].include? money | |
raise ArgumentError, "invalid money type: #{money}" | |
end | |
@cache_stock[money] += 1 | |
@total_money += money | |
end | |
def stock(id) | |
@stock[id] | |
end | |
def cache_stock(money_type) | |
@cache_stock[money_type] | |
end | |
def buyable | |
Drink.list.each do |drink| | |
if @total_money >= drink.price && @stock[drink.id] > 0 | |
return [drink.id] | |
end | |
end | |
[] | |
end | |
def buy(id) | |
drink = Drink.by_id(id) | |
if @total_money < drink.price | |
raise '投入金額が不足しています' | |
end | |
if stock(id) <= 0 | |
raise '商品の在庫がありません' | |
end | |
balance = @total_money - drink.price | |
[1000, 500, 100, 50, 10].each do |type| | |
num = balance / type | |
@cache_stock[type] -= num | |
balance -= type * num | |
end | |
@stock[id] -= 1 | |
@total_sales += drink.price | |
@total_money = 0 | |
end | |
def sales | |
@total_sales | |
end | |
end |
This file contains hidden or 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 -*- | |
require 'vending_machine' | |
describe VendingMachine do | |
let(:vm){VendingMachine.new} | |
[10, 50, 100, 500, 1000].each do |m| | |
context "#{m}円玉を投入" do | |
it "合計金額が#{m}になる" do | |
vm.input(m) | |
vm.total_money.should == m | |
end | |
end | |
end | |
context '1円玉を投入' do | |
it 'エラーになる' do | |
expect{vm.input(1)}.to raise_error(ArgumentError, "invalid money type: 1") | |
end | |
end | |
context 'お金を複数回投入' do | |
it '#total_money が投入した全金額の合計になる' do | |
vm.input(100) | |
vm.input(500) | |
vm.input(10) | |
vm.total_money.should == 610 | |
end | |
end | |
it '在庫としてコーラ5個がある' do | |
vm.stock('cola').should == 5 | |
end | |
context '投入金額が120円未満' do | |
it '#buyable 空配列が返る' do | |
vm.input(100) | |
vm.input(10) | |
vm.buyable.should == [] | |
end | |
context '飲み物を購入する' do | |
it 'エラーになる' do | |
expect{vm.buy('cola')}.to raise_error(RuntimeError, '投入金額が不足しています') | |
end | |
end | |
end | |
context '投入金額が120円以上' do | |
before do | |
vm.input(100) | |
vm.input(10) | |
vm.input(10) | |
end | |
it '#buyable 購入可能な飲み物一覧が返る' do | |
vm.buyable.should == ['cola'] | |
end | |
context '飲み物を購入する' do | |
before do | |
vm.buy('cola') | |
end | |
it '購入した飲み物の在庫が減る' do | |
vm.stock('cola').should == 4 | |
end | |
it '売り上げ金額が加算される' do | |
vm.sales.should == 120 | |
end | |
end | |
end | |
context 'コーラが2個売れると' do | |
before do | |
vm.input(500) | |
vm.buy('cola') | |
vm.input(500) | |
vm.buy('cola') | |
end | |
it '売り上げ金額が240円になる' do | |
vm.sales.should == 240 | |
end | |
it 'コーラの在庫が3個になる' do | |
vm.stock('cola').should == 3 | |
end | |
end | |
context 'コーラが売り切れ状態で120円投入' do | |
before do | |
5.times do | |
vm.input(100) | |
vm.input(10) | |
vm.input(10) | |
vm.buy('cola') | |
end | |
vm.input(100) | |
vm.input(10) | |
vm.input(10) | |
end | |
it '#buyable が空配列' do | |
vm.buyable.should == [] | |
end | |
it '#buy がエラー' do | |
expect{vm.buy('cola')}.to raise_error(RuntimeError, '商品の在庫がありません') | |
end | |
end | |
it '現金として 1000円が5枚, 硬貨が各10枚ある' do | |
[10, 50, 100, 500].each do |m| | |
vm.cache_stock(m).should == 10 | |
end | |
vm.cache_stock(1000).should == 5 | |
end | |
context '100円玉2枚でコーラを買う' do | |
before do | |
vm.input(100) | |
vm.input(100) | |
vm.buy('cola') | |
end | |
it '現金として100円玉が12枚、50円玉が9枚, 10円玉が7枚になる' do | |
vm.cache_stock(100).should == 12 | |
vm.cache_stock(50).should == 9 | |
vm.cache_stock(10).should == 7 | |
end | |
it '投入金額が 0 になる' do | |
vm.total_money.should == 0 | |
end | |
end | |
context '10円玉が1枚しかない状態' do | |
before do | |
3.times do | |
vm.input(100) | |
vm.input(100) | |
vm.buy('cola') | |
end | |
end | |
it 'コーラを購入' do | |
vm.input(100) | |
vm.input(100) | |
expect{vm.buy('cola')}.to raise_error(RuntimeError, 'お釣りが不足しています') | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment