SgfParser 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
data/.document CHANGED
@@ -1,5 +1,5 @@
1
- README.rdoc
2
- lib/**/*.rb
3
- bin/*
4
- features/**/*.feature
5
- LICENSE
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color --format doc
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.9.2@jrun
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ # A sample Gemfile
2
+ source "http://rubygems.org"
3
+
4
+
5
+ group :development do
6
+ gem "jeweler"
7
+ gem "rcov"
8
+ end
9
+
10
+ group :test do
11
+ gem "rspec"
12
+ end
@@ -0,0 +1,27 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.2)
5
+ git (1.2.5)
6
+ jeweler (1.6.4)
7
+ bundler (~> 1.0)
8
+ git (>= 1.2.5)
9
+ rake
10
+ rake (0.9.2)
11
+ rcov (0.9.9)
12
+ rspec (2.6.0)
13
+ rspec-core (~> 2.6.0)
14
+ rspec-expectations (~> 2.6.0)
15
+ rspec-mocks (~> 2.6.0)
16
+ rspec-core (2.6.4)
17
+ rspec-expectations (2.6.0)
18
+ diff-lcs (~> 1.1.2)
19
+ rspec-mocks (2.6.0)
20
+
21
+ PLATFORMS
22
+ ruby
23
+
24
+ DEPENDENCIES
25
+ jeweler
26
+ rcov
27
+ rspec
data/Rakefile CHANGED
@@ -18,38 +18,23 @@ rescue LoadError
18
18
  puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
19
19
  end
20
20
 
21
- require 'spec/rake/spectask'
22
- Spec::Rake::SpecTask.new(:spec) do |spec|
23
- spec.libs << 'lib' << 'spec'
24
- spec.spec_files = FileList['spec/**/*_spec.rb']
21
+ require 'rspec/core/rake_task'
22
+ desc 'Default: run specs.'
23
+ task :default => :spec
24
+
25
+ desc "Run specs"
26
+ RSpec::Core::RakeTask.new do |spec|
27
+ spec.pattern = "./spec/**/*_spec.rb"
25
28
  end
26
29
 
27
- Spec::Rake::SpecTask.new(:rcov) do |spec|
28
- spec.libs << 'lib' << 'spec'
30
+ RSpec::Core::RakeTask.new(:coverage) do |spec|
29
31
  spec.pattern = 'spec/**/*_spec.rb'
30
32
  spec.rcov = true
33
+ spec.rcov_opts = ['--exclude', 'spec']
31
34
  end
32
35
 
33
- task :spec => :check_dependencies
34
-
35
- # In case I ever want to go back to cucumber.
36
- #begin
37
- # require 'cucumber/rake/task'
38
- # Cucumber::Rake::Task.new(:features)
39
- #
40
- # task :features => :check_dependencies
41
- #rescue LoadError
42
- # task :features do
43
- # abort "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
44
- # end
45
- #end
46
-
47
- #task :default => [:spec, :features]
48
-
49
- task :default => [:spec]
50
-
51
- require 'rake/rdoctask'
52
- Rake::RDocTask.new do |rdoc|
36
+ require 'rdoc/task'
37
+ RDoc::Task.new do |rdoc|
53
38
  version = File.exist?('VERSION') ? File.read('VERSION') : ""
54
39
 
55
40
  rdoc.rdoc_dir = 'rdoc'
@@ -1,67 +1,71 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in rakefile, and run the gemspec command
4
- # -*- encoding: utf-8 -*-
5
-
6
- Gem::Specification.new do |s|
7
- s.name = %q{SgfParser}
8
- s.version = "0.9.0"
9
-
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Aldric Giacomoni"]
12
- s.date = %q{2010-04-30}
13
- s.description = %q{SGFParser is a library that parses and saves SGF (Smart Game Format) files.}
14
- s.email = %q{aldric@trevoke.net}
15
- s.extra_rdoc_files = [
16
- "LICENSE",
17
- "README.rdoc"
18
- ]
19
- s.files = [
20
- ".document",
21
- ".gitignore",
22
- "LICENSE",
23
- "README.rdoc",
24
- "Rakefile",
25
- "SgfParser.gemspec",
26
- "VERSION",
27
- "lib/sgf/parser/node.rb",
28
- "lib/sgf/parser/properties.rb",
29
- "lib/sgf/parser/tree.rb",
30
- "lib/sgf/parser/tree_parse.rb",
31
- "lib/sgf/sgf_indent.rb",
32
- "lib/sgf_parser.rb",
33
- "sample_sgf/ff4_ex.sgf",
34
- "sample_sgf/redrose-tartrate.sgf",
35
- "sample_usage/parsing_files.rb",
36
- "spec/node_spec.rb",
37
- "spec/spec.opts",
38
- "spec/spec_helper.rb",
39
- "spec/tree_spec.rb",
40
- "tryme.rb"
41
- ]
42
- s.homepage = %q{http://github.com/Trevoke/SGFParser}
43
- s.rdoc_options = ["--charset=UTF-8"]
44
- s.require_paths = ["lib"]
45
- s.rubygems_version = %q{1.3.6}
46
- s.summary = %q{A library for working with SGF files.}
47
- s.test_files = [
48
- "spec/node_spec.rb",
49
- "spec/spec_helper.rb",
50
- "spec/tree_parser_spec.rb",
51
- "spec/tree_spec.rb"
52
- ]
53
-
54
- if s.respond_to? :specification_version then
55
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
56
- s.specification_version = 3
57
-
58
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
59
- s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
60
- else
61
- s.add_dependency(%q<rspec>, [">= 1.2.9"])
62
- end
63
- else
64
- s.add_dependency(%q<rspec>, [">= 1.2.9"])
65
- end
66
- end
67
-
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{SgfParser}
8
+ s.version = "0.9.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Aldric Giacomoni"]
12
+ s.date = %q{2011-07-29}
13
+ s.description = %q{SGFParser is a library that parses and saves SGF (Smart Game Format) files.}
14
+ s.email = %q{aldric@trevoke.net}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".rspec",
22
+ ".rvmrc",
23
+ "Gemfile",
24
+ "Gemfile.lock",
25
+ "LICENSE",
26
+ "README.rdoc",
27
+ "Rakefile",
28
+ "SgfParser.gemspec",
29
+ "VERSION",
30
+ "lib/sgf/parser/node.rb",
31
+ "lib/sgf/parser/properties.rb",
32
+ "lib/sgf/parser/tree.rb",
33
+ "lib/sgf/parser/tree_parse.rb",
34
+ "lib/sgf/sgf_indent.rb",
35
+ "lib/sgf/sgfindent.rb",
36
+ "lib/sgf_parser.rb",
37
+ "sample_sgf/ff4_ex.sgf",
38
+ "sample_sgf/ff4_ex_saved.sgf",
39
+ "sample_sgf/redrose-tartrate.sgf",
40
+ "sample_sgf/simple.sgf",
41
+ "sample_sgf/simple_saved.sgf",
42
+ "sample_usage/parsing_files.rb",
43
+ "spec/node_spec.rb",
44
+ "spec/spec_helper.rb",
45
+ "spec/tree_parser_spec.rb",
46
+ "spec/tree_spec.rb"
47
+ ]
48
+ s.homepage = %q{http://github.com/Trevoke/SGFParser}
49
+ s.require_paths = ["lib"]
50
+ s.rubygems_version = %q{1.6.2}
51
+ s.summary = %q{A library for working with SGF files.}
52
+
53
+ if s.respond_to? :specification_version then
54
+ s.specification_version = 3
55
+
56
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
57
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
58
+ s.add_development_dependency(%q<rcov>, [">= 0"])
59
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
60
+ else
61
+ s.add_dependency(%q<jeweler>, [">= 0"])
62
+ s.add_dependency(%q<rcov>, [">= 0"])
63
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
64
+ end
65
+ else
66
+ s.add_dependency(%q<jeweler>, [">= 0"])
67
+ s.add_dependency(%q<rcov>, [">= 0"])
68
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
69
+ end
70
+ end
71
+
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.0
1
+ 0.9.1
@@ -1,8 +1,5 @@
1
1
  module SgfParser
2
2
 
3
- # Each part of the SGF Tree is a node. This holds links to the parent node,
4
- # to the next node(s) in the tree, and of course, the properties of said node.
5
- # Accessors : node.parent, node.children, node.properties
6
3
  class Node
7
4
 
8
5
  attr_accessor :parent, :children, :properties
@@ -19,9 +16,6 @@ module SgfParser
19
16
  @properties.merge! args[:properties] if !args[:properties].nil?
20
17
  end
21
18
 
22
- # Adds one child or several children. Can be passed in as a comma-separated
23
- # list or an array of node children. Will raise an error if one of the
24
- # arguments is not of class Node.
25
19
  def add_children *nodes
26
20
  nodes.flatten!
27
21
  raise "Non-node child given!" if nodes.find { |node| node.class != Node }
@@ -30,8 +24,6 @@ module SgfParser
30
24
  @children.concat nodes
31
25
  end
32
26
 
33
- # Adds one or more properties to the node.
34
- # Argument: a hash {'property' => 'value'}
35
27
  def add_properties hash
36
28
  hash.each do |key, value|
37
29
  @properties[key] ||= ""
@@ -39,18 +31,14 @@ module SgfParser
39
31
  end
40
32
  end
41
33
 
42
- # Iterates over each child of the given node
43
- # node.each_child { |child| puts child.properties }
44
34
  def each_child
45
35
  @children.each { |child| yield child }
46
36
  end
47
37
 
48
- # Compares one node's properties to another node's properties
49
38
  def == other_node
50
39
  @properties == other_node.properties
51
40
  end
52
41
 
53
- # Making comments easier to access.
54
42
  def comments
55
43
  @properties["C"]
56
44
  end
@@ -1,19 +1,10 @@
1
1
  module SgfParser
2
2
 
3
- # This is a placeholder for the root of the gametree(s). It's an abstraction,
4
- # but it allows an easy way to save, iterate over, and compare other trees.
5
- # Accessors: tree.root
6
3
  class Tree
7
4
  include Enumerable
8
5
 
9
6
  attr_accessor :root
10
7
 
11
- # Create a new tree. Can also be used to load a tree from either a file or
12
- # a string. Raises an error if both are provided.
13
- # options: \n
14
- # :filename => filename \n
15
- # !!! OR !!! \n
16
- # :string => string \n
17
8
  def initialize args={}
18
9
  @root = Node.new
19
10
  @sgf = ""
@@ -27,10 +18,9 @@ module SgfParser
27
18
  parse unless @sgf.empty?
28
19
  end
29
20
 
30
- # Iterates over the tree, node by node, in preorder fashion.
31
- # Does not support other types of iteration, but may in the future.
32
- # tree.each { |node| puts "I am node. Hear me #{node.properties} !"}
33
21
  def each order=:preorder, &block
22
+ # I know, I know. SGF is only preorder. Well, it's implemented, ain't it?
23
+ # Stop complaining.
34
24
  case order
35
25
  when :preorder
36
26
  preorder @root, &block
@@ -51,10 +41,8 @@ module SgfParser
51
41
  # tree.save :filename => file_name
52
42
  def save args={}
53
43
  raise ArgumentError, "No file name provided" if args[:filename].nil?
54
- # SGF files are trees stored in pre-order traversal.
55
44
  @savable_sgf = "("
56
45
  @root.children.each { |child| write_node child }
57
- # write_node @root
58
46
  @savable_sgf << ")"
59
47
 
60
48
  File.open(args[:filename], 'w') { |f| f << @savable_sgf }
@@ -67,11 +55,12 @@ module SgfParser
67
55
  @savable_sgf << ";"
68
56
  unless node.properties.empty?
69
57
  properties = ""
70
- node.properties.each do |k, v|
71
- v_escaped = v.gsub("]", "\\]")
72
- properties += "#{k.to_s}[#{v_escaped}]"
58
+ node.properties.each do |identity, property|
59
+ new_property = property[1...-1]
60
+ new_property.gsub!("]", "\\]") if identity == "C"
61
+ properties += "#{identity.to_s}[#{new_property}]"
73
62
  end
74
- @savable_sgf << "#{properties}"
63
+ @savable_sgf << properties
75
64
  end
76
65
 
77
66
  case node.children.size
@@ -104,13 +93,13 @@ module SgfParser
104
93
  preorder(child, &block)
105
94
  end
106
95
  end
107
- end # preorder
96
+ end
108
97
 
109
98
  def method_missing method_name, *args
110
99
  output = @root.children[0].properties[method_name]
111
100
  super(method_name, args) if output.nil?
112
101
  output
113
- end # method_missing
102
+ end
114
103
 
115
104
  end
116
105
 
@@ -3,9 +3,8 @@ require 'stringio'
3
3
  module SgfParser
4
4
  class Tree
5
5
 
6
- private
6
+ #private
7
7
 
8
- # Creates a tree (truly, a linked list) from @sgf.
9
8
  def parse
10
9
  while char = next_character
11
10
  case char
@@ -65,14 +64,29 @@ module SgfParser
65
64
 
66
65
  def get_property
67
66
  buffer = ""
68
- while true
69
- next_bit = @stream.sysread(1)
70
- break if next_bit == "]"
71
- next_bit << @stream.sysread(1) if next_bit == "\\"
72
- next_bit = "]" if next_bit == "\\]"
73
- buffer << next_bit
67
+ while char = next_character
68
+ case char
69
+ when "]" then break unless multiple_properties?
70
+ when "\\" then
71
+ char << next_character
72
+ char = "]" if char == "\\]"
73
+ end
74
+
75
+ buffer << char
76
+ end
77
+ "[#{buffer}]"
78
+ end
79
+
80
+ def multiple_properties?
81
+ multiple_properties = false
82
+ if char = next_character
83
+ char = next_character if char == "\n"
84
+ if char == "["
85
+ multiple_properties = true
86
+ end
87
+ @stream.pos -= 1
88
+ multiple_properties
74
89
  end
75
- buffer
76
90
  end
77
91
 
78
92
  def store_character(char)
@@ -0,0 +1,118 @@
1
+ module SgfParser
2
+
3
+ # This indents an SGF file to make it more readable. It outputs to the screen
4
+ # by default, but can be given a file as output.
5
+ # Usage: SgfParser::Indenter.new infile, outfile
6
+ class Indenter
7
+
8
+ def initialize file, out=$stdout
9
+ sgf = ""
10
+ File.open(file) { |f| sgf = f.read }
11
+ @new_string = ""
12
+ sgf.gsub! "\\\\n\\\\r", ""
13
+ sgf.gsub! "\\\\r\\\\n", ""
14
+ sgf.gsub! "\\\\r", ""
15
+ sgf.gsub! "\\\\n", ""
16
+ #sgf.gsub! "\n", ""
17
+
18
+ end_of_a_series = false
19
+ identprop = false # We are not in the middle of an identprop value.
20
+ # An identprop is an identity property - a value.
21
+
22
+ sgf_array = sgf.split(//)
23
+ iterator = 0
24
+ array_length = sgf_array.size
25
+ indent = 0
26
+
27
+ while iterator < array_length - 1
28
+ char = sgf_array[iterator]
29
+
30
+ case char
31
+ when '(' # Opening a new branch
32
+ if !identprop
33
+ @new_string << "\n"
34
+ indent += 2
35
+ #tabulate indent
36
+ @new_string << " " * indent
37
+ end
38
+ @new_string << char
39
+
40
+ when ')' # Closing a branch
41
+ @new_string << char
42
+ if !identprop
43
+ @new_string << "\n"
44
+ indent -= 2
45
+ @new_string << " " * indent
46
+ #tabulate indent
47
+ end
48
+
49
+ when ';' # Opening a new node
50
+ if !identprop
51
+ @new_string << "\n"
52
+ @new_string << " " * indent
53
+ #tabulate indent
54
+ end
55
+ @new_string << char
56
+
57
+ when '[' # Open comment?
58
+ if !identprop #If we're not inside a comment, then now we are.
59
+ identprop = true
60
+ end_of_a_series = false
61
+ end
62
+ @new_string << char
63
+
64
+ when ']' # Close comment
65
+ end_of_a_series = true # Maybe end of a series of comments.
66
+ identprop = false # That's our cue to close a comment.
67
+ @new_string << char
68
+
69
+ when "\\" # If we're inside a comment, then maybe we're about to escape a ].
70
+ # This is the whole reason we need this ugly charade of a loop.
71
+ if identprop
72
+ if sgf_array[iterator + 1] == "]"
73
+ @new_string << "\\]"
74
+ iterator += 1
75
+ else
76
+ @new_string << "\\"
77
+ end
78
+ else
79
+ #This should never happen - a backslash outside a comment ?!
80
+ #But let's not have it be told that I'm not prepared.
81
+ @new_string << "\\"
82
+ end
83
+
84
+ when "\n"
85
+ @new_string << "\n"
86
+ @new_string << " " * indent
87
+ #tabulate indent
88
+
89
+ else
90
+ # Well, I guess it's "just" a character after all.
91
+ if end_of_a_series
92
+ end_of_a_series = false
93
+ end
94
+ @new_string << char
95
+ end
96
+
97
+ iterator += 1
98
+ end
99
+
100
+ if out == $stdout
101
+ $stdout << @new_string
102
+ else
103
+ File.open(out, 'w') { |file| file << @new_string }
104
+ end
105
+
106
+ end
107
+
108
+ private
109
+
110
+ def tabulate indent
111
+ indent.times { print " " }
112
+ end
113
+ end
114
+ end
115
+
116
+
117
+
118
+
@@ -0,0 +1,45 @@
1
+ (;FF[4]AP[Primiview:3.1]GM[1]SZ[19]GN[Gametree 1: properties]US[Arno Hollosi](;B[pd]N[Moves, comments, annotations]C[Nodename set to: "Moves, comments, annotations"];W[dp]GW[1]C[Marked as "Good for White"];B[pp]GB[2]C[Marked as "Very good for Black"];W[dc]GW[2]C[Marked as "Very good for White"];B[pj]DM[1]C[Marked as "Even position"];W[ci]UC[1]C[Marked as "Unclear position"];B[jd]TE[1]C[Marked as "Tesuji" or "Good move"];W[jp]BM[2]C[Marked as "Very bad move"];B[gd]DO[]C[Marked as "Doubtful move"];W[de]IT[]C[Marked as "Interesting move"];B[jj];C[White "Pass" move]W[];)(;AB[dd][de][df][dg][do:gq] AW[jd][je][jf][jg][kn:lq][pn:pq]N[Setup]C[Black & white stones at the top are added as single stones.
2
+
3
+ Black & white stones at the bottom are added using compressed point lists.];AE[ep][fp][kn][lo][lq][pn:pq]C[AddEmpty
4
+
5
+ Black stones & stones of left white group are erased in FF[3\] way.
6
+
7
+ White stones at bottom right were erased using compressed point list.];AB[pd]AW[pp]PL[B]C[Added two stones.
8
+
9
+ Node marked with "Black to play".];)(;AB[dd][de][df][dg][dh][di][dj][nj][ni][nh][nf][ne][nd][ij][ii][ih][hq][gq][fq][eq][dr][ds][dq][dp][cp][bp][ap][iq][ir][is][bo][bn][an][ms][mr]AW[pd][pe][pf][pg][ph][pi][pj][fd][fe][ff][fh][fi][fj][kh][ki][kj][os][or][oq][op][pp][qp][rp][sp][ro][rn][sn][nq][mq][lq][kq][kr][ks][fs][gs][gr][er]N[Markup]C[Position set up without compressed point lists.];TR[dd][de][df][ed][ee][ef][fd:ff] MA[dh][di][dj][ej][ei][eh][fh:fj] CR[nd][ne][nf][od][oe][of][pd:pf] SQ[nh][ni][nj][oh][oi][oj][ph:pj] SL[ih][ii][ij][jj][ji][jh][kh:kj] TW[pq:ss][so][lr:ns] TB[aq:cs][er:hs][ao]C[Markup at top partially using compressed point lists (for markup on white stones); listed clockwise, starting at upper left:
10
+ - TR (triangle)
11
+ - CR (circle)
12
+ - SQ (square)
13
+ - SL (selected points)
14
+ - MA ('X')
15
+
16
+ Markup at bottom: black & white territory (using compressed point lists)];LB[dc:1][fc:2][nc:3][pc:4][dj:a][fj:b][nj:c][pj:d][gs:ABCDEFGH][gr:ABCDEFG][gq:ABCDEF][gp:ABCDE][go:ABCD][gn:ABC][gm:AB][mm:12][mn:123][mo:1234][mp:12345][mq:123456][mr:1234567][ms:12345678]C[Label (LB property)
17
+
18
+ Top: 8 single char labels (1-4, a-d)
19
+
20
+ Bottom: Labels up to 8 char length.];)(;B[qd]N[Style & text type]C[There are hard linebreaks & soft linebreaks.
21
+ Soft linebreaks are linebreaks preceeded by '\\' like this one >o\
22
+ k<. Hard line breaks are all other linebreaks.
23
+ Soft linebreaks are converted to >nothing<, i.e. removed.
24
+
25
+ Note that linebreaks are coded differently on different systems.
26
+
27
+ Examples (>ok< shouldn't be split):
28
+
29
+ linebreak 1 "": >o\
30
+ k<
31
+ linebreak 2 "": >o\
32
+
33
+ linebreak 3 "": >o\
34
+ k<
35
+ linebreak 4 "": >o\
36
+ Black stones left (in this byo-yomi period): 10];W[qq]WL[200]OW[2]C[White time left: 200 sec
37
+ White stones left: 2];B[sr]BL[87.00]OB[9]C[Black time left: 87 sec
38
+ Black stones left: 9];W[qs]WL[13.20]OW[1]C[White time left: 13.2 sec
39
+ White stones left: 1];B[rs]C[One white stone at s2 captured];W[ps];B[pr];W[or]MN[2]C[Set move number to 2];B[os]C[Two white stones captured
40
+ (at q1 & r1)];MN[112]W[pq]C[Set move number to 112];B[sq];W[rp];B[ps];W[ns];B[ss];W[nr];B[rr];W[sp];);FF[4]AP[Primiview:3.1]GM[1]SZ[19]C[Gametree 2: game-info
41
+
42
+ Game-info properties are usually stored in the root node.
43
+ If games are merged into a single game-tree, they are stored in the node\
44
+ where the game first becomes distinguishable from all other games in\
45
+ the tree.];B[pd](;)(;)(;W[ep];B[pp](;)(;))
@@ -0,0 +1,11 @@
1
+ (;GM[1]FF[4]CA[UTF-8]
2
+ SZ[19]RU[Japanese]KM[0.50]TM[1290]OT[3x30 byo-yomi]
3
+ PB[tartrate]PW[redrose]BR[7d]WR[1p]DT[2003-06-18]PC[The Kiseido Go Server (KGS) at http://kgs.kiseido.com/]C[tartrate [7d?\]: hi
4
+ tartrate [7d?\]: thx
5
+ ]RE[B+Resign]
6
+ ;B[jj]BL[1280.503]CR[jj]C[redrose [1p\]: hi
7
+ Jerk [7d?\]: wow
8
+ Anark [11k\]: game of the day :)
9
+ Jerk [7d?\]: really big match
10
+ ]
11
+ ;W[ih]WL[1277.190]CR[ih];AB[aa][bb][cc])
@@ -0,0 +1,7 @@
1
+ (;GM[1]FF[4]CA[UTF-8]
2
+ tartrate [7d?\]: thx
3
+ ]RE[B+Resign];B[jj]BL[1280.503]CR[jj]C[redrose [1p\]: hi
4
+ Jerk [7d?\]: wow
5
+ Anark [11k\]: game of the day :)
6
+ Jerk [7d?\]: really big match
7
+ ];W[ih]WL[1277.190]CR[ih];))
@@ -1,9 +1,6 @@
1
1
  $LOAD_PATH.unshift(File.dirname(__FILE__))
