Skip to content

Commit

Permalink
Initial Map Control Calculations/Visualizations and Testing (#235)
Browse files Browse the repository at this point in the history
* Initial Map Control Calculations/Visualizations and Testing

* Addressed Jan Eric's PR comments, Added more documentation in notebook, Re-named some functions for code clarity purposes

* Fixed pre-commit errors, added opencv-python to requirements.txt, fixed notebook documentation

* pre-commit and pyright fixes

* Cherry-picked commits from Jan Eric's map_control branch which was a working, merged version of my branch. Added extra fix for black.

Addressed Jan-Eric's PR comments as well; highlights below:
* Added numerous dataclasses for map control purposes in types.py
* Removed uneccessary error checking
* Updated docstring documentation and formatting
* Updated test_map_control.py

* Addressed most of Jan Eric comments in plot.py

* Addressing Jan Erics comments on map_control.py, plot.py, and types.py

* Addressing rest of Jan Eric non-test PR comments

* Addressing Jan Erics non-testing comments on PR

* Addressed map cnotrol testing coverage issues. Added test in test_nav for calculate_tile_area. Fixed other code errors I came across as well

* Addressing unresolved comments not related to visualization testing

* Changes to types.py after rebasing main branch updates

* Changing function names to match awpy naming convention

* Removing deprecated functions, cleaning up notebook, adding testing for new plotting functions

* Addressing issues with new test_vis map control function

* Slight change to ommit returned axes object from plot_frame_map_control in plot_round_map_control

* Adding coverage in tests, removing opencv from requirements

* Addressing test failures in test_plot_round_map_control and test_calc_frame_map_control_values

* BFS now terminates based on cumalative area of tiles instead of number of steps from source tile. Updataes were made to the tests as well to reflect changes in codebase
  • Loading branch information
adisujithkumar authored Jul 28, 2023
1 parent db9d275 commit d70a66e
Show file tree
Hide file tree
Showing 10 changed files with 1,475 additions and 23 deletions.
424 changes: 424 additions & 0 deletions awpy/analytics/map_control.py

Large diffs are not rendered by default.

58 changes: 58 additions & 0 deletions awpy/analytics/nav.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
DistanceType,
GameFrame,
PlaceMatrix,
TileId,
Token,
)

Expand Down Expand Up @@ -1600,3 +1601,60 @@ def token_distance(
distance_type,
reference_point,
)


def calculate_tile_area(
map_name: str,
tile_id: TileId,
) -> float:
"""Calculates area of a given tile in a given map.
Args:
map_name (string): Map for tile
tile_id (TileId): Id for tile
Returns:
A float representing the area of the tile
Raises:
ValueError: If map_name is not in awpy.data.NAV
If area_id is not in awpy.data.NAV[map_name]
"""
if map_name not in NAV:
msg = "Map not found."
raise ValueError(msg)
if tile_id not in NAV[map_name]:
msg = "Tile ID not found."
raise ValueError(msg)

tile_info = NAV[map_name][tile_id]

tile_width = tile_info["northWestX"] - tile_info["southEastX"]
tile_height = tile_info["northWestY"] - tile_info["southEastY"]

return tile_width * tile_height


def calculate_map_area(
map_name: str,
) -> float:
"""Calculates total area of all nav tiles in a given map.
Args:
map_name (string): Map for area calculations
Returns:
A float representing the area of the map
Raises:
ValueError: If map_name is not in awpy.data.NAV
"""
if map_name not in NAV:
msg = "Map not found."
raise ValueError(msg)

total_area = 0
for tile in NAV[map_name]:
total_area += calculate_tile_area(map_name, tile)

return total_area
81 changes: 80 additions & 1 deletion awpy/types.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""This module contains the type definitions for the parsed json structure."""

from dataclasses import dataclass
from typing import Literal, NotRequired, TypeGuard, final, overload
from typing import Literal, NotRequired, TypeAlias, TypeGuard, final, overload

from typing_extensions import TypedDict

Expand Down Expand Up @@ -702,6 +702,85 @@ class RoundStatistics(TypedDict):
players_killed: dict[Literal["CT", "T"], set[str]]


# Type to represent different options for map control minimap plot
MapControlPlotType = Literal["default", "players"]

# 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]

# Return type for awpy.analytics.map_control._bfs_helper.
# Contains map control values for one team.
# Maps TileId to list of tile map control values.
TeamMapControlValues: TypeAlias = dict[TileId, list[float]]

# Return type for awpy.analytics.map_control.graph_to_tile_neighbors
# Maps TileId to set of neighboring tiles.
TileNeighbors: TypeAlias = dict[TileId, set[int]]


@dataclass
class TileDistanceObject:
"""Dataclass with data for map control tile distance calculations.
Holds information for distance to source tile and tile_id
distance is associated with.
"""

tile_id: TileId
distance: float


@dataclass
class BFSTileData:
"""Dataclass containing data for tiles during bfs algorithm.
Holds information for tile_id for tile, current map control
value, and steps remaining for bfs algorithm
"""

tile_id: TileId
map_control_value: float
steps_left: int


@dataclass
class TeamMetadata:
"""Dataclass containing metadata for one team.
Holds information for aliver player locations. Can include
more metadata (utility, bomb location, etc.) in the future
"""

alive_player_locations: list[PlayerPosition]


@dataclass
class FrameTeamMetadata:
"""Dataclass with metadata on both teams in frame.
Return type for awpy.analytics.map_control.extract_teams_metadata.
Holds parsed metadata object (TeamMetadata) for both teams
"""

t_metadata: TeamMetadata
ct_metadata: TeamMetadata


@dataclass
class FrameMapControlValues:
"""Dataclass with map control values for both teams in frame.
Return type for awpy.analytics.map_control.calc_map_control.
Holds TeamMapControlValues for each team for a certain frame.
"""

t_values: TeamMapControlValues
ct_values: TeamMapControlValues


@overload
def other_side(side: Literal["CT"]) -> Literal["T"]:
...
Expand Down
1 change: 1 addition & 0 deletions awpy/visualization/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
"""Provides data visualization capabilities for CSGO data."""
SIDE_COLORS = {"ct": "#5d79ae", "t": "#de9b35"}
AWPY_TMP_FOLDER = "csgo_tmp"
Loading

0 comments on commit d70a66e

Please sign in to comment.