sports 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,16 +0,0 @@
1
- module Sports
2
-
3
- class Group
4
- attr_reader :key, :name, :teams
5
-
6
- def initialize( key: nil,
7
- name:,
8
- teams: )
9
- @key = key ## e.g. A,B,C or 1,2,3, - note: always a string or nil
10
- @name = name
11
- @teams = teams
12
- end
13
- end # class Group
14
-
15
- end # module Sports
16
-
@@ -1,35 +0,0 @@
1
-
2
- module Sports
3
-
4
-
5
- class League
6
- attr_reader :key, :name, :country, :intl
7
- attr_accessor :alt_names
8
-
9
- ## special import only attribs
10
- attr_accessor :alt_names_auto ## auto-generated alt names
11
-
12
- def initialize( key:, name:, alt_names: [], alt_names_auto: [],
13
- country: nil, intl: false, clubs: true )
14
- @key = key
15
- @name = name
16
- @alt_names = alt_names
17
- @alt_names_auto = alt_names_auto
18
-
19
- @country = country
20
- @intl = intl
21
- @clubs = clubs
22
- end
23
-
24
- def intl?() @intl == true; end
25
- def national?() @intl == false; end
26
- alias_method :domestic?, :national?
27
-
28
- def clubs?() @clubs == true; end
29
- def national_teams?() @clubs == false; end
30
- alias_method :club?, :clubs?
31
- alias_method :national_team?, :national_teams?
32
-
33
- end # class League
34
-
35
- end # module Sports
@@ -1,180 +0,0 @@
1
-
2
- module Sports
3
-
4
-
5
- class Match
6
-
7
- attr_reader :date,
8
- :time,
9
- :team1, :team2, ## todo/fix: use team1_name, team2_name or similar - for compat with db activerecord version? why? why not?
10
- :score1, :score2, ## full time
11
- :score1i, :score2i, ## half time (first (i) part)
12
- :score1et, :score2et, ## extra time
13
- :score1p, :score2p, ## penalty
14
- :score1agg, :score2agg, ## full time (all legs) aggregated
15
- :winner, # return 1,2,0 1 => team1, 2 => team2, 0 => draw/tie
16
- :round, ## todo/fix: use round_num or similar - for compat with db activerecord version? why? why not?
17
- :leg, ## e.g. '1','2','3','replay', etc. - use leg for marking **replay** too - keep/make leg numeric?! - why? why not?
18
- :stage,
19
- :group,
20
- :status, ## e.g. replay, cancelled, awarded, abadoned, postponed, etc.
21
- :conf1, :conf2, ## special case for mls e.g. conference1, conference2 (e.g. west, east, central)
22
- :country1, :country2, ## special case for champions league etc. - uses FIFA country code
23
- :comments,
24
- :league ## (optinal) added as text for now (use struct?)
25
-
26
-
27
- attr_accessor :goals ## todo/fix: make goals like all other attribs!!
28
-
29
- def initialize( **kwargs )
30
- @score1 = @score2 = nil ## full time
31
- @score1i = @score2i = nil ## half time (first (i) part)
32
- @score1et = @score2et = nil ## extra time
33
- @score1p = @score2p = nil ## penalty
34
- @score1agg = @score2agg = nil ## full time (all legs) aggregated
35
-
36
-
37
- update( kwargs ) unless kwargs.empty?
38
- end
39
-
40
- def update( **kwargs )
41
- ## note: check with has_key? because value might be nil!!!
42
- @date = kwargs[:date] if kwargs.has_key? :date
43
- @time = kwargs[:time] if kwargs.has_key? :time
44
-
45
- ## todo/fix: use team1_name, team2_name or similar - for compat with db activerecord version? why? why not?
46
- @team1 = kwargs[:team1] if kwargs.has_key? :team1
47
- @team2 = kwargs[:team2] if kwargs.has_key? :team2
48
-
49
- @conf1 = kwargs[:conf1] if kwargs.has_key? :conf1
50
- @conf2 = kwargs[:conf2] if kwargs.has_key? :conf2
51
- @country1 = kwargs[:country1] if kwargs.has_key? :country1
52
- @country2 = kwargs[:country2] if kwargs.has_key? :country2
53
-
54
- ## note: round is a string!!! e.g. '1', '2' for matchday or 'Final', 'Semi-final', etc.
55
- ## todo: use to_s - why? why not?
56
- @round = kwargs[:round] if kwargs.has_key? :round
57
- @stage = kwargs[:stage] if kwargs.has_key? :stage
58
- @leg = kwargs[:leg] if kwargs.has_key? :leg
59
- @group = kwargs[:group] if kwargs.has_key? :group
60
- @status = kwargs[:status] if kwargs.has_key? :status
61
- @comments = kwargs[:comments] if kwargs.has_key? :comments
62
-
63
- @league = kwargs[:league] if kwargs.has_key? :league
64
-
65
-
66
- if kwargs.has_key?( :score ) ## check all-in-one score struct for convenience!!!
67
- score = kwargs[:score]
68
- if score.nil? ## reset all score attribs to nil!!
69
- @score1 = nil
70
- @score1i = nil
71
- @score1et = nil
72
- @score1p = nil
73
- ## @score1agg = nil
74
-
75
- @score2 = nil
76
- @score2i = nil
77
- @score2et = nil
78
- @score2p = nil
79
- ## @score2agg = nil
80
- else
81
- @score1 = score.score1
82
- @score1i = score.score1i
83
- @score1et = score.score1et
84
- @score1p = score.score1p
85
- ## @score1agg = score.score1agg
86
-
87
- @score2 = score.score2
88
- @score2i = score.score2i
89
- @score2et = score.score2et
90
- @score2p = score.score2p
91
- ## @score2agg = score.score2agg
92
- end
93
- else
94
- @score1 = kwargs[:score1] if kwargs.has_key? :score1
95
- @score1i = kwargs[:score1i] if kwargs.has_key? :score1i
96
- @score1et = kwargs[:score1et] if kwargs.has_key? :score1et
97
- @score1p = kwargs[:score1p] if kwargs.has_key? :score1p
98
- @score1agg = kwargs[:score1agg] if kwargs.has_key? :score1agg
99
-
100
- @score2 = kwargs[:score2] if kwargs.has_key? :score2
101
- @score2i = kwargs[:score2i] if kwargs.has_key? :score2i
102
- @score2et = kwargs[:score2et] if kwargs.has_key? :score2et
103
- @score2p = kwargs[:score2p] if kwargs.has_key? :score2p
104
- @score2agg = kwargs[:score2agg] if kwargs.has_key? :score2agg
105
-
106
- ## note: (always) (auto-)convert scores to integers
107
- @score1 = @score1.to_i if @score1
108
- @score1i = @score1i.to_i if @score1i
109
- @score1et = @score1et.to_i if @score1et
110
- @score1p = @score1p.to_i if @score1p
111
- @score1agg = @score1agg.to_i if @score1agg
112
-
113
- @score2 = @score2.to_i if @score2
114
- @score2i = @score2i.to_i if @score2i
115
- @score2et = @score2et.to_i if @score2et
116
- @score2p = @score2p.to_i if @score2p
117
- @score2agg = @score2agg.to_i if @score2agg
118
- end
119
-
120
- ## todo/fix:
121
- ## gr-greece/2014-15/G1.csv:
122
- ## G1,10/05/15,Niki Volos,OFI,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
123
- ##
124
-
125
- ## for now score1 and score2 must be present
126
- ## if @score1.nil? || @score2.nil?
127
- ## puts "** WARN: missing scores for match:"
128
- ## pp kwargs
129
- ## ## exit 1
130
- ## end
131
-
132
- ## todo/fix: auto-calculate winner
133
- # return 1,2,0 1 => team1, 2 => team2, 0 => draw/tie
134
- ### calculate winner - use 1,2,0
135
- ##
136
- ## move winner calc to score class - why? why not?
137
- if @score1 && @score2
138
- if @score1 > @score2
139
- @winner = 1
140
- elsif @score2 > @score1
141
- @winner = 2
142
- elsif @score1 == @score2
143
- @winner = 0
144
- else
145
- end
146
- else
147
- @winner = nil # unknown / undefined
148
- end
149
-
150
- self ## note - MUST return self for chaining
151
- end
152
-
153
-
154
-
155
- def over?() true; end ## for now all matches are over - in the future check date!!!
156
- def complete?() true; end ## for now all scores are complete - in the future check scores; might be missing - not yet entered
157
-
158
-
159
- def score
160
- Score.new( @score1i, @score2i, ## half time (first (i) part)
161
- @score1, @score2, ## full time
162
- @score1et, @score2et, ## extra time
163
- @score1p, @score2p ) ## penalty
164
- end
165
-
166
-
167
- ####
168
- ## deprecated - use score.to_s and friends - why? why not?
169
- # def score_str # pretty print (full time) scores; convenience method
170
- # "#{@score1}-#{@score2}"
171
- # end
172
-
173
- # def scorei_str # pretty print (half time) scores; convenience method
174
- # "#{@score1i}-#{@score2i}"
175
- # end
176
- end # class Match
177
-
178
- end # module Sports
179
-
180
-
@@ -1,215 +0,0 @@
1
-
2
-
3
- module Sports
4
-
5
-
6
- class Matchlist ## todo: find a better name - MatchStats, MatchFixtures, MatchSchedule, ...
7
- ## use MatchCache/Buffer/Summary/Snippet/Segment/List...
8
- ## or MatchAnalyzer/Checker/Proofer/Query - why? why not?
9
- attr_reader :matches # count of matches
10
- ## :name,
11
- ## :goals, # count of (total) goals - use total_goals - why? why not?
12
- ## :teams, -- has its own reader
13
- ## :rounds # note: use if all teams have same match count
14
- ## add last_updated/updated or something - why? why not?
15
-
16
- def initialize( matches )
17
- @matches = matches
18
- end
19
-
20
-
21
- def usage
22
- @usage ||= build_usage( @matches )
23
- @usage
24
- end
25
-
26
- def team_usage() usage.team_usage; end
27
-
28
- def teams
29
- @team_names ||= team_usage.keys.sort
30
- @team_names
31
- end
32
-
33
- def goals() usage.goals; end
34
-
35
- ## note: start_date and end_date might be nil / optional missing!!!!
36
- def start_date?() usage.start_date?; end
37
- def end_date?() usage.end_date?; end
38
-
39
- def start_date() usage.start_date; end
40
- def end_date() usage.end_date; end
41
-
42
- def has_dates?() usage.has_dates?; end
43
- def dates_str() usage.dates_str; end
44
- def days() usage.days; end
45
-
46
-
47
- def rounds() usage.rounds; end
48
-
49
- ## todo: add has_rounds? alias for rounds? too
50
- ## return true if all match_played in team_usage are the same
51
- ## e.g. assumes league with matchday rounds
52
- def rounds?() usage.rounds?; end
53
-
54
- def match_counts() usage.match_counts; end
55
- def match_counts_str() usage.match_counts_str; end
56
-
57
-
58
-
59
- def stage_usage
60
- @stage_usage ||= build_stage_usage( @matches )
61
- @stage_usage
62
- end
63
-
64
- def stages() stage_usage.keys; end ## note: returns empty array for stages for now - why? why not?
65
-
66
-
67
- ############################
68
- # matchlist helpers
69
- private
70
- class StatLine
71
- attr_reader :team_usage,
72
- :matches,
73
- :goals,
74
- :rounds, ## keep rounds - why? why not?
75
- :start_date,
76
- :end_date
77
-
78
- def teams() @team_usage.keys.sort; end ## (auto-)sort here always - why? why not?
79
-
80
- def start_date?() @start_date.nil? == false; end
81
- def end_date?() @end_date.nil? == false; end
82
-
83
- def has_dates?() @start_date && @end_date; end
84
- def dates_str
85
- ## note: start_date/end_date might be optional/missing
86
- if has_dates?
87
- "#{start_date.strftime( '%a %d %b %Y' )} - #{end_date.strftime( '%a %d %b %Y' )}"
88
- else
89
- "??? - ???"
90
- end
91
- end
92
-
93
- def days() end_date.jd - start_date.jd; end
94
-
95
-
96
- def rounds
97
- rounds? ## note: use rounds? to calculate (cache) rounds
98
- @rounds ## note: return number of rounds or nil (for uneven matches played by teams)
99
- end
100
-
101
- ## todo: add has_rounds? alias for rounds? too
102
- def rounds?
103
- ## return true if all match_played in team_usage are the same
104
- ## e.g. assumes league with matchday rounds
105
- if @has_rounds.nil? ## check/todo: if undefined attribute is nil by default??
106
- ## check/calc rounds
107
- ## note: values => matches_played by team
108
- if match_counts.size == 1
109
- @rounds = match_counts[0][0]
110
- else
111
- @rounds = nil
112
- end
113
- @has_rounds = @rounds ? true : false
114
- end
115
- @has_rounds
116
- end
117
-
118
-
119
- def build_match_counts ## use/rename to matches_played - why? why not?
120
- counts = Hash.new(0)
121
- team_usage.values.each do |count|
122
- counts[count] += 1
123
- end
124
-
125
- ## sort (descending) highest usage value first (in returned array)
126
- ## e.g. [[32,8],[31,2]] ## 32 matches by 8 teams, 31 matches by 2 teams etc.
127
- counts.sort_by {|count, usage| -count }
128
- end
129
-
130
- def match_counts
131
- # match counts / nos played per team
132
- @match_counts ||= build_match_counts
133
- @match_counts
134
- end
135
-
136
- def match_counts_str
137
- ## pretty print / formatted match_counts
138
- buf = String.new('')
139
- match_counts.each_with_index do |rec,i|
140
- buf << ' ' if i > 0 ## add (space) separator
141
- buf << "#{rec[0]}×#{rec[1]}"
142
- end
143
- buf
144
- end
145
-
146
-
147
-
148
- def initialize
149
- @matches = 0
150
- @goals = 0
151
-
152
- @start_date = nil
153
- @end_date = nil
154
-
155
- @team_usage = Hash.new(0)
156
-
157
- @match_counts = nil
158
- end
159
-
160
-
161
- def update( match )
162
- @matches += 1 ## match counter
163
-
164
- if match.score1 && match.score2
165
- @goals += match.score1
166
- @goals += match.score2
167
-
168
- ## todo: add after extra time? if knock out (k.o.) - why? why not?
169
- ## make it a flag/opt?
170
- end
171
-
172
- @team_usage[ match.team1 ] += 1
173
- @team_usage[ match.team2 ] += 1
174
-
175
- if match.date
176
- ## return / store date as string as is - why? why not?
177
- date = Date.strptime( match.date, '%Y-%m-%d' )
178
-
179
- @start_date = date if @start_date.nil? || date < @start_date
180
- @end_date = date if @end_date.nil? || date > @end_date
181
- end
182
- end
183
- end # class StatLine
184
-
185
-
186
- ## collect total usage stats (for all matches)
187
- def build_usage( matches )
188
- stat = StatLine.new
189
- matches.each do |match|
190
- stat.update( match )
191
- end
192
- stat
193
- end
194
-
195
- ## collect usage stats by stage (e.g. regular / playoff / etc.)
196
- def build_stage_usage( matches )
197
- stages = {}
198
-
199
- matches.each do |match|
200
- stage_key = if match.stage.nil?
201
- 'Regular' ## note: assume Regular stage if not defined (AND not explicit unknown)
202
- else
203
- match.stage
204
- end
205
-
206
- stages[ stage_key ] ||= StatLine.new
207
- stages[ stage_key ].update( match )
208
- end
209
-
210
- stages
211
- end
212
-
213
- end # class Matchlist
214
-
215
- end # module Sports
@@ -1,23 +0,0 @@
1
- module Sports
2
-
3
- class Round
4
- attr_reader :name, :start_date, :end_date, :knockout
5
- attr_accessor :num # note: make read & writable - why? why not?
6
-
7
- def initialize( name:,
8
- num: nil,
9
- start_date: nil,
10
- end_date: nil,
11
- knockout: false,
12
- auto: true )
13
- @name = name
14
- @num = num
15
- @start_date = start_date
16
- @end_date = end_date
17
- @knockout = knockout
18
- @auto = auto # auto-created (inline reference/header without proper definition before)
19
- end
20
- end # class Round
21
-
22
- end # module Sports
23
-