sportdb-structs 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,9 +2,52 @@
2
2
  module Sports
3
3
 
4
4
 
5
+ class LeaguePeriod
6
+ attr_reader :key, :name, :qname, :slug,
7
+ :prev_name, :start_season, :end_season
8
+ def initialize( key:, name:, qname:, slug:,
9
+ prev_name: nil,
10
+ start_season: nil, end_season: nil )
11
+ @key = key
12
+ @name = name
13
+ @qname = qname
14
+ @slug = slug
15
+ @prev_name = prev_name
16
+ @start_season = start_season
17
+ @end_season = end_season
18
+ end
19
+
20
+
21
+ def pretty_print( printer )
22
+ buf = String.new
23
+ buf << "<LeaguePeriod"
24
+ buf << " #{@key}"
25
+ buf << " (#{@start_season}-#{@end_season})" if @start_season || @end_season
26
+ buf << " -"
27
+ buf << " #{@name}"
28
+ if @name != @qname
29
+ buf << " | #{@qname}"
30
+ else
31
+ buf << "*"
32
+ end
33
+ buf << ">"
34
+
35
+ printer.text( buf )
36
+ end
37
+ end # class LeaguePeriod
38
+
39
+
40
+ ################
41
+ # todo: add a type field -
42
+ # add a tier field - why? why not?
43
+ # e.g. league/cup (or national_league, national_cup, intl_cup, etc.?)
44
+ # e.g. 1st-tier, 2nd-tier, etc.
45
+
46
+
5
47
  class League
6
48
  attr_reader :key, :name, :country, :intl
7
49
  attr_accessor :alt_names
50
+ attr_accessor :periods
8
51
 
9
52
 
10
53
  def initialize( key:, name:, alt_names: [],
@@ -12,12 +55,15 @@ class League
12
55
  @key = key
13
56
  @name = name
14
57
  @alt_names = alt_names
15
-
58
+
16
59
  @country = country
17
60
  @intl = intl
18
61
  @clubs = clubs
62
+
63
+ @periods = [] ## change/rename to history - why? why not?
19
64
  end
20
65
 
66
+
21
67
  def intl?() @intl == true; end
22
68
  def national?() @intl == false; end
23
69
  alias_method :domestic?, :national?
@@ -27,35 +73,122 @@ class League
27
73
  alias_method :club?, :clubs?
28
74
  alias_method :national_team?, :national_teams?
29
75
 
30
- =begin
76
+
77
+ #############################
78
+ ### virtual helpers
79
+ ## 1) codes (returns uniq array of all codes in lowercase
80
+ ## incl. key, code and alt_codes in alt_names)
81
+ ## 2) names (returns uniq array of all names - with language tags stripped)
82
+ ##
83
+
84
+ ## note: split names into names AND codes
85
+ ## 1) key plus all lower case names are codes
86
+ ## 2) all upper case names are names AND codes
87
+ ## 3) all other names are names
88
+
89
+ ## only allow asci a to z (why? why not?)
90
+ ## excludes Ö1 or such (what else?)
91
+ ## allow space and dot - why? why not?
92
+ ## e.g. HNL 1
93
+ ## NB I or NB II etc.
94
+ IS_CODE_N_NAME_RE = %r{^
95
+ [\p{Lu}0-9. ]+
96
+ $}x
97
+ ## add space (or /) - why? why not?
98
+ IS_CODE_RE = %r{^
99
+ [\p{Ll}0-9.]+
100
+ $}x
101
+
102
+
103
+ def codes
104
+ ## change/rename to more_codes - why? why?
105
+ ## get reference (tier/canonicial) codes via periods!!!!
106
+
107
+ ## note - "auto-magically" downcase code (and code'n'name matches)!!
108
+ ## note - do NOT include key as code for now!!!
109
+ ##
110
+ ## todo/check - auto-remove space from code - why? why not?
111
+ ## e.g. NB I, NB II, HNL 1 => NBI, NBII, HBNL1, etc -
112
+ codes = []
113
+ alt_names.each do |name|
114
+ if IS_CODE_N_NAME_RE.match?( name )
115
+ codes << name.downcase
116
+ elsif IS_CODE_RE.match?( name )
117
+ codes << name
118
+ else ## assume name
119
+ ## do nothing - skip/ignore
120
+ end
121
+ end
122
+ codes.uniq
123
+ end
124
+
125
+
126
+ include SportDb::NameHelper # pulls-in strip_lang
127
+
128
+ def names
129
+ names = [@name]
130
+ alt_names.each do |name|
131
+ if IS_CODE_N_NAME_RE.match?( name )
132
+ names << name
133
+ elsif IS_CODE_RE.match?( name )
134
+ ## do nothing - skip/ignore
135
+ else ## assume name
136
+ names << strip_lang( name )
137
+ end
138
+ end
139
+
140
+ ## report duplicate names - why? why not
141
+ ## check for duplicates - simple check for now - fix/improve
142
+ ## todo/fix: (auto)remove duplicates - why? why not?
143
+ count = names.size
144
+ count_uniq = names.uniq.size
145
+ if count != count_uniq
146
+ puts "** !!! ERROR !!! - #{count-count_uniq} duplicate name(s):"
147
+ pp names
148
+ pp self
149
+ exit 1
150
+ end
151
+
152
+ names.uniq
153
+ end
154
+
155
+
156
+ =begin
31
157
  @alt_names=[],
32
158
  @clubs=true,
33
159
  @country=<Country: at - Austria (AUT)|Österreich [de], fifa|uefa)>,