2
2
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
3
  require 'sgf_parser'
4
- require 'spec'
5
- require 'spec/autorun'
4
+ require 'rspec'
5
+ require 'rspec/autorun'
6
6
 
7
- Spec::Runner.configure do |config|
8
-
9
- end
@@ -6,8 +6,19 @@ describe "SgfParser::Tree.parse" do
6
6
  @tree = SgfParser::Tree.new :filename => 'sample_sgf/ff4_ex.sgf'
7
7
  end
8
8
 
9
- it "should return true" do
10
- true
9
+ it "should have FF in the first node" do
10
+ @tree.root.children[0].properties.keys.should include("FF")
11
+ end
12
+
13
+ it "should give an error if FF is missing from the first node" do
14
+ pending "To be coded later"
15
+ end
16
+
17
+ it "should parse properly the AW property" do
18
+ input = StringIO.new "dd][de][ef]"
19
+ tree = SgfParser::Tree.new
20
+ tree.instance_variable_set "@stream", input
21
+ tree.get_property.should == "[dd][de][ef]"
11
22
  end
12
23
 
13
24
  end
@@ -3,20 +3,39 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
3
3
  describe "SgfParser::Tree" do
4
4
 
5
5
  before :each do
6
- @tree = SgfParser::Tree.new :filename => 'sample_sgf/ff4_ex.sgf'
6
+
7
7
  end
