Spaces:
Sleeping
Sleeping
File size: 7,229 Bytes
0a87e25 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | from config import FLOW_RATES, USAGE_PATTERNS, USER_MULTIPLIERS, DRINKING_WATER
def calculate_usage(requirements):
"""
Calculates daily water usage and survival days.
IMPORTANT - How effective multipliers work (matching Excel model):
- eff_shower/sink = SUM of (count Γ mult) across all user types
β This already encodes total group usage, so NO extra Γ num_adults needed
- eff_toilet = SUM of all adult counts (toilet mult = 1 for everyone)
β Used for display only; toilet formula uses base per-person Γ 1 event
- Toilet daily = flow Γ frequency Γ 1 (base, not scaled by eff_toilet)
- Drinking adults = 0.7 Γ num_adults from CORE PARAMS (not user type total)
"""
# ββ User type counts (from User Type Distribution) ββββββββββββββββββββββ
num_expert = requirements.get("num_expert", 0)
num_typical = requirements.get("num_typical", 0)
num_glamper = requirements.get("num_glamper", 0)
# ββ Core params ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
num_adults = requirements.get("num_adults", num_expert + num_typical + num_glamper)
num_children = requirements.get("num_children", 0)
climate_mult = requirements.get("climate_mult", 1.0)
# ββ Effective Multipliers (SUM β already encodes all adults) βββββββββββββ
# Excel: Eff Shower = 2Γ0.6 + 0Γ1.0 + 1Γ1.5 = 2.7 (NOT divided by adults)
eff_shower_mult = (
num_expert * USER_MULTIPLIERS["expert"]["shower"] +
num_typical * USER_MULTIPLIERS["typical"]["shower"] +
num_glamper * USER_MULTIPLIERS["glamper"]["shower"]
)
eff_sink_mult = (
num_expert * USER_MULTIPLIERS["expert"]["sink"] +
num_typical * USER_MULTIPLIERS["typical"]["sink"] +
num_glamper * USER_MULTIPLIERS["glamper"]["sink"]
)
# Toilet mult = 1 for all types β eff_toilet = total adults (display only)
eff_toilet_mult = num_expert + num_typical + num_glamper
# ββ Daily Fresh Water Per Activity βββββββββββββββββββββββββββββββββββββββ
# Shower: flow Γ duration Γ frequency Γ eff_shower_mult Γ climate
# (eff_shower_mult already accounts for all adults β no Γ num_adults)
shower_daily = (
FLOW_RATES["shower"] *
USAGE_PATTERNS["shower"]["duration"] *
USAGE_PATTERNS["shower"]["frequency"] *
eff_shower_mult *
climate_mult
)
# Kitchen Sink: same pattern
kitchen_sink_daily = (
FLOW_RATES["kitchen_sink"] *
USAGE_PATTERNS["kitchen_sink"]["duration"] *
USAGE_PATTERNS["kitchen_sink"]["frequency"] *
eff_sink_mult *
climate_mult
)
# Bathroom Sink: same pattern
bathroom_sink_daily = (
FLOW_RATES["bathroom_sink"] *
USAGE_PATTERNS["bathroom_sink"]["duration"] *
USAGE_PATTERNS["bathroom_sink"]["frequency"] *
eff_sink_mult *
climate_mult
)
# Toilet: base per-person usage only (1.8 gal Γ 6 flushes Γ 1 person base)
# Excel shows 10.8 regardless of group size in activity table
toilet_daily = (
FLOW_RATES["toilet"] *
USAGE_PATTERNS["toilet"]["frequency"] *
1 # base single-person; eff_toilet is display only
)
# Drinking: uses core num_adults (e.g., 2) not user-type total
drinking_adults_daily = DRINKING_WATER["adult"] * num_adults
drinking_children_daily = DRINKING_WATER["child"] * num_children
total_drinking_daily = drinking_adults_daily + drinking_children_daily
# ββ Totals βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
total_fresh_used_per_day = (
shower_daily + kitchen_sink_daily + bathroom_sink_daily +
toilet_daily + total_drinking_daily
)
total_grey_added_per_day = shower_daily + kitchen_sink_daily + bathroom_sink_daily
total_black_added_per_day = toilet_daily
# ββ Tank Levels ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
fresh_cap = requirements.get("fresh_cap", 0)
grey_cap = requirements.get("grey_cap", 0)
black_cap = requirements.get("black_cap", 0)
fresh_level = requirements.get("fresh_level", 0)
grey_level = requirements.get("grey_level", 0)
black_level = requirements.get("black_level", 0)
# ββ Survival Days ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Fresh: runs DOWN β days until empty
# Grey: fills UP β days until full
# Black: fills UP β days until full
days_fresh = (fresh_level / total_fresh_used_per_day
if total_fresh_used_per_day > 0 and fresh_level > 0
else 0.0)
days_grey = ((grey_cap - grey_level) / total_grey_added_per_day
if total_grey_added_per_day > 0
else float('inf'))
days_black = ((black_cap - black_level) / total_black_added_per_day
if total_black_added_per_day > 0
else float('inf'))
overall_survival = min(days_fresh, days_grey, days_black)
# Limiting factor
tank_map = {days_fresh: "Fresh", days_grey: "Grey", days_black: "Black"}
limiting_tank = tank_map[min(days_fresh, days_grey, days_black)]
return {
"daily_usage": {
"fresh": round(total_fresh_used_per_day, 2),
"grey": round(total_grey_added_per_day, 2),
"black": round(total_black_added_per_day, 2),
"drinking": round(total_drinking_daily, 2),
"shower": round(shower_daily, 2),
"kitchen_sink": round(kitchen_sink_daily, 2),
"bathroom_sink": round(bathroom_sink_daily, 2),
"toilet": round(toilet_daily, 2),
},
"survival_days": {
"fresh": round(days_fresh, 4),
"grey": round(days_grey, 4),
"black": round(days_black, 4),
"overall": round(overall_survival, 4),
"limiting_tank": limiting_tank,
},
"effective_multipliers": {
"shower": round(eff_shower_mult, 3),
"sink": round(eff_sink_mult, 3),
"toilet": eff_toilet_mult,
},
"tanks": {
"fresh": {"cap": fresh_cap, "level": fresh_level},
"grey": {"cap": grey_cap, "level": grey_level},
"black": {"cap": black_cap, "level": black_level}
}
} |