use std::num::NonZeroU32;
use std::time::Duration;
use serde::{Deserialize, Serialize};
use crate::enums::Measure;
use crate::types::{DocumentationRef, ExperimenterRef, Id, TccRef};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ThermalCyclingConditions {
pub id: Id,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub description: Option<String>,
#[serde(skip_serializing_if = "Vec::is_empty", default)]
pub documentation: Vec<DocumentationRef>,
#[serde(
rename = "lidTemperature",
skip_serializing_if = "Option::is_none",
default
)]
pub lid_temperature: Option<f64>,
#[serde(
rename = "experimenter",
skip_serializing_if = "Vec::is_empty",
default
)]
pub experimenters: Vec<ExperimenterRef>,
#[serde(rename = "step")]
pub steps: Vec<Step>,
}
impl ThermalCyclingConditions {
#[must_use]
pub fn new(id: Id) -> Self {
Self {
id,
description: None,
documentation: Vec::new(),
lid_temperature: None,
experimenters: Vec::new(),
steps: Vec::new(),
}
}
#[must_use]
pub fn reference(&self) -> TccRef {
self.id.clone().into()
}
pub fn push_step(&mut self, kind: StepKind) -> &mut Step {
let next = self
.steps
.iter()
.map(|s| s.nr)
.max()
.map_or(NonZeroU32::MIN, |max| max.saturating_add(1));
self.steps.push(Step {
nr: next,
description: None,
kind,
});
self.steps.last_mut().expect("pushed in this call")
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Step {
pub nr: NonZeroU32,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub description: Option<String>,
pub kind: StepKind,
}
impl Step {
#[must_use]
pub fn new(nr: NonZeroU32, kind: StepKind) -> Self {
Self {
nr,
description: None,
kind,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum StepKind {
#[serde(rename = "temperature")]
Temperature(TemperatureStep),
#[serde(rename = "gradient")]
Gradient(GradientStep),
#[serde(rename = "loop")]
Loop(LoopStep),
#[serde(rename = "pause")]
Pause(PauseStep),
#[serde(rename = "lidOpen")]
LidOpen,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TemperatureStep {
pub temperature: f64,
pub duration: NonZeroU32,
#[serde(
rename = "temperatureChange",
skip_serializing_if = "Option::is_none",
default
)]
pub temperature_change: Option<f64>,
#[serde(
rename = "durationChange",
skip_serializing_if = "Option::is_none",
default
)]
pub duration_change: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub measure: Option<Measure>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub ramp: Option<f64>,
}
impl TemperatureStep {
#[must_use]
pub fn new(temperature: f64, duration: NonZeroU32) -> Self {
Self {
temperature,
duration,
temperature_change: None,
duration_change: None,
measure: None,
ramp: None,
}
}
#[must_use]
pub fn hold(&self) -> Duration {
Duration::from_secs(self.duration.get().into())
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct GradientStep {
#[serde(rename = "highTemperature")]
pub high_temperature: f64,
#[serde(rename = "lowTemperature")]
pub low_temperature: f64,
pub duration: NonZeroU32,
#[serde(
rename = "temperatureChange",
skip_serializing_if = "Option::is_none",
default
)]
pub temperature_change: Option<f64>,
#[serde(
rename = "durationChange",
skip_serializing_if = "Option::is_none",
default
)]
pub duration_change: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub measure: Option<Measure>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub ramp: Option<f64>,
}
impl GradientStep {
#[must_use]
pub fn new(high_temperature: f64, low_temperature: f64, duration: NonZeroU32) -> Self {
Self {
high_temperature,
low_temperature,
duration,
temperature_change: None,
duration_change: None,
measure: None,
ramp: None,
}
}
#[must_use]
pub fn hold(&self) -> Duration {
Duration::from_secs(self.duration.get().into())
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct LoopStep {
pub goto: NonZeroU32,
pub repeat: u32,
}
impl LoopStep {
#[must_use]
pub fn new(goto: NonZeroU32, repeat: u32) -> Self {
Self { goto, repeat }
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PauseStep {
pub temperature: f64,
}
impl PauseStep {
#[must_use]
pub fn new(temperature: f64) -> Self {
Self { temperature }
}
}