8
8
 
9
9
  it "should parse properly" do
10
- @tree.class.should == SgfParser::Tree
11
- @tree.root.children.size.should == 2
12
- @tree.root.children[0].children.size.should == 5
10
+ tree = SgfParser::Tree.new :filename => 'sample_sgf/ff4_ex.sgf'
11
+ tree.class.should == SgfParser::Tree
12
+ tree.root.children.size.should == 2
13
+ tree.root.children[0].children.size.should == 5
14
+ end
15
+
16
+ it "should save a simple tree properly" do
17
+ tree = SgfParser::Tree.new :filename => 'sample_sgf/simple.sgf'
18
+ new = 'sample_sgf/simple_saved.sgf'
19
+ tree.save :filename => new
20
+ tree2 = SgfParser::Tree.new :filename => new
21
+ tree.should == tree2
13
22
  end
14
23
 
15
- it "should save properly" do
16
- @new = 'sample_sgf/ff4_ex_saved.sgf'
17
- @tree.save :filename => @new
18
- @tree2 = SgfParser::Tree.new :filename => @new
19
- @tree2.should == @tree
24
+ it "should save the sample SGF properly" do
25
+ tree = SgfParser::Tree.new :filename => 'sample_sgf/ff4_ex.sgf'
26
+ new = 'sample_sgf/ff4_ex_saved.sgf'
27
+ tree.save :filename => new
28
+ tree2 = SgfParser::Tree.new :filename => new
29
+ tree_children = []
30
+ tree2_children = []
31
+ tree.each { |node| tree_children << node }
32
+ tree2.each { |node| tree2_children << node }
33
+ tree_children.size.should == tree2_children.size
34
+ tree_children.each_with_index do |node, index|
35
+ node.properties.should == tree2_children[index].properties
36
+ end
37
+ tree_children.should == tree2_children
38
+ tree2.should == tree
20
39
  end
21
40
 
22
41
  end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: SgfParser
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
4
+ hash: 57
5
+ prerelease:
5
6
  segments:
6
7
  - 0
7
8
  - 9
8
- - 0
9
- version: 0.9.0
9
+ - 1
10
+ version: 0.9.1
10
11
  platform: ruby
11
12
  authors:
12
13
  - Aldric Giacomoni
@@ -14,23 +15,53 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-04-30 00:00:00 -04:00
18
+ date: 2011-07-29 00:00:00 -04:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
- name: rspec
22
- prerelease: false
22
+ type: :development
23
23
  requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ name: jeweler
33
+ version_requirements: *id001
34
+ prerelease: false
35
+ - !ruby/object:Gem::Dependency
36
+ type: :development
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
24
39
  requirements:
25
40
  - - ">="
26
41
  - !ruby/object:Gem::Version
42
+ hash: 3
43
+ segments:
44
+ - 0
45
+ version: "0"
46
+ name: rcov
47
+ version_requirements: *id002
48
+ prerelease: false
49
+ - !ruby/object:Gem::Dependency
50
+ type: :development
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ hash: 13
27
57
  segments:
28
58
  - 1
29
59
  - 2
30
60
  - 9
31
61
  version: 1.2.9
32
- type: :development
33
- version_requirements: *id001
62
+ name: rspec
63
+ version_requirements: *id003
64
+ prerelease: false
34
65
  description: SGFParser is a library that parses and saves SGF (Smart Game Format) files.
