From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: <yew-devel-bounces@lists.proxmox.com> Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id 18ED91FF1CD for <inbox@lore.proxmox.com>; Fri, 30 May 2025 14:22:50 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 1AB2C2EA1D; Fri, 30 May 2025 14:23:06 +0200 (CEST) From: Dominik Csapak <d.csapak@proxmox.com> To: yew-devel@lists.proxmox.com Date: Fri, 30 May 2025 14:21:55 +0200 Message-Id: <20250530122202.2779300-14-d.csapak@proxmox.com> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250530122202.2779300-1-d.csapak@proxmox.com> References: <20250530122202.2779300-1-d.csapak@proxmox.com> MIME-Version: 1.0 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.022 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: [yew-devel] [PATCH yew-comp 13/20] rrd: refactor series related struct and functions into own module X-BeenThere: yew-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Yew framework devel list at Proxmox <yew-devel.lists.proxmox.com> List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/yew-devel>, <mailto:yew-devel-request@lists.proxmox.com?subject=unsubscribe> List-Archive: <http://lists.proxmox.com/pipermail/yew-devel/> List-Post: <mailto:yew-devel@lists.proxmox.com> List-Help: <mailto:yew-devel-request@lists.proxmox.com?subject=help> List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/yew-devel>, <mailto:yew-devel-request@lists.proxmox.com?subject=subscribe> Reply-To: Yew framework devel list at Proxmox <yew-devel@lists.proxmox.com> Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: yew-devel-bounces@lists.proxmox.com Sender: "yew-devel" <yew-devel-bounces@lists.proxmox.com> makes the main graph module a bit smaller. While at it, document the compute_*_path functions. Signed-off-by: Dominik Csapak <d.csapak@proxmox.com> --- src/rrd/graph.rs | 101 +------------------------------------------ src/rrd/mod.rs | 3 ++ src/rrd/series.rs | 107 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 99 deletions(-) create mode 100644 src/rrd/series.rs diff --git a/src/rrd/graph.rs b/src/rrd/graph.rs index b58bd58..161269f 100644 --- a/src/rrd/graph.rs +++ b/src/rrd/graph.rs @@ -15,20 +15,6 @@ use pwt::widget::{Button, Container, Panel}; use pwt_macros::builder; -pub struct Series { - pub label: AttrValue, - pub data: Vec<f64>, -} - -impl Series { - pub fn new(label: impl Into<AttrValue>, data: Vec<f64>) -> Self { - Self { - label: label.into(), - data, - } - } -} - #[derive(Derivative)] #[derivative(Clone, PartialEq)] #[derive(Properties)] @@ -166,7 +152,9 @@ impl Default for LayoutProps { use pwt::widget::canvas::{Canvas, Circle, Group, Path, Rect, SvgLength, Text}; +use super::series::{compute_fill_path, compute_outline_path}; use super::units::{get_grid_unit_base10, get_grid_unit_base2, get_time_grid_unit}; +use super::Series; fn format_date_time(t: i64) -> String { let (time, date) = format_time(t); @@ -264,91 +252,6 @@ fn compute_min_max(props: &RRDGraph, data1: &[f64], data2: &[f64]) -> (f64, f64, (min_data, max_data, grid_unit) } -fn compute_outline_path( - time_data: &[i64], - values: &[f64], - compute_x: impl Fn(i64) -> f64, - compute_y: impl Fn(f64) -> f64, -) -> String { - let mut path = String::new(); - let mut last_undefined = true; - for (i, t) in time_data.iter().enumerate() { - let value = *values.get(i).unwrap_or(&f64::NAN); - let x = compute_x(*t); - - if last_undefined { - if value.is_nan() { - continue; - } - last_undefined = false; - let y = compute_y(value); - path.push_str(&format!(" M {:.1} {:.1}", x, y)); - } else { - if value.is_nan() { - last_undefined = true; - continue; - } - let y = compute_y(value); - path.push_str(&format!(" L {:.1} {:.1}", x, y)); - } - } - path -} - -fn compute_fill_path( - time_data: &[i64], - values: &[f64], - min_data: f64, - max_data: f64, - compute_x: impl Fn(i64) -> f64, - compute_y: impl Fn(f64) -> f64, -) -> String { - let mut y0 = compute_y(0.0); - if min_data > 0.0 { - y0 = compute_y(min_data) - } - if max_data < 0.0 { - y0 = compute_y(max_data) - } - let mut path = String::new(); - let mut last_undefined = true; - for i in 0..time_data.len() { - let t = time_data[i]; - let value = *values.get(i).unwrap_or(&f64::NAN); - - let x = compute_x(t); - - if last_undefined { - if value.is_nan() { - continue; - } - last_undefined = false; - path.push_str(&format!(" M {:.1} {:.1}", x, y0)); - } else if value.is_nan() { - last_undefined = true; - let x = if i > 0 { - compute_x(time_data[i - 1]) - } else { - x - }; - path.push_str(&format!(" L {:.1} {:.1}", x, y0)); - - continue; - } - let y = compute_y(value); - path.push_str(&format!(" L {:.1} {:.1}", x, y)); - } - - if let Some(t) = time_data.last() { - if !last_undefined { - let x = compute_x(*t); - path.push_str(&format!(" L {:.1} {:.1}", x, y0)); - } - } - - path -} - impl PwtRRDGraph { fn get_view_data<'a>(&self, ctx: &'a Context<Self>) -> (&'a [i64], &'a [f64], &'a [f64]) { let props = ctx.props(); diff --git a/src/rrd/mod.rs b/src/rrd/mod.rs index 7931053..fe63ff5 100644 --- a/src/rrd/mod.rs +++ b/src/rrd/mod.rs @@ -1,4 +1,7 @@ mod graph; pub use graph::*; +pub(crate) mod series; +pub use series::Series; + pub(crate) mod units; diff --git a/src/rrd/series.rs b/src/rrd/series.rs new file mode 100644 index 0000000..8807598 --- /dev/null +++ b/src/rrd/series.rs @@ -0,0 +1,107 @@ +use yew::AttrValue; + +/// Represents a series of data for an [`crate::RRDGraph`] +pub struct Series { + pub label: AttrValue, + pub data: Vec<f64>, +} + +impl Series { + pub fn new(label: impl Into<AttrValue>, data: Vec<f64>) -> Self { + Self { + label: label.into(), + data, + } + } +} + +/// Calculate the outline path of a series of [`f64`] data for [`i64`] points in time. +/// +/// The line will not be drawn for points that are missing +pub fn compute_outline_path( + time_data: &[i64], + values: &[f64], + compute_x: impl Fn(i64) -> f64, + compute_y: impl Fn(f64) -> f64, +) -> String { + let mut path = String::new(); + let mut last_undefined = true; + for (i, t) in time_data.iter().enumerate() { + let value = *values.get(i).unwrap_or(&f64::NAN); + let x = compute_x(*t); + + if last_undefined { + if value.is_nan() { + continue; + } + last_undefined = false; + let y = compute_y(value); + path.push_str(&format!(" M {:.1} {:.1}", x, y)); + } else { + if value.is_nan() { + last_undefined = true; + continue; + } + let y = compute_y(value); + path.push_str(&format!(" L {:.1} {:.1}", x, y)); + } + } + path +} + +/// Calculate the fill path for a series of [`f64`] points for [`i64`] points in time. +/// +/// The area will not be filled for points that are missing +pub fn compute_fill_path( + time_data: &[i64], + values: &[f64], + min_data: f64, + max_data: f64, + compute_x: impl Fn(i64) -> f64, + compute_y: impl Fn(f64) -> f64, +) -> String { + let mut y0 = compute_y(0.0); + if min_data > 0.0 { + y0 = compute_y(min_data) + } + if max_data < 0.0 { + y0 = compute_y(max_data) + } + let mut path = String::new(); + let mut last_undefined = true; + for i in 0..time_data.len() { + let t = time_data[i]; + let value = *values.get(i).unwrap_or(&f64::NAN); + + let x = compute_x(t); + + if last_undefined { + if value.is_nan() { + continue; + } + last_undefined = false; + path.push_str(&format!(" M {:.1} {:.1}", x, y0)); + } else if value.is_nan() { + last_undefined = true; + let x = if i > 0 { + compute_x(time_data[i - 1]) + } else { + x + }; + path.push_str(&format!(" L {:.1} {:.1}", x, y0)); + + continue; + } + let y = compute_y(value); + path.push_str(&format!(" L {:.1} {:.1}", x, y)); + } + + if let Some(t) = time_data.last() { + if !last_undefined { + let x = compute_x(*t); + path.push_str(&format!(" L {:.1} {:.1}", x, y0)); + } + } + + path +} -- 2.39.5 _______________________________________________ yew-devel mailing list yew-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/yew-devel