rubygoal-core 1.0.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/LICENSE +18 -0
- data/README.md +85 -0
- data/bin/rubygoal +15 -0
- data/lib/rubygoal.rb +1 -0
- data/lib/rubygoal/ball.rb +60 -0
- data/lib/rubygoal/coach.rb +81 -0
- data/lib/rubygoal/coach_definition.rb +54 -0
- data/lib/rubygoal/coach_loader.rb +55 -0
- data/lib/rubygoal/coaches/coach_definition_away.rb +72 -0
- data/lib/rubygoal/coaches/coach_definition_home.rb +76 -0
- data/lib/rubygoal/configuration.rb +49 -0
- data/lib/rubygoal/coordinate.rb +33 -0
- data/lib/rubygoal/field.rb +134 -0
- data/lib/rubygoal/formation.rb +73 -0
- data/lib/rubygoal/formation/formation_dsl.rb +67 -0
- data/lib/rubygoal/game.rb +162 -0
- data/lib/rubygoal/goal.rb +26 -0
- data/lib/rubygoal/match_data.rb +130 -0
- data/lib/rubygoal/moveable.rb +67 -0
- data/lib/rubygoal/player.rb +87 -0
- data/lib/rubygoal/players/average.rb +16 -0
- data/lib/rubygoal/players/captain.rb +15 -0
- data/lib/rubygoal/players/fast.rb +16 -0
- data/lib/rubygoal/players/goalkeeper.rb +26 -0
- data/lib/rubygoal/players/player_movement.rb +98 -0
- data/lib/rubygoal/recorder.rb +56 -0
- data/lib/rubygoal/simulator.rb +33 -0
- data/lib/rubygoal/team.rb +198 -0
- data/lib/rubygoal/teams/away.rb +15 -0
- data/lib/rubygoal/teams/home.rb +15 -0
- data/lib/rubygoal/util.rb +36 -0
- data/lib/rubygoal/version.rb +3 -0
- data/test/ball_test.rb +56 -0
- data/test/coach_test.rb +49 -0
- data/test/field_test.rb +103 -0
- data/test/fixtures/four_fast_players_coach_definition.rb +27 -0
- data/test/fixtures/less_players_coach_definition.rb +25 -0
- data/test/fixtures/mirror_strategy_coach_definition.rb +42 -0
- data/test/fixtures/more_players_coach_definition.rb +27 -0
- data/test/fixtures/test_away_coach_definition.rb +34 -0
- data/test/fixtures/test_home_coach_definition.rb +34 -0
- data/test/fixtures/two_captains_coach_definition.rb +27 -0
- data/test/fixtures/valid_coach_definition.rb +26 -0
- data/test/formation_test.rb +81 -0
- data/test/game_test.rb +84 -0
- data/test/match_data_test.rb +149 -0
- data/test/player_test.rb +125 -0
- data/test/players/goalkeeper_test.rb +49 -0
- data/test/players/player_movement_test.rb +76 -0
- data/test/recorder_test.rb +118 -0
- data/test/team_test.rb +97 -0
- data/test/test_helper.rb +21 -0
- metadata +158 -0
data/test/field_test.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
require 'rubygoal/field'
|
4
|
+
|
5
|
+
module Rubygoal
|
6
|
+
class FieldTest < Minitest::Test
|
7
|
+
def test_center_position
|
8
|
+
assert_equal Position.new(959, 581), Field.center_position
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_home_goal_position
|
12
|
+
assert_equal Position.new(262, 581), Field.goal_position(:home)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_away_goal_position
|
16
|
+
assert_equal Position.new(1656, 581), Field.goal_position(:away)
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_home_position_side
|
20
|
+
assert_equal :home, Field.position_side(Position.new(958, 0))
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_away_position_side
|
24
|
+
assert_equal :away, Field.position_side(Position.new(960, 0))
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_left_out_of_bounds_width
|
28
|
+
assert Field.out_of_bounds_width?(Position.new(261, 0))
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_inside_left_bounds_width
|
32
|
+
refute Field.out_of_bounds_width?(Position.new(262, 0))
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_inside_right_bounds_width
|
36
|
+
refute Field.out_of_bounds_width?(Position.new(1656, 0))
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_right_out_of_bounds_width
|
40
|
+
assert Field.out_of_bounds_width?(Position.new(1657, 0))
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_up_out_of_bounds_height
|
44
|
+
assert Field.out_of_bounds_height?(Position.new(0, 111))
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_inside_upper_bounds_height
|
48
|
+
refute Field.out_of_bounds_height?(Position.new(0, 112))
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_inside_bottom_bounds_height
|
52
|
+
refute Field.out_of_bounds_height?(Position.new(0, 1050))
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_down_out_of_bounds_width
|
56
|
+
assert Field.out_of_bounds_height?(Position.new(0, 1051))
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_middle_goal
|
60
|
+
assert Field.goal?(Position.new(261, 581))
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_upper_goal
|
64
|
+
assert Field.goal?(Position.new(261, 718))
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_bottom_goal
|
68
|
+
assert Field.goal?(Position.new(261, 444))
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_upper_missed_goal
|
72
|
+
refute Field.goal?(Position.new(261, 719))
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_bottom_missed_goal
|
76
|
+
refute Field.goal?(Position.new(261, 443))
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_close_to_goal_straight
|
80
|
+
assert Field.close_to_goal?(Position.new(536, 581), :home)
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_not_close_to_goal_straight
|
84
|
+
refute Field.close_to_goal?(Position.new(537, 581), :home)
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_close_to_goal_upper_diagonal
|
88
|
+
assert Field.close_to_goal?(Position.new(456, 775), :home)
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_not_close_to_goal_upper_diagonal
|
92
|
+
refute Field.close_to_goal?(Position.new(457, 776), :home)
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_close_to_goal_lower_diagonal
|
96
|
+
assert Field.close_to_goal?(Position.new(456, 387), :home)
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_not_close_to_goal_lower_diagonal
|
100
|
+
refute Field.close_to_goal?(Position.new(457, 386), :home)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Rubygoal
|
2
|
+
class FourFastPlayersCoachDefinition < CoachDefinition
|
3
|
+
team do
|
4
|
+
name "FourFastPlayers"
|
5
|
+
|
6
|
+
players do
|
7
|
+
captain :captain
|
8
|
+
|
9
|
+
fast :fast1
|
10
|
+
fast :fast2
|
11
|
+
fast :fast3
|
12
|
+
fast :fast4
|
13
|
+
|
14
|
+
average :average1
|
15
|
+
average :average2
|
16
|
+
average :average3
|
17
|
+
average :average4
|
18
|
+
average :average5
|
19
|
+
average :average6
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def formation(match)
|
24
|
+
Formation.new
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Rubygoal
|
2
|
+
class LessPlayersCoachDefnition < CoachDefinition
|
3
|
+
team do
|
4
|
+
name "LessPlayers"
|
5
|
+
|
6
|
+
players do
|
7
|
+
captain :captain
|
8
|
+
|
9
|
+
fast :fast1
|
10
|
+
fast :fast2
|
11
|
+
fast :fast3
|
12
|
+
|
13
|
+
average :average2
|
14
|
+
average :average3
|
15
|
+
average :average4
|
16
|
+
average :average5
|
17
|
+
average :average6
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def formation(match)
|
22
|
+
Formation.new
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Rubygoal
|
2
|
+
class MirrorStrategyCoachDefinition < CoachDefinition
|
3
|
+
team do
|
4
|
+
name "Mimic Team"
|
5
|
+
|
6
|
+
players do
|
7
|
+
average :average1
|
8
|
+
average :average2
|
9
|
+
average :average3
|
10
|
+
average :average4
|
11
|
+
average :average5
|
12
|
+
average :average6
|
13
|
+
|
14
|
+
fast :fast1
|
15
|
+
fast :fast2
|
16
|
+
fast :fast3
|
17
|
+
|
18
|
+
captain :captain
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def formation(match)
|
23
|
+
# Mirror opponent players
|
24
|
+
|
25
|
+
formation = Formation.new
|
26
|
+
|
27
|
+
opponent = match.other.positions
|
28
|
+
my_players = players
|
29
|
+
|
30
|
+
opponent.each_with_index do |(_, opponent_pos), index|
|
31
|
+
formation.lineup do
|
32
|
+
custom_position do
|
33
|
+
player my_players[index].name
|
34
|
+
position opponent_pos.x, 100.0 - opponent_pos.y
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
formation
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Rubygoal
|
2
|
+
class MorePlayersCoachDefinition < CoachDefinition
|
3
|
+
team do
|
4
|
+
name "MorePlayers"
|
5
|
+
|
6
|
+
players do
|
7
|
+
captain :captain
|
8
|
+
|
9
|
+
fast :fast1
|
10
|
+
fast :fast2
|
11
|
+
fast :fast3
|
12
|
+
|
13
|
+
average :average1
|
14
|
+
average :average2
|
15
|
+
average :average3
|
16
|
+
average :average4
|
17
|
+
average :average5
|
18
|
+
average :average6
|
19
|
+
average :average7
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def formation(match)
|
24
|
+
Formation.new
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Rubygoal
|
2
|
+
class TestAwayCoachDefinition < CoachDefinition
|
3
|
+
team do
|
4
|
+
name "Test Away Team"
|
5
|
+
|
6
|
+
players do
|
7
|
+
captain :away_captain
|
8
|
+
|
9
|
+
fast :away_fast1
|
10
|
+
fast :away_fast2
|
11
|
+
fast :away_fast3
|
12
|
+
|
13
|
+
average :away_average1
|
14
|
+
average :away_average2
|
15
|
+
average :away_average3
|
16
|
+
average :away_average4
|
17
|
+
average :away_average5
|
18
|
+
average :away_average6
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def formation(match)
|
23
|
+
formation = Formation.new
|
24
|
+
|
25
|
+
formation.lineup do
|
26
|
+
defenders :away_average1, :away_fast1, :none, :away_fast3, :away_average5
|
27
|
+
midfielders :away_average2, :away_average3, :away_captain, :away_average4, :away_average6
|
28
|
+
attackers :away_fast2
|
29
|
+
end
|
30
|
+
|
31
|
+
formation
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Rubygoal
|
2
|
+
class TestHomeCoachDefinition < CoachDefinition
|
3
|
+
team do
|
4
|
+
name "Test Home Team"
|
5
|
+
|
6
|
+
players do
|
7
|
+
captain :home_captain
|
8
|
+
|
9
|
+
fast :home_fast1
|
10
|
+
fast :home_fast2
|
11
|
+
fast :home_fast3
|
12
|
+
|
13
|
+
average :home_average1
|
14
|
+
average :home_average2
|
15
|
+
average :home_average3
|
16
|
+
average :home_average4
|
17
|
+
average :home_average5
|
18
|
+
average :home_average6
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def formation(match)
|
23
|
+
formation = Formation.new
|
24
|
+
|
25
|
+
formation.lineup do
|
26
|
+
defenders :home_average1, :home_fast1, :none, :home_fast3, :home_average5
|
27
|
+
midfielders :home_average2, :none, :home_captain, :none, :home_average6
|
28
|
+
attackers :none, :home_average3, :home_fast2, :home_average4, :none
|
29
|
+
end
|
30
|
+
|
31
|
+
formation
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Rubygoal
|
2
|
+
class TwoCaptainsCoachDefinition < CoachDefinition
|
3
|
+
team do
|
4
|
+
name "TwoCaptains"
|
5
|
+
|
6
|
+
players do
|
7
|
+
captain :captain
|
8
|
+
captain :captain2
|
9
|
+
|
10
|
+
fast :fast1
|
11
|
+
fast :fast2
|
12
|
+
fast :fast3
|
13
|
+
|
14
|
+
average :average1
|
15
|
+
average :average2
|
16
|
+
average :average3
|
17
|
+
average :average4
|
18
|
+
average :average5
|
19
|
+
average :average6
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def formation(match)
|
24
|
+
Formation.new
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Rubygoal
|
2
|
+
class ValidCoachDefinition < CoachDefinition
|
3
|
+
team do
|
4
|
+
name "ValidTeam"
|
5
|
+
|
6
|
+
players do
|
7
|
+
captain :captain
|
8
|
+
|
9
|
+
fast :fast1
|
10
|
+
fast :fast2
|
11
|
+
fast :fast3
|
12
|
+
|
13
|
+
average :average1
|
14
|
+
average :average2
|
15
|
+
average :average3
|
16
|
+
average :average4
|
17
|
+
average :average5
|
18
|
+
average :average6
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def formation(match)
|
23
|
+
Formation.new
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
require 'rubygoal/formation'
|
4
|
+
|
5
|
+
module Rubygoal
|
6
|
+
class TestFormation < Minitest::Test
|
7
|
+
def setup
|
8
|
+
@formation = Formation.new
|
9
|
+
@formation.lineup do
|
10
|
+
defenders :average1, :average2, :none, :average3, :average4
|
11
|
+
midfielders :average5, :fast1, :none, :fast2, :average6
|
12
|
+
attackers :none, :captain, :none, :fast3, :none
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_default_formation_is_valid
|
17
|
+
assert @formation.valid?
|
18
|
+
assert_empty @formation.errors
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_player_default_positions
|
22
|
+
expected_positions = {
|
23
|
+
average1: Position.new(232, 156),
|
24
|
+
average2: Position.new(232, 312),
|
25
|
+
average3: Position.new(232, 625),
|
26
|
+
average4: Position.new(232, 782),
|
27
|
+
average5: Position.new(697, 156),
|
28
|
+
average6: Position.new(697, 782),
|
29
|
+
captain: Position.new(1162, 312),
|
30
|
+
fast1: Position.new(697, 312),
|
31
|
+
fast2: Position.new(697, 625),
|
32
|
+
fast3: Position.new(1162, 625)
|
33
|
+
}
|
34
|
+
|
35
|
+
expected_positions.each do |name, pos|
|
36
|
+
assert_in_delta pos, @formation.players_position[name], 1
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_custom_default_positions
|
41
|
+
@formation.lineup do
|
42
|
+
lines do
|
43
|
+
defenders 13
|
44
|
+
midfielders 43
|
45
|
+
attackers 65
|
46
|
+
end
|
47
|
+
|
48
|
+
defenders :average1, :average2, :none, :average3, :average4
|
49
|
+
midfielders :none, :fast1, :none, :fast2, :average6
|
50
|
+
attackers :none, :captain, :none, :none, :none
|
51
|
+
|
52
|
+
custom_position do
|
53
|
+
player :fast3
|
54
|
+
position 30, 10
|
55
|
+
end
|
56
|
+
custom_position do
|
57
|
+
player :average5
|
58
|
+
position 60, 50
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
expected_positions = {
|
63
|
+
average1: Position.new(181, 156),
|
64
|
+
average2: Position.new(181, 312),
|
65
|
+
average3: Position.new(181, 625),
|
66
|
+
average4: Position.new(181, 781),
|
67
|
+
average6: Position.new(600, 781),
|
68
|
+
captain: Position.new(906, 312),
|
69
|
+
fast1: Position.new(600, 312),
|
70
|
+
fast2: Position.new(600, 625),
|
71
|
+
|
72
|
+
fast3: Position.new(418, 94),
|
73
|
+
average5: Position.new(836, 469)
|
74
|
+
}
|
75
|
+
|
76
|
+
expected_positions.each do |name, pos|
|
77
|
+
assert_in_delta pos, @formation.players_position[name], 1
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/test/game_test.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'timecop'
|
3
|
+
|
4
|
+
module Rubygoal
|
5
|
+
class GameTest < Minitest::Test
|
6
|
+
def setup
|
7
|
+
home_coach = Coach.new(TestHomeCoachDefinition.new)
|
8
|
+
away_coach = Coach.new(TestAwayCoachDefinition.new)
|
9
|
+
@game = Game.new(home_coach, away_coach)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_initial_score
|
13
|
+
assert_equal 0, @game.score_home
|
14
|
+
assert_equal 0, @game.score_away
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_score_after_home_team_goal
|
18
|
+
goal_position = Field::goal_position(:away).add(Position.new(1, 0))
|
19
|
+
@game.ball.position = goal_position
|
20
|
+
|
21
|
+
@game.update
|
22
|
+
|
23
|
+
assert_equal 1, @game.score_home
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_score_after_away_team_goal
|
27
|
+
goal_position = Field::goal_position(:home).add(Position.new(-1, 0))
|
28
|
+
@game.ball.position = goal_position
|
29
|
+
|
30
|
+
@game.update
|
31
|
+
|
32
|
+
assert_equal 1, @game.score_away
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_celebrating_goal_after_init
|
36
|
+
refute @game.celebrating_goal?
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_celebrating_goal_after_away_team_goal
|
40
|
+
goal_position = Field::goal_position(:home).add(Position.new(-1, 0))
|
41
|
+
@game.ball.position = goal_position
|
42
|
+
|
43
|
+
@game.update
|
44
|
+
|
45
|
+
assert @game.celebrating_goal?
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_initial_time
|
49
|
+
assert_equal Rubygoal.configuration.game_time, @game.time
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_time_pass
|
53
|
+
# Begin game with an initial update call
|
54
|
+
@game.update
|
55
|
+
|
56
|
+
# Simulate time passing
|
57
|
+
elapsed_time = 70
|
58
|
+
Timecop.travel(Time.now + elapsed_time)
|
59
|
+
|
60
|
+
@game.update
|
61
|
+
|
62
|
+
remaining_time = Rubygoal.configuration.game_time - elapsed_time
|
63
|
+
assert_in_delta remaining_time, @game.time, 0.05
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_players
|
67
|
+
assert_equal 22, @game.players.size
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_recorded_game
|
71
|
+
Rubygoal.configuration.record_game = true
|
72
|
+
home_coach = Coach.new(TestHomeCoachDefinition.new)
|
73
|
+
away_coach = Coach.new(TestAwayCoachDefinition.new)
|
74
|
+
game = Game.new(home_coach, away_coach)
|
75
|
+
|
76
|
+
expected_teams = {
|
77
|
+
home: 'Test Home Team',
|
78
|
+
away: 'Test Away Team'
|
79
|
+
}
|
80
|
+
|
81
|
+
assert_equal expected_teams, game.recorded_game[:teams]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|