mirror of
https://github.com/eigenein/wotbreplay-parser.git
synced 2026-10-21 10:27:01 +02:00
Compare commits
22
Commits
0.1.0
...
0.2.0-alpha.7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2fb61425a | ||
|
|
93cea446f5 | ||
|
|
8d45bb28ed | ||
|
|
1e0ce05c18 | ||
|
|
f63ba599ec | ||
|
|
f619ffd93e | ||
|
|
7d99456aaa | ||
|
|
be4a6c21b5 | ||
|
|
805a2af81b | ||
|
|
899456eaf7 | ||
|
|
96e63f81f4 | ||
|
|
5786253cd5 | ||
|
|
e1f38014b8 | ||
|
|
7376cfc97e | ||
|
|
bc3b39e764 | ||
|
|
4edcc50a87 | ||
|
|
bccb5b519e | ||
|
|
ac086b1eb2 | ||
|
|
68e00c5eca | ||
|
|
6fb70da06f | ||
|
|
679b0ddadf | ||
|
|
21206737c0 |
No files matched your search
@@ -0,0 +1,5 @@
|
||||
github: [eigenein]
|
||||
custom:
|
||||
- 'https://www.paypal.me/eigenein'
|
||||
- 'https://bunq.me/eigenein'
|
||||
- 'https://money.yandex.ru/to/410011693851843'
|
||||
@@ -42,7 +42,6 @@ jobs:
|
||||
with:
|
||||
release_name: ${{ github.ref_name }}
|
||||
body: ${{ steps.changelog.outputs.changelog }}
|
||||
prerelease: false
|
||||
|
||||
- name: Publish the crates
|
||||
run: |
|
||||
|
||||
+3
-2
@@ -7,14 +7,15 @@ authors = ["Pavel Perestoronin <[email protected]>"]
|
||||
readme = "README.md"
|
||||
repository = "https://github.com/eigenein/wotbreplay-parser"
|
||||
license = "MIT"
|
||||
keywords = []
|
||||
categories = []
|
||||
keywords = ["world-of-tanks-blitz", "replay", "parser", "wargaming", "results"]
|
||||
categories = ["parsing"]
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
[dependencies]
|
||||
prost = "0.11.3"
|
||||
serde = { version = "1.0.148", features = ["derive"] }
|
||||
serde_bytes = "0.11.7"
|
||||
serde-pickle = "1.1.1"
|
||||
thiserror = "1.0.37"
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Pavel Perestoronin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -8,6 +8,35 @@ World of Tanks Blitz replay parser in Rust.
|
||||

|
||||
[](https://docs.rs/wotbreplay-parser)
|
||||
|
||||
## Quickstart
|
||||
|
||||
```rust
|
||||
use std::fs::File;
|
||||
|
||||
use anyhow::Result;
|
||||
use wotbreplay_parser::Replay;
|
||||
use wotbreplay_parser::models::TeamNumber;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let battle_results = Replay::open(File::open("tests/replays/battle_results.wotbreplay")?)?
|
||||
.read_battle_results()?;
|
||||
|
||||
assert_eq!(battle_results.timestamp, 1670018359);
|
||||
assert_eq!(battle_results.players.len(), 14);
|
||||
|
||||
assert_eq!(battle_results.players[0].account_id, 520886428);
|
||||
assert_eq!(battle_results.players[0].info.nickname, "77mmmr");
|
||||
assert_eq!(battle_results.players[0].info.team(), TeamNumber::Two);
|
||||
assert_eq!(battle_results.players[0].info.platoon_id, None);
|
||||
|
||||
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.platoon_id, Some(547466834));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
## Replay structure
|
||||
|
||||
`*.wotbreplay` is a ZIP-archive containing:
|
||||
|
||||
+24
@@ -1,3 +1,15 @@
|
||||
//! World of Tanks Blitz replay parser.
|
||||
|
||||
#![warn(
|
||||
clippy::all,
|
||||
clippy::missing_const_for_fn,
|
||||
clippy::trivially_copy_pass_by_ref,
|
||||
clippy::map_unwrap_or,
|
||||
clippy::explicit_into_iter_loop,
|
||||
clippy::unused_self,
|
||||
clippy::needless_pass_by_value
|
||||
)]
|
||||
|
||||
mod error;
|
||||
pub mod models;
|
||||
mod replay;
|
||||
@@ -6,3 +18,15 @@ mod result;
|
||||
pub use crate::error::Error;
|
||||
pub use crate::replay::Replay;
|
||||
pub use crate::result::Result;
|
||||
|
||||
#[cfg(doctest)]
|
||||
mod test_readme {
|
||||
macro_rules! external_doc_test {
|
||||
($x:expr) => {
|
||||
#[doc = $x]
|
||||
extern "C" {}
|
||||
};
|
||||
}
|
||||
|
||||
external_doc_test!(include_str!("../README.md"));
|
||||
}
|
||||
+4
-30
@@ -1,31 +1,5 @@
|
||||
use ::prost::Message;
|
||||
mod battle_results;
|
||||
mod battle_results_dat;
|
||||
|
||||
#[derive(Message)]
|
||||
pub struct BattleResults {
|
||||
#[prost(int64, tag = "2")]
|
||||
pub timestamp: i64,
|
||||
|
||||
#[prost(message, repeated, tag = "201")]
|
||||
pub players: Vec<Player>,
|
||||
}
|
||||
|
||||
#[derive(Message)]
|
||||
pub struct Player {
|
||||
#[prost(uint32, tag = "1")]
|
||||
pub account_id: u32,
|
||||
|
||||
#[prost(message, required, tag = "2")]
|
||||
pub info: PlayerInfo,
|
||||
}
|
||||
|
||||
#[derive(Message)]
|
||||
pub struct PlayerInfo {
|
||||
#[prost(string, tag = "1")]
|
||||
pub nickname: String,
|
||||
|
||||
#[prost(uint32, optional, tag = "2")]
|
||||
pub platoon_id: Option<u32>,
|
||||
|
||||
#[prost(uint32, tag = "3")]
|
||||
pub team_number: u32,
|
||||
}
|
||||
pub use self::battle_results::*;
|
||||
pub use self::battle_results_dat::*;
|
||||
@@ -0,0 +1,190 @@
|
||||
use prost::bytes::Buf;
|
||||
use prost::Message;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::result::Result;
|
||||
|
||||
impl BattleResults {
|
||||
/// Parse battle results from the buffer.
|
||||
///
|
||||
/// Note, that this does NOT parse `battle_results.dat` itself, but the un-pickled tuple element.
|
||||
pub fn parse(buffer: impl Buf) -> Result<Self> {
|
||||
Self::decode(buffer).map_err(Error::DecodeFailed)
|
||||
}
|
||||
}
|
||||
|
||||
/// Parsed battle results.
|
||||
#[derive(Message, Serialize)]
|
||||
pub struct BattleResults {
|
||||
/// Battle timestamp.
|
||||
#[prost(int64, tag = "2")]
|
||||
pub timestamp: i64,
|
||||
|
||||
#[prost(enumeration = "TeamNumber", tag = "3")]
|
||||
pub winning_team: i32,
|
||||
|
||||
/// Replay's author results.
|
||||
#[prost(message, required, tag = "8")]
|
||||
pub author_results: AuthorResults,
|
||||
|
||||
/// Author's free XP, including premium.
|
||||
#[prost(uint32, tag = "137")]
|
||||
pub free_xp: u32,
|
||||
|
||||
/// Players in the battle.
|
||||
#[prost(message, repeated, tag = "201")]
|
||||
pub players: Vec<Player>,
|
||||
|
||||
/// Player's results.
|
||||
#[prost(message, repeated, tag = "301")]
|
||||
pub player_results: Vec<PlayerResults>,
|
||||
}
|
||||
|
||||
/// Battle player.
|
||||
#[derive(Message, Serialize)]
|
||||
pub struct Player {
|
||||
/// Player's account ID.
|
||||
#[prost(uint32, tag = "1")]
|
||||
pub account_id: u32,
|
||||
|
||||
/// Player's extended information.
|
||||
#[prost(message, required, tag = "2")]
|
||||
pub info: PlayerInfo,
|
||||
}
|
||||
|
||||
/// Player's extended information.
|
||||
#[derive(Message, Serialize)]
|
||||
pub struct PlayerInfo {
|
||||
/// Player's nickname.
|
||||
#[prost(string, tag = "1")]
|
||||
pub nickname: String,
|
||||
|
||||
/// Some sort of platoon ID:
|
||||
/// - contains same ID for a platoon members, or
|
||||
/// - `None` for non-platoon players
|
||||
#[prost(uint32, optional, tag = "2")]
|
||||
pub platoon_id: Option<u32>,
|
||||
|
||||
/// Player's team assignment.
|
||||
#[prost(enumeration = "TeamNumber", tag = "3")]
|
||||
pub team: i32,
|
||||
|
||||
#[prost(string, optional, tag = "5")]
|
||||
pub clan_tag: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, prost::Enumeration, Serialize,
|
||||
)]
|
||||
#[repr(i32)]
|
||||
pub enum TeamNumber {
|
||||
One = 1,
|
||||
Two = 2,
|
||||
}
|
||||
|
||||
/// Player's battle results.
|
||||
#[derive(Message, Serialize)]
|
||||
pub struct PlayerResults {
|
||||
/// Looks like some sort of sequential result ID. They reference each other,
|
||||
/// but I haven't figured this out yet.
|
||||
#[prost(uint32, tag = "1")]
|
||||
pub result_id: u32,
|
||||
|
||||
/// Extended player's results information.
|
||||
#[prost(message, required, tag = "2")]
|
||||
pub info: PlayerResultsInfo,
|
||||
}
|
||||
|
||||
/// Extended player's results information.
|
||||
#[derive(Message, Serialize)]
|
||||
pub struct PlayerResultsInfo {
|
||||
/// Credits earned – without special awards and medals and premium account excluded.
|
||||
#[prost(uint32, tag = "2")]
|
||||
pub credits_earned: u32,
|
||||
|
||||
/// Base XP (the total without multipliers).
|
||||
#[prost(uint32, tag = "3")]
|
||||
pub base_xp: u32,
|
||||
|
||||
#[prost(uint32, tag = "4")]
|
||||
pub n_shots: u32,
|
||||
|
||||
#[prost(uint32, tag = "5")]
|
||||
pub n_hits_dealt: u32,
|
||||
|
||||
#[prost(uint32, tag = "7")]
|
||||
pub n_penetrations_dealt: u32,
|
||||
|
||||
#[prost(uint32, tag = "8")]
|
||||
pub damage_dealt: u32,
|
||||
|
||||
/// TODO: distinguish the kinds of assisted damage.
|
||||
#[prost(uint32, tag = "9")]
|
||||
pub damage_assisted_1: u32,
|
||||
|
||||
/// TODO: distinguish the kinds of assisted damage.
|
||||
#[prost(uint32, tag = "10")]
|
||||
pub damage_assisted_2: u32,
|
||||
|
||||
#[prost(uint32, tag = "12")]
|
||||
pub n_hits_received: u32,
|
||||
|
||||
#[prost(uint32, tag = "13")]
|
||||
pub n_non_penetrating_hits_received: u32,
|
||||
|
||||
#[prost(uint32, tag = "15")]
|
||||
pub n_penetrations_received: u32,
|
||||
|
||||
#[prost(uint32, tag = "17")]
|
||||
pub n_enemies_damaged: u32,
|
||||
|
||||
#[prost(uint32, tag = "18")]
|
||||
pub n_enemies_destroyed: u32,
|
||||
|
||||
#[prost(uint32, tag = "32")]
|
||||
pub victory_points_earned: u32,
|
||||
|
||||
#[prost(uint32, tag = "33")]
|
||||
pub victory_points_seized: u32,
|
||||
|
||||
/// Player's account ID.
|
||||
#[prost(uint32, tag = "101")]
|
||||
pub account_id: u32,
|
||||
|
||||
/// Player's tank ID as per Wargaming.net API.
|
||||
#[prost(uint32, tag = "103")]
|
||||
pub tank_id: u32,
|
||||
|
||||
/// Rating for the Rating Battles.
|
||||
///
|
||||
/// Note, that this is **not** the game client's displayed rating.
|
||||
/// This field matches the `mm_rating` as returned by the Wargaming.net API.
|
||||
#[prost(float, optional, tag = "107")]
|
||||
pub mm_rating: Option<f32>,
|
||||
|
||||
#[prost(uint32, tag = "117")]
|
||||
pub damage_blocked: u32,
|
||||
}
|
||||
|
||||
impl PlayerResultsInfo {
|
||||
/// Returns displayed rating as per the game client.
|
||||
pub fn display_rating(&self) -> Option<u32> {
|
||||
self.mm_rating
|
||||
.map(|mm_rating| (mm_rating * 10.0 + 3000.0) as u32)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Message, Serialize)]
|
||||
pub struct AuthorResults {
|
||||
/// Earned credits, including premium and special awards and medals.
|
||||
#[prost(uint32, tag = "2")]
|
||||
pub credits_earned: u32,
|
||||
|
||||
/// Combat XP, including premium.
|
||||
#[prost(uint32, tag = "3")]
|
||||
pub combat_xp: u32,
|
||||
|
||||
#[prost(uint32, tag = "8")]
|
||||
pub damage_dealt: u32,
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
use std::io::Read;
|
||||
|
||||
use prost::Message;
|
||||
use serde::Deserialize;
|
||||
use serde_bytes::ByteBuf;
|
||||
|
||||
use crate::models::BattleResults;
|
||||
use crate::{Error, Result};
|
||||
|
||||
/// Represents un-pickled `battle_results.dat`.
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct BattleResultsDat(
|
||||
/// No idea what this is.
|
||||
/// My best guess – some kind of checksum,
|
||||
/// but none of MD5, SHA1, SHA224, SHA256, SHA384, SHA512, nor CRC64 over the buffer have matched.
|
||||
pub u64,
|
||||
/// Protobuf-serialized battle results.
|
||||
pub ByteBuf,
|
||||
);
|
||||
|
||||
impl BattleResultsDat {
|
||||
/// Parses the pickled structure from the reader which contains `battle_results.dat`.
|
||||
pub fn from_reader(reader: impl Read) -> Result<Self> {
|
||||
serde_pickle::from_reader(reader, Default::default()).map_err(Error::UnpickleFailed)
|
||||
}
|
||||
|
||||
/// Decodes the battle results from the internal buffer.
|
||||
pub fn decode_battle_results(&self) -> Result<BattleResults> {
|
||||
BattleResults::decode(self.1.as_ref()).map_err(Error::DecodeFailed)
|
||||
}
|
||||
}
|
||||
+11
-13
@@ -1,35 +1,33 @@
|
||||
use std::io::{Read, Seek};
|
||||
|
||||
use prost::Message;
|
||||
use serde_bytes::ByteBuf;
|
||||
use zip::ZipArchive;
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::models::BattleResults;
|
||||
use crate::models::{BattleResults, BattleResultsDat};
|
||||
use crate::result::Result;
|
||||
|
||||
/// Opened (but not yet parsed) replay.
|
||||
pub struct Replay<R>(pub(crate) ZipArchive<R>);
|
||||
|
||||
impl<R: Read + Seek> Replay<R> {
|
||||
/// Opens a replay from the reader.
|
||||
/// Opens a replay from the reader which contains a `*.wotbreplay`.
|
||||
pub fn open(reader: R) -> Result<Self> {
|
||||
ZipArchive::new(reader)
|
||||
.map_err(Error::OpenArchiveFailed)
|
||||
.map(Self)
|
||||
}
|
||||
|
||||
/// Reads and parses the battle results from the replay.
|
||||
pub fn read_battle_results(&mut self) -> Result<BattleResults> {
|
||||
let mut pickled_battle_results = self
|
||||
self.read_battle_results_dat()?.decode_battle_results()
|
||||
}
|
||||
|
||||
/// Reads and parses the included `battle_results.dat`.
|
||||
pub fn read_battle_results_dat(&mut self) -> Result<BattleResultsDat> {
|
||||
let pickled_battle_results = self
|
||||
.0
|
||||
.by_name("battle_results.dat")
|
||||
.map_err(Error::OpenBattleResultsFailed)?;
|
||||
let mut serialized_battle_results = Vec::new();
|
||||
pickled_battle_results
|
||||
.read_to_end(&mut serialized_battle_results)
|
||||
.map_err(Error::ReadEntryFailed)?;
|
||||
let (_, battle_results): (u64, ByteBuf) =
|
||||
serde_pickle::from_slice(&serialized_battle_results, Default::default())
|
||||
.map_err(Error::UnpickleFailed)?;
|
||||
BattleResults::decode(battle_results.as_ref()).map_err(Error::DecodeFailed)
|
||||
BattleResultsDat::from_reader(pickled_battle_results)
|
||||
}
|
||||
}
|
||||
+108
-14
@@ -1,26 +1,120 @@
|
||||
use std::fs::File;
|
||||
|
||||
use anyhow::Result;
|
||||
use wotbreplay_parser::models::TeamNumber;
|
||||
use wotbreplay_parser::Replay;
|
||||
|
||||
#[test]
|
||||
fn battle_results_ok() -> Result<()> {
|
||||
let mut replay = Replay::open(File::open(
|
||||
"tests/replays/20221202_2259__zeekrab_It20_Car_Comb_45t_2308705958773814583.wotbreplay",
|
||||
)?)?;
|
||||
let battle_results = replay.read_battle_results()?;
|
||||
fn player_results_ok() -> Result<()> {
|
||||
let battle_results = Replay::open(File::open("tests/replays/player_results.wotbreplay")?)?
|
||||
.read_battle_results()?;
|
||||
|
||||
assert_eq!(battle_results.timestamp, 1670018359);
|
||||
assert_eq!(battle_results.players.len(), 14);
|
||||
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.damage_dealt, 2584);
|
||||
assert_eq!(snak_the_ripper_info.damage_assisted_1, 37);
|
||||
assert_eq!(snak_the_ripper_info.account_id, 566225799);
|
||||
assert_eq!(snak_the_ripper_info.display_rating(), Some(4070));
|
||||
assert_eq!(snak_the_ripper_info.n_shots, 6);
|
||||
assert_eq!(snak_the_ripper_info.n_hits_dealt, 5);
|
||||
assert_eq!(snak_the_ripper_info.n_penetrations_dealt, 5);
|
||||
assert_eq!(snak_the_ripper_info.tank_id, 5233);
|
||||
assert_eq!(snak_the_ripper_info.n_enemies_damaged, 3);
|
||||
assert_eq!(snak_the_ripper_info.n_enemies_destroyed, 2);
|
||||
|
||||
assert_eq!(battle_results.players[0].account_id, 520886428);
|
||||
assert_eq!(battle_results.players[0].info.nickname, "77mmmr");
|
||||
assert_eq!(battle_results.players[0].info.team_number, 2);
|
||||
assert_eq!(battle_results.players[0].info.platoon_id, None);
|
||||
let zeekrab_info = &battle_results.player_results[10].info;
|
||||
assert_eq!(zeekrab_info.base_xp, 701);
|
||||
assert_eq!(zeekrab_info.damage_dealt, 1438);
|
||||
assert_eq!(zeekrab_info.damage_assisted_2, 31);
|
||||
assert_eq!(zeekrab_info.damage_blocked, 190);
|
||||
assert_eq!(zeekrab_info.account_id, 594778041);
|
||||
assert_eq!(zeekrab_info.display_rating(), Some(4277));
|
||||
assert_eq!(zeekrab_info.n_shots, 5);
|
||||
assert_eq!(zeekrab_info.n_hits_dealt, 5);
|
||||
assert_eq!(zeekrab_info.n_penetrations_dealt, 5);
|
||||
assert_eq!(zeekrab_info.n_hits_received, 3);
|
||||
assert_eq!(zeekrab_info.n_penetrations_received, 3);
|
||||
assert_eq!(zeekrab_info.n_non_penetrating_hits_received, 0);
|
||||
assert_eq!(zeekrab_info.victory_points_earned, 40);
|
||||
assert_eq!(zeekrab_info.victory_points_seized, 40);
|
||||
assert_eq!(zeekrab_info.tank_id, 26657);
|
||||
assert_eq!(zeekrab_info.credits_earned, 37679);
|
||||
assert_eq!(zeekrab_info.n_enemies_damaged, 2);
|
||||
assert_eq!(zeekrab_info.n_enemies_destroyed, 1);
|
||||
|
||||
assert_eq!(battle_results.players[1].info.nickname, "SNAK_THE_RIPPER");
|
||||
assert_eq!(battle_results.players[1].info.team_number, 1);
|
||||
assert_eq!(battle_results.players[1].info.platoon_id, Some(547466834));
|
||||
let balls_soup_info = &battle_results.player_results[8].info;
|
||||
assert_eq!(balls_soup_info.damage_dealt, 2064);
|
||||
assert_eq!(balls_soup_info.display_rating(), None);
|
||||
assert_eq!(balls_soup_info.n_shots, 9);
|
||||
assert_eq!(balls_soup_info.n_hits_dealt, 8);
|
||||
assert_eq!(balls_soup_info.n_penetrations_dealt, 8);
|
||||
assert_eq!(balls_soup_info.n_hits_received, 6);
|
||||
assert_eq!(balls_soup_info.n_penetrations_received, 4);
|
||||
assert_eq!(balls_soup_info.n_non_penetrating_hits_received, 2);
|
||||
assert_eq!(balls_soup_info.tank_id, 4737);
|
||||
assert_eq!(balls_soup_info.n_enemies_damaged, 4);
|
||||
assert_eq!(balls_soup_info.n_enemies_destroyed, 1);
|
||||
|
||||
let ceaser_info = &battle_results.player_results[0].info;
|
||||
assert_eq!(ceaser_info.damage_dealt, 919);
|
||||
assert_eq!(ceaser_info.display_rating(), Some(4439));
|
||||
assert_eq!(ceaser_info.n_shots, 9);
|
||||
assert_eq!(ceaser_info.n_hits_dealt, 6);
|
||||
assert_eq!(ceaser_info.n_penetrations_dealt, 5);
|
||||
assert_eq!(ceaser_info.n_enemies_damaged, 3);
|
||||
assert_eq!(ceaser_info.n_enemies_destroyed, 0);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clan_tags_ok() -> Result<()> {
|
||||
let battle_results = Replay::open(File::open("tests/replays/player_results.wotbreplay")?)?
|
||||
.read_battle_results()?;
|
||||
|
||||
assert_eq!(battle_results.players[1].info.clan_tag.as_deref(), Some("AN0NY"));
|
||||
assert_eq!(battle_results.players[10].info.clan_tag.as_deref(), Some("BBS"));
|
||||
assert_eq!(battle_results.players[11].info.clan_tag, None);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn victory_points_ok() -> Result<()> {
|
||||
let battle_results = Replay::open(File::open("tests/replays/victory_points.wotbreplay")?)?
|
||||
.read_battle_results()?;
|
||||
|
||||
assert_eq!(battle_results.player_results[1].info.victory_points_seized, 40);
|
||||
assert_eq!(battle_results.player_results[1].info.victory_points_earned, 40);
|
||||
|
||||
assert_eq!(battle_results.player_results[3].info.victory_points_seized, 0);
|
||||
assert_eq!(battle_results.player_results[3].info.victory_points_earned, 112);
|
||||
|
||||
assert_eq!(battle_results.player_results[5].info.victory_points_earned, 280);
|
||||
assert_eq!(battle_results.player_results[5].info.victory_points_seized, 0);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn winning_team_ok() -> Result<()> {
|
||||
let battle_results = Replay::open(File::open("tests/replays/winning_team.wotbreplay")?)?
|
||||
.read_battle_results()?;
|
||||
|
||||
assert_eq!(battle_results.winning_team(), TeamNumber::One);
|
||||
|
||||
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_results.credits_earned, 53623);
|
||||
assert_eq!(battle_results.author_results.combat_xp, 2370);
|
||||
assert_eq!(battle_results.author_results.damage_dealt, 1738);
|
||||
assert_eq!(battle_results.free_xp, 116);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
*.wotbreplay linguist-generated
|
||||
Generated
BIN
Binary file not shown.
File renamed without changes.
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