bagel 0.1.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 +7 -0
- data/.gitignore +13 -0
- data/.prettierignore +2 -0
- data/.rspec +3 -0
- data/.rubocop.yml +13 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +187 -0
- data/Rakefile +12 -0
- data/bagel.gemspec +32 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/lib/bagel/colors.rb +8 -0
- data/lib/bagel/fonts.rb +3 -0
- data/lib/bagel/graphic/comment.rb +49 -0
- data/lib/bagel/graphic/intro.rb +49 -0
- data/lib/bagel/graphic/scoreboard/context.rb +28 -0
- data/lib/bagel/graphic/scoreboard/games.rb +13 -0
- data/lib/bagel/graphic/scoreboard/name.rb +32 -0
- data/lib/bagel/graphic/scoreboard/points.rb +13 -0
- data/lib/bagel/graphic/scoreboard/score.rb +38 -0
- data/lib/bagel/graphic/scoreboard/server.rb +16 -0
- data/lib/bagel/graphic/scoreboard/sets.rb +13 -0
- data/lib/bagel/graphic/scoreboard.rb +102 -0
- data/lib/bagel/graphic/stats/duration.rb +33 -0
- data/lib/bagel/graphic/stats/header.rb +32 -0
- data/lib/bagel/graphic/stats/result.rb +41 -0
- data/lib/bagel/graphic/stats/stat.rb +48 -0
- data/lib/bagel/graphic/stats.rb +80 -0
- data/lib/bagel/graphic.rb +23 -0
- data/lib/bagel/tennis/checker.rb +100 -0
- data/lib/bagel/tennis/outcome.rb +48 -0
- data/lib/bagel/tennis/player.rb +22 -0
- data/lib/bagel/tennis/point.rb +17 -0
- data/lib/bagel/tennis/score.rb +68 -0
- data/lib/bagel/tennis/scoring.rb +26 -0
- data/lib/bagel/tennis/serve.rb +36 -0
- data/lib/bagel/tennis/stats/aces.rb +28 -0
- data/lib/bagel/tennis/stats/break_points_won.rb +33 -0
- data/lib/bagel/tennis/stats/double_faults.rb +28 -0
- data/lib/bagel/tennis/stats/first_serve_in.rb +33 -0
- data/lib/bagel/tennis/stats/first_serve_points_won.rb +33 -0
- data/lib/bagel/tennis/stats/net_points_won.rb +33 -0
- data/lib/bagel/tennis/stats/points_won.rb +24 -0
- data/lib/bagel/tennis/stats/second_serve_points_won.rb +33 -0
- data/lib/bagel/tennis/stats/stat.rb +40 -0
- data/lib/bagel/tennis/stats/unforced_errors.rb +24 -0
- data/lib/bagel/tennis/stats/winners.rb +24 -0
- data/lib/bagel/tennis/stats.rb +16 -0
- data/lib/bagel/tennis.rb +13 -0
- data/lib/bagel/timeframe.rb +31 -0
- data/lib/bagel/version.rb +5 -0
- data/lib/bagel/video/clip.rb +41 -0
- data/lib/bagel/video/clip_builder_factory.rb +13 -0
- data/lib/bagel/video/clip_builders/clip_builder.rb +32 -0
- data/lib/bagel/video/clip_builders/intro_clip_builder.rb +37 -0
- data/lib/bagel/video/clip_builders/point_clip_builder.rb +67 -0
- data/lib/bagel/video/clip_builders/stats_clip_builder.rb +56 -0
- data/lib/bagel/video/clip_data_parser.rb +39 -0
- data/lib/bagel/video/clip_director.rb +16 -0
- data/lib/bagel/video/clip_saver.rb +59 -0
- data/lib/bagel/video/fade.rb +24 -0
- data/lib/bagel/video/ffmpeg/concat_file.rb +45 -0
- data/lib/bagel/video/ffmpeg/fade_filter.rb +34 -0
- data/lib/bagel/video/ffmpeg/overlay_filter.rb +52 -0
- data/lib/bagel/video/ffmpeg.rb +41 -0
- data/lib/bagel/video/orientation.rb +8 -0
- data/lib/bagel/video/overlays/comment.rb +15 -0
- data/lib/bagel/video/overlays/intro.rb +15 -0
- data/lib/bagel/video/overlays/overlay.rb +28 -0
- data/lib/bagel/video/overlays/scoreboard.rb +15 -0
- data/lib/bagel/video/overlays/second_serve.rb +15 -0
- data/lib/bagel/video/overlays/stats.rb +15 -0
- data/lib/bagel/video/padding.rb +9 -0
- data/lib/bagel/video/video.rb +18 -0
- data/lib/bagel/video.rb +32 -0
- data/lib/bagel.rb +76 -0
- metadata +196 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
module Bagel::Graphic
|
2
|
+
class Scoreboard::Context
|
3
|
+
HEIGHT = 40
|
4
|
+
PADDING = 10
|
5
|
+
|
6
|
+
def initialize(context)
|
7
|
+
@context = context
|
8
|
+
end
|
9
|
+
|
10
|
+
def draw
|
11
|
+
text = Image.new(HEIGHT * 10, HEIGHT * 2) { self.background_color = COLOR_WHITE }
|
12
|
+
|
13
|
+
draw = Magick::Draw.new do |d|
|
14
|
+
d.font_family = FONT_FAMILY
|
15
|
+
d.font_weight = FONT_WEIGHT
|
16
|
+
d.pointsize = 24
|
17
|
+
d.gravity = WestGravity
|
18
|
+
d.fill = COLOR_BLACK
|
19
|
+
end
|
20
|
+
|
21
|
+
draw.annotate(text, 0, 0, 0, 0, @context)
|
22
|
+
text.trim!
|
23
|
+
|
24
|
+
canvas = Image.new(text.columns + PADDING * 2, HEIGHT) { self.background_color = COLOR_WHITE }
|
25
|
+
canvas.composite!(text, WestGravity, PADDING, 0, OverCompositeOp)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Bagel
|
2
|
+
module Graphic
|
3
|
+
class Scoreboard::Name
|
4
|
+
WIDTH = 160
|
5
|
+
HEIGHT = 50
|
6
|
+
|
7
|
+
PADDING = 10
|
8
|
+
|
9
|
+
def initialize(name)
|
10
|
+
@name = name
|
11
|
+
end
|
12
|
+
|
13
|
+
def draw
|
14
|
+
text = Image.new(WIDTH, HEIGHT) { self.background_color = COLOR_GREY }
|
15
|
+
|
16
|
+
draw = Magick::Draw.new do |d|
|
17
|
+
d.font_family = FONT_FAMILY
|
18
|
+
d.font_weight = FONT_WEIGHT
|
19
|
+
d.pointsize = FONT_SIZE
|
20
|
+
d.gravity = CenterGravity
|
21
|
+
d.fill = COLOR_WHITE
|
22
|
+
end
|
23
|
+
|
24
|
+
draw.annotate(text, 0, 0, 0, 0, @name.upcase)
|
25
|
+
text.trim!
|
26
|
+
|
27
|
+
canvas = Image.new(WIDTH, HEIGHT) { self.background_color = COLOR_GREY }
|
28
|
+
canvas.composite!(text, WestGravity, PADDING, 0, OverCompositeOp)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Bagel
|
2
|
+
module Graphic
|
3
|
+
class Scoreboard::Score
|
4
|
+
WIDTH = 50
|
5
|
+
HEIGHT = 50
|
6
|
+
|
7
|
+
def initialize(value)
|
8
|
+
@value = value
|
9
|
+
end
|
10
|
+
|
11
|
+
def draw
|
12
|
+
text = Image.new(HEIGHT * 2, HEIGHT * 2) { |i| i.background_color = color_bg }
|
13
|
+
|
14
|
+
draw = Magick::Draw.new do |d|
|
15
|
+
d.font_family = FONT_FAMILY
|
16
|
+
d.font_weight = FONT_WEIGHT
|
17
|
+
d.pointsize = FONT_SIZE
|
18
|
+
d.gravity = CenterGravity
|
19
|
+
d.fill = color_text
|
20
|
+
end
|
21
|
+
|
22
|
+
draw.annotate(text, 0, 0, 0, 0, @value.to_s)
|
23
|
+
text.trim!
|
24
|
+
|
25
|
+
canvas = Image.new(HEIGHT, HEIGHT) { |i| i.background_color = color_bg }
|
26
|
+
canvas.composite!(text, CenterGravity, 0, 0, OverCompositeOp)
|
27
|
+
end
|
28
|
+
|
29
|
+
def color_bg
|
30
|
+
raise 'abstract'
|
31
|
+
end
|
32
|
+
|
33
|
+
def color_text
|
34
|
+
raise 'abstract'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Bagel
|
2
|
+
module Graphic
|
3
|
+
class Scoreboard::Server
|
4
|
+
WIDTH = 10
|
5
|
+
HEIGHT = 50
|
6
|
+
|
7
|
+
def initialize(is_server)
|
8
|
+
@is_server = is_server
|
9
|
+
end
|
10
|
+
|
11
|
+
def draw
|
12
|
+
Image.new(WIDTH, HEIGHT) { |i| i.background_color = @is_server ? COLOR_ORANGE : COLOR_GREY }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module Bagel::Graphic
|
2
|
+
class Scoreboard
|
3
|
+
MARGIN = 3
|
4
|
+
PADDING = 10
|
5
|
+
|
6
|
+
FILENAME_SUFFIX = '-score'
|
7
|
+
|
8
|
+
private attr_reader :score, :names
|
9
|
+
|
10
|
+
def initialize(score, names)
|
11
|
+
@score, @names = score, names
|
12
|
+
end
|
13
|
+
|
14
|
+
def save
|
15
|
+
offset_y = Scoreboard::Context::HEIGHT + MARGIN
|
16
|
+
|
17
|
+
width = Scoreboard::Server::WIDTH + Scoreboard::Name::WIDTH + (Scoreboard::Score::HEIGHT * 3) + (MARGIN * 3)
|
18
|
+
height = (Scoreboard::Server::HEIGHT * 2) + Scoreboard::Context::HEIGHT + (MARGIN * 2)
|
19
|
+
|
20
|
+
canvas = Image.new(width, height) { |i| i.background_color = COLOR_TRANSPARENT }
|
21
|
+
|
22
|
+
margin_x = 0
|
23
|
+
|
24
|
+
if score.context
|
25
|
+
canvas.composite!(img_context, NorthWestGravity, 0, 0, OverCompositeOp)
|
26
|
+
end
|
27
|
+
|
28
|
+
canvas.composite!(img_server_a, NorthWestGravity, margin_x, offset_y, OverCompositeOp)
|
29
|
+
canvas.composite!(img_server_b, SouthWestGravity, margin_x, 0, OverCompositeOp)
|
30
|
+
|
31
|
+
margin_x += Scoreboard::Server::WIDTH
|
32
|
+
|
33
|
+
canvas.composite!(img_name_a, NorthWestGravity, margin_x, offset_y, OverCompositeOp)
|
34
|
+
canvas.composite!(img_name_b, SouthWestGravity, margin_x, 0, OverCompositeOp)
|
35
|
+
|
36
|
+
margin_x += Scoreboard::Name::WIDTH + MARGIN
|
37
|
+
|
38
|
+
score.sets.each do |set|
|
39
|
+
canvas.composite!(img_games_a(set[0]), NorthWestGravity, margin_x, offset_y, OverCompositeOp)
|
40
|
+
canvas.composite!(img_games_b(set[1]), SouthWestGravity, margin_x, 0, OverCompositeOp)
|
41
|
+
margin_x += Scoreboard::Score::HEIGHT + MARGIN
|
42
|
+
end
|
43
|
+
|
44
|
+
if score.points
|
45
|
+
canvas.composite!(img_points_a, NorthWestGravity, margin_x, offset_y, OverCompositeOp)
|
46
|
+
canvas.composite!(img_points_b, SouthWestGravity, margin_x, 0, OverCompositeOp)
|
47
|
+
end
|
48
|
+
|
49
|
+
canvas.write(path)
|
50
|
+
|
51
|
+
path
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def img_context
|
57
|
+
@img_context ||= Scoreboard::Context.new(score.context).draw
|
58
|
+
end
|
59
|
+
|
60
|
+
def img_server_a
|
61
|
+
@img_server_a ||= Scoreboard::Server.new(score.server?(Player.ONE)).draw
|
62
|
+
end
|
63
|
+
|
64
|
+
def img_server_b
|
65
|
+
@img_server_b ||= Scoreboard::Server.new(score.server?(Player.TWO)).draw
|
66
|
+
end
|
67
|
+
|
68
|
+
def img_name_a
|
69
|
+
@img_name_a ||= Scoreboard::Name.new(names[0]).draw
|
70
|
+
end
|
71
|
+
|
72
|
+
def img_name_b
|
73
|
+
@img_name_b ||= Scoreboard::Name.new(names[1]).draw
|
74
|
+
end
|
75
|
+
|
76
|
+
def img_games_a(games)
|
77
|
+
Scoreboard::Games.new(games).draw
|
78
|
+
end
|
79
|
+
|
80
|
+
def img_games_b(games)
|
81
|
+
Scoreboard::Games.new(games).draw
|
82
|
+
end
|
83
|
+
|
84
|
+
def img_points_a
|
85
|
+
points = Scoring.point_call(score.points[0], score.points[1], score.tiebreak?)
|
86
|
+
Scoreboard::Points.new(points).draw
|
87
|
+
end
|
88
|
+
|
89
|
+
def img_points_b
|
90
|
+
points = Scoring.point_call(score.points[1], score.points[0], score.tiebreak?)
|
91
|
+
Scoreboard::Points.new(points).draw
|
92
|
+
end
|
93
|
+
|
94
|
+
def path
|
95
|
+
File.join(Bagel.config.graphic_dir, filename)
|
96
|
+
end
|
97
|
+
|
98
|
+
def filename
|
99
|
+
"#{score.id}#{FILENAME_SUFFIX}#{FILENAME_EXTENSION}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Bagel
|
2
|
+
module Graphic
|
3
|
+
class Stats::Duration
|
4
|
+
WIDTH = Stats::WIDTH
|
5
|
+
HEIGHT = 90
|
6
|
+
|
7
|
+
COLOR_BG = COLOR_GREY
|
8
|
+
COLOR_TEXT = COLOR_WHITE
|
9
|
+
|
10
|
+
def initialize(minutes)
|
11
|
+
@minutes = minutes
|
12
|
+
end
|
13
|
+
|
14
|
+
def draw
|
15
|
+
canvas = Image.new(WIDTH, HEIGHT) { |i| i.background_color = COLOR_BG }
|
16
|
+
|
17
|
+
text = Image.new(WIDTH, HEIGHT) { |i| i.background_color = COLOR_BG }
|
18
|
+
|
19
|
+
draw = Magick::Draw.new do |d|
|
20
|
+
d.font_family = FONT_FAMILY
|
21
|
+
d.pointsize = 32
|
22
|
+
d.gravity = Magick::CenterGravity
|
23
|
+
d.fill = COLOR_TEXT
|
24
|
+
end
|
25
|
+
|
26
|
+
draw.annotate(text, 0, 0, 0, 0, "SET TIME: #{@minutes} MINUTES")
|
27
|
+
text.trim!
|
28
|
+
|
29
|
+
canvas.composite!(text, CenterGravity, 0, 0, AtopCompositeOp)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Bagel
|
2
|
+
module Graphic
|
3
|
+
class Stats::Header
|
4
|
+
WIDTH = Stats::WIDTH
|
5
|
+
HEIGHT = 90
|
6
|
+
|
7
|
+
COLOR_BG = COLOR_GREY
|
8
|
+
COLOR_TEXT = COLOR_WHITE
|
9
|
+
|
10
|
+
def initialize(set_number)
|
11
|
+
@set_number = set_number
|
12
|
+
end
|
13
|
+
|
14
|
+
def draw
|
15
|
+
text = Image.new(WIDTH, HEIGHT) { |i| i.background_color = COLOR_BG }
|
16
|
+
|
17
|
+
draw = Magick::Draw.new do |d|
|
18
|
+
d.font_family = FONT_FAMILY
|
19
|
+
d.pointsize = 36
|
20
|
+
d.gravity = Magick::CenterGravity
|
21
|
+
d.fill = COLOR_TEXT
|
22
|
+
end
|
23
|
+
|
24
|
+
draw.annotate(text, 0, 0, 0, 0, "SET #{@set_number} SUMMARY")
|
25
|
+
text.trim!
|
26
|
+
|
27
|
+
canvas = Image.new(WIDTH, HEIGHT) { |i| i.background_color = COLOR_BG }
|
28
|
+
canvas.composite!(text, CenterGravity, 0, 0, OverCompositeOp)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Bagel
|
2
|
+
module Graphic
|
3
|
+
class Stats::Result
|
4
|
+
WIDTH = Stats::WIDTH
|
5
|
+
HEIGHT = 70
|
6
|
+
|
7
|
+
COLOR_BG = COLOR_GREY
|
8
|
+
COLOR_TEXT = COLOR_WHITE
|
9
|
+
|
10
|
+
def initialize(names, games)
|
11
|
+
@names = names.map(&:upcase)
|
12
|
+
@games = games
|
13
|
+
|
14
|
+
@d = Magick::Draw.new do |d|
|
15
|
+
d.font_family = FONT_FAMILY
|
16
|
+
d.pointsize = 36
|
17
|
+
d.gravity = Magick::CenterGravity
|
18
|
+
d.fill = COLOR_TEXT
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def draw
|
23
|
+
canvas = Image.new(WIDTH, HEIGHT) { |i| i.background_color = COLOR_BG }
|
24
|
+
canvas.composite!(cell(@names.first), WestGravity, 0, 0, OverCompositeOp)
|
25
|
+
canvas.composite!(cell(@games.join(' - '), 72), CenterGravity, 0, 0, OverCompositeOp)
|
26
|
+
canvas.composite!(cell(@names.last), EastGravity, 0, 0, OverCompositeOp)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def cell(value, font_size=36)
|
32
|
+
cell = Image.new(WIDTH/3, HEIGHT) { |i| i.background_color = COLOR_BG }
|
33
|
+
text = Image.new(WIDTH, HEIGHT) { |i| i.background_color = COLOR_BG }
|
34
|
+
@d.pointsize = font_size
|
35
|
+
@d.annotate(text, 0, 0, 0, 0, value)
|
36
|
+
text.trim!
|
37
|
+
cell.composite!(text, CenterGravity, 0, 0, OverCompositeOp)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Bagel::Graphic
|
2
|
+
class Stats::Stat
|
3
|
+
WIDTH = Stats::WIDTH
|
4
|
+
HEIGHT = 65
|
5
|
+
|
6
|
+
COLOR_TEXT = COLOR_WHITE
|
7
|
+
COLOR_TEXT_HIGHLIGHT = COLOR_ORANGE
|
8
|
+
|
9
|
+
def initialize(index, stat)
|
10
|
+
@index = index
|
11
|
+
@stat = stat
|
12
|
+
|
13
|
+
@color_bg = @index.even? ? COLOR_GREY_LIGHT : COLOR_GREY_DARK
|
14
|
+
|
15
|
+
@canvas = Image.new(WIDTH, HEIGHT) { |i| i.background_color = @color_bg }
|
16
|
+
@d = Magick::Draw.new do |d|
|
17
|
+
d.font_family = FONT_FAMILY
|
18
|
+
d.pointsize = 36
|
19
|
+
d.gravity = Magick::CenterGravity
|
20
|
+
d.fill = COLOR_TEXT
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def draw
|
25
|
+
left = cell(value: @stat.values[0], highlight: @stat.superior[0], is_small: false)
|
26
|
+
center = cell(value: @stat.name, is_small: true)
|
27
|
+
right = cell(value: @stat.values[1], highlight: @stat.superior[1], is_small: false)
|
28
|
+
|
29
|
+
@canvas.composite!(left, WestGravity, 0, 0, OverCompositeOp)
|
30
|
+
@canvas.composite!(center, CenterGravity, 0, 0, OverCompositeOp)
|
31
|
+
@canvas.composite!(right, EastGravity, 0, 0, OverCompositeOp)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def cell(args)
|
37
|
+
cell = Image.new(WIDTH / 3, HEIGHT) { |i| i.background_color = @color_bg }
|
38
|
+
text = Image.new(WIDTH, HEIGHT) { |i| i.background_color = @color_bg }
|
39
|
+
|
40
|
+
@d.fill = args[:highlight] ? COLOR_TEXT_HIGHLIGHT : COLOR_TEXT
|
41
|
+
@d.pointsize = 32 if args[:is_small]
|
42
|
+
|
43
|
+
@d.annotate(text, 0, 0, 0, 0, args[:value].to_s)
|
44
|
+
text.trim!
|
45
|
+
cell.composite!(text, CenterGravity, 0, 0, OverCompositeOp)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Bagel::Graphic
|
2
|
+
class Stats
|
3
|
+
WIDTH = 1440
|
4
|
+
HEIGHT = 900
|
5
|
+
|
6
|
+
COLOR_BG = COLOR_GREY
|
7
|
+
|
8
|
+
FILENAME_SUFFIX = '-stats'
|
9
|
+
|
10
|
+
private attr_reader :names, :score, :points
|
11
|
+
|
12
|
+
def initialize(names:, score:, points:)
|
13
|
+
@names = names
|
14
|
+
@score = score
|
15
|
+
@points = points
|
16
|
+
|
17
|
+
@canvas = Image.new(WIDTH, HEIGHT) { |i| i.background_color = COLOR_BG }
|
18
|
+
@offset_y = 0
|
19
|
+
end
|
20
|
+
|
21
|
+
def save
|
22
|
+
add_header
|
23
|
+
add_result
|
24
|
+
add_duration
|
25
|
+
|
26
|
+
add_stat(0, Bagel::Tennis::Stats::Aces.new(points))
|
27
|
+
add_stat(1, Bagel::Tennis::Stats::DoubleFaults.new(points))
|
28
|
+
add_stat(0, Bagel::Tennis::Stats::FirstServeIn.new(points))
|
29
|
+
add_stat(1, Bagel::Tennis::Stats::FirstServePointsWon.new(points))
|
30
|
+
add_stat(0, Bagel::Tennis::Stats::SecondServePointsWon.new(points))
|
31
|
+
add_stat(1, Bagel::Tennis::Stats::Winners.new(points))
|
32
|
+
add_stat(0, Bagel::Tennis::Stats::UnforcedErrors.new(points))
|
33
|
+
add_stat(1, Bagel::Tennis::Stats::NetPointsWon.new(points))
|
34
|
+
add_stat(0, Bagel::Tennis::Stats::BreakPointsWon.new(points))
|
35
|
+
add_stat(1, Bagel::Tennis::Stats::PointsWon.new(points))
|
36
|
+
|
37
|
+
@canvas.write(path)
|
38
|
+
path
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def add_header
|
44
|
+
graphic = Bagel::Graphic::Stats::Header.new(score.set_number).draw
|
45
|
+
@canvas.composite!(graphic, NorthGravity, 0, @offset_y, OverCompositeOp)
|
46
|
+
@offset_y += Stats::Header::HEIGHT
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_result
|
50
|
+
graphic = Bagel::Graphic::Stats::Result.new(names, score.set_score).draw
|
51
|
+
@canvas.composite!(graphic, NorthGravity, 0, @offset_y, OverCompositeOp)
|
52
|
+
@offset_y += Stats::Result::HEIGHT
|
53
|
+
end
|
54
|
+
|
55
|
+
def add_duration
|
56
|
+
graphic = Bagel::Graphic::Stats::Duration.new(duration).draw
|
57
|
+
@canvas.composite!(graphic, NorthGravity, 0, @offset_y, OverCompositeOp)
|
58
|
+
@offset_y += Stats::Duration::HEIGHT
|
59
|
+
end
|
60
|
+
|
61
|
+
def add_stat(index, stat)
|
62
|
+
row = Bagel::Graphic::Stats::Stat.new(index, stat).draw
|
63
|
+
@canvas.composite!(row, NorthGravity, 0, @offset_y, OverCompositeOp)
|
64
|
+
@offset_y += Stats::Stat::HEIGHT
|
65
|
+
end
|
66
|
+
|
67
|
+
def duration
|
68
|
+
start, finish = points[0].start, points[-1].finish
|
69
|
+
Timeframe.new(start, finish).duration_minutes
|
70
|
+
end
|
71
|
+
|
72
|
+
def filename
|
73
|
+
"#{score.set_number.to_s.rjust(2, '0')}#{FILENAME_SUFFIX}#{FILENAME_EXTENSION}"
|
74
|
+
end
|
75
|
+
|
76
|
+
def path
|
77
|
+
File.join(Bagel.config.graphic_dir, filename)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|