smoke test convert
This commit is contained in:
110
src/main.rs
110
src/main.rs
@@ -1,6 +1,6 @@
|
|||||||
use strafesnet_roblox_bot_file::v0;
|
use strafesnet_roblox_bot_file::{v0,v1};
|
||||||
|
|
||||||
use std::path::{Path,PathBuf};
|
use std::path::PathBuf;
|
||||||
use futures::{StreamExt,TryStreamExt};
|
use futures::{StreamExt,TryStreamExt};
|
||||||
|
|
||||||
#[expect(dead_code)]
|
#[expect(dead_code)]
|
||||||
@@ -40,42 +40,65 @@ async fn main()->Result<(),Error>{
|
|||||||
return Err(Error::InvalidArgs);
|
return Err(Error::InvalidArgs);
|
||||||
};
|
};
|
||||||
|
|
||||||
const ONE_SECOND:u64=1<<32;
|
#[derive(Clone,Copy)]
|
||||||
#[derive(Default)]
|
struct Ratio{
|
||||||
|
num:u64,
|
||||||
|
den:u64,
|
||||||
|
}
|
||||||
|
impl Ratio{
|
||||||
|
fn float(&self)->f32{
|
||||||
|
self.num as f32/self.den as f32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl PartialEq for Ratio{
|
||||||
|
fn eq(&self,other:&Self)->bool{
|
||||||
|
(self.num*other.den).eq(&(other.num*self.den))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Eq for Ratio{}
|
||||||
|
impl PartialOrd for Ratio{
|
||||||
|
fn partial_cmp(&self,other:&Self)->Option<core::cmp::Ordering>{
|
||||||
|
(self.num*other.den).partial_cmp(&(other.num*self.den))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Ord for Ratio{
|
||||||
|
fn cmp(&self,other:&Self)->core::cmp::Ordering{
|
||||||
|
(self.num*other.den).cmp(&(other.num*self.den))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct FoldState{
|
struct FoldState{
|
||||||
count:usize,
|
count:usize,
|
||||||
jumps:u64,
|
min_size_ratio:Ratio,
|
||||||
duration:u64,
|
max_size_ratio:Ratio,
|
||||||
settings:u64,
|
total_size_before:u64,
|
||||||
outliers:Vec<PathBuf>,
|
total_size_after:u64,
|
||||||
}
|
}
|
||||||
impl std::fmt::Display for FoldState{
|
impl std::fmt::Display for FoldState{
|
||||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||||
write!(f,"count={} jumps={} duration={:.3} settings={}",self.count,self.jumps,self.duration as f64/(ONE_SECOND as f64),self.settings)
|
let count=self.count;
|
||||||
|
let min_size_ratio=self.min_size_ratio.float();
|
||||||
|
let max_size_ratio=self.max_size_ratio.float();
|
||||||
|
let total_size_before=self.total_size_before;
|
||||||
|
let total_size_after=self.total_size_after;
|
||||||
|
write!(f,"count={count} min_size_ratio={min_size_ratio:.02} max_size_ratio={max_size_ratio:.02} total_size_before={total_size_before:.02} total_size_after={total_size_after:.02}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl FoldState{
|
impl FoldState{
|
||||||
fn accumulate(&mut self,path:&Path,block:&v0::Block){
|
fn new()->Self{
|
||||||
if let (Some(first),Some(last))=(block.output_events.first(),block.output_events.last()){
|
FoldState{
|
||||||
let last=last.time*ONE_SECOND as f64;
|
count:0,
|
||||||
let first=first.time*ONE_SECOND as f64;
|
min_size_ratio:Ratio{num:u64::MAX,den:1},
|
||||||
let duration=last as u64-first as u64;
|
max_size_ratio:Ratio{num:0,den:1},
|
||||||
if 30000*ONE_SECOND<duration{
|
total_size_before:0,
|
||||||
self.outliers.push(path.to_owned());
|
total_size_after:0,
|
||||||
return;
|
|
||||||
}
|
|
||||||
self.duration+=duration;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
fn accumulate(&mut self,size_before:u64,size_after:u64){
|
||||||
self.count+=1;
|
self.count+=1;
|
||||||
self.jumps+=block.sound_events.iter()
|
let ratio=Ratio{num:size_before,den:size_after};
|
||||||
.filter(|event|event.event.sound_type==v0::SoundType::JumpGround)
|
self.min_size_ratio=self.min_size_ratio.min(ratio);
|
||||||
.count() as u64;
|
self.max_size_ratio=self.max_size_ratio.max(ratio);
|
||||||
// find settings events after run has started
|
|
||||||
if let Some(run_start)=block.run_events.iter().find(|event|matches!(event.event,v0::RunEvent::Start(_))){
|
|
||||||
self.settings+=block.setting_events.iter()
|
|
||||||
.filter(|event|run_start.time<event.time)
|
|
||||||
.count() as u64;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,23 +114,13 @@ async fn main()->Result<(),Error>{
|
|||||||
.map(|result:Result<_,Error>|async move{
|
.map(|result:Result<_,Error>|async move{
|
||||||
let (path,file)=result?;
|
let (path,file)=result?;
|
||||||
let result=tokio::task::spawn_blocking(move||{
|
let result=tokio::task::spawn_blocking(move||{
|
||||||
let block=v0::read_all_to_block(std::io::Cursor::new(file.as_slice())).map_err(RoundTripError::Decode)?;
|
let block_v0=v0::read_all_to_block(std::io::Cursor::new(file.as_slice())).map_err(RoundTripError::Decode)?;
|
||||||
let mut data=Vec::with_capacity(file.len()+1024);
|
let mut data=Vec::with_capacity(file.len());
|
||||||
v0::serialize(&block,&mut std::io::Cursor::new(&mut data)).map_err(RoundTripError::Encode)?;
|
let block_v1=strafesnet_roblox_bot_file::convert::from_v0(&block_v0);
|
||||||
let block_rt=v0::read_all_to_block(std::io::Cursor::new(data)).map_err(RoundTripError::RoundTripDecode)?;
|
v1::serialize(&block_v1,&mut std::io::Cursor::new(&mut data)).map_err(RoundTripError::Encode)?;
|
||||||
if !(
|
let size_before=file.len();
|
||||||
block_rt.input_events.len()==block.input_events.len()&&
|
let size_after=data.len();
|
||||||
block_rt.output_events.len()==block.output_events.len()&&
|
Ok((size_before,size_after))
|
||||||
block_rt.sound_events.len()==block.sound_events.len()&&
|
|
||||||
block_rt.world_events.len()==block.world_events.len()&&
|
|
||||||
block_rt.gravity_events.len()==block.gravity_events.len()&&
|
|
||||||
block_rt.run_events.len()==block.run_events.len()&&
|
|
||||||
block_rt.camera_events.len()==block.camera_events.len()&&
|
|
||||||
block_rt.setting_events.len()==block.setting_events.len()
|
|
||||||
){
|
|
||||||
return Err(RoundTripError::NotEqual);
|
|
||||||
}
|
|
||||||
Ok(block)
|
|
||||||
}).await?;
|
}).await?;
|
||||||
match result{
|
match result{
|
||||||
Err(err)=>Err(Error::BotFile{path,err}),
|
Err(err)=>Err(Error::BotFile{path,err}),
|
||||||
@@ -115,14 +128,11 @@ async fn main()->Result<(),Error>{
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.buffer_unordered(available_parallelism)
|
.buffer_unordered(available_parallelism)
|
||||||
.try_fold(FoldState::default(),async|mut state,(path,block)|{
|
.try_fold(FoldState::new(),async|mut state,(path,(size_before,size_after))|{
|
||||||
state.accumulate(&path,&block);
|
state.accumulate(size_before as u64,size_after as u64);
|
||||||
println!("{:?} {}",path.file_name(),state);
|
println!("{:?} {}",path.file_name(),state);
|
||||||
Ok(state)
|
Ok(state)
|
||||||
}).await?;
|
}).await?;
|
||||||
for path in &tally.outliers{
|
|
||||||
println!("outlier: {:?}",path.file_name());
|
|
||||||
}
|
|
||||||
println!("{}",tally);
|
println!("{}",tally);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user