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
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
|