sportdb-writers 0.4.3 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b08a4a77a08af12a0f8c7b9873c5115b8b8135e13e3b7d878ab246567a8ffa32
4
- data.tar.gz: a6e9f8f3b0933667f2fa4cf5eb7903c4410ead48e3647dfb903e261bb3f164be
3
+ metadata.gz: fd14b82e447eaf5824ab5b9636b9a91decee9d0962bb4c1b43d60e38c48e8a7e
4
+ data.tar.gz: 1b93a17a72cff8cab52b5f40929d57bbb3fa8c0d84a51ee0dc6b33b34028c4ae
5
5
  SHA512:
6
- metadata.gz: 1ebb1e1a90a196a992fef5eebf43baea0e613f559d73db25d8bd8812da67fe31bb4f286b767e7423c80f00d25d1c3f745972946448eaab8a3239e9f53a8d78fc
7
- data.tar.gz: 02342a063aef2f2604567a70a76e4caf48e49b555ab1b09fb7da996b6812547c17d684a053b3164f9b797de44e4c2a2c490a66b7865983d8d63fb78eda3294a8
6
+ metadata.gz: ef84ebdd48f0751fab889ec66f6a92a22827f192f4ccd9bf52cd6cec0c6c35578dda52c02538964333515f3d006cb2bd68ad63501ffc01218be88cf7f20ee54f
7
+ data.tar.gz: d0313c242c59d62aa6b9874acd0e16a35142e1945d6100d8d8a021544266ca548c6b9819856118781f58f72b2d84a9137f1d1c1b5ea498606961bc2de3bbe57c
data/CHANGELOG.md CHANGED
@@ -1,5 +1,4 @@
1
- ### 0.4.3
1
+ ### 0.5.0
2
2
  ### 0.0.1 / 2020-11-15
3
3
 
4
4
  * Everything is new. First release.
5
-
data/Manifest.txt CHANGED
@@ -3,7 +3,8 @@ Manifest.txt
3
3
  README.md
4
4
  Rakefile
5
5
  lib/sportdb/writers.rb
6
- lib/sportdb/writers/goals.rb
6
+ lib/sportdb/writers/build_goals.rb
7
+ lib/sportdb/writers/build_stats.rb
8
+ lib/sportdb/writers/rounds.rb
7
9
  lib/sportdb/writers/txt_writer.rb
8
- lib/sportdb/writers/txt_writer_v2.rb
9
10
  lib/sportdb/writers/version.rb
@@ -55,4 +55,50 @@ def self.merge_goals( matches, goals )
55
55
  end
56
56
 
57
57
 
58
+
59
+ def self.build_goals( goals )
60
+ ## todo/fix: for now assumes always minutes (without offset) - add offset support
61
+
62
+ ## note: "fold" multiple goals by players
63
+ team1_goals = {}
64
+ team2_goals = {}
65
+ goals.each do |goal|
66
+ team_goals = goal.team == 1 ? team1_goals : team2_goals
67
+ player_goals = team_goals[ goal.player ] ||= []
68
+ player_goals << goal
69
+ end
70
+
71
+ buf = String.new
72
+ if team1_goals.size > 0
73
+ buf << build_goals_for_team( team1_goals )
74
+ end
75
+
76
+ ## note: only add a separator (;) if BOTH teams have goal scores
77
+ if team1_goals.size > 0 && team2_goals.size > 0
78
+ buf << '; '
79
+ end
80
+
81
+ if team2_goals.size > 0
82
+ buf << build_goals_for_team( team2_goals )
83
+ end
84
+ buf
85
+ end
86
+
87
+
88
+ def self.build_goals_for_team( team_goals )
89
+ buf = String.new
90
+ team_goals.each_with_index do |(player_name, goals),i|
91
+ buf << ' ' if i > 0
92
+ buf << "#{player_name} "
93
+ buf << goals.map do |goal|
94
+ str = "#{goal.minute}'"
95
+ str << "(og)" if goal.owngoal?
96
+ str << "(p)" if goal.penalty?
97
+ str
98
+ end.join( ', ' )
99
+ end
100
+ buf
101
+ end
102
+
103
+
58
104
  end # module Writer
@@ -0,0 +1,95 @@
1
+ module SportDb
2
+ class TxtMatchWriter
3
+
4
+
5
+
6
+ ## helper - to calculate match stats e.g.
7
+ ## how many stages, start and end dates, etc.
8
+ def self._calc_stats( matches )
9
+ ### check for stages & stats
10
+ stats = { 'stage' => Hash.new(0),
11
+ 'date' => { 'start_date' => nil,
12
+ 'end_date' => nil, },
13
+ 'teams' => Hash.new(0),
14
+ 'matches' => 0,
15
+ 'use_stages' => false,
16
+ }
17
+
18
+ ## add matches played stats too??
19
+ ## for now only simply count used
20
+ stats['matches'] = matches.size
21
+
22
+ matches.each do |match|
23
+ stage = match.stage
24
+ stage = 'Regular Season' if stage.nil? || stage.empty?
25
+ stats['stage'][ stage ] += 1
26
+
27
+ ## note - date for now optional (not required)!!!!
28
+ ## only teams for match
29
+ if match.date
30
+ ## todo/fix - norm date (parse as Date)
31
+ ## check format etc.
32
+ date = if match.date.is_a?( String )
33
+ Date.strptime( match.date, '%Y-%m-%d' )
34
+ else ## assume it's already a date (object)
35
+ match.date
36
+ end
37
+ stats['date']['start_date'] ||= date
38
+ stats['date']['end_date'] ||= date
39
+
40
+ stats['date']['start_date'] = date if date < stats['date']['start_date']
41
+ stats['date']['end_date'] = date if date > stats['date']['end_date']
42
+ end
43
+
44
+ [match.team1, match.team2].each do |team|
45
+ stats['teams'][ team ] += 1 if team && !['N.N.'].include?( team )
46
+ end
47
+ end
48
+
49
+ ## add & update use_stage flag
50
+ stats['use_stages'] = if stats['stage'].size >= 2 ||
51
+ (stats['stage'].size == 1 &&
52
+ stats['stage'].keys[0] != 'Regular Season')
53
+ true
54
+ else
55
+ false
56
+ end
57
+ stats
58
+ end
59
+
60
+ def self._build_stats( stats )
61
+ ### add comment header
62
+ buf = String.new
63
+ # e.g. 13 April – 25 September 2024
64
+ # or 16 August 2024 – 25 May 2025
65
+ ## note - date is optional!!
66
+ if stats['date']['start_date']
67
+ buf << "# Date "
68
+ start_date = stats['date']['start_date']
69
+ end_date = stats['date']['end_date']
70
+ if start_date.year != end_date.year
71
+ buf << "#{start_date.strftime('%a %b %-d %Y')} - #{end_date.strftime('%a %b %-d %Y')}"
72
+ else
73
+ buf << "#{start_date.strftime('%a %b %-d')} - #{end_date.strftime('%a %b %-d %Y')}"
74
+ end
75
+ buf << " (#{end_date.jd-start_date.jd}d)" ## add days
76
+ buf << "\n"
77
+ end
78
+
79
+ buf << "# Teams #{stats['teams'].size}\n"
80
+ buf << "# Matches #{stats['matches']}\n"
81
+
82
+ if stats['use_stages']
83
+ buf << "# Stages "
84
+ stages = stats['stage'].map { |name,count| "#{name} (#{count})" }.join( ' ' )
85
+ buf << stages
86
+ buf << "\n"
87
+ end
88
+
89
+ buf
90
+ end
91
+
92
+
93
+
94
+ end # class TxtMatchWriter
95
+ end # module SportDb
@@ -0,0 +1,26 @@
1
+ module SportDb
2
+ class TxtMatchWriter
3
+
4
+
5
+
6
+ ## translate from lang x (german, etc) to english
7
+ ROUND_TRANSLATIONS = {
8
+ # de/german
9
+ '1. Runde' => 'Round 1',
10
+ '2. Runde' => 'Round 2',
11
+ 'Achtelfinale' => 'Round of 16',
12
+ 'Viertelfinale' => 'Quarterfinals',
13
+ 'Halbfinale' => 'Semifinals',
14
+ 'Finale' => 'Final',
15
+
16
+ 'Gruppe A' => 'Group A',
17
+ 'Gruppe B' => 'Group B',
18
+ 'Gruppe C' => 'Group C',
19
+ 'Gruppe D' => 'Group D',
20
+ 'Gruppe E' => 'Group E',
21
+ 'Gruppe F' => 'Group F',
22
+ }
23
+
24
+
25
+ end # class TxtMatchWriter
26
+ end # module SportDb
@@ -2,111 +2,6 @@ module SportDb
2
2
  class TxtMatchWriter
