sportdb 1.9.10 → 1.9.11

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ed1aa660c6f5bcc10d6197bbf48494c6fe6e0e3f
4
- data.tar.gz: 6ab3685c798fff2e82e94af70b5d8c9e048d8db2
3
+ metadata.gz: 68f64d57578e9dffc8a1f676e0d7771fb486e7ef
4
+ data.tar.gz: 02d84695cdcb3b1fea7269db822292f9003e7305
5
5
  SHA512:
6
- metadata.gz: a2f5811eb0d21e5f3ec58df3c9c087998017fc716a41b4105c96a31164fed79018e922367a14163dac30ced4151ba6bb93ed006c5bb8e270f5fd41458fd93043
7
- data.tar.gz: dd6220cddf7565946b24b2e471efba17e93c29f47366abed585bd3bea4d3556190d557ebcbf00bdc64fe6597e98e5e3e53eee144bbb6772ea8f6809dfc94167c
6
+ metadata.gz: 1c1da39819f4b5921ea03598f0bce3b129e0219fdd2016ebad21626f9667ed50b0655302f8c251eda3a0c30b1c3dfbce7d113735f7db0bf9b0ae463c47a17ede
7
+ data.tar.gz: d3eedae5177bb1708a60bc03267f8672e5c290707d98ceb1338b509f144d2a4a1ba51c626ae2f72b536a9eb891f95aa953123599cfb508a29585891835f38645
@@ -13,6 +13,8 @@ config/fixtures/ro.yml
13
13
  data/seasons.txt
14
14
  data/setups/all.txt
15
15
  lib/sportdb.rb
16
+ lib/sportdb/builder/builder.rb
17
+ lib/sportdb/builder/dataset.rb
16
18
  lib/sportdb/calc.rb
17
19
  lib/sportdb/cli/main.rb
18
20
  lib/sportdb/cli/opts.rb
@@ -125,6 +127,7 @@ test/data/world-cup/teams_1962.txt
125
127
  test/data/world-cup/teams_1974.txt
126
128
  test/helper.rb
127
129
  test/test_assoc_reader.rb
130
+ test/test_builder.rb
128
131
  test/test_changes.rb
129
132
  test/test_cursor.rb
130
133
  test/test_date.rb
@@ -8,6 +8,9 @@
8
8
  # core and stlibs (note: get included via worlddb gem; see worlddb gem/lib)
9
9
 
10
10
 
11
+ require 'fileutils'
12
+
13
+
11
14
  # rubygems / 3rd party libs
12
15
 
13
16
  require 'active_record'
@@ -110,6 +113,10 @@ require 'sportdb/deleter'
110
113
  require 'sportdb/stats'
111
114
 
112
115
 
116
+ require 'sportdb/builder/dataset'
117
+ require 'sportdb/builder/builder'
118
+
119
+
113
120
  module SportDb
114
121
 
115
122
  def self.config_path
@@ -152,6 +159,12 @@ module SportDb
152
159
  reader.load_setup( setup )
153
160
  end
154
161
 
162
+ def self.read_setup_from_zip( zip_name, setup, include_path, opts={} ) ## todo/check - use a better (shorter) name ??
163
+ reader = ZipReader.new( zip_name, include_path, opts )
164
+ reader.load_setup( setup )
165
+ reader.close
166
+ end
167
+
155
168
  def self.read_all( include_path ) # convenience helper
156
169
  read_setup( 'setups/all', include_path )
157
170
  end
@@ -0,0 +1,58 @@
1
+ # encoding: utf-8
2
+
3
+ module SportDb
4
+
5
+ class Builder
6
+
7
+ include LogUtils::Logging
8
+
9
+ def initialize()
10
+ @datasets = []
11
+ end
12
+
13
+ def self.load_file( path )
14
+ code = File.read_utf8( path )
15
+ self.load( code )
16
+ end
17
+
18
+ def self.load( code )
19
+ builder = Builder.new
20
+ builder.instance_eval( code )
21
+ builder
22
+ end
23
+
24
+
25
+ def football( name, opts={} )
26
+ logger.info( "[builder] add football-dataset '#{@name}'" )
27
+ @datasets << FootballDataset.new( name, opts )
28
+ end
29
+
30
+ def world( name, opts={} )
31
+ logger.info( "[builder] add world-dataset '#{@name}'" )
32
+ @datasets << WorldDataset.new( name, opts )
33
+ end
34
+
35
+
36
+ def run()
37
+ logger.info( "[builder] begin - run" )
38
+ download() # step 1 - download zips for datasets
39
+ read() # step 2 - read in datasets from zips
40
+ logger.info( "[builder] end - run" )
41
+ end
42
+
43
+ def download()
44
+ logger.info( "[builder] dowload" )
45
+ @datasets.each do |dataset|
46
+ dataset.download()
47
+ end
48
+ end
49
+
50
+ def read()
51
+ logger.info( "[builder] read" )
52
+ @datasets.each do |dataset|
53
+ dataset.read()
54
+ end
55
+ end
56
+
57
+ end # class Builder
58
+ end # module SportDb
@@ -0,0 +1,90 @@
1
+ # encoding: utf-8
2
+
3
+ module SportDb
4
+
5
+ class Dataset
6
+ include LogUtils::Logging
7
+
8
+ def initialize( name, opts={} )
9
+ @name = name
10
+ @opts = opts
11
+ end
12
+
13
+ def setup()
14
+ value = @opts[:setup] || 'all'
15
+ "setups/#{value}"
16
+ end
17
+
18
+ def remote_zip_url() # remote zip url
19
+ "https://github.com/#{@name}/archive/master.zip"
20
+ end
21
+
22
+ def local_zip_name()
23
+ ### note: replace / in name w/ --I--
24
+ ## e.g. flatten the filename, that is, do NOT include any folders
25
+ @name.gsub('/', '--I--') # note: will NOT include/return .zip extension
26
+ end
27
+
28
+ def local_zip_root()
29
+ "./tmp"
30
+ end
31
+
32
+ def local_zip_path() # local zip path
33
+ "#{local_zip_root}/#{local_zip_name}.zip"
34
+ end
35
+
36
+
37
+ def download()
38
+ logger.info( "[builder] download dataset '#{@name}'" )
39
+ logger.info( "[builder] from '#{remote_zip_url}'" )
40
+ logger.info( "[builder] to '#{local_zip_path}'..." )
41
+
42
+ download_blob( remote_zip_url, local_zip_path )
43
+ end
44
+
45
+ ####
46
+ # download tasks for zips
47
+ def download_blob( url, dest )
48
+ logger.info "downloading #{url} to #{dest}..."
49
+
50
+ ## make sure dest path exists
51
+ dest_p = File.dirname( dest )
52
+ FileUtils.mkdir_p( dest_p ) unless File.exists?( dest_p ) ## use Dir.exists?? why? why not??
53
+
54
+ worker = Fetcher::Worker.new
55
+ worker.copy( url, dest )
56
+ ## print some file stats
57
+ logger.debug " size: #{File.size(dest)} bytes"
58
+ end
59
+
60
+ end # class Dataset
61
+
62
+
63
+ class WorldDataset < Dataset
64
+
65
+ def initialize( name, opts={} )
66
+ super( name, opts )
67
+ end
68
+
69
+ def read()
70
+ logger.info( "[builder] read world-dataset '#{@name}', '#{setup}'" )
71
+
72
+ WorldDb.read_setup_from_zip( local_zip_name(), setup(), local_zip_root(), { skip_tags: true } )
73
+ end
74
+ end # class WorldDataset
75
+
76
+ class FootballDataset < Dataset
77
+
78
+ def initialize( name, opts={} )
79
+ super( name, opts )
80
+ end
81
+
82
+ def read()
83
+ logger.info( "[builder] read football-dataset '#{@name}', '#{setup}'" )
84
+
85
+ SportDb.read_setup_from_zip( local_zip_name(), setup(), local_zip_root() )
86
+ end
87
+ end # class FootballDataset
88
+
89
+
90
+ end # module SportDb
@@ -108,6 +108,34 @@ command [:create] do |c|
108
108
  end # command create
109
109
 
110
110
 
