examples/bottles.rb in surrounded-1.0.0 vs examples/bottles.rb in surrounded-1.1.0
- old
+ new
@@ -1,145 +1,135 @@
-require 'surrounded'
+require "surrounded"
+class CountdownSong
+ def initialize(max:, min:)
+ @max = max
+ @min = min
+ end
+ attr_reader :max, :min
-class Countdown
- extend Surrounded::Context
-
- initialize :singer, :number, :location
-
- trigger :start do
- singer.start
+ def sing_with(verse_template)
+ max.downto(min).map { |num| verse(num, verse_template) }
end
-
- trigger :continue do
- singer.continue
+
+ def verse(number, verse_template)
+ verse_template.lyrics(number)
end
-
- trigger :finish do
- singer.announce_status
+end
+
+class BottleVerse
+ def self.lyrics(number)
+ new(bottle_number: number).lyrics
end
-
- role :singer do
- def start
- announce_full_status
- take_action
+
+ extend Surrounded::Context
+
+ initialize :bottle_number
+
+ trigger :lyrics do
+ "#{bottle_number} of beer on the wall, ".capitalize +
+ "#{bottle_number} of beer.\n" +
+ "#{bottle_number.action}, " +
+ "#{bottle_number.successor} of beer on the wall.\n"
+ end
+
+ role :bottle_number, :wrapper do
+ def self.handles(number)
+ BottleVerse.register_bottle_role(number, self)
end
-
- def continue
- announce_status
- pause
- start
+
+ def to_s
+ "#{quantity} #{container}"
end
-
- def announce_full_status
- output %{#{location.status}, #{location.inventory}}.capitalize
+
+ def quantity
+ __getobj__.to_s
end
-
- def announce_status
- output %{#{location.status}}.capitalize
+
+ def container
+ "bottles"
end
-
- def take_action
- if location.empty?
- output %{Go to the store and get some more}
- next_part.finish
- else
- output %{#{location.subtraction}, pass it around}.capitalize
- next_part.continue
- end
+
+ def action
+ "Take #{pronoun} down and pass it around"
end
-
- def pause
- output ""
+
+ def pronoun
+ "one"
end
-
- def next_part
- context.class.new(singer, number.pred, location)
+
+ def successor
+ context.bottle_role_player(pred)
end
end
-
- role :number, :wrap do
- def name
- self.zero? ? 'no more' : to_i
+
+ # Inherit from existing role
+ def self.bottle_role(name, &block)
+ mod_name = RoleName(name)
+ klass = Class.new(BottleNumber, &block)
+ const_set(mod_name, klass)
+ end
+
+ def self.register_bottle_role(number, klass)
+ @@registry ||= Hash.new { BottleNumber }
+ @@registry[number] = klass
+ end
+
+ def bottle_role_for(number)
+ @@registry[number]
+ end
+
+ def map_role_bottle_number(num)
+ map_role(:bottle_number, bottle_role_for(num), num)
+ end
+
+ def bottle_role_player(number)
+ bottle_role_for(number).new(number)
+ end
+
+ role :bottle_number_0, :bottle_role do
+ handles 0
+
+ def quantity
+ "no more"
end
-
- def pronoun
- self == 1 ? 'it' : 'one'
+
+ def action
+ "Go to the store and buy some more"
end
-
- def container
- self == 1 ? 'bottle' : 'bottles'
+
+ def successor
+ context.bottle_role_player(99)
end
-
- def pred
- self.zero? ? 99 : super
- end
end
-
- role :location do
- def empty?
- number.zero?
+
+ role :bottle_number_1, :bottle_role do
+ handles 1
+
+ def container
+ "bottle"
end
-
- def inventory
- %{#{number.name} #{number.container} of beer}
+
+ def pronoun
+ "it"
end
-
- def status
- %{#{inventory} #{placement} #{name}}
- end
-
- def subtraction
- %{take #{number.pronoun} #{removal_strategy}}
- end
end
end
-class Location
- include Surrounded
-
- def placement
- 'on'
+class Bottles
+ def song_template(upper: 99, lower: 0)
+ CountdownSong.new(max: upper, min: lower)
end
-
- def removal_strategy
- 'off'
- end
-
- def name
- "the " + self.class.to_s.downcase
- end
-end
-class Wall < Location
- def removal_strategy
- 'down'
+ def song
+ song_template.sing_with(BottleVerse)
end
-end
-class Box < Location
- def placement
- 'in'
+ def verses(upper, lower)
+ song_template(upper: upper, lower: lower).sing_with(BottleVerse)
end
-
- def removal_strategy
- 'out'
- end
-end
-class Chorus
- include Surrounded
- def output(value)
- STDOUT.puts(value)
+ def verse(number)
+ song_template.verse(number, BottleVerse)
end
end
-class Sheet
- include Surrounded
- def output(value)
- File.open('bottles.txt', 'a') do |f|
- f.puts(value)
- end
- end
-end
-
-Countdown.new(Chorus.new, 3, Wall.new).start
-# Countdown.new(Sheet.new, 3, Box.new).start
\ No newline at end of file
+puts Bottles.new.song