MoonBit-native small-site stormwater retrofit and rain-garden sizing toolkit.
moon add BB-ai-nb/spongekitimport {
"BB-ai-nb/spongekit"
}let event = @spongekit.rain_event("25mm design storm", 25.0)
let catchments = [
@spongekit.catchment_from_surface("roof", 120.0, @spongekit.Roof),
@spongekit.catchment_from_surface("walkway", 80.0, @spongekit.Pavement),
]
let plan = @spongekit.size_rain_garden(
catchments,
event,
@spongekit.default_garden_spec(),
)let soil = @spongekit.soil_profile(@spongekit.EngineeredMedia)
let tuned = @spongekit.spec_with_soil(@spongekit.default_garden_spec(), soil)let events = [
@spongekit.weighted_event("small storm", 10.0, 0.60),
@spongekit.weighted_event("design storm", 25.0, 0.30),
@spongekit.weighted_event("stress storm", 45.0, 0.10),
]
let summary = @spongekit.evaluate_event_series(
catchments,
events,
@spongekit.default_garden_spec(),
)let candidates = [
@spongekit.area_candidate("tree pit retrofit", 8.0),
@spongekit.area_candidate("courtyard strip", 22.0),
@spongekit.area_candidate("sunken lawn edge", 32.0),
]
let comparison = @spongekit.compare_candidate_areas(
catchments,
event,
@spongekit.default_garden_spec(),
candidates,
)match @spongekit.recommend_facility_mix(catchments, event, 36.0) {
Ok(train) => {
match @spongekit.estimate_treatment_train_cost(
train,
@spongekit.default_cost_profile(),
) {
Ok(costs) => println(costs.total_capital_cost.to_string())
Err(error) => println(error.label())
}
}
Err(error) => println(error.label())
}let scenarios = @spongekit.default_stress_scenarios(36.0)
let comparison = @spongekit.compare_retrofit_scenarios(
catchments,
event,
@spongekit.default_garden_spec(),
scenarios,
)let passport = @spongekit.scenario_passport("library courtyard", scenario_result)
println(passport.to_markdown())moon run cmd/mainstatus=ready
recommended_area_m2=26.285714285714285
{"status":"ready","event":"25mm campus retrofit storm",...}
train_capture_ratio=0.9978504347826087
train_capital_cost=35745.419279999995
best_scenario=showcase upgrade
average_scenario_score=81moon check
moon build
moon test
moon run cmd/main
moon package
moon publish --dry-runpub(all) struct CandidateComparison {
candidate_count : Int
best_name : String
best_score : Int
performances : Array[CandidatePerformance]
} derive(Eq, Debug)pub(all) struct CandidatePerformance {
name : String
area_m2 : Double
cell_count : Int
cell_area_m2 : Double
storage_capacity_m3 : Double
runoff_volume_m3 : Double
captured_volume_m3 : Double
bypass_volume_m3 : Double
capture_ratio : Double
drawdown_hours : Double
score : Int
status : PlanStatus
issues : Array[PlanIssue]
} derive(Eq, Debug)pub(all) struct CostProfile {
tier : CostTier
currency : String
construction_per_m2 : Double
excavation_per_m3 : Double
media_per_m3 : Double
planting_per_m2 : Double
pretreatment_each : Double
inspection_per_visit : Double
sediment_service_per_visit : Double
annual_maintenance_rate : Double
design_markup_rate : Double
contingency_rate : Double
lifespan_years : Int
} derive(Eq, Debug)pub(all) struct EventSizing {
event_name : String
depth_mm : Double
weight : Double
runoff_volume_m3 : Double
recommended_area_m2 : Double
capture_ratio : Double
drawdown_hours : Double
status : PlanStatus
} derive(Eq, Debug)pub(all) struct FacilityContribution {
name : String
kind : FacilityKind
footprint_area_m2 : Double
storage_capacity_m3 : Double
event_runoff_m3 : Double
captured_volume_m3 : Double
bypass_volume_m3 : Double
capture_ratio : Double
drawdown_hours : Double
resilience_score : Int
status : PlanStatus
notes : Array[String]
} derive(Eq, Debug)pub(all) struct FacilityCost {
name : String
kind : FacilityKind
currency : String
footprint_area_m2 : Double
capital_cost : Double
annual_maintenance_cost : Double
lifecycle_cost : Double
annualized_cost : Double
cost_per_captured_m3 : Double
recommended_visits_per_year : Int
notes : Array[String]
} derive(Eq, Debug)pub(all) struct FacilitySpec {
kind : FacilityKind
name : String
footprint_area_m2 : Double
storage_depth_mm : Double
infiltration_rate_mm_per_hr : Double
drain_delay_hours : Double
pretreatment_score : Double
vegetation_score : Double
max_capture_ratio : Double
overflow_priority : Int
} derive(Eq, Debug)pub(all) struct GardenPlan {
status : PlanStatus
event_name : String
catchment_count : Int
catchment_area_m2 : Double
design_rain_mm : Double
runoff_volume_m3 : Double
storage_depth_mm : Double
required_area_m2 : Double
recommended_area_m2 : Double
cell_count : Int
cell_area_m2 : Double
drawdown_hours : Double
capture_ratio : Double
issues : Array[PlanIssue]
} derive(Eq, Debug)pub(all) struct MaintenancePlan {
priority : MaintenancePriority
interval_days : Int
risk_score : Int
actions : Array[MaintenanceAction]
note : String
} derive(Eq, Debug)pub(all) struct RetrofitPassport {
site_name : String
event_name : String
band : PassportBand
overall_score : Int
footprint_area_m2 : Double
runoff_volume_m3 : Double
captured_volume_m3 : Double
bypass_volume_m3 : Double
capture_ratio : Double
capital_cost : Double
annual_maintenance_cost : Double
maintenance_priority : MaintenancePriority
maintenance_interval_days : Int
public_summary : String
field_actions : Array[String]
assumptions : Array[String]
} derive(Eq, Debug)pub(all) struct RetrofitScenario {
name : String
rainfall_multiplier : Double
runoff_multiplier : Double
infiltration_multiplier : Double
target_capture_ratio : Double
available_area_m2 : Double
sediment_load_index : Double
cost_tier : CostTier
capital_budget : Double
annual_budget : Double
} derive(Eq, Debug)pub(all) struct ScenarioComparison {
scenario_count : Int
best_name : String
worst_name : String
average_score : Double
max_runoff_m3 : Double
min_capture_ratio : Double
results : Array[ScenarioResult]
} derive(Eq, Debug)pub(all) struct ScenarioResult {
name : String
adjusted_rain_mm : Double
adjusted_runoff_m3 : Double
recommended_area_m2 : Double
candidate_best_name : String
candidate_best_score : Int
treatment_capture_ratio : Double
treatment_bypass_m3 : Double
treatment_resilience_score : Int
maintenance_priority : MaintenancePriority
maintenance_risk_score : Int
total_capital_cost : Double
lifecycle_cost : Double
budget_fit_score : Int
overall_score : Int
status : PlanStatus
notes : Array[String]
} derive(Eq, Debug)pub(all) struct SeriesSummary {
event_count : Int
ready_count : Int
review_count : Int
controlling_event_name : String
max_recommended_area_m2 : Double
weighted_runoff_m3 : Double
weighted_capture_ratio : Double
results : Array[EventSizing]
} derive(Eq, Debug)pub(all) enum SpongeError {
NonPositiveArea
NegativeRainfall
InvalidRunoffCoefficient
InvalidCurveNumber
InvalidInfiltrationRate
InvalidStorageDepth
InvalidSafetyFactor
InvalidCellLimit
InvalidWeight
InvalidCandidateArea
InvalidSedimentLoad
InvalidFacilitySpec
InvalidCostProfile
InvalidScenarioInput
} derive(Eq, Debug)pub(all) struct TrainCostSummary {
currency : String
facility_count : Int
total_capital_cost : Double
annual_maintenance_cost : Double
lifecycle_cost : Double
annualized_cost : Double
captured_volume_m3 : Double
cost_per_captured_m3 : Double
highest_cost_name : String
highest_cost : Double
items : Array[FacilityCost]
notes : Array[String]
} derive(Eq, Debug)pub(all) struct TreatmentTrainPlan {
event_name : String
facility_count : Int
runoff_volume_m3 : Double
footprint_area_m2 : Double
total_capacity_m3 : Double
total_captured_m3 : Double
bypass_volume_m3 : Double
capture_ratio : Double
weighted_drawdown_hours : Double
resilience_score : Int
status : PlanStatus
contributions : Array[FacilityContribution]
notes : Array[String]
} derive(Eq, Debug)fn adjusted_catchment_for_soil(catchment : Catchment, soil : SoilProfile) -> Result[Catchment, SpongeError]fn area_candidate_with_cell_limit(name : String, area_m2 : Double, max_cell_area_m2 : Double) -> AreaCandidatefn blended_soil_profile(name : String, soils : Array[SoilProfile], weights : Array[Double]) -> Result[SoilProfile, SpongeError]fn budget_fit_score(summary : TrainCostSummary, capital_budget : Double, annual_budget : Double) -> Result[Int, SpongeError]fn build_retrofit_passport(site_name : String, garden : GardenPlan, train : TreatmentTrainPlan, cost : TrainCostSummary, maintenance : MaintenancePlan) -> RetrofitPassportfn compare_candidate_areas(catchments : Array[Catchment], event : RainEvent, spec : GardenSpec, candidates : Array[AreaCandidate]) -> Result[CandidateComparison, SpongeError]fn compare_retrofit_scenarios(catchments : Array[Catchment], base_event : RainEvent, spec : GardenSpec, scenarios : Array[RetrofitScenario]) -> Result[ScenarioComparison, SpongeError]fn curve_number_runoff(area_m2 : Double, rainfall_mm : Double, curve_number : Double) -> Result[CurveNumberResult, SpongeError]fn curve_number_runoff_depth(rainfall_mm : Double, curve_number : Double) -> Result[Double, SpongeError]fn custom_cost_profile(currency : String, construction_per_m2 : Double, excavation_per_m3 : Double, media_per_m3 : Double, planting_per_m2 : Double, pretreatment_each : Double, inspection_per_visit : Double, sediment_service_per_visit : Double, annual_maintenance_rate : Double, design_markup_rate : Double, contingency_rate : Double, lifespan_years : Int) -> CostProfilefn estimate_facility_cost(contribution : FacilityContribution, profile : CostProfile) -> Result[FacilityCost, SpongeError]fn estimate_treatment_train_cost(plan : TreatmentTrainPlan, profile : CostProfile) -> Result[TrainCostSummary, SpongeError]fn evaluate_candidate_area(catchments : Array[Catchment], event : RainEvent, spec : GardenSpec, candidate : AreaCandidate) -> Result[CandidatePerformance, SpongeError]fn evaluate_event_series(catchments : Array[Catchment], events : Array[WeightedRainEvent], spec : GardenSpec) -> Result[SeriesSummary, SpongeError]fn evaluate_facility(event_runoff_m3 : Double, facility : FacilitySpec) -> Result[FacilityContribution, SpongeError]fn evaluate_retrofit_scenario(catchments : Array[Catchment], base_event : RainEvent, spec : GardenSpec, scenario : RetrofitScenario) -> Result[ScenarioResult, SpongeError]fn evaluate_treatment_train(catchments : Array[Catchment], event : RainEvent, facilities : Array[FacilitySpec]) -> Result[TreatmentTrainPlan, SpongeError]fn facility_template(kind : FacilityKind, name : String, footprint_area_m2 : Double) -> FacilitySpecfn facility_with_hydraulics(kind : FacilityKind, name : String, footprint_area_m2 : Double, storage_depth_mm : Double, infiltration_rate_mm_per_hr : Double, drain_delay_hours : Double, pretreatment_score : Double, vegetation_score : Double, max_capture_ratio : Double, overflow_priority : Int) -> FacilitySpecfn maintenance_plan(plan : GardenPlan, soil : SoilProfile, sediment_load_index : Double, months_since_service : Int) -> Result[MaintenancePlan, SpongeError]fn recommend_facility_mix(catchments : Array[Catchment], event : RainEvent, available_area_m2 : Double) -> Result[TreatmentTrainPlan, SpongeError]fn retrofit_scenario(name : String, rainfall_multiplier : Double, available_area_m2 : Double) -> RetrofitScenariofn scenario_with_budget(name : String, rainfall_multiplier : Double, runoff_multiplier : Double, infiltration_multiplier : Double, target_capture_ratio : Double, available_area_m2 : Double, sediment_load_index : Double, cost_tier : CostTier, capital_budget : Double, annual_budget : Double) -> RetrofitScenariofn size_rain_garden(catchments : Array[Catchment], event : RainEvent, spec : GardenSpec) -> Result[GardenPlan, SpongeError]fn total_runoff_volume(catchments : Array[Catchment], event : RainEvent) -> Result[RunoffResult, SpongeError]Install
Download zipMoonBit-native small-site stormwater retrofit and rain-garden sizing toolkit.