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
data/lib/sgf/game.rb
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
module SGF
|
2
|
-
class Game
|
3
|
-
|
4
|
-
include Enumerable
|
5
|
-
|
6
|
-
SGF::Game::PROPERTIES.each do |human_readable_method, sgf_identity|
|
7
|
-
define_method(human_readable_method.to_sym) do
|
8
|
-
@root[sgf_identity] ? @root[sgf_identity] : raise(SGF::NoIdentityError)
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
attr_accessor :current_node, :root
|
13
|
-
|
14
|
-
#Takes a SGF::Node as an argument. It will be a problem if that node isn't
|
15
|
-
#really the first node of of a game (ie: no FF property)
|
16
|
-
def initialize node
|
17
|
-
raise ArgumentError, "Expected SGF::Node argument but received #{node.class}" unless node.instance_of? SGF::Node
|
18
|
-
@root = node
|
19
|
-
@current_node = node
|
20
|
-
end
|
21
|
-
|
22
|
-
#A simple way to go to the next node in the same branch of the tree
|
23
|
-
def next_node
|
24
|
-
@current_node = @current_node.children[0]
|
25
|
-
end
|
26
|
-
|
27
|
-
#Iterate through all the nodes in preorder fashion
|
28
|
-
def each &block
|
29
|
-
preorder @root, &block
|
30
|
-
end
|
31
|
-
|
32
|
-
def node_count
|
33
|
-
count = 0
|
34
|
-
each { |node| count += 1 }
|
35
|
-
count
|
36
|
-
end
|
37
|
-
|
38
|
-
def to_s
|
39
|
-
"<SGF::Game:#{object_id}>"
|
40
|
-
end
|
41
|
-
|
42
|
-
alias :inspect :to_s
|
43
|
-
|
44
|
-
def to_str
|
45
|
-
SGF::Writer.new.stringify_tree_from @root
|
46
|
-
end
|
47
|
-
|
48
|
-
private
|
49
|
-
|
50
|
-
def method_missing method_name, *args
|
51
|
-
human_readable_identity = method_name.to_s.downcase
|
52
|
-
identity = SGF::Game::PROPERTIES[human_readable_identity]
|
53
|
-
return @root[identity] if identity
|
54
|
-
super(method_name, args)
|
55
|
-
end
|
56
|
-
|
57
|
-
def preorder node=@root, &block
|
58
|
-
yield node
|
59
|
-
node.each_child do |child|
|
60
|
-
preorder child, &block
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
data/lib/sgf/tree.rb
DELETED
@@ -1,77 +0,0 @@
|
|
1
|
-
module SGF
|
2
|
-
|
3
|
-
#Tree holds most of the logic, for now. It has all the nodes, can iterate over them, and can even save to a file!
|
4
|
-
#Somehow this feels like it should be split into another class or two...
|
5
|
-
class Tree
|
6
|
-
include Enumerable
|
7
|
-
|
8
|
-
attr_accessor :root, :current_node, :errors
|
9
|
-
|
10
|
-
def initialize
|
11
|
-
@root = Node.new
|
12
|
-
@current_node = @root
|
13
|
-
@errors = []
|
14
|
-
end
|
15
|
-
|
16
|
-
def each
|
17
|
-
games.each { |game| game.each { |node| yield node } }
|
18
|
-
end
|
19
|
-
|
20
|
-
# Compares a tree to another tree, node by node.
|
21
|
-
# Nodes must be the same (same properties, parents and children).
|
22
|
-
def == other_tree
|
23
|
-
one = []
|
24
|
-
two = []
|
25
|
-
each { |node| one << node }
|
26
|
-
other_tree.each { |node| two << node }
|
27
|
-
one == two
|
28
|
-
end
|
29
|
-
|
30
|
-
#Returns an array of the Game objects in this tree.
|
31
|
-
def games
|
32
|
-
populate_game_array
|
33
|
-
end
|
34
|
-
|
35
|
-
def to_s
|
36
|
-
out = "#<SGF::Tree:#{self.object_id}, "
|
37
|
-
out << "#{games.count} Games, "
|
38
|
-
out << "#{node_count} Nodes"
|
39
|
-
out << ">"
|
40
|
-
end
|
41
|
-
|
42
|
-
alias :inspect :to_s
|
43
|
-
|
44
|
-
def to_str
|
45
|
-
SGF::Writer.new.stringify_tree_from @root
|
46
|
-
end
|
47
|
-
|
48
|
-
# Saves the Tree as an SGF file. Takes a filename as argument.
|
49
|
-
def save filename
|
50
|
-
SGF::Writer.new.save(@root, filename)
|
51
|
-
end
|
52
|
-
|
53
|
-
private
|
54
|
-
|
55
|
-
def node_count
|
56
|
-
count = 0
|
57
|
-
games.each { |game| count += game.node_count }
|
58
|
-
count
|
59
|
-
end
|
60
|
-
|
61
|
-
def populate_game_array
|
62
|
-
games = []
|
63
|
-
@root.children.each do |first_node_of_gametree|
|
64
|
-
games << Game.new(first_node_of_gametree)
|
65
|
-
end
|
66
|
-
games
|
67
|
-
end
|
68
|
-
|
69
|
-
def method_missing method_name, *args
|
70
|
-
output = @root.children[0].properties[method_name]
|
71
|
-
super(method_name, args) if output.nil?
|
72
|
-
output
|
73
|
-
end
|
74
|
-
|
75
|
-
end # Tree
|
76
|
-
end # SGF
|
77
|
-
|
data/spec/game_spec.rb
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
|
3
|
-
describe "SGF::Game" do
|
4
|
-
|
5
|
-
it "should hold the first node of the game" do
|
6
|
-
game = get_first_game_from 'spec/data/ff4_ex.sgf'
|
7
|
-
game.current_node["FF"].should == "4"
|
8
|
-
end
|
9
|
-
|
10
|
-
it "should throw up if initialized with a non-Node argument" do
|
11
|
-
expect { SGF::Game.new("I am a string") }.to raise_error(ArgumentError)
|
12
|
-
expect { SGF::Game.new(SGF::Node.new) }.to_not raise_error(ArgumentError)
|
13
|
-
end
|
14
|
-
|
15
|
-
it "should have the expected game-level information" do
|
16
|
-
game = get_first_game_from 'spec/data/ff4_ex.sgf'
|
17
|
-
game.name.should == "Gametree 1: properties"
|
18
|
-
game.data_entry.should == "Arno Hollosi"
|
19
|
-
expect { game.opening }.to raise_error(SGF::NoIdentityError)
|
20
|
-
expect { game.nonexistent_identity }.to raise_error(NoMethodError)
|
21
|
-
end
|
22
|
-
|
23
|
-
it "should give you a minimum of useful information on inspect" do
|
24
|
-
game = get_first_game_from 'spec/data/simple.sgf'
|
25
|
-
inspect = game.inspect
|
26
|
-
inspect.should match /SGF::Game/
|
27
|
-
inspect.should match /#{game.object_id}/
|
28
|
-
end
|
29
|
-
|
30
|
-
context "When talking about nodes" do
|
31
|
-
|
32
|
-
it "should have 'root' as the default current node" do
|
33
|
-
game = get_first_game_from 'spec/data/ff4_ex.sgf'
|
34
|
-
game.current_node.should == game.root
|
35
|
-
end
|
36
|
-
|
37
|
-
it "should have a nice way to go to children[0]" do
|
38
|
-
game = get_first_game_from 'spec/data/ff4_ex.sgf'
|
39
|
-
game.next_node
|
40
|
-
game.current_node.should == game.root.children[0]
|
41
|
-
end
|
42
|
-
|
43
|
-
it "should have a way of setting an arbitrary node to the current node" do
|
44
|
-
game = get_first_game_from 'spec/data/ff4_ex.sgf'
|
45
|
-
game.current_node = game.root.children[3]
|
46
|
-
game.current_node.properties.keys.sort.should == ["B", "C", "N"]
|
47
|
-
game.current_node.children.size.should == 6
|
48
|
-
end
|
49
|
-
|
50
|
-
end
|
51
|
-
|
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
|
-
array[0].c.should == "root"
|
57
|
-
array[1].c.should == "a"
|
58
|
-
array[2].c.should == "b"
|
59
|
-
end
|
60
|
-
|
61
|
-
it "should go through all nodes, even if block returns 'nil' (puts, anyone?)" do
|
62
|
-
root = SGF::Node.new :properties => {"FF" => "4", "PB" => "Me", "PW" => "You"}
|
63
|
-
game = SGF::Game.new root
|
64
|
-
root.add_children SGF::Node.new(:properties => {"B" => "dd"})
|
65
|
-
nodes = []
|
66
|
-
game.each { |node| nodes << node; nil }
|
67
|
-
nodes.size.should == 2
|
68
|
-
end
|
69
|
-
|
70
|
-
end
|
data/spec/tree_spec.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
|
3
|
-
describe "SGF::Tree" do
|
4
|
-
|
5
|
-
before :each do
|
6
|
-
@tree = get_tree_from 'spec/data/ff4_ex.sgf'
|
7
|
-
end
|
8
|
-
|
9
|
-
it "should have two gametrees" do
|
10
|
-
@tree.games.size.should == 2
|
11
|
-
end
|
12
|
-
|
13
|
-
it "should have a decent inspect" do
|
14
|
-
inspect = @tree.inspect
|
15
|
-
inspect.should match /SGF::Tree/
|
16
|
-
inspect.should match /#{@tree.object_id}/
|
17
|
-
inspect.should match /2 Games/
|
18
|
-
inspect.should match /62 Nodes/
|
19
|
-
end
|
20
|
-
|
21
|
-
it "should use preorder traversal for each" do
|
22
|
-
@tree = get_tree_from 'spec/data/example1.sgf'
|
23
|
-
array = []
|
24
|
-
@tree.each {|node| array << node}
|
25
|
-
array[0].c.should == "root"
|
26
|
-
array[1].c.should == "a"
|
27
|
-
array[2].c.should == "b"
|
28
|
-
end
|
29
|
-
|
30
|
-
it "should load a file properly" do
|
31
|
-
@tree.class.should == SGF::Tree
|
32
|
-
@tree.root.children.size.should == 2
|
33
|
-
@tree.root.children[0].children.size.should == 5
|
34
|
-
end
|
35
|
-
|
36
|
-
end
|