use std::path::PathBuf;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
pub const EPOCH_KINDS: [(&str, f32); 6] = [("baseline", 210.0), ("stimulus", 32.0), ("response", 140.0), ("artefact", 0.0), ("sleep", 265.0), ("other", 180.0)];
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct EpochDoc {
pub id: String,
pub recording: PathBuf,
pub name: String,
#[serde(default = "other")]
pub kind: String,
pub start_sec: f64,
pub end_sec: f64,
#[serde(default, skip_serializing_if = "String::is_empty")]
pub notes: String,
}
fn other() -> String {
"other".into()
}
impl EpochDoc {
pub fn duration_sec(&self) -> f64 {
self.end_sec - self.start_sec
}
}
pub fn kind_hue(kind: &str) -> f32 {
EPOCH_KINDS.iter().find(|(k, _)| *k == kind).map_or_else(|| kind.bytes().fold(0u32, |h, b| h.wrapping_mul(31).wrapping_add(b as u32)) as f32 % 360.0, |(_, h)| *h)
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct EventSetDoc {
pub id: String,
pub recording: PathBuf,
pub name: String,
pub table: PathBuf,
#[serde(default = "tick_hue")]
pub hue: f32,
#[serde(default = "tick_height")]
pub tick_height: f32,
#[serde(default = "tick_width")]
pub tick_width: f32,
#[serde(default)]
pub show_offsets: bool,
#[serde(default = "shown")]
pub visible: bool,
}
pub const DEFAULT_TICK_HUE: f32 = 50.0;
pub const DEFAULT_TICK_HEIGHT: f32 = 0.6;
pub const DEFAULT_TICK_WIDTH: f32 = 1.5;
fn tick_hue() -> f32 {
DEFAULT_TICK_HUE
}
fn tick_height() -> f32 {
DEFAULT_TICK_HEIGHT
}
fn tick_width() -> f32 {
DEFAULT_TICK_WIDTH
}
fn shown() -> bool {
true
}
impl EventSetDoc {
pub fn new(recording: PathBuf, name: impl Into<String>, table: PathBuf) -> Self {
Self { id: String::new(), recording, name: name.into(), table, hue: DEFAULT_TICK_HUE, tick_height: DEFAULT_TICK_HEIGHT, tick_width: DEFAULT_TICK_WIDTH, show_offsets: false, visible: true }
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct Placement {
pub path: PathBuf,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub source: Option<String>,
pub start_sec: f64,
}