3
3
 
4
4
 
5
- ## translate from lang x (german, etc) to english
6
- ROUND_TRANSLATIONS = {
7
- # de/german
8
- '1. Runde' => 'Round 1',
9
- '2. Runde' => 'Round 2',
10
- 'Achtelfinale' => 'Round of 16',
11
- 'Viertelfinale' => 'Quarterfinals',
12
- 'Halbfinale' => 'Semifinals',
13
- 'Finale' => 'Final',
14
-
15
- 'Gruppe A' => 'Group A',
16
- 'Gruppe B' => 'Group B',
17
- 'Gruppe C' => 'Group C',
18
- 'Gruppe D' => 'Group D',
19
- 'Gruppe E' => 'Group E',
20
- 'Gruppe F' => 'Group F',
21
- }
22
-
23
-
24
- ## helper - to calculate match stats e.g.
25
- ## how many stages, start and end dates, etc.
26
- def self._calc_stats( matches )
27
- ### check for stages & stats
28
- stats = { 'stage' => Hash.new(0),
29
- 'date' => { 'start_date' => nil,
30
- 'end_date' => nil, },
31
- 'teams' => Hash.new(0),
32
- 'matches' => 0,
33
- 'use_stages' => false,
34
- }
35
-
36
- ## add matches played stats too??
37
- ## for now only simply count used
38
- stats['matches'] = matches.size
39
-
40
- matches.each do |match|
41
- stage = match.stage
42
- stage = 'Regular Season' if stage.nil? || stage.empty?
43
- stats['stage'][ stage ] += 1
44
-
45
- ## note - date for now optional (not required)!!!!
46
- ## only teams for match
47
- if match.date
48
- ## todo/fix - norm date (parse as Date)
49
- ## check format etc.
50
- date = if match.date.is_a?( String )
51
- Date.strptime( match.date, '%Y-%m-%d' )
52
- else ## assume it's already a date (object)
53
- match.date
54
- end
55
- stats['date']['start_date'] ||= date
56
- stats['date']['end_date'] ||= date
57
-
58
- stats['date']['start_date'] = date if date < stats['date']['start_date']
59
- stats['date']['end_date'] = date if date > stats['date']['end_date']
60
- end
61
-
62
- [match.team1, match.team2].each do |team|
63
- stats['teams'][ team ] += 1 if team && !['N.N.'].include?( team )
64
- end
65
- end
66
-
67
- ## add & update use_stage flag
68
- stats['use_stages'] = if stats['stage'].size >= 2 ||
69
- (stats['stage'].size == 1 &&
70
- stats['stage'].keys[0] != 'Regular Season')
71
- true
72
- else
73
- false
74
- end
75
- stats
76
- end
77
-
78
- def self._build_stats( stats )
79
- ### add comment header
80
- buf = String.new
81
- # e.g. 13 April – 25 September 2024
82
- # or 16 August 2024 – 25 May 2025
83
- ## note - date is optional!!
84
- if stats['date']['start_date']
85
- buf << "# Date "
86
- start_date = stats['date']['start_date']
87
- end_date = stats['date']['end_date']
88
- if start_date.year != end_date.year
89
- buf << "#{start_date.strftime('%a %b/%-d %Y')} - #{end_date.strftime('%a %b/%-d %Y')}"
90
- else
91
- buf << "#{start_date.strftime('%a %b/%-d')} - #{end_date.strftime('%a %b/%-d %Y')}"
92
- end
93
- buf << " (#{end_date.jd-start_date.jd}d)" ## add days
94
- buf << "\n"
95
- end
96
-
97
- buf << "# Teams #{stats['teams'].size}\n"
98
- buf << "# Matches #{stats['matches']}\n"
99
-
100
- if stats['use_stages']
101
- buf << "# Stages "
102
- stages = stats['stage'].map { |name,count| "#{name} (#{count})" }.join( ' ' )
103
- buf << stages
104
- buf << "\n"
105
- end
106
-
107
- buf
108
- end
109
-
110
5
 