111
+ desc "Build DB (download/create/load); use ./Datafile - zips get downloaded to ./tmp"
112
+ command [:build,:b] do |c|
113
+
114
+ c.action do |g,o,args|
115
+
116
+ builder = SportDb::Builder.load_file( './Datafile' )
117
+ builder.download # builder step 1 - download all datasets/zips
118
+
119
+ connect_to_db( opts )
120
+
121
+ LogDb.create
122
+ ConfDb.create
123
+ TagDb.create
124
+ WorldDb.create
125
+ PersonDb.create
126
+ SportDb.create
127
+
128
+ SportDb.read_builtin # e.g. seasons.txt etc
129
+
130
+ builder.read # builder step 2 - read all datasets
131
+
132
+ puts 'Done.'
133
+ end # action
134
+ end # command setup
135
+
136
+
137
+
138
+
111
139
  desc "Create DB schema 'n' load all world and sports data"
112
140
  arg_name 'NAME' # optional setup profile name
113
141
  command [:setup,:s] do |c|
@@ -5,7 +5,160 @@ module SportDb
5
5
 
6
6
  class ZipReader < ReaderBase
7
7
 
8
+ def initialize( name, include_path, opts = {} )
8
9
 
10
+ ## todo/fix: make include_path an opts (included in opts?) - why? why not??
11
+
12
+ path = "#{include_path}/#{name}.zip"
13
+ ## todo: check if zip exists
14
+
15
+ @zip_file = Zip::File.open( path ) ## NOTE: do NOT create if file is missing; let it crash
16
+
17
+ ### allow prefix (path) in name
18
+ ### e.g. assume all files relative to setup manifest
19
+ ## e.g. at-austria-master/setups/all.txt or
20
+ ## be-belgium-master/setups/all.txt
21
+ ## for
22
+ ## setups/all.txt
23
+ ###
24
+ ## will get (re)set w/ fixture/setup reader
25
+ ##
26
+ ## todo/fix: change/rename to @relative_path ?? - why? why not?
27
+ @zip_prefix = ''
28
+ end
29
+
30
+ def close
31
+ ## todo/check: add a close method - why? why not ???
32
+ @zip_file.close
33
+ end
34
+
35
+
36
+ def create_fixture_reader( name )
37
+ ## e.g. pass in => setups/all or setups/test etc. e.g. w/o .txt extension
38
+ query = "**/#{name}.txt"
39
+
40
+ ## note: returns an array of Zip::Entry
41
+ candidates = @zip_file.glob( query )
42
+ pp candidates
43
+
44
+ ## use first candidates entry as match
45
+ ## todo/fix: issue warning if more than one entries/matches!!
46
+
47
+ ## get fullpath e.g. at-austria-master/setups/all.txt
48
+ path = candidates[0].name
49
+ logger.debug " zip entry path >>#{path}<<"
50
+
51
+ ## cut-off at-austria-master/ NOTE: includes trailing slash (if present)
52
+ ## logger.debug " path.size #{path.size} >>#{path}<<"
53
+ ## logger.debug " name.size #{name.size+4} >>#{name}<<"
54
+
55
+ ## note: add +4 for extension (.txt)
56
+ @zip_prefix = path[ 0...(path.size-(name.size+4)) ]
57
+ logger.debug " zip entry prefix >>#{@zip_prefix}<<"
58
+
59
+ logger.info "parsing data in zip '#{name}' (#{path})..."
60
+
61
+ FixtureReader.from_zip( @zip_file, path )
62
+ end
63
+
64
+ def create_club_squad_reader( name, more_attribs={} )
65
+ path = name_to_zip_entry_path( name )
66
+
67
+ logger.info "parsing data in zip (club squad) '#{name}' (#{path})..."
68
+ ClubSquadReader.from_zip( @zip_file, path, more_attribs )
69
+ end
70
+
71
+ def create_national_team_squad_reader( name, more_attribs={} )
72
+ path = name_to_zip_entry_path( name )
73
+
74
+ logger.info "parsing data in zip (national team squad) '#{name}' (#{path})..."
75
+ NationalTeamSquadReader.from_zip( @zip_file, path, more_attribs )
76
+ end
77
+
78
+ def create_season_reader( name )
79
+ path = name_to_zip_entry_path( name )
80
+
81
+ logger.info "parsing data in zip (season) '#{name}' (#{path})..."
82
+ SeasonReader.from_zip( @zip_file, path )
83
+ end
84
+
85
+ def create_assoc_reader( name )
86
+ path = name_to_zip_entry_path( name )
87
+
88
+ logger.info "parsing data in zip (assoc) '#{name}' (#{path})..."
89
+ AssocReader.from_zip( @zip_file, path )
90
+ end
91
+
92
+ def create_ground_reader( name, more_attribs={} )
93
+ path = name_to_zip_entry_path( name )
94
+
95
+ logger.info "parsing data in zip (ground) '#{name}' (#{path})..."
96
+ GroundReader.from_zip( @zip_file, path, more_attribs )
97
+ end
98
+
99
+ def create_league_reader( name, more_attribs={} )
100
+ path = name_to_zip_entry_path( name )
101
+
102
+ logger.info "parsing data in zip (league) '#{name}' (#{path})..."
103
+ LeagueReader.from_zip( @zip_file, path, more_attribs )
104
+ end
105
+
106
+ def create_team_reader( name, more_attribs={} )
107
+ path = name_to_zip_entry_path( name )
108
+
109
+ logger.info "parsing data in zip (team) '#{name}' (#{path})..."
110
+ TeamReader.from_zip( @zip_file, path, more_attribs )
111
+ end
112
+
113
+ def create_event_reader( name, more_attribs={} )
114
+ path = name_to_zip_entry_path( name, '.yml' ) ## NOTE: use .yml extension
115
+
116
+ logger.info "parsing data in zip (event) '#{name}' (#{path})..."
117
+ EventReader.from_zip( @zip_file, path, more_attribs )
118
+ end
119
+
120
+ def create_game_reader( name, more_attribs={} )
121
+ ## NOTE: pass in .yml as path (that is, event config!!!!)
122
+ path = name_to_zip_entry_path( name, '.yml' ) ## NOTE: use .yml extension
123
+
124
+ logger.info "parsing data in zip (fixture) '#{name}' (#{path})..."
125
+ GameReader.from_zip( @zip_file, path, more_attribs )
126
+ end
127
+
128
+
129
+ def create_person_reader( name, more_attribs={} )
130
+ ## fix-fix-fix: change to new format e.g. from_file, from_zip etc!!!
131
+ ## reader = PersonDb::PersonReader.new( include_path )
132
+ # reader.read( name, country_id: country.id )
133
+ end
134
+
135
+ private
136
+
137
+ def path_to_real_path( path )
138
+ # map name to name_real_path
139
+ # name might include !/ for virtual path (gets cut off)
140
+ # e.g. at-austria!/w-wien/beers becomse w-wien/beers
141
+ pos = path.index( '!/')
142
+ if pos.nil?
143
+ path # not found; real path is the same as name
144
+ else
145
+ # cut off everything until !/ e.g.
146
+ # at-austria!/w-wien/beers becomes
147
+ # w-wien/beers
148
+ path[ (pos+2)..-1 ]
149
+ end
150
+ end
151
+
152
+ def name_to_zip_entry_path( name, extension='.txt' )
153
+ path = "#{name}#{extension}"
154
+
155
+ real_path = path_to_real_path( path )
156
+
157
+ # NOTE: add possible zip entry prefix path
158
+ # (if present includes trailing slash e.g. /)
159
+ entry_path = "#{@zip_prefix}#{real_path}"
160
+ entry_path
161
+ end
9
162
 