35
66
  email: aldric@trevoke.net
36
67
  executables: []
@@ -42,7 +73,10 @@ extra_rdoc_files:
42
73
  - README.rdoc
43
74
  files:
44
75
  - .document
45
- - .gitignore
76
+ - .rspec
77
+ - .rvmrc
78
+ - Gemfile
79
+ - Gemfile.lock
46
80
  - LICENSE
47
81
  - README.rdoc
48
82
  - Rakefile
@@ -53,47 +87,51 @@ files:
53
87
  - lib/sgf/parser/tree.rb
54
88
  - lib/sgf/parser/tree_parse.rb
55
89
  - lib/sgf/sgf_indent.rb
90
+ - lib/sgf/sgfindent.rb
56
91
  - lib/sgf_parser.rb
57
92
  - sample_sgf/ff4_ex.sgf
93
+ - sample_sgf/ff4_ex_saved.sgf
58
94
  - sample_sgf/redrose-tartrate.sgf
95
+ - sample_sgf/simple.sgf
96
+ - sample_sgf/simple_saved.sgf
59
97
  - sample_usage/parsing_files.rb
60
98
  - spec/node_spec.rb
61
- - spec/spec.opts
62
99
  - spec/spec_helper.rb
100
+ - spec/tree_parser_spec.rb
63
101
  - spec/tree_spec.rb
