mirror of
https://gitlab.cern.ch/wotsubo/psboard-qaqc-postprocess.git
synced 2025-07-02 01:29:28 +09:00
new: implement till parsing file (no output)
This commit is contained in:
parent
474f2397c6
commit
a14eb4ea48
7 changed files with 604 additions and 24 deletions
205
src/main.rs
205
src/main.rs
|
@ -1,10 +1,11 @@
|
|||
use core::str;
|
||||
use core::{panic, str};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
env,
|
||||
fmt::Display,
|
||||
fs::File,
|
||||
io::{BufRead, BufReader},
|
||||
path,
|
||||
io::{BufRead, BufReader, Write},
|
||||
path::{self, PathBuf},
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
|
@ -15,12 +16,26 @@ use log::{debug, error, info, trace, warn};
|
|||
use regex::Regex;
|
||||
use semver::Version;
|
||||
|
||||
fn get_default_output_path() -> PathBuf {
|
||||
PathBuf::from_str("outpu.csv").expect("Error")
|
||||
}
|
||||
fn get_default_log_path() -> PathBuf {
|
||||
let mut path = env::current_exe().unwrap();
|
||||
path.pop();
|
||||
path.push("log");
|
||||
path.push("debug.log");
|
||||
path
|
||||
}
|
||||
|
||||
/// Parse master jathub logfile for PS Board QAQC and write out to CSV.
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(version, about, long_about = None)]
|
||||
struct Args {
|
||||
/// Master log file.
|
||||
master_log: path::PathBuf,
|
||||
/// Output CSV file.
|
||||
// #[arg(default_value = get_default_log_path().into_os_string())]
|
||||
outfile: PathBuf,
|
||||
#[command(flatten)]
|
||||
verbose: clap_verbosity_flag::Verbosity,
|
||||
}
|
||||
|
@ -99,14 +114,14 @@ impl FromStr for Position {
|
|||
}
|
||||
|
||||
/// PSB ID printed on the tape on the board.
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
struct PsbId {
|
||||
id: u8,
|
||||
id: u32,
|
||||
}
|
||||
|
||||
impl PsbId {
|
||||
/// Without validation.
|
||||
pub fn new(id: u8) -> Self {
|
||||
pub fn new(id: u32) -> Self {
|
||||
PsbId { id }
|
||||
}
|
||||
}
|
||||
|
@ -115,7 +130,10 @@ impl FromStr for PsbId {
|
|||
type Err = anyhow::Error;
|
||||
|
||||
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
||||
let num: u8 = s.parse()?;
|
||||
if !s.starts_with("PB") {
|
||||
return Err(anyhow!("Must prefixed with PB: {}", s));
|
||||
}
|
||||
let num = s[2..].parse()?;
|
||||
// TODO: add validation
|
||||
warn!("No validation implemented");
|
||||
Ok(PsbId::new(num))
|
||||
|
@ -123,24 +141,26 @@ impl FromStr for PsbId {
|
|||
}
|
||||
|
||||
/// QAQC results for each boards extracted from master log.
|
||||
///
|
||||
/// Temporary stores raw values.
|
||||
/// TODO: specify each filed types.(maybe multi values)
|
||||
#[derive(Debug)]
|
||||
struct BoardResult {
|
||||
id: PsbId,
|
||||
qspif: bool,
|
||||
qspip: bool,
|
||||
recov: bool,
|
||||
clock: bool,
|
||||
regac: bool,
|
||||
asdtp: bool,
|
||||
done: bool,
|
||||
qspif: u8,
|
||||
qspip: u8,
|
||||
recov: u8,
|
||||
clock: u8,
|
||||
regac: u8,
|
||||
asdtp: u8,
|
||||
done: u8,
|
||||
}
|
||||
|
||||
/// Full result for a single QAQC run from a log file on JATHub master.
|
||||
#[derive(Debug)]
|
||||
struct MasterLogResult {
|
||||
version: Version,
|
||||
datetime: DateTime<Local>,
|
||||
datetime: DateTime<Utc>,
|
||||
shifter: String,
|
||||
board_results: HashMap<Position, BoardResult>,
|
||||
}
|
||||
|
@ -210,7 +230,8 @@ impl MasterLogResult {
|
|||
}
|
||||
|
||||
let mut assignments = HashMap::new();
|
||||
for i in 0..18 {
|
||||
// till 19 for `===========`
|
||||
for i in 0..19 {
|
||||
let line = lines.next().context("Unexpected EOF")??;
|
||||
if line.starts_with("=========") {
|
||||
debug!("End of assignments");
|
||||
|
@ -232,10 +253,136 @@ impl MasterLogResult {
|
|||
trace!("Read all PBS assignments");
|
||||
info!("{:?}", assignments);
|
||||
|
||||
if !lines
|
||||
.next()
|
||||
.context("Invalid log format")??
|
||||
.contains("QAQC status")
|
||||
{
|
||||
info!("{:?}", lines.next());
|
||||
return Err(anyhow!("Invalid log format(result table header)"));
|
||||
}
|
||||
let _sep = lines
|
||||
.next()
|
||||
.context("Invalid log format(result table separator)")??;
|
||||
|
||||
if !lines
|
||||
.next()
|
||||
.context("Invalid log format")??
|
||||
.contains("Station0")
|
||||
{
|
||||
return Err(anyhow!("Invalid log format(result Station0)"));
|
||||
}
|
||||
|
||||
let mut board_results = HashMap::new();
|
||||
for station_minor in [0, 1] {
|
||||
info!("Result for {:?}", station_minor);
|
||||
for _ in 1..10 {
|
||||
let line = lines.next().context("Invalid log format(result body)")??;
|
||||
if line.contains("Station1") || line.contains("======") {
|
||||
break;
|
||||
}
|
||||
let parts: Vec<&str> = line.split('|').collect();
|
||||
let first = parts.first().context("No col 1")?;
|
||||
let raw_station_id = {
|
||||
let re = Regex::new(r"JATHub_( ?\d*)$")?;
|
||||
re.captures(first).map(|v| {
|
||||
v.get(1)
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.split_whitespace()
|
||||
.next()
|
||||
.unwrap()
|
||||
.parse::<u8>()
|
||||
})
|
||||
}
|
||||
.context("Invalid station format")??;
|
||||
let station_id = match station_minor {
|
||||
0 => raw_station_id,
|
||||
1 => raw_station_id - 10,
|
||||
_ => panic!("Unexpected"),
|
||||
};
|
||||
trace!("Row {} {:?}", station_id, parts);
|
||||
if parts.len() != 9 {
|
||||
return Err(anyhow!(
|
||||
"Invalid number of results(expected: 9, detected: {})",
|
||||
parts.len()
|
||||
));
|
||||
}
|
||||
|
||||
// Origin is different (-1)
|
||||
let pos = Position {
|
||||
major: PositionLayer::A,
|
||||
minor: station_minor,
|
||||
patch: station_id - 1,
|
||||
};
|
||||
debug!("pos from table {}", pos);
|
||||
|
||||
let psbid = assignments
|
||||
.get(&pos)
|
||||
.context(format!("No board on pos {}", pos))?
|
||||
.clone();
|
||||
|
||||
let result = BoardResult {
|
||||
id: psbid,
|
||||
qspif: parts
|
||||
.get(1)
|
||||
.map(|v| v.split_whitespace().next().unwrap().parse())
|
||||
.context("Invalid qspif")??,
|
||||
qspip: parts
|
||||
.get(2)
|
||||
.map(|v| v.split_whitespace().next().unwrap().parse())
|
||||
.context("Invalid qspip")??,
|
||||
recov: parts
|
||||
.get(3)
|
||||
.map(|v| v.split_whitespace().next().unwrap().parse())
|
||||
.context("Invalid recov")??,
|
||||
clock: parts
|
||||
.get(4)
|
||||
.map(|v| v.split_whitespace().next().unwrap().parse())
|
||||
.context("Invalid clock")??,
|
||||
regac: parts
|
||||
.get(5)
|
||||
.map(|v| v.split_whitespace().next().unwrap().parse())
|
||||
.context("Invalid regac")??,
|
||||
asdtp: parts
|
||||
.get(6)
|
||||
.map(|v| v.split_whitespace().next().unwrap().parse())
|
||||
.context("Invalid asdtp")??,
|
||||
done: parts
|
||||
.get(7)
|
||||
.map(|v| v.split_whitespace().next().unwrap().parse())
|
||||
.context("Invalid done")??,
|
||||
};
|
||||
|
||||
match board_results.insert(pos, result) {
|
||||
None => (),
|
||||
Some(v) => {
|
||||
panic!("Unexpected value already exists: {:?}", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug!("{:#?}", board_results);
|
||||
|
||||
Ok(MasterLogResult {
|
||||
version,
|
||||
datetime,
|
||||
shifter,
|
||||
board_results,
|
||||
})
|
||||
}
|
||||
|
||||
fn write(&self, f: impl Write) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
fn check_csv_header(f: impl BufRead) -> Result<()> {
|
||||
// f.lines()
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let args = Args::parse();
|
||||
env_logger::Builder::new()
|
||||
|
@ -244,10 +391,24 @@ fn main() -> Result<()> {
|
|||
debug!("Args: {:?}", args);
|
||||
println!("Hello, world!");
|
||||
|
||||
let file = File::open(args.master_log)?;
|
||||
let mut reader = BufReader::new(file);
|
||||
let result = MasterLogResult::parse_file(reader)?;
|
||||
debug!(
|
||||
"{:?}",
|
||||
" 1".split_whitespace().next().unwrap().parse::<u8>()
|
||||
);
|
||||
|
||||
let result = {
|
||||
let file = File::open(args.master_log)?;
|
||||
let reader = BufReader::new(file);
|
||||
MasterLogResult::parse_file(reader)?
|
||||
};
|
||||
debug!("{:?}", result);
|
||||
|
||||
// {
|
||||
// let file = File::options()
|
||||
// .read(true)
|
||||
// .open(args.outfile)?;
|
||||
// }
|
||||
//
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -305,7 +466,7 @@ mod test {
|
|||
#[test]
|
||||
fn parse_pos_id_line() {
|
||||
assert_eq!(
|
||||
extract_position_id("Position / assigned-ID : A-0-0 / 000004").unwrap(),
|
||||
extract_position_id("Position / assigned-ID : A-0-0 / PB0004").unwrap(),
|
||||
(
|
||||
Position {
|
||||
major: PositionLayer::A,
|
||||
|
@ -316,7 +477,7 @@ mod test {
|
|||
)
|
||||
);
|
||||
assert_eq!(
|
||||
extract_position_id("Position / assigned-ID : A-1-7 / 000108").unwrap(),
|
||||
extract_position_id("Position / assigned-ID : A-1-7 / PB0108").unwrap(),
|
||||
(
|
||||
Position {
|
||||
major: PositionLayer::A,
|
||||
|
@ -327,7 +488,7 @@ mod test {
|
|||
)
|
||||
);
|
||||
assert_ne!(
|
||||
extract_position_id("Position / assigned-ID : A-1-7 / 000108").unwrap(),
|
||||
extract_position_id("Position / assigned-ID : A-1-7 / PB0108").unwrap(),
|
||||
(
|
||||
Position {
|
||||
major: PositionLayer::A,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue