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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -1
- data/Manifest.txt +4 -0
- data/Rakefile +1 -0
- data/lib/sportdb/csv/goal.rb +192 -0
- data/lib/sportdb/csv/goal_parser_csv.rb +28 -0
- data/lib/sportdb/csv/match_parser_csv.rb +490 -0
- data/lib/sportdb/csv/match_status_parser.rb +63 -0
- data/lib/sportdb/structs/country.rb +101 -5
- data/lib/sportdb/structs/league.rb +148 -15
- data/lib/sportdb/structs/match.rb +17 -15
- data/lib/sportdb/structs/round.rb +3 -2
- data/lib/sportdb/structs/team.rb +12 -9
- data/lib/sportdb/structs/version.rb +2 -2
- data/lib/sportdb/structs.rb +40 -3
- metadata +23 -5
@@ -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
|
-
|
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 << ": #{@
|
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[
|
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[
|
199
|
+
data['num'] = @num if @num
|
198
200
|
if @date
|
199
201
|
## assume 2020-09-19 date format!!
|
200
|
-
data[
|
202
|
+
data['date'] = @date.is_a?( String ) ? @date : @date.strftime('%Y-%m-%d')
|
201
203
|
|
202
|
-
data[
|
204
|
+
data['time'] = @time if @time
|
203
205
|
end
|
204
206
|
|
205
|
-
data[
|
206
|
-
data[
|
207
|
+
data['team1'] = @team1.is_a?( String ) ? @team1 : @team1.name
|
208
|
+
data['team2'] = @team2.is_a?( String ) ? @team2 : @team2.name
|
207
209
|
|
208
|
-
data[
|
210
|
+
data['score'] = {}
|
209
211
|
|
210
|
-
data[
|
211
|
-
data[
|
212
|
-
data[
|
213
|
-
data[
|
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[
|
217
|
+
data['status'] = @status if @status
|
216
218
|
|
217
|
-
data[
|
218
|
-
data[
|
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 )
|
data/lib/sportdb/structs/team.rb
CHANGED
@@ -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
|
-
|
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
|
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
|
|
data/lib/sportdb/structs.rb
CHANGED
@@ -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
|
+
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-
|
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.
|
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.
|
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.
|
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,
|