diff options
Diffstat (limited to 'src/lib.rs')
-rw-r--r-- | src/lib.rs | 87 |
1 files changed, 80 insertions, 7 deletions
@@ -1,21 +1,58 @@ //! `evtclib` is a crate aiming to provide utility functions to parse and work //! with `.evtc` reports generated by arcdps. //! +//! # About evtc Files +//! +//! evtc files are files generated by the (inofficial) arcdps addon to Guild Wars 2. They contain +//! metadata about a fight in the game, such as the boss's name (if it was a raid or fractal boss), +//! the participants, and a stripped-down log of the complete fight. +//! +//! There are other programs (such as +//! [GW2-Elite-Insights-Parser](https://github.com/baaron4/GW2-Elite-Insights-Parser/)) and +//! websites (such as [dps.report](https://dps.report)) which allow you to generate reports from +//! evtc files. +//! +//! A common way to store and distribute evtc files is to zip them to either a `.evtc.zip` (old +//! way) or a `.zevtc` (new way). evtclib uses [`zip`](https://crates.io/crates/zip) to read them, +//! prodiving the [`raw::parse_zip`][raw::parse_zip] convenience function. +//! +//! # Crate Structure +//! +//! The crate consists of two main parts: The [`raw`][raw] parser, which is used to read structured +//! data from binary input streams, and the higher-level abstrations provided in the root and +//! [`event`][event] submodules. +//! +//! Additionally, there are some defintions (such as IDs for various game items) in the +//! [`gamedata`][gamedata] module. +//! +//! The main structs that you should be dealing with are the [`Log`][Log] and its components, such +//! as [`Event`][Event] and [`Agent`][Agent]. +//! //! # Workflow //! +//! Currently, there is no convenience function to turn a file into a [`Log`][Log] directly, so you +//! have to use the [`raw`][raw] submodule to obtain a low-level [`Evtc`][raw::Evtc], and then +//! convert it to the high-level [`Log`][Log]. +//! //! ```no_run -//! # use std::fs::File; -//! // Open some file for processing -//! let mut file = File::open("my_log.evtc").unwrap(); +//! # fn main() -> Result<(), Box<dyn std::error::Error>> { +//! use std::fs::File; +//! // Open a file for processing +//! let mut file = File::open("my_log.evtc")?; //! // Parse the raw content of the file -//! let raw_log = evtclib::raw::parse_file(&mut file).unwrap(); +//! let raw_log = evtclib::raw::parse_file(&mut file)?; //! // Process the file to do the nitty-gritty low-level stuff done -//! let log = evtclib::process(&raw_log).unwrap(); +//! let log = evtclib::process(&raw_log)?; //! // Do work on the log +//! for player in log.players() { +//! println!("Player {} participated!", player.account_name()); +//! } +//! # Ok(()) +//! # } //! ``` //! -//! (Look at the note on "Buffering" in the [parser -//! module](raw/parser/index.html#buffering)) +//! Make sure to take a look at the note on "Buffering" in the [parser +//! module](raw/parser/index.html#buffering) in order to increase the speed of your application. use std::convert::TryFrom; use std::marker::PhantomData; @@ -32,14 +69,23 @@ pub use event::{Event, EventKind}; pub mod gamedata; pub use gamedata::{Boss, EliteSpec, Profession}; +/// Any error that can occur during the processing of evtc files. #[derive(Error, Debug)] pub enum EvtcError { + /// Generic error for invalid data in the evtc file. #[error("invalid data has been provided")] InvalidData, + /// The profession id is not known. + /// + /// The field contains the unknown profession id. #[error("invalid profession id: {0}")] InvalidProfession(u32), + /// The elite specialization id is not known. + /// + /// The field contains the unknown elite specialization id. #[error("invalid elite specialization id: {0}")] InvalidEliteSpec(u32), + /// The file contains invalid utf-8. #[error("utf8 decoding error: {0}")] Utf8Error(#[from] std::str::Utf8Error), } @@ -95,12 +141,17 @@ impl Player { /// [Entangle](https://wiki.guildwars2.com/wiki/Entangle) or the other objects in the arena. #[derive(Debug, Clone, Hash, PartialEq, Eq, CopyGetters)] pub struct Gadget { + /// The id of the gadget. + /// + /// Note that gadgets do not have true ids and the id is generated "through a combination of + /// gadget parameters". #[get_copy = "pub"] id: u16, name: String, } impl Gadget { + /// The name of the gadget. pub fn name(&self) -> &str { &self.name } @@ -112,12 +163,14 @@ impl Gadget { /// friendly characters like Mesmer's clones and illusions, Necromancer minions, and so on. #[derive(Debug, Clone, Hash, PartialEq, Eq, CopyGetters)] pub struct Character { + /// The id of the character. #[get_copy = "pub"] id: u16, name: String, } impl Character { + /// The name of the character. pub fn name(&self) -> &str { &self.name } @@ -144,8 +197,17 @@ impl Character { /// ``` #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub enum AgentKind { + /// The agent is a player. + /// + /// The player-specific data is in the included [`Player`][Player] struct. Player(Player), + /// The agent is a gadget. + /// + /// The gadget-specific data is in the included [`Gadget`][Gadget] struct. Gadget(Gadget), + /// The agent is a character. + /// + /// The character-specific data is in the included [`Character`][Character] struct. Character(Character), } @@ -753,6 +815,17 @@ 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)?; |