aboutsummaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs157
1 files changed, 6 insertions, 151 deletions
diff --git a/src/lib.rs b/src/lib.rs
index eb371bd..64c4ad6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -32,8 +32,9 @@
//!
//! `evtclib` provides two convenience functions to obtain a [`Log`][Log]:
//!
-//! If you have a stream (that is, something that is [`Read`][Read] + [`Seek`][Seek]), you can use
-//! [`process_stream`][process_stream] to obtain a [`Log`][Log] by reading from the stream.
+//! If you have a stream (that is, something that is [`Read`][std::io::Read] +
+//! [`Seek`][std::io::Seek]), you can use [`process_stream`][process_stream] to obtain a
+//! [`Log`][Log] by reading from the stream.
//!
//! If your evtc is saved in a file, you can use [`process_file`][process_file] to obtain a [`Log`]
//! from it. This will also ensure that the buffering is set up correctly, to avoid unnecessary
@@ -89,10 +90,7 @@
use std::collections::HashMap;
use std::convert::TryFrom;
-use std::fs::File;
-use std::io::{BufReader, Read, Seek};
use std::marker::PhantomData;
-use std::path::Path;
use getset::{CopyGetters, Getters};
use num_traits::FromPrimitive;
@@ -103,6 +101,9 @@ pub mod raw;
pub mod event;
pub use event::{Event, EventKind};
+mod processing;
+pub use processing::{Compression, process, process_file, process_stream};
+
pub mod gamedata;
use gamedata::CmTrigger;
pub use gamedata::{Boss, EliteSpec, Profession};
@@ -909,152 +910,6 @@ impl Log {
}
}
-/// Main function to turn a low-level [`Evtc`][raw::Evtc] to a high-level [`Log`][Log].
-///
-/// This function takes an [`Evtc`][raw::Evtc] and does the required type conversions and
-/// pre-processing to get a high-level [`Log`][Log]. This pre-processing includes
-///
-/// * Setting the correct aware times for the agents
-/// * Setting the master agents for each agent
-/// * Converting all events
-///
-/// Note that the structures are quite different, so this function does not consume the given
-/// [`Evtc`][raw::Evtc].
-pub fn process(data: &raw::Evtc) -> Result<Log, EvtcError> {
- // Prepare "augmented" agents
- let mut agents = setup_agents(data)?;
- // Do the first aware/last aware field
- set_agent_awares(data, &mut agents)?;
-
- // Set the master addr field
- set_agent_masters(data, &mut agents)?;
-
- let events = data
- .events
- .iter()
- .filter_map(|e| Event::try_from(e).ok())
- .collect();
-
- Ok(Log {
- agents,
- events,
- boss_id: data.header.combat_id,
- })
-}
-
-/// Indicates the given compression method for the file.
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub enum Compression {
- /// No compression was used.
- None,
- /// The file is wrapped in a zip archive.
- Zip,
-}
-
-/// Convenience function to process a given stream directly.
-///
-/// This is a shorthand for using [`raw::parse_file`][raw::parse_file] followed by
-/// [`process`][process].
-///
-/// The [`Seek`][Seek] bound is needed for zip compressed archives. If you have a reader that does
-/// not support seeking, you can use [`raw::parse_file`][raw::parse_file] directly instead.
-///
-/// ```no_run
-/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
-/// use std::io::Cursor;
-/// use evtclib::Compression;
-/// let data = Cursor::new(vec![]);
-/// let log = evtclib::process_stream(data, Compression::None)?;
-/// # Ok(()) }
-/// ```
-pub fn process_stream<R: Read + Seek>(
- input: R,
- compression: Compression,
-) -> Result<Log, EvtcError> {
- let evtc = match compression {
- Compression::None => raw::parse_file(input)?,
- Compression::Zip => raw::parse_zip(input)?,
- };
- process(&evtc)
-}
-
-/// Convenience function to process a given file directly.
-///
-/// This is a shorthand for opening the file and then using [`process_stream`][process_stream] with
-/// it. This function automatically wraps the raw file in a buffered reader, to ensure the bext
-/// reading performance.
-///
-/// If you need more fine-grained control, consider using [`process_stream`][process_stream] or
-/// [`raw::parse_file`][raw::parse_file] followed by [`process`][process] instead.
-///
-/// ```no_run
-/// # use evtclib::Compression;
-/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
-/// let log = evtclib::process_file("logfile.zevtc", Compression::Zip)?;
-/// # Ok(()) }
-/// ```
-pub fn process_file<P: AsRef<Path>>(path: P, compression: Compression) -> Result<Log, EvtcError> {
- let file = File::open(path).map_err(Into::<raw::ParseError>::into)?;
- let buffered = BufReader::new(file);
- process_stream(buffered, compression)
-}
-
-fn setup_agents(data: &raw::Evtc) -> Result<Vec<Agent>, EvtcError> {
- let mut agents = Vec::with_capacity(data.agents.len());
-
- for raw_agent in &data.agents {
- agents.push(Agent::try_from(raw_agent)?);
- }
- Ok(agents)
-}
-
-fn get_agent_by_addr(agents: &mut [Agent], addr: u64) -> Option<&mut Agent> {
- for agent in agents {
- if agent.addr == addr {
- return Some(agent);
- }
- }
- None
-}
-
-fn set_agent_awares(data: &raw::Evtc, agents: &mut [Agent]) -> Result<(), EvtcError> {
- for event in &data.events {
- if event.is_statechange == raw::CbtStateChange::None {
- if let Some(current_agent) = get_agent_by_addr(agents, event.src_agent) {
- current_agent.instance_id = event.src_instid;
- if current_agent.first_aware == 0 {
- current_agent.first_aware = event.time;
- }
- current_agent.last_aware = event.time;
- }
- }
- }
- Ok(())
-}
-
-fn set_agent_masters(data: &raw::Evtc, agents: &mut [Agent]) -> Result<(), EvtcError> {
- for event in &data.events {
- if event.src_master_instid != 0 {
- let mut master_addr = None;
- for agent in &*agents {
- if agent.instance_id == event.src_master_instid
- && agent.first_aware < event.time
- && event.time < agent.last_aware
- {
- master_addr = Some(agent.addr);
- break;
- }
- }
- if let Some(master_addr) = master_addr {
- if let Some(current_slave) = get_agent_by_addr(agents, event.src_agent) {
- current_slave.master_agent = Some(master_addr);
- }
- }
- }
- }
- Ok(())
-}
-
fn time_between_buffs(events: &[Event], wanted_buff_id: u32) -> u64 {
let mut time_maps: HashMap<u64, Vec<u64>> = HashMap::new();
for event in events {