34
160
  @intl=false,
35
161
  @key="at.1",
36
- @name="Bundesliga">,
162
+ @name="Bundesliga">,
37
163
  =end
38
164
 
39
- def pretty_print( printer )
165
+ def pretty_print( printer )
40
166
  buf = String.new
41
167
  buf << "<League"
42
168
  buf << " INTL" if @intl
43
- buf << if @clubs
44
- " CLUBS"
45
- else
169
+ buf << if @clubs
170
+ " CLUBS"
171
+ else
46
172
  " NATIONAL TEAMS"
47
- end
48
- buf << ": #{@key} - #{@name}"
49
- buf << "|#{@alt_names.join('|')}" if @alt_names && !@alt_names.empty?
50
- buf << ", #{@country.name} (#{@country.code})" if @country
51
- buf << ">"
52
-
53
- printer.text( buf )
54
- end
173
+ end
174
+ buf << ": #{@name}"
55
175
 
176
+ if @alt_names && !@alt_names.empty?
177
+ buf << "|"
178
+ buf << @alt_names.join('|')
179
+ end
56
180
 
181
+ buf << ", #{@country.name} (#{@country.code})" if @country
57
182
 
183
+ if @periods && !@periods.empty?
184
+ buf << ", "
185
+ buf << @periods.map{|period| period.key }.uniq.join('|')
186
+ end
187
+ buf << ">"
58
188
 
189
+ printer.text( buf )
190
+ end
59
191
  end # class League
60
192
 
193
+
61
194
  end # module Sports
@@ -181,12 +181,14 @@ class Match
181
181
 
182
182
 
183
183
  def as_json
184
- ##
184
+ #####
185
+ ## note - use string keys (NOT symbol for data keys)
186
+ ## for easier json compatibility
185
187
  data = {}
186
188
 
187
189
  ## check round
188
190
  if @round
189
- data[:round ] = if round.is_a?( Integer )
191
+ data['round'] = if round.is_a?( Integer )
190
192
  "Matchday #{@round}"
191
193
  else ## assume string
192
194
  @round
@@ -194,28 +196,28 @@ def as_json
194
196
  end
195
197
 
196
198
 
197
- data[:num] = @num if @num
199
+ data['num'] = @num if @num
198
200
  if @date
199
201
  ## assume 2020-09-19 date format!!
200
- data[:date] = @date.is_a?( String ) ? @date : @date.strftime('%Y-%m-%d')
202
+ data['date'] = @date.is_a?( String ) ? @date : @date.strftime('%Y-%m-%d')
201
203
 
202
- data[:time] = @time if @time
204
+ data['time'] = @time if @time
203
205
  end
204
206
 
205
- data[:team1] = @team1.is_a?( String ) ? @team1 : @team1.name
206
- data[:team2] = @team2.is_a?( String ) ? @team2 : @team2.name
207
+ data['team1'] = @team1.is_a?( String ) ? @team1 : @team1.name
208
+ data['team2'] = @team2.is_a?( String ) ? @team2 : @team2.name
207
209
 
208
- data[:score] = {}
210
+ data['score'] = {}
209
211
 
210
- data[:score][:ht] = [@score1i, @score2i] if @score1i && @score2i
211
- data[:score][:ft] = [@score1, @score2] if @score1 && @score2
212
- data[:score][:et] = [@score1et, @score2et] if @score1et && @score2et
213
- data[:score][:p] = [@score1p, @score2p] if @score1p && @score2p
212
+ data['score']['ht'] = [@score1i, @score2i] if @score1i && @score2i
213
+ data['score']['ft'] = [@score1, @score2] if @score1 && @score2
214
+ data['score']['et'] = [@score1et, @score2et] if @score1et && @score2et
215
+ data['score']['p'] = [@score1p, @score2p] if @score1p && @score2p
214
216
 
215
- data[:status] = @status if @status
217
+ data['status'] = @status if @status
216
218
 
217
- data[:group] = @group if @group
218
- data[:stage] = @stage if @stage
219
+ data['group'] = @group if @group
220
+ data['stage'] = @stage if @stage
219
221
 
220
222
  =begin
221
223
  "round": "Spieltag 1",
@@ -21,13 +21,14 @@ module Sports
21
21
  def pretty_print( printer )
22
22
  ## todo/check - how to display/format key - use () or not - why? why not?
23
23
  buf = String.new
24
- buf << "<Round: "
24
+ buf << "<Round"
25
+ buf << " AUTO" if @auto
26
+ buf << ": "
25
27
  buf << "(#{@num}) " if @num
26
28
  buf << "#{@name}, "
27
29
  buf << "#{@start_date}"
28
30
  buf << " - #{@end_date}" if @start_date != @end_date
29
31
  buf << " (knockout)" if @knockout
30
- buf << " (auto)" if @auto
31
32
  buf << ">"
32
33
 
33
34
  printer.text( buf )
@@ -64,7 +64,7 @@ class Team # shared base for clubs AND natinal_teams
64
64
 
65
65
  def initialize( **kwargs )
66
66
  @alt_names = []
67
-
67
+
68
68
  update( **kwargs ) unless kwargs.empty?
69
69
  end
70
70
 
@@ -89,14 +89,14 @@ class NationalTeam < Team
89
89
  self ## note - MUST return self for chaining
90
90
  end
91
91
 
92
- def pretty_print( printer )
92
+ def pretty_print( printer )
93
93
  buf = String.new
94
94
  buf << "<NationalTeam: #{@name}"
95
95
  ## use code from country or from team ???
96
- buf << " (#{@code})"
96
+ buf << " (#{@code})"
97
97
  buf << ">"
98
98
 
99
- printer.text( buf )
99
+ printer.text( buf )
100
100
  end
101
101
  end # class NationalTeam
102
102
 
@@ -121,8 +121,9 @@ class Club < Team
121
121
  def geos() @a == nil ? @geos : @a.geos; end
122
122
 
123
123
 
124
- def initialize( **kwargs )
125
- super
124
+ def initialize( auto: false, **kwargs )
125
+ @auto = auto
126
+ super( **kwargs ) ## todo/check - use super only or super() - must it always come first?
126
127
  end
127
128
 
128
129
  def update( **kwargs )
@@ -135,13 +136,15 @@ class Club < Team
135
136
  end
136
137
 
137
138
 
138
- def pretty_print( printer )
139
+ def pretty_print( printer )
139
140
  buf = String.new
140
- buf << "<Club: #{@name}"
141
+ buf << "<Club"
142
+ buf << " AUTO" if @auto
143
+ buf << ": #{@name}"
141
144
  buf << " (#{@country.code})" if @country
142
145
  buf << ">"
143
146
 
144
- printer.text( buf )
147
+ printer.text( buf )
145
148
  end
146
149
  end # class Club
147
150
 
@@ -3,8 +3,8 @@ module SportDb
3
3
  module Module
4
4
  module Structs
5
5
  MAJOR = 0 ## todo: namespace inside version or something - why? why not??
6
- MINOR = 4
7
- PATCH = 1
6
+ MINOR = 5
7
+ PATCH = 0
8
8
  VERSION = [MAJOR,MINOR,PATCH].join('.')
9
9
 
10
10
  def self.version
@@ -3,11 +3,16 @@ require 'alphabets' # unaccent, downcase_i18n, variants, ...
3
3
  require 'season/formats' # Season.parse, ...
4
4
  require 'score/formats'
5
5
 
