Skip to content
Snippets Groups Projects
default_combine_data.rs 1.26 KiB
Newer Older
  • Learn to ignore specific revisions
  • use frame_support::traits::{Get, Time};
    
    Xiliang Chen's avatar
    Xiliang Chen committed
    use orml_traits::CombineData;
    
    use rstd::prelude::*;
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    
    use crate::{MomentOf, TimestampedValueOf, Trait};
    
    /// Sort by value and returns median timestamped value.
    /// Returns prev_value if not enough valid values.
    
    pub struct DefaultCombineData<T, MinimumCount, ExpiresIn>(rstd::marker::PhantomData<(T, MinimumCount, ExpiresIn)>);
    
    impl<T, MinimumCount, ExpiresIn> CombineData<T::OracleKey, TimestampedValueOf<T>>
    	for DefaultCombineData<T, MinimumCount, ExpiresIn>
    where
    	T: Trait,
    	MinimumCount: Get<u32>,
    	ExpiresIn: Get<MomentOf<T>>,
    {
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    	fn combine_data(
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    		values: Vec<TimestampedValueOf<T>>,
    		prev_value: Option<TimestampedValueOf<T>>,
    	) -> Option<TimestampedValueOf<T>> {
    
    		let expires_in = ExpiresIn::get();
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    		let now = T::Time::now();
    		let mut valid_values = values
    			.into_iter()
    			.filter_map(|x| {
    				if x.timestamp + expires_in > now {
    					return Some(x);
    				}
    				None
    			})
    			.collect::<Vec<TimestampedValueOf<T>>>();
    
    
    		let count = valid_values.len() as u32;
    		let minimum_count = MinimumCount::get();
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    		if count < minimum_count {
    			return prev_value;
    		}
    
    		valid_values.sort_by(|a, b| a.value.cmp(&b.value));
    
    		let median_index = count / 2;
    
    		return Some(valid_values[median_index as usize].clone());
    
    Ermal Kaleci's avatar
    Ermal Kaleci committed
    	}
    }