use super::ids::CouplingId;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AttentionBudget {
pub total_capacity: u64,
pub allocated: HashMap<CouplingId, u64>,
pub safety_reserve: u64,
pub exhaustion_threshold: f64,
}
impl AttentionBudget {
pub fn new(total_capacity: u64) -> Self {
let safety_reserve = total_capacity / 10; Self {
total_capacity,
allocated: HashMap::new(),
safety_reserve,
exhaustion_threshold: 0.8,
}
}
pub fn used(&self) -> u64 {
self.allocated.values().sum()
}
pub fn available(&self) -> u64 {
self.total_capacity
.saturating_sub(self.used())
.saturating_sub(self.safety_reserve)
}
pub fn utilization(&self) -> f64 {
if self.total_capacity == 0 {
return 0.0;
}
self.used() as f64 / self.total_capacity as f64
}
pub fn is_exhaustion_imminent(&self) -> bool {
self.utilization() > self.exhaustion_threshold
}
pub fn can_allocate(&self, amount: u64) -> bool {
self.available() >= amount
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AttentionBudgetSpec {
pub total_capacity: u64,
pub safety_reserve: Option<u64>,
pub exhaustion_threshold: Option<f64>,
}
impl Default for AttentionBudgetSpec {
fn default() -> Self {
Self {
total_capacity: 10000,
safety_reserve: None,
exhaustion_threshold: None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ExhaustionBehavior {
Reject,
GracefulDegrade,
Queue,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum AttentionClass {
Critical,
High,
Normal,
Low,
}
impl AttentionClass {
pub fn cost_multiplier(&self) -> f64 {
match self {
AttentionClass::Critical => 2.0,
AttentionClass::High => 1.5,
AttentionClass::Normal => 1.0,
AttentionClass::Low => 0.5,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AttentionConfig {
pub default_capacity: u64,
pub allow_unlimited: bool,
pub exhaustion_behavior: ExhaustionBehavior,
pub enable_rebalancing: bool,
}
impl Default for AttentionConfig {
fn default() -> Self {
Self {
default_capacity: 10000,
allow_unlimited: false,
exhaustion_behavior: ExhaustionBehavior::GracefulDegrade,
enable_rebalancing: true,
}
}
}