From 454096cc18ec649ab6f0488763a00af550715061 Mon Sep 17 00:00:00 2001
From: hinto-janaiyo <hinto.janaiyo@protonmail.com>
Date: Tue, 27 Dec 2022 12:58:46 -0500
Subject: [PATCH] Status Submenu: add [Status] to [disk::State]

---
 src/disk.rs   | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/gupax.rs  |   2 +-
 src/main.rs   |  15 +++---
 src/p2pool.rs |   2 +-
 src/status.rs |   6 +--
 src/xmrig.rs  |   2 +-
 6 files changed, 155 insertions(+), 14 deletions(-)

diff --git a/src/disk.rs b/src/disk.rs
index 8e7c048..0c3f59c 100644
--- a/src/disk.rs
+++ b/src/disk.rs
@@ -212,6 +212,7 @@ impl State {
 		let max_threads = num_cpus::get();
 		let current_threads = if max_threads == 1 { 1 } else { max_threads / 2 };
 		Self {
+			status: Status::default(),
 			gupax: Gupax::default(),
 			p2pool: P2pool::default(),
 			xmrig: Xmrig::with_threads(max_threads, current_threads),
@@ -747,6 +748,92 @@ pub enum File {
 	IntBlock,  // total_block  | Single [u128] representing total blocks found
 }
 
+//---------------------------------------------------------------------------------------------------- [Submenu] enum for [Status] tab
+#[derive(Clone,Copy,Eq,PartialEq,Debug,Deserialize,Serialize)]
+pub enum Submenu {
+	Processes,
+	P2pool,
+	Monero,
+}
+
+impl Default for Submenu {
+	fn default() -> Self {
+		Self::Processes
+	}
+}
+
+impl Display for Submenu {
+	fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+		use Submenu::*;
+		match self {
+			P2pool => write!(f, "P2Pool"),
+			_ => write!(f, "{}", self),
+		}
+	}
+}
+
+#[derive(Clone,Copy,Eq,PartialEq,Debug,Deserialize,Serialize)]
+pub enum Hash {
+	Hash,
+	Kilo,
+	Mega,
+	Giga,
+}
+
+impl Default for Hash {
+	fn default() -> Self {
+		Self::Hash
+	}
+}
+
+impl Hash {
+	pub fn convert(f: f64, og: Self, new: Self) -> f64 {
+		match og {
+			Self::Hash => {
+				match new {
+					Self::Hash => f,
+					Self::Kilo => f / 1_000.0,
+					Self::Mega => f / 1_000_000.0,
+					Self::Giga => f / 1_000_000_000.0,
+				}
+			},
+			Self::Kilo => {
+				match new {
+					Self::Hash => f * 1_000.0,
+					Self::Kilo => f,
+					Self::Mega => f / 1_000.0,
+					Self::Giga => f / 1_000_000.0,
+				}
+			},
+			Self::Mega => {
+				match new {
+					Self::Hash => f * 1_000_000.0,
+					Self::Kilo => f * 1_000.0,
+					Self::Mega => f,
+					Self::Giga => f / 1_000.0,
+				}
+			},
+			Self::Giga => {
+				match new {
+					Self::Hash => f * 1_000_000_000.0,
+					Self::Kilo => f * 1_000_000.0,
+					Self::Mega => f * 1_000.0,
+					Self::Giga => f,
+				}
+			},
+		}
+	}
+}
+
+impl Display for Hash {
+	fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+		match self {
+			Hash::Hash => write!(f, "{}", self),
+			_ => write!(f, "{}hash", self),
+		}
+	}
+}
+
 //---------------------------------------------------------------------------------------------------- [Node] Struct
 #[derive(Clone,Eq,PartialEq,Debug,Deserialize,Serialize)]
 pub struct Node {
@@ -766,18 +853,29 @@ pub struct Pool {
 //---------------------------------------------------------------------------------------------------- [State] Struct
 #[derive(Clone,Debug,Deserialize,Serialize)]
 pub struct State {
+	pub status: Status,
 	pub gupax: Gupax,
 	pub p2pool: P2pool,
 	pub xmrig: Xmrig,
 	pub version: Arc<Mutex<Version>>,
 }
 
+#[derive(Clone,PartialEq,Debug,Deserialize,Serialize)]
+pub struct Status {
+	pub submenu: Submenu,
+	pub monero_enabled: bool,
+	pub manual_hash: bool,
+	pub hashrate: f64,
+	pub hash_metric: Hash,
+}
+
 #[derive(Clone,Eq,PartialEq,Debug,Deserialize,Serialize)]
 pub struct Gupax {
 	pub simple: bool,
 	pub auto_update: bool,
 	pub auto_p2pool: bool,
 	pub auto_xmrig: bool,
+//	pub auto_monero: bool,
 	pub ask_before_quit: bool,
 	pub save_before_quit: bool,
 	pub update_via_tor: bool,
@@ -846,6 +944,18 @@ pub struct Version {
 }
 
 //---------------------------------------------------------------------------------------------------- [State] Defaults
+impl Default for Status {
+	fn default() -> Self {
+		Self {
+			submenu: Submenu::default(),
+			monero_enabled: false,
+			manual_hash: false,
+			hashrate: 0.0,
+			hash_metric: Hash::default(),
+		}
+	}
+}
+
 impl Default for Gupax {
 	fn default() -> Self {
 		Self {
@@ -983,6 +1093,13 @@ mod test {
 			tab = "About"
 			ratio = "Width"
 
+			[status]
+			submenu = "P2pool"
+			monero_enabled = true
+			manual_hash = false
+			hashrate = 1241.23
+			hash_metric = "Hash"
+
 			[p2pool]
 			simple = true
 			mini = true
@@ -1201,4 +1318,29 @@ mod test {
 		assert_eq!(api.log_payout, "P2Pool You received a payout of 0.000000000001 XMR in block 2642816");
 		assert_eq!(api.log_block,  "client 127.0.0.1:51111 user asdf found a mainchain block at height 2642816, submitting it");
 	}
+
+	#[test]
+	fn convert_hash() {
+		use crate::disk::Hash;
+		let hash = 1.0;
+		assert_eq!(Hash::convert(hash, Hash::Hash, Hash::Hash), 1.0);
+		assert_eq!(Hash::convert(hash, Hash::Hash, Hash::Kilo), 0.001);
+		assert_eq!(Hash::convert(hash, Hash::Hash, Hash::Mega), 0.000_001);
+		assert_eq!(Hash::convert(hash, Hash::Hash, Hash::Giga), 0.000_000_001);
+		let hash = 1.0;
+		assert_eq!(Hash::convert(hash, Hash::Kilo, Hash::Hash), 1_000.0);
+		assert_eq!(Hash::convert(hash, Hash::Kilo, Hash::Kilo), 1.0);
+		assert_eq!(Hash::convert(hash, Hash::Kilo, Hash::Mega), 0.001);
+		assert_eq!(Hash::convert(hash, Hash::Kilo, Hash::Giga), 0.000_001);
+		let hash = 1.0;
+		assert_eq!(Hash::convert(hash, Hash::Mega, Hash::Hash), 1_000_000.0);
+		assert_eq!(Hash::convert(hash, Hash::Mega, Hash::Kilo), 1_000.0);
+		assert_eq!(Hash::convert(hash, Hash::Mega, Hash::Mega), 1.0);
+		assert_eq!(Hash::convert(hash, Hash::Mega, Hash::Giga), 0.001);
+		let hash = 1.0;
+		assert_eq!(Hash::convert(hash, Hash::Giga, Hash::Hash), 1_000_000_000.0);
+		assert_eq!(Hash::convert(hash, Hash::Giga, Hash::Kilo), 1_000_000.0);
+		assert_eq!(Hash::convert(hash, Hash::Giga, Hash::Mega), 1_000.0);
+		assert_eq!(Hash::convert(hash, Hash::Giga, Hash::Giga), 1.0);
+	}
 }
diff --git a/src/gupax.rs b/src/gupax.rs
index 5411568..3702580 100644
--- a/src/gupax.rs
+++ b/src/gupax.rs
@@ -81,7 +81,7 @@ pub enum Ratio {
 }
 
 //---------------------------------------------------------------------------------------------------- Gupax
-impl Gupax {
+impl crate::disk::Gupax {
 	pub fn show(&mut self, og: &Arc<Mutex<State>>, state_path: &Path, update: &Arc<Mutex<Update>>, file_window: &Arc<Mutex<FileWindow>>, error_state: &mut ErrorState, restart: &Arc<Mutex<Restart>>, width: f32, height: f32, frame: &mut eframe::Frame, _ctx: &egui::Context, ui: &mut egui::Ui) {
 		// Update button + Progress bar
 		debug!("Gupax Tab | Rendering [Update] button + progress bar");
diff --git a/src/main.rs b/src/main.rs
index f396a24..84c4b27 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -63,7 +63,7 @@ mod xmrig;
 mod update;
 mod helper;
 mod human;
-use {ferris::*,constants::*,node::*,disk::*,status::*,update::*,gupax::*,helper::*};
+use {ferris::*,constants::*,node::*,disk::*,update::*,gupax::*,helper::*};
 
 // Sudo (dummy values for Windows)
 mod sudo;
@@ -1314,7 +1314,8 @@ impl eframe::App for App {
 		// They don't need to be compared anyway.
 		debug!("App | Checking diff between [og] & [state]");
 		let og = self.og.lock().unwrap();
-		if og.gupax != self.state.gupax       ||
+		if og.status != self.state.status     ||
+			og.gupax != self.state.gupax      ||
 			og.p2pool != self.state.p2pool    ||
 			og.xmrig != self.state.xmrig      ||
 			self.og_node_vec != self.node_vec ||
@@ -1406,6 +1407,7 @@ impl eframe::App for App {
 					let width = width / 2.0;
 					if key.is_r() && !wants_input && self.diff || ui.add_sized([width, height], Button::new("Reset")).on_hover_text("Reset changes").clicked() {
 						let og = self.og.lock().unwrap().clone();
+						self.state.status = og.status;
 						self.state.gupax = og.gupax;
 						self.state.p2pool = og.p2pool;
 						self.state.xmrig = og.xmrig;
@@ -1416,6 +1418,7 @@ impl eframe::App for App {
 						match State::save(&mut self.state, &self.state_path) {
 							Ok(_) => {
 								let mut og = self.og.lock().unwrap();
+								og.status = self.state.status.clone();
 								og.gupax = self.state.gupax.clone();
 								og.p2pool = self.state.p2pool.clone();
 								og.xmrig = self.state.xmrig.clone();
@@ -1695,19 +1698,19 @@ XMRig console byte length: {}\n
 				}
 				Tab::Status => {
 					debug!("App | Entering [Status] Tab");
-					Status::show(&self.pub_sys, &self.p2pool_api, &self.xmrig_api, &self.p2pool_img, &self.xmrig_img, p2pool_is_alive, xmrig_is_alive, self.max_threads, self.width, self.height, ctx, ui);
+					crate::disk::Status::show(&self.pub_sys, &self.p2pool_api, &self.xmrig_api, &self.p2pool_img, &self.xmrig_img, p2pool_is_alive, xmrig_is_alive, self.max_threads, self.width, self.height, ctx, ui);
 				}
 				Tab::Gupax => {
 					debug!("App | Entering [Gupax] Tab");
-					Gupax::show(&mut self.state.gupax, &self.og, &self.state_path, &self.update, &self.file_window, &mut self.error_state, &self.restart, self.width, self.height, frame, ctx, ui);
+					crate::disk::Gupax::show(&mut self.state.gupax, &self.og, &self.state_path, &self.update, &self.file_window, &mut self.error_state, &self.restart, self.width, self.height, frame, ctx, ui);
 				}
 				Tab::P2pool => {
 					debug!("App | Entering [P2Pool] Tab");
-					P2pool::show(&mut self.state.p2pool, &mut self.node_vec, &self.og, &self.ping, &self.regex, &self.p2pool, &self.p2pool_api, &mut self.p2pool_stdin, self.width, self.height, ctx, ui);
+					crate::disk::P2pool::show(&mut self.state.p2pool, &mut self.node_vec, &self.og, &self.ping, &self.regex, &self.p2pool, &self.p2pool_api, &mut self.p2pool_stdin, self.width, self.height, ctx, ui);
 				}
 				Tab::Xmrig => {
 					debug!("App | Entering [XMRig] Tab");
-					Xmrig::show(&mut self.state.xmrig, &mut self.pool_vec, &self.regex, &self.xmrig, &self.xmrig_api, &mut self.xmrig_stdin, self.width, self.height, ctx, ui);
+					crate::disk::Xmrig::show(&mut self.state.xmrig, &mut self.pool_vec, &self.regex, &self.xmrig, &self.xmrig_api, &mut self.xmrig_stdin, self.width, self.height, ctx, ui);
 				}
 			}
 		});
diff --git a/src/p2pool.rs b/src/p2pool.rs
index e85338e..9b3d827 100644
--- a/src/p2pool.rs
+++ b/src/p2pool.rs
@@ -31,7 +31,7 @@ use std::sync::{Arc,Mutex};
 use regex::Regex;
 use log::*;
 
-impl P2pool {
+impl crate::disk::P2pool {
 	pub fn show(&mut self, node_vec: &mut Vec<(String, Node)>, _og: &Arc<Mutex<State>>, ping: &Arc<Mutex<Ping>>, regex: &Regexes, process: &Arc<Mutex<Process>>, api: &Arc<Mutex<PubP2poolApi>>, buffer: &mut String, width: f32, height: f32, _ctx: &egui::Context, ui: &mut egui::Ui) {
 	let text_edit = height / 25.0;
 	//---------------------------------------------------------------------------------------------------- [Simple] Console
diff --git a/src/status.rs b/src/status.rs
index ea19180..96a06ed 100644
--- a/src/status.rs
+++ b/src/status.rs
@@ -31,11 +31,7 @@ use egui::{
 	TextStyle::Name,
 };
 
-// Main data structure for the Status tab
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct Status {}
-
-impl Status {
+impl crate::disk::Status {
 pub fn show(sys: &Arc<Mutex<Sys>>, p2pool_api: &Arc<Mutex<PubP2poolApi>>, xmrig_api: &Arc<Mutex<PubXmrigApi>>, p2pool_img: &Arc<Mutex<ImgP2pool>>, xmrig_img: &Arc<Mutex<ImgXmrig>>, p2pool_alive: bool, xmrig_alive: bool, max_threads: usize, width: f32, height: f32, _ctx: &egui::Context, ui: &mut egui::Ui) {
 	let width = (width/3.0)-(SPACE*1.666);
 	let min_height = height/1.1;
diff --git a/src/xmrig.rs b/src/xmrig.rs
index 084aad7..549aa18 100644
--- a/src/xmrig.rs
+++ b/src/xmrig.rs
@@ -32,7 +32,7 @@ use std::{
 use regex::Regex;
 use log::*;
 
-impl Xmrig {
+impl crate::disk::Xmrig {
 	pub fn show(&mut self, pool_vec: &mut Vec<(String, Pool)>, regex: &Regexes, process: &Arc<Mutex<Process>>, api: &Arc<Mutex<PubXmrigApi>>, buffer: &mut String, width: f32, height: f32, _ctx: &egui::Context, ui: &mut egui::Ui) {
 	let text_edit = height / 25.0;
 	//---------------------------------------------------------------------------------------------------- [Simple] Console