64
- - tryme.rb
65
102
  has_rdoc: true
66
103
  homepage: http://github.com/Trevoke/SGFParser
67
104
  licenses: []
68
105
 
69
106
  post_install_message:
70
- rdoc_options:
71
- - --charset=UTF-8
107
+ rdoc_options: []
108
+
72
109
  require_paths:
73
110
  - lib
74
111
  required_ruby_version: !ruby/object:Gem::Requirement
112
+ none: false
75
113
  requirements:
76
114
  - - ">="
77
115
  - !ruby/object:Gem::Version
116
+ hash: 3
78
117
  segments:
79
118
  - 0
80
119
  version: "0"
81
120
  required_rubygems_version: !ruby/object:Gem::Requirement
121
+ none: false
82
122
  requirements:
83
123
  - - ">="
84
124
  - !ruby/object:Gem::Version
125
+ hash: 3
85
126
  segments:
86
127
  - 0
87
128
  version: "0"
88
129
  requirements: []
89
130
 
90
131
  rubyforge_project:
91
- rubygems_version: 1.3.6
132
+ rubygems_version: 1.6.2
92
133
  signing_key:
93
134
  specification_version: 3
94
135
  summary: A library for working with SGF files.
95
- test_files:
96
- - spec/node_spec.rb
97
- - spec/spec_helper.rb
98
- - spec/tree_parser_spec.rb
99
- - spec/tree_spec.rb
136
+ test_files: []
137
+
data/.gitignore DELETED
@@ -1,25 +0,0 @@
1
- ## MAC OS
2
- .DS_Store
3
-
4
- ## TEXTMATE
5
- *.tmproj
6
- tmtags
7
-
8
- ## EMACS
9
- *~
10
- \#*
11
- .\#*
12
-
13
- ## VIM
14
- *.swp
15
-
16
- ## PROJECT::GENERAL
17
- coverage
18
- rdoc
19
- pkg
20
-
21
- ## PROJECT::SPECIFIC
22
-
23
-
24
- ## Rubymine
25
- .idea/*
@@ -1 +0,0 @@
1
- --color
data/tryme.rb DELETED
@@ -1,3 +0,0 @@
1
- require 'irb/completion'
2
- require 'lib/sgf_parser'
3
- sgf = SgfParser::Tree.new :filename => 'sample_sgf/ff4_ex.sgf'