# 5. Code Snippet Thực Tế (stylist_engine.py)

Dưới đây là phương thức cốt lõi `_score` tính điểm tương hợp giữa 2 sản phẩm:

```python
def _score(self, src: dict, tgt: dict, occasion: str) -> int:
    """Compute compatibility score (0-100) cho src+tgt pair dựa trên Color, Material, Role, và Occasion."""
    rules = self.rules
    weights = rules["score_weights"]
    total = 0

    # 1. Color score (0-30) - Tính toán ma trận màu và demographic
    color_score = self._color_score(src.get("color", ""), tgt.get("color", ""), tgt.get("gender", ""))
    total += int(color_score * weights["color"] / 30)

    # 2. Occasion score (0-20) - Mức độ trùng khớp NLP tags về dịp mặc
    if "occasion" in weights:
        occ_score = self._occasion_score(src.get("occasion_tags", []), tgt.get("occasion_tags", []), occasion)
        total += int(occ_score * weights["occasion"] / 20)

    # 3. Role bonus (0-15) - Ưu tiên Bottom > Accessory
    role = self._get_role(tgt)
    role_priority = rules.get("role_priority", {})
    role_bonus = max(0, 16 - role_priority.get(role, 3) * 5)
    total += int(role_bonus * weights["role"] / 15)

    # 4. Material & Season score (0-10) - Độ tương thích mùa
    if "material" in weights:
        material_score = self._material_score(src, tgt)
        total += int(material_score * weights["material"] / 10)

    return min(total, 100)
```

Quá trình chạy cho 1 sản phẩm `compute_dynamic_rule_matches` sẽ:
1. Lấy tập luật DB (`_fetch_rules_with_reason`) cho Anchor category.
2. Duyệt `catalog` và dùng `_pass_hard_filter` để loại bỏ rác.
3. Chạy `_score` để lấy điểm tổng.
4. Lọc Deduplicate (ưu tiên đa dạng màu và danh mục sản phẩm).