Spaces:
Running
Running
| 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} | |
| } | |
| } |