scientific_method/
observation.rs1use crate::Measurement;
4
5#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8pub struct ObservationRef {
9 pub condition: String,
10 pub measurement: String,
11}
12
13impl ObservationRef {
14 pub fn new(condition: impl Into<String>, measurement: impl Into<String>) -> Self {
15 Self {
16 condition: condition.into(),
17 measurement: measurement.into(),
18 }
19 }
20}
21
22#[derive(Debug, Clone, PartialEq)]
24#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
25pub struct Observation {
26 pub condition: String,
27 pub measurement: Measurement,
28}
29
30impl Observation {
31 pub fn new(condition: impl Into<String>, measurement: Measurement) -> Self {
32 Self {
33 condition: condition.into(),
34 measurement,
35 }
36 }
37
38 pub fn reference(&self) -> ObservationRef {
39 ObservationRef::new(&self.condition, &self.measurement.name)
40 }
41}
42
43#[derive(Debug, Clone, Default, PartialEq)]
48#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
49#[cfg_attr(feature = "serde", serde(transparent))]
50pub struct Observations(Vec<Observation>);
51
52impl Observations {
53 pub fn new() -> Self {
54 Self::default()
55 }
56
57 pub fn insert(&mut self, observation: Observation) -> Option<Observation> {
58 let reference = observation.reference();
59 if let Some(index) = self
60 .0
61 .iter()
62 .position(|existing| existing.reference() == reference)
63 {
64 Some(std::mem::replace(&mut self.0[index], observation))
65 } else {
66 self.0.push(observation);
67 None
68 }
69 }
70
71 pub fn with(mut self, observation: Observation) -> Self {
72 self.insert(observation);
73 self
74 }
75
76 pub fn get(&self, reference: &ObservationRef) -> Option<&Measurement> {
77 self.0
78 .iter()
79 .find(|observation| observation.reference() == *reference)
80 .map(|observation| &observation.measurement)
81 }
82
83 pub fn len(&self) -> usize {
84 self.0.len()
85 }
86
87 pub fn is_empty(&self) -> bool {
88 self.0.is_empty()
89 }
90
91 pub fn iter(&self) -> impl Iterator<Item = &Observation> {
92 self.0.iter()
93 }
94}