mirror of https://codeberg.org/topola/topola.git
feat(stepper): Replace overengineered SMA rate timeout with two accumulators
This commit is contained in:
parent
9345d5de8a
commit
18e8f9812c
|
|
@ -6,7 +6,7 @@ use std::ops::ControlFlow;
|
||||||
|
|
||||||
use topola::{
|
use topola::{
|
||||||
interactor::activity::ActivityStepperWithStatus,
|
interactor::activity::ActivityStepperWithStatus,
|
||||||
stepper::{EstimateProgress, GetMaybeReconfigurationTriggerProgress},
|
stepper::{EstimateProgress, GetTimeoutProgress},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{translator::Translator, viewport::Viewport};
|
use crate::{translator::Translator, viewport::Viewport};
|
||||||
|
|
@ -45,17 +45,17 @@ impl StatusBar {
|
||||||
if let Some(activity) = maybe_activity {
|
if let Some(activity) = maybe_activity {
|
||||||
let progress = activity.estimate_progress();
|
let progress = activity.estimate_progress();
|
||||||
let value = progress.value();
|
let value = progress.value();
|
||||||
let maximum = progress.reference();
|
let maximum = progress.maximum();
|
||||||
let ratio = *value as f32 / *maximum as f32;
|
let ratio = *value as f32 / *maximum as f32;
|
||||||
|
|
||||||
if let Some(trigger_progress) = activity.reconfiguration_trigger_progress() {
|
if let Some(trigger_progress) = activity.timeout_progress() {
|
||||||
ui.add(egui::ProgressBar::new(ratio).text(format!(
|
ui.add(egui::ProgressBar::new(ratio).text(format!(
|
||||||
"{:.1}% ({:.1}/{:.1}) (sma: {:.1}, min: {:.1}))",
|
"{:.1}% ({:.1}/{:.1}) (timeout: {:.1}/{:.1}))",
|
||||||
ratio * 100.0,
|
ratio * 100.0,
|
||||||
value,
|
value,
|
||||||
maximum,
|
maximum,
|
||||||
trigger_progress.value(),
|
trigger_progress.value(),
|
||||||
trigger_progress.reference(),
|
trigger_progress.maximum(),
|
||||||
)));
|
)));
|
||||||
} else {
|
} else {
|
||||||
ui.add(egui::ProgressBar::new(ratio).text(format!(
|
ui.add(egui::ProgressBar::new(ratio).text(format!(
|
||||||
|
|
@ -68,7 +68,7 @@ impl StatusBar {
|
||||||
|
|
||||||
let linear_subprogress = progress.subscale();
|
let linear_subprogress = progress.subscale();
|
||||||
let value = linear_subprogress.value();
|
let value = linear_subprogress.value();
|
||||||
let maximum = linear_subprogress.reference();
|
let maximum = linear_subprogress.maximum();
|
||||||
let ratio = *value as f32 / *maximum as f32;
|
let ratio = *value as f32 / *maximum as f32;
|
||||||
|
|
||||||
ui.add(egui::ProgressBar::new(ratio).text(format!(
|
ui.add(egui::ProgressBar::new(ratio).text(format!(
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ use crate::{
|
||||||
board::{edit::BoardEdit, AccessMesadata},
|
board::{edit::BoardEdit, AccessMesadata},
|
||||||
layout::via::ViaWeight,
|
layout::via::ViaWeight,
|
||||||
router::ng,
|
router::ng,
|
||||||
stepper::{Abort, EstimateProgress, GetMaybeReconfigurationTriggerProgress, LinearScale, Step},
|
stepper::{Abort, EstimateProgress, GetTimeoutProgress, LinearScale, Step},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
|
|
@ -199,14 +199,12 @@ impl<M> EstimateProgress for ExecutionStepper<M> {
|
||||||
|
|
||||||
// Since enum_dispatch does not really support generics, we implement this the
|
// Since enum_dispatch does not really support generics, we implement this the
|
||||||
// long way by using `match`.
|
// long way by using `match`.
|
||||||
impl<M> GetMaybeReconfigurationTriggerProgress for ExecutionStepper<M> {
|
impl<M> GetTimeoutProgress for ExecutionStepper<M> {
|
||||||
type Subscale = ();
|
type Subscale = ();
|
||||||
|
|
||||||
fn reconfiguration_trigger_progress(&self) -> Option<LinearScale<f64>> {
|
fn timeout_progress(&self) -> Option<LinearScale<f64>> {
|
||||||
match self {
|
match self {
|
||||||
ExecutionStepper::MultilayerAutoroute(autoroute) => {
|
ExecutionStepper::MultilayerAutoroute(autoroute) => autoroute.timeout_progress(),
|
||||||
autoroute.reconfiguration_trigger_progress()
|
|
||||||
}
|
|
||||||
ExecutionStepper::PlanarAutoroute(autoroute) => None,
|
ExecutionStepper::PlanarAutoroute(autoroute) => None,
|
||||||
ExecutionStepper::TopoAutoroute(..) => None,
|
ExecutionStepper::TopoAutoroute(..) => None,
|
||||||
ExecutionStepper::PlaceVia(..) => None,
|
ExecutionStepper::PlaceVia(..) => None,
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ use crate::{
|
||||||
IncrementFailedRatlineLayersMultilayerAutorouteReconfigurer,
|
IncrementFailedRatlineLayersMultilayerAutorouteReconfigurer,
|
||||||
MakeNextMultilayerAutorouteConfiguration, MultilayerAutorouteReconfigurer,
|
MakeNextMultilayerAutorouteConfiguration, MultilayerAutorouteReconfigurer,
|
||||||
},
|
},
|
||||||
planar_autoroute::PlanarAutorouteConfigurationStatus,
|
|
||||||
planar_preconfigurer::PlanarAutoroutePreconfigurerInput,
|
planar_preconfigurer::PlanarAutoroutePreconfigurerInput,
|
||||||
planar_reconfigurator::PlanarAutorouteReconfiguratorStatus,
|
planar_reconfigurator::PlanarAutorouteReconfiguratorStatus,
|
||||||
Autorouter, AutorouterError,
|
Autorouter, AutorouterError,
|
||||||
|
|
@ -30,8 +29,8 @@ use crate::{
|
||||||
geometry::primitive::PrimitiveShape,
|
geometry::primitive::PrimitiveShape,
|
||||||
router::{navcord::Navcord, navmesh::Navmesh, thetastar::ThetastarStepper},
|
router::{navcord::Navcord, navmesh::Navmesh, thetastar::ThetastarStepper},
|
||||||
stepper::{
|
stepper::{
|
||||||
Abort, EstimateProgress, GetMaybeReconfigurationTriggerProgress, LinearScale,
|
Abort, EstimateProgress, GetTimeoutProgress, LinearScale, ReconfiguratorStatus,
|
||||||
ReconfiguratorStatus, Reconfigure, SmaRateReconfigurationTrigger, Step,
|
Reconfigure, Step, TimeVsProgressAccumulatorTimeout,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -40,7 +39,7 @@ pub type MultilayerReconfiguratorStatus =
|
||||||
|
|
||||||
pub struct MultilayerAutorouteReconfigurator {
|
pub struct MultilayerAutorouteReconfigurator {
|
||||||
stepper: MultilayerAutorouteExecutionStepper,
|
stepper: MultilayerAutorouteExecutionStepper,
|
||||||
reconfiguration_trigger: SmaRateReconfigurationTrigger,
|
timeout: TimeVsProgressAccumulatorTimeout,
|
||||||
reconfigurer: MultilayerAutorouteReconfigurer,
|
reconfigurer: MultilayerAutorouteReconfigurer,
|
||||||
options: MultilayerAutorouteOptions,
|
options: MultilayerAutorouteOptions,
|
||||||
}
|
}
|
||||||
|
|
@ -74,7 +73,7 @@ impl MultilayerAutorouteReconfigurator {
|
||||||
preconfiguration,
|
preconfiguration,
|
||||||
options,
|
options,
|
||||||
)?,
|
)?,
|
||||||
reconfiguration_trigger: SmaRateReconfigurationTrigger::new(20, 0.5, 0.1),
|
timeout: TimeVsProgressAccumulatorTimeout::new(10.0, 5.0),
|
||||||
reconfigurer,
|
reconfigurer,
|
||||||
options,
|
options,
|
||||||
})
|
})
|
||||||
|
|
@ -86,7 +85,7 @@ impl MultilayerAutorouteReconfigurator {
|
||||||
) -> Result<ControlFlow<Option<BoardEdit>, MultilayerReconfiguratorStatus>, AutorouterError>
|
) -> Result<ControlFlow<Option<BoardEdit>, MultilayerReconfiguratorStatus>, AutorouterError>
|
||||||
{
|
{
|
||||||
// Reset the reconfiguration trigger.
|
// Reset the reconfiguration trigger.
|
||||||
self.reconfiguration_trigger = SmaRateReconfigurationTrigger::new(20, 1.0, 0.1);
|
self.timeout = TimeVsProgressAccumulatorTimeout::new(10.0, 5.0);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let Some(configuration) = self.reconfigurer.next_configuration(autorouter) else {
|
let Some(configuration) = self.reconfigurer.next_configuration(autorouter) else {
|
||||||
|
|
@ -117,7 +116,7 @@ impl<M: AccessMesadata> Step<Autorouter<M>, Option<BoardEdit>, MultilayerReconfi
|
||||||
) -> Result<ControlFlow<Option<BoardEdit>, MultilayerReconfiguratorStatus>, AutorouterError>
|
) -> Result<ControlFlow<Option<BoardEdit>, MultilayerReconfiguratorStatus>, AutorouterError>
|
||||||
{
|
{
|
||||||
if !self
|
if !self
|
||||||
.reconfiguration_trigger
|
.timeout
|
||||||
.update(*self.estimate_progress().value() as f64)
|
.update(*self.estimate_progress().value() as f64)
|
||||||
{
|
{
|
||||||
return self.reconfigure(autorouter);
|
return self.reconfigure(autorouter);
|
||||||
|
|
@ -161,13 +160,13 @@ impl EstimateProgress for MultilayerAutorouteReconfigurator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GetMaybeReconfigurationTriggerProgress for MultilayerAutorouteReconfigurator {
|
impl GetTimeoutProgress for MultilayerAutorouteReconfigurator {
|
||||||
type Subscale = ();
|
type Subscale = ();
|
||||||
|
|
||||||
fn reconfiguration_trigger_progress(&self) -> Option<LinearScale<f64>> {
|
fn timeout_progress(&self) -> Option<LinearScale<f64>> {
|
||||||
Some(LinearScale::new(
|
Some(LinearScale::new(
|
||||||
(*self.reconfiguration_trigger.maybe_sma_rate_per_sec())?,
|
self.timeout.start_instant().elapsed().as_secs_f64(),
|
||||||
*self.reconfiguration_trigger.min_sma_rate_per_sec(),
|
*self.timeout.progress_accumulator(),
|
||||||
(),
|
(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -317,7 +317,7 @@ impl EstimateProgress for PlanarAutorouteExecutionStepper {
|
||||||
.map_or(0.0, |route| *route.estimate_progress().value()),
|
.map_or(0.0, |route| *route.estimate_progress().value()),
|
||||||
self.route
|
self.route
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map_or(0.0, |route| *route.estimate_progress().reference()),
|
.map_or(0.0, |route| *route.estimate_progress().maximum()),
|
||||||
(),
|
(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ use crate::{
|
||||||
geometry::primitive::PrimitiveShape,
|
geometry::primitive::PrimitiveShape,
|
||||||
router::{navcord::Navcord, navmesh::Navmesh, thetastar::ThetastarStepper},
|
router::{navcord::Navcord, navmesh::Navmesh, thetastar::ThetastarStepper},
|
||||||
stepper::{
|
stepper::{
|
||||||
Abort, EstimateProgress, LinearScale, ReconfiguratorStatus, Reconfigure,
|
Abort, EstimateProgress, LinearScale, ReconfiguratorStatus, Reconfigure, Step,
|
||||||
SmaRateReconfigurationTrigger, Step,
|
TimeVsProgressAccumulatorTimeout,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -35,7 +35,7 @@ pub type PlanarAutorouteReconfiguratorStatus =
|
||||||
|
|
||||||
pub struct PlanarAutorouteReconfigurator {
|
pub struct PlanarAutorouteReconfigurator {
|
||||||
stepper: PlanarAutorouteExecutionStepper,
|
stepper: PlanarAutorouteExecutionStepper,
|
||||||
reconfiguration_trigger: SmaRateReconfigurationTrigger,
|
timeout: TimeVsProgressAccumulatorTimeout,
|
||||||
reconfigurer: PlanarAutorouteReconfigurer,
|
reconfigurer: PlanarAutorouteReconfigurer,
|
||||||
options: PlanarAutorouteOptions,
|
options: PlanarAutorouteOptions,
|
||||||
}
|
}
|
||||||
|
|
@ -65,7 +65,7 @@ impl PlanarAutorouteReconfigurator {
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
stepper: PlanarAutorouteExecutionStepper::new(autorouter, preconfiguration, options)?,
|
stepper: PlanarAutorouteExecutionStepper::new(autorouter, preconfiguration, options)?,
|
||||||
reconfiguration_trigger: SmaRateReconfigurationTrigger::new(5, 0.5, 0.1),
|
timeout: TimeVsProgressAccumulatorTimeout::new(3.0, 1.0),
|
||||||
// Note: I assume here that the first permutation is the same as the original order.
|
// Note: I assume here that the first permutation is the same as the original order.
|
||||||
reconfigurer,
|
reconfigurer,
|
||||||
options,
|
options,
|
||||||
|
|
@ -77,7 +77,7 @@ impl PlanarAutorouteReconfigurator {
|
||||||
autorouter: &mut Autorouter<impl AccessMesadata>,
|
autorouter: &mut Autorouter<impl AccessMesadata>,
|
||||||
) -> Result<ControlFlow<Option<BoardEdit>, PlanarAutorouteReconfiguratorStatus>, AutorouterError>
|
) -> Result<ControlFlow<Option<BoardEdit>, PlanarAutorouteReconfiguratorStatus>, AutorouterError>
|
||||||
{
|
{
|
||||||
self.reconfiguration_trigger = SmaRateReconfigurationTrigger::new(5, 0.5, 0.1);
|
self.timeout = TimeVsProgressAccumulatorTimeout::new(3.0, 1.0);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let Some(configuration) = self
|
let Some(configuration) = self
|
||||||
|
|
@ -111,7 +111,7 @@ impl<M: AccessMesadata> Step<Autorouter<M>, Option<BoardEdit>, PlanarAutorouteRe
|
||||||
) -> Result<ControlFlow<Option<BoardEdit>, PlanarAutorouteReconfiguratorStatus>, AutorouterError>
|
) -> Result<ControlFlow<Option<BoardEdit>, PlanarAutorouteReconfiguratorStatus>, AutorouterError>
|
||||||
{
|
{
|
||||||
if !self
|
if !self
|
||||||
.reconfiguration_trigger
|
.timeout
|
||||||
.update(*self.estimate_progress().value() as f64)
|
.update(*self.estimate_progress().value() as f64)
|
||||||
{
|
{
|
||||||
return self.reconfigure(autorouter);
|
return self.reconfigure(autorouter);
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,7 @@ use crate::{
|
||||||
ng,
|
ng,
|
||||||
thetastar::ThetastarStepper,
|
thetastar::ThetastarStepper,
|
||||||
},
|
},
|
||||||
stepper::{
|
stepper::{Abort, EstimateProgress, GetTimeoutProgress, LinearScale, OnEvent, Step},
|
||||||
Abort, EstimateProgress, GetMaybeReconfigurationTriggerProgress, LinearScale, OnEvent, Step,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Stores the interactive input data from the user.
|
/// Stores the interactive input data from the user.
|
||||||
|
|
@ -118,13 +116,13 @@ impl<M> EstimateProgress for ActivityStepper<M> {
|
||||||
|
|
||||||
// Since enum_dispatch does not really support generics, we implement this the
|
// Since enum_dispatch does not really support generics, we implement this the
|
||||||
// long way by using `match`.
|
// long way by using `match`.
|
||||||
impl<M> GetMaybeReconfigurationTriggerProgress for ActivityStepper<M> {
|
impl<M> GetTimeoutProgress for ActivityStepper<M> {
|
||||||
type Subscale = ();
|
type Subscale = ();
|
||||||
|
|
||||||
fn reconfiguration_trigger_progress(&self) -> Option<LinearScale<f64>> {
|
fn timeout_progress(&self) -> Option<LinearScale<f64>> {
|
||||||
match self {
|
match self {
|
||||||
ActivityStepper::Interaction(..) => None,
|
ActivityStepper::Interaction(..) => None,
|
||||||
ActivityStepper::Execution(execution) => execution.reconfiguration_trigger_progress(),
|
ActivityStepper::Execution(execution) => execution.timeout_progress(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -219,11 +217,11 @@ impl<M> EstimateProgress for ActivityStepperWithStatus<M> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M> GetMaybeReconfigurationTriggerProgress for ActivityStepperWithStatus<M> {
|
impl<M> GetTimeoutProgress for ActivityStepperWithStatus<M> {
|
||||||
type Subscale = ();
|
type Subscale = ();
|
||||||
|
|
||||||
fn reconfiguration_trigger_progress(&self) -> Option<LinearScale<f64>> {
|
fn timeout_progress(&self) -> Option<LinearScale<f64>> {
|
||||||
self.activity.reconfiguration_trigger_progress()
|
self.activity.timeout_progress()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
use core::ops::ControlFlow;
|
use core::ops::ControlFlow;
|
||||||
use std::{collections::VecDeque, time::Instant};
|
use std::time::Instant;
|
||||||
|
|
||||||
use derive_getters::Getters;
|
use derive_getters::Getters;
|
||||||
|
|
||||||
|
|
@ -87,7 +87,7 @@ pub trait OnEvent<Ctx, Event> {
|
||||||
#[derive(Clone, Copy, Debug, Getters)]
|
#[derive(Clone, Copy, Debug, Getters)]
|
||||||
pub struct LinearScale<V, S = ()> {
|
pub struct LinearScale<V, S = ()> {
|
||||||
value: V,
|
value: V,
|
||||||
reference: V,
|
maximum: V,
|
||||||
subscale: S,
|
subscale: S,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -95,7 +95,7 @@ impl<V, S> LinearScale<V, S> {
|
||||||
pub fn new(value: V, reference: V, subscale: S) -> Self {
|
pub fn new(value: V, reference: V, subscale: S) -> Self {
|
||||||
Self {
|
Self {
|
||||||
value,
|
value,
|
||||||
reference,
|
maximum: reference,
|
||||||
subscale,
|
subscale,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -109,87 +109,38 @@ pub trait EstimateProgress {
|
||||||
fn estimate_progress(&self) -> LinearScale<Self::Value, Self::Subscale>;
|
fn estimate_progress(&self) -> LinearScale<Self::Value, Self::Subscale>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait GetMaybeReconfigurationTriggerProgress {
|
pub trait GetTimeoutProgress {
|
||||||
type Subscale;
|
type Subscale;
|
||||||
|
|
||||||
fn reconfiguration_trigger_progress(&self) -> Option<LinearScale<f64, Self::Subscale>>;
|
fn timeout_progress(&self) -> Option<LinearScale<f64, Self::Subscale>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Getters)]
|
#[derive(Clone, Debug, Getters)]
|
||||||
pub struct SmaRateReconfigurationTrigger {
|
pub struct TimeVsProgressAccumulatorTimeout {
|
||||||
#[getter(skip)]
|
start_instant: Instant,
|
||||||
sample_buffer: VecDeque<f64>,
|
|
||||||
#[getter(skip)]
|
|
||||||
last_instant: Instant,
|
|
||||||
#[getter(skip)]
|
#[getter(skip)]
|
||||||
last_max_value: f64,
|
last_max_value: f64,
|
||||||
|
progress_accumulator: f64,
|
||||||
#[getter(skip)]
|
#[getter(skip)]
|
||||||
incoming_max_value: f64,
|
progress_bonus_s: f64,
|
||||||
maybe_sma_rate_per_sec: Option<f64>,
|
|
||||||
#[getter(skip)]
|
|
||||||
sample_buffer_size: usize,
|
|
||||||
#[getter(skip)]
|
|
||||||
sampling_interval_secs: f64,
|
|
||||||
min_sma_rate_per_sec: f64,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SmaRateReconfigurationTrigger {
|
impl TimeVsProgressAccumulatorTimeout {
|
||||||
pub fn new(
|
pub fn new(initial_timeout_s: f64, progress_bonus_s: f64) -> Self {
|
||||||
sample_buffer_size: usize,
|
|
||||||
sampling_interval_secs: f64,
|
|
||||||
min_sma_rate_per_sec: f64,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
sample_buffer: VecDeque::new(),
|
start_instant: Instant::now(),
|
||||||
last_instant: Instant::now(),
|
|
||||||
last_max_value: 0.0,
|
last_max_value: 0.0,
|
||||||
incoming_max_value: 0.0,
|
progress_accumulator: initial_timeout_s,
|
||||||
maybe_sma_rate_per_sec: None,
|
progress_bonus_s,
|
||||||
sample_buffer_size,
|
|
||||||
sampling_interval_secs,
|
|
||||||
min_sma_rate_per_sec,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, value: f64) -> bool {
|
pub fn update(&mut self, value: f64) -> bool {
|
||||||
self.incoming_max_value = self.incoming_max_value.max(value);
|
if value > self.last_max_value {
|
||||||
|
self.progress_accumulator += (value - self.last_max_value) * self.progress_bonus_s;
|
||||||
let elapsed = self.last_instant.elapsed();
|
self.last_max_value = value;
|
||||||
|
|
||||||
if elapsed.as_secs_f64() >= self.sampling_interval_secs {
|
|
||||||
let delta = self.incoming_max_value - self.last_max_value;
|
|
||||||
let count = (elapsed.as_secs_f64() / self.sampling_interval_secs) as usize;
|
|
||||||
let mut total_pushed = 0.0;
|
|
||||||
let mut total_popped = 0.0;
|
|
||||||
|
|
||||||
for _ in 0..count {
|
|
||||||
let pushed = (delta / count as f64) / self.sampling_interval_secs;
|
|
||||||
self.sample_buffer.push_back(delta / count as f64);
|
|
||||||
total_pushed += pushed;
|
|
||||||
|
|
||||||
if self.sample_buffer.len() > self.sample_buffer_size {
|
|
||||||
total_popped += self.sample_buffer.pop_front().unwrap_or_default();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(sma_rate_per_sec) = self.maybe_sma_rate_per_sec {
|
|
||||||
self.maybe_sma_rate_per_sec = Some(
|
|
||||||
sma_rate_per_sec
|
|
||||||
+ (total_pushed - total_popped) / self.sample_buffer_size as f64,
|
|
||||||
)
|
|
||||||
} else if self.sample_buffer.len() >= self.sample_buffer_size {
|
|
||||||
self.maybe_sma_rate_per_sec =
|
|
||||||
Some(self.sample_buffer.iter().sum::<f64>() / self.sample_buffer_size as f64)
|
|
||||||
}
|
|
||||||
|
|
||||||
self.last_instant = Instant::now();
|
|
||||||
self.last_max_value = self.incoming_max_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(sma_rate_per_sec) = self.maybe_sma_rate_per_sec {
|
self.start_instant.elapsed().as_secs_f64() < self.progress_accumulator
|
||||||
sma_rate_per_sec >= self.min_sma_rate_per_sec
|
|
||||||
} else {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue