fortune_teller 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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