sportdb-writers 0.4.2 → 0.4.3
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 +4 -4
- data/CHANGELOG.md +1 -1
- data/Manifest.txt +1 -0
- data/lib/sportdb/writers/txt_writer.rb +81 -50
- data/lib/sportdb/writers/txt_writer_v2.rb +188 -0
- data/lib/sportdb/writers/version.rb +1 -1
- data/lib/sportdb/writers.rb +18 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b08a4a77a08af12a0f8c7b9873c5115b8b8135e13e3b7d878ab246567a8ffa32
|
4
|
+
data.tar.gz: a6e9f8f3b0933667f2fa4cf5eb7903c4410ead48e3647dfb903e261bb3f164be
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ebb1e1a90a196a992fef5eebf43baea0e613f559d73db25d8bd8812da67fe31bb4f286b767e7423c80f00d25d1c3f745972946448eaab8a3239e9f53a8d78fc
|
7
|
+
data.tar.gz: 02342a063aef2f2604567a70a76e4caf48e49b555ab1b09fb7da996b6812547c17d684a053b3164f9b797de44e4c2a2c490a66b7865983d8d63fb78eda3294a8
|
data/CHANGELOG.md
CHANGED
data/Manifest.txt
CHANGED
@@ -11,31 +11,40 @@ class TxtMatchWriter
|
|
11
11
|
'Viertelfinale' => 'Quarterfinals',
|
12
12
|
'Halbfinale' => 'Semifinals',
|
13
13
|
'Finale' => 'Final',
|
14
|
-
}
|
15
|
-
|
16
14
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
+
}
|
21
22
|
|
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 )
|
23
27
|
### check for stages & stats
|
24
|
-
stats = { 'stage'
|
25
|
-
'date'
|
26
|
-
|
27
|
-
'teams'
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
31
39
|
|
32
40
|
matches.each do |match|
|
33
41
|
stage = match.stage
|
34
42
|
stage = 'Regular Season' if stage.nil? || stage.empty?
|
35
43
|
stats['stage'][ stage ] += 1
|
36
44
|
|
45
|
+
## note - date for now optional (not required)!!!!
|
46
|
+
## only teams for match
|
37
47
|
if match.date
|
38
|
-
|
39
48
|
## todo/fix - norm date (parse as Date)
|
40
49
|
## check format etc.
|
41
50
|
date = if match.date.is_a?( String )
|
@@ -48,52 +57,74 @@ def self.build( matches, rounds: true )
|
|
48
57
|
|
49
58
|
stats['date']['start_date'] = date if date < stats['date']['start_date']
|
50
59
|
stats['date']['end_date'] = date if date > stats['date']['end_date']
|
51
|
-
|
60
|
+
end
|
52
61
|
|
53
62
|
[match.team1, match.team2].each do |team|
|
54
63
|
stats['teams'][ team ] += 1 if team && !['N.N.'].include?( team )
|
55
64
|
end
|
56
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
|
57
77
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
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
|
84
109
|
|
85
|
-
buf << "# Teams #{stats['teams'].size}\n"
|
86
|
-
buf << "# Matches #{matches.size}\n"
|
87
110
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
111
|
+
## note: build returns buf - an (in-memory) string buf(fer)
|
112
|
+
def self.build( matches, rounds: true )
|
113
|
+
## note: make sure rounds is a bool, that is, true or false (do NOT pass in strings etc.)
|
114
|
+
raise ArgumentError, "rounds flag - bool expected; got: #{rounds.inspect}" unless rounds.is_a?( TrueClass ) || rounds.is_a?( FalseClass )
|
115
|
+
|
116
|
+
|
117
|
+
### calc stats and check for stages
|
118
|
+
stats = _calc_stats( matches )
|
119
|
+
|
120
|
+
buf = String.new
|
121
|
+
|
122
|
+
### add comment header
|
123
|
+
buf << _build_stats( stats )
|
124
|
+
buf << "\n\n"
|
95
125
|
|
96
126
|
|
127
|
+
use_stages = stats['use_stages' ]
|
97
128
|
if use_stages
|
98
129
|
## split matches by stage
|
99
130
|
matches_by_stage = {}
|
@@ -0,0 +1,188 @@
|
|
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
|
data/lib/sportdb/writers.rb
CHANGED
@@ -28,6 +28,7 @@ end # module Writer
|
|
28
28
|
require_relative 'writers/version'
|
29
29
|
require_relative 'writers/goals'
|
30
30
|
require_relative 'writers/txt_writer'
|
31
|
+
require_relative 'writers/txt_writer_v2'
|
31
32
|
|
32
33
|
|
33
34
|
|
@@ -42,10 +43,26 @@ class TxtMatchWriter
|
|
42
43
|
|
43
44
|
puts "==> writing to >#{path}<..."
|
44
45
|
File.open( path, 'w:utf-8' ) do |f|
|
45
|
-
f.write( "= #{name}\n" )
|
46
|
+
f.write( "= #{name}\n\n" )
|
46
47
|
f.write( buf )
|
47
48
|
end
|
48
49
|
end # method self.write
|
50
|
+
|
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
|
+
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
|
+
|
65
|
+
|
49
66
|
end # class TxtMatchWriter
|
50
67
|
end # module SportDb
|
51
68
|
|
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.
|
4
|
+
version: 0.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gerald Bauer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-03-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sportdb-structs
|
@@ -75,6 +75,7 @@ files:
|
|
75
75
|
- lib/sportdb/writers.rb
|
76
76
|
- lib/sportdb/writers/goals.rb
|
77
77
|
- lib/sportdb/writers/txt_writer.rb
|
78
|
+
- lib/sportdb/writers/txt_writer_v2.rb
|
78
79
|
- lib/sportdb/writers/version.rb
|
79
80
|
homepage: https://github.com/sportdb/sport.db
|
80
81
|
licenses:
|