mirror of
https://codeberg.org/icewind/tf-log-parser.git
synced 2026-06-03 18:24:09 +02:00
fix damage
This commit is contained in:
parent
ef38aadb68
commit
cdaa164575
6 changed files with 97 additions and 7 deletions
|
|
@ -1,3 +1,5 @@
|
||||||
|
//! Example for creating a handler that combines the output of multiple handlers
|
||||||
|
|
||||||
use main_error::MainError;
|
use main_error::MainError;
|
||||||
use std::env::args;
|
use std::env::args;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
//! Example of creating a custom handler to extract data from the log
|
||||||
|
|
||||||
|
use main_error::MainError;
|
||||||
|
use std::env::args;
|
||||||
|
use std::fs;
|
||||||
|
use tf_log_parser::event::DamageEvent;
|
||||||
|
use tf_log_parser::{
|
||||||
|
parse_with_handler, EventHandler, GameEvent, RawEventType, SubjectData, SubjectId, SubjectMap,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HighestDamage {
|
||||||
|
user: String,
|
||||||
|
damage: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct HighestDamageHandler {
|
||||||
|
current: Option<(SubjectId, u32)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventHandler for HighestDamageHandler {
|
||||||
|
type Output = Option<HighestDamage>;
|
||||||
|
|
||||||
|
fn does_handle(&self, ty: RawEventType) -> bool {
|
||||||
|
matches!(ty, RawEventType::Damage)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle(&mut self, _time: u32, subject: SubjectId, event: &GameEvent) {
|
||||||
|
if let GameEvent::Damage(DamageEvent {
|
||||||
|
damage: Some(damage),
|
||||||
|
..
|
||||||
|
}) = event
|
||||||
|
{
|
||||||
|
let damage = damage.get();
|
||||||
|
// note that we leave the name empty for now to prevent needles cloning
|
||||||
|
match &mut self.current {
|
||||||
|
Some((_, current_damage)) if damage > *current_damage => {
|
||||||
|
self.current = Some((subject, damage))
|
||||||
|
}
|
||||||
|
None => self.current = Some((subject, damage)),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finish(self, subjects: &SubjectMap) -> Self::Output {
|
||||||
|
self.current.map(|(subject, damage)| {
|
||||||
|
let user = match &subjects[subject] {
|
||||||
|
SubjectData::Player { name, .. } => name.clone(),
|
||||||
|
_ => {
|
||||||
|
panic!("A non player did the most damage?")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
HighestDamage { user, damage }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<(), MainError> {
|
||||||
|
let path = args().skip(1).next().expect("No path provided");
|
||||||
|
let content = fs::read_to_string(path)?;
|
||||||
|
|
||||||
|
let HighestDamage { user, damage } =
|
||||||
|
parse_with_handler::<HighestDamageHandler>(&content)?.expect("nobody did any damage?");
|
||||||
|
|
||||||
|
println!("highest damage was {} done by {}", user, damage);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
@ -136,6 +136,12 @@ impl TryFrom<&RawSubject<'_>> for SubjectData {
|
||||||
#[derive(Debug, Hash, Eq, PartialEq)]
|
#[derive(Debug, Hash, Eq, PartialEq)]
|
||||||
pub struct SteamId3(pub SteamID);
|
pub struct SteamId3(pub SteamID);
|
||||||
|
|
||||||
|
impl From<SteamID> for SteamId3 {
|
||||||
|
fn from(id: SteamID) -> Self {
|
||||||
|
SteamId3(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Serialize for SteamId3 {
|
impl Serialize for SteamId3 {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
|
|
|
||||||
|
|
@ -43,11 +43,13 @@ impl<'a, T> GameEventErrTrait<T> for IResult<&str, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum GameEvent<'a> {
|
pub enum GameEvent<'a> {
|
||||||
ShotFired(ShotFiredEvent<'a>),
|
ShotFired(ShotFiredEvent<'a>),
|
||||||
ShotHit(ShotHitEvent<'a>),
|
ShotHit(ShotHitEvent<'a>),
|
||||||
Damage(DamageEvent<'a>),
|
Damage(DamageEvent<'a>),
|
||||||
Kill(KillEvent<'a>),
|
Kill(KillEvent<'a>),
|
||||||
|
KillAssist(KillAssistEvent<'a>),
|
||||||
Say(&'a str),
|
Say(&'a str),
|
||||||
SayTeam(&'a str),
|
SayTeam(&'a str),
|
||||||
Healed(HealedEvent<'a>),
|
Healed(HealedEvent<'a>),
|
||||||
|
|
@ -65,6 +67,18 @@ impl<'a> GameEvent<'a> {
|
||||||
RawEventType::ShotFired => {
|
RawEventType::ShotFired => {
|
||||||
GameEvent::ShotFired(shot_fired_event_parser(raw.params).with_type(raw.ty)?)
|
GameEvent::ShotFired(shot_fired_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
}
|
}
|
||||||
|
RawEventType::ShotHit => {
|
||||||
|
GameEvent::ShotHit(shot_hit_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
|
}
|
||||||
|
RawEventType::Damage => {
|
||||||
|
GameEvent::Damage(damage_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
|
}
|
||||||
|
RawEventType::Killed => {
|
||||||
|
GameEvent::Kill(kill_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
|
}
|
||||||
|
RawEventType::KillAssist => {
|
||||||
|
GameEvent::KillAssist(kill_assist_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
|
}
|
||||||
RawEventType::SayTeam => GameEvent::SayTeam(raw.params.trim_matches('"')),
|
RawEventType::SayTeam => GameEvent::SayTeam(raw.params.trim_matches('"')),
|
||||||
RawEventType::Say => GameEvent::Say(raw.params.trim_matches('"')),
|
RawEventType::Say => GameEvent::Say(raw.params.trim_matches('"')),
|
||||||
RawEventType::Healed => {
|
RawEventType::Healed => {
|
||||||
|
|
@ -122,7 +136,7 @@ fn param_pair_parse(input: &str) -> IResult<&str, (&str, &str)> {
|
||||||
let (input, _) = tag(r#"""#)(input)?;
|
let (input, _) = tag(r#"""#)(input)?;
|
||||||
|
|
||||||
if open_tag.is_some() {
|
if open_tag.is_some() {
|
||||||
let (_input, _) = tag("(")(input)?;
|
let (_input, _) = tag(")")(input)?;
|
||||||
}
|
}
|
||||||
Ok((input, (key, value)))
|
Ok((input, (key, value)))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::event::{param_parse, param_parse_with, position, quoted, u_int, ParamIter};
|
use crate::event::{param_parse, param_parse_with, position, u_int, ParamIter};
|
||||||
use crate::raw_event::{subject_parser, RawSubject};
|
use crate::raw_event::{subject_parser, RawSubject};
|
||||||
use nom::combinator::opt;
|
use nom::combinator::opt;
|
||||||
use nom::IResult;
|
use nom::IResult;
|
||||||
|
|
@ -19,9 +19,9 @@ pub struct ShotHitEvent<'a> {
|
||||||
pub weapon: Option<&'a str>,
|
pub weapon: Option<&'a str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shot_hit_event_parser(input: &str) -> IResult<&str, ShotFiredEvent> {
|
pub fn shot_hit_event_parser(input: &str) -> IResult<&str, ShotHitEvent> {
|
||||||
let (input, weapon) = opt(param_parse("weapon"))(input)?;
|
let (input, weapon) = opt(param_parse("weapon"))(input)?;
|
||||||
Ok((input, ShotFiredEvent { weapon }))
|
Ok((input, ShotHitEvent { weapon }))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -42,8 +42,8 @@ pub fn damage_event_parser(input: &str) -> IResult<&str, DamageEvent> {
|
||||||
};
|
};
|
||||||
for (key, value) in ParamIter::new(input) {
|
for (key, value) in ParamIter::new(input) {
|
||||||
match key {
|
match key {
|
||||||
"damage" => event.damage = NonZeroU32::new(quoted(u_int)(value)?.1),
|
"damage" => event.damage = NonZeroU32::new(u_int(value)?.1),
|
||||||
"realdamage" => event.real_damage = NonZeroU32::new(quoted(u_int)(value)?.1),
|
"realdamage" => event.real_damage = NonZeroU32::new(u_int(value)?.1),
|
||||||
"weapon" => event.weapon = Some(value.trim_matches('"')),
|
"weapon" => event.weapon = Some(value.trim_matches('"')),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ use std::ops::Index;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
mod event;
|
pub mod event;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod module;
|
pub mod module;
|
||||||
mod raw_event;
|
mod raw_event;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue