fix(site-finder): address PR #87 auto-review minor feedback
Backend (parcels.py):
- Centrality factor: weight=1.0 вместо weight=center_bonus (semantic — decay
для bonus не применяется, contribution = bonus IS the value). Защищает
future PDF-export/UI который мог бы показать weight отдельно от contribution.
- group_totals type: dict[str, dict[str, float | int]] — count это int,
contribution и contribution_pct это float. Уточняет hint для future mypy.
- Top-3 sort convention — добавлен inline-комментарий: positives "[:3] от
descending" (most-positive first); negatives "[-3:][::-1]" (most-negative
first). Оба "dominant first".
Frontend (ScoreBreakdownPanel.tsx):
- Stacked bar legend orphan fix: positive groups идут в legend под баром (как
до того); negative groups показываются отдельной строкой ниже "Снижают балл —
Шум/трамвай: −0.46". Никаких swatch'ей без bar-сегмента.
Per auto-review on 1d1c169.
This commit is contained in:
parent
1002214f12
commit
b5a218160d
2 changed files with 39 additions and 3 deletions
|
|
@ -902,7 +902,9 @@ def analyze_parcel(
|
||||||
else:
|
else:
|
||||||
center_bonus = 0.0
|
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:
|
if center_bonus > 0:
|
||||||
factors_detailed.append(
|
factors_detailed.append(
|
||||||
{
|
{
|
||||||
|
|
@ -911,7 +913,7 @@ def analyze_parcel(
|
||||||
"category_ru": "Центральность",
|
"category_ru": "Центральность",
|
||||||
"group": "Локация",
|
"group": "Локация",
|
||||||
"value": round(dist_to_center_km, 2),
|
"value": round(dist_to_center_km, 2),
|
||||||
"weight": center_bonus,
|
"weight": 1.0,
|
||||||
"contribution": round(center_bonus, 2),
|
"contribution": round(center_bonus, 2),
|
||||||
"verbal": (
|
"verbal": (
|
||||||
f"Близость к центру ЕКБ ({dist_to_center_km:.1f}км) — "
|
f"Близость к центру ЕКБ ({dist_to_center_km:.1f}км) — "
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,8 @@ export function ScoreBreakdownPanel({
|
||||||
color: "#6b7280",
|
color: "#6b7280",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{byGroup.map((g) => (
|
{/* Positive groups — visible в баре */}
|
||||||
|
{positiveGroups.map((g) => (
|
||||||
<div
|
<div
|
||||||
key={g.group}
|
key={g.group}
|
||||||
style={{ display: "flex", alignItems: "center", gap: 4 }}
|
style={{ display: "flex", alignItems: "center", gap: 4 }}
|
||||||
|
|
@ -134,6 +135,39 @@ export function ScoreBreakdownPanel({
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
{/* Negative groups — отдельной "drag" линией под баром (legend для bar
|
||||||
|
использует только positive, чтобы не было orphan swatches без сегмента) */}
|
||||||
|
{byGroup
|
||||||
|
.filter((g) => g.contribution < 0)
|
||||||
|
.map((g) => (
|
||||||
|
<div
|
||||||
|
key={`neg-${g.group}`}
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 4,
|
||||||
|
marginTop: 6,
|
||||||
|
fontSize: 12,
|
||||||
|
color: "#6b7280",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
display: "inline-block",
|
||||||
|
width: 10,
|
||||||
|
height: 10,
|
||||||
|
borderRadius: 2,
|
||||||
|
background: GROUP_COLORS[g.group] ?? GROUP_COLORS.Прочее,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<span>
|
||||||
|
Снижают балл — {g.group}:{" "}
|
||||||
|
<strong style={{ color: "#dc2626" }}>
|
||||||
|
{fmtContribution(g.contribution)}
|
||||||
|
</strong>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue