diff --git a/backend/app/api/v1/parcels.py b/backend/app/api/v1/parcels.py index d65b412c..b0dae3b2 100644 --- a/backend/app/api/v1/parcels.py +++ b/backend/app/api/v1/parcels.py @@ -612,7 +612,9 @@ def analyze_parcel( else: center_bonus = 0.0 - # X1 (#47): centrality как отдельный synthetic factor в breakdown + # X1 (#47): centrality как отдельный synthetic factor в breakdown. + # NB: для centrality decay не применяется (bonus IS the value), поэтому + # weight=1.0 семантически — "no decay multiplier"; contribution = center_bonus. if center_bonus > 0: factors_detailed.append( { @@ -621,7 +623,7 @@ def analyze_parcel( "category_ru": "Центральность", "group": "Локация", "value": round(dist_to_center_km, 2), - "weight": center_bonus, + "weight": 1.0, "contribution": round(center_bonus, 2), "verbal": ( f"Близость к центру ЕКБ ({dist_to_center_km:.1f}км) — " @@ -1004,11 +1006,15 @@ def analyze_parcel( f["contribution_pct"] = round(100.0 * abs(f["contribution"]) / abs_total, 1) factors_sorted = sorted(factors_detailed, key=lambda x: x["contribution"], reverse=True) + # Convention: оба top-list'а отсортированы "dominant first": + # positives → most-positive first (просто [:3] от descending sort) + # negatives → most-negative first ([-3:][::-1] = последние три (наиболее + # отрицательные) реверсом, чтобы first item был самым большим минусом) score_top_3_positives = [f for f in factors_sorted if f["contribution"] > 0][:3] score_top_3_negatives = [f for f in factors_sorted if f["contribution"] < 0][-3:][::-1] - # By-group totals — для stacked-bar в UI - group_totals: dict[str, dict[str, float]] = {} + # By-group totals — для stacked-bar в UI. count это int, contribution* — float. + group_totals: dict[str, dict[str, float | int]] = {} for f in factors_detailed: g = group_totals.setdefault( f["group"], {"contribution": 0.0, "count": 0, "contribution_pct": 0.0} diff --git a/frontend/src/components/site-finder/ScoreBreakdownPanel.tsx b/frontend/src/components/site-finder/ScoreBreakdownPanel.tsx index 74d382a1..5f86c52e 100644 --- a/frontend/src/components/site-finder/ScoreBreakdownPanel.tsx +++ b/frontend/src/components/site-finder/ScoreBreakdownPanel.tsx @@ -111,7 +111,8 @@ export function ScoreBreakdownPanel({ color: "#6b7280", }} > - {byGroup.map((g) => ( + {/* Positive groups — visible в баре */} + {positiveGroups.map((g) => (