fbtxt-document 0.9.0 → 0.9.1
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 +18 -5
- data/lib/fbtxt/document/export_utils.rb +100 -0
- data/lib/fbtxt/document/match_tree.rb +13 -31
- data/lib/fbtxt/document/match_tree_on/on_cards_line.rb +66 -0
- data/lib/fbtxt/document/match_tree_on/on_goal_line.rb +43 -25
- data/lib/fbtxt/document/match_tree_on/on_lineup_line.rb +96 -0
- data/lib/fbtxt/document/match_tree_on/on_match_bye.rb +35 -0
- data/lib/fbtxt/document/match_tree_on/on_match_line.rb +2 -20
- data/lib/fbtxt/document/match_tree_on/on_penalties.rb +57 -0
- data/lib/fbtxt/document/match_tree_on/on_referee_line.rb +25 -0
- data/lib/fbtxt/document/models/event.rb +72 -0
- data/lib/fbtxt/document/models/goal.rb +94 -0
- data/lib/fbtxt/document/{match_tree → models}/group.rb +2 -2
- data/lib/fbtxt/document/models/lineup.rb +147 -0
- data/lib/fbtxt/document/models/match.rb +194 -0
- data/lib/fbtxt/document/models/minute.rb +57 -0
- data/lib/fbtxt/document/models/penalty.rb +35 -0
- data/lib/fbtxt/document/models/player.rb +32 -0
- data/lib/fbtxt/document/models/referee.rb +24 -0
- data/lib/fbtxt/document/{match_tree → models}/round.rb +2 -2
- data/lib/fbtxt/document/models/score.rb +146 -0
- data/lib/fbtxt/document/version.rb +1 -1
- data/lib/fbtxt/document.rb +33 -6
- metadata +20 -7
- data/lib/fbtxt/document/match_tree/goal.rb +0 -67
- data/lib/fbtxt/document/match_tree/match.rb +0 -249
- /data/lib/fbtxt/document/{quick_match_reader.rb → document.rb} +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cede645c5634b77011d3c7989db7af19e68083f8af89436af1aabb6c873d115e
|
|
4
|
+
data.tar.gz: a4e98460ccc55c134d835add92b8dcdd7d35640c831cf504b11a36f88d25f34b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ec91acce5438a7260b6f1fc17475f91c05bce5b469bd284e613afbe89a9e4fc3b1bd0929c1845d59baa977c67b1ba8625a914e2a01d074273842d29d0cfa6871
|
|
7
|
+
data.tar.gz: d6f6db6fa65ad6126235d0b5205d2b294205979244d2c1e014a141ecd195e22d4ebd4c4bc6a9f828b8cb02072615fb13092dfc563b63598555a1bde311a37d85
|
data/CHANGELOG.md
CHANGED
data/Manifest.txt
CHANGED
|
@@ -3,17 +3,30 @@ Manifest.txt
|
|
|
3
3
|
README.md
|
|
4
4
|
Rakefile
|
|
5
5
|
lib/fbtxt/document.rb
|
|
6
|
+
lib/fbtxt/document/document.rb
|
|
7
|
+
lib/fbtxt/document/export_utils.rb
|
|
6
8
|
lib/fbtxt/document/match_tree-helpers.rb
|
|
7
9
|
lib/fbtxt/document/match_tree.rb
|
|
8
|
-
lib/fbtxt/document/
|
|
9
|
-
lib/fbtxt/document/match_tree/group.rb
|
|
10
|
-
lib/fbtxt/document/match_tree/match.rb
|
|
11
|
-
lib/fbtxt/document/match_tree/round.rb
|
|
10
|
+
lib/fbtxt/document/match_tree_on/on_cards_line.rb
|
|
12
11
|
lib/fbtxt/document/match_tree_on/on_date_header.rb
|
|
13
12
|
lib/fbtxt/document/match_tree_on/on_goal_line.rb
|
|
14
13
|
lib/fbtxt/document/match_tree_on/on_group_def.rb
|
|
14
|
+
lib/fbtxt/document/match_tree_on/on_lineup_line.rb
|
|
15
|
+
lib/fbtxt/document/match_tree_on/on_match_bye.rb
|
|
15
16
|
lib/fbtxt/document/match_tree_on/on_match_line.rb
|
|
17
|
+
lib/fbtxt/document/match_tree_on/on_penalties.rb
|
|
18
|
+
lib/fbtxt/document/match_tree_on/on_referee_line.rb
|
|
16
19
|
lib/fbtxt/document/match_tree_on/on_round_def.rb
|
|
17
20
|
lib/fbtxt/document/match_tree_on/on_round_outline.rb
|
|
18
|
-
lib/fbtxt/document/
|
|
21
|
+
lib/fbtxt/document/models/event.rb
|
|
22
|
+
lib/fbtxt/document/models/goal.rb
|
|
23
|
+
lib/fbtxt/document/models/group.rb
|
|
24
|
+
lib/fbtxt/document/models/lineup.rb
|
|
25
|
+
lib/fbtxt/document/models/match.rb
|
|
26
|
+
lib/fbtxt/document/models/minute.rb
|
|
27
|
+
lib/fbtxt/document/models/penalty.rb
|
|
28
|
+
lib/fbtxt/document/models/player.rb
|
|
29
|
+
lib/fbtxt/document/models/referee.rb
|
|
30
|
+
lib/fbtxt/document/models/round.rb
|
|
31
|
+
lib/fbtxt/document/models/score.rb
|
|
19
32
|
lib/fbtxt/document/version.rb
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
|
|
2
|
+
##
|
|
3
|
+
## add shared quick (export) helper / utility methods
|
|
4
|
+
###
|
|
5
|
+
|
|
6
|
+
module Fbtxt
|
|
7
|
+
module Export
|
|
8
|
+
|
|
9
|
+
#####
|
|
10
|
+
## todo
|
|
11
|
+
## move to Fbtxt::Export.genjson or such
|
|
12
|
+
## or use Fbtxt::Serialize/Batch or ??
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# usage for config
|
|
17
|
+
# e.g.
|
|
18
|
+
# [['1930/worldcup.json', ['worldcup/1930--uruguay/cup.txt']],
|
|
19
|
+
# ['1934/worldcup.json', ['worldcup/1934--italy/cup.txt']],
|
|
20
|
+
# ['2026/worldcup.json', ['worldcup/2026--usa/cup.txt', 'worldcup/2026--usa/cup_finals.txt']]]
|
|
21
|
+
#
|
|
22
|
+
# todo/check:
|
|
23
|
+
# change/rename indir to sourcedir/rootdir or such - why? why not?
|
|
24
|
+
def self.genjson( config, outdir: '.',
|
|
25
|
+
indir: '.' )
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
config.each do |outfile, infiles|
|
|
29
|
+
|
|
30
|
+
## step 1
|
|
31
|
+
## collect (parse) docs
|
|
32
|
+
docs = []
|
|
33
|
+
infiles.each_with_index do |infile,i|
|
|
34
|
+
inpath = File.join( indir, infile )
|
|
35
|
+
|
|
36
|
+
print "==> reading"
|
|
37
|
+
print " [#{i+1}/#{infiles.size}]" if infiles.size > 1
|
|
38
|
+
print " #{inpath}...\n"
|
|
39
|
+
|
|
40
|
+
doc = Document.read( inpath )
|
|
41
|
+
|
|
42
|
+
if doc.errors?
|
|
43
|
+
puts "!! #{doc.errors.size} parse error(s) in #{inpath}:"
|
|
44
|
+
pp doc.errors
|
|
45
|
+
exit 1
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
docs << doc
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
data = _merge_matches( *docs )
|
|
52
|
+
|
|
53
|
+
outpath = File.join( outdir, outfile )
|
|
54
|
+
|
|
55
|
+
####################
|
|
56
|
+
## hack - use pretty_inspect for json pretty print
|
|
57
|
+
txtjson = data.pretty_inspect
|
|
58
|
+
txtjson = txtjson.gsub( '=>', ': ' )
|
|
59
|
+
## puts txtjson[0,100] + "..."
|
|
60
|
+
## double check for syntax errors
|
|
61
|
+
json = JSON.parse( txtjson )
|
|
62
|
+
|
|
63
|
+
##
|
|
64
|
+
## try alternate pretty print
|
|
65
|
+
## puts JSON.pretty_generate( data, object_nl: "\n", array_nl: "\n", indent: 2)
|
|
66
|
+
##
|
|
67
|
+
## write_json( outpath, data )
|
|
68
|
+
|
|
69
|
+
puts " writing to >#{outpath}<"
|
|
70
|
+
puts txtjson[0,100] + "..."
|
|
71
|
+
|
|
72
|
+
write_text( outpath, txtjson )
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def self._merge_matches( *docs )
|
|
78
|
+
last_name = nil
|
|
79
|
+
matches = []
|
|
80
|
+
|
|
81
|
+
docs.each do |doc|
|
|
82
|
+
name = doc.title
|
|
83
|
+
|
|
84
|
+
if last_name && name != last_name
|
|
85
|
+
puts "!! ERROR - league names do NOT match; cannot merge/concat - sorry"
|
|
86
|
+
puts " #{last_name} != #{name}"
|
|
87
|
+
exit 1
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
last_name = name
|
|
91
|
+
matches += doc.matches
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
data = { 'name' => last_name,
|
|
95
|
+
'matches' => matches.as_json }
|
|
96
|
+
data
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
end # module Export
|
|
100
|
+
end # module Fbtxt
|
|
@@ -7,6 +7,10 @@ class MatchTree
|
|
|
7
7
|
include Debuggable
|
|
8
8
|
|
|
9
9
|
|
|
10
|
+
include Models ## e.g. Fbtxt::Model(s)
|
|
11
|
+
## Match,Round,Group,Goal,etc.
|
|
12
|
+
|
|
13
|
+
|
|
10
14
|
##
|
|
11
15
|
## note: allow start(_date) nil
|
|
12
16
|
## if in use (start: nil) years expected on first date!!!
|
|
@@ -69,14 +73,19 @@ class MatchTree
|
|
|
69
73
|
on_match_line_bye( node )
|
|
70
74
|
elsif node.is_a? RaccMatchParser::GoalLine
|
|
71
75
|
on_goal_line( node )
|
|
72
|
-
elsif node.is_a?
|
|
73
|
-
|
|
74
|
-
|
|
76
|
+
elsif node.is_a? RaccMatchParser::PenaltiesLine
|
|
77
|
+
on_penalties( node )
|
|
78
|
+
elsif node.is_a? RaccMatchParser::LineupLine
|
|
79
|
+
on_lineup_line( node )
|
|
80
|
+
elsif node.is_a? RaccMatchParser::CardsLine
|
|
81
|
+
on_cards_line( node )
|
|
82
|
+
elsif node.is_a? RaccMatchParser::RefereeLine
|
|
83
|
+
on_referee_line( node )
|
|
75
84
|
elsif node.is_a?( RaccMatchParser::Heading1 ) ||
|
|
76
85
|
node.is_a?( RaccMatchParser::Heading2 ) ||
|
|
77
86
|
node.is_a?( RaccMatchParser::Heading3 )
|
|
78
87
|
### skip headings (1/2/3) for now
|
|
79
|
-
elsif node.is_a?
|
|
88
|
+
elsif node.is_a? RaccMatchParser::BlankLine
|
|
80
89
|
### skip for now; do nothing
|
|
81
90
|
else
|
|
82
91
|
## report error
|
|
@@ -95,32 +104,5 @@ class MatchTree
|
|
|
95
104
|
end # method convert
|
|
96
105
|
|
|
97
106
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
def on_match_line_bye( node )
|
|
101
|
-
_trace( "on match (bye): >#{node}<" )
|
|
102
|
-
|
|
103
|
-
## note - bye records NO date/time or ground (or score etc.)
|
|
104
|
-
## for now only team1/team2 and match status!!
|
|
105
|
-
## plus inherited round/group
|
|
106
|
-
|
|
107
|
-
status = 'bye'
|
|
108
|
-
|
|
109
|
-
team = node.team
|
|
110
|
-
|
|
111
|
-
@teams[ team ] += 1
|
|
112
|
-
|
|
113
|
-
group = nil
|
|
114
|
-
group = @last_group if @last_group
|
|
115
|
-
|
|
116
|
-
round = nil
|
|
117
|
-
round = @last_round if @last_round
|
|
118
|
-
|
|
119
|
-
@matches << Match.new( team1: team, ## note: for now always use mapping value e.g. rec (NOT string e.g. team1.name)
|
|
120
|
-
round: round ? round.name : nil, ## note: for now always use string (assume unique canonical name for event)
|
|
121
|
-
group: group ? group.name : nil, ## note: for now always use string (assume unique canonical name for event)
|
|
122
|
-
status: status )
|
|
123
|
-
### todo: cache team lookups in hash?
|
|
124
|
-
end
|
|
125
107
|
end # class MatchTree
|
|
126
108
|
end # module Fbtxt
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
module Fbtxt
|
|
2
|
+
class MatchTree
|
|
3
|
+
|
|
4
|
+
def on_cards_line( node )
|
|
5
|
+
_trace( "on cards: >#{node}<" )
|
|
6
|
+
|
|
7
|
+
## get last match
|
|
8
|
+
match = @matches[-1]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
################################
|
|
12
|
+
## CardsLine = Struct.new( :type, :bookings )
|
|
13
|
+
## Booking = Struct.new( :name, :minute )
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## check if match has lineup ??
|
|
17
|
+
if match.lineup
|
|
18
|
+
## type = node.type ## e.g. 'Y', 'Y/R', 'R', 'SENTOFF', etc.
|
|
19
|
+
|
|
20
|
+
## note - flatten for now
|
|
21
|
+
## fix-fix-fix use lineup[0], lineup[1] latter - why? why not?
|
|
22
|
+
bookings = node.bookings.flatten
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
bookings.each do |b|
|
|
26
|
+
## find player ref in match lineup (team1/team2)
|
|
27
|
+
player = nil
|
|
28
|
+
## note - expapand lineup[] to one or two items
|
|
29
|
+
[*match.lineup].each_with_index do |lineup,i|
|
|
30
|
+
player = lineup.find_player( b.name )
|
|
31
|
+
next if player.nil?
|
|
32
|
+
|
|
33
|
+
## fix-fix-fix- keep player obj/ref - why? why not?
|
|
34
|
+
rec = EventCard.new(
|
|
35
|
+
type: node.type,
|
|
36
|
+
name: b.name,
|
|
37
|
+
minute: b.minute )
|
|
38
|
+
|
|
39
|
+
match.bookings ||= [[],[]]
|
|
40
|
+
match.bookings[i] << rec
|
|
41
|
+
|
|
42
|
+
break
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
if player.nil?
|
|
46
|
+
## raise ArgumentError,
|
|
47
|
+
## "player >#{b.name}< NOT found in match (lineup): #{match.pretty_inspect}"
|
|
48
|
+
|
|
49
|
+
### log warn for now
|
|
50
|
+
## might be trainer, staff or missing player from bench w/o sub
|
|
51
|
+
## fix-fix-fix
|
|
52
|
+
## log error!!
|
|
53
|
+
msg = "!! WARN - player >#{b.name}< NOT found; skipping booking #{b.pretty_inspect}"
|
|
54
|
+
puts msg
|
|
55
|
+
log( msg )
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
else
|
|
60
|
+
### warn - "standalone" bookings for now not yet supported!!!
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end ## class MatchTree
|
|
66
|
+
end ## module Fbtxt
|
|
@@ -5,6 +5,14 @@ class MatchTree
|
|
|
5
5
|
def on_goal_line( node )
|
|
6
6
|
_trace( "on goal line: >#{node}<" )
|
|
7
7
|
|
|
8
|
+
###
|
|
9
|
+
# note: goals formats
|
|
10
|
+
# (i) [[],[]] (nested/paired) or
|
|
11
|
+
# (ii) [] (flat/undefined)
|
|
12
|
+
##
|
|
13
|
+
## add Array#paired? and
|
|
14
|
+
## Array#flat?
|
|
15
|
+
## helper methods/checks or such - why? why not?
|
|
8
16
|
|
|
9
17
|
if node.goals[0].is_a?( Array )
|
|
10
18
|
goals1, goals2 = node.goals[0], node.goals[1]
|
|
@@ -17,25 +25,27 @@ class MatchTree
|
|
|
17
25
|
pp [goals1,goals2] if debug?
|
|
18
26
|
|
|
19
27
|
|
|
28
|
+
## quick & dirty - auto add goals to last match
|
|
29
|
+
## note - for hacky (quick& dirty) multi-line support
|
|
30
|
+
## always append for now
|
|
31
|
+
match = @matches[-1]
|
|
32
|
+
|
|
33
|
+
|
|
20
34
|
## special rule
|
|
21
35
|
## if goals 2 empty check if score for team 1 is zero
|
|
22
36
|
## and team 2 is NOT zero than
|
|
23
|
-
## make goals1
|
|
37
|
+
## make goals1 goals2!!
|
|
24
38
|
## e.g. Norway 0-1 Austria
|
|
25
39
|
## (Hof 32)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
match = @matches[-1]
|
|
40
|
+
if match.score &&
|
|
41
|
+
goals2.empty? && !goals1.empty?
|
|
30
42
|
|
|
31
43
|
##
|
|
32
|
-
## todo/fix
|
|
33
|
-
##
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
(match.score.
|
|
37
|
-
(match.score.is_a?(Hash) && match.score[:et].nil? &&
|
|
38
|
-
match.score[:ft] && match.score[:ft][0] == 0)
|
|
44
|
+
## todo/fix: move upstream
|
|
45
|
+
## use score1_zero? or such - why? why not?
|
|
46
|
+
if (match.score.reported? && match.score.reported[0] == 0 ) ||
|
|
47
|
+
(match.score.et? && match.score.et[0] == 0) ||
|
|
48
|
+
(match.score.ft? && !match.score.et? && match.score.ft[0] == 0)
|
|
39
49
|
## "parallel assignment (or multiple assignment") - swap values in single line
|
|
40
50
|
goals2, goals1 = goals1, goals2
|
|
41
51
|
end
|
|
@@ -43,18 +53,14 @@ class MatchTree
|
|
|
43
53
|
|
|
44
54
|
|
|
45
55
|
|
|
46
|
-
##
|
|
47
|
-
## todo/fix - sort goals by minute (+offset) !!!
|
|
48
|
-
|
|
49
56
|
goals = []
|
|
50
57
|
|
|
51
58
|
goals1.each do |rec|
|
|
52
59
|
rec.minutes.each do |minute|
|
|
53
60
|
goal = Goal.new(
|
|
54
|
-
|
|
61
|
+
name: rec.player,
|
|
55
62
|
team: 1,
|
|
56
|
-
minute: minute.
|
|
57
|
-
offset: minute.offset,
|
|
63
|
+
minute: minute.to_minute, ## from GoalMinute to Minute!!
|
|
58
64
|
penalty: minute.pen || false, # note: pass along/use false NOT nil
|
|
59
65
|
owngoal: minute.og || false
|
|
60
66
|
)
|
|
@@ -65,10 +71,9 @@ class MatchTree
|
|
|
65
71
|
goals2.each do |rec|
|
|
66
72
|
rec.minutes.each do |minute|
|
|
67
73
|
goal = Goal.new(
|
|
68
|
-
|
|
74
|
+
name: rec.player,
|
|
69
75
|
team: 2,
|
|
70
|
-
minute: minute.
|
|
71
|
-
offset: minute.offset,
|
|
76
|
+
minute: minute.to_minute, ## from GoalMinute to Minute!!
|
|
72
77
|
penalty: minute.pen || false, # note: pass along/use false NOT nil
|
|
73
78
|
owngoal: minute.og || false
|
|
74
79
|
)
|
|
@@ -76,18 +81,31 @@ class MatchTree
|
|
|
76
81
|
end
|
|
77
82
|
end
|
|
78
83
|
|
|
84
|
+
|
|
79
85
|
pp goals if debug?
|
|
80
86
|
|
|
87
|
+
|
|
88
|
+
## todo/fix
|
|
89
|
+
## PLUS auto-fill score1,score2 - why? why not?
|
|
90
|
+
|
|
81
91
|
## quick & dirty - auto add goals to last match
|
|
82
92
|
## note - for hacky (quick& dirty) multi-line support
|
|
83
93
|
## always append for now
|
|
84
|
-
match = @matches[-1]
|
|
85
94
|
match.goals ||= []
|
|
86
95
|
match.goals += goals
|
|
87
96
|
|
|
88
|
-
|
|
89
|
-
##
|
|
90
|
-
##
|
|
97
|
+
|
|
98
|
+
## always keep goal list sorted by minute - why? why not?
|
|
99
|
+
## - sort only on serialize (as_json) - why? why not?
|
|
100
|
+
match.goals = match.goals.sort do |l,r|
|
|
101
|
+
if l.minute && r.minute
|
|
102
|
+
## note - minute is obj!! (Fbtxt::Minute!!)
|
|
103
|
+
l.minute <=> r.minute
|
|
104
|
+
else
|
|
105
|
+
## keep as is (no minutes available)
|
|
106
|
+
0
|
|
107
|
+
end
|
|
108
|
+
end
|
|
91
109
|
end
|
|
92
110
|
|
|
93
111
|
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
module Fbtxt
|
|
2
|
+
class MatchTree
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
## fix - move "upstream to lineup" - why? why not?
|
|
7
|
+
## - rename each_lineup?
|
|
8
|
+
##
|
|
9
|
+
def _each_player( lineup, &blk )
|
|
10
|
+
lineup.each do |item|
|
|
11
|
+
blk.call(item)
|
|
12
|
+
## plus (walk) recursive sub(stitution)s
|
|
13
|
+
current = item
|
|
14
|
+
while current && current.sub
|
|
15
|
+
blk.call( current.sub.sub )
|
|
16
|
+
current = current.sub.sub
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
## change to _collect_inline_bookings/cards - why? why not?
|
|
22
|
+
def _collect_bookings( lineup )
|
|
23
|
+
recs = []
|
|
24
|
+
|
|
25
|
+
## Lineup = Struct.new( :name, :captain, :cards, :sub )
|
|
26
|
+
## Card = Struct.new( :name, :minute )
|
|
27
|
+
_each_player( lineup ) do |item|
|
|
28
|
+
if item.cards.is_a?(Array) && item.cards.size > 0
|
|
29
|
+
item.cards.each do |card|
|
|
30
|
+
recs << EventCard.new(
|
|
31
|
+
## fix/fix/fix change to card.type upstream - why? why not?
|
|
32
|
+
type: card.name,
|
|
33
|
+
name: item.name,
|
|
34
|
+
minute: card.minute )
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
## note - (auto-)sort by minute if present
|
|
42
|
+
recs = recs.sort do |l,r|
|
|
43
|
+
if l.minute && r.minute
|
|
44
|
+
## note - minute is obj!! (Fbtxt::Minute!!)
|
|
45
|
+
l.minute <=> r.minute
|
|
46
|
+
else
|
|
47
|
+
0 ## keep as is (no minutes available)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
recs
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def on_lineup_line( node )
|
|
60
|
+
_trace( "on lineup: >#{node}<" )
|
|
61
|
+
|
|
62
|
+
## get last match
|
|
63
|
+
match = @matches[-1]
|
|
64
|
+
|
|
65
|
+
## collect players
|
|
66
|
+
team_name = node.team
|
|
67
|
+
lineup = node.lineup
|
|
68
|
+
|
|
69
|
+
## note -
|
|
70
|
+
## lineup - uses nested array format
|
|
71
|
+
## for formation
|
|
72
|
+
##
|
|
73
|
+
## quick & dirty hack - flatten for now
|
|
74
|
+
## refine later
|
|
75
|
+
lineup = lineup.flatten
|
|
76
|
+
|
|
77
|
+
## LineupLine = Struct.new( :team, :lineup, :formation, :coach ) do
|
|
78
|
+
## Lineup = Struct.new( :name, :captain, :cards, :sub ) do
|
|
79
|
+
## Sub = Struct.new( :minute, :sub ) do
|
|
80
|
+
|
|
81
|
+
## todo/check if team name match
|
|
82
|
+
## warn if no match
|
|
83
|
+
|
|
84
|
+
match.lineup ||= []
|
|
85
|
+
|
|
86
|
+
## todo/fix-fix-fix add formation here too - why? why not?
|
|
87
|
+
|
|
88
|
+
match.lineup << Lineup.build( lineup )
|
|
89
|
+
|
|
90
|
+
match.bookings ||=[]
|
|
91
|
+
match.bookings << _collect_bookings( lineup )
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
end ## class MatchTree
|
|
96
|
+
end ## module Fbtxt
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Fbtxt
|
|
2
|
+
class MatchTree
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def on_match_line_bye( node )
|
|
7
|
+
_trace( "on match (bye): >#{node}<" )
|
|
8
|
+
|
|
9
|
+
## note - bye records NO date/time or ground (or score etc.)
|
|
10
|
+
## for now only team1/team2 and match status!!
|
|
11
|
+
## plus inherited round/group
|
|
12
|
+
|
|
13
|
+
status = 'bye'
|
|
14
|
+
|
|
15
|
+
team = node.team
|
|
16
|
+
|
|
17
|
+
@teams[ team ] += 1
|
|
18
|
+
|
|
19
|
+
group = nil
|
|
20
|
+
group = @last_group if @last_group
|
|
21
|
+
|
|
22
|
+
round = nil
|
|
23
|
+
round = @last_round if @last_round
|
|
24
|
+
|
|
25
|
+
@matches << Match.new( team1: team, ## note: for now always use mapping value e.g. rec (NOT string e.g. team1.name)
|
|
26
|
+
round: round ? round.name : nil, ## note: for now always use string (assume unique canonical name for event)
|
|
27
|
+
group: group ? group.name : nil, ## note: for now always use string (assume unique canonical name for event)
|
|
28
|
+
status: status )
|
|
29
|
+
### todo: cache team lookups in hash?
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
end ## class MatchTree
|
|
35
|
+
end ## module Fbtxt
|
|
@@ -43,27 +43,9 @@ class MatchTree
|
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
### todo/fix
|
|
47
|
-
## add keywords (e.g. ht, ft or such) to Score.new - why? why not?
|
|
48
|
-
## or use new Score.build( ht:, ft:, ) or such - why? why not?
|
|
49
|
-
## pp score
|
|
50
46
|
score = nil
|
|
51
|
-
score = node.score
|
|
52
|
-
|
|
53
|
-
## if node.score.is_a?(Array)
|
|
54
|
-
## ## assume "undefined" score
|
|
55
|
-
## score = node.score
|
|
56
|
-
## else ## (default) assume Hash
|
|
57
|
-
## # ht = node.score[:ht] || [nil,nil]
|
|
58
|
-
## # ft = node.score[:ft] || [nil,nil]
|
|
59
|
-
## # et = node.score[:et] || [nil,nil]
|
|
60
|
-
## # p = node.score[:p] || [nil,nil]
|
|
61
|
-
## # values = [*ht, *ft, *et, *p]
|
|
62
|
-
## # pp values
|
|
63
|
-
## ## pp node.score
|
|
64
|
-
## score = node.score
|
|
65
|
-
## end
|
|
66
|
-
## end
|
|
47
|
+
score = Score.build( node.score ) if node.score
|
|
48
|
+
## pp score
|
|
67
49
|
|
|
68
50
|
|
|
69
51
|
status = nil
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Fbtxt
|
|
2
|
+
class MatchTree
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
## check - use on_penalties_line ???
|
|
6
|
+
def on_penalties( node )
|
|
7
|
+
_trace( "on penalties: >#{node}<" )
|
|
8
|
+
|
|
9
|
+
## get last match
|
|
10
|
+
match = @matches[-1]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## PenaltiesLine = Struct.new( :penalties )
|
|
14
|
+
## Penalty = Struct.new( :name, :score, :note )
|
|
15
|
+
|
|
16
|
+
#####
|
|
17
|
+
## note
|
|
18
|
+
## (i) [] - single line (no separator)
|
|
19
|
+
## (ii) [[],[]] - nested team1/team2 (separator required)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
recs = nil
|
|
23
|
+
|
|
24
|
+
if node.penalties.is_a?(Array) && node.penalties.size == 2 &&
|
|
25
|
+
node.penalties[0].is_a?(Array) && node.penalties[1].is_a?(Array)
|
|
26
|
+
|
|
27
|
+
## use zip to make (flattend) sequence - why? why not?
|
|
28
|
+
## we do NOT know who really started (picked via coin toss!!)
|
|
29
|
+
## keep nested arrays for now
|
|
30
|
+
recs = [[],[]]
|
|
31
|
+
|
|
32
|
+
node.penalties.each_with_index.each do |pens,i|
|
|
33
|
+
pens.each do |pen|
|
|
34
|
+
recs[i] << Penalty.new(
|
|
35
|
+
name: pen.name,
|
|
36
|
+
score: pen.score,
|
|
37
|
+
note: pen.note )
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
else
|
|
41
|
+
## assume chronological sequence
|
|
42
|
+
recs = []
|
|
43
|
+
node.penalties.each do |pen|
|
|
44
|
+
recs << Penalty.new(
|
|
45
|
+
name: pen.name,
|
|
46
|
+
score: pen.score,
|
|
47
|
+
note: pen.note )
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
match.penalties = recs
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
end ## class MatchTree
|
|
57
|
+
end ## module Fbtxt
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Fbtxt
|
|
2
|
+
class MatchTree
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def on_referee_line( node )
|
|
6
|
+
_trace( "on referee(s): >#{node}<" )
|
|
7
|
+
|
|
8
|
+
## get last match
|
|
9
|
+
match = @matches[-1]
|
|
10
|
+
|
|
11
|
+
## support multiple referees (incl. assistant refs etc.)
|
|
12
|
+
## RefereeLine = Struct.new( :referees )
|
|
13
|
+
## Referee = Struct.new( :name, :country )
|
|
14
|
+
|
|
15
|
+
recs = []
|
|
16
|
+
node.referees.each do |ref|
|
|
17
|
+
recs << Referee.new( name: ref.name, country: ref.country )
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
match.referees = recs
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
end ## class MatchTree
|
|
25
|
+
end ## module Fbtxt
|