fortune_teller 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.txt CHANGED
@@ -1,5 +1,13 @@
1
- Total hack of a commandline Ruby version of an origami fortune teller:
2
- http://en.wikipedia.org/wiki/Paper_fortune_teller
1
+ What?
2
+ A total hack
3
+ A Ruby-based commandline version of an origami fortune-teller:
4
+ http://en.wikipedia.org/wiki/Paper_fortune_teller
5
+
6
+ Why?
7
+ Cuz my kids were making paper fortune-tellers and I thought I'd
8
+ inspire them with a little computer-science
9
+ (so far they just like that I can change my fortune-teller faster than
10
+ they can)
3
11
 
4
12
  To use it simply...
5
13
  install it:
@@ -27,6 +35,22 @@ At which point, you type your selection, followed by pressing the
27
35
  enter-key
28
36
  ...it's that easy.
29
37
 
38
+ To integrate with your own code...
39
+ require 'fortune_teller'
40
+
41
+ And have fun (see FortuneTeller::Game.run):
42
+
43
+ # array of array of strings
44
+ selection_groups = FortuneTeller::Game::DEFAULT_SELECTION_GROUPS.map(&:call)
45
+
46
+ # array of strings
47
+ fortunes = FortuneTeller::Game::DEFAULT_FORTUNES
48
+
49
+ # options include the :ui to use, default is CliUi
50
+
51
+ game = FortuneTeller::Game.new( selection_groups, fortunes, options )
52
+
53
+ game.run
54
+
30
55
  TODO:
31
- custom fortune-teller
32
- graphics
56
+ confirm (i.e. create proof-of-concept) that modularized & injected dependencies (i.e. :ui) work w/ Commandline, Ruby, Rubygame, etc...
@@ -8,4 +8,4 @@ rescue LoadError
8
8
  require_relative "../lib/fortune_teller"
9
9
  end
10
10
 
11
- FortuneTeller::Game.new.run
11
+ FortuneTeller::Game.run
@@ -1,62 +1,3 @@
1
- require_relative "fortune_teller/chooser"
1
+ require_relative "fortune_teller/game"
2
2
  module FortuneTeller
3
- class Game
4
- def jail_reveal
5
- Reveal.new( "Oops, you're in Jail!" )
6
- end
7
-
8
- def mud_reveal
9
- Reveal.new( "Oops, you're in the mud!" )
10
- end
11
-
12
- def cookie_reveal
13
- Reveal.new( "Wow, you get a cookie!" )
14
- end
15
-
16
- def final_choices
17
- @final_choices ||= [
18
- Panel.new( "blue", choice([jail_reveal, mud_reveal, cookie_reveal]) ),
19
- Panel.new( "green", choice([jail_reveal, mud_reveal, cookie_reveal]) ),
20
- Panel.new( "pink", choice([jail_reveal, mud_reveal, cookie_reveal]) ),
21
- ]
22
- end
23
-
24
- def final_choice_1
25
- @final_choice_1 ||= choice(final_choices)
26
- end
27
-
28
- def final_choice_2
29
- @final_choice_2 ||= choice(final_choices - [ final_choice_1 ])
30
- end
31
-
32
- def choice(choices)
33
- choices[rand(choices.size)]
34
- end
35
-
36
- def level_three_chooser
37
- Chooser.new( final_choice_1, final_choice_2 )
38
- end
39
-
40
- def level_two_chooser
41
- Chooser.new(
42
- Panel.new( "9", level_three_chooser ),
43
- Panel.new( "7", level_three_chooser ),
44
- Panel.new( "3", level_three_chooser ),
45
- Panel.new( "5", level_three_chooser ),
46
- )
47
- end
48
-
49
- def level_one_chooser
50
- Chooser.new(
51
- Panel.new( "bird", level_two_chooser ),
52
- Panel.new( "dog", level_two_chooser ),
53
- Panel.new( "chicken", level_two_chooser ),
54
- Panel.new( "mouse", level_two_chooser )
55
- )
56
- end
57
-
58
- def run
59
- level_one_chooser.choose
60
- end
61
- end
62
3
  end
