mirror of
https://codeberg.org/icewind/tf-log-parser.git
synced 2026-06-03 18:24:09 +02:00
class stats
This commit is contained in:
parent
cdaa164575
commit
9c63c8b658
8 changed files with 354 additions and 8 deletions
119
src/common.rs
119
src/common.rs
|
|
@ -1,12 +1,15 @@
|
||||||
use crate::raw_event::RawSubject;
|
use crate::raw_event::RawSubject;
|
||||||
|
use enum_iterator::IntoEnumIterator;
|
||||||
|
use serde::ser::SerializeMap;
|
||||||
use serde::{Serialize, Serializer};
|
use serde::{Serialize, Serializer};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
|
use std::ops::{Index, IndexMut};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use steamid_ng::{AccountType, Instance, SteamID, Universe};
|
use steamid_ng::{AccountType, Instance, SteamID, Universe};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Serialize, Copy, Clone, Eq, PartialEq, Debug, Ord, PartialOrd)]
|
#[derive(Serialize, Copy, Clone, Eq, PartialEq, Debug, Ord, PartialOrd, Hash)]
|
||||||
pub enum Team {
|
pub enum Team {
|
||||||
Red,
|
Red,
|
||||||
Blue,
|
Blue,
|
||||||
|
|
@ -39,8 +42,118 @@ impl FromStr for Team {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, IntoEnumIterator, Serialize)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum Class {
|
||||||
|
Scout,
|
||||||
|
Soldier,
|
||||||
|
Pyro,
|
||||||
|
DemoMan,
|
||||||
|
HeavyWeapons,
|
||||||
|
Engineer,
|
||||||
|
Medic,
|
||||||
|
Sniper,
|
||||||
|
Spy,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Class {
|
||||||
|
pub fn as_str(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Class::Scout => "scout",
|
||||||
|
Class::Soldier => "soldier",
|
||||||
|
Class::Pyro => "pyro",
|
||||||
|
Class::DemoMan => "demoman",
|
||||||
|
Class::HeavyWeapons => "heavyweapons",
|
||||||
|
Class::Engineer => "engineer",
|
||||||
|
Class::Medic => "medic",
|
||||||
|
Class::Sniper => "sniper",
|
||||||
|
Class::Spy => "spy",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Class {
|
||||||
|
type Err = ();
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
match s {
|
||||||
|
"scout" => Ok(Class::Scout),
|
||||||
|
"soldier" => Ok(Class::Soldier),
|
||||||
|
"pyro" => Ok(Class::Pyro),
|
||||||
|
"demoman" => Ok(Class::DemoMan),
|
||||||
|
"heavyweapons" => Ok(Class::HeavyWeapons),
|
||||||
|
"engineer" => Ok(Class::Engineer),
|
||||||
|
"medic" => Ok(Class::Medic),
|
||||||
|
"sniper" => Ok(Class::Sniper),
|
||||||
|
"spy" => Ok(Class::Spy),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ClassMap<T>([T; 9]);
|
||||||
|
|
||||||
|
impl<T> Index<Class> for ClassMap<T> {
|
||||||
|
type Output = T;
|
||||||
|
|
||||||
|
fn index(&self, index: Class) -> &Self::Output {
|
||||||
|
match index {
|
||||||
|
Class::Scout => &self.0[0],
|
||||||
|
Class::Soldier => &self.0[1],
|
||||||
|
Class::Pyro => &self.0[2],
|
||||||
|
Class::DemoMan => &self.0[3],
|
||||||
|
Class::HeavyWeapons => &self.0[4],
|
||||||
|
Class::Engineer => &self.0[5],
|
||||||
|
Class::Medic => &self.0[6],
|
||||||
|
Class::Sniper => &self.0[7],
|
||||||
|
Class::Spy => &self.0[8],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> IndexMut<Class> for ClassMap<T> {
|
||||||
|
fn index_mut(&mut self, index: Class) -> &mut Self::Output {
|
||||||
|
match index {
|
||||||
|
Class::Scout => &mut self.0[0],
|
||||||
|
Class::Soldier => &mut self.0[1],
|
||||||
|
Class::Pyro => &mut self.0[2],
|
||||||
|
Class::DemoMan => &mut self.0[3],
|
||||||
|
Class::HeavyWeapons => &mut self.0[4],
|
||||||
|
Class::Engineer => &mut self.0[5],
|
||||||
|
Class::Medic => &mut self.0[6],
|
||||||
|
Class::Sniper => &mut self.0[7],
|
||||||
|
Class::Spy => &mut self.0[8],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Serialize for ClassMap<T>
|
||||||
|
where
|
||||||
|
T: Serialize + Default + PartialEq,
|
||||||
|
{
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
let mut map = serializer.serialize_map(None)?;
|
||||||
|
for class in Class::into_enum_iter() {
|
||||||
|
let stats = &self[class];
|
||||||
|
if stats != &T::default() {
|
||||||
|
map.serialize_entry(&class, stats)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
map.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Default> Default for ClassMap<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
ClassMap(<[T; 9]>::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Optimized subject id
|
/// Optimized subject id
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Debug, Ord, PartialOrd)]
|
#[derive(Copy, Clone, Eq, PartialEq, Debug, Ord, PartialOrd, Hash)]
|
||||||
pub enum SubjectId {
|
pub enum SubjectId {
|
||||||
Player(u32),
|
Player(u32),
|
||||||
Team(Team),
|
Team(Team),
|
||||||
|
|
@ -54,7 +167,7 @@ impl SubjectId {
|
||||||
match self {
|
match self {
|
||||||
SubjectId::Player(account_id) => Some(SteamID::new(
|
SubjectId::Player(account_id) => Some(SteamID::new(
|
||||||
*account_id,
|
*account_id,
|
||||||
Instance::All,
|
Instance::Desktop,
|
||||||
AccountType::Individual,
|
AccountType::Individual,
|
||||||
Universe::Public,
|
Universe::Public,
|
||||||
)),
|
)),
|
||||||
|
|
|
||||||
24
src/event/game.rs
Normal file
24
src/event/game.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
use crate::event::{param_parse, param_parse_with};
|
||||||
|
use nom::combinator::opt;
|
||||||
|
use nom::number::complete::float;
|
||||||
|
use nom::IResult;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct RoundWinEvent<'a> {
|
||||||
|
pub team: Option<&'a str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn round_win_event_parser(input: &str) -> IResult<&str, RoundWinEvent> {
|
||||||
|
let (input, team) = opt(param_parse("against"))(input)?;
|
||||||
|
Ok((input, RoundWinEvent { team }))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct RoundLengthEvent {
|
||||||
|
pub length: Option<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn round_length_event_parser(input: &str) -> IResult<&str, RoundLengthEvent> {
|
||||||
|
let (input, length) = opt(param_parse_with("against", float))(input)?;
|
||||||
|
Ok((input, RoundLengthEvent { length }))
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
|
mod game;
|
||||||
mod medic;
|
mod medic;
|
||||||
mod player;
|
mod player;
|
||||||
|
|
||||||
|
use crate::event::game::{RoundLengthEvent, RoundWinEvent};
|
||||||
use crate::{RawEvent, RawEventType};
|
use crate::{RawEvent, RawEventType};
|
||||||
|
pub use game::*;
|
||||||
pub use medic::*;
|
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};
|
||||||
|
|
@ -59,6 +62,12 @@ pub enum GameEvent<'a> {
|
||||||
FirstHeal(FirstHealEvent),
|
FirstHeal(FirstHealEvent),
|
||||||
ChargeReady,
|
ChargeReady,
|
||||||
MedicDeath(MedicDeathEvent),
|
MedicDeath(MedicDeathEvent),
|
||||||
|
Spawned(SpawnEvent),
|
||||||
|
RoleChange(RoleChangeEvent),
|
||||||
|
RoundStart,
|
||||||
|
RoundWin(RoundWinEvent<'a>),
|
||||||
|
RoundLength(RoundLengthEvent),
|
||||||
|
RoundOverTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> GameEvent<'a> {
|
impl<'a> GameEvent<'a> {
|
||||||
|
|
@ -100,6 +109,20 @@ 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::Spawned => {
|
||||||
|
GameEvent::Spawned(spawn_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
|
}
|
||||||
|
RawEventType::ChangedRole => {
|
||||||
|
GameEvent::RoleChange(role_changed_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
|
}
|
||||||
|
RawEventType::RoundStart => GameEvent::RoundStart,
|
||||||
|
RawEventType::RoundLength => {
|
||||||
|
GameEvent::RoundLength(round_length_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
|
}
|
||||||
|
RawEventType::RoundWin => {
|
||||||
|
GameEvent::RoundWin(round_win_event_parser(raw.params).with_type(raw.ty)?)
|
||||||
|
}
|
||||||
|
RawEventType::RoundOvertime => GameEvent::RoundOverTime,
|
||||||
_ => {
|
_ => {
|
||||||
todo!("{:?} not parsed yet", raw.ty);
|
todo!("{:?} not parsed yet", raw.ty);
|
||||||
}
|
}
|
||||||
|
|
@ -161,6 +184,7 @@ fn param_parse_with<'a, T, P: Fn(&'a str) -> IResult<&'a str, T>>(
|
||||||
parser: P,
|
parser: P,
|
||||||
) -> impl Fn(&'a str) -> IResult<&'a str, T> {
|
) -> impl Fn(&'a str) -> IResult<&'a str, T> {
|
||||||
move |input: &str| {
|
move |input: &str| {
|
||||||
|
let (input, _) = opt(tag(" "))(input)?;
|
||||||
let (input, open_tag) = opt(tag("("))(input)?;
|
let (input, open_tag) = opt(tag("("))(input)?;
|
||||||
|
|
||||||
let (input, _) = tag(key)(input)?;
|
let (input, _) = tag(key)(input)?;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::common::Class;
|
||||||
use crate::event::{param_parse, param_parse_with, position, 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;
|
||||||
|
|
@ -60,7 +61,7 @@ pub struct KillEvent<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kill_event_parser(input: &str) -> IResult<&str, KillEvent> {
|
pub fn kill_event_parser(input: &str) -> IResult<&str, KillEvent> {
|
||||||
let (input, target) = param_parse_with("against", subject_parser)(input)?;
|
let (input, target) = subject_parser(input)?;
|
||||||
let (input, weapon) = param_parse("with")(input)?;
|
let (input, weapon) = param_parse("with")(input)?;
|
||||||
let mut event = KillEvent {
|
let mut event = KillEvent {
|
||||||
target,
|
target,
|
||||||
|
|
@ -101,3 +102,33 @@ pub fn kill_assist_event_parser(input: &str) -> IResult<&str, KillAssistEvent> {
|
||||||
}
|
}
|
||||||
Ok(("", event))
|
Ok(("", event))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct SpawnEvent {
|
||||||
|
pub class: Option<Class>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn spawn_event_parser(input: &str) -> IResult<&str, SpawnEvent> {
|
||||||
|
let (input, class_str) = param_parse("as")(input)?;
|
||||||
|
Ok((
|
||||||
|
input,
|
||||||
|
SpawnEvent {
|
||||||
|
class: class_str.parse().ok(),
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct RoleChangeEvent {
|
||||||
|
pub class: Option<Class>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn role_changed_event_parser(input: &str) -> IResult<&str, RoleChangeEvent> {
|
||||||
|
let (input, class_str) = param_parse("to")(input)?;
|
||||||
|
Ok((
|
||||||
|
input,
|
||||||
|
RoleChangeEvent {
|
||||||
|
class: class_str.parse().ok(),
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
pub use crate::common::{SteamId3, SubjectData, SubjectError, SubjectId};
|
pub use crate::common::{SteamId3, SubjectData, SubjectError, SubjectId};
|
||||||
use crate::event::GameEventError;
|
use crate::event::GameEventError;
|
||||||
pub use crate::module::EventHandler;
|
pub use crate::module::EventHandler;
|
||||||
use crate::module::{ChatHandler, HealSpreadHandler, MedicStatsHandler};
|
use crate::module::{ChatHandler, ClassStatsHandler, HealSpreadHandler, MedicStatsHandler};
|
||||||
use crate::raw_event::RawSubject;
|
use crate::raw_event::RawSubject;
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
pub use event::GameEvent;
|
pub use event::GameEvent;
|
||||||
|
|
@ -103,4 +103,5 @@ handler!(LogHandler {
|
||||||
chat: ChatHandler,
|
chat: ChatHandler,
|
||||||
heal_spread: HealSpreadHandler,
|
heal_spread: HealSpreadHandler,
|
||||||
medic_stats: MedicStatsHandler,
|
medic_stats: MedicStatsHandler,
|
||||||
|
class_stats: ClassStatsHandler,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
146
src/module/classstats.rs
Normal file
146
src/module/classstats.rs
Normal file
|
|
@ -0,0 +1,146 @@
|
||||||
|
use crate::common::{Class, ClassMap, SteamId3, SubjectId};
|
||||||
|
use crate::event::{DamageEvent, GameEvent, RoleChangeEvent, SpawnEvent};
|
||||||
|
use crate::module::EventHandler;
|
||||||
|
use crate::raw_event::{RawEventType, RawSubject};
|
||||||
|
use crate::SubjectMap;
|
||||||
|
use serde::Serialize;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::ops::{Add, AddAssign};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Default, PartialEq)]
|
||||||
|
pub struct ClassStat {
|
||||||
|
kills: u8,
|
||||||
|
deaths: u8,
|
||||||
|
assists: u8,
|
||||||
|
damage: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Add for ClassStat {
|
||||||
|
type Output = ClassStat;
|
||||||
|
|
||||||
|
fn add(self, rhs: Self) -> Self::Output {
|
||||||
|
ClassStat {
|
||||||
|
kills: self.kills + rhs.kills,
|
||||||
|
deaths: self.deaths + rhs.deaths,
|
||||||
|
assists: self.assists + rhs.assists,
|
||||||
|
damage: self.damage + rhs.damage,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddAssign for ClassStat {
|
||||||
|
fn add_assign(&mut self, rhs: Self) {
|
||||||
|
self.kills += rhs.kills;
|
||||||
|
self.deaths += rhs.deaths;
|
||||||
|
self.assists += rhs.assists;
|
||||||
|
self.damage += rhs.damage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct ClassStatsHandler {
|
||||||
|
active: bool,
|
||||||
|
classes: HashMap<SubjectId, Class>,
|
||||||
|
stats: HashMap<SteamId3, ClassMap<ClassStat>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClassStatsHandler {
|
||||||
|
fn handle_stats(&mut self, subject: SubjectId, target: &RawSubject, stats: ClassStat) {
|
||||||
|
if let Ok(target) = target.id() {
|
||||||
|
self.handle_stats_id(subject, target, stats)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_stats_id(&mut self, subject: SubjectId, target: SubjectId, stats: ClassStat) {
|
||||||
|
let subject = if let Some(steam_id) = subject.steam_id() {
|
||||||
|
steam_id
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(target_class) = self.classes.get(&target) {
|
||||||
|
self.stats.entry(SteamId3(subject)).or_default()[*target_class] += stats;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventHandler for ClassStatsHandler {
|
||||||
|
type Output = HashMap<SteamId3, ClassMap<ClassStat>>;
|
||||||
|
|
||||||
|
fn does_handle(&self, ty: RawEventType) -> bool {
|
||||||
|
matches!(
|
||||||
|
ty,
|
||||||
|
RawEventType::Killed
|
||||||
|
| RawEventType::KillAssist
|
||||||
|
| RawEventType::Damage
|
||||||
|
| RawEventType::Spawned
|
||||||
|
| RawEventType::ChangedRole
|
||||||
|
| RawEventType::RoundWin
|
||||||
|
| RawEventType::RoundStart
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle(&mut self, _time: u32, subject: SubjectId, event: &GameEvent) {
|
||||||
|
match event {
|
||||||
|
GameEvent::Spawned(SpawnEvent { class: Some(class) })
|
||||||
|
| GameEvent::RoleChange(RoleChangeEvent { class: Some(class) }) => {
|
||||||
|
self.classes.insert(subject, *class);
|
||||||
|
}
|
||||||
|
GameEvent::RoundStart => {
|
||||||
|
self.active = true;
|
||||||
|
}
|
||||||
|
GameEvent::RoundWin(_) => {
|
||||||
|
self.active = false;
|
||||||
|
}
|
||||||
|
GameEvent::Kill(kill) if self.active => {
|
||||||
|
self.handle_stats(
|
||||||
|
subject,
|
||||||
|
&kill.target,
|
||||||
|
ClassStat {
|
||||||
|
kills: 1,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if let Ok(target) = kill.target.id() {
|
||||||
|
self.handle_stats_id(
|
||||||
|
target,
|
||||||
|
subject,
|
||||||
|
ClassStat {
|
||||||
|
deaths: 1,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GameEvent::KillAssist(kill) if self.active => {
|
||||||
|
self.handle_stats(
|
||||||
|
subject,
|
||||||
|
&kill.target,
|
||||||
|
ClassStat {
|
||||||
|
assists: 1,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
GameEvent::Damage(DamageEvent {
|
||||||
|
damage: Some(damage),
|
||||||
|
target,
|
||||||
|
..
|
||||||
|
}) if self.active => {
|
||||||
|
self.handle_stats(
|
||||||
|
subject,
|
||||||
|
target,
|
||||||
|
ClassStat {
|
||||||
|
damage: damage.get() as u16,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finish(self, _subjects: &SubjectMap) -> Self::Output {
|
||||||
|
self.stats
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,7 @@ use crate::event::GameEvent;
|
||||||
use crate::raw_event::RawEventType;
|
use crate::raw_event::RawEventType;
|
||||||
use crate::SubjectMap;
|
use crate::SubjectMap;
|
||||||
pub use chat::{ChatHandler, ChatMessage, ChatType};
|
pub use chat::{ChatHandler, ChatMessage, ChatType};
|
||||||
|
pub use classstats::{ClassStat, ClassStatsHandler};
|
||||||
pub use healspread::HealSpreadHandler;
|
pub use healspread::HealSpreadHandler;
|
||||||
pub use lobbysettings::{
|
pub use lobbysettings::{
|
||||||
LobbySettingsError, LobbySettingsHandler, Location, Settings as LobbySettings,
|
LobbySettingsError, LobbySettingsHandler, Location, Settings as LobbySettings,
|
||||||
|
|
@ -10,6 +11,7 @@ pub use lobbysettings::{
|
||||||
pub use medicstats::{MedicStats, MedicStatsHandler};
|
pub use medicstats::{MedicStats, MedicStatsHandler};
|
||||||
|
|
||||||
mod chat;
|
mod chat;
|
||||||
|
mod classstats;
|
||||||
mod healspread;
|
mod healspread;
|
||||||
mod lobbysettings;
|
mod lobbysettings;
|
||||||
mod medicstats;
|
mod medicstats;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::{SubjectError, SubjectId};
|
||||||
use chrono::{DateTime, TimeZone, Utc};
|
use chrono::{DateTime, TimeZone, Utc};
|
||||||
use enum_iterator::IntoEnumIterator;
|
use enum_iterator::IntoEnumIterator;
|
||||||
use nom::branch::alt;
|
use nom::branch::alt;
|
||||||
|
|
@ -5,7 +6,7 @@ use nom::bytes::complete::{tag, take_while};
|
||||||
use nom::character::complete::{digit1, one_of};
|
use nom::character::complete::{digit1, one_of};
|
||||||
use nom::error::{make_error, ErrorKind};
|
use nom::error::{make_error, ErrorKind};
|
||||||
use nom::{Finish, IResult};
|
use nom::{Finish, IResult};
|
||||||
use std::convert::TryFrom;
|
use std::convert::{TryFrom, TryInto};
|
||||||
use std::num::ParseIntError;
|
use std::num::ParseIntError;
|
||||||
|
|
||||||
/// Event that has only been minimally parsed.
|
/// Event that has only been minimally parsed.
|
||||||
|
|
@ -125,6 +126,10 @@ impl<'a> RawSubject<'a> {
|
||||||
RawSubject::World => "World",
|
RawSubject::World => "World",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn id(&self) -> Result<SubjectId, SubjectError> {
|
||||||
|
self.try_into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn subject_parser_world(input: &str) -> IResult<&str, RawSubject> {
|
fn subject_parser_world(input: &str) -> IResult<&str, RawSubject> {
|
||||||
|
|
@ -266,7 +271,7 @@ impl RawEventType {
|
||||||
pub fn tag(self) -> &'static str {
|
pub fn tag(self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
RawEventType::JoinedTeam => r#"joined team"#,
|
RawEventType::JoinedTeam => r#"joined team"#,
|
||||||
RawEventType::ChangedRole => r#"changed role to"#,
|
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""#,
|
||||||
RawEventType::Damage => r#"triggered "damage""#,
|
RawEventType::Damage => r#"triggered "damage""#,
|
||||||
|
|
@ -277,7 +282,7 @@ impl RawEventType {
|
||||||
RawEventType::Suicide => r#"committed suicide"#,
|
RawEventType::Suicide => r#"committed suicide"#,
|
||||||
RawEventType::Domination => r#"triggered "domination""#,
|
RawEventType::Domination => r#"triggered "domination""#,
|
||||||
RawEventType::Revenge => r#"triggered "revenge""#,
|
RawEventType::Revenge => r#"triggered "revenge""#,
|
||||||
RawEventType::Spawned => r#"spawned as"#,
|
RawEventType::Spawned => r#"spawned"#,
|
||||||
RawEventType::SayTeam => r#"say_team"#,
|
RawEventType::SayTeam => r#"say_team"#,
|
||||||
RawEventType::Say => r#"say"#,
|
RawEventType::Say => r#"say"#,
|
||||||
RawEventType::EmptyUber => r#"triggered "empty_uber""#,
|
RawEventType::EmptyUber => r#"triggered "empty_uber""#,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue