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
| @@ -0,0 +1,149 @@ | |
| 1 | 
            +
            require 'test_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Rubygoal
         | 
| 4 | 
            +
              class MatchDataTest < Minitest::Test
         | 
| 5 | 
            +
                def test_home_team_is_winning
         | 
| 6 | 
            +
                  match_data = create_match_data(
         | 
| 7 | 
            +
                    :home,
         | 
| 8 | 
            +
                    score_home: 2,
         | 
| 9 | 
            +
                    score_away: 0
         | 
| 10 | 
            +
                  )
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  assert match_data.me.winning?
         | 
| 13 | 
            +
                  assert match_data.other.losing?
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                def test_home_team_is_losing
         | 
| 17 | 
            +
                  match_data = create_match_data(
         | 
| 18 | 
            +
                    :home,
         | 
| 19 | 
            +
                    score_home: 1,
         | 
| 20 | 
            +
                    score_away: 3
         | 
| 21 | 
            +
                  )
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  assert match_data.me.losing?
         | 
| 24 | 
            +
                  assert match_data.other.winning?
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                def test_away_team_is_winning
         | 
| 28 | 
            +
                  match_data = create_match_data(
         | 
| 29 | 
            +
                    :away,
         | 
| 30 | 
            +
                    score_home: 0,
         | 
| 31 | 
            +
                    score_away: 2
         | 
| 32 | 
            +
                  )
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  assert match_data.me.winning?
         | 
| 35 | 
            +
                  assert match_data.other.losing?
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                def test_away_team_is_losing
         | 
| 39 | 
            +
                  match_data = create_match_data(
         | 
| 40 | 
            +
                    :away,
         | 
| 41 | 
            +
                    score_home: 3,
         | 
| 42 | 
            +
                    score_away: 1
         | 
| 43 | 
            +
                  )
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                  assert match_data.me.losing?
         | 
| 46 | 
            +
                  assert match_data.other.winning?
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                def test_home_team_is_a_draw
         | 
| 50 | 
            +
                  match_data = create_match_data(
         | 
| 51 | 
            +
                    :home,
         | 
| 52 | 
            +
                    score_home: 1,
         | 
| 53 | 
            +
                    score_away: 1
         | 
| 54 | 
            +
                  )
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                  assert match_data.me.draw?
         | 
| 57 | 
            +
                  assert match_data.other.draw?
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                def test_away_team_is_a_draw
         | 
| 61 | 
            +
                  match_data = create_match_data(
         | 
| 62 | 
            +
                    :away,
         | 
| 63 | 
            +
                    score_home: 1,
         | 
| 64 | 
            +
                    score_away: 1
         | 
| 65 | 
            +
                  )
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                  assert match_data.me.draw?
         | 
| 68 | 
            +
                  assert match_data.other.draw?
         | 
| 69 | 
            +
                end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                def test_match_info_includes_time
         | 
| 72 | 
            +
                  match_data = create_match_data(
         | 
| 73 | 
            +
                    :away,
         | 
| 74 | 
            +
                    time: 100
         | 
| 75 | 
            +
                  )
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                  assert_equal 100, match_data.time
         | 
| 78 | 
            +
                end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                def test_match_info_includes_player_positions
         | 
| 81 | 
            +
                  match_data = create_match_data(
         | 
| 82 | 
            +
                    :away,
         | 
| 83 | 
            +
                    home_players_positions: {
         | 
| 84 | 
            +
                      name: Position.new(Field::WIDTH, Field::HEIGHT)
         | 
| 85 | 
            +
                    },
         | 
| 86 | 
            +
                    away_players_positions: {
         | 
| 87 | 
            +
                      name: Position.new(Field::WIDTH / 2, 0)
         | 
| 88 | 
            +
                    }
         | 
| 89 | 
            +
                  )
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                  assert_equal({ name: Position.new(50, 0) }, match_data.me.positions)
         | 
| 92 | 
            +
                  assert_equal({ name: Position.new(100, 100) }, match_data.other.positions)
         | 
| 93 | 
            +
                end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                def test_match_info_exclude_goalkeeper_position
         | 
| 96 | 
            +
                  match_data = create_match_data(
         | 
| 97 | 
            +
                    :home,
         | 
| 98 | 
            +
                    home_players_positions: {
         | 
| 99 | 
            +
                      goalkeeper: Position.new(Field::WIDTH, Field::HEIGHT),
         | 
| 100 | 
            +
                      name:       Position.new(Field::WIDTH, Field::HEIGHT)
         | 
| 101 | 
            +
                    },
         | 
| 102 | 
            +
                  )
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                  assert_equal({ name: Position.new(100, 100) }, match_data.me.positions)
         | 