111
6
  ## note: build returns buf - an (in-memory) string buf(fer)
112
7
  def self.build( matches, rounds: true )
@@ -114,43 +9,19 @@ def self.build( matches, rounds: true )
114
9
  raise ArgumentError, "rounds flag - bool expected; got: #{rounds.inspect}" unless rounds.is_a?( TrueClass ) || rounds.is_a?( FalseClass )
115
10
 
116
11
 
117
- ### calc stats and check for stages
12
+ ### check for stages & stats
118
13
  stats = _calc_stats( matches )
119
14
 
15
+
120
16
  buf = String.new
121
17
 
122
18
  ### add comment header
123
19
  buf << _build_stats( stats )
124
20
  buf << "\n\n"
125
21
 
22
+ buf << _build_batch( matches, rounds: rounds )
126
23
 
127
- use_stages = stats['use_stages' ]
128
- if use_stages
129
- ## split matches by stage
130
- matches_by_stage = {}
131
- matches.each do |match|
132
- stage = match.stage || ''
133
- matches_by_stage[stage] ||= []
134
- matches_by_stage[stage] << match
135
- end
136
-
137
- ## todo/fix
138
- ## note - empty stage must go first!!!!
139
- matches_by_stage.each_with_index do |(name, matches),i|
140
- buf << "\n" if i != 0 # add extra new line (if not first stage)
141
- if name.empty?
142
- buf << "# Regular Season\n" ## empty stage
143
- else
144
- buf << "== #{name}\n"
145
- end
146
- buf += _build_batch( matches, rounds: rounds )
147
- buf << "\n" if i+1 != matches_by_stage.size
148
- end
149
- buf
150
- else
151
- buf += _build_batch( matches, rounds: rounds )
152
- buf
153
- end
24
+ buf
154
25
  end
155
26
 
156
27
 
@@ -158,40 +29,62 @@ def self._build_batch( matches, rounds: true )
158
29
  ## note: make sure rounds is a bool, that is, true or false (do NOT pass in strings etc.)
159
30
  raise ArgumentError, "rounds flag - bool expected; got: #{rounds.inspect}" unless rounds.is_a?( TrueClass ) || rounds.is_a?( FalseClass )
160
31
 
161
- buf = String.new
162
-
163
32
  last_round = nil
33
+ last_year = nil
164
34
  last_date = nil
165
35
  last_time = nil
166
36
 
167
37
 
38
+ buf = String.new
39
+
40
+
168
41
  matches.each_with_index do |match,i|
169
42
 
170
43
  ## note: make rounds optional (set rounds flag to false to turn off)
171
44
  if rounds
172
- if match.round != last_round
45
+ ## build round string
46
+ round = if match.round
47
+ if match.round.is_a?( Integer ) ||
48
+ match.round =~ /^[0-9]+$/ ## all numbers/digits
49
+ ## default "class format
50
+ ## e.g. Runde 1, Spieltag 1, Matchday 1, Week 1
51
+ "Matchday #{match.round}"
52
+ else ## use as is from match
53
+ ## note: for now assume english names
54
+ (ROUND_TRANSLATIONS[match.round] || match.round)
55
+ end
56
+ else
57
+ nil
58
+ end
59
+
60
+ ## note - only stage present is possible
61
+ ## if stage present - (auto-)add upfront
62
+ if match.stage
63
+ if ['Regular', 'Regular stage'].include?(match.stage)
64
+ ## skip stage
65
+ else
66
+ round = round ? "#{match.stage}, #{round}" : "#{match.stage}"
67
+ end
68
+ end
69
+
70
+
71
+ if round.nil?
72
+ puts "!! ERROR - match with round nil (no round and no stage)"
73
+ pp match
74
+ exit 1
75
+ end
76
+
77
+
78
+
79
+ if round != last_round
173
80
  buf << (i == 0 ? "\n" : "\n\n") ## start with single empty line
174
- if match.round.is_a?( Integer ) ||
175
- match.round =~ /^[0-9]+$/ ## all numbers/digits
176
- ## default "class format
177
- ## e.g. Runde 1, Spieltag 1, Matchday 1, Week 1
178
- buf << "Matchday #{match.round}"
179
- else ## use as is from match
180
- ## note: for now assume english names
181
- if match.round.nil?
182
- ## warn
183
- puts "!! ERROR - match with round nil?"
184
- pp match
185
- exit 1
186
- end
81
+ buf << "▪ #{round}\n"
187
82
 
188
- buf << (ROUND_TRANSLATIONS[match.round] || match.round)
189
- end
190
83
  ## note - reset last_date & last_time on every new round header
191
- last_date = nil
192
- last_time = nil
193
-
194
- buf << "\n"
84
+ ## kind of starting "new scope" (no date/time inheritance)
85
+ last_date = nil
86
+ last_time = nil
87
+ last_round = round
195
88
  end
196
89
  end
197
90
 
@@ -213,15 +106,23 @@ def self._build_batch( matches, rounds: true )
213
106
  date_yyyymmdd = date ? date.strftime( '%Y-%m-%d' ) : nil
214
107
 
215
108
  ## note: time is OPTIONAL for now
216
- ## note: use 17.00 and NOT 17:00 for now
217
- time_hhmm = time ? time.strftime( '%H.%M' ) : nil
109
+ ## note: use 17:00 always as time format (do NOT use 17.00!!!)
110
+ time_hhmm = time ? time.strftime( '%H:%M' ) : nil
218
111
 
219
112
 
220
113
  if date_yyyymmdd
221
114
  if date_yyyymmdd != last_date
222
115
  ## note: add an extra leading blank line (if no round headings printed)
223
116
  buf << "\n" unless rounds
224
- buf << "[#{date.strftime( '%a %b/%-d' )}]\n"
117
+
118
+ buf << " "
119
+ ## note: only add year if different for last date header
120
+ buf << if (date ? date.year : nil) != last_year
121
+ "#{date.strftime( '%a %b %-d %Y' )}"
122
+ else
123
+ "#{date.strftime( '%a %b %-d' )}"
124
+ end
125
+ buf << "\n"
225
126
  last_time = nil
226
127
  end
227
128
  end
@@ -237,22 +138,26 @@ def self._build_batch( matches, rounds: true )
237
138
 
238
139
  if time
239
140
  if last_time != time_hhmm
240
- line << "%5s" % time_hhmm
141
+ line << " %5s" % time_hhmm
241
142
  else
242
- line << ' '
143
+ line << (' ' *7)
243
144
  end
244
145
  line << ' '
245
146
  else
246
- line << ' '
147
+ line << (' ' *9)
247
148
  end
248
149
 
249
150
  line << "%-23s" % team1 ## note: use %-s for left-align
250
-
251
- ## note: separate by at least two spaces for now
252
- line << " #{match.score.to_s( lang: 'en' )} "
253
-
151
+ line << " v "
254
152
  line << "%-23s" % team2
255
153
 
154
+ ## note - only print if score is available
155
+ ## returns - for not available for now!!!!
156
+ score = match.score.to_s( lang: 'en' )
157
+ if score != '-'
158
+ ## note: separate by at least two spaces for now
159
+ line << " #{score} "
160
+ end
256
161
 
257
162
  if match.status
258
163
  line << ' '
@@ -269,9 +174,10 @@ def self._build_batch( matches, rounds: true )
269
174
  line << '[postponed]'
270
175
  ## was -- note: add NOTHING for postponed for now
271
176
  else
