sgf_parser 0.1.0

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.
Files changed (53) hide show
  1. data/.irbrc +3 -0
  2. data/.rvmrc +4 -0
  3. data/Gemfile +10 -0
  4. data/Gemfile.lock +17 -0
  5. data/LICENSE +20 -0
  6. data/README.textile +27 -0
  7. data/Rakefile +20 -0
  8. data/TODO +0 -0
  9. data/VERSION +1 -0
  10. data/bin/sgf +28 -0
  11. data/bin/stm2dot +18 -0
  12. data/doc/sgf_state_machine.dot +58 -0
  13. data/doc/sgf_state_machine.svg +269 -0
  14. data/lib/sgf.rb +15 -0
  15. data/lib/sgf/binary_file_error.rb +4 -0
  16. data/lib/sgf/debugger.rb +15 -0
  17. data/lib/sgf/default_event_listener.rb +37 -0
  18. data/lib/sgf/model/constants.rb +19 -0
  19. data/lib/sgf/model/event_listener.rb +72 -0
  20. data/lib/sgf/model/game.rb +52 -0
  21. data/lib/sgf/model/label.rb +12 -0
  22. data/lib/sgf/model/node.rb +115 -0
  23. data/lib/sgf/model/property_handler.rb +51 -0
  24. data/lib/sgf/more/state_machine_presenter.rb +43 -0
  25. data/lib/sgf/more/stm_dot_converter.rb +139 -0
  26. data/lib/sgf/parse_error.rb +25 -0
  27. data/lib/sgf/parser.rb +56 -0
  28. data/lib/sgf/renderer.rb +25 -0
  29. data/lib/sgf/sgf_helper.rb +55 -0
  30. data/lib/sgf/sgf_state_machine.rb +174 -0
  31. data/lib/sgf/state_machine.rb +76 -0
  32. data/sgf_parser.gemspec +95 -0
  33. data/spec/fixtures/2009-11-01-1.sgf +24 -0
  34. data/spec/fixtures/2009-11-01-2.sgf +23 -0
  35. data/spec/fixtures/chinese_gb.sgf +9 -0
  36. data/spec/fixtures/chinese_utf.sgf +9 -0
  37. data/spec/fixtures/example.sgf +18 -0
  38. data/spec/fixtures/good.sgf +55 -0
  39. data/spec/fixtures/good1.sgf +167 -0
  40. data/spec/fixtures/kgs.sgf +723 -0
  41. data/spec/fixtures/test.png +0 -0
  42. data/spec/sgf/model/event_listener_spec.rb +97 -0
  43. data/spec/sgf/model/game_spec.rb +29 -0
  44. data/spec/sgf/model/node_spec.rb +84 -0
  45. data/spec/sgf/more/state_machine_presenter_spec.rb +29 -0
  46. data/spec/sgf/parse_error_spec.rb +10 -0
  47. data/spec/sgf/parser_spec.rb +210 -0
  48. data/spec/sgf/sgf_helper_spec.rb +68 -0
  49. data/spec/sgf/sgf_state_machine_spec.rb +166 -0
  50. data/spec/sgf/state_machine_spec.rb +137 -0
  51. data/spec/spec.opts +4 -0
  52. data/spec/spec_helper.rb +47 -0
  53. metadata +150 -0
