1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
use super::{ sink_names_input, source_names_output, BinBuildEnvironment, BinDescription, Calculator, FetchItem, GetCalibration, Item, Iteration, Result, Scope, SinkBin, SinkNames, SourceBin, SourceId, SourceNames, SourceSinkBinDescription, WriteDotSimple, SINK_INPUT, SOURCE_OUTPUT, }; use crate::error; use indexmap::IndexSet; static BIN_TYPE: &'static str = "derivation"; pub struct Bin { scope: Scope, source_input: Box<FetchItem>, previous_value: Item, result_output: Item, } impl SinkBin for Bin {} impl SourceBin for Bin { fn get_source_data(&self, source: &SourceId) -> Result<Item> { if source.id == SOURCE_OUTPUT { Ok(self.result_output.clone()) } else { error::MissingSourceName { scope: self.scope.clone(), name: source.id.to_string(), bin_type: BIN_TYPE.to_string(), } .fail() } } } impl Calculator for Bin { fn calculate(&mut self, _iteration: &Iteration) -> Result<()> { let input = self.source_input.fetch_item(&self.scope)?; self.result_output = match (self.previous_value.to_float(), input.to_float()) { (Ok(p), Ok(v)) => Item::F64(v - p), _ => Item::Nothing, }; self.previous_value = input; Ok(()) } } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct Description; impl BinDescription for Description { type Bin = Bin; fn check_validity( &self, _scope: &Scope, _get_calibration: &mut GetCalibration, ) -> Result<()> { Ok(()) } fn bin_type(&self) -> &'static str { BIN_TYPE } } impl SinkNames for Description { fn sink_names(&self) -> IndexSet<String> { sink_names_input() } } impl SourceNames for Description { fn source_names(&self) -> Result<IndexSet<String>> { Ok(source_names_output()) } } impl SourceSinkBinDescription for Description { fn build_bin( &self, scope: &Scope, env: &mut BinBuildEnvironment, ) -> Result<Self::Bin> { Ok(Bin { scope: scope.clone(), source_input: env.resolve(SINK_INPUT)?, previous_value: Item::Nothing, result_output: Item::Nothing, }) } } impl WriteDotSimple for Description {} #[cfg(test)] mod tests { use super::Description; use crate::bins::{directsource, verificationsink}; use crate::{run_bin, Item, Result}; use indexmap::indexset; #[test] fn simulate() -> Result<()> { use crate::Item::*; let input = directsource::Description { columns: indexset!["input".to_string()], rows: vec![ vec![Nothing], vec![Item::from(0f64)], vec![Item::from(2f64)], vec![Item::from(1.5f64)], vec![Item::from(0f64)], vec![Nothing], vec![Item::from(-3i32)], vec![Item::from(-3i32)], vec![Item::from(-4.5f32)], vec![Nothing], vec![Item::from(-3)], vec![Item::from(5)], ] .into(), }; let verification = verificationsink::Description { columns: indexset!["output".to_string()], expected: vec![ vec![Nothing], vec![Nothing], vec![Item::from(2f64)], vec![Item::from(-0.5f64)], vec![Item::from(-1.5f64)], vec![Nothing], vec![Nothing], vec![Item::from(0f64)], vec![Item::from(-1.5f64)], vec![Nothing], vec![Nothing], vec![Item::from(8f64)], ] .into(), }; run_bin(&input, &Description {}, &verification) } }