| 105 | 
            +
                end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                def test_home_match_info_includes_ball_position
         | 
| 108 | 
            +
                  match_data = create_match_data(
         | 
| 109 | 
            +
                    :home,
         | 
| 110 | 
            +
                    ball_position: Field.absolute_position(
         | 
| 111 | 
            +
                      Position.new(Field::WIDTH / 4, Field::HEIGHT / 2),
         | 
| 112 | 
            +
                      :home
         | 
| 113 | 
            +
                    )
         | 
| 114 | 
            +
                  )
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                  assert_equal Position.new(25, 50), match_data.ball
         | 
| 117 | 
            +
                end
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                def test_away_match_info_includes_ball_position
         | 
| 120 | 
            +
                  match_data = create_match_data(
         | 
| 121 | 
            +
                    :away,
         | 
| 122 | 
            +
                    ball_position: Field.absolute_position(
         | 
| 123 | 
            +
                      Position.new(Field::WIDTH / 4, Field::HEIGHT / 2),
         | 
| 124 | 
            +
                      :away
         | 
| 125 | 
            +
                    )
         | 
| 126 | 
            +
                  )
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                  assert_equal Position.new(25, 50), match_data.ball
         | 
| 129 | 
            +
                end
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                private
         | 
| 132 | 
            +
             | 
| 133 | 
            +
                def create_match_data(side, game_options)
         | 
| 134 | 
            +
                  MatchData::Factory.new(game_test_double(game_options), side)
         | 
| 135 | 
            +
                    .create
         | 
| 136 | 
            +
                end
         | 
| 137 | 
            +
             | 
| 138 | 
            +
                def game_test_double(game_options)
         | 
| 139 | 
            +
                  OpenStruct.new({
         | 
| 140 | 
            +
                    time: 0,
         | 
| 141 | 
            +
                    score_home: 0,
         | 
| 142 | 
            +
                    score_away: 0,
         | 
| 143 | 
            +
                    ball_position: Field.center_position,
         | 
| 144 | 
            +
                    home_players_positions: {},
         | 
| 145 | 
            +
                    away_players_positions: {}
         | 
| 146 | 
            +
                  }.merge(game_options))
         | 
| 147 | 
            +
                end
         | 
| 148 | 
            +
              end
         | 
| 149 | 
            +
            end
         | 
    
        data/test/player_test.rb
    ADDED
    
    | @@ -0,0 +1,125 @@ | |
| 1 | 
            +
            require 'test_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Rubygoal
         | 
| 4 | 
            +
              class PlayerTest < Minitest::Test
         | 
| 5 | 
            +
                def setup
         | 
| 6 | 
            +
                  home_coach = Coach.new(TestHomeCoachDefinition.new)
         | 
| 7 | 
            +
                  away_coach = Coach.new(TestAwayCoachDefinition.new)
         | 
| 8 | 
            +
                  @game = Game.new(home_coach, away_coach)
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  @player = game.players.first
         | 
| 11 | 
            +
                  @player.send(:time_to_kick_again=, 0)
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                def test_player_can_kick_the_ball_in_the_same_position
         | 
| 15 | 
            +
                  position = Position.new(100, 100)
         | 
| 16 | 
            +
                  game.ball.position = position
         | 
| 17 | 
            +
                  player.position = position
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  assert player.can_kick?(game.ball)
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                def test_player_can_kick_the_ball_when_is_close
         | 
| 23 | 
            +
                  game.ball.position = Position.new(100, 100)
         | 
| 24 | 
            +
                  player.position = Position.new(110, 115)
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  assert player.can_kick?(game.ball)
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                def test_player_can_not_kick_the_ball_when_is_far
         | 
| 30 | 
            +
                  game.ball.position = Position.new(100, 100)
         | 
| 31 | 
            +
                  player.position = Position.new(200, 200)
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  refute player.can_kick?(game.ball)
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                def test_player_can_not_kick_the_ball_again
         | 
| 37 | 
            +
                  position = Position.new(100, 100)
         | 
| 38 | 
            +
                  game.ball.position = position
         | 
| 39 | 
            +
                  player.position = position
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  player.kick(game.ball, Position.new(300, 300))
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  refute player.can_kick?(game.ball)
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                def test_player_can_kick_the_ball_again_after_time
         | 
| 47 | 
            +
                  position = Position.new(100, 100)
         | 
| 48 | 
            +
                  game.ball.position = position
         | 
| 49 | 
            +
                  player.position = position
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  player.kick(game.ball, Position.new(300, 300))
         | 
