mirror of
https://github.com/hinto-janai/gupax.git
synced 2024-11-17 09:47:36 +00:00
Status Submenu: add basic [PayoutView] GUI <-> API UI
This commit is contained in:
parent
983f6560ad
commit
553081d2aa
5 changed files with 153 additions and 2 deletions
|
@ -175,6 +175,12 @@ pub const STATUS_XMRIG_THREADS: &str = "The amount of threads XMRig is curre
|
|||
pub const STATUS_SUBMENU_PROCESSES: &str = "View the status of process related data for [Gupax|P2Pool|XMRig]";
|
||||
pub const STATUS_SUBMENU_P2POOL: &str = "View P2Pool specific data";
|
||||
pub const STATUS_SUBMENU_MONERO: &str = "View general Monero blockchain data";
|
||||
pub const STATUS_SUBMENU_PAYOUT: &str = "The total amount of payouts received via P2Pool across all time";
|
||||
pub const STATUS_SUBMENU_XMR: &str = "The total of XMR mined via P2Pool across all time";
|
||||
pub const STATUS_SUBMENU_LATEST: &str = "Sort the logs latest to oldest";
|
||||
pub const STATUS_SUBMENU_OLDEST: &str = "Sort the logs oldest to latest";
|
||||
pub const STATUS_SUBMENU_BIGGEST: &str = "Sort the logs by biggest payouts first";
|
||||
pub const STATUS_SUBMENU_SMALLEST: &str = "Sort the logs by smallest payouts first";
|
||||
|
||||
// Gupax
|
||||
pub const GUPAX_UPDATE: &str = "Check for updates on Gupax, P2Pool, and XMRig via GitHub's API and upgrade automatically";
|
||||
|
|
68
src/disk.rs
68
src/disk.rs
|
@ -561,9 +561,12 @@ impl Pool {
|
|||
#[derive(Clone,Debug)]
|
||||
pub struct GupaxP2poolApi {
|
||||
pub log: String, // Log file only containing full payout lines
|
||||
pub log_rev: String, // Same as above but reversed based off lines
|
||||
pub payout: HumanNumber, // Human-friendly display of payout count
|
||||
pub payout_u64: u64, // [u64] version of above
|
||||
pub payout_ord: PayoutOrd, // Ordered Vec of payouts, see [PayoutOrd]
|
||||
pub payout_low: String, // A pre-allocated/computed [String] of the above Vec from low payout to high
|
||||
pub payout_high: String, // Same as above but high -> low
|
||||
pub xmr: AtomicUnit, // XMR stored as atomic units
|
||||
pub path_log: PathBuf, // Path to [log]
|
||||
pub path_payout: PathBuf, // Path to [payout]
|
||||
|
@ -576,9 +579,12 @@ impl GupaxP2poolApi {
|
|||
pub fn new() -> Self {
|
||||
Self {
|
||||
log: String::new(),
|
||||
log_rev: String::new(),
|
||||
payout: HumanNumber::unknown(),
|
||||
payout_u64: 0,
|
||||
payout_ord: PayoutOrd::new(),
|
||||
payout_low: String::new(),
|
||||
payout_high: String::new(),
|
||||
xmr: AtomicUnit::new(),
|
||||
path_xmr: PathBuf::new(),
|
||||
path_payout: PathBuf::new(),
|
||||
|
@ -624,6 +630,34 @@ impl GupaxP2poolApi {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn update_log_rev(&mut self) {
|
||||
let mut log_rev = String::with_capacity(self.log.len());
|
||||
for line in self.log.lines().rev() {
|
||||
log_rev.push_str(line);
|
||||
log_rev.push_str("\n");
|
||||
}
|
||||
self.log_rev = log_rev;
|
||||
}
|
||||
|
||||
pub fn append_head_log_rev(&mut self, line: &str) {
|
||||
self.log_rev = format!("{}\n{}", line, self.log_rev);
|
||||
}
|
||||
|
||||
pub fn update_payout_low(&mut self) {
|
||||
self.payout_ord.sort_payout_low_to_high();
|
||||
self.payout_low = self.payout_ord.to_string();
|
||||
}
|
||||
|
||||
pub fn update_payout_high(&mut self) {
|
||||
self.payout_ord.sort_payout_high_to_low();
|
||||
self.payout_high = self.payout_ord.to_string();
|
||||
}
|
||||
|
||||
pub fn update_payout_strings(&mut self) {
|
||||
self.update_payout_low();
|
||||
self.update_payout_high();
|
||||
}
|
||||
|
||||
pub fn read_all_files_and_update(&mut self) -> Result<(), TomlError> {
|
||||
let payout_u64 = match read_to_string(File::Payout, &self.path_payout)?.trim().parse::<u64>() {
|
||||
Ok(o) => o,
|
||||
|
@ -636,6 +670,7 @@ impl GupaxP2poolApi {
|
|||
let payout = HumanNumber::from_u64(payout_u64);
|
||||
let log = read_to_string(File::Log, &self.path_log)?;
|
||||
self.payout_ord.update_from_payout_log(&log);
|
||||
self.update_payout_strings();
|
||||
*self = Self {
|
||||
log,
|
||||
payout,
|
||||
|
@ -643,16 +678,19 @@ impl GupaxP2poolApi {
|
|||
xmr,
|
||||
..std::mem::take(self)
|
||||
};
|
||||
self.update_log_rev();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Takes the log line and (date, atomic_unit, block) and updates [self] and the [PayoutOrd]
|
||||
pub fn add_payout(&mut self, log_payout_line: &str, date: String, atomic_unit: AtomicUnit, block: HumanNumber) {
|
||||
self.log.push_str(log_payout_line);
|
||||
self.append_head_log_rev(log_payout_line);
|
||||
self.payout_u64 += 1;
|
||||
self.payout = HumanNumber::from_u64(self.payout_u64);
|
||||
self.xmr = self.xmr.add_self(atomic_unit);
|
||||
self.payout_ord.push(date, atomic_unit, block);
|
||||
self.update_payout_strings();
|
||||
}
|
||||
|
||||
pub fn write_to_all_files(&self) -> Result<(), TomlError> {
|
||||
|
@ -764,6 +802,34 @@ impl Display for Submenu {
|
|||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- [PayoutView] enum for [Status/P2Pool] tab
|
||||
// The enum buttons for selecting which "view" to sort the payout log in.
|
||||
#[derive(Clone,Copy,Eq,PartialEq,Debug,Deserialize,Serialize)]
|
||||
pub enum PayoutView {
|
||||
Latest, // Shows the most recent logs first
|
||||
Oldest, // Shows the oldest logs first
|
||||
Biggest, // Shows highest to lowest payouts
|
||||
Smallest, // Shows lowest to highest payouts
|
||||
}
|
||||
|
||||
impl PayoutView {
|
||||
fn new() -> Self {
|
||||
Self::Latest
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for PayoutView {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for PayoutView {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "{}", self)
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- [Hash] enum for [Status/P2Pool]
|
||||
#[derive(Clone,Copy,Eq,PartialEq,Debug,Deserialize,Serialize)]
|
||||
pub enum Hash {
|
||||
|
@ -856,6 +922,7 @@ pub struct State {
|
|||
#[derive(Clone,PartialEq,Debug,Deserialize,Serialize)]
|
||||
pub struct Status {
|
||||
pub submenu: Submenu,
|
||||
pub payout_view: PayoutView,
|
||||
pub monero_enabled: bool,
|
||||
pub manual_hash: bool,
|
||||
pub hashrate: f64,
|
||||
|
@ -941,6 +1008,7 @@ impl Default for Status {
|
|||
fn default() -> Self {
|
||||
Self {
|
||||
submenu: Submenu::default(),
|
||||
payout_view: PayoutView::default(),
|
||||
monero_enabled: false,
|
||||
manual_hash: false,
|
||||
hashrate: 0.0,
|
||||
|
|
|
@ -1742,7 +1742,7 @@ XMRig console byte length: {}\n
|
|||
}
|
||||
Tab::Status => {
|
||||
debug!("App | Entering [Status] Tab");
|
||||
crate::disk::Status::show(&mut self.state.status, &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(&mut self.state.status, &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.gupax_p2pool_api, self.width, self.height, ctx, ui);
|
||||
}
|
||||
Tab::Gupax => {
|
||||
debug!("App | Entering [Gupax] Tab");
|
||||
|
|
|
@ -25,6 +25,8 @@ use crate::{
|
|||
Hash,
|
||||
Submenu,
|
||||
macros::*,
|
||||
GupaxP2poolApi,
|
||||
PayoutView,
|
||||
};
|
||||
use std::sync::{Arc,Mutex};
|
||||
use log::*;
|
||||
|
@ -32,10 +34,12 @@ use egui::{
|
|||
Label,RichText,TextStyle,
|
||||
TextStyle::Monospace,
|
||||
TextStyle::Name,
|
||||
TextEdit,
|
||||
SelectableLabel,
|
||||
};
|
||||
|
||||
impl crate::disk::Status {
|
||||
pub fn show(&mut self, 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) {
|
||||
pub fn show(&mut self, 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, gupax_p2pool_api: &Arc<Mutex<GupaxP2poolApi>>, width: f32, height: f32, _ctx: &egui::Context, ui: &mut egui::Ui) {
|
||||
//---------------------------------------------------------------------------------------------------- [Processes]
|
||||
if self.submenu == Submenu::Processes {
|
||||
let width = (width/3.0)-(SPACE*1.666);
|
||||
|
@ -123,7 +127,50 @@ pub fn show(&mut self, sys: &Arc<Mutex<Sys>>, p2pool_api: &Arc<Mutex<PubP2poolAp
|
|||
drop(api);
|
||||
})});
|
||||
});
|
||||
//---------------------------------------------------------------------------------------------------- [P2Pool]
|
||||
} else if self.submenu == Submenu::P2pool {
|
||||
let mut api = lock!(gupax_p2pool_api);
|
||||
let text = height / 25.0;
|
||||
let log = height / 2.4;
|
||||
ui.style_mut().override_text_style = Some(Monospace);
|
||||
// Payout Text + PayoutView buttons
|
||||
ui.group(|ui| {
|
||||
ui.horizontal(|ui| {
|
||||
let width = (width/3.0)-(SPACE*4.0);
|
||||
ui.add_sized([width, text], Label::new(RichText::new(format!("Total Payouts: {}", api.payout)).underline().color(LIGHT_GRAY))).on_hover_text(STATUS_SUBMENU_PAYOUT);
|
||||
ui.separator();
|
||||
ui.add_sized([width, text], Label::new(RichText::new(format!("Total XMR: {}", api.xmr)).underline().color(LIGHT_GRAY))).on_hover_text(STATUS_SUBMENU_XMR);
|
||||
let width = width / 4.0;
|
||||
ui.separator();
|
||||
if ui.add_sized([width, text], SelectableLabel::new(self.payout_view == PayoutView::Latest, "Latest")).on_hover_text(STATUS_SUBMENU_LATEST).clicked() { self.payout_view = PayoutView::Latest; }
|
||||
ui.separator();
|
||||
if ui.add_sized([width, text], SelectableLabel::new(self.payout_view == PayoutView::Oldest, "Oldest")).on_hover_text(STATUS_SUBMENU_OLDEST).clicked() { self.payout_view = PayoutView::Oldest; }
|
||||
ui.separator();
|
||||
if ui.add_sized([width, text], SelectableLabel::new(self.payout_view == PayoutView::Biggest, "Biggest")).on_hover_text(STATUS_SUBMENU_BIGGEST).clicked() {
|
||||
api.update_payout_high();
|
||||
self.payout_view = PayoutView::Biggest;
|
||||
}
|
||||
ui.separator();
|
||||
if ui.add_sized([width, text], SelectableLabel::new(self.payout_view == PayoutView::Smallest, "Smallest")).on_hover_text(STATUS_SUBMENU_SMALLEST).clicked() {
|
||||
api.update_payout_low();
|
||||
self.payout_view = PayoutView::Smallest;
|
||||
}
|
||||
});
|
||||
ui.separator();
|
||||
// Actual logs
|
||||
egui::Frame::none().fill(DARK_GRAY).show(ui, |ui| {
|
||||
egui::ScrollArea::vertical().stick_to_bottom(self.payout_view == PayoutView::Oldest).max_width(width).max_height(log).auto_shrink([false; 2]).show_viewport(ui, |ui, _| {
|
||||
match self.payout_view {
|
||||
PayoutView::Latest => ui.add_sized([width, log], TextEdit::multiline(&mut api.log.as_str())),
|
||||
PayoutView::Oldest => ui.add_sized([width, log], TextEdit::multiline(&mut api.log_rev.as_str())),
|
||||
PayoutView::Biggest => ui.add_sized([width, log], TextEdit::multiline(&mut api.payout_high.as_str())),
|
||||
PayoutView::Smallest => ui.add_sized([width, log], TextEdit::multiline(&mut api.payout_low.as_str())),
|
||||
};
|
||||
});
|
||||
});
|
||||
});
|
||||
drop(api);
|
||||
//---------------------------------------------------------------------------------------------------- [Monero]
|
||||
} else if self.submenu == Submenu::Monero {
|
||||
}
|
||||
}
|
||||
|
|
30
src/xmr.rs
30
src/xmr.rs
|
@ -225,10 +225,18 @@ impl PayoutOrd {
|
|||
self.0.sort_by(|a, b| b.1.0.cmp(&a.1.0));
|
||||
}
|
||||
|
||||
// These sorting functions take around [0.0035~] seconds on a Ryzen 5950x
|
||||
// given a Vec filled with 1_000_000 elements, not bad.
|
||||
pub fn sort_payout_low_to_high(&mut self) {
|
||||
self.0.sort_by(|a, b| a.1.0.cmp(&b.1.0));
|
||||
}
|
||||
|
||||
// Returns a reversed [Iter] of the [PayoutOrd]
|
||||
// This is obviously faster than actually reordering the Vec.
|
||||
pub fn rev_iter(&self) -> std::iter::Rev<std::slice::Iter<'_, (String, AtomicUnit, HumanNumber)>> {
|
||||
self.0.iter().rev()
|
||||
}
|
||||
|
||||
// Recent <-> Oldest relies on the line order.
|
||||
// The raw log lines will be shown instead of this struct.
|
||||
}
|
||||
|
@ -354,4 +362,26 @@ r#"2022-09-08 18:42:55.4636 | 0.001000000000 XMR | Block 2,654,321
|
|||
println!("2: {:#?}", payout_ord);
|
||||
assert!(PayoutOrd::is_same(&payout_ord, &payout_ord_2) == false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn view_reverse_payout_ord() {
|
||||
use crate::xmr::PayoutOrd;
|
||||
use crate::xmr::AtomicUnit;
|
||||
use crate::human::HumanNumber;
|
||||
let mut payout_ord = PayoutOrd::from_vec(vec![
|
||||
("2022-09-08 18:42:55.4636".to_string(), AtomicUnit::from_u64(1000000000), HumanNumber::from_u64(2654321)),
|
||||
("2022-09-09 16:18:26.7582".to_string(), AtomicUnit::from_u64(2000000000), HumanNumber::from_u64(2654322)),
|
||||
("2022-09-10 11:15:21.1272".to_string(), AtomicUnit::from_u64(3000000000), HumanNumber::from_u64(2654323)),
|
||||
]);
|
||||
println!("OG: {:#?}", payout_ord);
|
||||
|
||||
for (_, atomic_unit, _) in payout_ord.rev_iter() {
|
||||
if atomic_unit.to_u64() == 3000000000 {
|
||||
break
|
||||
} else {
|
||||
println!("expected: 3000000000, found: {}", atomic_unit);
|
||||
panic!("not reversed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue