Browse Source

map/ model: changed node_id from Vec to HashSet

lunar-mining 4 years ago
parent
commit
5c1c55ef47
4 changed files with 123 additions and 79 deletions
  1. 42 20
      bin/map/src/main.rs
  2. 12 8
      bin/map/src/model.rs
  3. 19 51
      bin/map/src/ui.rs
  4. 50 0
      bin/map/src/view.rs

+ 42 - 20
bin/map/src/main.rs

@@ -14,6 +14,7 @@ use log::{debug, info, trace};
 use serde_json::{json, Value};
 use simplelog::*;
 use smol::Executor;
+use std::collections::HashSet;
 use std::{fs::File, io, io::Read, path::PathBuf};
 use termion::{async_stdin, event::Key, input::TermRead, raw::IntoRawMode};
 use tui::{
@@ -102,7 +103,7 @@ async fn main() -> Result<()> {
 
     let infos = Vec::new();
     let info_list = InfoList::new(infos.clone());
-    let ids = Vec::new();
+    let ids = HashSet::new();
     let id_list = IdList::new(ids);
 
     let model = Arc::new(Model::new(id_list, info_list));
@@ -133,7 +134,9 @@ async fn run_rpc(config: &MapConfig, ex: Arc<Executor<'_>>, model: Arc<Model>) -
         rpc_vec.push(node);
     }
     for node in rpc_vec {
+        debug!("Created client: {}", node.node_id);
         let client = Map::new(node.node_id);
+        // TODO: ping/ pong protocol
         ex.spawn(poll(client, model.clone())).detach();
     }
 
@@ -141,7 +144,8 @@ async fn run_rpc(config: &MapConfig, ex: Arc<Executor<'_>>, model: Arc<Model>) -
 }
 
 async fn poll(client: Map, model: Arc<Model>) -> Result<()> {
-    info!("RPC connected to {}", client.url);
+    debug!("Attemping to poll: {}", client.url);
+    let mut index = 0;
     loop {
         let reply = client.get_info().await?;
 
@@ -155,22 +159,33 @@ async fn poll(client: Map, model: Arc<Model>) -> Result<()> {
             let mut outconnects = Vec::new();
             let mut inconnects = Vec::new();
 
+            let msgs = outgoing[1].get("message").unwrap();
+
+            if index == 0 {
+                index += 1;
+            } else if index >= 5 {
+                index = 0
+            } else {
+                index = index + 1;
+            }
+            debug!("INDEX {}", index);
+
             let out0 = Connection::new(
                 outgoing[0].get("id").unwrap().as_str().unwrap().to_string(),
-                outgoing[0].get("message").unwrap().as_str().unwrap().to_string(),
+                msgs[index].as_str().unwrap().to_string(),
             );
             let out1 = Connection::new(
                 outgoing[1].get("id").unwrap().as_str().unwrap().to_string(),
-                outgoing[1].get("message").unwrap().as_str().unwrap().to_string(),
+                msgs[index].as_str().unwrap().to_string(),
             );
 
             let in0 = Connection::new(
                 incoming[0].get("id").unwrap().as_str().unwrap().to_string(),
-                incoming[0].get("message").unwrap().as_str().unwrap().to_string(),
+                msgs[index].as_str().unwrap().to_string(),
             );
             let in1 = Connection::new(
                 incoming[1].get("id").unwrap().as_str().unwrap().to_string(),
-                incoming[1].get("message").unwrap().as_str().unwrap().to_string(),
+                msgs[index].as_str().unwrap().to_string(),
             );
 
             outconnects.push(out0);
@@ -186,25 +201,28 @@ async fn poll(client: Map, model: Arc<Model>) -> Result<()> {
                 incoming: inconnects,
             }];
 
+            let mut id_set = HashSet::new();
             for node in infos {
+                id_set.insert(node.id);
                 // update node info if we don't have it already
-                if !model.id_list.node_id.lock().await.contains(&node.clone().id) {
-                    model.id_list.node_id.lock().await.push(node.clone().id);
-                    debug!("Model ID list: {:?}", model.id_list.node_id.lock().await);
-                    // TODO: update new info if we don't have
-                    model.info_list.infos.lock().await.push(node.clone());
-                    debug!("Model INFO list: {:?}", model.info_list.infos.lock().await);
-                }
+                //if !model.id_list.node_id.lock().await.contains(&node.clone().id) {
+
+                //model.info_list.infos.lock().await.push(node.clone());
+                //debug!("Model ID list: {:?}", model.id_list.node_id.lock().await);
             }
+            model.id_list.node_id.lock().await.union(&id_set);
+            //debug!("Model INFO list: {:?}", model.info_list.infos.lock().await);
+            //}
         } else {
             // TODO: error handling
-            println!("Reply is an error");
+            debug!("Reply is empty");
         }
 
-        async_util::sleep(20).await;
+        async_util::sleep(5).await;
     }
 }
 
+// hashmap union
 async fn render<B: Backend>(
     _config: &MapConfig,
     terminal: &mut Terminal<B>,
@@ -224,10 +242,13 @@ async fn render<B: Backend>(
     loop {
         // on first run, add available nodes
         // every time run the program, simply update nodes
-        view.update(
-            model.id_list.node_id.lock().await.clone(),
-            model.info_list.infos.lock().await.clone(),
-        );
+        //debug!("UPDATE INFO LIST: {:?}", model.info_list.infos.lock().await.clone());
+        //view.update(
+        //    model.id_list.node_id.lock().await.clone(),
+        //    model.info_list.infos.lock().await.clone(),
+        //);
+        //debug!("UPDATE INFO LIST: {:?}", model.info_list.infos.lock().await.clone());
+        //debug!("VIEW {:?}", view.info_list.infos);
         if view.info_list.infos.is_empty() {
             // TODO: make this a loading widget
             // TODO: this lags forever if IRC is not running. add an error
@@ -243,7 +264,7 @@ async fn render<B: Backend>(
             match k.unwrap() {
                 Key::Char('q') => {
                     terminal.clear()?;
-                    return Ok(())
+                    return Ok(());
                 }
                 Key::Char('j') => {
                     view.id_list.next();
@@ -256,5 +277,6 @@ async fn render<B: Backend>(
                 _ => (),
             }
         }
+        //async_util::sleep(1).await;
     }
 }

+ 12 - 8
bin/map/src/model.rs

@@ -1,6 +1,7 @@
 use async_std::sync::Mutex;
 use darkfi::error::Result;
 use log::debug;
+use std::collections::{HashMap, HashSet};
 use tui::widgets::ListState;
 
 pub struct Model {
@@ -14,21 +15,23 @@ impl Model {
     }
 
     pub async fn update(self, infos: Vec<NodeInfo>) -> Result<()> {
-        for node in infos {
-            self.info_list.infos.lock().await.push(node.clone());
-            self.id_list.node_id.lock().await.push(node.clone().id);
-        }
+        //for node in infos {
+        //    self.info_list.infos.lock().await.push(node.clone());
+        //    self.id_list.node_id.lock().await.push(node.clone().id);
+        //}
+        // Hashset will be a union
         Ok(())
     }
 }
 
 pub struct IdList {
     pub state: Mutex<ListState>,
-    pub node_id: Mutex<Vec<String>>,
+    pub node_id: Mutex<HashSet<String>>,
 }
 
 impl IdList {
-    pub fn new(node_id: Vec<String>) -> IdList {
+    // change vec to hashset
+    pub fn new(node_id: HashSet<String>) -> IdList {
         let node_id = Mutex::new(node_id);
         IdList { state: Mutex::new(ListState::default()), node_id }
     }
@@ -36,6 +39,7 @@ impl IdList {
 
 pub struct InfoList {
     pub index: Mutex<usize>,
+    // hashmap
     pub infos: Mutex<Vec<NodeInfo>>,
 }
 
@@ -49,7 +53,7 @@ impl InfoList {
     }
 }
 
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
 pub struct NodeInfo {
     pub id: String,
     pub outgoing: Vec<Connection>,
@@ -62,7 +66,7 @@ impl NodeInfo {
     }
 }
 
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
 pub struct Connection {
     pub id: String,
     pub message: String,

+ 19 - 51
bin/map/src/ui.rs

@@ -17,30 +17,13 @@ pub fn ui<B: Backend>(f: &mut Frame<'_, B>, mut view: View) {
         .split(f.size());
 
     let info = &view.info_list.infos;
+    //debug!("UI ID LIST: {:?}", view.id_list.node_id);
+    //debug!("UI INFO LIST: {:?}", view.info_list.infos);
     let index = view.info_list.index;
 
     let iconnects = info[index].incoming.clone();
     let oconnects = info[index].outgoing.clone();
 
-    let mut iconnect_ids = Vec::new();
-    let mut oconnect_ids = Vec::new();
-
-    if !iconnects.is_empty() {
-        for connect in iconnects {
-            iconnect_ids.push(connect.id);
-        }
-    } else {
-        // TODO: Render 'info not found'
-        debug!("EMPTY VECTOR");
-    }
-    if !oconnects.is_empty() {
-        for connect in oconnects {
-            oconnect_ids.push(connect.id);
-        }
-    } else {
-        debug!("EMPTY VECTOR");
-    }
-
     let nodes: Vec<ListItem> = view
         .id_list
         .node_id
@@ -49,11 +32,23 @@ pub fn ui<B: Backend>(f: &mut Frame<'_, B>, mut view: View) {
             let mut lines = vec![Spans::from(id.to_string())];
             for line in lines.clone() {
                 lines.push(Spans::from(Span::styled("  Outgoing:", Style::default())));
-                lines.push(Spans::from(format!("    {}", oconnect_ids[0])));
-                lines.push(Spans::from(format!("    {}", oconnect_ids[1])));
+                lines.push(Spans::from(format!(
+                    "    {}         [R: {}]",
+                    oconnects[0].id, oconnects[0].message
+                )));
+                lines.push(Spans::from(format!(
+                    "    {}         [S: {}]",
+                    oconnects[1].id, oconnects[1].message
+                )));
                 lines.push(Spans::from(Span::styled("  Incoming:", Style::default())));
-                lines.push(Spans::from(format!("    {}", iconnect_ids[0])));
-                lines.push(Spans::from(format!("    {}", iconnect_ids[1])));
+                lines.push(Spans::from(format!(
+                    "    {}         [R: {}]",
+                    iconnects[0].id, iconnects[0].message
+                )));
+                lines.push(Spans::from(format!(
+                    "    {}         [S: {}]",
+                    iconnects[1].id, iconnects[1].message
+                )));
             }
             ListItem::new(lines).style(Style::default())
         })
@@ -70,34 +65,7 @@ pub fn ui<B: Backend>(f: &mut Frame<'_, B>, mut view: View) {
 }
 
 fn render_info_right<B: Backend>(view: View, f: &mut Frame<'_, B>, index: usize, slice: Vec<Rect>) {
-    let info = &view.info_list.infos;
-
-    let iconnects = info[index].incoming.clone();
-    let oconnects = info[index].outgoing.clone();
-
-    let mut iconnect_msgs = Vec::new();
-    let mut oconnect_msgs = Vec::new();
-
-    if !iconnects.is_empty() {
-        for connect in iconnects {
-            iconnect_msgs.push(connect.message)
-        }
-    }
-    if !oconnects.is_empty() {
-        for connect in oconnects {
-            oconnect_msgs.push(connect.message);
-        }
-    }
-    let span = vec![
-        Spans::from(format!("Last message:")),
-        Spans::from(format!("")),
-        Spans::from(format!("{}", oconnect_msgs[0])),
-        Spans::from(format!("{}", oconnect_msgs[1])),
-        Spans::from(format!("")),
-        Spans::from(format!("")),
-        Spans::from(format!("{}", oconnect_msgs[0])),
-        Spans::from(format!("{}", oconnect_msgs[1])),
-    ];
+    let span = vec![];
     let graph =
         Paragraph::new(span).block(Block::default().borders(Borders::ALL)).style(Style::default());
     f.render_widget(graph, slice[1]);

+ 50 - 0
bin/map/src/view.rs

@@ -1,5 +1,6 @@
 use crate::model::NodeInfo;
 use log::debug;
+use std::collections::HashSet;
 use tui::widgets::ListState;
 
 #[derive(Clone)]
@@ -13,13 +14,60 @@ impl View {
         View { id_list, info_list }
     }
 
+    // do we have this node id?
+    //      if not, add everything
+    //
+    //      if yes, do we have these connections?
+    //          if not, add everything
+    //          if yes, do we have these msgs?
+    //              if not, add
     pub fn update(&mut self, node_id: Vec<String>, infos: Vec<NodeInfo>) {
+        // TODO: change nodeinfo.id to hashmap(k)
+        //
+        //let mut index = 0;
         for node in node_id.clone() {
             if !self.id_list.node_id.contains(&node) {
                 self.id_list.update(node_id.clone());
                 self.info_list.update(infos.clone());
             }
+            //for info in self.info_list.infos.clone() {
+            //    index = index + 1;
+            //    if !info.outgoing.contains(&infos[index].outgoing[index]) {
+            //        info.outgoing.update(&infos[index].outgoing[index])
+            //    }
+            //}
         }
+        // all node ids that are not contained
+        //debug!("UPDATE CALLED");
+        //debug!("INFOS {:?}", infos);
+        // node_id.union(self.id_list.node_id)
+        //let new_node_ids =
+        //    node_id.into_iter().filter(|id| !self.id_list.node_id.contains(id)).collect();
+        ////[self.id_list.node_id, new_node_ids].concat();
+        //self.id_list.update(new_node_ids);
+
+        //// all node infos of node info that is different
+        //// hashmap union
+        //let mut new_node_info: HashSet<NodeInfo> = infos
+        //    .into_iter()
+        //    .filter_map(|id| {
+        //        let opt_ni = self.info_list.infos.iter().find(|inf| inf.id == id.id);
+        //        opt_ni.map(|ni| (ni, id))
+        //    })
+        //    .filter(|(view_ni, ni)| *view_ni != ni)
+        //    .map(|(_, ni)| ni)
+        //    .collect();
+
+        //debug!("NEW NODE INFO: {:?}", new_node_info);
+        //self.info_list.infos = self
+        //    .info_list
+        //    .infos
+        //    .iter()
+        //    .cloned()
+        //    //.map(|i| new_node_info.find(|inf| i == *inf).map_or(i, |inf| inf))
+        //    .map(|i| new_node_info.get(&i).map_or(i, |inf| inf.clone()))
+        //    .collect();
+        ////self.info_list.update(new_node_info);
     }
 }
 
@@ -92,6 +140,8 @@ impl InfoListView {
         self.index = (self.index + 1) % self.infos.len();
     }
 
+    // TODO: fix crash
+    // == 0
     pub async fn previous(&mut self) {
         if self.index > 0 {
             self.index -= 1;