mirror of
https://github.com/eigenein/wotbreplay-parser.git
synced 2026-10-23 19:29:48 +02:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
632f1781e7 | ||
|
|
fa6ac70d21 | ||
|
|
1fb4bea267 |
No files matched your search
@@ -43,17 +43,11 @@ jobs:
|
|||||||
command: test
|
command: test
|
||||||
args: --all-targets
|
args: --all-targets
|
||||||
|
|
||||||
- name: 🧪 Test all features
|
- name: 🧪 Test
|
||||||
uses: actions-rs/cargo@v1
|
uses: actions-rs/cargo@v1
|
||||||
with:
|
with:
|
||||||
command: test
|
command: test
|
||||||
args: --all-targets --all-features
|
args: --all-features
|
||||||
|
|
||||||
- name: 🧪 Test docs
|
|
||||||
uses: actions-rs/cargo@v1
|
|
||||||
with:
|
|
||||||
command: test
|
|
||||||
args: --doc --all-features
|
|
||||||
|
|
||||||
- name: 🪄 Clippy
|
- name: 🪄 Clippy
|
||||||
uses: actions-rs/clippy-check@v1
|
uses: actions-rs/clippy-check@v1
|
||||||
|
|||||||
@@ -18,20 +18,20 @@ use wotbreplay_parser::models::battle_results::TeamNumber;
|
|||||||
use wotbreplay_parser::replay::Replay;
|
use wotbreplay_parser::replay::Replay;
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
let battle_results = Replay::open(File::open("tests/replays/battle_results.wotbreplay")?)?
|
let battle_results = Replay::open(File::open("tests/replays/player_results.wotbreplay")?)?
|
||||||
.read_battle_results()?;
|
.read_battle_results()?;
|
||||||
|
|
||||||
assert_eq!(battle_results.timestamp, 1670018359);
|
assert_eq!(battle_results.timestamp, 1670083956);
|
||||||
assert_eq!(battle_results.players.len(), 14);
|
assert_eq!(battle_results.players.len(), 14);
|
||||||
|
|
||||||
assert_eq!(battle_results.players[0].account_id, 520886428);
|
assert_eq!(battle_results.players[0].account_id, 595693744);
|
||||||
assert_eq!(battle_results.players[0].info.nickname, "77mmmr");
|
assert_eq!(battle_results.players[0].info.nickname, "yuranhik_hustriy26");
|
||||||
assert_eq!(battle_results.players[0].info.team(), TeamNumber::Two);
|
assert_eq!(battle_results.players[0].info.team(), TeamNumber::One);
|
||||||
assert_eq!(battle_results.players[0].info.platoon_id, None);
|
assert_eq!(battle_results.players[0].info.platoon_id, Some(545104609));
|
||||||
|
|
||||||
assert_eq!(battle_results.players[1].info.nickname, "SNAK_THE_RIPPER");
|
assert_eq!(battle_results.players[1].info.nickname, "SNAK_THE_RIPPER");
|
||||||
assert_eq!(battle_results.players[1].info.team(), TeamNumber::One);
|
assert_eq!(battle_results.players[1].info.team(), TeamNumber::Two);
|
||||||
assert_eq!(battle_results.players[1].info.platoon_id, Some(547466834));
|
assert_eq!(battle_results.players[1].info.platoon_id, Some(273692628));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -6,10 +6,10 @@ pub enum Error {
|
|||||||
ZipError(#[from] zip::result::ZipError),
|
ZipError(#[from] zip::result::ZipError),
|
||||||
|
|
||||||
#[error("Protocol Buffers error")]
|
#[error("Protocol Buffers error")]
|
||||||
DecodeFailed(#[from] prost::DecodeError),
|
ProtobufError(#[from] prost::DecodeError),
|
||||||
|
|
||||||
#[error("Pickle error")]
|
#[error("Pickle error")]
|
||||||
UnpickleFailed(#[from] serde_pickle::Error),
|
PickleError(#[from] serde_pickle::Error),
|
||||||
|
|
||||||
#[error("I/O error")]
|
#[error("I/O error")]
|
||||||
IoError(#[from] std::io::Error),
|
IoError(#[from] std::io::Error),
|
||||||
@@ -19,7 +19,7 @@ pub enum Error {
|
|||||||
|
|
||||||
#[cfg(feature = "meta")]
|
#[cfg(feature = "meta")]
|
||||||
#[error("JSON error")]
|
#[error("JSON error")]
|
||||||
JsonDecodeFailed(#[from] serde_json::Error),
|
JsonError(#[from] serde_json::Error),
|
||||||
|
|
||||||
#[error("invalid magic: {0:#X}, expected: {1:#X}")]
|
#[error("invalid magic: {0:#X}, expected: {1:#X}")]
|
||||||
InvalidMagic(u32, u32),
|
InvalidMagic(u32, u32),
|
||||||
|
|||||||
+1
-1
@@ -52,7 +52,7 @@ impl Data {
|
|||||||
let Some(packet) = Packet::from_reader(&mut reader)? else { break };
|
let Some(packet) = Packet::from_reader(&mut reader)? else { break };
|
||||||
match packet.payload {
|
match packet.payload {
|
||||||
Payload::ReplayHeader(header) => {
|
Payload::ReplayHeader(header) => {
|
||||||
this.replay_header = Some(header);
|
this.replay_header = Some(*header);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
this.other_packets.push(packet);
|
this.other_packets.push(packet);
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ pub enum EntityMethod {
|
|||||||
Unknown {
|
Unknown {
|
||||||
sub_type: u32,
|
sub_type: u32,
|
||||||
|
|
||||||
|
/// Whole packet payload (including the sub-type).
|
||||||
#[serde_as(as = "serde_with::hex::Hex")]
|
#[serde_as(as = "serde_with::hex::Hex")]
|
||||||
payload: Vec<u8>,
|
payload: Vec<u8>,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,11 +11,17 @@ use crate::result::Result;
|
|||||||
#[serde_as]
|
#[serde_as]
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
pub enum Payload {
|
pub enum Payload {
|
||||||
ReplayHeader(ReplayHeader),
|
ReplayHeader(Box<ReplayHeader>),
|
||||||
EntityMethod(EntityMethod),
|
EntityMethod(EntityMethod),
|
||||||
|
|
||||||
/// Default payload when type is not known.
|
/// Default payload when type is not known.
|
||||||
Unknown(#[serde_as(as = "serde_with::hex::Hex")] Vec<u8>),
|
Unknown {
|
||||||
|
type_: u32,
|
||||||
|
|
||||||
|
/// Whole packet payload.
|
||||||
|
#[serde_as(as = "serde_with::hex::Hex")]
|
||||||
|
raw: Vec<u8>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Payload {
|
impl Payload {
|
||||||
@@ -34,17 +40,20 @@ impl Payload {
|
|||||||
assert_magic(reader.read_u8()?, 0x00)?;
|
assert_magic(reader.read_u8()?, 0x00)?;
|
||||||
read_pickled(&mut reader, pickled_length as usize)?
|
read_pickled(&mut reader, pickled_length as usize)?
|
||||||
};
|
};
|
||||||
Self::ReplayHeader(ReplayHeader {
|
Self::ReplayHeader(Box::new(ReplayHeader {
|
||||||
summary,
|
summary,
|
||||||
author_nickname,
|
author_nickname,
|
||||||
arena_unique_id,
|
arena_unique_id,
|
||||||
arena_type_id,
|
arena_type_id,
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
8 => Self::EntityMethod(EntityMethod::new(payload)?),
|
8 => Self::EntityMethod(EntityMethod::new(payload)?),
|
||||||
|
|
||||||
_ => Self::Unknown(payload),
|
_ => Self::Unknown {
|
||||||
|
raw: payload,
|
||||||
|
type_,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
Ok(this)
|
Ok(this)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,24 +4,69 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct Summary {
|
pub struct Summary {
|
||||||
#[serde(rename = "playersBattleCategoriesIds")]
|
#[serde(rename(deserialize = "playersBattleCategoriesIds"))]
|
||||||
pub players_battle_categories_ids: HashMap<u32, (u8, u32)>,
|
pub players_battle_categories_ids: HashMap<u32, (u8, u32)>,
|
||||||
|
|
||||||
#[serde(rename = "battleLevel")]
|
#[serde(rename(deserialize = "battleLevel"))]
|
||||||
pub battle_level: u8,
|
pub battle_level: u8,
|
||||||
|
|
||||||
#[serde(rename = "battleCategoryId")]
|
#[serde(rename(deserialize = "battleCategoryId"))]
|
||||||
pub battle_category_id: u8,
|
pub battle_category_id: u8,
|
||||||
|
|
||||||
#[serde(rename = "mouseEnabled")]
|
#[serde(rename(deserialize = "mouseEnabled"))]
|
||||||
pub is_mouse_enabled: bool,
|
pub is_mouse_enabled: bool,
|
||||||
|
|
||||||
#[serde(rename = "mmType")]
|
#[serde(rename(deserialize = "mmType"))]
|
||||||
pub matchmaker_type: u8,
|
pub matchmaker_type: u8,
|
||||||
|
|
||||||
#[serde(rename = "camouflageSlot")]
|
#[serde(rename(deserialize = "camouflageSlot"))]
|
||||||
pub camouflage_slot: u8,
|
pub camouflage_slot: u8,
|
||||||
|
|
||||||
#[serde(rename = "avgMmr")]
|
#[serde(rename(deserialize = "avgMmr"))]
|
||||||
pub average_mmr: Vec<f64>,
|
pub average_mmr: Vec<Option<f64>>,
|
||||||
|
|
||||||
|
#[serde(rename(deserialize = "playerWaitTimes"))]
|
||||||
|
pub player_wait_times: HashMap<u32, f64>,
|
||||||
|
|
||||||
|
#[serde(rename(deserialize = "accountDatabaseIds"))]
|
||||||
|
pub account_database_ids: Vec<u32>,
|
||||||
|
|
||||||
|
#[serde(rename(deserialize = "turboBattlesStats"))]
|
||||||
|
pub turbo_battles_statistics: TurboBattlesStatistics,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct TurboBattlesStatistics {
|
||||||
|
#[serde(rename(deserialize = "turboBattleChance"))]
|
||||||
|
pub battle_chance: f64,
|
||||||
|
|
||||||
|
#[serde(rename(deserialize = "turboLeaveChance"))]
|
||||||
|
pub leave_chance: f64,
|
||||||
|
|
||||||
|
#[serde(rename(deserialize = "possibleTurboBattlesNotForSkip"))]
|
||||||
|
pub possible_battles_not_for_skip: u32,
|
||||||
|
|
||||||
|
#[serde(rename(deserialize = "possibleTurboBattlesForSkip"))]
|
||||||
|
pub possible_battles_for_skip: u32,
|
||||||
|
|
||||||
|
#[serde(rename(deserialize = "turboBattlesForSkip"))]
|
||||||
|
pub battles_for_skip: u32,
|
||||||
|
|
||||||
|
#[serde(rename(deserialize = "turboBattlesNotForSkip"))]
|
||||||
|
pub battles_not_for_skip: u32,
|
||||||
|
|
||||||
|
#[serde(rename(deserialize = "abSkip"))]
|
||||||
|
pub ab_skip: i32,
|
||||||
|
|
||||||
|
#[serde(rename(deserialize = "beta"))]
|
||||||
|
pub beta: f64,
|
||||||
|
|
||||||
|
#[serde(rename(deserialize = "premiumVehDiff"))]
|
||||||
|
pub premium_vehicle_difference: i32,
|
||||||
|
|
||||||
|
#[serde(rename(deserialize = "htDiff"))]
|
||||||
|
pub ht_difference: i32,
|
||||||
|
|
||||||
|
#[serde(rename(deserialize = "alpha"))]
|
||||||
|
pub alpha: f64,
|
||||||
}
|
}
|
||||||
+6
-14
@@ -12,7 +12,13 @@ fn player_results_ok() -> Result<()> {
|
|||||||
let battle_results: BattleResults = battle_results_dat.try_into()?;
|
let battle_results: BattleResults = battle_results_dat.try_into()?;
|
||||||
|
|
||||||
assert_eq!(battle_results.winner_team_number, 2);
|
assert_eq!(battle_results.winner_team_number, 2);
|
||||||
|
|
||||||
assert_eq!(battle_results.author.team_number, 2);
|
assert_eq!(battle_results.author.team_number, 2);
|
||||||
|
assert_eq!(battle_results.author.credits_earned, 59518);
|
||||||
|
assert_eq!(battle_results.author.combat_xp, 5255);
|
||||||
|
assert_eq!(battle_results.author.damage_dealt, 1438);
|
||||||
|
assert_eq!(battle_results.author.account_id, 594778041);
|
||||||
|
assert_eq!(battle_results.free_xp, 260);
|
||||||
|
|
||||||
let snak_the_ripper_info = &battle_results.player_results[3].info;
|
let snak_the_ripper_info = &battle_results.player_results[3].info;
|
||||||
assert_eq!(snak_the_ripper_info.base_xp, 929);
|
assert_eq!(snak_the_ripper_info.base_xp, 929);
|
||||||
@@ -111,17 +117,3 @@ fn victory_points_ok() -> Result<()> {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn author_results_ok() -> Result<()> {
|
|
||||||
let battle_results = Replay::open(File::open("tests/replays/author_results.wotbreplay")?)?
|
|
||||||
.read_battle_results()?;
|
|
||||||
|
|
||||||
assert_eq!(battle_results.author.credits_earned, 53623);
|
|
||||||
assert_eq!(battle_results.author.combat_xp, 2370);
|
|
||||||
assert_eq!(battle_results.author.damage_dealt, 1738);
|
|
||||||
assert_eq!(battle_results.author.account_id, 594778041);
|
|
||||||
assert_eq!(battle_results.free_xp, 116);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
+17
-8
@@ -5,22 +5,31 @@ use wotbreplay_parser::replay::Replay;
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn data_ok() -> Result<()> {
|
fn data_ok() -> Result<()> {
|
||||||
let mut replay = Replay::open(File::open("tests/replays/player_results.wotbreplay")?)?;
|
let mut replay = Replay::open(File::open(
|
||||||
|
"tests/replays/20230429_0126__helaas_pindakaas_A140_ASTRON_REX_105_16114615898101270.wotbreplay",
|
||||||
|
)?)?;
|
||||||
let data = replay.read_data()?;
|
let data = replay.read_data()?;
|
||||||
|
|
||||||
assert_eq!(data.client_version, "9.4.0_apple");
|
assert_eq!(data.client_version, "9.8.5_apple");
|
||||||
assert_eq!(data.other_packets.len(), 44720);
|
assert_eq!(data.other_packets.len(), 60138);
|
||||||
|
|
||||||
let header = data.replay_header.unwrap();
|
let header = data.replay_header.unwrap();
|
||||||
assert_eq!(header.author_nickname, "zeekrab");
|
assert_eq!(header.author_nickname, "helaas_pindakaas");
|
||||||
assert_eq!(header.arena_unique_id, 1661909200500084);
|
assert_eq!(header.arena_unique_id, 16114615898101270);
|
||||||
assert_eq!(header.arena_type_id, 65567);
|
assert_eq!(header.arena_type_id, 43);
|
||||||
assert_eq!(header.summary.battle_level, 8);
|
assert_eq!(header.summary.battle_level, 9);
|
||||||
assert_eq!(header.summary.battle_category_id, 13);
|
assert_eq!(header.summary.battle_category_id, 13);
|
||||||
assert!(header.summary.is_mouse_enabled);
|
assert!(header.summary.is_mouse_enabled);
|
||||||
assert_eq!(header.summary.matchmaker_type, 2);
|
assert_eq!(header.summary.matchmaker_type, 2);
|
||||||
assert_eq!(header.summary.camouflage_slot, 1);
|
assert_eq!(header.summary.camouflage_slot, 1);
|
||||||
assert_eq!(header.summary.average_mmr, [-25.396859946846963, 77.58806455880404]);
|
assert_eq!(header.summary.average_mmr, [Some(59.29457753400008), Some(99.34182121604681)]);
|
||||||
|
assert_eq!(
|
||||||
|
header.summary.account_database_ids,
|
||||||
|
[
|
||||||
|
517033644, 537867068, 597583401, 601893865, 576810156, 531053956, 599580824, 558025185,
|
||||||
|
526927603, 594778041, 505587490, 597422303, 531923111, 587617355
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Generated
BIN
Binary file not shown.
Reference in new issue
Block a user