A parser for .dat
battle result files generated by the game World of Tanks. .dat
files are generated whenever a battle's results are viewed in-game. For Windows, these files are found in a location like:
C:\Users\<YOUR_USER_NAME>\AppData\Roaming\Wargaming.net\WorldOfTanks\battle_results
The .dat
files are simply pickle dumps. In theory, this would mean that reading these files are as simple as opening these files using the pickle module in Python (v2.7). However, the problem is that there is no information on the identifiers of a field. This means that reading from the file directly gives you results like this:
python
[-43243256354, 1673683215, 70, 1]
This crate simply identifies the correct identifiers based on the checksum value (which is usualy the first item in a list of values like above) and converts the above into something like this:
json
{
"arenaCreateTime": 1673683215,
"arenaTypeID": 70,
"bonusType": 1
}
```rust use wotdatfileparser::DatFileParser;
let file = std::fs::read("inputfiles/WOT1191_0/19011713064132879.dat").unwrap();
// You must construct the parser first as it needs to // do some initialization to parse the datfiles. // You can then use this same parser to parse any number of datfiles let parser = DatFileParser::new();
// The parser generates a Battle struct let battle = parser.parse(&file).unwrap();
asserteq!( &battle.common["teamHealth"], &serdejson::json!({ "1": 13595, "2": 12985 }) ); asserteq!(&battle.common["duration"], &serdejson::json!(407));
// Battle implements serde::Serialize and serde::Deserialize. // So, you can use other data formats as well. // Here we will convert it to json and print it: let battleasjson = serdejson::tostringpretty(&battle).unwrap(); println!("{battleas_json}"); ```
If you need to change how some serde_pickle::Value
are converted to serde_json::Value
, you can
intercept it and provide your own implementation:
```rust use wotdatfileparser::{DatFileParser, Intercept};
let file = std::fs::read("inputfiles/WOT1191_0/19011713064132879.dat").unwrap(); let parser = DatFileParser::new();
// We use the following closure to change how a serdepickle::Value is // converted to serdejson::Value. We can also use it to log any errors // in the datfileparser(by matching the Failed variant) let interceptfn = |intercept, originalvalue| { use Intercept::*; match intercept { Success(field, ) | NotPresent(field, _) | ManuallyParsed(field, _) | Failed(field, _, _) => { if field.name == "teamHealth" { // Here we can inspect the originalvalue and provide our own impl // for converting the serdepickle::Value to serdejson::Value // But for this example, we will just return the following: serdejson::Value::String("My own parser for teamHealth".into()) } else { intercept.originalresult() } }, } };
// The parser generates a Battle struct let battle = parser.parseintercept(&file, interceptfn).unwrap();
asserteq!( &battle.common["teamHealth"], &serdejson::json!("My own parser for teamHealth") ); asserteq!(&battle.common["duration"], &serdejson::json!(407)); ```
1.19.0 - 1.19.1