diff --git a/src/constants.rs b/src/constants.rs index ea2d715..ec500cc 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -197,6 +197,9 @@ pub const P2POOL_LOG: &str = "Verbosity of the console log"; pub const P2POOL_AUTO_NODE: &str = "Automatically ping the community Monero nodes at Gupax startup"; pub const P2POOL_AUTO_SELECT: &str = "Automatically select the fastest community Monero node after pinging"; pub const P2POOL_SELECT_FASTEST: &str = "Select the fastest community Monero node"; +pub const P2POOL_SELECT_RANDOM: &str = "Select a random community Monero node"; +pub const P2POOL_SELECT_LAST: &str = "Select the previous community Monero node"; +pub const P2POOL_SELECT_NEXT: &str = "Select the next community Monero node"; pub const P2POOL_PING: &str = "Ping the built-in community Monero nodes"; pub const P2POOL_ADDRESS: &str = "You must use a primary Monero address to mine on P2Pool (starts with a 4). It is highly recommended to create a new wallet since addresses are public on P2Pool!"; pub const P2POOL_INPUT: &str = "Send a command to P2Pool"; diff --git a/src/node.rs b/src/node.rs index cda079d..4f21cab 100644 --- a/src/node.rs +++ b/src/node.rs @@ -19,6 +19,7 @@ use crate::{ constants::*, }; use serde::{Serialize,Deserialize}; +use rand::{thread_rng, Rng}; use std::time::{Instant,Duration}; use std::sync::{Arc,Mutex}; use egui::Color32; @@ -56,12 +57,88 @@ pub const NODE_IPS: [&str; 17] = [ MONERUJO,PLOWSOF_1,PLOWSOF_2,RINO,SETH,SUPPORTXMR,SUPPORTXMR_IR,XMRVSBEAST, ]; +pub const COMMUNITY_NODE_LENGTH: usize = NODE_IPS.len(); + #[derive(Copy,Clone,Eq,PartialEq,Debug,Deserialize,Serialize)] pub enum NodeEnum { C3pool,Cake,CakeEu,CakeUk,CakeUs,MajesticBankIs,MajesticBankSu,Monerujo,Plowsof1, Plowsof2,Rino,Feather1,Feather2,Seth,SupportXmr,SupportXmrIr,XmrVsBeast, } +impl NodeEnum { + fn get_index(&self) -> usize { + match self { + C3pool => 0, + Cake => 1, + CakeEu => 2, + CakeUk => 3, + CakeUs => 4, + Feather1 => 5, + Feather2 => 6, + MajesticBankIs => 7, + MajesticBankSu => 8, + Monerujo => 9, + Plowsof1 => 10, + Plowsof2 => 11, + Rino => 12, + Seth => 13, + SupportXmr => 14, + SupportXmrIr => 15, + _ => 16, + } + } + + // Return a random node (that isn't the one already selected). + pub fn get_random(&self) -> Self { + let index = Self::get_index(self); + let mut rand = thread_rng().gen_range(0..COMMUNITY_NODE_LENGTH); + while rand == index { + rand = thread_rng().gen_range(0..COMMUNITY_NODE_LENGTH); + } + ip_to_enum(NODE_IPS[rand]) + } + + // Return the node [-1] of this one (wraps around) + pub fn get_last(&self) -> Self { + let index = Self::get_index(self); + if index == 0 { + ip_to_enum(NODE_IPS[COMMUNITY_NODE_LENGTH-1]) + } else { + ip_to_enum(NODE_IPS[index-1]) + } + } + + // Return the node [+1] of this one (wraps around) + pub fn get_next(&self) -> Self { + let index = Self::get_index(self); + if index == COMMUNITY_NODE_LENGTH-1 { + ip_to_enum(NODE_IPS[0]) + } else { + ip_to_enum(NODE_IPS[index+1]) + } + } + + // This returns relative to the ping. + pub fn get_last_from_ping(&self, nodes: &Vec<NodeData>) -> Self { + let mut found = false; + let mut last = *self; + for data in nodes { + if found { return last } + if *self == data.id { found = true; } else { last = data.id; } + } + last + } + + pub fn get_next_from_ping(&self, nodes: &Vec<NodeData>) -> Self { + let mut found = false; + for data in nodes { + if found { return data.id } + if *self == data.id { found = true; } + } + *self + } +} + impl std::fmt::Display for NodeEnum { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{:#?}", self) @@ -225,6 +302,7 @@ impl Ping { ping.lock().unwrap().msg = msg; ping.lock().unwrap().pinged = true; ping.lock().unwrap().auto_selected = false; + ping.lock().unwrap().prog = 100.0; }, Err(err) => { error!("Ping ... FAIL ... {}", err); @@ -260,7 +338,7 @@ impl Ping { let ping = Arc::clone(ping); ping.lock().unwrap().pinging = true; ping.lock().unwrap().prog = 0.0; - let percent = (100.0 / ((NODE_IPS.len()) as f32)).floor(); + let percent = (100.0 / (COMMUNITY_NODE_LENGTH as f32)).floor(); // Create HTTP client let info = "Creating HTTP Client".to_string(); @@ -271,8 +349,8 @@ impl Ping { // Random User Agent let rand_user_agent = crate::Pkg::get_user_agent(); // Handle vector - let mut handles = Vec::with_capacity(NODE_IPS.len()); - let node_vec = Arc::new(Mutex::new(Vec::with_capacity(NODE_IPS.len()))); + let mut handles = Vec::with_capacity(COMMUNITY_NODE_LENGTH); + let node_vec = Arc::new(Mutex::new(Vec::with_capacity(COMMUNITY_NODE_LENGTH))); for ip in NODE_IPS { let client = client.clone(); @@ -300,7 +378,6 @@ impl Ping { let mut ping = ping.lock().unwrap(); ping.fastest = node_vec[0].id; ping.nodes = node_vec; - ping.prog = 100.0; ping.msg = info; drop(ping); Ok(fastest_info) diff --git a/src/p2pool.rs b/src/p2pool.rs index b4ccae7..1d91ac9 100644 --- a/src/p2pool.rs +++ b/src/p2pool.rs @@ -164,17 +164,40 @@ impl P2pool { debug!("P2Pool Tab | Rendering [Select fastest ... Ping] buttons"); ui.horizontal(|ui| { - let width = (width/2.0)-4.0; - // [Select fastest node] - if ui.add_sized([width, height], Button::new("Select fastest node")).on_hover_text(P2POOL_SELECT_FASTEST).clicked() && ping.lock().unwrap().pinged { - self.node = ping.lock().unwrap().fastest; - } - - // [Ping Button] - ui.set_enabled(!ping.lock().unwrap().pinging); - if ui.add_sized([width, height], Button::new("Ping community nodes")).on_hover_text(P2POOL_PING).clicked() { - Ping::spawn_thread(ping); - }}); + let width = (width/5.0)-6.0; + // [Select random node] + if ui.add_sized([width, height], Button::new("Select random node")).on_hover_text(P2POOL_SELECT_RANDOM).clicked() { + self.node = NodeEnum::get_random(&self.node); + } + // [Select fastest node] + if ui.add_sized([width, height], Button::new("Select fastest node")).on_hover_text(P2POOL_SELECT_FASTEST).clicked() && ping.lock().unwrap().pinged { + self.node = ping.lock().unwrap().fastest; + } + // [Ping Button] + ui.add_enabled_ui(!ping.lock().unwrap().pinging, |ui| { + if ui.add_sized([width, height], Button::new("Ping community nodes")).on_hover_text(P2POOL_PING).clicked() { + Ping::spawn_thread(ping); + } + }); + // [Last <-] + if ui.add_sized([width, height], Button::new("⬅ Last")).on_hover_text(P2POOL_SELECT_LAST).clicked() { + let ping = ping.lock().unwrap(); + match ping.pinged { + true => self.node = NodeEnum::get_last_from_ping(&self.node, &ping.nodes), + false => self.node = NodeEnum::get_last(&self.node), + } + drop(ping); + } + // [Next ->] + if ui.add_sized([width, height], Button::new("Next ➡")).on_hover_text(P2POOL_SELECT_NEXT).clicked() { + let ping = ping.lock().unwrap(); + match ping.pinged { + true => self.node = NodeEnum::get_next_from_ping(&self.node, &ping.nodes), + false => self.node = NodeEnum::get_next(&self.node), + } + drop(ping); + } + }); ui.vertical(|ui| { let height = height / 2.0;