@@ -0,0 +1,68 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ module SGF
4
+ describe SGFHelper do
5
+ before :each do
6
+ @helper = Object.new.extend(SGFHelper)
7
+ end
8
+
9
+ describe "xy_to_sgf_pos" do
10
+ it "should convert x,y to sgf position string like ab" do
11
+ @helper.xy_to_sgf_pos(1, 2).should == "bc"
12
+ end
13
+ end
14
+
15
+ describe "move_to_sgf" do
16
+ it "should convert color, x, y to sgf like ;B[ab]" do
17
+ @helper.move_to_sgf(1, 1, 2).should == ";B[bc]"
18
+ end
19
+ end
20
+
21
+ describe "to_position_array" do
22
+
23
+ [nil, "", " ", "A", "ABC"].each do |bad_argument|
24
+ it "should throw ArgumentError on bad argument(#{bad_argument.inspect})" do
25
+ lambda { @helper.to_position_array(bad_argument) }.should raise_error(ArgumentError)
26
+ end
27
+ end
28
+
29
+ it "should convert AB to [[0, 1]]" do
30
+ @helper.to_position_array("AB").should == [[0, 1]]
31
+ end
32
+
33
+ it "should be case insensitive" do
34
+ @helper.to_position_array("ab").should == [[0, 1]]
35
+ @helper.to_position_array("aB").should == [[0, 1]]
36
+ @helper.to_position_array("Ab").should == [[0, 1]]
37
+ @helper.to_position_array("AB").should == [[0, 1]]
38
+ end
39
+
40
+ it "should ignore leading and trailing spaces" do
41
+ @helper.to_position_array(" AB").should == [[0, 1]]
42
+ @helper.to_position_array("AB ").should == [[0, 1]]
43
+ @helper.to_position_array(" AB ").should == [[0, 1]]
44
+ end
45
+
46
+ it "should convert AB:BC to [[0,1], [0,2], [1,1], [1,2]]" do
47
+ @helper.to_position_array("AB:BC").should == [[0,1], [0,2], [1,1], [1,2]]
48
+ end
49
+
50
+ end
51
+
52
+ describe "to_position" do
53
+ it "should convert AB to [0, 1]" do
54
+ @helper.to_position("AB").should == [0, 1]
55
+ end
56
+
57
+ it "should be case insensitive" do
58
+ @helper.to_position("ab").should == [0, 1]
59
+ end
60
+ end
61
+
62
+ describe "to_label" do
63
+ it "should return label" do
64
+ @helper.to_label("AB:C").should == SGF::Model::Label.new(@helper.to_position("AB"), "C")
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,166 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ module SGF
4
+ describe SGFStateMachine do
5
+ describe "with no context" do
6
+ before :each do
7
+ @stm = SGFStateMachine.new
8
+ end
9
+
10
+ it "should return state machine for sgf" do
11
+ @stm.class.should == SGFStateMachine
12
+ end
13
+
14
+ it "should have start_state of #{SGFStateMachine::STATE_BEGIN}" do
15
+ @stm.start_state.should == SGFStateMachine::STATE_BEGIN
16
+ end
17
+
18
+ [
19
+ [SGFStateMachine::STATE_BEGIN, '(', SGFStateMachine::STATE_GAME_BEGIN],
20
+ [SGFStateMachine::STATE_GAME_BEGIN, ';', SGFStateMachine::STATE_NODE],
21
+ [SGFStateMachine::STATE_NODE, 'A', SGFStateMachine::STATE_PROP_NAME_BEGIN],
22
+ [SGFStateMachine::STATE_NODE, ')', SGFStateMachine::STATE_VAR_END],
23
+ [SGFStateMachine::STATE_PROP_NAME, 'A', SGFStateMachine::STATE_PROP_NAME],
24
+ [SGFStateMachine::STATE_PROP_NAME, '[', SGFStateMachine::STATE_VALUE_BEGIN],
25
+ [SGFStateMachine::STATE_VALUE_BEGIN, 'A', SGFStateMachine::STATE_VALUE],
26
+ [SGFStateMachine::STATE_VALUE_BEGIN, ']', SGFStateMachine::STATE_VALUE_END],
27
+ [SGFStateMachine::STATE_VALUE, ']', SGFStateMachine::STATE_VALUE_END],
28
+ [SGFStateMachine::STATE_VALUE, '\\', SGFStateMachine::STATE_VALUE_ESCAPE],
29
+ [SGFStateMachine::STATE_VALUE_ESCAPE, ']', SGFStateMachine::STATE_VALUE],
30
+ [SGFStateMachine::STATE_VALUE_END, ';', SGFStateMachine::STATE_NODE],
31
+ [SGFStateMachine::STATE_VALUE_END, '(', SGFStateMachine::STATE_VAR_BEGIN],
32
+ [SGFStateMachine::STATE_VALUE_END, ')', SGFStateMachine::STATE_VAR_END],
33
+ [SGFStateMachine::STATE_VALUE_END, 'A', SGFStateMachine::STATE_PROP_NAME_BEGIN],
34
+ [SGFStateMachine::STATE_VAR_BEGIN, ';', SGFStateMachine::STATE_NODE],
35
+ [SGFStateMachine::STATE_VAR_END, ';', SGFStateMachine::STATE_NODE],
36
+ [SGFStateMachine::STATE_VAR_END, '(', SGFStateMachine::STATE_VAR_BEGIN]
37
+ ].each do |state_before, input, state_after|
38
+ it "should have transition for '#{state_before}' + '#{input}' => '#{state_after}'" do
39
+ @stm.state = state_before
40
+ @stm.event input
41
+ @stm.state.should == state_after
42
+ end
43
+ end
44
+
45
+ it "end should trigger transition to game_end" do
46
+ @stm.state = SGFStateMachine::STATE_VAR_END
47
+ @stm.end
48
+ @stm.state.should == SGFStateMachine::STATE_GAME_END
49
+ end
50
+
51
+ it "should handle escaped characters" do
52
+ @stm.state = SGFStateMachine::STATE_VALUE
53
+ @stm.event '\\'
54
+ @stm.state.should == SGFStateMachine::STATE_VALUE_ESCAPE
55
+ @stm.event ']'
56
+ @stm.state.should == SGFStateMachine::STATE_VALUE
57
+ end
58
+
59
+ [
60
+ [SGFStateMachine::STATE_BEGIN , 'A'],
61
+ [SGFStateMachine::STATE_GAME_BEGIN , '['],
62
+ [SGFStateMachine::STATE_NODE , '['],
63
+ [SGFStateMachine::STATE_VAR_BEGIN , '['],
64
+ [SGFStateMachine::STATE_VAR_END , '['],
65
+ [SGFStateMachine::STATE_PROP_NAME_BEGIN , ']'],
66
+ [SGFStateMachine::STATE_PROP_NAME , ']'],
67
+ [SGFStateMachine::STATE_VALUE_END , ']'],
68
+ ].each do |state_before, input|
69
+ it "should raise error for '#{state_before}' + '#{input}'" do
70
+ @stm.state = state_before
71
+ lambda {
72
+ @stm.event input
73
+ }.should raise_error
74
+ end
75
+ end
76
+ end
77
+
78
+ describe "with context" do
79
+ before :each do
80
+ @context = Object.new
81
+ @stm = SGFStateMachine.new
82
+ @stm.context = @context
83
+ @stm.reset
84
+ end
85
+
86
+ it "Transition to game begin should call context.start_game" do
87
+ mock(@context).start_game
88
+ @stm.state = SGFStateMachine::STATE_BEGIN
89
+ @stm.event "("
90
+ end
91
+
92
+ it "Transition to node should call context.start_node" do
93
+ mock(@context).start_node
94
+ @stm.state = SGFStateMachine::STATE_GAME_BEGIN
95
+ @stm.event ";"
96
+ end
97
+
98
+ it "Transition to variation begin should call context.start_variation" do
99
+ mock(@context).start_variation
100
+ @stm.state = SGFStateMachine::STATE_NODE
101
+ @stm.event "("
102
+ end
103
+
104
+ it "Transition to prop name begin should set store input to buffer" do
105
+ @stm.state = SGFStateMachine::STATE_NODE
106
+ @stm.event "A"
107
+ @stm.buffer.should == "A"
108
+ end
109
+
110
+ it "Transition to prop name from prop name begin should append input to buffer" do
111
+ @stm.buffer = "A"
112
+ @stm.state = SGFStateMachine::STATE_PROP_NAME_BEGIN
113
+ @stm.event "B"
114
+ @stm.buffer.should == "AB"
115
+ end
116
+
117
+ it "Transition to game variation end should call context.end_variation" do
118
+ mock(@context).end_variation
119
+ @stm.state = SGFStateMachine::STATE_VALUE_END
120
+ @stm.event ")"
121
+ end
122
+
123
+ it "Transition to value begin should call context.property_name= with buffer" do
124
+ mock(@context).property_name = "AB"
125
+ @stm.buffer = "AB"
126
+ @stm.state = SGFStateMachine::STATE_PROP_NAME
127
+ @stm.event "["
128
+ end
129
+
130
+ it "Transition to value should store input to buffer" do
131
+ @stm.buffer = "AB"
132
+ @stm.state = SGFStateMachine::STATE_VALUE_BEGIN
133
+ @stm.event "V"
134
+ @stm.buffer.should == "V"
135
+ end
136
+
137
+ it "Transition from value escape to value should store input to buffer" do
138
+ @stm.buffer = "AB"
139
+ @stm.state = SGFStateMachine::STATE_VALUE_ESCAPE
140
+ @stm.event "V"
141
+ @stm.buffer.should == "ABV"
142
+ end
143
+
144
+ it "Transition to value from value should append input to buffer" do
145
+ @stm.buffer = "Valu"
146
+ @stm.state = SGFStateMachine::STATE_VALUE
147
+ @stm.event "e"
148
+ @stm.buffer.should == "Value"
149
+ end
150
+
151
+ it "Transition to value end should call context.property_value" do
152
+ mock(@context).property_value = "Value"
153
+ @stm.buffer = "Value"
154
+ @stm.state = SGFStateMachine::STATE_VALUE
155
+ @stm.event "]"
156
+ end
157
+
158
+ it "Transition to node from variation begin should not create node" do
159
+ dont_allow(@context).start_node
160
+ @stm.state = SGFStateMachine::STATE_VAR_BEGIN
161
+ @stm.event ";"
162
+ end
163
+ end
164
+
165
+ end
166
+ end
@@ -0,0 +1,137 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ module SGF
4
+ describe StateMachine do
5
+ before :each do
6
+ @stm = StateMachine.new :start
7
+ end
8
+
9
+ it "state should return current state" do
10
+ @stm.state.should == :start
11
+ end
12
+
13
+ it "transition should create transition" do
14
+ callback = lambda{}
15
+ @stm.transition :start, /a/, :end, callback
16
+
17
+ t = @stm.transitions[:start][0]
18
+ t.before_state.should == :start
19
+ t.event_pattern.should == /a/
20
+ t.after_state.should == :end
21
+ t.callback.should == callback
22
+ end
23
+
24
+ it "transition should create multiple transitions for multiple start states" do
25
+ @stm.transition [:start, :start2], /a/, :end
26
+
27
+ t = @stm.transitions[:start][0]
28
+ t.before_state.should == :start
29
+ t.event_pattern.should == /a/
30
+ t.after_state.should == :end
31
+ t2 = @stm.transitions[:start2][0]
32
+ t2.before_state.should == :start2
33
+ t2.event_pattern.should == /a/
34
+ t2.after_state.should == :end
35
+ end
36
+
37
+ it "transition_if should create transition with condition" do
38
+ condition = lambda{}
39
+ @stm.transition_if condition, :start, /a/, :end
40
+
41
+ t = @stm.transitions[:start][0]
42
+ t.condition.should == condition
43
+ t.before_state.should == :start
44
+ t.event_pattern.should == /a/
45
+ t.after_state.should == :end
46
+ end
47
+
48
+ it "transition_if should create multiple transitions for multiple start states" do
49
+ condition = lambda{}
50
+ @stm.transition_if condition, [:start, :start2], /a/, :end
51
+
52
+ t = @stm.transitions[:start][0]
53
+ t.condition.should == condition
54
+ t.before_state.should == :start
55
+ t2 = @stm.transitions[:start2][0]
56
+ t2.condition.should == condition
57
+ t2.before_state.should == :start2
58
+ end
59
+
60
+ it "desc should set description for next transition" do
61
+ @stm.desc 'conditional transition'
62
+ @stm.transition [:start, :start2], /a/, :end
63
+
64
+ @stm.transitions[:start][0].description.should == 'conditional transition'
65
+ @stm.transitions[:start2][0].description.should == 'conditional transition'
66
+ end
67
+
68
+ it "desc should not description for transition after next transition" do
69
+ @stm.desc 'conditional transition'
70
+ @stm.transition [:start, :start2], /a/, :end
71
+ @stm.transition :start3, /a/, :end
72
+
73
+ @stm.transitions[:start3][0].description.should be_nil
74
+ end
75
+
76
+ it "reset should reset its state to start state" do
77
+ @stm.transition :start, /.*/, :end
78
+ @stm.event('a').should be_true
79
+ @stm.state.should == :end
80
+
81
+ @stm.reset
82
+
83
+ @stm.state.should == :start
84
+ end
85
+
86
+ it "event should trigger state transition and return true if match the pattern" do
87
+ @stm.transition :start, /.*/, :end
88
+ @stm.event('a').should be_true
89
+ @stm.state.should == :end
90
+ end
91
+
92
+ it "event should return false if no transition is defined for state" do
93
+ @stm.event('a').should be_false
94
+ end
95
+
96
+ it "event should trigger state transition if current state is any of transition's start states and input match the pattern" do
97
+ @stm.transition [:start, :another], /.*/, :end
98
+ @stm.event 'a'
99
+ @stm.state.should == :end
100
+ @stm.instance_variable_set(:'@state', :another)
101
+ @stm.event 'a'
102
+ @stm.state.should == :end
103
+ end
104
+
105
+ it "event should not trigger state transition and return false if it does not match the pattern" do
106
+ @stm.transition :start, /a/, :end
107
+ @stm.event('b').should be_false
108
+ @stm.state.should == :start
109
+ end
110
+
111
+ it "event should not trigger state transition and return false if condition is not met" do
112
+ @stm.transition_if lambda{false}, :start, /a/, :end
113
+ @stm.event('a').should be_false
114
+ @stm.state.should == :start
115
+ end
116
+
117
+ it "nil means end of input" do
118
+ @stm.transition :start, nil, :end
119
+ @stm.end
120
+ @stm.state.should == :end
121
+ end
122
+
123
+ it "transition should invoke the lambda if triggered by an event" do
124
+ @stm.buffer = "123"
125
+ @stm.transition :start, /4/, :end, lambda{|stm| @stm.buffer += @stm.input }
126
+ @stm.event '4'
127
+ @stm.buffer.should == "1234"
128
+ end
129
+
130
+ it "clear_buffer should clear buffer" do
131
+ @stm.buffer = "abc"
132
+ @stm.clear_buffer
133
+ @stm.buffer.should == ""
134
+ end
135
+
136
+ end
137
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --format progress
3
+ --loadby mtime
4
+ --reverse
@@ -0,0 +1,47 @@
1
+ $:.push(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'rubygems'
4
+ require 'spec'
5
+
6
+ Spec::Runner.configure do |config|
7
+ # If you're not using ActiveRecord you should remove these
8
+ # lines, delete config/database.yml and disable :active_record
9
+ # in your config/boot.rb
10
+ # config.use_transactional_fixtures = true
11
+ # config.use_instantiated_fixtures = false
12
+ # config.fixture_path = RAILS_ROOT + '/../spec/fixtures/'
13
+
14
+ # == Fixtures
15
+ #
16
+ # You can declare fixtures for each example_group like this:
17
+ # describe "...." do
18
+ # fixtures :table_a, :table_b
19
+ #
20
+ # Alternatively, if you prefer to declare them only once, you can
21
+ # do so right here. Just uncomment the next line and replace the fixture
22
+ # names with your fixtures.
23
+ #
24
+ # config.global_fixtures = :table_a, :table_b
25
+ #
26
+ # If you declare global fixtures, be aware that they will be declared
27
+ # for all of your examples, even those that don't use them.
28
+ #
29
+ # You can also declare which fixtures to use (for example fixtures for test/fixtures):
30
+ #
31
+ # config.fixture_path = RAILS_ROOT + '/spec/fixtures/'
32
+ #
33
+ # == Mock Framework
34
+ #
35
+ # RSpec uses it's own mocking framework by default. If you prefer to
36
+ # use mocha, flexmock or RR, uncomment the appropriate line:
37
+ #
38
+ # config.mock_with :mocha
39
+ # config.mock_with :flexmock
40
+ config.mock_with :rr
41
+ #
42
+ # == Notes
43
+ #
44
+ # For more information take a look at Spec::Example::Configuration and Spec::Runner
45
+ end
46
+
47
+ require 'sgf'
metadata ADDED
@@ -0,0 +1,150 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sgf_parser
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Guoliang Cao
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-11-28 00:00:00 -05:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ prerelease: false
23
+ name: jeweler
24
+ type: :development
25
+ version_requirements: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 3
31
+ segments:
32
+ - 0
33
+ version: "0"
34
+ requirement: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ prerelease: false
37
+ name: rspec
38
+ type: :development
39
+ version_requirements: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ hash: 27
45
+ segments:
46
+ - 1
47
+ - 3
48
+ - 0
49
+ version: 1.3.0
50
+ requirement: *id002
51
+ description: A simple SGF parser
52
+ email: gcao99@gmail.com
53
+ executables:
54
+ - stm2dot
55
+ - sgf
56
+ extensions: []
57
+
58
+ extra_rdoc_files:
59
+ - LICENSE
60
+ - README.textile
61
+ - TODO
62
+ files:
63
+ - .irbrc
64
+ - .rvmrc
65
+ - Gemfile
66
+ - Gemfile.lock
67
+ - LICENSE
68
+ - README.textile
69
+ - Rakefile
70
+ - TODO
71
+ - VERSION
72
+ - bin/sgf
73
+ - bin/stm2dot
74
+ - doc/sgf_state_machine.dot
75
+ - doc/sgf_state_machine.svg
76
+ - lib/sgf.rb
77
+ - lib/sgf/binary_file_error.rb
78
+ - lib/sgf/debugger.rb
79
+ - lib/sgf/default_event_listener.rb
80
+ - lib/sgf/model/constants.rb
81
+ - lib/sgf/model/event_listener.rb
82
+ - lib/sgf/model/game.rb
83
+ - lib/sgf/model/label.rb
84
+ - lib/sgf/model/node.rb
85
+ - lib/sgf/model/property_handler.rb
86
+ - lib/sgf/more/state_machine_presenter.rb
87
+ - lib/sgf/more/stm_dot_converter.rb
88
+ - lib/sgf/parse_error.rb
89
+ - lib/sgf/parser.rb
90
+ - lib/sgf/renderer.rb
91
+ - lib/sgf/sgf_helper.rb
92
+ - lib/sgf/sgf_state_machine.rb
93
+ - lib/sgf/state_machine.rb
94
+ - sgf_parser.gemspec
95
+ - spec/fixtures/2009-11-01-1.sgf
96
+ - spec/fixtures/2009-11-01-2.sgf
97
+ - spec/fixtures/chinese_gb.sgf
98
+ - spec/fixtures/chinese_utf.sgf
99
+ - spec/fixtures/example.sgf
100
+ - spec/fixtures/good.sgf
101
+ - spec/fixtures/good1.sgf
102
+ - spec/fixtures/kgs.sgf
103
+ - spec/fixtures/test.png
104
+ - spec/sgf/model/event_listener_spec.rb
105
+ - spec/sgf/model/game_spec.rb
106
+ - spec/sgf/model/node_spec.rb
107
+ - spec/sgf/more/state_machine_presenter_spec.rb
108
+ - spec/sgf/parse_error_spec.rb
109
+ - spec/sgf/parser_spec.rb
110
+ - spec/sgf/sgf_helper_spec.rb
111
+ - spec/sgf/sgf_state_machine_spec.rb
112
+ - spec/sgf/state_machine_spec.rb
113
+ - spec/spec.opts
114
+ - spec/spec_helper.rb
115
+ has_rdoc: true
116
+ homepage: http://github.com/gcao/discuz_robot
117
+ licenses: []
118
+
119
+ post_install_message:
120
+ rdoc_options: []
121
+
122
+ require_paths:
123
+ - lib
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ none: false
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ hash: 3
130
+ segments:
131
+ - 0
132
+ version: "0"
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ none: false
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ hash: 3
139
+ segments:
140
+ - 0
141
+ version: "0"
142
+ requirements: []
143
+
144
+ rubyforge_project:
145
+ rubygems_version: 1.4.2
146
+ signing_key:
147
+ specification_version: 3
148
+ summary: A SGF parser
149
+ test_files: []
150
+