sportdb-structs 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,84 +1,84 @@
1
-
2
- module Sports
3
-
4
-
5
- class TeamUsage
6
-
7
- class TeamUsageLine ## nested class
8
- attr_accessor :team,
9
- :matches, ## number of matches (played),
10
- :seasons, ## (optianl) array of seasons, use seasons.size for count
11
- :levels ## (optional) hash of levels (holds mapping level to TeamUsageLine)
12
-
13
- def initialize( team )
14
- @team = team
15
-
16
- @matches = 0
17
- @seasons = []
18
- @levels = {}
19
- end
20
- end # (nested) class TeamUsageLine
21
-
22
-
23
-
24
- def initialize( opts={} )
25
- @lines = {} # StandingsLines cached by team name/key
26
- end
27
-
28
-
29
- def update( matches, season: '?', level: nil )
30
- ## convenience - update all matches at once
31
- matches.each_with_index do |match,i| # note: index(i) starts w/ zero (0)
32
- update_match( match, season: season, level: level )
33
- end
34
- self # note: return self to allow chaining
35
- end
36
-
37
- def to_a
38
- ## return lines; sort
39
-
40
- # build array from hash
41
- ary = []
42
- @lines.each do |k,v|
43
- ary << v
44
- end
45
-
46
- ## for now sort just by name (a-z)
47
- ary.sort! do |l,r|
48
- ## note: reverse order (thus, change l,r to r,l)
49
- l.team <=> r.team
50
- end
51
-
52
- ary
53
- end # to_a
54
-
55
-
56
- private
57
- def update_match( m, season: '?', level: nil ) ## add a match
58
-
59
- line1 = @lines[ m.team1 ] ||= TeamUsageLine.new( m.team1 )
60
- line2 = @lines[ m.team2 ] ||= TeamUsageLine.new( m.team2 )
61
-
62
- line1.matches +=1
63
- line2.matches +=1
64
-
65
- ## include season if not seen before (allow season in multiple files!!!)
66
- line1.seasons << season unless line1.seasons.include?( season )
67
- line2.seasons << season unless line2.seasons.include?( season )
68
-
69
- if level
70
- line1_level = line1.levels[ level ] ||= TeamUsageLine.new( m.team1 )
71
- line2_level = line2.levels[ level ] ||= TeamUsageLine.new( m.team2 )
72
-
73
- line1_level.matches +=1
74
- line2_level.matches +=1
75
-
76
- line1_level.seasons << season unless line1_level.seasons.include?( season )
77
- line2_level.seasons << season unless line2_level.seasons.include?( season )
78
- end
79
- end # method update_match
80
-
81
-
82
- end # class TeamUsage
83
-
84
- end # module Sports
1
+
2
+ module Sports
3
+
4
+
5
+ class TeamUsage
6
+
7
+ class TeamUsageLine ## nested class
8
+ attr_accessor :team,
9
+ :matches, ## number of matches (played),
10
+ :seasons, ## (optianl) array of seasons, use seasons.size for count
11
+ :levels ## (optional) hash of levels (holds mapping level to TeamUsageLine)
12
+
13
+ def initialize( team )
14
+ @team = team
15
+
16
+ @matches = 0
17
+ @seasons = []
18
+ @levels = {}
19
+ end
20
+ end # (nested) class TeamUsageLine
21
+
22
+
23
+
24
+ def initialize( opts={} )
25
+ @lines = {} # StandingsLines cached by team name/key
26
+ end
27
+
28
+
29
+ def update( matches, season: '?', level: nil )
30
+ ## convenience - update all matches at once
31
+ matches.each_with_index do |match,i| # note: index(i) starts w/ zero (0)
32
+ update_match( match, season: season, level: level )
33
+ end
34
+ self # note: return self to allow chaining
35
+ end
36
+
37
+ def to_a
38
+ ## return lines; sort
39
+
40
+ # build array from hash
41
+ ary = []
42
+ @lines.each do |k,v|
43
+ ary << v
44
+ end
45
+
46
+ ## for now sort just by name (a-z)
47
+ ary.sort! do |l,r|
48
+ ## note: reverse order (thus, change l,r to r,l)
49
+ l.team <=> r.team
50
+ end
51
+
52
+ ary
53
+ end # to_a
54
+
55
+
56
+ private
57
+ def update_match( m, season: '?', level: nil ) ## add a match
58
+
59
+ line1 = @lines[ m.team1 ] ||= TeamUsageLine.new( m.team1 )
60
+ line2 = @lines[ m.team2 ] ||= TeamUsageLine.new( m.team2 )
61
+
62
+ line1.matches +=1
63
+ line2.matches +=1
64
+
65
+ ## include season if not seen before (allow season in multiple files!!!)
66
+ line1.seasons << season unless line1.seasons.include?( season )
67
+ line2.seasons << season unless line2.seasons.include?( season )
68
+
69
+ if level
70
+ line1_level = line1.levels[ level ] ||= TeamUsageLine.new( m.team1 )
71
+ line2_level = line2.levels[ level ] ||= TeamUsageLine.new( m.team2 )
72
+
73
+ line1_level.matches +=1
74
+ line2_level.matches +=1
75
+
76
+ line1_level.seasons << season unless line1_level.seasons.include?( season )
77
+ line2_level.seasons << season unless line2_level.seasons.include?( season )
78
+ end
79
+ end # method update_match
80
+
81
+
82
+ end # class TeamUsage
83
+
84
+ end # module Sports
@@ -4,7 +4,7 @@ module SportDb
4
4
  module Structs
