use std::path::PathBuf;
use crate::spend::{CEILING_HEAD, Price, Prices};
use crate::ui_state::UiState;
use super::dispatch::Deps;
use super::reply::{PricesView, Reply};
pub(super) fn view(deps: &Deps, ui: &UiState, released: Option<usize>) -> PricesView {
let prices = ui.prices();
PricesView {
rows: prices.rows(),
ceiling: ui.ceiling(),
spent: crate::spend::of_world(&roster(deps), &prices),
released,
}
}
pub(super) fn price(
deps: &Deps,
ui: &mut UiState,
provider: &str,
model: &str,
rates: Option<Price>,
) -> Reply {
let mut table: Prices = ui.prices();
table.set(provider, model, rates);
ui.set_prices(&table);
Reply::Prices(view(deps, ui, None))
}
pub(super) fn ceiling(deps: &Deps, ui: &mut UiState, ts: &str, micro_usd: Option<u64>) -> Reply {
ui.set_ceiling(micro_usd);
let roster = roster(deps);
let prices = ui.prices();
let over = ui.ceiling().refusal(&roster, &prices).is_some();
let released = if over { 0 } else { release(deps, ts, &roster) };
Reply::Prices(view(deps, ui, Some(released)))
}
fn release(deps: &Deps, ts: &str, roster: &[PathBuf]) -> usize {
let mut count = 0;
for workspace in roster {
for (agent, held) in crate::control::hold::all(workspace) {
if !held.reason.starts_with(CEILING_HEAD) {
continue;
}
let _ = super::control::advance(deps, ts, workspace, &agent);
count += 1;
}
}
count
}
fn roster(deps: &Deps) -> Vec<PathBuf> {
crate::binding::workspaces(&deps.yog_data_root, &deps.world.litany_data_root())
.into_iter()
.map(|w| w.path)
.collect()
}
#[cfg(test)]
mod tests;