6
+ require 'cocos' # pull-in for read_csv & more
7
+
6
8
 
7
9
  ###
8
10
  # our own code
9
11
  require_relative 'structs/version' # let version always go first
10
12
 
13
+ ## shared support helpers/machinery
14
+ require_relative 'structs/name_helper'
15
+
11
16
  require_relative 'structs/country'
12
17
  require_relative 'structs/league'
13
18
  require_relative 'structs/team'
@@ -24,9 +29,6 @@ require_relative 'structs/team_usage'
24
29
  require_relative 'structs/event_info'
25
30
 
26
31
 
27
- ## shared support helpers/machinery
28
- require_relative 'structs/name_helper'
29
-
30
32
 
31
33
  ##
32
34
  ## todo/fix - move "inline" player to structs/player file !!!!
@@ -76,7 +78,10 @@ module SportDb
76
78
  ## add "old" convenience aliases for structs - why? why not?
77
79
  ## todo/check: just use include Sports !!!!
78
80
  Country = ::Sports::Country
81
+ City = ::Sports::City
82
+
79
83
  League = ::Sports::League
84
+ LeaguePeriod = ::Sports::LeaguePeriod
80
85
  Group = ::Sports::Group
81
86
  Round = ::Sports::Round
82
87
  Match = ::Sports::Match
@@ -99,6 +104,38 @@ end # module SportDb
99
104
 
100
105
 
101
106
 
107
+ ###
108
+ # csv (tabular dataset) support / machinery
109
+ require_relative 'csv/match_status_parser'
110
+ require_relative 'csv/goal'
111
+ require_relative 'csv/goal_parser_csv'
112
+ require_relative 'csv/match_parser_csv'
113
+
114
+
115
+ ### add convenience shortcut helpers
116
+ module Sports
117
+ class Match
118
+ def self.read_csv( path, headers: nil, filters: nil, converters: nil, sep: nil )
119
+ SportDb::CsvMatchParser.read( path,
120
+ headers: headers,
121
+ filters: filters,
122
+ converters: converters,
123
+ sep: sep )
124
+ end
125
+
126
+ def self.parse_csv( txt, headers: nil, filters: nil, converters: nil, sep: nil )
127
+ SportDb::CsvMatchParser.parse( txt,
128
+ headers: headers,
129
+ filters: filters,
130
+ converters: converters,
131
+ sep: sep )
132
+ end
133
+ end # class Match
134
+ end # module Sports
135
+
136
+
137
+
138
+
102
139
  #####
103
140
  # note: add Sport and Football convenience alias - why? why not?
104
141
  Sport = Sports
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sportdb-structs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-09-28 00:00:00.000000000 Z
11
+ date: 2024-12-30 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: cocos
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.4.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 0.4.0
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: alphabets
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -78,14 +92,14 @@ dependencies:
78
92
  requirements:
79
93
  - - "~>"
80
94
  - !ruby/object:Gem::Version
81
- version: '4.1'
95
+ version: '4.2'
82
96
  type: :development
83
97
  prerelease: false
84
98
  version_requirements: !ruby/object:Gem::Requirement
85
99
  requirements:
86
100
  - - "~>"
87
101
  - !ruby/object:Gem::Version
88
- version: '4.1'
102
+ version: '4.2'
89
103
  description: sportdb-structs - sport data structures for matches, scores, leagues,
90
104
  seasons, rounds, groups, teams, clubs and more
91
105
  email: gerald.bauer@gmail.com
@@ -100,6 +114,10 @@ files:
100
114
  - Manifest.txt
101
115
  - README.md
102
116
  - Rakefile
117
+ - lib/sportdb/csv/goal.rb
118
+ - lib/sportdb/csv/goal_parser_csv.rb
119
+ - lib/sportdb/csv/match_parser_csv.rb
120
+ - lib/sportdb/csv/match_status_parser.rb
103
121
  - lib/sportdb/structs.rb
104
122
  - lib/sportdb/structs/country.rb
105
123
  - lib/sportdb/structs/event_info.rb
@@ -136,7 +154,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
136
154
  - !ruby/object:Gem::Version
137
155
  version: '0'
138
156
  requirements: []
139
- rubygems_version: 3.4.10
157
+ rubygems_version: 3.5.22
140
158
  signing_key:
141
159
  specification_version: 4
142
160
  summary: sportdb-structs - sport data structures for matches, scores, leagues, seasons,