272
- puts "!! WARN - unknown match status >#{match.status}<:"
177
+ puts "!! ERROR - unknown match status >#{match.status}<:"
273
178
  pp match
274
179
  line << "[#{match.status.downcase}]" ## print "literal" downcased for now
180
+ exit 1
275
181
  end
276
182
  end
277
183
 
@@ -282,63 +188,16 @@ def self._build_batch( matches, rounds: true )
282
188
  if match.goals
283
189
  buf << ' ' # 4 space indent
284
190
  buf << ' ' if time # 7 (5+2) space indent (for hour e.g. 17.30)
285
- buf << "[#{build_goals(match.goals)}]"
191
+ buf << "(#{build_goals(match.goals)})"
286
192
  buf << "\n"
287
193
  end
288
194
 
289
-
290
- last_round = match.round
195
+ last_year = date ? date.year : nil
291
196
  last_date = date_yyyymmdd
292
197
  last_time = time_hhmm
293
198
  end
294
199
  buf
295
200
  end
296
201
 
297
-
298
- def self.build_goals( goals )
299
- ## todo/fix: for now assumes always minutes (without offset) - add offset support
300
-
301
- ## note: "fold" multiple goals by players
302
- team1_goals = {}
303
- team2_goals = {}
304
- goals.each do |goal|
305
- team_goals = goal.team == 1 ? team1_goals : team2_goals
306
- player_goals = team_goals[ goal.player ] ||= []
307
- player_goals << goal
308
- end
309
-
310
- buf = String.new
311
- if team1_goals.size > 0
312
- buf << build_goals_for_team( team1_goals )
313
- end
314
-
315
- ## note: only add a separator (;) if BOTH teams have goal scores
316
- if team1_goals.size > 0 && team2_goals.size > 0
317
- buf << '; '
318
- end
319
-
320
- if team2_goals.size > 0
321
- buf << build_goals_for_team( team2_goals )
322
- end
323
- buf
324
- end
325
-
326
-
327
- def self.build_goals_for_team( team_goals )
328
- buf = String.new
329
- team_goals.each_with_index do |(player_name, goals),i|
330
- buf << ' ' if i > 0
331
- buf << "#{player_name} "
332
- buf << goals.map do |goal|
333
- str = "#{goal.minute}'"
334
- str << " (o.g.)" if goal.owngoal?
335
- str << " (pen.)" if goal.penalty?
336
- str
337
- end.join( ', ' )
338
- end
339
- buf
340
- end
341
-
342
-
343
202
  end # class TxtMatchWriter
344
203
  end # module SportDb
@@ -3,8 +3,8 @@ module SportDb
3
3
  module Module
4
4
  module Writers
5
5
  MAJOR = 0 ## todo: namespace inside version or something - why? why not??
6
- MINOR = 4
7
- PATCH = 3
6
+ MINOR = 5
7
+ PATCH = 0
8
8
  VERSION = [MAJOR,MINOR,PATCH].join('.')
9
9
 
10
10
  def self.version
@@ -26,42 +26,38 @@ end # module Writer
26
26
  ###
27
27
  # our own code
28
28
  require_relative 'writers/version'
29
- require_relative 'writers/goals'
29
+
30
+ require_relative 'writers/rounds'
31
+
32
+ require_relative 'writers/build_stats'
33
+ require_relative 'writers/build_goals'
34
+
30
35
  require_relative 'writers/txt_writer'
31
- require_relative 'writers/txt_writer_v2'
32
36
 
33
37
 
34
38
 
35
39
  module SportDb
36
40
  class TxtMatchWriter
41
+
42
+
43
+
44
+
45
+ ## fix - change name: to title: !!!!
46
+ ## fix: remove rounds: true|false - make it works without rounds without flag!!!!!
47
+
37
48
  def self.write( path, matches, name:, rounds: true)
38
49
 
39
50
  buf = build( matches, rounds: rounds )
40
-
41
- ## for convenience - make sure parent folders/directories exist
42
- FileUtils.mkdir_p( File.dirname( path) ) unless Dir.exist?( File.dirname( path ))
43
-
44
- puts "==> writing to >#{path}<..."
45
- File.open( path, 'w:utf-8' ) do |f|
46
- f.write( "= #{name}\n\n" )
47
- f.write( buf )
48
- end
49
- end # method self.write
50
51
 
