refactor(realestate-matcher): integer tier points + clearer legacy path docstring

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-28 08:38:09 +09:00
parent a75ff069df
commit eb04b954a5
2 changed files with 30 additions and 6 deletions

View File

@@ -6,12 +6,13 @@ from .db import _conn, _profile_row_to_dict
logger = logging.getLogger("realestate-lab") 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]]: def _region_score(profile: Dict[str, Any], ann: Dict[str, Any]) -> tuple[int, list[str]]:
"""지역 점수 계산. 광역 10점 + 자치구 5티어 가중치 0~25점. """지역 점수 계산. 광역 10점 + 자치구 5티어 점수 0~25점.
자치구 기준 미설정 시 광역 매칭만으로 35점 풀 점수(기존 호환). preferred_districts에 자치구가 하나라도 등록되면 티어 가중 모드로 동작.
자치구가 하나도 등록되지 않으면(빈 dict 또는 모든 티어가 빈 리스트) 광역 매칭만으로 35점 풀 점수(기존 호환).
""" """
region_name = ann.get("region_name") or "" region_name = ann.get("region_name") or ""
district = ann.get("district") 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: if not region_match:
return 0, [] return 0, []
has_districts = any(preferred_districts.get(t) for t in TIER_WEIGHTS) has_districts = any(preferred_districts.values())
if not has_districts: if not has_districts:
return 35, [f"선호 지역 일치: {region_name}"] return 35, [f"선호 지역 일치: {region_name}"]
score = 10 score = 10
reasons = [f"광역 일치: {region_name}"] 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 []): if district and district in (preferred_districts.get(tier) or []):
tier_score = round(25 * weight)
score += tier_score score += tier_score
reasons.append(f"자치구 {tier}티어: {district} (+{tier_score})") reasons.append(f"자치구 {tier}티어: {district} (+{tier_score})")
break break

View File

@@ -81,3 +81,27 @@ def test_eligibility_score_two_types_returns_20():
def test_eligibility_score_caps_at_25(): def test_eligibility_score_caps_at_25():
from app.matcher import _eligibility_score from app.matcher import _eligibility_score
assert _eligibility_score(["a", "b", "c", "d", "e"]) == 25 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