10
163
  end # class ZipReader
11
164
 
@@ -11,8 +11,15 @@ class AssocReader
11
11
  # e.g. lets you use Usage instead of Model::Usage
12
12
  include Models
13
13
 
14
+
14
15
  def self.from_zip( zip_file, entry_path, more_attribs={} )
15
- ## to be done
16
+ ## get text content from zip
17
+ entry = zip_file.find_entry( entry_path )
18
+
19
+ text = entry.get_input_stream().read()
20
+ text = text.force_encoding( Encoding::UTF_8 )
21
+
22
+ self.from_string( text, more_attribs )
16
23
  end
17
24
 
18
25
  def self.from_file( path, more_attribs={} )
@@ -15,7 +15,15 @@ class EventReader
15
15
  attr_reader :fixtures # fixtures/sources entry from event config
16
16
 
17
17
  def self.from_zip( zip_file, entry_path, more_attribs={} )
18
- ## to be done
18
+ ## get text content from zip
19
+ entry = zip_file.find_entry( entry_path )
20
+
21
+ text = entry.get_input_stream().read()
22
+ text = text.force_encoding( Encoding::UTF_8 )
23
+
24
+ config = File.basename( entry_path ) # name a of .yml file
25
+
26
+ self.from_string( text, config, more_attribs )
19
27
  end
