SgfParser 2.0.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.autotest +13 -0
- data/.gitignore +9 -0
- data/.rspec +3 -1
- data/.ruby-version +1 -0
- data/.travis.yml +3 -0
- data/CHANGELOG +12 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +42 -16
- data/README.md +97 -0
- data/SgfParser.gemspec +5 -8
- data/bin/sgf_indent.rb +5 -4
- data/examples/simple_iteration_of_games_in_a_directory.rb +3 -3
- data/lib/sgf.rb +18 -9
- data/lib/sgf/collection.rb +75 -0
- data/lib/sgf/collection_assembler.rb +32 -0
- data/lib/sgf/error.rb +1 -2
- data/lib/sgf/error_checkers.rb +15 -0
- data/lib/sgf/gametree.rb +64 -0
- data/lib/sgf/node.rb +139 -83
- data/lib/sgf/parser.rb +57 -157
- data/lib/sgf/parsing_tokens.rb +40 -0
- data/lib/sgf/properties.rb +80 -83
- data/lib/sgf/stream.rb +50 -0
- data/lib/sgf/variation.rb +16 -0
- data/lib/sgf/version.rb +1 -1
- data/lib/sgf/writer.rb +35 -37
- data/spec/acceptance_spec.rb +27 -0
- data/spec/collection_spec.rb +65 -0
- data/spec/gametree_spec.rb +99 -0
- data/spec/node_spec.rb +174 -68
- data/spec/parser_spec.rb +76 -74
- data/spec/spec_helper.rb +90 -9
- data/spec/variation_spec.rb +15 -0
- data/spec/writer_spec.rb +22 -21
- data/wercker.yml +21 -0
- metadata +77 -39
- data/.rvmrc +0 -1
- data/README.rdoc +0 -18
- data/lib/sgf/game.rb +0 -64
- data/lib/sgf/tree.rb +0 -77
- data/spec/game_spec.rb +0 -70
- data/spec/tree_spec.rb +0 -36
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe SGF::Gametree do
|
4
|
+
|
5
|
+
let(:game) { get_first_game_from 'spec/data/ff4_ex.sgf' }
|
6
|
+
let(:root_node) {
|
7
|
+
SGF::Node.new({FF: '4', AP: 'Primiview:3.1',
|
8
|
+
GM: '1', SZ: '19', GN: 'Gametree 1: properties',
|
9
|
+
US: 'Arno Hollosi'})
|
10
|
+
}
|
11
|
+
subject { game }
|
12
|
+
|
13
|
+
it 'should throw up if initialized with a non-Node argument' do
|
14
|
+
expect { SGF::Gametree.new('I am a string') }.to raise_error(ArgumentError)
|
15
|
+
expect { SGF::Gametree.new(SGF::Node.new) }.not_to raise_error
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'has game-level information' do
|
19
|
+
expect(subject.name).to eq 'Gametree 1: properties'
|
20
|
+
expect(subject.data_entry).to eq 'Arno Hollosi'
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should raise errors' do
|
24
|
+
expect { subject.opening }.to raise_error(SGF::NoIdentityError)
|
25
|
+
expect { subject.nonexistent_identity }.to raise_error(SGF::NoIdentityError)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'has meta information' do
|
29
|
+
expect(subject.inspect).to match(/SGF::Gametree/)
|
30
|
+
expect(subject.inspect).to match(/#{game.object_id}/)
|
31
|
+
end
|
32
|
+
|
33
|
+
context "When talking about nodes" do
|
34
|
+
it "begins on the root node" do
|
35
|
+
expect(subject.current_node).to eq root_node
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should have a nice way to go to children[0]" do
|
39
|
+
subject.next_node
|
40
|
+
expect(subject.current_node).to eq subject.root.children[0]
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should have a way of setting an arbitrary node to the current node" do
|
44
|
+
subject.current_node = subject.root.children[3]
|
45
|
+
expect(subject.current_node.properties.keys).to match_array %w(B C N)
|
46
|
+
expect(subject.current_node.children.size).to eq 6
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
context "blocks" do
|
52
|
+
it "should use preorder traversal for each" do
|
53
|
+
game = get_first_game_from 'spec/data/example1.sgf'
|
54
|
+
array = []
|
55
|
+
game.each { |node| array << node }
|
56
|
+
expect(array[0].c).to eq "root"
|
57
|
+
expect(array[1].c).to eq "a"
|
58
|
+
expect(array[2].c).to eq "b"
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should go through all nodes, even if block returns 'nil' (puts, anyone?)" do
|
62
|
+
game = SGF::Gametree.new root_node
|
63
|
+
game.root.add_children SGF::Node.new(B: "dd")
|
64
|
+
nodes = []
|
65
|
+
game.each { |node| nodes << node; nil }
|
66
|
+
expect(nodes.size).to eq 2
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "Slices" do
|
71
|
+
|
72
|
+
it "should return a node-only gametree if slice is [0..0]" do
|
73
|
+
game = SGF::Gametree.new root_node
|
74
|
+
slice = game.slice(0..0)
|
75
|
+
expect(slice).to be_instance_of SGF::Gametree
|
76
|
+
expect(slice.root).to eq root_node
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should slice through a one-branch list" do
|
80
|
+
node = SGF::Node.new
|
81
|
+
game = SGF::Gametree.new node
|
82
|
+
node.pw = 'Aldric'
|
83
|
+
child1 = SGF::Node.new b: "qq"
|
84
|
+
child2 = SGF::Node.new a: "rn"
|
85
|
+
child3 = SGF::Node.new b: "nr"
|
86
|
+
node.add_children child1
|
87
|
+
child1.add_children child2
|
88
|
+
child2.add_children child3
|
89
|
+
slice = game.slice(1..3)
|
90
|
+
expect(slice).to be_instance_of SGF::Gametree
|
91
|
+
root = slice.root
|
92
|
+
expect(root.b).to eq 'qq'
|
93
|
+
expect(root.parent).to be_nil
|
94
|
+
expect(root.children[0].a).to eq 'rn'
|
95
|
+
expect(root.children[0].children[0].b).to eq 'nr'
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
data/spec/node_spec.rb
CHANGED
@@ -1,90 +1,196 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
3
|
+
RSpec.describe SGF::Node do
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
end
|
5
|
+
let(:node) { SGF::Node.new }
|
6
|
+
subject { node }
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
8
|
+
context 'inspect' do
|
9
|
+
subject { node.inspect }
|
10
|
+
it { is_expected.to match(/#{node.object_id}/) }
|
11
|
+
it { is_expected.to match(/SGF::Node/) }
|
12
|
+
it { is_expected.to match(/Has no parent/) }
|
15
13
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
14
|
+
it "should give you a relatively useful inspect" do
|
15
|
+
node.add_properties({C: "Oh hi", PB: "Dosaku", AE: "[dd][gh]"})
|
16
|
+
is_expected.to match(/3 Properties/)
|
20
17
|
|
21
|
-
|
22
|
-
|
23
|
-
@node.parent = parent
|
24
|
-
@node.parent.should == parent
|
25
|
-
end
|
18
|
+
node.add_children SGF::Node.new, SGF::Node.new
|
19
|
+
expect(node.inspect).to match(/2 Children/)
|
26
20
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
child3 = SGF::Node.new
|
31
|
-
@node.add_children child1, child2, child3
|
32
|
-
@node.children.should == [child1, child2, child3]
|
33
|
-
end
|
21
|
+
node.parent = SGF::Node.new
|
22
|
+
expect(node.inspect).to match(/Has a parent/)
|
23
|
+
end
|
34
24
|
|
35
|
-
it "should link to children, who should get new parents" do
|
36
|
-
child1 = SGF::Node.new
|
37
|
-
child2 = SGF::Node.new
|
38
|
-
child3 = SGF::Node.new
|
39
|
-
@node.add_children child1, child2, child3
|
40
|
-
@node.children.each { |child| child.parent.should == @node }
|
41
25
|
end
|
42
26
|
|
43
|
-
it "should
|
44
|
-
|
45
|
-
|
46
|
-
@node.properties["TC"].should == "Hello, world!"
|
27
|
+
it "should properly show a string version of the node" do
|
28
|
+
subject.add_properties({"C" => "Oh hi]", "PB" => "Dosaku"})
|
29
|
+
expect(subject.to_s).to eq ";C[Oh hi\\]]\nPB[Dosaku]"
|
47
30
|
end
|
48
31
|
|
49
|
-
it "should
|
50
|
-
|
51
|
-
|
52
|
-
@node.pw.should == "The Tick"
|
53
|
-
@node.pb.should == "Batmanuel"
|
32
|
+
it "should properly show a string version of the node if identities are symbols" do
|
33
|
+
subject.add_properties({C: "Oh hi]", PB: "Dosaku"})
|
34
|
+
expect(subject.to_s).to eq ";C[Oh hi\\]]\nPB[Dosaku]"
|
54
35
|
end
|
55
36
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
37
|
+
context "Heredity" do
|
38
|
+
|
39
|
+
let(:parent) { SGF::Node.new }
|
40
|
+
let(:child1) { SGF::Node.new }
|
41
|
+
let(:child3) { SGF::Node.new }
|
42
|
+
let(:child2) { SGF::Node.new }
|
43
|
+
|
44
|
+
it "should link to a parent" do
|
45
|
+
subject.parent = parent
|
46
|
+
expect(subject.parent).to eq parent
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should link to children" do
|
50
|
+
node.add_children child1, child2, child3
|
51
|
+
expect(node.children).to eq [child1, child2, child3]
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should link to children, who should get new parents" do
|
55
|
+
node.add_children child1, child2, child3
|
56
|
+
node.children.each { |child| expect(child.parent).to eq node }
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should not be the child of many nodes" do
|
60
|
+
parent2 = SGF::Node.new
|
61
|
+
parent.add_children node
|
62
|
+
parent2.add_children node
|
63
|
+
expect(node.parent).to eq(parent2)
|
64
|
+
expect(parent2.children).to include(node)
|
65
|
+
expect(parent.children).to_not include(node)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should become a child of its new parent" do
|
69
|
+
node.parent = parent
|
70
|
+
expect(parent.children).to include node
|
71
|
+
end
|
72
|
+
|
62
73
|
end
|
63
74
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
75
|
+
context "Properties" do
|
76
|
+
|
77
|
+
it "should store properties" do
|
78
|
+
node.add_properties PB: "Dosaku"
|
79
|
+
expect(node.properties).to eq({"PB" => "Dosaku"})
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should allow concatenation of properties" do
|
83
|
+
node.add_properties "TC" => "Hello,"
|
84
|
+
node.add_properties "TC" => " world!"
|
85
|
+
expect(node.properties["TC"]).to eq "Hello, world!"
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should give you the properties based on method given" do
|
89
|
+
node.add_properties "PW" => "The Tick"
|
90
|
+
node.add_properties "PB" => "Batmanuel"
|
91
|
+
expect(node.pw).to eq "The Tick"
|
92
|
+
expect(node.pb).to eq "Batmanuel"
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should allow you to change a property completely" do
|
96
|
+
node.add_properties "RE" => "This is made up"
|
97
|
+
node.properties["RE"] = "This is also made up"
|
98
|
+
expect(node.re).to eq "This is also made up"
|
99
|
+
node.re = "And that too"
|
100
|
+
expect(node.re).to eq "And that too"
|
101
|
+
node[:RE] = 'kokolegorille'
|
102
|
+
expect(node[:RE]).to eq 'kokolegorille'
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should implement [] as a shortcut to read properties" do
|
106
|
+
node.add_properties "PB" => "Dosaku"
|
107
|
+
expect(node["PB"]).to eq "Dosaku"
|
108
|
+
expect(node[:PB]).to eq "Dosaku"
|
109
|
+
end
|
110
|
+
|
68
111
|
end
|
69
112
|
|
70
|
-
|
71
|
-
|
72
|
-
|
113
|
+
context "Node depth" do
|
114
|
+
|
115
|
+
it "should get a node depth number one more by the parent when attached to a parent" do
|
116
|
+
child = SGF::Node.new
|
117
|
+
node.add_children child
|
118
|
+
expect(node.depth).to eq 0
|
119
|
+
expect(child.depth).to eq 1
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should properly set depth if a parent is passed to initializer" do
|
123
|
+
node2 = SGF::Node.new parent: node
|
124
|
+
expect(node2.parent).to eq node
|
125
|
+
expect(node2.depth).to eq 1
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should properly update depth when parentage changes" do
|
129
|
+
link1 = SGF::Node.new
|
130
|
+
link2 = SGF::Node.new
|
131
|
+
link2.parent = link1
|
132
|
+
link1.parent = node
|
133
|
+
expect(node.parent).to be_nil
|
134
|
+
expect(link1.parent).to eq node
|
135
|
+
expect(link2.parent).to eq link1
|
136
|
+
expect(node.depth).to eq 0
|
137
|
+
expect(link1.depth).to eq 1
|
138
|
+
expect(link2.depth).to eq 2
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should properly update depth if parent is set to nil / parent is removed" do
|
142
|
+
parent = SGF::Node.new
|
143
|
+
child = SGF::Node.new
|
144
|
+
|
145
|
+
node.add_children child
|
146
|
+
node.parent = parent
|
147
|
+
expect(node.depth).to eq 1
|
148
|
+
expect(child.depth).to eq 2
|
149
|
+
|
150
|
+
node.parent = nil
|
151
|
+
expect(node.depth).to eq 0
|
152
|
+
expect(child.depth).to eq 1
|
153
|
+
|
154
|
+
node.parent = parent
|
155
|
+
expect(node.depth).to eq 1
|
156
|
+
expect(child.depth).to eq 2
|
157
|
+
|
158
|
+
node.remove_parent
|
159
|
+
expect(node.depth).to eq 0
|
160
|
+
expect(child.depth).to eq 1
|
161
|
+
end
|
162
|
+
|
163
|
+
it "should properly update depth when childhood changes" do
|
164
|
+
link1 = SGF::Node.new
|
165
|
+
link2 = SGF::Node.new
|
166
|
+
link3 = SGF::Node.new
|
167
|
+
link1.add_children link2
|
168
|
+
link2.add_children link3
|
169
|
+
node.add_children link1
|
170
|
+
node.add_children link3
|
171
|
+
expect(node.depth).to eq 0
|
172
|
+
expect(link1.depth).to eq 1
|
173
|
+
expect(link2.depth).to eq 2
|
174
|
+
expect(link3.depth).to eq 1
|
175
|
+
end
|
176
|
+
end
|
73
177
|
|
74
|
-
|
75
|
-
|
178
|
+
context "self-consistency" do
|
179
|
+
it "should only track changes from its current parent" do
|
180
|
+
link1 = SGF::Node.new
|
181
|
+
link2 = SGF::Node.new
|
76
182
|
|
77
|
-
|
78
|
-
|
183
|
+
link3 = SGF::Node.new
|
184
|
+
link1.add_children link2
|
185
|
+
node.parent = link2
|
186
|
+
expect(node.depth).to eq 2
|
79
187
|
|
80
|
-
|
81
|
-
|
82
|
-
@node.inspect.should match /Has a parent/
|
83
|
-
end
|
188
|
+
link1.depth = 2
|
189
|
+
expect(node.depth).to eq 4
|
84
190
|
|
85
|
-
|
86
|
-
|
87
|
-
|
191
|
+
node.parent = link3
|
192
|
+
link1.depth = 6
|
193
|
+
expect(node.depth).to eq 1
|
194
|
+
end
|
88
195
|
end
|
89
|
-
|
90
|
-
end
|
196
|
+
end
|
data/spec/parser_spec.rb
CHANGED
@@ -1,117 +1,119 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
3
|
+
RSpec.describe SGF::Parser do
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
let(:parser) { SGF::Parser.new }
|
6
|
+
|
7
|
+
describe "when given invalid SGF files" do
|
8
|
+
it "should give an error if the first two character are not (;" do
|
9
|
+
expect { parser.parse ';)' }.to raise_error SGF::MalformedDataError
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should not give an error if it is told to sit down and shut up" do
|
13
|
+
expect { parser.parse(';)', false) }.to_not raise_error
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should properly parse a file that has many AB/AW/AE values in a single node" do
|
17
|
+
invalid_sgf = "(;AB[dd]AB[aa])"
|
18
|
+
collection = parser.parse invalid_sgf
|
19
|
+
|
20
|
+
node = SGF::Node.new AB: %w[dd aa]
|
21
|
+
expected = SGF::Collection.new
|
22
|
+
expected.root.add_children node
|
9
23
|
|
10
|
-
|
11
|
-
|
12
|
-
|
24
|
+
expect(collection).to eq expected
|
25
|
+
expect(collection.errors).to include "Multiple AB identities are present in a single node. A property should only exist once per node."
|
26
|
+
end
|
13
27
|
end
|
14
28
|
|
15
29
|
it "should parse a simple node" do
|
16
|
-
|
17
|
-
|
18
|
-
tree.root.children[0].pw.should == "5"
|
30
|
+
collection = parser.parse ";PW[Dosaku]", false
|
31
|
+
expect(collection.root.children[0].pw).to eq "Dosaku"
|
19
32
|
end
|
20
33
|
|
21
34
|
it "should parse a node with two properties" do
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
35
|
+
collection = parser.parse ";PB[Aldric]PW[Bob]", false
|
36
|
+
expect(collection.root.children[0].pb).to eq "Aldric"
|
37
|
+
expect(collection.root.children[0].pw).to eq "Bob"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should apparently ignore line breaks in the middle of a property name -- is this right?" do
|
41
|
+
collection = parser.parse ";P\nB[Aldric]P\n\n\nW[Bob]", false
|
42
|
+
expect(collection.root.children[0].pb).to eq "Aldric"
|
43
|
+
expect(collection.root.children[0].pw).to eq "Bob"
|
26
44
|
end
|
27
45
|
|
28
46
|
it "should parse two nodes with one property each" do
|
29
|
-
|
30
|
-
|
31
|
-
node
|
32
|
-
node.
|
33
|
-
node.children[0].pw.should == "Bob"
|
47
|
+
collection = parser.parse ";PB[Aldric];PW[Bob]", false
|
48
|
+
node = collection.root.children[0]
|
49
|
+
expect(node.pb).to eq "Aldric"
|
50
|
+
expect(node.children[0].pw).to eq "Bob"
|
34
51
|
end
|
35
52
|
|
36
53
|
it "should parse a tree with a single branch" do
|
37
|
-
|
38
|
-
|
39
|
-
node
|
40
|
-
node.
|
41
|
-
node.
|
42
|
-
node.children[0].b.should == "qq"
|
54
|
+
collection = parser.parse "(;FF[4]PW[Aldric]PB[Bob];B[qq])"
|
55
|
+
node = collection.root.children[0]
|
56
|
+
expect(node.pb).to eq "Bob"
|
57
|
+
expect(node.pw).to eq "Aldric"
|
58
|
+
expect(node.children[0].b).to eq "qq"
|
43
59
|
end
|
44
60
|
|
45
61
|
it "should parse a tree with two branches" do
|
46
|
-
|
47
|
-
|
48
|
-
node
|
49
|
-
node.
|
50
|
-
node.children.
|
51
|
-
node.children[
|
52
|
-
node.children[1].c.should == "branch"
|
62
|
+
collection = parser.parse "(;FF[4](;C[main])(;C[branch]))"
|
63
|
+
node = collection.root.children[0]
|
64
|
+
expect(node.ff).to eq "4"
|
65
|
+
expect(node.children.size).to eq 2
|
66
|
+
expect( node.children[0].c).to eq "main"
|
67
|
+
expect(node.children[1].c).to eq "branch"
|
53
68
|
end
|
54
69
|
|
55
|
-
it "should parse a comment with a ] inside" do
|
56
|
-
|
57
|
-
|
58
|
-
tree.root.children[0].c.should == "Oh hi] there"
|
70
|
+
it "should parse a comment with a \\] inside" do
|
71
|
+
collection = parser.parse "(;C[Oh hi\\] there])"
|
72
|
+
expect(collection.root.children[0].c).to eq "Oh hi] there"
|
59
73
|
end
|
60
74
|
|
61
75
|
it "should parse a multi-property identity well" do
|
62
|
-
|
63
|
-
|
64
|
-
tree.root.children[0].children[0].aw.should == ["bd", "cc", "qr"]
|
76
|
+
collection = parser.parse "(;FF[4];AW[bd][cc][qr])"
|
77
|
+
expect(collection.root.children[0].children[0].aw).to eq %w(bd cc qr)
|
65
78
|
end
|
66
79
|
|
67
80
|
it "should parse multiple trees" do
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
tree.root.children[1].children[0].pb.should == "ad"
|
81
|
+
collection = parser.parse "(;FF[4]PW[Aldric];AW[dd][cc])(;FF[4]PW[Hi];PB[ad])"
|
82
|
+
expect(collection.root.children.size).to eq 2
|
83
|
+
expect(collection.root.children[0].children[0].aw).to eq %w(dd cc)
|
84
|
+
expect(collection.root.children[1].children[0].pb).to eq "ad"
|
73
85
|
end
|
74
86
|
|
75
87
|
it "should not put (; into the identity when separated by line breaks" do
|
76
|
-
|
77
|
-
|
78
|
-
game
|
79
|
-
game.children.
|
80
|
-
game.children[
|
81
|
-
game.children[1].b.should == "da"
|
88
|
+
collection = parser.parse "(;FF[4]\n\n(;B[dd])(;B[da]))"
|
89
|
+
game = collection.root.children[0]
|
90
|
+
expect(game.children.size).to eq 2
|
91
|
+
expect(game.children[0].b).to eq "dd"
|
92
|
+
expect( game.children[1].b).to eq "da"
|
82
93
|
end
|
83
94
|
|
84
95
|
it "should parse the simplified sample SGF" do
|
85
|
-
|
86
|
-
|
87
|
-
root
|
88
|
-
root.children.size.should == 2
|
96
|
+
collection = parser.parse SIMPLIFIED_SAMPLE_SGF
|
97
|
+
root = collection.root
|
98
|
+
expect(root.children.size).to eq 2
|
89
99
|
node = root.children[0].children[0]
|
90
|
-
node.ar.
|
100
|
+
expect(node.ar).to eq %w(aa:sc sa:ac aa:sa aa:ac cd:cj gd:md fh:ij kj:nh)
|
91
101
|
end
|
92
102
|
|
93
103
|
it "should parse a file if given a file handler as input" do
|
94
|
-
parser = sgf_parser
|
95
104
|
file = File.open 'spec/data/simple.sgf'
|
96
|
-
|
97
|
-
game =
|
98
|
-
game.white_player.
|
99
|
-
game.black_player.
|
105
|
+
collection = parser.parse file
|
106
|
+
game = collection.gametrees.first
|
107
|
+
expect(game.white_player).to eq "redrose"
|
108
|
+
expect(game.black_player).to eq "tartrate"
|
100
109
|
end
|
101
110
|
|
102
|
-
it "should parse a file if given a local path as input"
|
103
|
-
parser = sgf_parser
|
111
|
+
it "should parse a file if given a local path as input" do
|
104
112
|
local_path = 'spec/data/simple.sgf'
|
105
|
-
|
106
|
-
game =
|
107
|
-
game.white_player.
|
108
|
-
game.black_player.
|
109
|
-
end
|
110
|
-
|
111
|
-
private
|
112
|
-
|
113
|
-
def sgf_parser
|
114
|
-
SGF::Parser.new
|
113
|
+
collection = parser.parse local_path
|
114
|
+
game = collection.gametrees.first
|
115
|
+
expect(game.white_player).to eq "redrose"
|
116
|
+
expect(game.black_player).to eq "tartrate"
|
115
117
|
end
|
116
118
|
|
117
119
|
end
|