5
5
  MAJOR = 0 ## todo: namespace inside version or something - why? why not??
6
6
  MINOR = 1
7
- PATCH = 1
7
+ PATCH = 2
8
8
  VERSION = [MAJOR,MINOR,PATCH].join('.')
9
9
 
10
10
  def self.version
@@ -1,13 +1,13 @@
1
- ## note: use the local version of sportdb gems
2
- $LOAD_PATH.unshift( File.expand_path( '../date-formats/lib' ))
3
- $LOAD_PATH.unshift( File.expand_path( '../score-formats/lib' ))
4
- $LOAD_PATH.unshift( File.expand_path( '../sportdb-langs/lib' ))
5
-
6
-
7
- ## minitest setup
8
- require 'minitest/autorun'
9
-
10
-
11
- ## our own code
12
- require 'sportdb/structs'
13
-
1
+ ## note: use the local version of sportdb gems
2
+ $LOAD_PATH.unshift( File.expand_path( '../date-formats/lib' ))
3
+ $LOAD_PATH.unshift( File.expand_path( '../score-formats/lib' ))
4
+ $LOAD_PATH.unshift( File.expand_path( '../sportdb-langs/lib' ))
5
+
6
+
7
+ ## minitest setup
8
+ require 'minitest/autorun'
9
+
10
+
11
+ ## our own code
12
+ require 'sportdb/structs'
13
+
@@ -1,57 +1,57 @@
1
- ###
2
- # to run use
3
- # ruby -I ./lib -I ./test test/test_match_status_parser.rb
4
-
5
-
6
- require 'helper'
7
-
8
-
9
- class TestMatchStatusParser < MiniTest::Test
10
-
11
- Status = SportDb::Status
12
- StatusParser = SportDb::StatusParser
13
-
14
- def test_find
15
- [['awarded [cancelled] canceled [ddd]', Status::CANCELLED],
16
- ['awarded [bbb; canceled] canceled [awarded; comments] eeee', Status::AWARDED],
17
- ['aaa bbb ccc ddd eeee', nil],
18
- ].each do |rec|
19
- line = rec[0]
20
- status_exp = rec[1]
21
- puts "line (before): >#{line}<"
22
- status = StatusParser.find!( line )
23
- puts "status: >#{status}<"
24
- puts "line (after): >#{line}<"
25
- puts
26
-
27
- if status_exp.nil?
28
- assert_nil status
29
- else
30
- assert_equal status_exp, status
31
- end
32
- end
33
- end # method test_find
34
-
35
- def test_parse
36
- [['cancelled ddd', Status::CANCELLED],
37
- ['CANCELLED', Status::CANCELLED],
38
- ['can.', Status::CANCELLED],
39
- ['awarded; comments', Status::AWARDED],
40
- ['awd. - comments', Status::AWARDED],
41
- ['aaa bbb ccc ddd eeee', nil],
42
- ].each do |rec|
43
- str = rec[0]
44
- status_exp = rec[1]
45
- status = StatusParser.parse( str )
46
-
47
- if status_exp.nil? ## for "silencing" minitest warning - Use assert_nil if expecting nil
48
- assert_nil status
49
- else
50
- assert_equal status_exp, status
51
- end
52
- end
53
- end
54
-
55
- end # class TestMatchStatusParser
56
-
57
-
1
+ ###
2
+ # to run use
3
+ # ruby -I ./lib -I ./test test/test_match_status_parser.rb
4
+
5
+
6
+ require 'helper'
7
+
8
+
9
+ class TestMatchStatusParser < MiniTest::Test
10
+
11
+ Status = SportDb::Status
12
+ StatusParser = SportDb::StatusParser
13
+
14
+ def test_find
15
+ [['awarded [cancelled] canceled [ddd]', Status::CANCELLED],
16
+ ['awarded [bbb; canceled] canceled [awarded; comments] eeee', Status::AWARDED],
17
+ ['aaa bbb ccc ddd eeee', nil],
18
+ ].each do |rec|
19
+ line = rec[0]
20
+ status_exp = rec[1]
21
+ puts "line (before): >#{line}<"
22
+ status = StatusParser.find!( line )
23
+ puts "status: >#{status}<"
24
+ puts "line (after): >#{line}<"
25
+ puts
26
+
27
+ if status_exp.nil?
28
+ assert_nil status
29
+ else
30
+ assert_equal status_exp, status
31
+ end
32
+ end
33
+ end # method test_find
34
+
35
+ def test_parse
36
+ [['cancelled ddd', Status::CANCELLED],
37
+ ['CANCELLED', Status::CANCELLED],
38
+ ['can.', Status::CANCELLED],
39
+ ['awarded; comments', Status::AWARDED],
40
+ ['awd. - comments', Status::AWARDED],
41
+ ['aaa bbb ccc ddd eeee', nil],
42
+ ].each do |rec|
43
+ str = rec[0]
44
+ status_exp = rec[1]
45
+ status = StatusParser.parse( str )
46
+
47
+ if status_exp.nil? ## for "silencing" minitest warning - Use assert_nil if expecting nil
48
+ assert_nil status
49
+ else
50
+ assert_equal status_exp, status
51
+ end
52
+ end
53
+ end
54
+
55
+ end # class TestMatchStatusParser
56
+
57
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sportdb-structs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-09-15 00:00:00.000000000 Z
11
+ date: 2020-11-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: alphabets
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: 0.1.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: season-formats
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 0.0.1
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 0.0.1
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: csvreader
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -84,30 +98,36 @@ dependencies:
84
98
  name: rdoc
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
- - - "~>"
101
+ - - ">="
88
102
  - !ruby/object:Gem::Version