20
28
 
21
29
  def self.from_file( path, more_attribs={} )
@@ -16,9 +16,46 @@ class GameReader
16
16
 
17
17
  include FixtureHelpers
18
18
 
19
-
20
19
  def self.from_zip( zip_file, entry_path, more_attribs={} )
21
- ## to be done
20
+
21
+ logger = LogKernel::Logger.root
22
+
23
+ reader = EventReader.from_zip( zip_file, entry_path )
24
+ reader.read()
25
+
26
+ event = reader.event ## was fetch_event( name )
27
+ fixtures = reader.fixtures ## was fetch_event_fixtures( name )
28
+
29
+ if fixtures.empty?
30
+ ## logger.warn "no fixtures found for event - >#{name}<; assume fixture name is the same as event"
31
+ ## change extension from .yml to .txt
32
+ fixtures_with_path = [ entry_path.sub('.yml','.txt') ]
33
+ else
34
+ ## add path to fixtures (use path from event e.g)
35
+ # - bl + at-austria!/2012_13/bl -> at-austria!/2012_13/bl
36
+ # - bl_ii + at-austria!/2012_13/bl -> at-austria!/2012_13/bl_ii
37
+
38
+ dir = File.dirname( entry_path ) # use dir for fixtures
39
+
40
+ fixtures_with_path = fixtures.map do |fx|
41
+ fx_new = "#{dir}/#{fx}.txt" # add path upfront
42
+ logger.debug "fx: #{fx_new} | >#{fx}< + >#{dir}<"
43
+ fx_new
44
+ end
45
+ end
46
+
47
+ ## fix-fix-fix: change file extension to ??
48
+ text_ary = []
49
+ fixtures_with_path.each do |fixture_path|
50
+ entry = zip_file.find_entry( fixture_path )
51
+
52
+ text = entry.get_input_stream().read()
53
+ text = text.force_encoding( Encoding::UTF_8 )
54
+
55
+ text_ary << text
56
+ end
57
+
58
+ self.from_string( event, text_ary, more_attribs )
22
59
  end
23
60
 
24
61
  def self.from_file( path, more_attribs={} )
@@ -12,7 +12,13 @@ class GroundReader
12
12
  include Models
13
13
 
14
14
  def self.from_zip( zip_file, entry_path, more_attribs={} )
15
- ## to be done
15
+ ## get text content from zip
16
+ entry = zip_file.find_entry( entry_path )
17
+
18
+ text = entry.get_input_stream().read()
19
+ text = text.force_encoding( Encoding::UTF_8 )
20
+
21
+ self.from_string( text, more_attribs )
16
22
  end
17
23
 
18
24
  def self.from_file( path, more_attribs={} )
@@ -13,7 +13,13 @@ class LeagueReader
13
13
 
14
14
 
15
15
  def self.from_zip( zip_file, entry_path, more_attribs={} )
16
- ## to be done
16
+ ## get text content from zip
17
+ entry = zip_file.find_entry( entry_path )
18
+
19
+ text = entry.get_input_stream().read()
20
+ text = text.force_encoding( Encoding::UTF_8 )
21
+
22
+ self.from_string( text, more_attribs )
17
23
  end
18
24
 
19
25
  def self.from_file( path, more_attribs={} )
@@ -13,7 +13,13 @@ class SeasonReader
13
13
 
14
14
 
15
15
  def self.from_zip( zip_file, entry_path )
16
- ## to be done
16
+ ## get text content from zip
17
+ entry = zip_file.find_entry( entry_path )
18
+
19
+ text = entry.get_input_stream().read()
20
+ text = text.force_encoding( Encoding::UTF_8 )
21
+
22
+ self.from_string( text )
17
23
  end
18
24
 
19
25
  def self.from_file( path )
@@ -23,7 +23,13 @@ class ClubSquadReader
23
23
 
24
24
 
25
25
  def self.from_zip( zip_file, entry_path, more_attribs={} )
26
- ## to be done
26
+ ## get text content from zip
27
+ entry = zip_file.find_entry( entry_path )
28
+
29
+ text = entry.get_input_stream().read()
30
+ text = text.force_encoding( Encoding::UTF_8 )
31
+
32
+ self.from_string( text, more_attribs )
27
33
  end
28
34
 
29
35
  def self.from_file( path, more_attribs={} )
@@ -20,7 +20,13 @@ class NationalTeamSquadReader
20
20
 
21
21
 
22
22
  def self.from_zip( zip_file, entry_path, more_attribs={} )
23
- ## to be done
23
+ ## get text content from zip
24
+ entry = zip_file.find_entry( entry_path )
25
+
26
+ text = entry.get_input_stream().read()
27
+ text = text.force_encoding( Encoding::UTF_8 )
28
+
29
+ self.from_string( text, more_attribs )
24
30
  end
25
31
 
26
32
  def self.from_file( path, more_attribs={} )
@@ -12,7 +12,13 @@ class TeamReader
12
12
  include Models
13
13
 
14
14
  def self.from_zip( zip_file, entry_path, more_attribs={} )
15
- ## to be done
15
+ ## get text content from zip
16
+ entry = zip_file.find_entry( entry_path )
17
+
18
+ text = entry.get_input_stream().read()
19
+ text = text.force_encoding( Encoding::UTF_8 )
20
+
21
+ self.from_string( text, more_attribs )
16
22
  end
17
23
 
18
24
  def self.from_file( path, more_attribs={} )
@@ -3,7 +3,7 @@ module SportDb
3
3
 
4
4
  MAJOR = 1 ## todo: namespace inside version or something - why? why not??
5
5
  MINOR = 9
6
- PATCH = 10
6
+ PATCH = 11
7
7
  VERSION = [MAJOR,MINOR,PATCH].join('.')
8
8
 
9
9
  def self.version
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+
3
+ ###
4
+ # to run use
5
+ # ruby -I ./lib -I ./test test/test_builder.rb
6
+
7
+ require 'helper'
8
+
9
+ class TestBuilder < MiniTest::Test
10
+
11
+ def test_builder
12
+ code =<<EOS
13
+ ## comments
14
+
15
+ world 'openmundi/world.db', setup: 'countries'
16
+
17
+ football 'openfootball/national-teams' ## NOTE: default is setup: 'all'
18
+
19
+ ### todo/fix: download archive only once(!!) even if included more than once
20
+ ## football 'openfootball/world-cup', setup: '2014_quali'
21
+
22
+ football 'openfootball/world-cup', setup: '2014'
23
+
24
+ ## more comments
25
+
26
+ EOS
27
+
28
+ builder = SportDb::Builder.load( code )
29
+ ## builder.run
30
+ ## builder.download
31
+ builder.read
32
+
33
+ assert true # if we get here - test success
34
+ end
35
+
36
+ end # class TestBuilder
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sportdb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.10
4
+ version: 1.9.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-22 00:00:00.000000000 Z
11
+ date: 2014-11-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: props
@@ -260,6 +260,8 @@ files:
260
260
  - data/seasons.txt
261
261
  - data/setups/all.txt
262
262
  - lib/sportdb.rb
263
+ - lib/sportdb/builder/builder.rb
264
+ - lib/sportdb/builder/dataset.rb
263
265
  - lib/sportdb/calc.rb
264
266
  - lib/sportdb/cli/main.rb
265
267
  - lib/sportdb/cli/opts.rb
@@ -372,6 +374,7 @@ files:
372
374
  - test/data/world-cup/teams_1974.txt
373
375
  - test/helper.rb
374
376
  - test/test_assoc_reader.rb
377
+ - test/test_builder.rb
375
378
  - test/test_changes.rb
376
379
  - test/test_cursor.rb
377
380
  - test/test_date.rb
@@ -435,6 +438,7 @@ test_files:
435
438
  - test/test_round_def.rb
436
439
  - test/test_utils.rb
437
440
  - test/test_reader_from_string.rb
441
+ - test/test_builder.rb
438
442
  - test/test_round_header.rb
439
443
  - test/test_round_auto.rb
440
444
  - test/test_goals.rb