use std::collections::HashMap;
use crate::hit_object_info::HitObjectInfo;
use crate::enums::GameMode;
use super::{MapMetadata, TimingPointInfo, TimingGroup, EditorLayerInfo, BookmarkInfo, CustomAudioSampleInfo, SoundEffectInfo};
#[derive(Debug, Clone)]
pub struct Qua {
pub metadata: MapMetadata,
pub timing_points: Vec<TimingPointInfo>,
pub hit_objects: Vec<HitObjectInfo>,
pub editor_layers: Vec<EditorLayerInfo>,
pub bookmarks: Vec<BookmarkInfo>,
pub custom_audio_samples: Vec<CustomAudioSampleInfo>,
pub sound_effects: Vec<SoundEffectInfo>,
pub timing_groups: HashMap<String, TimingGroup>,
}
impl Qua {
pub const DEFAULT_SCROLL_GROUP_ID: &'static str = "default";
pub fn new() -> Self {
Self {
metadata: MapMetadata::default(),
timing_points: Vec::new(),
hit_objects: Vec::new(),
editor_layers: Vec::new(),
bookmarks: Vec::new(),
custom_audio_samples: Vec::new(),
sound_effects: Vec::new(),
timing_groups: HashMap::new(),
}
}
pub fn mode(&self) -> GameMode {
self.metadata.mode
}
pub fn get_key_count(&self, include_scratch: bool) -> i32 {
self.metadata.mode.to_key_count(include_scratch)
}
pub fn has_scratch_key(&self) -> bool {
self.metadata.has_scratch_key
}
pub fn length(&self) -> f32 {
if self.hit_objects.is_empty() {
return 0.0;
}
self.hit_objects
.iter()
.map(|obj| obj.end_time.max(obj.start_time) as f32)
.fold(0.0, f32::max)
}
pub fn game_mode(&self) -> GameMode {
self.metadata.mode
}
}
impl Default for Qua {
fn default() -> Self {
Self::new()
}
}
impl Qua {
pub fn from_file(path: &str) -> Result<Self, Box<dyn std::error::Error>> {
crate::qua::parser::parse_from_file(path)
}
pub fn from_str(content: &str) -> Result<Self, Box<dyn std::error::Error>> {
crate::qua::parser::parse_from_str(content)
}
}