@@ -3,16 +3,34 @@ require_relative "logger"
3
3
  module FortuneTeller
4
4
  class Chooser
5
5
  LOCATIONS = [ :tl, :tr, :bl, :br ]
6
+
7
+ def self.subset(list, num=list.size)
8
+ Logger.log("got list: #{list.inspect}, num: #{num.inspect}")
9
+ choices = list.dup
10
+ num.times.collect {|num|
11
+ reduce_choices!(choices)
12
+ }
13
+ end
14
+
15
+ def self.reduce_choices!( choices, by=random_choice(choices) )
16
+ choices.delete(by)
17
+ end
18
+
19
+ def self.random_choice(choices)
20
+ choices[rand(choices.size)]
21
+ end
22
+
6
23
  attr_reader :tl_panel, :tr_panel, :bl_panel, :br_panel
7
- attr_reader :list_renderer
8
- def initialize(_tl_panel, _tr_panel, _bl_panel = nil, _br_panel = nil, options = {})
24
+ attr_reader :list_renderer, :ui
25
+ def initialize(_tl_panel, _tr_panel, options = {})
26
+ @ui = options[:ui]
9
27
  @tl_panel = _tl_panel
10
28
  Logger.log "tl_panel: #{@tl_panel}"
11
29
  @tr_panel = _tr_panel
12
30
  Logger.log "tr_panel: #{@tr_panel}"
13
- @bl_panel = _bl_panel || NilPanel.new
31
+ @bl_panel = options[:bl_panel] || NilPanel.new(@ui)
14
32
  Logger.log "bl_panel: #{@bl_panel}"
15
- @br_panel = _br_panel || NilPanel.new
33
+ @br_panel = options[:br_panel] || NilPanel.new(@ui)
16
34
  Logger.log "br_panel: #{@br_panel}"
17
35
  @list_renderer = options[:list_renderer] || ListRenderer.new
18
36
  define_selection_aliases
@@ -52,32 +70,23 @@ module FortuneTeller
52
70
  def choose
53
71
  choice = nil
54
72
  begin
55
- self.class.clear_screen
56
- choice = self.class.prompt( list_renderer.render( selections | [:exit] ) )
73
+ ui.clear_screen
74
+ choice = ui.prompt( list_renderer.render( selections | [:exit] ) )
57
75
  Logger.log("got: #{choice.inspect}")
58
76
  end until( valid?( choice ) )
59
77
  Logger.log("trying it...")
60
- self.class.clear_screen(1)
78
+ ui.clear_screen(1)
79
+ # need to unalias methods...
61
80
  send( choice )
62
81
  end
63
82
 
64
- def self.clear_screen( after = 0 )
65
- sleep( after )
66
- puts "\e[H\e[2J"
67
- end
68
-
69
83
  LOCATIONS.each do |location|
70
84
  define_method(location) {
71
- send( "#{location}_panel" ).pick
85
+ send( "#{location}_panel" ).tap do |panel|
86
+ panel.pick
87
+ end
72
88
  }
73
89
  end
74
-
75
- def self.prompt(text)
76
- print text
77
- gets.chomp.tap do |result|
78
- puts
79
- end
80
- end
81
90
  end
82
91
  end
83
92
  require_relative "panel"
@@ -0,0 +1,51 @@
1
+ module FortuneTeller
2
+ class CliUi
3
+ DEFAULT_SOUND_FILE = 'flick_flick.ogg'.freeze
4
+ attr_reader :game, :sound_file
5
+ def initialize( options = {} )
6
+ @game = options[ :game ]
7
+ @sound_file = options[ :sound_file ] || DEFAULT_SOUND_FILE
8
+ end
9
+
10
+ def prompt(text)
11
+ print text
12
+ gets.chomp.tap do |result|
13
+ display
14
+ end
15
+ end
16
+
17
+ def exit( message = nil )
18
+ display( message )
19
+ Kernel.exit
20
+ end
21
+
22
+ def display( text = nil )
23
+ puts text
24
+ end
25
+
26
+ def interstitial( text )
27
+ display text
28
+ play
29
+ sleep(1.2)
30
+ end
31
+
32
+ def clear_screen( after = 0 )
33
+ sleep( after )
34
+ display "\e[H\e[2J"
35
+ end
36
+
37
+ def play
38
+ sound.play
39
+ end
40
+
41
+ def sound
42
+ @sound ||= begin
43
+ require "rubygame"
44
+ if defined?(Rubygame::Sound)
45
+ Rubygame::Sound.load(sound_file)
46
+ end
47
+ rescue
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,101 @@
1
+ require_relative "chooser"
2
+ require_relative "cli_ui"
3
+ module FortuneTeller
4
+ class Game
5
+ DEFAULT_SELECTION_GROUPS = [
6
+ lambda { Chooser.subset([ "dog", "chicken", "mouse", "cat", "dragon", "turtle", "tiger", "snake", "monkey" ], 4) },
7
+ lambda { Chooser.subset([ "3", "9", "5", "7", "10", "27", "100" ], 4) },
8
+ lambda { Chooser.subset([ "pink", "green", "blue", "yellow" ], 2) },
9
+ ].freeze
10
+
11
+ DEFAULT_FORTUNES = [
12
+ "Oops, you're in Jail!",
13
+ "Yuck, you're in the mud!",
14
+ "Wow, you get a cookie!",
15
+ "Ouch, you got bit!",
16
+ "Hey, you get a hug!",
17
+ ].freeze
18
+
19
+ def self.run( options = {} )
20
+ options[:selection_groups] ||= DEFAULT_SELECTION_GROUPS.map(&:call)
21
+ options[:fortunes] ||= DEFAULT_FORTUNES
22
+ new( options.delete(:selection_groups), options.delete(:fortunes), options ).run
23
+ end
24
+
25
+ attr_reader :selection_groups, :fortunes
26
+ attr_reader :chooser_class, :reveal_class, :panel_class
27
+ attr_reader :chooser_options
28
+ attr_reader :ui
29
+ def initialize( selection_groups, fortunes, options = {} )
30
+ @original_selection_groups = selection_groups
31
+ @original_fortunes = fortunes
32
+
33
+ @ui = options[:ui] || CliUi.new(:game => self)
34
+
35
+ @chooser_class = options[:choose_class] || Chooser
36
+ @reveal_class = options[:reveal_class] || Reveal
37
+ @panel_class = options[:panel_class] || Panel
38
+ @chooser_options = options[:chooser_options] || {}
39
+ @chooser_options[:ui] ||= ui
40
+
41
+ reset
42
+ end
43
+
44
+ def restart
45
+ reset
46
+ run
47
+ end
48
+
49
+ def reset
50
+ @fortunes = @original_fortunes.dup
51
+ @selection_groups = @original_selection_groups.dup
52
+ end
53
+
54
+ def run
55
+ chooser_tree.choose
56
+ end
57
+
58
+
59
+ private
60
+
61
+ def fortune_reveals
62
+ @fortune_reveals ||= fortunes.map { |fortune|
63
+ reveal_class.new( fortune, :ui => ui )
64
+ }
65
+ end
66
+
67
+ def final_choices
68
+ @final_choices ||= selection_groups.pop.map { |selection|
69
+ Logger.log("fc-selection: #{selection.inspect}")
70
+ panel_class.new( selection, :reveal => chooser_class.reduce_choices!(fortune_reveals), :ui => ui )
71
+ }
72
+ end
73
+
74
+ def final_chooser
75
+ @final_chooser ||= chooser_class.new( chooser_class.reduce_choices!(final_choices), chooser_class.reduce_choices!(final_choices), chooser_options )
76
+ end
77
+
78
+ def chooser_tree
79
+ @chooser_tree ||= generate_choosers
80
+ end
81
+
82
+
83
+ def generate_choosers
84
+ choosers = [ final_chooser ]
85
+ begin
86
+ panels = []
87
+ if selection_group = selection_groups.pop
88
+ selection_group.each do |selection|
89
+ panels << panel_class.new( selection, :reveal => choosers.first, :ui => ui )
90
+ end
91
+ end
92
+ chooser_params = panels.pop, panels.pop
93
+ chooser_options[:bl_panel] = panels.pop if panels.first
94
+ chooser_options[:br_panel] = panels.pop if panels.first
95
+ chooser_params << chooser_options
96
+ choosers.unshift chooser_class.new( *chooser_params )
97
+ end until [] == selection_groups
98
+ return choosers.first
99
+ end
100
+ end
101
+ end
@@ -1,5 +1,9 @@
1
1
  module FortuneTeller
