mirror of
https://codeberg.org/icewind/tf-log-parser.git
synced 2026-06-03 18:24:09 +02:00
more event parsers
This commit is contained in:
parent
b95d68a845
commit
58100e5f7b
8 changed files with 418 additions and 17 deletions
|
|
@ -1,20 +1,34 @@
|
||||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||||
use std::fs::read_to_string;
|
use std::fs::read_to_string;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tf_log_parser::{parse, RawEvent};
|
use tf_log_parser::{parse, GameEvent, RawEvent};
|
||||||
|
|
||||||
pub fn parse_benchmark(c: &mut Criterion) {
|
pub fn parse_benchmark(c: &mut Criterion) {
|
||||||
let input = read_to_string("test_data/log_2892242.log").unwrap();
|
let input = read_to_string("test_data/log_2892242.log").unwrap();
|
||||||
c.bench_function("parse log 2892242", |b| b.iter(|| parse(black_box(&input))));
|
c.bench_function("parse log 2892242", |b| b.iter(|| parse(black_box(&input))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_event(c: &mut Criterion) {
|
||||||
|
let input = read_to_string("test_data/log_2892242.log").unwrap();
|
||||||
|
let raw: Vec<_> = input
|
||||||
|
.split("L ")
|
||||||
|
.filter(|line| !line.is_empty())
|
||||||
|
.flat_map(RawEvent::parse)
|
||||||
|
.collect();
|
||||||
|
c.bench_function("parse event 2892242", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
black_box(&raw).iter().flat_map(GameEvent::parse).count();
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
pub fn parse_raw(c: &mut Criterion) {
|
pub fn parse_raw(c: &mut Criterion) {
|
||||||
let input = read_to_string("test_data/log_2892242.log").unwrap();
|
let input = read_to_string("test_data/log_2892242.log").unwrap();
|
||||||
c.bench_function("parse raw 2892242", |b| {
|
c.bench_function("parse raw 2892242", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
black_box(&input)
|
black_box(&input)
|
||||||
.lines()
|
.split("L ")
|
||||||
.filter(|line| line.starts_with("L "))
|
.filter(|line| !line.is_empty())
|
||||||
.flat_map(RawEvent::parse)
|
.flat_map(RawEvent::parse)
|
||||||
.count();
|
.count();
|
||||||
})
|
})
|
||||||
|
|
@ -24,5 +38,5 @@ pub fn parse_raw(c: &mut Criterion) {
|
||||||
criterion_group!(
|
criterion_group!(
|
||||||
name = benches;
|
name = benches;
|
||||||
config = Criterion::default().measurement_time(Duration::from_secs(10));
|
config = Criterion::default().measurement_time(Duration::from_secs(10));
|
||||||
targets = parse_benchmark, parse_raw);
|
targets = parse_benchmark, parse_raw, parse_event);
|
||||||
criterion_main!(benches);
|
criterion_main!(benches);
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ use thiserror::Error;
|
||||||
pub enum Team {
|
pub enum Team {
|
||||||
Red,
|
Red,
|
||||||
Blue,
|
Blue,
|
||||||
|
Spectator,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Team {
|
impl Team {
|
||||||
|
|
@ -21,6 +22,7 @@ impl Team {
|
||||||
match self {
|
match self {
|
||||||
Team::Red => "Red",
|
Team::Red => "Red",
|
||||||
Team::Blue => "Blue",
|
Team::Blue => "Blue",
|
||||||
|
Team::Spectator => "Spectator",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -38,6 +40,7 @@ impl FromStr for Team {
|
||||||
match s {
|
match s {
|
||||||
"Blue" => Ok(Team::Blue),
|
"Blue" => Ok(Team::Blue),
|
||||||
"Red" => Ok(Team::Red),
|
"Red" => Ok(Team::Red),
|
||||||
|
"Spectator" => Ok(Team::Spectator),
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
use crate::event::{param_parse, param_parse_with};
|
use crate::event::{param_parse, param_parse_with, parse_from_str, position, u_int, ParamIter};
|
||||||
|
use crate::raw_event::{subject_parser, RawSubject};
|
||||||
|
use nom::bytes::complete::{tag, take_while};
|
||||||
use nom::combinator::opt;
|
use nom::combinator::opt;
|
||||||
use nom::number::complete::float;
|
use nom::number::complete::float;
|
||||||
use nom::IResult;
|
use nom::IResult;
|
||||||
|
|
@ -22,3 +24,145 @@ pub fn round_length_event_parser(input: &str) -> IResult<&str, RoundLengthEvent>
|
||||||
let (input, length) = opt(param_parse_with("against", float))(input)?;
|
let (input, length) = opt(param_parse_with("against", float))(input)?;
|
||||||
Ok((input, RoundLengthEvent { length }))
|
Ok((input, RoundLengthEvent { length }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct LogFileStartedEvent<'a> {
|
||||||
|
pub file: Option<&'a str>,
|
||||||
|
pub game: Option<&'a str>,
|
||||||
|
pub version: Option<&'a str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn log_file_started_event_parser(input: &str) -> IResult<&str, LogFileStartedEvent> {
|
||||||
|
let (input, file) = opt(param_parse("file"))(input)?;
|
||||||
|
let (input, game) = opt(param_parse("game"))(input)?;
|
||||||
|
let (input, version) = opt(param_parse("version"))(input)?;
|
||||||
|
Ok((
|
||||||
|
input,
|
||||||
|
LogFileStartedEvent {
|
||||||
|
file,
|
||||||
|
game,
|
||||||
|
version,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TournamentModeStartedEvent<'a> {
|
||||||
|
pub blue: &'a str,
|
||||||
|
pub red: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tournament_mode_started_event_parser(
|
||||||
|
input: &str,
|
||||||
|
) -> IResult<&str, TournamentModeStartedEvent> {
|
||||||
|
let (input, _) = tag("\nBlue Team: ")(input)?;
|
||||||
|
let (input, blue) = take_while(|c| c != '\n')(input)?;
|
||||||
|
let (input, _) = tag("\nRed Team: ")(input)?;
|
||||||
|
let (input, red) = take_while(|c| c != '\n')(input)?;
|
||||||
|
Ok((input, TournamentModeStartedEvent { blue, red }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct CaptureBlockedEvent<'a> {
|
||||||
|
pub cp: Option<u8>,
|
||||||
|
pub cp_name: Option<&'a str>,
|
||||||
|
pub position: Option<(i32, i32, i32)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn capture_blocked_event_parser(input: &str) -> IResult<&str, CaptureBlockedEvent> {
|
||||||
|
let (input, cp) = opt(param_parse_with("cp", u_int))(input)?;
|
||||||
|
let (input, cp_name) = opt(param_parse("map"))(input)?;
|
||||||
|
let (input, position) = opt(param_parse_with("red", position))(input)?;
|
||||||
|
Ok((
|
||||||
|
input,
|
||||||
|
CaptureBlockedEvent {
|
||||||
|
cp: cp.map(|cp| cp as u8),
|
||||||
|
cp_name,
|
||||||
|
position,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PointCapturedEvent<'a> {
|
||||||
|
pub cp: Option<u8>,
|
||||||
|
pub cp_name: Option<&'a str>,
|
||||||
|
pub num_cappers: Option<u8>,
|
||||||
|
pub players: Vec<(RawSubject<'a>, (i32, i32, i32))>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn point_captures_event_parser(input: &str) -> IResult<&str, PointCapturedEvent> {
|
||||||
|
let (input, cp) = opt(param_parse_with("cp", u_int))(input)?;
|
||||||
|
let (input, cp_name) = opt(param_parse("map"))(input)?;
|
||||||
|
let (input, num_cappers) = opt(param_parse_with("numcappers", u_int))(input)?;
|
||||||
|
|
||||||
|
let mut players = Vec::new();
|
||||||
|
|
||||||
|
let mut params = ParamIter::new(input);
|
||||||
|
match (params.next(), params.next()) {
|
||||||
|
(Some((subject_key, subject)), Some((position_key, position_str)))
|
||||||
|
if subject_key.starts_with("player") && position_key.starts_with("position") =>
|
||||||
|
{
|
||||||
|
let (_, subject) = subject_parser(subject)?;
|
||||||
|
let (_, position) = position(position_str)?;
|
||||||
|
players.push((subject, position));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
input,
|
||||||
|
PointCapturedEvent {
|
||||||
|
cp: cp.map(|cp| cp as u8),
|
||||||
|
num_cappers: num_cappers.map(|num| num as u8),
|
||||||
|
cp_name,
|
||||||
|
players,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct CurrentScoreEvent {
|
||||||
|
pub score: u8,
|
||||||
|
pub player: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn current_score_event_parser(input: &str) -> IResult<&str, CurrentScoreEvent> {
|
||||||
|
let (input, score) = param_parse_with("cp", u_int)(input)?;
|
||||||
|
let (input, player) = param_parse_with("with", u_int)(input)?;
|
||||||
|
Ok((
|
||||||
|
input,
|
||||||
|
CurrentScoreEvent {
|
||||||
|
score: score as u8,
|
||||||
|
player: player as u8,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct GameOverEvent<'a> {
|
||||||
|
pub reason: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn game_over_event_parser(input: &str) -> IResult<&str, GameOverEvent> {
|
||||||
|
let (input, reason) = param_parse("reason")(input)?;
|
||||||
|
Ok((input, GameOverEvent { reason }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct FinalScoreEvent {
|
||||||
|
pub score: u8,
|
||||||
|
pub player: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn final_score_event_parser(input: &str) -> IResult<&str, FinalScoreEvent> {
|
||||||
|
let (input, score) = param_parse_with("cp", u_int)(input)?;
|
||||||
|
let (input, player) = param_parse_with("with", u_int)(input)?;
|
||||||
|
Ok((
|
||||||
|
input,
|
||||||
|
FinalScoreEvent {
|
||||||
|
score: score as u8,
|
||||||
|
player: player as u8,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,3 +76,18 @@ pub fn medic_death_event_parser(input: &str) -> IResult<&str, MedicDeathEvent> {
|
||||||
}
|
}
|
||||||
Ok((input, MedicDeathEvent { charge }))
|
Ok((input, MedicDeathEvent { charge }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct MedicDeathExEvent {
|
||||||
|
pub charge_percentage: Option<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn medic_death_ex_event_parser(input: &str) -> IResult<&str, MedicDeathExEvent> {
|
||||||
|
let (input, charge_percentage) = opt(param_parse_with("time", quoted(u_int)))(input)?;
|
||||||
|
Ok((
|
||||||
|
input,
|
||||||
|
MedicDeathExEvent {
|
||||||
|
charge_percentage: charge_percentage.map(|charge: u32| charge as u8),
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,10 @@ pub use medic::*;
|
||||||
use nom::bytes::complete::{tag, take_while};
|
use nom::bytes::complete::{tag, take_while};
|
||||||
use nom::character::complete::{alpha1, digit1};
|
use nom::character::complete::{alpha1, digit1};
|
||||||
use nom::combinator::opt;
|
use nom::combinator::opt;
|
||||||
use nom::error::ErrorKind;
|
use nom::error::{ErrorKind, ParseError};
|
||||||
use nom::{Err, IResult};
|
use nom::{Err, IResult};
|
||||||
pub use player::*;
|
pub use player::*;
|
||||||
|
use std::str::FromStr;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
|
|
@ -68,12 +69,34 @@ pub enum GameEvent<'a> {
|
||||||
FirstHeal(FirstHealEvent),
|
FirstHeal(FirstHealEvent),
|
||||||
ChargeReady,
|
ChargeReady,
|
||||||
MedicDeath(MedicDeathEvent),
|
MedicDeath(MedicDeathEvent),
|
||||||
|
MedicDeathEx(MedicDeathExEvent),
|
||||||
Spawned(SpawnEvent),
|
Spawned(SpawnEvent),
|
||||||
RoleChange(RoleChangeEvent),
|
RoleChange(RoleChangeEvent),
|
||||||
RoundStart,
|
RoundStart,
|
||||||
RoundWin(RoundWinEvent<'a>),
|
RoundWin(RoundWinEvent<'a>),
|
||||||
RoundLength(RoundLengthEvent),
|
RoundLength(RoundLengthEvent),
|
||||||
RoundOverTime,
|
RoundOverTime,
|
||||||
|
LogFileStarted(LogFileStartedEvent<'a>),
|
||||||
|
Connected(ConnectedEvent),
|
||||||
|
Disconnect(DisconnectEvent<'a>),
|
||||||
|
SteamIdValidated,
|
||||||
|
Entered,
|
||||||
|
Joined(JoinedTeamEvent),
|
||||||
|
Suicide(CommittedSuicideEvent<'a>),
|
||||||
|
PickedUp(PickedUpEvent<'a>),
|
||||||
|
Domination(DominationEvent<'a>),
|
||||||
|
EmptyUber,
|
||||||
|
Revenge(RevengeEvent<'a>),
|
||||||
|
TournamentModeStarted(TournamentModeStartedEvent<'a>),
|
||||||
|
CaptureBlocked(CaptureBlockedEvent<'a>),
|
||||||
|
PointCaptured(PointCapturedEvent<'a>),
|
||||||
|
CurrentScore(CurrentScoreEvent),
|
||||||
|
BuiltObject(BuiltObjectEvent<'a>),
|
||||||
|
KilledObject(KilledObjectEvent<'a>),
|
||||||
|
Extinguished(ExtinguishedEvent<'a>),
|
||||||
|
GameOver(GameOverEvent<'a>),
|
||||||
|
FinalScore(FinalScoreEvent),
|
||||||
|
LogFileClosed,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> GameEvent<'a> {
|
impl<'a> GameEvent<'a> {
|
||||||
|
|
@ -115,6 +138,9 @@ impl<'a> GameEvent<'a> {
|
||||||
RawEventType::MedicDeath => {
|
RawEventType::MedicDeath => {
|
||||||
GameEvent::MedicDeath(medic_death_event_parser(raw.params).with_type(raw.ty)?)
|
GameEvent::MedicDeath(medic_death_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
}
|
}
|
||||||
|
RawEventType::MedicDeathEx => {
|
||||||
|
GameEvent::MedicDeathEx(medic_death_ex_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
|
}
|
||||||
RawEventType::Spawned => {
|
RawEventType::Spawned => {
|
||||||
GameEvent::Spawned(spawn_event_parser(raw.params).with_type(raw.ty)?)
|
GameEvent::Spawned(spawn_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
}
|
}
|
||||||
|
|
@ -129,6 +155,61 @@ impl<'a> GameEvent<'a> {
|
||||||
GameEvent::RoundWin(round_win_event_parser(raw.params).with_type(raw.ty)?)
|
GameEvent::RoundWin(round_win_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
}
|
}
|
||||||
RawEventType::RoundOvertime => GameEvent::RoundOverTime,
|
RawEventType::RoundOvertime => GameEvent::RoundOverTime,
|
||||||
|
RawEventType::LogFileStarted => GameEvent::LogFileStarted(
|
||||||
|
log_file_started_event_parser(raw.params).with_type(raw.ty)?,
|
||||||
|
),
|
||||||
|
RawEventType::Connected => {
|
||||||
|
GameEvent::Connected(connected_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
|
}
|
||||||
|
RawEventType::Disconnected => {
|
||||||
|
GameEvent::Disconnect(disconnected_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
|
}
|
||||||
|
RawEventType::SteamIdValidated => GameEvent::SteamIdValidated,
|
||||||
|
RawEventType::Entered => GameEvent::Entered,
|
||||||
|
RawEventType::Joined => {
|
||||||
|
GameEvent::Joined(joined_team_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
|
}
|
||||||
|
RawEventType::Suicide => {
|
||||||
|
GameEvent::Suicide(committed_suicide_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
|
}
|
||||||
|
RawEventType::PickedUp => {
|
||||||
|
GameEvent::PickedUp(picked_up_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
|
}
|
||||||
|
RawEventType::Domination => {
|
||||||
|
GameEvent::Domination(domination_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
|
}
|
||||||
|
RawEventType::EmptyUber => GameEvent::EmptyUber,
|
||||||
|
RawEventType::Revenge => {
|
||||||
|
GameEvent::Revenge(revenge_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
|
}
|
||||||
|
RawEventType::TournamentStart => GameEvent::TournamentModeStarted(
|
||||||
|
tournament_mode_started_event_parser(raw.params).with_type(raw.ty)?,
|
||||||
|
),
|
||||||
|
RawEventType::CaptureBlocked => GameEvent::CaptureBlocked(
|
||||||
|
capture_blocked_event_parser(raw.params).with_type(raw.ty)?,
|
||||||
|
),
|
||||||
|
RawEventType::PointCaptured => {
|
||||||
|
GameEvent::PointCaptured(point_captures_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
|
}
|
||||||
|
RawEventType::CurrentScore => {
|
||||||
|
GameEvent::CurrentScore(current_score_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
|
}
|
||||||
|
RawEventType::PlayerBuiltObject => {
|
||||||
|
GameEvent::BuiltObject(built_object_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
|
}
|
||||||
|
RawEventType::PlayerKilledObject => {
|
||||||
|
GameEvent::KilledObject(killed_object_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
|
}
|
||||||
|
RawEventType::PlayerExtinguished => {
|
||||||
|
GameEvent::Extinguished(extinguished_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
|
}
|
||||||
|
RawEventType::GameOver => {
|
||||||
|
GameEvent::GameOver(game_over_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
|
}
|
||||||
|
RawEventType::FinalScore => {
|
||||||
|
GameEvent::FinalScore(final_score_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
|
}
|
||||||
|
RawEventType::LogFileClosed => GameEvent::LogFileClosed,
|
||||||
_ => {
|
_ => {
|
||||||
todo!("{:?} not parsed yet", raw.ty);
|
todo!("{:?} not parsed yet", raw.ty);
|
||||||
}
|
}
|
||||||
|
|
@ -205,6 +286,12 @@ fn param_parse_with<'a, T, P: Fn(&'a str) -> IResult<&'a str, T>>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_from_str<T: FromStr>(input: &str) -> IResult<&str, T> {
|
||||||
|
T::from_str(input)
|
||||||
|
.map(|res| ("", res))
|
||||||
|
.map_err(|_| nom::Err::Error(nom::error::Error::from_error_kind(input, ErrorKind::IsNot)))
|
||||||
|
}
|
||||||
|
|
||||||
fn int(input: &str) -> IResult<&str, i32> {
|
fn int(input: &str) -> IResult<&str, i32> {
|
||||||
let (input, sign) = opt(tag("-"))(input)?;
|
let (input, sign) = opt(tag("-"))(input)?;
|
||||||
let (input, raw) = digit1(input)?;
|
let (input, raw) = digit1(input)?;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
use crate::common::Class;
|
use crate::common::{Class, Team};
|
||||||
use crate::event::{param_parse, param_parse_with, position, u_int, ParamIter};
|
use crate::event::{param_parse, param_parse_with, parse_from_str, 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;
|
||||||
|
use std::net::SocketAddr;
|
||||||
use std::num::NonZeroU32;
|
use std::num::NonZeroU32;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -132,3 +133,141 @@ pub fn role_changed_event_parser(input: &str) -> IResult<&str, RoleChangeEvent>
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ConnectedEvent {
|
||||||
|
pub address: SocketAddr,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn connected_event_parser(input: &str) -> IResult<&str, ConnectedEvent> {
|
||||||
|
let (input, address) = param_parse_with("to", parse_from_str)(input)?;
|
||||||
|
Ok((input, ConnectedEvent { address }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct JoinedTeamEvent {
|
||||||
|
pub team: Team,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn joined_team_event_parser(input: &str) -> IResult<&str, JoinedTeamEvent> {
|
||||||
|
let (input, team) = param_parse_with("team", parse_from_str)(input)?;
|
||||||
|
Ok((input, JoinedTeamEvent { team }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct CommittedSuicideEvent<'a> {
|
||||||
|
pub weapon: &'a str,
|
||||||
|
pub attacker_position: Option<(i32, i32, i32)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn committed_suicide_event_parser(input: &str) -> IResult<&str, CommittedSuicideEvent> {
|
||||||
|
let (input, weapon) = param_parse("with")(input)?;
|
||||||
|
let (input, attacker_position) = opt(param_parse_with("attacker_position", position))(input)?;
|
||||||
|
Ok((
|
||||||
|
input,
|
||||||
|
CommittedSuicideEvent {
|
||||||
|
weapon,
|
||||||
|
attacker_position,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PickedUpEvent<'a> {
|
||||||
|
pub item: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn picked_up_event_parser(input: &str) -> IResult<&str, PickedUpEvent> {
|
||||||
|
let (input, item) = param_parse("item")(input)?;
|
||||||
|
Ok((input, PickedUpEvent { item }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DominationEvent<'a> {
|
||||||
|
pub against: RawSubject<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn domination_event_parser(input: &str) -> IResult<&str, DominationEvent> {
|
||||||
|
let (input, against) = param_parse_with("against", subject_parser)(input)?;
|
||||||
|
Ok((input, DominationEvent { against }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct RevengeEvent<'a> {
|
||||||
|
pub against: RawSubject<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn revenge_event_parser(input: &str) -> IResult<&str, RevengeEvent> {
|
||||||
|
let (input, against) = param_parse_with("against", subject_parser)(input)?;
|
||||||
|
Ok((input, RevengeEvent { against }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DisconnectEvent<'a> {
|
||||||
|
pub reason: Option<&'a str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn disconnected_event_parser(input: &str) -> IResult<&str, DisconnectEvent> {
|
||||||
|
let (input, reason) = opt(param_parse("reason"))(input)?;
|
||||||
|
Ok((input, DisconnectEvent { reason }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct BuiltObjectEvent<'a> {
|
||||||
|
pub object: Option<&'a str>,
|
||||||
|
pub position: Option<(i32, i32, i32)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn built_object_event_parser(input: &str) -> IResult<&str, BuiltObjectEvent> {
|
||||||
|
let (input, object) = opt(param_parse("object"))(input)?;
|
||||||
|
let (input, position) = opt(param_parse_with("position", position))(input)?;
|
||||||
|
Ok((input, BuiltObjectEvent { object, position }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct KilledObjectEvent<'a> {
|
||||||
|
pub object: Option<&'a str>,
|
||||||
|
pub weapon: Option<&'a str>,
|
||||||
|
pub object_owner: Option<RawSubject<'a>>,
|
||||||
|
pub attacker_position: Option<(i32, i32, i32)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn killed_object_event_parser(input: &str) -> IResult<&str, KilledObjectEvent> {
|
||||||
|
let (input, object) = opt(param_parse("object"))(input)?;
|
||||||
|
let (input, weapon) = opt(param_parse("weapon"))(input)?;
|
||||||
|
let (input, object_owner) = opt(param_parse_with("objectowner", subject_parser))(input)?;
|
||||||
|
let (input, attacker_position) = opt(param_parse_with("attacker_position", position))(input)?;
|
||||||
|
Ok((
|
||||||
|
input,
|
||||||
|
KilledObjectEvent {
|
||||||
|
object,
|
||||||
|
weapon,
|
||||||
|
object_owner,
|
||||||
|
attacker_position,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ExtinguishedEvent<'a> {
|
||||||
|
pub against: RawSubject<'a>,
|
||||||
|
pub with: &'a str,
|
||||||
|
pub attacker_position: Option<(i32, i32, i32)>,
|
||||||
|
pub victim_position: Option<(i32, i32, i32)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn extinguished_event_parser(input: &str) -> IResult<&str, ExtinguishedEvent> {
|
||||||
|
let (input, against) = param_parse_with("against", subject_parser)(input)?;
|
||||||
|
let (input, with) = param_parse("with")(input)?;
|
||||||
|
let (input, attacker_position) = opt(param_parse_with("attacker_position", position))(input)?;
|
||||||
|
let (input, victim_position) = opt(param_parse_with("victim_position", position))(input)?;
|
||||||
|
Ok((
|
||||||
|
input,
|
||||||
|
ExtinguishedEvent {
|
||||||
|
against,
|
||||||
|
with,
|
||||||
|
attacker_position,
|
||||||
|
victim_position,
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,8 +61,8 @@ pub fn parse_with_handler<Handler: EventHandler>(
|
||||||
Error,
|
Error,
|
||||||
> {
|
> {
|
||||||
let events = log
|
let events = log
|
||||||
.lines()
|
.split("L ")
|
||||||
.filter(|line| line.starts_with("L "))
|
.filter(|line| !line.is_empty())
|
||||||
.map(RawEvent::parse);
|
.map(RawEvent::parse);
|
||||||
|
|
||||||
let mut handler = Handler::default();
|
let mut handler = Handler::default();
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ impl<'a> RawEvent<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn event_parser(input: &str) -> IResult<&str, RawEvent> {
|
fn event_parser(input: &str) -> IResult<&str, RawEvent> {
|
||||||
let (input, _) = tag("L ")(input)?;
|
|
||||||
let (input, date) = date_parser(input)?;
|
let (input, date) = date_parser(input)?;
|
||||||
|
|
||||||
let (input, _) = tag(": ")(input)?;
|
let (input, _) = tag(": ")(input)?;
|
||||||
|
|
@ -190,7 +189,7 @@ pub fn subject_parser(input: &str) -> IResult<&str, RawSubject> {
|
||||||
|
|
||||||
#[derive(IntoEnumIterator, Copy, Clone, Debug, PartialEq)]
|
#[derive(IntoEnumIterator, Copy, Clone, Debug, PartialEq)]
|
||||||
pub enum RawEventType {
|
pub enum RawEventType {
|
||||||
JoinedTeam,
|
Joined,
|
||||||
ChangedRole,
|
ChangedRole,
|
||||||
ShotFired,
|
ShotFired,
|
||||||
ShotHit,
|
ShotHit,
|
||||||
|
|
@ -212,7 +211,7 @@ pub enum RawEventType {
|
||||||
PlayerKilledObject,
|
PlayerKilledObject,
|
||||||
PlayerExtinguished,
|
PlayerExtinguished,
|
||||||
ObjectDetonated,
|
ObjectDetonated,
|
||||||
PickedUpItem,
|
PickedUp,
|
||||||
MedicDeath,
|
MedicDeath,
|
||||||
MedicDeathEx,
|
MedicDeathEx,
|
||||||
ChargeEnd,
|
ChargeEnd,
|
||||||
|
|
@ -253,7 +252,7 @@ pub enum RawEventType {
|
||||||
impl RawEventType {
|
impl RawEventType {
|
||||||
pub fn tag(self) -> &'static str {
|
pub fn tag(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
RawEventType::JoinedTeam => r#"joined team"#,
|
RawEventType::Joined => r#"joined"#,
|
||||||
RawEventType::ChangedRole => r#"changed role"#,
|
RawEventType::ChangedRole => r#"changed role"#,
|
||||||
RawEventType::ShotFired => r#"triggered "shot_fired""#,
|
RawEventType::ShotFired => r#"triggered "shot_fired""#,
|
||||||
RawEventType::ShotHit => r#"triggered "shot_hit""#,
|
RawEventType::ShotHit => r#"triggered "shot_hit""#,
|
||||||
|
|
@ -275,7 +274,7 @@ impl RawEventType {
|
||||||
RawEventType::PlayerKilledObject => r#"triggered "killedobject""#,
|
RawEventType::PlayerKilledObject => r#"triggered "killedobject""#,
|
||||||
RawEventType::ObjectDetonated => r#"triggered "object_detonated""#,
|
RawEventType::ObjectDetonated => r#"triggered "object_detonated""#,
|
||||||
RawEventType::PlayerExtinguished => r#"triggered "player_extinguished""#,
|
RawEventType::PlayerExtinguished => r#"triggered "player_extinguished""#,
|
||||||
RawEventType::PickedUpItem => r#"picked up item"#,
|
RawEventType::PickedUp => r#"picked up"#,
|
||||||
RawEventType::MedicDeath => r#"triggered "medic_death""#,
|
RawEventType::MedicDeath => r#"triggered "medic_death""#,
|
||||||
RawEventType::MedicDeathEx => r#"triggered "medic_death_ex""#,
|
RawEventType::MedicDeathEx => r#"triggered "medic_death_ex""#,
|
||||||
RawEventType::ChargeEnd => r#"triggered "chargeended""#,
|
RawEventType::ChargeEnd => r#"triggered "chargeended""#,
|
||||||
|
|
@ -295,8 +294,8 @@ impl RawEventType {
|
||||||
RawEventType::PointCaptured => r#"triggered "pointcaptured""#,
|
RawEventType::PointCaptured => r#"triggered "pointcaptured""#,
|
||||||
RawEventType::CaptureBlocked => r#"triggered "captureblocked""#,
|
RawEventType::CaptureBlocked => r#"triggered "captureblocked""#,
|
||||||
RawEventType::GameOver => r#"triggered "Game_Over""#,
|
RawEventType::GameOver => r#"triggered "Game_Over""#,
|
||||||
RawEventType::CurrentScore => r#"current score"#,
|
RawEventType::CurrentScore => r#"current"#,
|
||||||
RawEventType::FinalScore => r#"final score"#,
|
RawEventType::FinalScore => r#"final"#,
|
||||||
RawEventType::WinLimit => r#"triggered "Intermission_Win_Limit""#,
|
RawEventType::WinLimit => r#"triggered "Intermission_Win_Limit""#,
|
||||||
RawEventType::Paused => r#"triggered "Game_Paused""#,
|
RawEventType::Paused => r#"triggered "Game_Paused""#,
|
||||||
RawEventType::UnPaused => r#"triggered "Game_Unpaused""#,
|
RawEventType::UnPaused => r#"triggered "Game_Unpaused""#,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue