quaver-rs 0.1.0

A Rust library for parsing and analyzing Quaver rhythm game maps
Documentation
use crate::rulesets::structs::{
    finger_action::FingerAction,
    finger_state::FingerState,
    hand::Hand,
    strain_solver_hit_object::StrainSolverHitObject,
};

/// Data point that is represented by a group of hitobjects.
/// Used for calculating strain value at a given time for a given hand.
#[derive(Debug, Clone)]
pub struct StrainSolverData {
    /// Chorded Hit Objects at the current start time
    pub hit_objects: Vec<StrainSolverHitObject>,
    
    /// Is determined by the following StrainSolverData object on the current hand.
    /// It should be defined externally from this class.
    pub next_strain_solver_data_on_current_hand: Option<Box<StrainSolverData>>,
    
    /// When the current action/pattern starts
    pub start_time: f32,
    
    /// When the longest LN in self.hit_objects ends
    pub end_time: f32,
    
    /// Base strain value calculated by its action
    pub action_strain_coefficient: f32,
    
    /// Strain multiplier determined by pattern difficulty
    pub pattern_strain_multiplier: f32,
    
    /// Multiplier that gets added to any pattern that could be manipulated via rolls.
    pub roll_manipulation_strain_multiplier: f32,
    
    /// Multiplier that gets applied to any pattern that could be manipulated via long jacks.
    pub jack_manipulation_strain_multiplier: f32,
    
    /// Total strain value for this data point
    pub total_strain_value: f32,
    
    /// Hand that this data point represents
    pub hand: Hand,
    
    /// Finger Action that this data point represents
    pub finger_action: FingerAction,
    
    /// Duration of FingerAction in ms
    pub finger_action_duration_ms: f32,
    
    /// Pattern that this data point represents.
    /// TODO: replace with enum
    pub pattern: String,
    
    /// Is an index value of this hand's finger state. (Determined by every finger's state)
    pub finger_state: FingerState,
}

impl StrainSolverData {
    /// Data used to represent a point in time and other variables that influence difficulty.
    pub fn new(hit_object: StrainSolverHitObject, rate: f32) -> Self {
        let start_time = hit_object.hit_object.start_time as f32 / rate;
        let end_time = hit_object.hit_object.end_time as f32 / rate;
        
        Self {
            hit_objects: vec![hit_object],
            next_strain_solver_data_on_current_hand: None,
            start_time,
            end_time,
            action_strain_coefficient: 1.0,
            pattern_strain_multiplier: 1.0,
            roll_manipulation_strain_multiplier: 1.0,
            jack_manipulation_strain_multiplier: 1.0,
            total_strain_value: 0.0,
            hand: Hand::Left, // Default value
            finger_action: FingerAction::None,
            finger_action_duration_ms: 0.0,
            pattern: String::new(),
            finger_state: FingerState::NONE,
        }
    }
    
    /// Is determined by if this data point has more than one hit object (per hand)
    pub fn hand_chord(&self) -> bool {
        self.hit_objects.len() > 1
    }
    
    /// Calculate the strain value of this current point.
    pub fn calculate_strain_value(&mut self) {
        // Calculate the strain value of each individual object and add to total
        for hit_object in &mut self.hit_objects {
            hit_object.strain_value = self.action_strain_coefficient 
                * self.pattern_strain_multiplier 
                * self.roll_manipulation_strain_multiplier 
                * self.jack_manipulation_strain_multiplier 
                * hit_object.ln_strain_multiplier;
            self.total_strain_value += hit_object.strain_value;
        }
        
        // Average the strain value between the objects
        if !self.hit_objects.is_empty() {
            self.total_strain_value /= self.hit_objects.len() as f32;
        }
    }
    
    pub fn solve_finger_state(&mut self) {
        for hit_object in &self.hit_objects {
            self.finger_state |= hit_object.finger_state;
        }
    }
}