sportdb-structs 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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,