///|
pub struct StationCapacity {
station : String
available_hours : Double
planned_hours : Double
operators : Int
utilization : Double
overloaded : Bool
} derive(Debug, ToJson)
///|
pub struct ProductionStage {
name : String
duration_hours : Double
required_station : String
sequence : Int
completed : Bool
} derive(Debug, ToJson)
///|
pub fn station_capacity(
station~ : String,
available_hours~ : Double,
planned_hours~ : Double,
operators~ : Int,
) -> StationCapacity {
let utilization = if available_hours <= 0.0 {
0.0
} else {
planned_hours / available_hours
}
{
station,
available_hours,
planned_hours,
operators,
utilization,
overloaded: utilization > 1.0,
}
}
///|
pub fn stage(
name~ : String,
duration_hours~ : Double,
required_station~ : String,
sequence~ : Int,
) -> ProductionStage {
{ name, duration_hours, required_station, sequence, completed: false }
}
///|
pub fn complete_stage(value : ProductionStage) -> ProductionStage {
{ ..value, completed: true }
}
///|
pub fn capacity_remaining(capacity : StationCapacity) -> Double {
capacity.available_hours - capacity.planned_hours
}
///|
pub fn capacity_headroom(capacity : StationCapacity) -> Double {
if capacity.available_hours <= 0.0 {
0.0
} else {
capacity_remaining(capacity) / capacity.available_hours
}
}
///|
pub fn capacity_status(capacity : StationCapacity) -> String {
if capacity.overloaded {
"overloaded"
} else if capacity.utilization >= 0.85 {
"near_limit"
} else {
"available"
}
}
///|
pub fn add_planned_hours(
capacity : StationCapacity,
hours : Double,
) -> StationCapacity {
station_capacity(
station=capacity.station,
available_hours=capacity.available_hours,
planned_hours=capacity.planned_hours + hours,
operators=capacity.operators,
)
}
///|
pub fn stage_duration(stages : Array[ProductionStage]) -> Double {
let mut total = 0.0
for value in stages {
total += value.duration_hours
}
total
}
///|
pub fn completed_stage_count(stages : Array[ProductionStage]) -> Int {
let mut count = 0
for value in stages {
if value.completed {
count += 1
}
}
count
}
///|
pub fn stage_completion_rate(stages : Array[ProductionStage]) -> Double {
if stages.length() == 0 {
0.0
} else {
completed_stage_count(stages).to_double() / stages.length().to_double()
}
}
///|
pub fn stages_for_station(
stages : Array[ProductionStage],
station : String,
) -> Array[ProductionStage] {
let result : Array[ProductionStage] = []
for value in stages {
if value.required_station == station {
result.push(value)
}
}
result
}
///|
pub fn sort_stages(stages : Array[ProductionStage]) -> Array[ProductionStage] {
let result = stages.copy()
result.sort_by(fn(a, b) { a.sequence - b.sequence })
result
}
///|
pub fn invalid_stage_sequence(stages : Array[ProductionStage]) -> Int {
let sorted = sort_stages(stages)
for i in 1.. Double {
if capacities.length() == 0 {
0.0
} else {
let mut high = capacities[0].utilization
let mut low = high
for value in capacities {
high = high.max(value.utilization)
low = low.min(value.utilization)
}
high - low
}
}
///|
pub fn total_available_hours(capacities : Array[StationCapacity]) -> Double {
let mut total = 0.0
for value in capacities {
total += value.available_hours
}
total
}
///|
pub fn total_planned_hours(capacities : Array[StationCapacity]) -> Double {
let mut total = 0.0
for value in capacities {
total += value.planned_hours
}
total
}
///|
pub fn plan_utilization(capacities : Array[StationCapacity]) -> Double {
let available = total_available_hours(capacities)
if available <= 0.0 {
0.0
} else {
total_planned_hours(capacities) / available
}
}