Table of content

What is this :grey_question:

The rules of the game are explained in my original post.

18th Challenge

challenge

Today’s challenge is continuation of a previous challenge. The task is to extend the existing project with tests

Solution :white_check_mark:

The new solution looks like this:

	use std::cmp::max;
	pub type CodingRate=u32;

	pub enum CodingRates{
	    CodingRate45,
	    CodingRate46,
	    CodingRate47,
	    CodingRate48
	}

	pub struct Modulation {
	    pub(crate) spreading_factor:u64,
	    pub(crate) bandwidth:u64
	}

	pub struct FrameMetaInformation {
	    pub(crate) payload_length:u64,
	    pub(crate) preamble_length:u64,
	    pub(crate) is_header_enabled:bool,
	    pub(crate) is_low_data_rate_optimization_enabled:bool,
	    pub(crate) modulation:Modulation,
	    pub(crate) coding_rate:CodingRates,

	}

	impl CodingRates{
	    fn value(&self) -> CodingRate {
	        match self{
	            CodingRates::CodingRate45 => 1,
	            CodingRates::CodingRate46 => 2,
	            CodingRates::CodingRate47 => 3,
	            CodingRates::CodingRate48 => 4,
	        }
	    }
	}

	impl FrameMetaInformation{

	    pub(crate) fn get_airtime(&self) -> u64{
	        (self.get_preamble_duration() +
	            self.modulation.get_symbol_duration() * self.get_payload_symbol_count() as f64) as u64
	    }

	    fn get_preamble_duration(&self) -> f64{
	        self.modulation.get_preamble_duration(self.preamble_length)
	    }

	    fn get_payload_symbol_count(&self) -> u64 {
	        let de = self.is_low_data_rate_optimization_enabled as u64;
	        let h = (!self.is_low_data_rate_optimization_enabled) as u64;

	        let a = (8 * self.payload_length + 28 + 16 - 20 * h) as f64;
	        let b = (4 * (self.modulation.spreading_factor - 2 * de)) as f64;
	        let c = (self.coding_rate.value() as f64) + 4.0;

	        8 + max(((a / b).ceil() * c) as u64, 0)
	    }

	}

	impl Modulation{
	    fn get_symbol_duration(&self) -> f64{
	        ((1<<self.spreading_factor) * 1000_000 / self.bandwidth) as f64
	    }
	    fn get_preamble_duration(&self,preamble_length:u64) -> f64{
	        (100.0 * preamble_length as f64 + 425.0) / 100.0 * self.get_symbol_duration()
	    }
	}

	#[test]
	fn test_get_payload_symbol_count(){
	    let f = FrameMetaInformation{
	        payload_length: 13,
	        preamble_length: 0,
	        is_header_enabled: true,
	        is_low_data_rate_optimization_enabled: false,
	        modulation: Modulation {
	            spreading_factor: 12,
	            bandwidth: 0
	        },
	        coding_rate: CodingRates::CodingRate45
	    };

	    assert_eq!(23,f.get_payload_symbol_count())
	}

	#[cfg(test)]
	mod tests {

	    use super::*;

	    #[test]
	    fn test_get_preamble_duration() {
	        let m = Modulation {
	            spreading_factor: 12,
	            bandwidth: 125
	        };
	        assert_eq!(401408_000.0, m.get_preamble_duration(8));
	    }

	    #[test]
	    fn test_get_symbol_duration() {
	        let mut m = Modulation {
	            spreading_factor: 12,
	            bandwidth: 125
	        };
	        assert_eq!(32768_000.0, m.get_symbol_duration());
	        m.spreading_factor = 9;
	        assert_eq!(4096_000.0, m.get_symbol_duration());
	        m.bandwidth = 500;
	        assert_eq!(1024_000.0, m.get_symbol_duration());
	    }

	    #[test]
	    fn test_airtime_calculation() {
	        let f = FrameMetaInformation {
	            payload_length: 13,
	            preamble_length: 8,
	            is_header_enabled: true,
	            is_low_data_rate_optimization_enabled: false,
	            modulation: Modulation {
	                spreading_factor: 12,
	                bandwidth: 125
	            },
	            coding_rate: CodingRates::CodingRate45,
	        };

	        assert_eq!(1_155_072_000, f.get_airtime() as u64);
	    }
	}
	

To get a good feel for it see / clone github. You can see the tests in action on rust playground