use crate::words;
use alice_protocol_reader::prelude::RDH;
use serde::{Deserialize, Serialize};
use stats_collector::its_stats::alpide_stats::AlpideStats;
pub mod lib;
pub mod stats_collector;
pub(super) mod stats_report;
mod stats_validation;
#[derive(Debug, Clone, PartialEq)]
pub enum StatType {
Fatal(Box<str>),
Error(Box<str>),
RunTriggerType((u32, Box<str>)),
TriggerType(u32),
SystemId(SystemId),
RDHSeen(u16),
RDHFiltered(u16),
PayloadSize(u32),
LinksObserved(u8),
RdhVersion(u8),
DataFormat(u8),
HBFSeen,
LayerStaveSeen {
layer: u8,
stave: u8,
},
FeeId(u16),
AlpideStats(AlpideStats),
}
impl std::fmt::Display for StatType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
StatType::RunTriggerType((val, description)) => {
write!(f, "Run trigger type: {val}: {description}")
}
StatType::RDHSeen(val) => write!(f, "{val} RDHs seen"),
StatType::RDHFiltered(val) => write!(f, "{val} RDHs filtered"),
StatType::PayloadSize(bytes) => write!(f, "Payload size: {bytes}"),
StatType::LinksObserved(id) => write!(f, "Link observed: {id}"),
StatType::RdhVersion(v) => write!(f, "RDH version: {v}"),
StatType::DataFormat(format) => write!(f, "Data format: {format}"),
StatType::HBFSeen => write!(f, "HBFs seen increment"),
StatType::LayerStaveSeen {
layer: layer_id,
stave: stave_id,
} => write!(f, "Layer/stave seen: {layer_id}/{stave_id}"),
StatType::FeeId(id) => write!(f, "FEE ID: {id}"),
StatType::TriggerType(trig_val) => write!(f, "Trigger type: {trig_val:#X}"),
StatType::AlpideStats(alpide_stats) => write!(f, "ALPIDE stats {alpide_stats:?}"),
StatType::SystemId(s_id) => write!(f, "System ID: {s_id}"),
StatType::Error(e) => write!(f, "Error: {e}"),
StatType::Fatal(e) => write!(f, "Fatal error: {e}"),
}
}
}
#[allow(missing_docs)]
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub enum SystemId {
TPC,
TRD,
TOF,
HMP,
PHS,
CPV,
MCH,
ZDC,
TRG,
EMC,
TST, ITS,
FDD,
FT0,
FV0,
MFT,
MID,
DCS,
FOC, Unloaded,
}
impl SystemId {
pub fn from_system_id(sys_id: u8) -> Result<Self, String> {
match sys_id {
3 => Ok(SystemId::TPC),
4 => Ok(SystemId::TRD),
5 => Ok(SystemId::TOF),
6 => Ok(SystemId::HMP),
7 => Ok(SystemId::PHS),
8 => Ok(SystemId::CPV),
10 => Ok(SystemId::MCH),
15 => Ok(SystemId::ZDC),
17 => Ok(SystemId::TRG),
18 => Ok(SystemId::EMC),
19 => Ok(SystemId::TST),
32 => Ok(SystemId::ITS),
33 => Ok(SystemId::FDD),
34 => Ok(SystemId::FT0),
35 => Ok(SystemId::FV0),
36 => Ok(SystemId::MFT),
37 => Ok(SystemId::MID),
38 => Ok(SystemId::DCS),
39 => Ok(SystemId::FOC),
255 => Ok(SystemId::Unloaded),
_ => Err(format!("Unknown system ID {sys_id}")),
}
}
}
impl std::fmt::Display for SystemId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
SystemId::TPC => write!(f, "TPC"),
SystemId::TRD => write!(f, "TRD"),
SystemId::TOF => write!(f, "TOF"),
SystemId::HMP => write!(f, "HMP"),
SystemId::PHS => write!(f, "PHS"),
SystemId::CPV => write!(f, "CPV"),
SystemId::MCH => write!(f, "MCH"),
SystemId::ZDC => write!(f, "ZDC"),
SystemId::TRG => write!(f, "TRG"),
SystemId::EMC => write!(f, "EMC"),
SystemId::TST => write!(f, "TST"),
SystemId::ITS => write!(f, "ITS"),
SystemId::FDD => write!(f, "FDD"),
SystemId::FT0 => write!(f, "FT0"),
SystemId::FV0 => write!(f, "FV0"),
SystemId::MFT => write!(f, "MFT"),
SystemId::MID => write!(f, "MID"),
SystemId::DCS => write!(f, "DCS"),
SystemId::FOC => write!(f, "FOC"),
SystemId::Unloaded => write!(f, "Unloaded"),
}
}
}
pub fn collect_system_specific_stats<T: RDH + 'static>(
rdh: &T,
system_id: &mut Option<SystemId>,
stats_send_chan: &flume::Sender<StatType>,
) -> Result<(), String> {
if system_id.is_none() {
let observed_sys_id = match SystemId::from_system_id(rdh.rdh0().system_id) {
Ok(id) => id,
Err(e) => return Err(e),
};
*system_id = Some(observed_sys_id);
}
if let Some(system_id) = system_id {
match system_id {
SystemId::ITS => {
log::trace!("Collecting stats for ITS");
collect_its_stats(rdh, stats_send_chan)
}
SystemId::FOC => {
log::trace!("Collecting stats for Focal");
}
_ => (), }
} else {
unreachable!("System ID should have been determined by now")
}
Ok(())
}
fn collect_its_stats<T: RDH>(rdh: &T, stats_send_chan: &flume::Sender<StatType>) {
let layer = words::its::layer_from_feeid(rdh.fee_id());
let stave = words::its::stave_number_from_feeid(rdh.fee_id());
stats_send_chan
.send(StatType::LayerStaveSeen { layer, stave })
.unwrap();
}