Skip to content

Commit

Permalink
Changed PlayerPosition to tuple[float, float, float]
Browse files Browse the repository at this point in the history
  • Loading branch information
JanEricNitschke committed Jul 28, 2023
1 parent d70a66e commit 53e6849
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 24 deletions.
2 changes: 1 addition & 1 deletion awpy/analytics/map_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ def _extract_team_metadata(
"""
coords = ("x", "y", "z")
alive_players: list[PlayerPosition] = [
[player[dim] for dim in coords]
tuple(player[dim] for dim in coords)
for player in side_data["players"] or []
if player["isAlive"]
]
Expand Down
51 changes: 34 additions & 17 deletions awpy/analytics/nav.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
from collections import defaultdict
from itertools import pairwise
from statistics import mean, median
from typing import Literal, get_args
from typing import Literal, get_args, overload

import networkx as nx
import numpy as np
Expand All @@ -56,6 +56,8 @@
DistanceType,
GameFrame,
PlaceMatrix,
PlayerPosition,
PlayerPosition2D,
TileId,
Token,
)
Expand Down Expand Up @@ -104,16 +106,30 @@ def point_in_area(map_name: str, area_id: int, point: list[float]) -> bool:
return contains_x and contains_y


@overload
def find_closest_area(
map_name: str, point: list[float], *, flat: bool = False
map_name: str, point: PlayerPosition, *, flat: Literal[False] = ...
) -> ClosestArea:
...


@overload
def find_closest_area(
map_name: str, point: PlayerPosition2D, *, flat: Literal[True] = ...
) -> ClosestArea:
...


def find_closest_area(
map_name: str, point: PlayerPosition | PlayerPosition2D, *, flat: bool = False
) -> ClosestArea:
"""Finds the closest area in the nav mesh.
Searches through all the areas by comparing point to area centerpoint.
Args:
map_name (string): Map to search
point (list): Point as a list [x,y,z]
point (tuple): Point as a tuple (x,y,z) or (x, y)
flat (Boolean): Whether z should be ignored.
Returns:
Expand All @@ -128,10 +144,10 @@ def find_closest_area(
raise ValueError(msg)
if flat:
if len(point) != 2: # noqa: PLR2004
msg = "Point must be a list [X,Y] when flat is True"
msg = "Point must be a tuple (X,Y) when flat is True"
raise ValueError(msg)
elif len(point) != 3: # noqa: PLR2004
msg = "Point must be a list [X,Y,Z]"
msg = "Point must be a list (X,Y,Z)"
raise ValueError(msg)
closest_area: ClosestArea = {
"mapName": map_name,
Expand All @@ -148,7 +164,8 @@ def find_closest_area(
dist = np.sqrt(
(point[0] - avg_x) ** 2
+ (point[1] - avg_y) ** 2
+ (point[2] - avg_z) ** 2
# If flat is false we have a 3D PlayerPosition
+ (point[2] - avg_z) ** 2 # pyright: ignore [reportGeneralTypeIssues]
)
if dist < closest_area["distance"]:
closest_area["areaId"] = area
Expand Down Expand Up @@ -184,7 +201,7 @@ def _check_arguments_area_distance(
if map_name not in NAV:
msg = "Map not found."
raise ValueError(msg)
if (area_a not in NAV[map_name].keys()) or (area_b not in NAV[map_name].keys()):
if (area_a not in NAV[map_name]) or (area_b not in NAV[map_name]):
msg = "Area ID not found."
raise ValueError(msg)
if dist_type not in get_args(DistanceType):
Expand Down Expand Up @@ -342,8 +359,8 @@ def area_distance(

def point_distance(
map_name: str,
point_a: list[float],
point_b: list[float],
point_a: PlayerPosition,
point_b: PlayerPosition,
dist_type: PointDistanceType = "graph",
) -> DistanceObject:
"""Returns the distance between two points.
Expand Down Expand Up @@ -442,7 +459,7 @@ def generate_position_token(map_name: str, frame: GameFrame) -> Token:
for player in ct_players:
if player["isAlive"]:
closest_area = find_closest_area(
map_name, [player["x"], player["y"], player["z"]]
map_name, (player["x"], player["y"], player["z"])
)
ct_token[
map_area_names.index(NAV[map_name][closest_area["areaId"]]["areaName"])
Expand All @@ -452,7 +469,7 @@ def generate_position_token(map_name: str, frame: GameFrame) -> Token:
for player in t_players:
if player["isAlive"]:
closest_area = find_closest_area(
map_name, [player["x"], player["y"], player["z"]]
map_name, (player["x"], player["y"], player["z"])
)
t_token[
map_area_names.index(NAV[map_name][closest_area["areaId"]]["areaName"])
Expand Down Expand Up @@ -784,20 +801,20 @@ def generate_centroids(
# Get the centroids and rep. point of the hull
try:
my_polygon = Polygon(hull)
my_centroid = [
my_centroid = (
*list(np.array(my_polygon.centroid.coords)[0]),
mean(z_s[area_name]),
]
rep_point = [
)
rep_point = (
*list(np.array(my_polygon.representative_point().coords)[0]),
mean(z_s[area_name]),
]
)
except ValueError: # A LinearRing must have at least 3 coordinate tuples
my_centroid = [
my_centroid = (
mean([x for (x, _) in hull]),
mean([y for (_, y) in hull]),
mean(z_s[area_name]),
]
)
rep_point = my_centroid

# Find the closest tile for these points
Expand Down
7 changes: 5 additions & 2 deletions awpy/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -708,8 +708,11 @@ class RoundStatistics(TypedDict):
# Type to represent tile id for navigation tiles.
TileId: TypeAlias = int

# Type to represent player position (list of floats [x, y, z])
PlayerPosition: TypeAlias = list[float]
# Type to represent player position (tuple of floats [x, y, z])
PlayerPosition: TypeAlias = tuple[float, float, float]

# Type to represent player position (tuple of floats [x, y, z])
PlayerPosition2D: TypeAlias = tuple[float, float]

# Return type for awpy.analytics.map_control._bfs_helper.
# Contains map control values for one team.
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,8 @@ extension-pkg-allow-list = ["cv2"]

[tool.pylint.basic]
# Good variable names which should always be accepted, separated by a comma.
good-names = ["i", "j", "k", "ex", "Run", "_", "x", "y", "z", "e"]
good-names = ["i", "j", "k", "ex", "Run", "_", "x", "y", "z", "e", "PlayerPosition2D"]
include-naming-hint = true

[tool.pylint.design]
# Maximum number of arguments for function / method.
Expand Down
8 changes: 5 additions & 3 deletions tests/test_nav.py
Original file line number Diff line number Diff line change
Expand Up @@ -517,11 +517,13 @@ def test_point_in_area(self):
def test_find_area(self):
"""Tests find_area."""
with pytest.raises(ValueError, match="Map not found."):
find_closest_area(map_name="test", point=[0, 0, 0])
with pytest.raises(ValueError, match=re.escape("Point must be a list [X,Y,Z]")):
find_closest_area(map_name="test", point=(0, 0, 0))
with pytest.raises(
ValueError, match=re.escape("Point must be a tuple (X,Y,Z)")
):
find_closest_area(map_name="de_dust2", point=[0, 0])
with pytest.raises(
ValueError, match=re.escape("Point must be a list [X,Y] when flat is True")
ValueError, match=re.escape("Point must be a tuple (X,Y) when flat is True")
):
find_closest_area(map_name="de_dust2", point=[0, 0, 0], flat=True)
example_area = NAV["de_dust2"][152]
Expand Down

0 comments on commit 53e6849

Please sign in to comment.