89
103
  version: '4.0'
104
+ - - "<"
105
+ - !ruby/object:Gem::Version
106
+ version: '7'
90
107
  type: :development
91
108
  prerelease: false
92
109
  version_requirements: !ruby/object:Gem::Requirement
93
110
  requirements:
94
- - - "~>"
111
+ - - ">="
95
112
  - !ruby/object:Gem::Version
96
113
  version: '4.0'
114
+ - - "<"
115
+ - !ruby/object:Gem::Version
116
+ version: '7'
97
117
  - !ruby/object:Gem::Dependency
98
118
  name: hoe
99
119
  requirement: !ruby/object:Gem::Requirement
100
120
  requirements:
101
121
  - - "~>"
102
122
  - !ruby/object:Gem::Version
103
- version: '3.16'
123
+ version: '3.22'
104
124
  type: :development
105
125
  prerelease: false
106
126
  version_requirements: !ruby/object:Gem::Requirement
107
127
  requirements:
108
128
  - - "~>"
109
129
  - !ruby/object:Gem::Version
110
- version: '3.16'
130
+ version: '3.22'
111
131
  description: sportdb-structs - sport data structures for matches, scores, leagues,
112
132
  seasons, rounds, groups, teams, clubs and more
113
133
  email: opensport@googlegroups.com
@@ -128,7 +148,6 @@ files:
128
148
  - lib/sportdb/structs/match_parser_csv.rb
129
149
  - lib/sportdb/structs/match_status_parser.rb
130
150
  - lib/sportdb/structs/name_helper.rb
