Spaces:
Sleeping
Sleeping
apingali Claude Sonnet 4.6 commited on
Commit ·
bf0e212
1
Parent(s): a903d24
fix(drive-and-save): no negative savings when home metro is suppressed
Browse filesWhen the home metro has insufficient hospital data (n_hospitals < min_hospitals),
its median price is unreliable. Guard the savings branch with `not home_suppressed`
so a suppressed home falls through to the else branch (savings=0.0) rather than
producing a nonsensical negative savings figure. Also moves `import h3` up to
sit with the other third-party imports at the top of core.py.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- core.py +3 -3
- test_core.py +10 -0
core.py
CHANGED
|
@@ -9,6 +9,7 @@ import math
|
|
| 9 |
from dataclasses import dataclass
|
| 10 |
from pathlib import Path
|
| 11 |
|
|
|
|
| 12 |
import yaml
|
| 13 |
|
| 14 |
CONFIG_PATH = Path(__file__).parent / "config.yaml"
|
|
@@ -24,8 +25,6 @@ def load_config(path: "Path | str" = CONFIG_PATH) -> dict:
|
|
| 24 |
# H3 distance helpers
|
| 25 |
# ---------------------------------------------------------------------------
|
| 26 |
|
| 27 |
-
import h3
|
| 28 |
-
|
| 29 |
|
| 30 |
def _haversine_km(lat1: float, lon1: float, lat2: float, lon2: float) -> float:
|
| 31 |
R = 6371.0
|
|
@@ -141,6 +140,7 @@ def rank_metros(medians_df, metros_df, procedure_code: str, home_metro: str, cfg
|
|
| 141 |
visible = [r for r in rows if not r.suppressed]
|
| 142 |
home_row = next((r for r in rows if r.is_home), None)
|
| 143 |
home_median = home_row.median_price if home_row else None
|
|
|
|
| 144 |
|
| 145 |
candidates = [r for r in visible if not r.is_home]
|
| 146 |
cheapest = candidates[0] if candidates else None # rows already price-asc
|
|
@@ -148,7 +148,7 @@ def rank_metros(medians_df, metros_df, procedure_code: str, home_metro: str, cfg
|
|
| 148 |
home_row and not home_row.suppressed and visible and visible[0].is_home
|
| 149 |
)
|
| 150 |
|
| 151 |
-
if cheapest and home_median is not None and not home_is_cheapest:
|
| 152 |
savings = home_median - cheapest.median_price
|
| 153 |
savings_pct = (savings / home_median * 100.0) if home_median else 0.0
|
| 154 |
drive_to = cheapest.drive_min
|
|
|
|
| 9 |
from dataclasses import dataclass
|
| 10 |
from pathlib import Path
|
| 11 |
|
| 12 |
+
import h3
|
| 13 |
import yaml
|
| 14 |
|
| 15 |
CONFIG_PATH = Path(__file__).parent / "config.yaml"
|
|
|
|
| 25 |
# H3 distance helpers
|
| 26 |
# ---------------------------------------------------------------------------
|
| 27 |
|
|
|
|
|
|
|
| 28 |
|
| 29 |
def _haversine_km(lat1: float, lon1: float, lat2: float, lon2: float) -> float:
|
| 30 |
R = 6371.0
|
|
|
|
| 140 |
visible = [r for r in rows if not r.suppressed]
|
| 141 |
home_row = next((r for r in rows if r.is_home), None)
|
| 142 |
home_median = home_row.median_price if home_row else None
|
| 143 |
+
home_suppressed = home_row.suppressed if home_row else True
|
| 144 |
|
| 145 |
candidates = [r for r in visible if not r.is_home]
|
| 146 |
cheapest = candidates[0] if candidates else None # rows already price-asc
|
|
|
|
| 148 |
home_row and not home_row.suppressed and visible and visible[0].is_home
|
| 149 |
)
|
| 150 |
|
| 151 |
+
if cheapest and home_median is not None and not home_suppressed and not home_is_cheapest:
|
| 152 |
savings = home_median - cheapest.median_price
|
| 153 |
savings_pct = (savings / home_median * 100.0) if home_median else 0.0
|
| 154 |
drive_to = cheapest.drive_min
|
test_core.py
CHANGED
|
@@ -133,6 +133,16 @@ def test_build_cta_url_homepage_fallback_when_no_pattern():
|
|
| 133 |
assert "utm_source=mile-hi-labs" in url
|
| 134 |
|
| 135 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 136 |
def test_build_cta_url_uses_deep_link_pattern():
|
| 137 |
cfg = core.load_config()
|
| 138 |
cfg["funnel"]["deep_link_pattern"] = "/procedure/{code}/?metro={metro_slug}"
|
|
|
|
| 133 |
assert "utm_source=mile-hi-labs" in url
|
| 134 |
|
| 135 |
|
| 136 |
+
def test_rank_metros_home_suppressed_no_negative_savings():
|
| 137 |
+
medians, metros = _fixtures()
|
| 138 |
+
# "Tiny Town" has n_hospitals=1 (suppressed) and the lowest price ($50)
|
| 139 |
+
r = core.rank_metros(medians, metros, "45378", "Tiny Town", CFG)
|
| 140 |
+
assert r.savings >= 0 # never negative
|
| 141 |
+
assert r.savings == 0 # home price unreliable -> no claimed savings
|
| 142 |
+
assert r.home_is_cheapest is False
|
| 143 |
+
assert r.cheapest_metro == "Boulder" # cheapest non-suppressed shown informationally
|
| 144 |
+
|
| 145 |
+
|
| 146 |
def test_build_cta_url_uses_deep_link_pattern():
|
| 147 |
cfg = core.load_config()
|
| 148 |
cfg["funnel"]["deep_link_pattern"] = "/procedure/{code}/?metro={metro_slug}"
|