From 1c2f7d32ec504b75ccade923721c8e8c4753a67a Mon Sep 17 00:00:00 2001
From: hinto-janaiyo <hinto.janaiyo@protonmail.com>
Date: Sun, 11 Dec 2022 20:43:34 -0500
Subject: [PATCH] helper/sudo: small p2pool api fixes, don't allow ESC when
 [testing]

---
 README.md        |  8 ++++++--
 src/constants.rs |  8 ++++++++
 src/helper.rs    | 23 ++++++++++++++++++-----
 src/main.rs      |  4 ++--
 src/status.rs    | 45 ++++++++++++++++++++++++++++++++-------------
 5 files changed, 66 insertions(+), 22 deletions(-)

diff --git a/README.md b/README.md
index d5d562b..bba4b3b 100644
--- a/README.md
+++ b/README.md
@@ -16,10 +16,10 @@ Gupax (*guh-picks*) is a (Windows|macOS|Linux) GUI for mining [**Monero**](https
 - [Advanced](#Advanced)
 	- [Verifying](#Verifying)
 	- [Command Line](#Command-Line)
-	- [Tor/Arti](#Tor-Arti)
+	- [Tor/Arti](#TorArti)
 	- [Logs](#Logs)
 	- [Disk](#Disk)
-	- [Swapping P2Pool/XMRig](#Swapping-P2Pool-XMRig)
+	- [Swapping P2Pool/XMRig](#Swapping-P2PoolXMRig)
 	- [Gupax](#Gupax)
 	- [P2Pool](#P2Pool)
 	- [XMRig](#XMRig)
@@ -109,6 +109,10 @@ With Monero GUI managing the Monero node on one side and Gupax managing P2Pool/X
 
 ---
 
+### Swapping P2Pool/XMRig
+
+---
+
 ### Gupax
 
 ---
diff --git a/src/constants.rs b/src/constants.rs
index 11acba7..f7ea51b 100644
--- a/src/constants.rs
+++ b/src/constants.rs
@@ -118,6 +118,14 @@ pub const STATUS_GUPAX_MEMORY_USAGE: &str = "How much memory Gupax is currently
 pub const STATUS_GUPAX_SYSTEM_CPU_USAGE: &str = "How much CPU your entire system is currently using. This accounts for all your threads (it is out of 100%)";
 pub const STATUS_GUPAX_SYSTEM_MEMORY: &str = "How much memory your entire system has (including swap) and is currently using in Gigabytes";
 pub const STATUS_GUPAX_SYSTEM_CPU_MODEL: &str = "The detected model of your system's CPU and its current frequency";
+//--
+pub const STATUS_P2POOL_UPTIME: &str = "How long P2Pool has been online";
+pub const STATUS_P2POOL_PAYOUTS: &str = "The total amount of payouts received and an extrapolated estimate of how many you will receive. Warning: these stats will be quite inaccurate if your P2Pool hasn't been running for a long time!";
+pub const STATUS_P2POOL_XMR: &str = "The total amount of XMR mined via P2Pool and an extrapolated estimate of how many you will mine in the future. Warning: these stats will be quite inaccurate if your P2Pool hasn't been running for a long time!";
+pub const STATUS_P2POOL_HASHRATE: &str = "The total amount of hashrate your P2Pool has pointed at it in 15 minute, 1 hour, and 24 hour averages";
+pub const STATUS_P2POOL_SHARES: &str = "The total amount of shares found on P2Pool";
+pub const STATUS_P2POOL_EFFORT: &str = "The average amount of effort needed to find a share, and the current effort";
+pub const STATUS_P2POOL_CONNECTIONS: &str = "The total amount of miner connections on this P2Pool";
 
 // Gupax
 pub const GUPAX_UPDATE: &str = "Check for updates on Gupax, P2Pool, and XMRig via GitHub's API and upgrade automatically";
diff --git a/src/helper.rs b/src/helper.rs
index 8ca64e3..d273067 100644
--- a/src/helper.rs
+++ b/src/helper.rs
@@ -453,6 +453,20 @@ impl Helper {
 
 		path.pop();
 		path.push(P2POOL_API_PATH);
+		// Attempt to remove stale API file
+		match std::fs::remove_file(&path) {
+			Ok(_) => info!("P2Pool | Attempting to remove stale API file ... OK"),
+			Err(e) => warn!("P2Pool | Attempting to remove stale API file ... FAIL ... {}", e),
+		}
+		// Attempt to create a default empty one.
+		use std::io::Write;
+		if let Ok(_) = std::fs::File::create(&path) {
+			let text = r#"{"hashrate_15m":0,"hashrate_1h":0,"hashrate_24h":0,"shares_found":0,"average_effort":0.0,"current_effort":0.0,"connections":0}"#;
+			match std::fs::write(&path, text) {
+				Ok(_) => info!("P2Pool | Creating default empty API file ... OK"),
+				Err(e) => warn!("P2Pool | Creating default empty API file ... FAIL ... {}", e),
+			}
+		}
 		let regex = P2poolRegex::new();
 		let start = process.lock().unwrap().start;
 
@@ -528,7 +542,7 @@ impl Helper {
 				// Deserialize
 				if let Ok(s) = PrivP2poolApi::str_to_priv_p2pool_api(&string) {
 					// Update the structs.
-					PubP2poolApi::update_from_priv(&pub_api, &priv_api);
+					PubP2poolApi::update_from_priv(&pub_api, s);
 				}
 			}
 
@@ -1319,9 +1333,8 @@ impl PubP2poolApi {
 	}
 
 	// Mutate [PubP2poolApi] with data from a [PrivP2poolApi] and the process output.
-	fn update_from_priv(public: &Arc<Mutex<Self>>, private: &Arc<Mutex<PrivP2poolApi>>) {
+	fn update_from_priv(public: &Arc<Mutex<Self>>, private: PrivP2poolApi) {
 		// priv -> pub conversion
-		let private = private.lock().unwrap();
 		let mut public = public.lock().unwrap();
 		*public = Self {
 			hashrate_15m: HumanNumber::from_u128(private.hashrate_15m),
@@ -1331,8 +1344,8 @@ impl PubP2poolApi {
 			average_effort: HumanNumber::to_percent(private.average_effort),
 			current_effort: HumanNumber::to_percent(private.current_effort),
 			connections: HumanNumber::from_u16(private.connections),
-			..public.clone()
-		}
+			..std::mem::take(&mut *public)
+		};
 	}
 
 	// Essentially greps the output for [x.xxxxxxxxxxxx XMR] where x = a number.
diff --git a/src/main.rs b/src/main.rs
index 8965da9..4a934e0 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1041,7 +1041,7 @@ impl eframe::App for App {
 							let color = if hide { BLACK } else { BRIGHT_YELLOW };
 							if ui.add_sized([box_width, height], Button::new(RichText::new("👁").color(color))).on_hover_text(PASSWORD_HIDE).clicked() { sudo.hide = !sudo.hide; }
 						});
-						if esc || ui.add_sized([width, height*4.0], Button::new("Leave")).clicked() { self.error_state.reset(); };
+						if (esc && !sudo.testing) || ui.add_sized([width, height*4.0], Button::new("Leave")).clicked() { self.error_state.reset(); };
 						// If [test_sudo()] finished, reset error state.
 						if sudo.success {
 							self.error_state.reset();
@@ -1336,7 +1336,7 @@ impl eframe::App for App {
 					});
 				}
 				Tab::Status => {
-					Status::show(&self.pub_sys, &self.p2pool_api, &self.xmrig_api, &self.p2pool_img, &self.xmrig_img, self.width, self.height, ctx, ui);
+					Status::show(&self.pub_sys, &self.p2pool_api, &self.xmrig_api, &self.p2pool_img, &self.xmrig_img, self.p2pool.lock().unwrap().is_alive(), self.xmrig.lock().unwrap().is_alive(), self.width, self.height, ctx, ui);
 				}
 				Tab::Gupax => {
 					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);
diff --git a/src/status.rs b/src/status.rs
index 8101212..babcdfe 100644
--- a/src/status.rs
+++ b/src/status.rs
@@ -35,41 +35,60 @@ use egui::{
 pub struct Status {}
 
 impl 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>>, width: f32, height: f32, ctx: &egui::Context, ui: &mut egui::Ui) {
+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_online: bool, xmrig_online: bool, width: f32, height: f32, ctx: &egui::Context, ui: &mut egui::Ui) {
 	let width = (width/3.0)-(SPACE*1.666);
 	let min_height = height/1.14;
-	let height = height/20.0;
+	let height = height/25.0;
 	ui.horizontal(|ui| {
 	// [Gupax]
 	ui.group(|ui| { ui.vertical(|ui| {
 		ui.set_min_height(min_height);
-		ui.add_sized([width, height*2.0], Label::new(RichText::new("[Gupax]").color(LIGHT_GRAY).text_style(TextStyle::Name("MonospaceLarge".into()))));
+		ui.add_sized([width, height*2.0], Label::new(RichText::new("[Gupax]").color(LIGHT_GRAY).text_style(TextStyle::Name("MonospaceLarge".into())))).on_hover_text("Gupax is online");
 		// Uptime
+		let sys = sys.lock().unwrap();
 		ui.add_sized([width, height], Label::new(RichText::new("Uptime").underline().color(BONE))).on_hover_text(STATUS_GUPAX_UPTIME);
-		ui.add_sized([width, height], Label::new(format!("{}", sys.lock().unwrap().gupax_uptime)));
+		ui.add_sized([width, height], Label::new(format!("{}", sys.gupax_uptime)));
 		ui.add_sized([width, height], Label::new(RichText::new("Gupax CPU").underline().color(BONE))).on_hover_text(STATUS_GUPAX_CPU_USAGE);
-		ui.add_sized([width, height], Label::new(format!("{}", sys.lock().unwrap().gupax_cpu_usage)));
+		ui.add_sized([width, height], Label::new(format!("{}", sys.gupax_cpu_usage)));
 		ui.add_sized([width, height], Label::new(RichText::new("Gupax Memory").underline().color(BONE))).on_hover_text(STATUS_GUPAX_MEMORY_USAGE);
-		ui.add_sized([width, height], Label::new(format!("{}", sys.lock().unwrap().gupax_memory_used_mb)));
+		ui.add_sized([width, height], Label::new(format!("{}", sys.gupax_memory_used_mb)));
 		ui.add_sized([width, height], Label::new(RichText::new("System CPU").underline().color(BONE))).on_hover_text(STATUS_GUPAX_SYSTEM_CPU_USAGE);
-		ui.add_sized([width, height], Label::new(format!("{}", sys.lock().unwrap().system_cpu_usage)));
+		ui.add_sized([width, height], Label::new(format!("{}", sys.system_cpu_usage)));
 		ui.add_sized([width, height], Label::new(RichText::new("System Memory").underline().color(BONE))).on_hover_text(STATUS_GUPAX_SYSTEM_MEMORY);
-		ui.add_sized([width, height], Label::new(format!("{}", sys.lock().unwrap().system_memory)));
+		ui.add_sized([width, height], Label::new(format!("{}", sys.system_memory)));
 		ui.add_sized([width, height], Label::new(RichText::new("System CPU Model").underline().color(BONE))).on_hover_text(STATUS_GUPAX_SYSTEM_CPU_MODEL);
-		ui.add_sized([width, height], Label::new(format!("{}", sys.lock().unwrap().system_cpu_model)));
+		ui.add_sized([width, height], Label::new(format!("{}", sys.system_cpu_model)));
+		drop(sys);
 	})});
 	// [P2Pool]
 	ui.group(|ui| { ui.vertical(|ui| {
+		ui.set_enabled(p2pool_online);
 		ui.set_min_height(min_height);
-		ui.add_sized([width, height*2.0], Label::new(RichText::new("[P2Pool]").color(LIGHT_GRAY).text_style(TextStyle::Name("MonospaceLarge".into()))));
+		ui.add_sized([width, height*2.0], Label::new(RichText::new("[P2Pool]").color(LIGHT_GRAY).text_style(TextStyle::Name("MonospaceLarge".into())))).on_hover_text("P2Pool is online").on_disabled_hover_text("P2Pool is offline");
 		// Uptime
-		ui.add_sized([width, height], Label::new(RichText::new("Uptime").underline()));
-		ui.add_sized([width, height], Label::new(format!("{}", p2pool_api.lock().unwrap().uptime)));
+		let api = p2pool_api.lock().unwrap();
+		ui.add_sized([width, height], Label::new(RichText::new("Uptime").underline().color(BONE))).on_hover_text(STATUS_P2POOL_UPTIME);
+		ui.add_sized([width, height], Label::new(format!("{}", api.uptime)));
+		ui.add_sized([width, height], Label::new(RichText::new("Shares Found").underline().color(BONE))).on_hover_text(STATUS_P2POOL_SHARES);
+		ui.add_sized([width, height], Label::new(format!("{}", api.shares_found)));
+		ui.add_sized([width, height], Label::new(RichText::new("Payouts").underline().color(BONE))).on_hover_text(STATUS_P2POOL_PAYOUTS);
+		ui.add_sized([width, height], Label::new(format!("Total: {}", api.payouts)));
+		ui.add_sized([width, height], Label::new(format!("[{}/hour] [{}/day] [{}/month]", api.payouts_hour, api.payouts_day, api.payouts_month)));
+		ui.add_sized([width, height], Label::new(RichText::new("XMR Mined").underline().color(BONE))).on_hover_text(STATUS_P2POOL_XMR);
+		ui.add_sized([width, height], Label::new(format!("Total: {} XMR", api.xmr)));
+		ui.add_sized([width, height], Label::new(format!("[{}/hour] [{}/day] [{}/month]", api.xmr_hour, api.xmr_day, api.xmr_month)));
+		ui.add_sized([width, height], Label::new(RichText::new("P2Pool Hashrate [15m/1h/24h]").underline().color(BONE))).on_hover_text(STATUS_P2POOL_HASHRATE);
+		ui.add_sized([width, height], Label::new(format!("[{} H/s] [{} H/s] [{} H/s]", api.hashrate_15m, api.hashrate_1h, api.hashrate_24h)));
+		ui.add_sized([width, height], Label::new(RichText::new("Miners Connected").underline().color(BONE))).on_hover_text(STATUS_P2POOL_CONNECTIONS);
+		ui.add_sized([width, height], Label::new(format!("{}", api.connections)));
+		ui.add_sized([width, height], Label::new(RichText::new("Effort").underline().color(BONE))).on_hover_text(STATUS_P2POOL_EFFORT);
+		ui.add_sized([width, height], Label::new(format!("[Average: {}] [Current: {}]", api.average_effort, api.current_effort)));
 	})});
 	// [XMRig]
 	ui.group(|ui| { ui.vertical(|ui| {
+		ui.set_enabled(xmrig_online);
 		ui.set_min_height(min_height);
-		ui.add_sized([width, height*2.0], Label::new(RichText::new("[XMRig]").color(LIGHT_GRAY).text_style(TextStyle::Name("MonospaceLarge".into()))));
+		ui.add_sized([width, height*2.0], Label::new(RichText::new("[XMRig]").color(LIGHT_GRAY).text_style(TextStyle::Name("MonospaceLarge".into())))).on_hover_text("XMRig is online").on_disabled_hover_text("XMRig is offline");
 		// Uptime
 		ui.add_sized([width, height], Label::new(RichText::new("Uptime").underline()));
 		ui.add_sized([width, height], Label::new(format!("{}", xmrig_api.lock().unwrap().uptime)));