131
- - lib/sportdb/structs/season.rb
132
151
  - lib/sportdb/structs/structs/country.rb
133
152
  - lib/sportdb/structs/structs/goal.rb
134
153
  - lib/sportdb/structs/structs/group.rb
@@ -146,7 +165,6 @@ files:
146
165
  - test/test_match.rb
147
166
  - test/test_match_status_parser.rb
148
167
  - test/test_name_helper.rb
149
- - test/test_season.rb
150
168
  homepage: https://github.com/sportdb/sport.db
151
169
  licenses:
152
170
  - Public Domain
@@ -1,199 +0,0 @@
1
-
2
- ### note: make Season like Date a "top-level" / "generic" class
3
-
4
-
5
- class Season
6
- ##
7
- ## todo: add (optional) start_date and end_date - why? why not?
8
-
9
- ## todo/todo/todo/check/check/check !!!
10
- ## todo: add a kernel Seaons e.g. Season('2011/12')
11
- ## forward to Season.convert( *args ) - why? why not?
12
-
13
- ## todo: add unicode - too - why? why not? see wikipedia pages, for example
14
-
15
- YYYY_YYYY_RE = %r{^ ## e.g. 2011-2012 or 2011/2012
16
- (\d{4})
17
- [/-]
18
- (\d{4})
19
- $
20
- }x
21
- YYYY_YY_RE = %r{^ ## e.g. 2011-12 or 2011/12
22
- (\d{4})
23
- [/-]
24
- (\d{2})
25
- $
26
- }x
27
- YYYY_Y_RE = %r{^ ## e.g. 2011-2 or 2011/2
28
- (\d{4})
29
- [/-]
30
- (\d{1})
31
- $
32
- }x
33
- YYYY_RE = %r{^ ## e.g. 2011
34
- (\d{4})
35
- $
36
- }x
37
-
38
-
39
- def self.parse( str )
40
- new( *_parse( str ))
41
- end
42
-
43
- def self._parse( str ) ## "internal" parse helper
44
- if str =~ YYYY_YYYY_RE ## e.g. 2011/2012
45
- [$1.to_i, $2.to_i]
46
- elsif str =~ YYYY_YY_RE ## e.g. 2011/12
47
- fst = $1.to_i
48
- snd = $2.to_i
49
- snd_exp = '%02d' % [(fst+1) % 100] ## double check: e.g 00 == 00, 01==01 etc.
50
- raise ArgumentError, "[Season.parse] invalid year in season >>#{str}<<; expected #{snd_exp} but got #{$2}" if snd_exp != $2
51
- [fst, fst+1]
52
- elsif str =~ YYYY_Y_RE ## e.g. 2011/2
53
- fst = $1.to_i
54
- snd = $2.to_i
55
- snd_exp = '%d' % [(fst+1) % 10] ## double check: e.g 0 == 0, 1==1 etc.
56
- raise ArgumentError, "[Season.parse] invalid year in season >>#{str}<<; expected #{snd_exp} but got #{$2}" if snd_exp != $2
57
- [fst, fst+1]
58
- elsif str =~ YYYY_RE ## e.g. 2011
59
- [$1.to_i]
60
- else
61
- raise ArgumentError, "[Season.parse] unkown season format >>#{str}<<; sorry cannot parse"
62
- end
63
- end
64
-
65
-
66
- def self.convert( *args ) ## note: used by Kernel method Season()
67
- if args.size == 1 && args[0].is_a?( Season )
68
- args[0] # pass through / along as is 1:1
69
- elsif args.size == 1 && args[0].is_a?( String )
70
- parse( args[0] )
71
- elsif args.size == 1 && args[0].is_a?( Integer ) && args[0] > 9999
72
- ## note: allow convenience "hack" such as:
73
- # 202021 or 2020_21 => '2020/21' or
74
- # 2020_1 or 2020_1 => '2020/21' or
75
- # 20202021 or 2020_2021 => '2020/21'
76
- str = args[0].to_s
77
- parse( "#{str[0..3]}/#{str[4..-1]}" )
78
- else ## assume all integer args e.g. 2020 or 2020, 2021 and such
79
- new( *args ) ## try conversion with new
80
- end
81
- end
82
-
83
-
84
- attr_reader :start_year,
85
- :end_year
86
-
87
- def initialize( *args ) ## change args to years - why? why not?
88
- if args.size == 1 && args[0].is_a?( Integer )
89
- @start_year = args[0]
90
- @end_year = args[0]
91
- elsif args.size == 2 && args[0].is_a?( Integer ) &&
92
- args[1].is_a?( Integer )
93
- @start_year = args[0]
94
- @end_year = args[1]
95
- end_year_exp = @start_year+1
96
- raise ArgumentError, "[Season] invalid year in season >>#{to_s}<<; expected #{end_year_exp} but got #{@end_year}" if end_year_exp != @end_year
97
- else
98
- pp args
99
- raise ArgumentError, "[Season] expected season start year (integer) with opt. end year"
100
- end
101
- end
102
-
103
-
104
-
105
- ## convenience helper - move to sportdb or such - remove - why - why not???
106
- def start_date ## generate "generic / syntetic start date" - keep helper - why? why not?
107
- if year?
108
- Date.new( start_year, 1, 1 )
109
- else
110
- Date.new( start_year 1, 7 )
111
- end
112
- end
113
-
114
-
115
- ## single-year season e.g. 2011 if start_year is end_year - todo - find a better name?
116
- def year?() @start_year == @end_year; end
117
-
118
- def prev
119
- if year?
120
- Season.new( @start_year-1 )
121
- else
122
- Season.new( @start_year-1, @end_year-1 )
123
- end
124
- end
125
-
126
- def next
127
- if year?
128
- Season.new( @start_year+1 )
129
- else
130
- Season.new( @start_year+1, @end_year+1 )
131
- end
132
- end
133
- alias_method :succ, :next ## add support for ranges
134
-
135
-
136
- include Comparable
137
- def <=>(other)
138
- ## todo/fix/fix: check if other is_a?( Season )!!!
139
- ## what to return if other type/class ??
140
- ## note: check special edge case - year season and other e.g.
141
- ## 2010 <=> 2010/2011
142
-
143
- res = @start_year <=> other.start_year
144
- res = @end_year <=> other.end_year if res == 0
145
- res
146
- end
147
-
148
-
149
- def to_formatted_s( format=:default, sep: '/' )
150
- if year?
151
- '%d' % @start_year
152
- else
153
- case format
154
- when :default, :short, :s ## e.g. 1999/00 or 2019/20
155
- "%d#{sep}%02d" % [@start_year, @end_year % 100]
156
- when :long, :l ## e.g. 1999/2000 or 2019/2020
157
- "%d#{sep}%d" % [@start_year, @end_year]
158
- else
159
- raise ArgumentError, "[Season.to_s] unsupported format >#{format}<"
160
- end
161
- end
162
- end
163
- alias_method :to_s, :to_formatted_s
164
-
165
- def key() to_s( :short ); end
166
- alias_method :to_key, :key
167
- alias_method :name, :key
168
- alias_method :title, :key
169
-
170
- alias_method :inspect, :key ## note: add inspect debug support change debug output to string!!
171
-
172
-
173
-
174
- def to_path( format=:default )
175
- case format
176
- when :default, :short, :s ## e.g. 1999-00 or 2019-20
177
- to_s( :short, sep: '-' )
178
- when :long, :l ## e.g. 1999-2000 or 2019-2000
179
- to_s( :long, sep: '-' )
180
- when :archive, :decade, :d ## e.g. 1990s/1999-00 or 2010s/2019-20
181
- "%3d0s/%s" % [@start_year / 10, to_s( :short, sep: '-' )]
182
- when :century, :c ## e.g. 1900s/1990-00 or 2000s/2019-20
183
- "%2d00s/%s" % [@start_year / 100, to_s( :short, sep: '-' )]
184
- else
185
- raise ArgumentError, "[Season.to_path] unsupported format >#{format}<"
186
- end
187
- end # method to_path
188
- alias_method :directory, :to_path ## keep "legacy" directory alias - why? why not?
189
- alias_method :path, :to_path
190
-
191
- end # class Season
192
-
193
-
194
-
195
- ### note: add a convenience "shortcut" season kernel method conversion method
196
- ## use like Season( '2012/3' ) or such
197
- module Kernel
198
- def Season( *args ) Season.convert( *args ); end
199
- end