rubygoal 2.0.0 → 2.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 +4 -4
- data/bin/rubygoal +12 -2
- data/lib/rubygoal.rb +1 -18
- 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 +68 -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 +53 -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
- metadata +35 -23
- data/lib/rubygoal/gui.rb +0 -20
- data/lib/rubygoal/gui/ball.rb +0 -26
- data/lib/rubygoal/gui/field.rb +0 -21
- data/lib/rubygoal/gui/game.rb +0 -166
- data/lib/rubygoal/gui/goal.rb +0 -23
- data/lib/rubygoal/gui/players.rb +0 -28
- data/lib/rubygoal/gui/version.rb +0 -5
- data/media/average_away.png +0 -0
- data/media/average_home.png +0 -0
- data/media/background.png +0 -0
- data/media/ball.png +0 -0
- data/media/captain_away.png +0 -0
- data/media/captain_home.png +0 -0
- data/media/fast_away.png +0 -0
- data/media/fast_home.png +0 -0
- data/media/goal.png +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d155a0a59d614e49e7832da9ca8fc4c02273d179
|
4
|
+
data.tar.gz: de24cb2ef8982d53a277e5bc3f6bd0f7334d9058
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3885e0a61ac501bb8507758a3e133015a338a01079333f9b41973e452f5e7310c49941c722702a7dbc6753553729945b8120cfcab325a679b46e23d955e3170c
|
7
|
+
data.tar.gz: 42685daf89b6fb6c45bab128e121199db7a8cc0e3725e9cf245e3485d87c02f9b892aa495237a2d7b81a2bab9082169a2317ce07be5bf440683653acb1f8203b
|
data/bin/rubygoal
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# -*- mode: ruby -*-
|
3
3
|
|
4
|
-
require 'rubygoal/
|
5
|
-
|
4
|
+
require 'rubygoal/simulator'
|
5
|
+
|
6
|
+
simulator = Rubygoal::Simulator.new
|
7
|
+
simulator.simulate
|
8
|
+
|
9
|
+
timestamp = Time.now.strftime("%Y%m%d%H%M%S")
|
10
|
+
file = File.new("recorded_game_#{timestamp}.json", 'w')
|
11
|
+
JSON.dump(simulator.recorded_game, file)
|
12
|
+
|
13
|
+
p "Match recorded in #{file.path}"
|
14
|
+
|
15
|
+
|
data/lib/rubygoal.rb
CHANGED
@@ -1,18 +1 @@
|
|
1
|
-
require 'rubygoal
|
2
|
-
require 'rubygoal/gui/game'
|
3
|
-
|
4
|
-
module Rubygoal
|
5
|
-
class << self
|
6
|
-
def start
|
7
|
-
game = Game.new(load_coach(:home), load_coach(:away))
|
8
|
-
gui = Gui::Game.new(game)
|
9
|
-
gui.show
|
10
|
-
end
|
11
|
-
|
12
|
-
private
|
13
|
-
|
14
|
-
def load_coach(side)
|
15
|
-
CoachLoader.new(side).coach
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
1
|
+
require 'rubygoal/game'
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'rubygoal/util'
|
2
|
+
require 'rubygoal/field'
|
3
|
+
require 'rubygoal/moveable'
|
4
|
+
|
5
|
+
module Rubygoal
|
6
|
+
class Ball
|
7
|
+
include Moveable
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
super
|
11
|
+
reinitialize_position
|
12
|
+
end
|
13
|
+
|
14
|
+
def goal?
|
15
|
+
Field.goal?(position)
|
16
|
+
end
|
17
|
+
|
18
|
+
def move(direction, speed)
|
19
|
+
self.velocity = Velocity.new(
|
20
|
+
Util.offset_x(direction, speed),
|
21
|
+
Util.offset_y(direction, speed)
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
def reinitialize_position
|
26
|
+
self.position = Field.center_position
|
27
|
+
end
|
28
|
+
|
29
|
+
def update(elapsed_time)
|
30
|
+
super
|
31
|
+
|
32
|
+
prevent_out_of_bounds
|
33
|
+
decelerate(elapsed_time)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def prevent_out_of_bounds
|
39
|
+
if Field.out_of_bounds_width?(position)
|
40
|
+
velocity.x *= -1
|
41
|
+
end
|
42
|
+
if Field.out_of_bounds_height?(position)
|
43
|
+
velocity.y *= -1
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def decelerate(elapsed_time)
|
48
|
+
coef = deceleration_coef(elapsed_time)
|
49
|
+
|
50
|
+
self.velocity = velocity.mult(coef)
|
51
|
+
end
|
52
|
+
|
53
|
+
def deceleration_coef(elapsed_time)
|
54
|
+
custom_frame_rate = 1 / 60.0
|
55
|
+
time_coef = elapsed_time / custom_frame_rate
|
56
|
+
|
57
|
+
Rubygoal.configuration.deceleration_coef ** time_coef
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Rubygoal
|
4
|
+
class Coach
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
def_delegators :coach_definition, :players, :name, :formation
|
8
|
+
|
9
|
+
def initialize(coach_definition)
|
10
|
+
@coach_definition = coach_definition
|
11
|
+
end
|
12
|
+
|
13
|
+
def errors
|
14
|
+
[].tap do |errors|
|
15
|
+
check_unique_captain(errors)
|
16
|
+
check_players_count(:average, errors)
|
17
|
+
check_players_count(:fast, errors)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def valid?
|
22
|
+
errors.empty?
|
23
|
+
end
|
24
|
+
|
25
|
+
def players_by_type(type)
|
26
|
+
players.select { |p| p.type == type }
|
27
|
+
end
|
28
|
+
|
29
|
+
def captain_player
|
30
|
+
players_by_type(:captain).first
|
31
|
+
end
|
32
|
+
|
33
|
+
def fast_players
|
34
|
+
players_by_type(:fast)
|
35
|
+
end
|
36
|
+
|
37
|
+
def average_players
|
38
|
+
players_by_type(:average)
|
39
|
+
end
|
40
|
+
|
41
|
+
def initial_formation
|
42
|
+
average_names = average_players.map(&:name)
|
43
|
+
fast_names = fast_players.map(&:name)
|
44
|
+
captain_name = captain_player.name
|
45
|
+
|
46
|
+
formation = Formation.new
|
47
|
+
|
48
|
+
formation.lineup do
|
49
|
+
defenders average_names[0], average_names[2], :none, average_names[3], average_names[4]
|
50
|
+
midfielders average_names[1], fast_names[0], :none, fast_names[1], average_names[5]
|
51
|
+
attackers :none, captain_name, :none, fast_names[2], :none
|
52
|
+
end
|
53
|
+
|
54
|
+
formation
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
attr_reader :coach_definition
|
60
|
+
|
61
|
+
def game_config
|
62
|
+
Rubygoal.configuration
|
63
|
+
end
|
64
|
+
|
65
|
+
def check_unique_captain(errors)
|
66
|
+
captain_count = players_by_type(:captain).size
|
67
|
+
|
68
|
+
if captain_count != 1
|
69
|
+
errors << "The number of captains is #{captain_count}"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def check_players_count(type, errors)
|
74
|
+
players_count = players_by_type(type).size
|
75
|
+
|
76
|
+
if players_count != game_config.send("#{type}_players_count")
|
77
|
+
errors << "The number of #{type} players is #{players_count}"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Rubygoal
|
2
|
+
class CoachDefinition
|
3
|
+
PlayerDefinition = Struct.new(:name, :type)
|
4
|
+
|
5
|
+
class << self
|
6
|
+
attr_reader :team_name
|
7
|
+
|
8
|
+
def team(&block)
|
9
|
+
instance_eval(&block)
|
10
|
+
end
|
11
|
+
|
12
|
+
def name(team_name)
|
13
|
+
@team_name = team_name
|
14
|
+
end
|
15
|
+
|
16
|
+
def players(&block)
|
17
|
+
@team_players = []
|
18
|
+
instance_eval(&block)
|
19
|
+
end
|
20
|
+
|
21
|
+
def method_missing(method, *args)
|
22
|
+
name = args.first.to_sym
|
23
|
+
@team_players << PlayerDefinition.new(name, method.to_sym)
|
24
|
+
end
|
25
|
+
|
26
|
+
def team_players
|
27
|
+
@team_players || [
|
28
|
+
PlayerDefinition.new(:captain, :captain),
|
29
|
+
PlayerDefinition.new(:fast1, :fast),
|
30
|
+
PlayerDefinition.new(:fast2, :fast),
|
31
|
+
PlayerDefinition.new(:fast3, :fast),
|
32
|
+
PlayerDefinition.new(:average1, :average),
|
33
|
+
PlayerDefinition.new(:average2, :average),
|
34
|
+
PlayerDefinition.new(:average3, :average),
|
35
|
+
PlayerDefinition.new(:average4, :average),
|
36
|
+
PlayerDefinition.new(:average5, :average),
|
37
|
+
PlayerDefinition.new(:average6, :average),
|
38
|
+
]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def players
|
43
|
+
self.class.team_players
|
44
|
+
end
|
45
|
+
|
46
|
+
def name
|
47
|
+
self.class.team_name
|
48
|
+
end
|
49
|
+
|
50
|
+
def formation(match)
|
51
|
+
raise NotImplementedError
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rubygoal/coach'
|
2
|
+
require 'rubygoal/coaches/coach_definition_home'
|
3
|
+
require 'rubygoal/coaches/coach_definition_away'
|
4
|
+
|
5
|
+
module Rubygoal
|
6
|
+
class CoachLoader
|
7
|
+
DEFAULT_COACH_DEFINITIONS = {
|
8
|
+
home: CoachDefinitionHome,
|
9
|
+
away: CoachDefinitionAway
|
10
|
+
}
|
11
|
+
|
12
|
+
def initialize(side)
|
13
|
+
@side = side
|
14
|
+
end
|
15
|
+
|
16
|
+
def coach
|
17
|
+
Coach.new(load_definition_coach)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
attr_reader :side
|
23
|
+
|
24
|
+
def default_definition_class
|
25
|
+
DEFAULT_COACH_DEFINITIONS[side]
|
26
|
+
end
|
27
|
+
|
28
|
+
def load_definition_coach
|
29
|
+
if filename && File.exists?(filename)
|
30
|
+
load filename
|
31
|
+
|
32
|
+
class_name = camelize(File.basename(filename, ".rb"))
|
33
|
+
Rubygoal.const_get(class_name).new
|
34
|
+
else
|
35
|
+
if filename && Rubygoal.configuration.debug_output
|
36
|
+
puts "File `#{filename}` doesn't exist. Using #{default_definition_class.name}."
|
37
|
+
end
|
38
|
+
|
39
|
+
default_definition_class.new
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def filename
|
44
|
+
side == :home ? ARGV[0] : ARGV[1]
|
45
|
+
end
|
46
|
+
|
47
|
+
def camelize(term)
|
48
|
+
string = term.to_s
|
49
|
+
string = string.sub(/^[a-z\d]*/) { $&.capitalize }
|
50
|
+
string.gsub!(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" }
|
51
|
+
string.gsub!('/', '::')
|
52
|
+
string
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'rubygoal/coach_definition'
|
2
|
+
require 'rubygoal/formation'
|
3
|
+
|
4
|
+
module Rubygoal
|
5
|
+
class CoachDefinitionAway < CoachDefinition
|
6
|
+
|
7
|
+
team do
|
8
|
+
name "Argentina"
|
9
|
+
end
|
10
|
+
|
11
|
+
def formation(match)
|
12
|
+
formation = Formation.new
|
13
|
+
|
14
|
+
if match.me.winning?
|
15
|
+
formation.lineup do
|
16
|
+
defenders :average1, :fast1, :none, :fast3, :average5
|
17
|
+
midfielders :average2, :none, :captain, :none, :average6
|
18
|
+
att_midfielders :average3
|
19
|
+
attackers :none, :none, :fast2, :average4, :none
|
20
|
+
end
|
21
|
+
elsif match.me.draw?
|
22
|
+
formation.lineup do
|
23
|
+
lines do
|
24
|
+
defenders 13
|
25
|
+
midfielders 40
|
26
|
+
attackers 65
|
27
|
+
end
|
28
|
+
|
29
|
+
defenders :average1, :fast1, :none, :average3, :average5
|
30
|
+
midfielders :average2, :none, :none, :none, :average6
|
31
|
+
attackers :none, :fast2, :none, :average4, :none
|
32
|
+
|
33
|
+
custom_position do
|
34
|
+
player :fast3
|
35
|
+
position 30, 10
|
36
|
+
end
|
37
|
+
custom_position do
|
38
|
+
player :captain
|
39
|
+
position match.ball.x, match.ball.y
|
40
|
+
end
|
41
|
+
end
|
42
|
+
elsif match.me.losing?
|
43
|
+
if match.time < 30
|
44
|
+
formation.lineup do
|
45
|
+
defenders :none, :average2, :average4, :average5, :none
|
46
|
+
midfielders :average1, :none, :none, :fast2, :average6
|
47
|
+
attackers :none, :average3, :none, :fast3, :none
|
48
|
+
|
49
|
+
custom_position do
|
50
|
+
player :fast1
|
51
|
+
position 33, 50
|
52
|
+
end
|
53
|
+
custom_position do
|
54
|
+
player :captain
|
55
|
+
position 67, 50
|
56
|
+
end
|
57
|
+
end
|
58
|
+
else
|
59
|
+
formation.lineup do
|
60
|
+
defenders :none, :average2, :fast1, :average5, :none
|
61
|
+
def_midfielders :average4
|
62
|
+
midfielders :average1, :none, :none, :captain, :average6
|
63
|
+
att_midfielders :fast2
|
64
|
+
attackers :none, :average3, :none, :fast3, :none
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
formation
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'rubygoal/coach_definition'
|
2
|
+
require 'rubygoal/formation'
|
3
|
+
|
4
|
+
module Rubygoal
|
5
|
+
class CoachDefinitionHome < CoachDefinition
|
6
|
+
|
7
|
+
team do
|
8
|
+
name "Uruguay"
|
9
|
+
|
10
|
+
players do
|
11
|
+
captain :godin
|
12
|
+
|
13
|
+
fast :cavani
|
14
|
+
fast :rolan
|
15
|
+
fast :suarez
|
16
|
+
|
17
|
+
average :pereira
|
18
|
+
average :gimenez
|
19
|
+
average :arevalo
|
20
|
+
average :lodeiro
|
21
|
+
average :cacerez
|
22
|
+
average :rodriguez
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def formation(match)
|
27
|
+
formation = Formation.new
|
28
|
+
|
29
|
+
if match.me.winning?
|
30
|
+
formation.defenders :pereira, :cacerez, :gimenez, :godin, :rodriguez
|
31
|
+
formation.midfielders :lodeiro, :none, :rolan, :none, :arevalo
|
32
|
+
formation.attackers :none, :cavani, :none, :suarez, :none
|
33
|
+
elsif match.time < 20
|
34
|
+
formation.defenders :none, :rolan, :cacerez, :gimenez, :none
|
35
|
+
formation.midfielders :arevalo, :lodeiro, :godin, :none, :pereira
|
36
|
+
formation.attackers :suarez, :none, :none, :cavani, :rodriguez
|
37
|
+
elsif match.time < 20 && match.me.winning?
|
38
|
+
# Mirror opponent players
|
39
|
+
|
40
|
+
opponent = match.other.positions
|
41
|
+
my_players = players
|
42
|
+
|
43
|
+
opponent.each_with_index do |(opponent_name, opponent_pos), index|
|
44
|
+
formation.lineup do
|
45
|
+
custom_position do
|
46
|
+
player my_players[index].name
|
47
|
+
position opponent_pos.x, 100.0 - opponent_pos.y
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
else
|
52
|
+
formation.lineup do
|
53
|
+
if match.ball.x < 50
|
54
|
+
lines do
|
55
|
+
defenders 10
|
56
|
+
midfielders 30
|
57
|
+
attackers 50
|
58
|
+
end
|
59
|
+
else
|
60
|
+
lines do
|
61
|
+
defenders 30
|
62
|
+
midfielders 50
|
63
|
+
attackers 70
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
defenders :pereira, :cacerez, :gimenez, :godin, :rodriguez
|
68
|
+
midfielders :lodeiro, :none, :rolan, :none, :arevalo
|
69
|
+
attackers :none, :cavani, :none, :suarez, :none
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
formation
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|