1 use crate::util::{RandomSignal, SinSignal, StatefulList, TabsState}; 2 3 const TASKS: [&str; 24] = [ 4 "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9", "Item10", 5 "Item11", "Item12", "Item13", "Item14", "Item15", "Item16", "Item17", "Item18", "Item19", 6 "Item20", "Item21", "Item22", "Item23", "Item24", 7 ]; 8 9 const LOGS: [(&str, &str); 26] = [ 10 ("Event1", "INFO"), 11 ("Event2", "INFO"), 12 ("Event3", "CRITICAL"), 13 ("Event4", "ERROR"), 14 ("Event5", "INFO"), 15 ("Event6", "INFO"), 16 ("Event7", "WARNING"), 17 ("Event8", "INFO"), 18 ("Event9", "INFO"), 19 ("Event10", "INFO"), 20 ("Event11", "CRITICAL"), 21 ("Event12", "INFO"), 22 ("Event13", "INFO"), 23 ("Event14", "INFO"), 24 ("Event15", "INFO"), 25 ("Event16", "INFO"), 26 ("Event17", "ERROR"), 27 ("Event18", "ERROR"), 28 ("Event19", "INFO"), 29 ("Event20", "INFO"), 30 ("Event21", "WARNING"), 31 ("Event22", "INFO"), 32 ("Event23", "INFO"), 33 ("Event24", "WARNING"), 34 ("Event25", "INFO"), 35 ("Event26", "INFO"), 36 ]; 37 38 const EVENTS: [(&str, u64); 24] = [ 39 ("B1", 9), 40 ("B2", 12), 41 ("B3", 5), 42 ("B4", 8), 43 ("B5", 2), 44 ("B6", 4), 45 ("B7", 5), 46 ("B8", 9), 47 ("B9", 14), 48 ("B10", 15), 49 ("B11", 1), 50 ("B12", 0), 51 ("B13", 4), 52 ("B14", 6), 53 ("B15", 4), 54 ("B16", 6), 55 ("B17", 4), 56 ("B18", 7), 57 ("B19", 13), 58 ("B20", 8), 59 ("B21", 11), 60 ("B22", 9), 61 ("B23", 3), 62 ("B24", 5), 63 ]; 64 65 pub struct Signal<S: Iterator> { 66 source: S, 67 pub points: Vec<S::Item>, 68 tick_rate: usize, 69 } 70 71 impl<S> Signal<S> 72 where 73 S: Iterator, 74 { on_tick(&mut self)75 fn on_tick(&mut self) { 76 for _ in 0..self.tick_rate { 77 self.points.remove(0); 78 } 79 self.points 80 .extend(self.source.by_ref().take(self.tick_rate)); 81 } 82 } 83 84 pub struct Signals { 85 pub sin1: Signal<SinSignal>, 86 pub sin2: Signal<SinSignal>, 87 pub window: [f64; 2], 88 } 89 90 impl Signals { on_tick(&mut self)91 fn on_tick(&mut self) { 92 self.sin1.on_tick(); 93 self.sin2.on_tick(); 94 self.window[0] += 1.0; 95 self.window[1] += 1.0; 96 } 97 } 98 99 pub struct Server<'a> { 100 pub name: &'a str, 101 pub location: &'a str, 102 pub coords: (f64, f64), 103 pub status: &'a str, 104 } 105 106 pub struct App<'a> { 107 pub title: &'a str, 108 pub should_quit: bool, 109 pub tabs: TabsState<'a>, 110 pub show_chart: bool, 111 pub progress: f64, 112 pub sparkline: Signal<RandomSignal>, 113 pub tasks: StatefulList<&'a str>, 114 pub logs: StatefulList<(&'a str, &'a str)>, 115 pub signals: Signals, 116 pub barchart: Vec<(&'a str, u64)>, 117 pub servers: Vec<Server<'a>>, 118 pub enhanced_graphics: bool, 119 } 120 121 impl<'a> App<'a> { new(title: &'a str, enhanced_graphics: bool) -> App<'a>122 pub fn new(title: &'a str, enhanced_graphics: bool) -> App<'a> { 123 let mut rand_signal = RandomSignal::new(0, 100); 124 let sparkline_points = rand_signal.by_ref().take(300).collect(); 125 let mut sin_signal = SinSignal::new(0.2, 3.0, 18.0); 126 let sin1_points = sin_signal.by_ref().take(100).collect(); 127 let mut sin_signal2 = SinSignal::new(0.1, 2.0, 10.0); 128 let sin2_points = sin_signal2.by_ref().take(200).collect(); 129 App { 130 title, 131 should_quit: false, 132 tabs: TabsState::new(vec!["Tab0", "Tab1", "Tab2"]), 133 show_chart: true, 134 progress: 0.0, 135 sparkline: Signal { 136 source: rand_signal, 137 points: sparkline_points, 138 tick_rate: 1, 139 }, 140 tasks: StatefulList::with_items(TASKS.to_vec()), 141 logs: StatefulList::with_items(LOGS.to_vec()), 142 signals: Signals { 143 sin1: Signal { 144 source: sin_signal, 145 points: sin1_points, 146 tick_rate: 5, 147 }, 148 sin2: Signal { 149 source: sin_signal2, 150 points: sin2_points, 151 tick_rate: 10, 152 }, 153 window: [0.0, 20.0], 154 }, 155 barchart: EVENTS.to_vec(), 156 servers: vec![ 157 Server { 158 name: "NorthAmerica-1", 159 location: "New York City", 160 coords: (40.71, -74.00), 161 status: "Up", 162 }, 163 Server { 164 name: "Europe-1", 165 location: "Paris", 166 coords: (48.85, 2.35), 167 status: "Failure", 168 }, 169 Server { 170 name: "SouthAmerica-1", 171 location: "São Paulo", 172 coords: (-23.54, -46.62), 173 status: "Up", 174 }, 175 Server { 176 name: "Asia-1", 177 location: "Singapore", 178 coords: (1.35, 103.86), 179 status: "Up", 180 }, 181 ], 182 enhanced_graphics, 183 } 184 } 185 on_up(&mut self)186 pub fn on_up(&mut self) { 187 self.tasks.previous(); 188 } 189 on_down(&mut self)190 pub fn on_down(&mut self) { 191 self.tasks.next(); 192 } 193 on_right(&mut self)194 pub fn on_right(&mut self) { 195 self.tabs.next(); 196 } 197 on_left(&mut self)198 pub fn on_left(&mut self) { 199 self.tabs.previous(); 200 } 201 on_key(&mut self, c: char)202 pub fn on_key(&mut self, c: char) { 203 match c { 204 'q' => { 205 self.should_quit = true; 206 } 207 't' => { 208 self.show_chart = !self.show_chart; 209 } 210 _ => {} 211 } 212 } 213 on_tick(&mut self)214 pub fn on_tick(&mut self) { 215 // Update progress 216 self.progress += 0.001; 217 if self.progress > 1.0 { 218 self.progress = 0.0; 219 } 220 221 self.sparkline.on_tick(); 222 self.signals.on_tick(); 223 224 let log = self.logs.items.pop().unwrap(); 225 self.logs.items.insert(0, log); 226 227 let event = self.barchart.pop().unwrap(); 228 self.barchart.insert(0, event); 229 } 230 } 231