Home

Awesome

Workflow Status Version Maintenance

subtr-actor

subtr-actor

subtr-actor is a versatile library designed to facilitate the processes of working with and extracting data from Rocket League replays. Utilizing the powerful boxcars library for parsing, subtr-actor simplifies (or 'subtracts', as hinted by its name) the underlying actor-based structure of replay files, making them more accessible and easier to manipulate.

Overview of Key Components

Collector implementations

subtr-actor also includes implementations of the Collector trait:

Examples

Getting JSON

fn get_json(filepath: std::path::PathBuf) -> anyhow::Result<String> {
    let data = std::fs::read(filepath.as_path())?;
    let replay = boxcars::ParserBuilder::new(&data)
        .must_parse_network_data()
        .on_error_check_crc()
        .parse()?;
    Ok(subtr_actor::ReplayDataCollector::new()
        .get_replay_data(&replay)
        .map_err(|e| e.variant)?
        .as_json()?)
}

Getting a ::ndarray::Array2

In the following example, we demonstrate how to use boxcars, NDArrayCollector and FrameRateDecorator to write a function that takes a replay filepath and collections of features adders and returns a ReplayMetaWithHeaders along with a ::ndarray::Array2 . The resulting ::ndarray::Array2 would be appropriate for use in a machine learning context. Note that ReplayProcessor is also used implicitly here in the Collector::process_replay

use subtr_actor::*;

fn get_ndarray_with_info_from_replay_filepath(
    filepath: std::path::PathBuf,
    feature_adders: FeatureAdders<f32>,
    player_feature_adders: PlayerFeatureAdders<f32>,
    fps: Option<f32>,
) -> anyhow::Result<(ReplayMetaWithHeaders, ::ndarray::Array2<f32>)> {
    let data = std::fs::read(filepath.as_path())?;
    let replay = boxcars::ParserBuilder::new(&data)
        .must_parse_network_data()
        .on_error_check_crc()
        .parse()?;

    let mut collector = NDArrayCollector::new(feature_adders, player_feature_adders);

    FrameRateDecorator::new_from_fps(fps.unwrap_or(10.0), &mut collector)
        .process_replay(&replay)
        .map_err(|e| e.variant)?;

    Ok(collector.get_meta_and_ndarray().map_err(|e| e.variant)?)
}

fn get_ndarray_with_default_feature_adders(
    filepath: std::path::PathBuf,
) -> anyhow::Result<(ReplayMetaWithHeaders, ::ndarray::Array2<f32>)> {
    get_ndarray_with_info_from_replay_filepath(
        filepath,
        vec![
            InterpolatedBallRigidBodyNoVelocities::arc_new(0.003),
            CurrentTime::arc_new(),
        ],
        vec![
            InterpolatedPlayerRigidBodyNoVelocities::arc_new(0.003),
            PlayerBoost::arc_new(),
            PlayerAnyJump::arc_new(),
            PlayerDemolishedBy::arc_new(),
        ],
        Some(30.0),
    )
}

Using NDArrayCollector::from_strings

In the second function we see the use of feature adders like InterpolatedPlayerRigidBodyNoVelocities. The feature adders that are included with subtr_actor can all be found in the crate::collector::ndarray module. It is also possible to access these feature adders by name with strings, which can be useful when implementing bindings for other languages since those languages may not be able to access rust structs an instantiate them easily or at all.

pub static DEFAULT_GLOBAL_FEATURE_ADDERS: [&str; 1] = ["BallRigidBody"];

pub static DEFAULT_PLAYER_FEATURE_ADDERS: [&str; 3] =
    ["PlayerRigidBody", "PlayerBoost", "PlayerAnyJump"];

fn build_ndarray_collector(
    global_feature_adders: Option<Vec<String>>,
    player_feature_adders: Option<Vec<String>>,
) -> subtr_actor::SubtrActorResult<subtr_actor::NDArrayCollector<f32>> {
    let global_feature_adders = global_feature_adders.unwrap_or_else(|| {
        DEFAULT_GLOBAL_FEATURE_ADDERS
            .iter()
            .map(|i| i.to_string())
            .collect()
    });
    let player_feature_adders = player_feature_adders.unwrap_or_else(|| {
        DEFAULT_PLAYER_FEATURE_ADDERS
            .iter()
            .map(|i| i.to_string())
            .collect()
    });
    let global_feature_adders: Vec<&str> = global_feature_adders.iter().map(|s| &s[..]).collect();
    let player_feature_adders: Vec<&str> = player_feature_adders.iter().map(|s| &s[..]).collect();
    subtr_actor::NDArrayCollector::<f32>::from_strings(
        &global_feature_adders,
        &player_feature_adders,
    )
}