def test_get_non_offside_forward_team_mates_03(self): # Initialise myself state: PlayerState = PlayerState() state.world_view.side = "r" state.team_name = "Team1" state.position.set_value(Coordinate(1.94, -2.54), 0) # Set opponents op1 = PrecariousData( ObservedPlayer("Team2", 1, 4.47, 45, 0, 0, 0, 0, False, Coordinate(-2.06, -4.54)), 0) op2 = PrecariousData( ObservedPlayer("Team2", 2, 5.55, -45, 0, 0, 0, 0, False, Coordinate(-2.2, 1.15)), 0) state.world_view.other_players.append(op1) state.world_view.other_players.append(op2) # Set team_mate who is offside tm = PrecariousData( ObservedPlayer("Team1", 2, 6.08, 0, 0, 0, 0, 0, False, Coordinate(-4.06, -1.54)), 0) state.world_view.other_players.append(tm) non_offside_team_mates = state.world_view.get_non_offside_forward_team_mates( "Team1", state.world_view.side, state.position.get_value(), max_data_age=1, min_distance_free=2, min_dist_from_me=1) self.assertEqual( len(non_offside_team_mates), 0, "In this scenario, there should be no free non-offside players")
def __init__(self, **kwargs): Coordinate.__init__(self, **kwargs) #半径 self.radius = kwargs['radius'] #角度 self.angle = kwargs.get('angle', 90.0) #圆心 self.center = (0, 0) x = Geometry.sin(self.angle / 2) * self.radius y = Geometry.cos(self.angle / 2) * self.radius self.source = x, y self.target = -x, y #外切圆心,外切半径 if self.angle < 90: #三点求圆 self.wrap_center = Geometry.circle_center(self.source, self.target, self.center) self.wrap_radius = Geometry.distance(self.wrap_center, self.center) elif self.angle < 180: #两侧点中点 self.wrap_center = (0, y) self.wrap_radius = x else: #所在的圆 self.wrap_center = self.center self.wrap_radius = self.radius
def calculate_fieldprogress_length(start_ball: Ball, last_ball: Ball): goal_x = 52.5 goal_y = 0 goal_coord = Coordinate(goal_x, goal_y) start_coord = Coordinate(start_ball.x_coord, start_ball.y_coord) last_coord = Coordinate(last_ball.x_coord, last_ball.y_coord) start_dist = get_distance_between_coords(start_coord, goal_coord) end_dist = get_distance_between_coords(last_coord, goal_coord) return start_dist - end_dist
def is_near_lower_goal(goalie): if goalie.side == "l": x = -25 y = 33 if goalie.side == "r": x = 25 y = 33 if get_distance_between_coords(Coordinate(goalie.x_coord, goalie.y_coord), Coordinate(x, y)) < 2: return True return False
def __init__(self, **kwargs): Coordinate.__init__(self, **kwargs) #起始朝向 self.toward = kwargs.get('toward', self.rotate) #轨迹包含的线段 self.compose = kwargs['compose'] #角速度,每个时间片旋转的角度 self.velocity = kwargs.get('velocity', 20.0) #剩余角度 self.residual = 0.0
def __init__(self, **kwargs): Coordinate.__init__(self, **kwargs) #宽度 self.width = kwargs['width'] #高度 self.height = kwargs['height'] #包络圆心 self.wrap_center = (0, self.height / 2) #包络半径 self.wrap_radius = Geometry.distance(self.wrap_center, (self.width / 2, 0))
def __init__(self, **kwargs): Coordinate.__init__(self, **kwargs) Motion.__init__(self, **kwargs) #长度 self.length = kwargs['length'] #源点 self.source = (0, 0) #目标点 self.target = (0, self.length) #距离 self.distance = self.length
def __init__(self, **kwargs): Coordinate.__init__(self, **kwargs) #形状组成,由扇形和矩形组成 self.compose = kwargs.get('compose', []) #快速计算范围,不精确 sx = sy = 0.0 for shape in self.compose: x, y = shape.wrap_center sx += x sy += y sx /= len(self.compose) sy /= len(self.compose) self.wrap_center = (sx, sy) self.wrap_radius = sum(map(lambda x: x.wrap_radius, self.compose))
def __init__(self, **kwargs): Coordinate.__init__(self, **kwargs) Motion.__init__(self, **kwargs) #长度 self.length = kwargs['length'] middle = kwargs['middle'] #中间点,middle=0为圆 self.middle = (middle, self.length / 2) #源点 self.source = (0, 0) #目标点 if middle: self.target = (0, self.length) else: self.target = self.source #圆弧的圆心 if middle: self.center = Geometry.circle_center(self.source, self.target, self.middle) else: self.center = self.middle #半径 self.radius = Geometry.distance(self.source, self.center) #角度 center_x, center_y = self.center if middle > 0: self.angle = 360 - 2 * Geometry.acos(center_x / self.radius) elif middle < 0: self.angle = 2 * Geometry.acos(center_x / self.radius) else: self.angle = 360 #距离 self.distance = Geometry.radian(self.angle) * self.radius #上一个点 self.last_step = self.source
def test_get_non_offside_forward_team_mates_02(self): # Initialise myself state: PlayerState = PlayerState() state.world_view.side = "l" state.team_name = "Team1" state.position.set_value(Coordinate(-1.94, -2.54), 0) # Set opponents op1 = PrecariousData( ObservedPlayer("Team2", 1, 4.47, 45, 0, 0, 0, 0, False, Coordinate(2.06, -4.54)), 0) op2 = PrecariousData( ObservedPlayer("Team2", 2, 9.63, -45, 0, 0, 0, 0, False, Coordinate(6.4, 2.27)), 0) state.world_view.other_players.append(op1) state.world_view.other_players.append(op2) # Set team_mate who is offside tm = PrecariousData( ObservedPlayer("Team1", 2, 6.08, 0, 0, 0, 0, 0, False, Coordinate(4.06, -1.54)), 0) state.world_view.other_players.append(tm) non_offside_team_mates = state.world_view.get_non_offside_forward_team_mates( "Team1", state.world_view.side, state.position.get_value(), max_data_age=1, min_distance_free=2, min_dist_from_me=1) non_off_side_player: [ObservedPlayer] = non_offside_team_mates[0] self.assertEqual(non_off_side_player.num, 2, "Assert that the correct player is found") self.assertEqual( len(non_offside_team_mates), 1, "In this scenario, there should be 1 non-offside player")
def is_goalie_near_ball(game: Game, start_tick, end_tick): goalie = None for tick in range(start_tick, end_tick): stage = game.show_time[tick] for g in stage.goalies: if g.side == "r": goalie = g if goalie is None: print("goalie is none!!") return False if stage.get_ball_coord().euclidean_distance_from( Coordinate(goalie.x_coord, goalie.y_coord)) < _HIGHEST_DIST_GOALIE: if game.ball_first_time_outside_field is not None and tick <= game.ball_first_time_outside_field: return True return False
def get_ball_coord(self) -> Coordinate: return Coordinate(self.ball.x_coord, self.ball.y_coord)
def _find_applicable_strat_player(state: PlayerState) -> _StrategyGenerator: # Matches the current state of the game to a uppaal model, if applicable # Check if dribble strategy model can be applied if state.team_name in DRIBBLE_OR_PASS_TEAMS and state.needs_dribble_or_pass_strat( ): print(state.now(), " DRIBBLE STRAT - Player : ", state.num) possession_dir = Path(__file__).parent / "models" / "possessionmodel" if not possession_dir.exists(): os.makedirs(possession_dir) original_pos_model = Path( possession_dir).parent / "PassOrDribbleModel.xml" model_name = "possessionmodel{0}{1}.xml".format( state.world_view.side, state.num) new_pos_file = possession_dir / model_name if not new_pos_file.exists(): f = open(new_pos_file, "x") copyfile(original_pos_model, new_pos_file) f.close() return _StrategyGenerator( "/possessionmodel/possessionmodel{0}{1}".format( state.world_view.side, state.num), _update_dribble_or_pass_model, _extract_pass_or_dribble_strategy) # Check if stamina strategy model can be applied if state.team_name in STAMINA_MODEL_TEAMS and ( state.now() % 121) == (state.num + 1) * 10: print(state.num, state.team_name) return _StrategyGenerator( "/staminamodel/staminamodel{0}{1}".format(state.world_view.side, state.num), _update_stamina_model_simple, _extract_stamina_solution_simple) # Check if the goalie defence model can be applied if state.team_name in GOALIE_MODEL_TEAMS and state.player_type == "goalie": ball_possessor = state.get_ball_possessor() if ball_possessor is not None and ball_possessor.coord is not None: side = 1 if state.world_view.side == "r" else -1 steps_per_meter = goalie_strategy.STEPS_PER_METER # Convert coordinate to fit the squares from the strategy possessor_new_x = math.floor(ball_possessor.coord.pos_x * side / steps_per_meter) * steps_per_meter possessor_new_y = math.floor( ball_possessor.coord.pos_y / steps_per_meter) * steps_per_meter goalie_new_x = math.floor(state.position.get_value().pos_x * side / steps_per_meter) * steps_per_meter goalie_new_y = math.floor(state.position.get_value().pos_y / steps_per_meter) * steps_per_meter if abs(state.position.get_value().pos_x) > 52.5: goalie_new_x = 52 * side # Example: "(36.5, -19.5),(47.5, -8.5)" -> "(goalie_x, goalie_y),(player_x, player_y)" key = "({0}.0, {1}.0),({2}.0, {3}.0)".format( str(goalie_new_x), str(goalie_new_y), str(possessor_new_x), str(possessor_new_y)) if key in state.goalie_position_dict.keys(): result = state.goalie_position_dict[key] optimal_x = int(goalie_new_x * side + result[0] * side) optimal_y = int(goalie_new_y + result[1]) optimal_coord = Coordinate(optimal_x, optimal_y) state.goalie_position_strategy = optimal_coord return None
def _update_dribble_or_pass_model(state: PlayerState, model: UppaalModel): # This function edits the UPPAAL file to represent the current state of the game # Amount of ticks to forecast game state # This should be the expected time that it takes to generate the strategy FORECAST_TICKS = 6 team_mates = state.world_view.get_teammates_precarious(state.team_name, 10, min_dist=5) opponents = state.world_view.get_opponents_precarious(state.team_name, 10, min_dist=0) # Forecast position of the ball possessor if state.get_y_north_velocity_vector() is not None: possessor_forecasted = ( state.position.get_value().vector() + state.get_y_north_velocity_vector() * FORECAST_TICKS).coord() else: possessor_forecasted = state.position.get_value() # Forecast position of other players forecasted_team_positions = list( map( lambda p: p.get_value().forecasted_position( (state.now() - p.last_updated_time) + FORECAST_TICKS), team_mates)) forecasted_opponent_positions = list( map( lambda p: p.get_value().forecasted_position( (state.now() - p.last_updated_time) + FORECAST_TICKS), opponents)) if state.players_close_behind > 0: forecasted_opponent_positions.append( Coordinate( possessor_forecasted.pos_x - 1, possessor_forecasted.pos_y, )) # Convert to textual format understandable by uppaal team_pos_value = _to_3d_double_array_coordinate(forecasted_team_positions) opponent_pos_value = _to_3d_double_array_coordinate( forecasted_opponent_positions) possessor_val = _to_2d_double_array_coordinate(possessor_forecasted) model.set_global_declaration_value("TEAM_MATES", len(forecasted_team_positions)) model.set_global_declaration_value("OPPONENTS", len(forecasted_opponent_positions)) model.set_global_declaration_value("team_pos[TEAM_MATES][2]", team_pos_value) model.set_global_declaration_value("opponent_pos[OPPONENTS][2]", opponent_pos_value) model.set_global_declaration_value("possessor[2]", possessor_val) if state.is_test_player(): # Debugging all_posis = list( map(lambda p: p.get_value().coord, state.world_view.other_players)) debug_msg( str(state.now()) + " All positions: " + str(all_posis), "DRIBBLE_PASS_MODEL") debug_msg( str(state.now()) + " Forecasted team positions: " + str(team_pos_value), "DRIBBLE_PASS_MODEL") debug_msg( str(state.now()) + " Forecasted opponent positions: " + str(opponent_pos_value), "DRIBBLE_PASS_MODEL") debug_msg( str(state.now()) + " Forecasted possessor position: " + str(possessor_val), "DRIBBLE_PASS_MODEL") return forecasted_team_positions
def advance(previous_location: Coordinate, vel_vector: Vector2D): return Coordinate(previous_location.pos_x + vel_vector.x, previous_location.pos_y + vel_vector.y)
def __repr__(self) -> str: return "(team=" + str(self.team) + ", num=" + str(self.num) + ", distance=" + str( self.distance) + ", direction=" \ + str(self.direction) + ", dist_chng=" + str(self.dist_chng) + ", dir_chng=" + str(self.dir_chng) \ + ", body_dir=" + str(self.body_dir) + ", head_dir=" + str(self.head_dir) + ", is_goalie=" \ + str(self.is_goalie) + ", coord=" + str(self.coord) + ")" def forecasted_position(self, ticks): if ticks == 0 or self.velocity is None or self.velocity.magnitude( ) <= 0.1: return self.coord return (self.coord.vector() + (self.velocity * ticks)).coord() LOWER_FIELD_BOUND = Coordinate(-60, -40) UPPER_FIELD_BOUND = Coordinate(60, 40) class History: def __init__(self, max_size) -> None: self.list = deque([]) self.max_size = max_size def add_data_point(self, element, time_stamp): self.list.appendleft((element, time_stamp)) if len(self.list) > self.max_size: self.list.pop() # Pop oldest element