51
- def self.write_v2( path, matches, name:, rounds: true)
52
-
53
- buf = build_v2( matches, rounds: rounds )
54
-
55
- ## for convenience - make sure parent folders/directories exist
56
- FileUtils.mkdir_p( File.dirname( path) ) unless Dir.exist?( File.dirname( path ))
57
-
58
52
  puts "==> writing to >#{path}<..."
59
- File.open( path, 'w:utf-8' ) do |f|
60
- f.write( "= #{name}\n\n" )
61
- f.write( buf )
62
- end
63
- end # method self.write_v2
64
53
 
54
+ txt = "= #{name}\n\n" + buf
55
+ write_text( path, txt )
56
+ end # method self.write
57
+
58
+ class << self
59
+ alias_method :write_v2, :write
60
+ end
65
61
 
66
62
  end # class TxtMatchWriter
67
63
  end # module SportDb
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sportdb-writers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
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: 2025-03-21 00:00:00.000000000 Z
11
+ date: 2026-05-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sportdb-structs
@@ -73,9 +73,10 @@ files:
73
73
  - README.md
74
74
  - Rakefile
75
75
  - lib/sportdb/writers.rb
76
- - lib/sportdb/writers/goals.rb
76
+ - lib/sportdb/writers/build_goals.rb
77
+ - lib/sportdb/writers/build_stats.rb
78
+ - lib/sportdb/writers/rounds.rb
77
79
  - lib/sportdb/writers/txt_writer.rb
78
- - lib/sportdb/writers/txt_writer_v2.rb
79
80
  - lib/sportdb/writers/version.rb
80
81
  homepage: https://github.com/sportdb/sport.db
81
82
  licenses:
@@ -1,188 +0,0 @@
1
- module SportDb
2
- class TxtMatchWriter
3
-
4
-
5
-
6
- ## note: build returns buf - an (in-memory) string buf(fer)
7
- def self.build_v2( matches, rounds: true )
8
- ## note: make sure rounds is a bool, that is, true or false (do NOT pass in strings etc.)
9
- raise ArgumentError, "rounds flag - bool expected; got: #{rounds.inspect}" unless rounds.is_a?( TrueClass ) || rounds.is_a?( FalseClass )
10
-
11
-
12
- ### check for stages & stats
13
- stats = _calc_stats( matches )
14
-
15
-
16
- buf = String.new
17
-
18
- ### add comment header
19
- buf << _build_stats( stats )
20
- buf << "\n\n"
21
-
22
- buf << _build_batch_v2( matches, rounds: rounds )
23
-
24
- buf
25
- end
26
-
27
-
28
- def self._build_batch_v2( matches, rounds: true )
29
- ## note: make sure rounds is a bool, that is, true or false (do NOT pass in strings etc.)
30
- raise ArgumentError, "rounds flag - bool expected; got: #{rounds.inspect}" unless rounds.is_a?( TrueClass ) || rounds.is_a?( FalseClass )
31
-
32
- last_round = nil
33
- last_year = nil
34
- last_date = nil
35
- last_time = nil
36
-
37
-
38
- buf = String.new
39
-
40
-
41
- matches.each_with_index do |match,i|
42
-
43
- ## note: make rounds optional (set rounds flag to false to turn off)
44
- if rounds
45
- ## build round string
46
- round = if match.round.is_a?( Integer ) ||
47
- match.round =~ /^[0-9]+$/ ## all numbers/digits
48
- ## default "class format
49
- ## e.g. Runde 1, Spieltag 1, Matchday 1, Week 1
50
- "Matchday #{match.round}"
51
- else ## use as is from match
52
- ## note: for now assume english names
53
- if match.round.nil?
54
- ## warn
55
- puts "!! ERROR - match with round nil?"
56
- pp match
57
- exit 1
58
- end
59
- (ROUND_TRANSLATIONS[match.round] || match.round)
60
- end
61
-
62
- ## if stage present - (auto-)add upfront
63
- round = "#{match.stage}, #{round}" if match.stage
64
-
65
-
66
- if round != last_round
67
- buf << (i == 0 ? "\n" : "\n\n") ## start with single empty line
68
- buf << "» #{round}\n"
69
-
70
- ## note - reset last_date & last_time on every new round header
71
- last_date = nil
72
- last_time = nil
73
- last_round = round
74
- end
75
- end
76
-
77
-
78
- date = if match.date.is_a?( String )
79
- Date.strptime( match.date, '%Y-%m-%d' )
80
- else ## assume it's already a date (object) or nil!!!!
81
- match.date
82
- end
83
-
84
- time = if match.time.is_a?( String )
85
- Time.strptime( match.time, '%H:%M')
86
- else ## assume it's already a time (object) or nil
87
- match.time
88
- end
89
-
90
-
91
- ## note - date might be NIL!!!!!
92
- date_yyyymmdd = date ? date.strftime( '%Y-%m-%d' ) : nil
93
-
94
- ## note: time is OPTIONAL for now
95
- ## note: use 17.00 and NOT 17:00 for now
96
- time_hhmm = time ? time.strftime( '%H.%M' ) : nil
97
-
98
-
99
- if date_yyyymmdd
100
- if date_yyyymmdd != last_date
101
- ## note: add an extra leading blank line (if no round headings printed)
102
- buf << "\n" unless rounds
103
-
104
- buf << " "
105
- ## note: only add year if different for last date header
106
- buf << if (date ? date.year : nil) != last_year
107
- "#{date.strftime( '%a %b/%-d %Y' )}"
108
- else
109
- "#{date.strftime( '%a %b/%-d' )}"
110
- end
111
- buf << "\n"
112
- last_time = nil
113
- end
114
- end
115
-
116
-
117
- ## allow strings and structs for team names
118
- team1 = match.team1.is_a?( String ) ? match.team1 : match.team1.name
119
- team2 = match.team2.is_a?( String ) ? match.team2 : match.team2.name
120
-
121
-
122
- line = String.new
123
- line << ' '
124
-
125
- if time
126
- if last_time != time_hhmm
127
- line << " %5s" % time_hhmm
128
- else
129
- line << (' ' *7)
130
- end
131
- line << ' '
132
- else
133
- line << (' ' *9)
134
- end
135
-
136
- line << "%-23s" % team1 ## note: use %-s for left-align
137
- line << " v "
138
- line << "%-23s" % team2
139
-
140
- ## note - only print if score is available
141
- ## returns - for not available for now!!!!
142
- score = match.score.to_s( lang: 'en' )
143
- if score != '-'
144
- ## note: separate by at least two spaces for now
145
- line << " #{score} "
146
- end
147
-
148
- if match.status
149
- line << ' '
150
- case match.status
151
- when Status::CANCELLED
152
- line << '[cancelled]'
153
- when Status::AWARDED
154
- line << '[awarded]'
155
- when Status::ABANDONED
156
- line << '[abandoned]'
157
- when Status::REPLAY
158
- line << '[replay]'
159
- when Status::POSTPONED
160
- line << '[postponed]'
161
- ## was -- note: add NOTHING for postponed for now
162
- else
163
- puts "!! WARN - unknown match status >#{match.status}<:"
164
- pp match
165
- line << "[#{match.status.downcase}]" ## print "literal" downcased for now
166
- end
167
- end
168
-
169
- ## add match line
170
- buf << line.rstrip ## remove possible right trailing spaces before adding
171
- buf << "\n"
172
-
173
- if match.goals
174
- buf << ' ' # 4 space indent
175
- buf << ' ' if time # 7 (5+2) space indent (for hour e.g. 17.30)
176
- buf << "[#{build_goals(match.goals)}]"
177
- buf << "\n"
178
- end
179
-
180
- last_year = date ? date.year : nil
181
- last_date = date_yyyymmdd
182
- last_time = time_hhmm
183
- end
184
- buf
185
- end
186
-
187
- end # class TxtMatchWriter
188
- end # module SportDb