summaryrefslogtreecommitdiffstats
path: root/src/backend/landscape.rs
blob: 4916f759a4638ac3264d4f2d384b088c6a0ebfb2 (plain)
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
use anyhow::Result;
use std::sync::Arc;
use tokio::sync::RwLock;
use resiter::Map;

use crate::util::*;
use crate::backend::sim::*;
use crate::backend::rain::*;

pub struct Landscape {
    elements: Vec<Arc<RwLock<LandscapeElement>>>,
}

impl Landscape {
    pub fn new(elements: Vec<usize>) -> Self {
        let elements = elements
            .into_iter()
            .map(LandscapeElement::new)
            .map(RwLock::new)
            .map(Arc::new)
            .collect();

        Landscape { elements }
    }

    // here is where the fun is
    pub async fn let_it_rain(self, hours: usize) -> Result<RainyLandscape> {
        use futures::StreamExt;

        self.prepare_element_simulation()
            .await?
            .into_iter()
            .map(|el| el.let_it_rain(hours))
            .collect::<futures::stream::FuturesUnordered<_>>()
            .collect::<Vec<_>>()
            .await
            .into_iter()
            .map_ok(ElementRainingSimulation::into_landscape_element)
            .collect::<Result<Vec<_>>>()
            .map(RainyLandscape::new)
    }

    async fn prepare_element_simulation(&self) -> Result<Vec<ElementRainingSimulation>> {
        let mut simulation_elements = self.elements
            .iter()
            .map(Arc::clone)
            .map(ElementRainingSimulation::new)
            .collect::<Vec<_>>();

        if simulation_elements.len() >= 3 {
            log::debug!("Having three or more landscape elements in the simulation, pairing them now");
            let mut windows = ThreeElemWindowMut::new(&mut simulation_elements);
            while let Some(mut window) = windows.next() {
                // we know from the ThreeElemWindowMut impl that 'window' always has three elements

                let el = window[0].element().clone();
                window[1].set_left_neighbor(Some(el));

                let el = window[1].element().clone();
                window[0].set_right_neighbor(Some(el));

                let el = window[2].element().clone();
                window[1].set_right_neighbor(Some(el));

                let el = window[1].element().clone();
                window[2].set_left_neighbor(Some(el));
            }
        } else if simulation_elements.len() == 2 {
            log::debug!("Having only two landscape elements in the simulation, pairing them now");
            let el = simulation_elements[1].element().clone();
            simulation_elements[0].set_right_neighbor(Some(el));

            let el = simulation_elements[0].element().clone();
            simulation_elements[1].set_left_neighbor(Some(el));
        }

        Ok(simulation_elements)
    }
}

#[derive(getset::Setters, getset::Getters)]
pub struct LandscapeElement {
    #[getset(get = "pub")]
    height: usize,

    #[getset(get = "pub")]
    rain_elements: Vec<RainElement>,
}

impl LandscapeElement {
    fn new(height: usize) -> Self {
        LandscapeElement {
            height,
            rain_elements: Vec::new(),
        }
    }

    pub fn get_current_height(&self) -> f32 {
        let rain: f32 = self.rain_elements.iter().map(|e| e.as_f32()).sum();
        (self.height as f32) + rain
    }

    pub fn increase_rain_level(&mut self, el: RainElement) {
        self.rain_elements.push(el);
    }
}


#[derive(getset::Getters)]
pub struct RainyLandscape {
    #[getset(get = "pub")]
    elements: Vec<Arc<RwLock<LandscapeElement>>>
}

impl RainyLandscape {
    fn new(elements: Vec<Arc<RwLock<LandscapeElement>>>) -> Self {
        RainyLandscape { elements }
    }
}