diff --git a/realestate-lab/app/matcher.py b/realestate-lab/app/matcher.py index 3df8b2b..60039b8 100644 --- a/realestate-lab/app/matcher.py +++ b/realestate-lab/app/matcher.py @@ -6,12 +6,13 @@ from .db import _conn, _profile_row_to_dict logger = logging.getLogger("realestate-lab") -TIER_WEIGHTS = {"S": 1.00, "A": 0.80, "B": 0.60, "C": 0.40, "D": 0.20} +TIER_POINTS = {"S": 25, "A": 20, "B": 15, "C": 10, "D": 5} def _region_score(profile: Dict[str, Any], ann: Dict[str, Any]) -> tuple[int, list[str]]: - """지역 점수 계산. 광역 10점 + 자치구 5티어 가중치 0~25점. - 자치구 기준 미설정 시 광역 매칭만으로 35점 풀 점수(기존 호환). + """지역 점수 계산. 광역 10점 + 자치구 5티어 점수 0~25점. + preferred_districts에 자치구가 하나라도 등록되면 티어 가중 모드로 동작. + 자치구가 하나도 등록되지 않으면(빈 dict 또는 모든 티어가 빈 리스트) 광역 매칭만으로 35점 풀 점수(기존 호환). """ region_name = ann.get("region_name") or "" district = ann.get("district") or "" @@ -22,15 +23,14 @@ def _region_score(profile: Dict[str, Any], ann: Dict[str, Any]) -> tuple[int, li if not region_match: return 0, [] - has_districts = any(preferred_districts.get(t) for t in TIER_WEIGHTS) + has_districts = any(preferred_districts.values()) if not has_districts: return 35, [f"선호 지역 일치: {region_name}"] score = 10 reasons = [f"광역 일치: {region_name}"] - for tier, weight in TIER_WEIGHTS.items(): + for tier, tier_score in TIER_POINTS.items(): if district and district in (preferred_districts.get(tier) or []): - tier_score = round(25 * weight) score += tier_score reasons.append(f"자치구 {tier}티어: {district} (+{tier_score})") break diff --git a/realestate-lab/tests/test_matcher.py b/realestate-lab/tests/test_matcher.py index c757c64..f6bd7b9 100644 --- a/realestate-lab/tests/test_matcher.py +++ b/realestate-lab/tests/test_matcher.py @@ -81,3 +81,27 @@ def test_eligibility_score_two_types_returns_20(): def test_eligibility_score_caps_at_25(): from app.matcher import _eligibility_score assert _eligibility_score(["a", "b", "c", "d", "e"]) == 25 + + +def test_region_score_b_tier_district(): + """광역 매칭 + B티어 자치구: 10 + 15 = 25.""" + from app.matcher import _region_score + profile = { + "preferred_regions": ["서울"], + "preferred_districts": {"S": [], "A": [], "B": ["관악구"], "C": [], "D": []}, + } + ann = {"region_name": "서울특별시", "district": "관악구"} + score, _ = _region_score(profile, ann) + assert score == 25 + + +def test_region_score_c_tier_district(): + """광역 매칭 + C티어 자치구: 10 + 10 = 20.""" + from app.matcher import _region_score + profile = { + "preferred_regions": ["서울"], + "preferred_districts": {"S": [], "A": [], "B": [], "C": ["은평구"], "D": []}, + } + ann = {"region_name": "서울특별시", "district": "은평구"} + score, _ = _region_score(profile, ann) + assert score == 20