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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/bin/rubygoal +12 -2
  3. data/lib/rubygoal.rb +1 -18
  4. data/lib/rubygoal/ball.rb +60 -0
  5. data/lib/rubygoal/coach.rb +81 -0
  6. data/lib/rubygoal/coach_definition.rb +54 -0
  7. data/lib/rubygoal/coach_loader.rb +55 -0
  8. data/lib/rubygoal/coaches/coach_definition_away.rb +72 -0
  9. data/lib/rubygoal/coaches/coach_definition_home.rb +76 -0
  10. data/lib/rubygoal/configuration.rb +49 -0
  11. data/lib/rubygoal/coordinate.rb +33 -0
  12. data/lib/rubygoal/field.rb +134 -0
  13. data/lib/rubygoal/formation.rb +73 -0
  14. data/lib/rubygoal/formation/formation_dsl.rb +67 -0
  15. data/lib/rubygoal/game.rb +162 -0
  16. data/lib/rubygoal/goal.rb +26 -0
  17. data/lib/rubygoal/match_data.rb +130 -0
  18. data/lib/rubygoal/moveable.rb +68 -0
  19. data/lib/rubygoal/player.rb +87 -0
  20. data/lib/rubygoal/players/average.rb +16 -0
  21. data/lib/rubygoal/players/captain.rb +15 -0
  22. data/lib/rubygoal/players/fast.rb +16 -0
  23. data/lib/rubygoal/players/goalkeeper.rb +26 -0
  24. data/lib/rubygoal/players/player_movement.rb +98 -0
  25. data/lib/rubygoal/recorder.rb +53 -0
  26. data/lib/rubygoal/simulator.rb +33 -0
  27. data/lib/rubygoal/team.rb +198 -0
  28. data/lib/rubygoal/teams/away.rb +15 -0
  29. data/lib/rubygoal/teams/home.rb +15 -0
  30. data/lib/rubygoal/util.rb +36 -0
  31. data/lib/rubygoal/version.rb +3 -0
  32. metadata +35 -23
  33. data/lib/rubygoal/gui.rb +0 -20
  34. data/lib/rubygoal/gui/ball.rb +0 -26
  35. data/lib/rubygoal/gui/field.rb +0 -21
  36. data/lib/rubygoal/gui/game.rb +0 -166
  37. data/lib/rubygoal/gui/goal.rb +0 -23
  38. data/lib/rubygoal/gui/players.rb +0 -28
  39. data/lib/rubygoal/gui/version.rb +0 -5
  40. data/media/average_away.png +0 -0
  41. data/media/average_home.png +0 -0
  42. data/media/background.png +0 -0
  43. data/media/ball.png +0 -0
  44. data/media/captain_away.png +0 -0
  45. data/media/captain_home.png +0 -0
  46. data/media/fast_away.png +0 -0
  47. data/media/fast_home.png +0 -0
  48. data/media/goal.png +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7a9f36e4a9184d9837b4834ab1449995676e02ca
4
- data.tar.gz: 6c5e76bef10ba32174430b6ffd68e175eebdb463
3
+ metadata.gz: d155a0a59d614e49e7832da9ca8fc4c02273d179
4
+ data.tar.gz: de24cb2ef8982d53a277e5bc3f6bd0f7334d9058
5
5
  SHA512:
6
- metadata.gz: 256936663d874aeb3a2c9a690af37da3bc43811c98442d3f73b2321ccc9eb9ea52d3f4466b5964e6d84fa15f5c5398399fe4e8fc47053db2c58a7fd5e87538a9
7
- data.tar.gz: 135a5704aea61868d8286e619821a56db2e7c923ead040dd1c97d2aa0d5b73b9e2f9067897df4f624e74e4e9ff19d095d71f6b06301bc7201e6fa31921bb86d4
6
+ metadata.gz: 3885e0a61ac501bb8507758a3e133015a338a01079333f9b41973e452f5e7310c49941c722702a7dbc6753553729945b8120cfcab325a679b46e23d955e3170c
7
+ data.tar.gz: 42685daf89b6fb6c45bab128e121199db7a8cc0e3725e9cf245e3485d87c02f9b892aa495237a2d7b81a2bab9082169a2317ce07be5bf440683653acb1f8203b
@@ -1,5 +1,15 @@
1
1
  #!/usr/bin/env ruby
2
2
  # -*- mode: ruby -*-
3
3
 
4
- require 'rubygoal/gui'
5
- Rubygoal::Gui.start
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
+
@@ -1,18 +1 @@
1
- require 'rubygoal-core'
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