| 52 | 
            +
                  player.update(Rubygoal.configuration.kick_again_delay)
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  assert player.can_kick?(game.ball)
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                def test_kick_the_ball_to_a_different_place
         | 
| 58 | 
            +
                  position = Position.new(100, 100)
         | 
| 59 | 
            +
                  game.ball.position = position
         | 
| 60 | 
            +
                  game.ball.velocity = Velocity.new(0, 0)
         | 
| 61 | 
            +
                  player.position = position
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                  player.kick(game.ball, Position.new(300, 300))
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                  refute_equal Velocity.new(0, 0), game.ball.velocity
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                def test_kick_direction_range_right
         | 
| 69 | 
            +
                  # Set little error: < 2 degrees (180 * 0.01 < 2)
         | 
| 70 | 
            +
                  player.instance_variable_set(:@error, 0.01)
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                  position = Position.new(100, 100)
         | 
| 73 | 
            +
                  game.ball.position = position
         | 
| 74 | 
            +
                  game.ball.velocity = Velocity.new(0, 0)
         | 
| 75 | 
            +
                  player.position = position
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                  # 0 degree kick
         | 
| 78 | 
            +
                  player.kick(game.ball, Position.new(200, 100))
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                  velocity = game.ball.velocity
         | 
| 81 | 
            +
                  velocity_angle = Util.angle(0, 0, velocity.x, velocity.y)
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                  assert_in_delta 0, velocity_angle, 2
         | 
| 84 | 
            +
                end
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                def test_kick_direction_range_left
         | 
| 87 | 
            +
                  # Set little error: < 2 degrees (180 * 0.01 < 2)
         | 
| 88 | 
            +
                  player.instance_variable_set(:@error, 0.01)
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                  position = Position.new(100, 100)
         | 
| 91 | 
            +
                  game.ball.position = position
         | 
| 92 | 
            +
                  game.ball.velocity = Velocity.new(0, 0)
         | 
| 93 | 
            +
                  player.position = position
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                  # 180 degree kick
         | 
| 96 | 
            +
                  player.kick(game.ball, Position.new(0, 100))
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                  velocity = game.ball.velocity
         | 
| 99 | 
            +
                  velocity_angle = Util.positive_angle(0, 0, velocity.x, velocity.y)
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                  assert_in_delta 180, velocity_angle, 2
         | 
| 102 | 
            +
                end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                def test_kick_strength
         | 
| 105 | 
            +
                  # Set little error: distance error = 1 (20 * 0.05 = 1)
         | 
| 106 | 
            +
                  player.instance_variable_set(:@error, 0.05)
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                  position = Position.new(100, 100)
         | 
| 109 | 
            +
                  game.ball.position = position
         | 
| 110 | 
            +
                  game.ball.velocity = Velocity.new(0, 0)
         | 
| 111 | 
            +
                  player.position = position
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                  player.kick(game.ball, Position.new(200, 200))
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                  velocity = game.ball.velocity
         | 
| 116 | 
            +
                  velocity_strength = Util.distance(0, 0, velocity.x, velocity.y)
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                  assert_in_delta 20, velocity_strength, 1
         | 
| 119 | 
            +
                end
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                private
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                attr_reader :game, :player
         | 
| 124 | 
            +
              end
         | 
| 125 | 
            +
            end
         | 
| @@ -0,0 +1,49 @@ | |
| 1 | 
            +
            require 'test_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Rubygoal
         | 
| 4 | 
            +
              class GaolKeeperPlayerTest < Minitest::Test
         | 
| 5 | 
            +
                def setup
         | 
| 6 | 
            +
                  home_coach = Coach.new(TestHomeCoachDefinition.new)
         | 
| 7 | 
            +
                  away_coach = Coach.new(TestAwayCoachDefinition.new)
         | 
| 8 | 
            +
                  @game = Game.new(home_coach, away_coach)
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  @player = game.players.first
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def test_goalkeeper_is_already_covering_goal
         | 
| 14 | 
            +
                  goal_pos = Field.goal_position(:home)
         | 
| 15 | 
            +
                  game.ball.position = Position.new(300, goal_pos.y)
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  player.move_to_cover_goal(game.ball)
         | 
| 18 | 
            +
                  player.update(elapsed_time)
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                  assert_equal Velocity.new(0, 0), player.velocity
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def test_goalkeeper_moves_down_to_cover_goal
         | 
| 24 | 
            +
                  game.ball.position = Position.new(300, 300)
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  player.move_to_cover_goal(game.ball)
         | 
| 27 | 
            +
                  player.update(elapsed_time)
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  assert_in_delta Velocity.new(0, -3.5), player.velocity, 0.001
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                def test_goalkeeper_moves_up_to_cover_goal
         | 
| 33 | 
            +
                  game.ball.position = Position.new(300, 900)
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  player.move_to_cover_goal(game.ball)
         | 
| 36 | 
            +
                  player.update(elapsed_time)
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  assert_in_delta Velocity.new(0, 3.5), player.velocity, 0.001
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                private
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                attr_reader :game, :player
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                def elapsed_time
         | 
| 46 | 
            +
                  1 / 60.0
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
            end
         | 
| @@ -0,0 +1,76 @@ | |
| 1 | 
            +
            require 'test_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Rubygoal
         | 
| 4 | 
            +
              class PlayerMovementTest < Minitest::Test
         | 
| 5 | 
            +
                def setup
         | 
| 6 | 
            +
                  home_coach = Coach.new(TestHomeCoachDefinition.new)
         | 
| 7 | 
            +
                  away_coach = Coach.new(TestAwayCoachDefinition.new)
         | 
| 8 | 
            +
                  game = Game.new(home_coach, away_coach)
         | 
| 9 | 
            +
                  home_team = game.team_home
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  @player = home_team.players.values[0]
         | 
| 12 | 
            +
                  @other_player = home_team.players.values[1]
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  @player_movement = PlayerMovement.new(game, player)
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                def test_do_not_modify_velocity_if_not_blocker
         | 
| 18 | 
            +
                  player.position = Position.new(100, 0)
         | 
| 19 | 
            +
                  other_player.position = Position.new(170, 0)
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  player.move_to(Position.new(500, 0))
         | 
| 22 | 
            +
                  player_movement.update(elapsed_time)
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  assert_equal Velocity.new(3.5, 0), player.velocity
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                def test_modify_velocity_if_there_is_a_blocker_very_close
         | 
| 28 | 
            +
                  player.position = Position.new(100, 0)
         | 
| 29 | 
            +
                  other_player.position = Position.new(149, 0)
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  player.move_to(Position.new(500, 0))
         | 
| 32 | 
            +
                  player_movement.update(elapsed_time)
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  assert_in_delta Velocity.new(2.5, -2.5), player.velocity, 0.1
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                def test_decelerate_if_there_is_a_blocker_a_bit_close
         | 
| 38 | 
            +
                  player.position = Position.new(100, 0)
         | 
| 39 | 
            +
                  other_player.position = Position.new(169, 0)
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  player.move_to(Position.new(500, 0))
         | 
| 42 | 
            +
                  player_movement.update(elapsed_time)
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  assert_in_delta Velocity.new(3.1, 0), player.velocity, 0.1
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                def test_stop_if_close_to_destination_and_there_is_blocker
         | 
| 48 | 
            +
                  player.position = Position.new(100, 0)
         | 
| 49 | 
            +
                  other_player.position = Position.new(149, 0)
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  player.move_to(Position.new(160, 0))
         | 
| 52 | 
            +
                  player_movement.update(elapsed_time)
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  assert_equal Velocity.new(0, 0), player.velocity
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                def test_stop_if_blocker_is_ver_close_and_moving
         | 
| 58 | 
            +
                  player.position = Position.new(100, 0)
         | 
| 59 | 
            +
                  other_player.position = Position.new(150, 0)
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                  player.move_to(Position.new(500, 0))
         | 
| 62 | 
            +
                  other_player.move_to(Position.new(150, 500))
         | 
| 63 | 
            +
                  player_movement.update(elapsed_time)
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                  assert_equal Velocity.new(0, 0), player.velocity
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                private
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                attr_reader :player_movement, :player, :other_player
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                def elapsed_time
         | 
| 73 | 
            +
                  1 / 60.0
         | 
| 74 | 
            +
                end
         | 
| 75 | 
            +
              end
         | 
| 76 | 
            +
            end
         | 
| @@ -0,0 +1,118 @@ | |
| 1 | 
            +
            require 'test_helper'
         | 
| 2 | 
            +
            require 'timecop'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            require 'rubygoal/recorder'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            module Rubygoal
         | 
| 7 | 
            +
              class RecorderTest < Minitest::Test
         | 
| 8 | 
            +
                def setup
         | 
| 9 | 
            +
                  Rubygoal.configuration.record_game = true
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  home_coach = Coach.new(TestHomeCoachDefinition.new)
         | 
| 12 | 
            +
                  away_coach = Coach.new(TestAwayCoachDefinition.new)
         | 
| 13 | 
            +
                  @game = Game.new(home_coach, away_coach)
         | 
| 14 | 
            +
                  @recorder = @game.recorder
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                def test_recorded_team_names
         | 