2
2
  class NilPanel
3
+ attr_reader :ui
4
+ def initialize(ui)
5
+ @ui = ui
6
+ end
3
7
  def to_s
4
8
  ""
5
9
  end
@@ -9,11 +13,11 @@ module FortuneTeller
9
13
  end
10
14
 
11
15
  def pick
12
- Kernel.exit
16
+ ui.exit
13
17
  end
14
18
 
15
19
  def choose
16
- Kernel.exit
20
+ ui.exit
17
21
  end
18
22
  end
19
23
  end
@@ -3,9 +3,11 @@ module FortuneTeller
3
3
  class Panel
4
4
  attr_reader :label
5
5
  attr_accessor :reveal
6
- def initialize(_label, _reveal = nil )
7
- @label = _label
8
- @reveal = _reveal ||= NilPanel.new
6
+ attr_accessor :ui
7
+ def initialize(label, options = {} )
8
+ @label = label
9
+ @ui = options[:ui]
10
+ @reveal = options[:reveal] || NilPanel.new(@ui)
9
11
  end
10
12
  alias_method :to_s, :label
11
13
 
@@ -14,23 +16,10 @@ module FortuneTeller
14
16
  end
15
17
 
16
18
  def pick
17
- puts "Flick, flick, flick, flick...\n"
18
- sound.play
19
- sleep(1.2)
19
+ ui.interstitial( "Flick, flick, flick, flick..." )
20
20
  reveal.choose
21
21
  end
22
22
 
23
- private
24
-
25
- def sound
26
- @sound ||= begin
27
- require "rubygame"
28
- if defined?(Rubygame::Sound)
29
- Rubygame::Sound.load('flick_flick.ogg')
30
- end
31
- rescue
32
- end
33
- end
34
23
  end
35
24
  end
36
25
  require_relative "reveal"
@@ -1,8 +1,7 @@
1
1
  module FortuneTeller
2
2
  class Reveal < Panel
3
3
  def choose
4
- puts self
5
- exit
4
+ ui.exit( self.to_s )
6
5
  end
7
6
  end
8
7
  end
@@ -1,3 +1,3 @@
1
1
  module FortuneTeller
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fortune_teller
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-26 00:00:00.000000000 Z
12
+ date: 2012-08-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rubygame
@@ -61,6 +61,8 @@ files:
61
61
  - fortune_teller.gemspec
62
62
  - lib/fortune_teller.rb
63
63
  - lib/fortune_teller/chooser.rb
64
+ - lib/fortune_teller/cli_ui.rb
65
+ - lib/fortune_teller/game.rb
64
66
  - lib/fortune_teller/list_renderer.rb
65
67
  - lib/fortune_teller/logger.rb
66
68
  - lib/fortune_teller/nil_panel.rb
@@ -82,7 +84,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
82
84
  version: '0'
83
85
  segments:
84
86
  - 0
85
- hash: 3644824976486714964
87
+ hash: 3561951047884625826
86
88
  required_rubygems_version: !ruby/object:Gem::Requirement
87
89
  none: false
88
90
  requirements:
@@ -91,7 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
91
93
  version: '0'
92
94
  segments:
93
95
  - 0
94
- hash: 3644824976486714964
96
+ hash: 3561951047884625826
95
97
  requirements: []
96
98
  rubyforge_project: fortune_teller
97
99
  rubygems_version: 1.8.24