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