validator: write check error message
This commit is contained in:
parent
34b8d7475d
commit
5846e92924
@ -50,6 +50,20 @@ struct ModeID(u64);
|
||||
impl ModeID{
|
||||
const MAIN:Self=Self(0);
|
||||
const BONUS:Self=Self(1);
|
||||
fn write_start_zone(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
match self{
|
||||
ModeID(0)=>write!(f,"MapStart"),
|
||||
ModeID(1)=>write!(f,"BonusStart"),
|
||||
ModeID(other)=>write!(f,"Bonus{other}Start"),
|
||||
}
|
||||
}
|
||||
fn write_finish_zone(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
match self{
|
||||
ModeID(0)=>write!(f,"MapFinish"),
|
||||
ModeID(1)=>write!(f,"BonusFinish"),
|
||||
ModeID(other)=>write!(f,"Bonus{other}Finish"),
|
||||
}
|
||||
}
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
pub enum ZoneParseError{
|
||||
@ -173,10 +187,20 @@ impl<'a,Str> StringCheckContext<'a,Str>
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'a,Str:std::fmt::Display> std::fmt::Display for StringCheckContext<'a,Str>{
|
||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
write!(f,"expected: {}, observed: {}",self.expected,self.observed)
|
||||
}
|
||||
}
|
||||
|
||||
// check if a string is empty
|
||||
pub struct StringEmpty;
|
||||
pub struct StringEmptyCheck<Context>(Result<Context,StringEmpty>);
|
||||
impl std::fmt::Display for StringEmpty{
|
||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
write!(f,"Empty string")
|
||||
}
|
||||
}
|
||||
|
||||
// check for duplicate objects
|
||||
pub struct DuplicateCheckContext<ID>(HashMap<ID,u64>);
|
||||
@ -355,6 +379,98 @@ impl<'a> MapCheck<'a>{
|
||||
}
|
||||
}
|
||||
|
||||
fn comma_separated<T,F>(f:&mut std::fmt::Formatter<'_>,mut it:impl Iterator<Item=T>,custom_write:F)->std::fmt::Result
|
||||
where
|
||||
F:Fn(&mut std::fmt::Formatter<'_>,T)->std::fmt::Result,
|
||||
{
|
||||
if let Some(t)=it.next(){
|
||||
custom_write(f,t)?;
|
||||
for t in it{
|
||||
write!(f,", ")?;
|
||||
custom_write(f,t)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl<'a> std::fmt::Display for MapCheck<'a>{
|
||||
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
||||
if let StringCheck(Err(context))=&self.model_class{
|
||||
writeln!(f,"Invalid Model Class: {context}")?;
|
||||
}
|
||||
if let StringCheck(Err(context))=&self.model_name{
|
||||
writeln!(f,"Invalid Model Name: {context}")?;
|
||||
}
|
||||
match &self.display_name{
|
||||
Ok(StringEmptyCheck(Ok(StringCheck(Ok(_)))))=>(),
|
||||
Ok(StringEmptyCheck(Ok(StringCheck(Err(context)))))=>writeln!(f,"Invalid DisplayName: {context}")?,
|
||||
Ok(StringEmptyCheck(Err(context)))=>writeln!(f,"Invalid DisplayName: {context}")?,
|
||||
Err(StringValueError::ObjectNotFound)=>writeln!(f,"Missing DisplayName StringValue")?,
|
||||
Err(StringValueError::ValueNotSet)=>writeln!(f,"DisplayName Value not set")?,
|
||||
Err(StringValueError::NonStringValue)=>writeln!(f,"DisplayName Value is not a String")?,
|
||||
}
|
||||
match &self.creator{
|
||||
Ok(StringEmptyCheck(Ok(_)))=>(),
|
||||
Ok(StringEmptyCheck(Err(context)))=>writeln!(f,"Invalid Creator: {context}")?,
|
||||
Err(StringValueError::ObjectNotFound)=>writeln!(f,"Missing Creator StringValue")?,
|
||||
Err(StringValueError::ValueNotSet)=>writeln!(f,"Creator Value not set")?,
|
||||
Err(StringValueError::NonStringValue)=>writeln!(f,"Creator Value is not a String")?,
|
||||
}
|
||||
if let Err(_parse_game_id_error)=&self.game_id{
|
||||
writeln!(f,"Model name must be prefixed with bhop_ surf_ or flytrials_")?;
|
||||
}
|
||||
if let Err(())=&self.mapstart{
|
||||
writeln!(f,"Model has no MapStart")?;
|
||||
}
|
||||
if let DuplicateCheck(Err(DuplicateCheckContext(context)))=&self.mode_start_counts{
|
||||
write!(f,"Duplicate start zones: ")?;
|
||||
comma_separated(f,context.iter(),|f,(mode_id,count)|{
|
||||
mode_id.write_start_zone(f)?;
|
||||
write!(f,"({count} duplicates)")?;
|
||||
Ok(())
|
||||
})?;
|
||||
writeln!(f,"")?;
|
||||
}
|
||||
if let AtLeastOneMatchingAndNoExtraCheck(Err(context))=&self.mode_finish_counts{
|
||||
// perhaps there are extra end zones (context.extra)
|
||||
if !context.extra.is_empty(){
|
||||
write!(f,"Extra finish zones with no matching start zone: ")?;
|
||||
comma_separated(f,context.extra.iter(),|f,(mode_id,_count)|
|
||||
mode_id.write_finish_zone(f))?;
|
||||
writeln!(f,"")?;
|
||||
}
|
||||
// perhaps there are missing end zones (context.missing)
|
||||
if !context.missing.is_empty(){
|
||||
write!(f,"Missing finish zones: ")?;
|
||||
comma_separated(f,context.missing.iter(),|f,mode_id|
|
||||
mode_id.write_finish_zone(f)
|
||||
)?;
|
||||
writeln!(f,"")?;
|
||||
}
|
||||
}
|
||||
if let Err(())=&self.spawn1{
|
||||
writeln!(f,"Model has no Spawn1")?;
|
||||
}
|
||||
if let DuplicateCheck(Err(DuplicateCheckContext(context)))=&self.spawn_counts{
|
||||
write!(f,"Duplicate spawn zones: ")?;
|
||||
comma_separated(f,context.iter(),|f,(SpawnID(spawn_id),count)|{
|
||||
write!(f,"Spawn{spawn_id}({count} duplicates)")?;
|
||||
Ok(())
|
||||
})?;
|
||||
writeln!(f,"")?;
|
||||
}
|
||||
if let DuplicateCheck(Err(DuplicateCheckContext(context)))=&self.wormhole_out_counts{
|
||||
write!(f,"Duplicate wormhole out: ")?;
|
||||
comma_separated(f,context.iter(),|f,(WormholeOutID(wormhole_out_id),count)|{
|
||||
write!(f,"WormholeOut{wormhole_out_id}({count} duplicates)")?;
|
||||
Ok(())
|
||||
})?;
|
||||
writeln!(f,"")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CheckReportAndVersion{
|
||||
pub status:Result<MapInfoOwned,String>,
|
||||
pub version:u64,
|
||||
|
Loading…
x
Reference in New Issue
Block a user