///|
pub(all) struct BudgetProjection {
target : SloTarget
current : BudgetReport
projected_bad : Int
projected_total : Int
projected_consumed_bp : Int
remaining_after_projection : Int
status : String
} derive(Eq, Debug)
///|
pub fn project_budget(
target : SloTarget,
current : RequestWindow,
additional_total : Int,
additional_bad : Int,
) -> BudgetProjection {
let current_report = evaluate_budget(target, current)
let safe_total = if additional_total > 0 { additional_total } else { 0 }
let safe_bad = if additional_bad > 0 {
if additional_bad > safe_total {
safe_total
} else {
additional_bad
}
} else {
0
}
let projected_total = current.total + safe_total
let projected_bad = current.bad() + safe_bad
let allowed = projected_total * target.allowed_error_bp() / 10000
let consumed = if allowed <= 0 {
if projected_bad > 0 {
10000
} else {
0
}
} else {
projected_bad * 10000 / allowed
}
let remaining = allowed - projected_bad
let status = if remaining < 0 {
"exhausted"
} else if consumed >= 10000 {
"at_limit"
} else if consumed >= 8000 {
"near_limit"
} else {
"within_budget"
}
{
target,
current: current_report,
projected_bad,
projected_total,
projected_consumed_bp: consumed,
remaining_after_projection: remaining,
status,
}
}
///|
pub fn BudgetProjection::safe(self : BudgetProjection) -> Bool {
self.remaining_after_projection >= 0
}
///|
pub fn BudgetProjection::status_name(self : BudgetProjection) -> String {
self.status
}
///|
pub fn BudgetProjection::to_json(self : BudgetProjection) -> String {
"{\"projected_bad\":\{self.projected_bad},\"projected_total\":\{self.projected_total},\"projected_consumed_bp\":\{self.projected_consumed_bp},\"remaining_after_projection\":\{self.remaining_after_projection},\"status\":\"\{self.status}\"}"
}
///|
pub fn remaining_budget_ratio_bp(report : BudgetReport) -> Int {
if report.allowed_bad <= 0 {
if report.actual_bad == 0 {
10000
} else {
0
}
} else if report.remaining_bad <= 0 {
0
} else {
report.remaining_bad * 10000 / report.allowed_bad
}
}
///|
pub fn budget_headroom(report : BudgetReport) -> Int {
if report.remaining_bad > 0 {
report.remaining_bad
} else {
0
}
}
///|
pub fn compliance_score(
target : SloTarget,
windows : Array[RequestWindow],
) -> Int {
if windows.length() == 0 {
0
} else {
let mut compliant = 0
for window in windows {
if window.availability_bp() >= target.target_bp {
compliant = compliant + 1
}
}
compliant * 10000 / windows.length()
}
}
///|
pub fn compliance_label(score_bp : Int) -> String {
if score_bp >= 9900 {
"excellent"
} else if score_bp >= 9500 {
"good"
} else if score_bp >= 8000 {
"at_risk"
} else {
"failing"
}
}
///|
pub fn target_gap_bp(target : SloTarget, window : RequestWindow) -> Int {
target.target_bp - window.availability_bp()
}
///|
pub fn target_is_met(target : SloTarget, window : RequestWindow) -> Bool {
target_gap_bp(target, window) <= 0
}
///|
pub fn best_window(windows : Array[RequestWindow]) -> RequestWindow {
if windows.length() == 0 {
RequestWindow::new("empty", 1, 0, 0)
} else {
let mut selected = windows[0]
for window in windows {
if window.availability_bp() > selected.availability_bp() {
selected = window
}
}
selected
}
}
///|
pub fn worst_window(windows : Array[RequestWindow]) -> RequestWindow {
if windows.length() == 0 {
RequestWindow::new("empty", 1, 0, 0)
} else {
let mut selected = windows[0]
for window in windows {
if window.availability_bp() < selected.availability_bp() {
selected = window
}
}
selected
}
}
///|
pub fn BudgetReport::budget_status(self : BudgetReport) -> String {
if self.remaining_bad < 0 {
"exhausted"
} else if self.consumed_bp >= 8000 {
"near_limit"
} else {
"healthy"
}
}
///|
pub fn BudgetReport::remaining_ratio_bp(self : BudgetReport) -> Int {
remaining_budget_ratio_bp(self)
}
///|
pub fn budget_status_priority(status : String) -> Int {
match status {
"exhausted" => 3
"near_limit" => 2
"at_limit" => 2
"healthy" => 0
"within_budget" => 0
_ => 1
}
}