SgfParser 2.0.0 → 3.0.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.
- 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
|