Skip to content

Commit

Permalink
v2.0.0b2 (#344)
Browse files Browse the repository at this point in the history
* fix clock error

* apologies

* start of usd stuff

* basic vis test

* fix usd open

* a vis module that works

* add the lock file

* everything float

* oops
  • Loading branch information
pnxenopoulos authored Jul 15, 2024
1 parent 3aedb12 commit 03f4250
Show file tree
Hide file tree
Showing 17 changed files with 906 additions and 437 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ["3.9", "3.10", "3.11", "3.12"]
python-version: ["3.9", "3.10", "3.11"] # Add 3.12 when pxr updates
timeout-minutes: 15
steps:
- name: Checkout awpy library
Expand Down Expand Up @@ -48,7 +48,7 @@ jobs:
- name: Install Poetry
uses: abatilo/actions-poetry@v2

- name: Setup a local virtual environment for poetry
shell: bash
run: |
Expand Down
68 changes: 60 additions & 8 deletions awpy/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,79 @@
from typing import Literal, Optional

import click
import requests
from loguru import logger
from tqdm import tqdm

from awpy import Demo
from awpy.data import AWPY_DATA_DIR
from awpy.data.usd_data import USD_LINKS


@click.group()
def awpy() -> None:
"""A simple CLI interface for Awpy."""


@awpy.command(help="Get Counter-Strike 2 resources like map files.")
@click.argument("resource_type", type=click.Choice(["map", "usd"]))
@click.argument("resource_name", type=str)
def get(resource_type: Literal["usd"], resource_name: str) -> None:
@awpy.command(
help="Get Counter-Strike 2 resources like map images, nav meshes or usd files."
)
@click.argument("resource_type", type=click.Choice(["map", "nav", "usd"]))
@click.argument("resource_name", required=False)
def get(
resource_type: Literal["map", "nav", "usd"], resource_name: Optional[str]
) -> None:
"""Get a resource given its type and name."""
if not AWPY_DATA_DIR.exists():
AWPY_DATA_DIR.mkdir(parents=True, exist_ok=True)
awpy_data_dir_creation_msg = f"Created awpy data directory at {AWPY_DATA_DIR}"
logger.debug(awpy_data_dir_creation_msg)

if resource_type == "usd":
if resource_name == "all":
logger.info("Getting all USDs...")
if resource_name:
url = USD_LINKS.get(resource_name)
if not url:
logger.error(f"No USD link found for {resource_name}")
return
usd_data_dir = AWPY_DATA_DIR / "usd"
usd_data_dir.mkdir(parents=True, exist_ok=True)
usd_file_path = usd_data_dir / f"{resource_name}.usdc"
logger.info(f"Getting USD for {resource_name}...")
response = requests.get(url, stream=True, timeout=300)
total_size = int(response.headers.get("content-length", 0))
block_size = 1024
with (
tqdm(total=total_size, unit="B", unit_scale=True) as progress_bar,
open(usd_file_path, "wb") as file,
):
for data in response.iter_content(block_size):
progress_bar.update(len(data))
file.write(data)
logger.info(f"Saved USD for {resource_name} to {usd_file_path}")
else:
getting_specific_usd_msg = f"Getting USD for {resource_name}..."
logger.info(getting_specific_usd_msg)
logger.info("Getting all USDs...")
for map_name, url in USD_LINKS.items():
usd_data_dir = AWPY_DATA_DIR / "usd"
usd_data_dir.mkdir(parents=True, exist_ok=True)
usd_file_path = usd_data_dir / f"{map_name}.usdc"
logger.info(f"Getting USD for {map_name}...")
response = requests.get(url, stream=True, timeout=300)
total_size = int(response.headers.get("content-length", 0))
block_size = 1024
with (
tqdm(total=total_size, unit="B", unit_scale=True) as progress_bar,
open(usd_file_path, "wb") as file,
):
for data in response.iter_content(block_size):
progress_bar.update(len(data))
file.write(data)
logger.info(f"Saved USD for {map_name} to {usd_file_path}")
elif resource_type == "map":
map_not_impl_msg = "Map files are not yet implemented."
raise NotImplementedError(map_not_impl_msg)
elif resource_type == "nav":
nav_not_impl_msg = "Nav files are not yet implemented."
raise NotImplementedError(nav_not_impl_msg)


@awpy.command(help="Parse a Counter-Strike 2 demo file.")
Expand Down
4 changes: 4 additions & 0 deletions awpy/data/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
"""Module to hold Counter-Strike 2 data."""

from pathlib import Path

AWPY_DATA_DIR = Path.home() / ".awpy"
8 changes: 8 additions & 0 deletions awpy/data/usd_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""USD files for maps.
To make:
- Get Blender with SourceIO
"""

USD_LINKS = {"de_dust2": "https://figshare.com/ndownloader/files/47199475"}
17 changes: 13 additions & 4 deletions awpy/parsers/clock.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,20 +50,29 @@ def parse_clock(
return f"{int(minutes):02}:{int(seconds):02}"


def _find_clock_time(row: pd.Series) -> str:
def _find_clock_time(row: pd.Series) -> Union[str, pd._libs.missing.NAType]:
"""Find the clock time for a row.
Args:
row: A row from a dataframe with ticks_since_* columns.
Returns:
str: The clock time in MM:SS format or NA if no valid time is found.
"""
times = {
"start": row["ticks_since_round_start"],
"freeze": row["ticks_since_freeze_time_end"],
"bomb": row["ticks_since_bomb_plant"],
}
# Filter out NA values and find the key with the minimum value
min_key = min((k for k in times if pd.notna(times[k])), key=lambda k: times[k])
return parse_clock(times[min_key], min_key)
# Filter out NA values
valid_times = {k: v for k, v in times.items() if pd.notna(v)}

if not valid_times:
return pd.NA

# Find the key with the minimum value among valid times
min_key = min(valid_times, key=valid_times.get)
return parse_clock(valid_times[min_key], min_key)


def parse_times(
Expand Down
2 changes: 1 addition & 1 deletion awpy/vis/__init__.py → awpy/plot/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Awpy visualization module."""
"""Awpy plotting module."""

SIDE_COLORS = {"ct": "#5d79ae", "t": "#de9b35"}
SUPPORTED_MAPS = ["de_dust2"]
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions awpy/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def apply_round_num(

# Add round
df["round"] = intervals.get_indexer(df[tick_col]) + 1
df["round"] = df["round"].replace(0, pd.NA)

return df

Expand Down
Loading

0 comments on commit 03f4250

Please sign in to comment.