| 18 | 
            +
                  expected_teams = {
         | 
| 19 | 
            +
                    home: 'Test Home Team',
         | 
| 20 | 
            +
                    away: 'Test Away Team'
         | 
| 21 | 
            +
                  }
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  assert_equal expected_teams, recorder.to_hash[:teams]
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                def test_recorded_score
         | 
| 27 | 
            +
                  expected_score = {
         | 
| 28 | 
            +
                    home: 0,
         | 
| 29 | 
            +
                    away: 0
         | 
| 30 | 
            +
                  }
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                  assert_equal expected_score, recorder.to_hash[:score]
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                def test_initial_recorded_frames
         | 
| 36 | 
            +
                  assert_equal [], recorder.to_hash[:frames]
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                def test_recorded_frame_after_first_update
         | 
| 40 | 
            +
                  @game.update
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  ball_position = Field.center_position
         | 
| 43 | 
            +
                  frames = recorder.to_hash[:frames]
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                  assert_equal 1, frames.count
         | 
| 46 | 
            +
                  assert_in_delta 120, frames.first[:time], 0.001
         | 
| 47 | 
            +
                  assert_equal(
         | 
| 48 | 
            +
                    { home: 0, away: 0 },
         | 
| 49 | 
            +
                    frames.first[:score]
         | 
| 50 | 
            +
                  )
         | 
| 51 | 
            +
                  assert_equal(
         | 
| 52 | 
            +
                    { x: ball_position.x, y: ball_position.y},
         | 
| 53 | 
            +
                    frames.first[:ball]
         | 
| 54 | 
            +
                  )
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                def test_recorded_frame_with_11_values_for_player_info
         | 
| 58 | 
            +
                  @game.update
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                  first_frame = recorder.to_hash[:frames].first
         | 
| 61 | 
            +
                  home_players = first_frame[:home_players]
         | 
| 62 | 
            +
                  away_players = first_frame[:away_players]
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                  assert_equal 11, home_players.count
         | 
| 65 | 
            +
                  assert_equal 11, away_players.count
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                def test_recorded_frame_with_detailed_player_info
         | 
| 69 | 
            +
                  @game.update
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                  first_frame = recorder.to_hash[:frames].first
         | 
| 72 | 
            +
                  home_players = first_frame[:home_players]
         | 
| 73 | 
            +
                  away_players = first_frame[:away_players]
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                  goalkeeper_field_pos = Position.new(50, Field::HEIGHT / 2)
         | 
| 76 | 
            +
                  goalkeeper_pos_home = Field.absolute_position(goalkeeper_field_pos, :home)
         | 
| 77 | 
            +
                  goalkeeper_pos_away = Field.absolute_position(goalkeeper_field_pos, :away)
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                  assert_equal(
         | 
| 80 | 
            +
                    {
         | 
| 81 | 
            +
                      x: goalkeeper_pos_home.x,
         | 
| 82 | 
            +
                      y: goalkeeper_pos_home.y,
         | 
| 83 | 
            +
                      angle: 0,
         | 
| 84 | 
            +
                      type: :average
         | 
| 85 | 
            +
                    },
         | 
| 86 | 
            +
                    home_players.first
         | 
| 87 | 
            +
                  )
         | 
| 88 | 
            +
                  assert_equal(
         | 
| 89 | 
            +
                    {
         | 
| 90 | 
            +
                      x: goalkeeper_pos_away.x,
         | 
| 91 | 
            +
                      y: goalkeeper_pos_away.y,
         | 
| 92 | 
            +
                      angle: 0,
         | 
| 93 | 
            +
                      type: :average
         | 
| 94 | 
            +
                    },
         | 
| 95 | 
            +
                    away_players.first
         | 
| 96 | 
            +
                  )
         | 
| 97 | 
            +
                end
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                def test_recorded_frame_some_updates
         | 
| 100 | 
            +
                  time = Time.now
         | 
| 101 | 
            +
                  21.times do
         | 
| 102 | 
            +
                    @game.update
         | 
| 103 | 
            +
                    time += 0.25
         | 
| 104 | 
            +
                    Timecop.travel(time)
         | 
| 105 | 
            +
                  end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                  frames = recorder.to_hash[:frames]
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                  assert_equal 21, frames.count
         | 
| 110 | 
            +
                  assert_in_delta 120, frames.first[:time], 0.001
         | 
| 111 | 
            +
                  assert_in_delta 115, frames.last[:time], 0.001
         | 
| 112 | 
            +
                end
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                private
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                attr_reader :game, :recorder
         | 
| 117 | 
            +
              end
         | 
| 118 | 
            +
            end
         |