# GESP等级：四级 | GESP Python 四级考点
"""
================================================================================
 练习1 ★ — 颜色数据清洗（set + dict 专项）
================================================================================

  练习目标：
    结合挑战1的知识，独立完成颜色数据的清洗、归并与查询。

  背景：
    你从多个来源收集了颜色数据，格式不一，需要统一清洗。
================================================================================
"""

print("=" * 60)
print("练习1 ★ — 颜色数据清洗")
print("=" * 60)

# ========== 原始数据 ==========
raw_input = [
    ("  lightBLUE ", "#ADD8E6"),
    ("LIGHTblue", "#ADD8E6"),
    ("  light_blue", "#ADD8E6"),
    ("darkRED", "#8B0000"),
    (" Dark_Red  ", "#8B0000"),
    ("dark_red", "#8B0000"),
    ("  navy ", "#000080"),
    ("Navy", "#000080"),
    ("gold", "#FFD700"),
    ("  GOLD ", "#FFD700"),
    ("golden", None),               # 缺失颜色值
    ("  ", "#FFFFFF"),              # 空名称
    (None, "#000000"),              # 空名称
]

print(f"\n原始数据条目数：{len(raw_input)}")

# ========== 练习1：名称规范化 ==========
# 待办：将名称统一为小写+下划线格式（snake_case），如 "light_blue"
# 去除首尾空格，替换空格为下划线，转小写，过滤空名称
def normalize_name(name: str) -> str:
    """将颜色名称规范化为 snake_case"""
    if name is None:
        return None
    name = name.strip().lower()
    name = name.replace(" ", "_")
    name = name.replace("-", "_")
    return name if name else None


# ========== 练习2：set 去重 ==========
# 待办：用 set 去重，保留最佳记录（有 hex 值的优先）
print("\n1. 数据清洗与去重：")
cleaned = {}  # dict: normalized_name -> hex_value

for name, hex_val in raw_input:
    norm_name = normalize_name(name)
    if norm_name is None:
        continue
    # 已存在且有 hex 值则跳过，否则用新值补全
    if norm_name in cleaned and cleaned[norm_name] is not None:
        continue
    cleaned[norm_name] = hex_val

print(f"   清洗后唯一颜色数：{len(cleaned)}")
for name, hexv in sorted(cleaned.items()):
    status = f"#{hexv}" if hexv else "【缺失 hex】"
    print(f"     {name:15s} → {status}")

# ========== 练习3：找出缺失 hex 的颜色 ==========
print("\n2. 缺失 hex 值的颜色（待补充）：")
missing_hex = {name for name, hexv in cleaned.items() if hexv is None}
print(f"   {missing_hex if missing_hex else '无缺失，数据完整'}")

# ========== 练习4：建立 RGB 映射 ==========
print("\n3. 建立 hex → RGB 映射表（部分演示）：")


def hex_to_rgb(hex_str: str) -> tuple:
    """#RRGGBB → (R, G, B)"""
    if hex_str is None:
        return None
    hex_str = hex_str.lstrip("#")
    return tuple(int(hex_str[i:i+2], 16) for i in range(0, 6, 2))


hex_to_name = {}  # 反向：hex → 名称列表
for name, hexv in cleaned.items():
    if hexv:
        hex_to_name.setdefault(hexv, []).append(name)

for hexv, names in sorted(hex_to_name.items()):
    rgb = hex_to_rgb(hexv)
    print(f"   {hexv} → RGB{rgb} → {', '.join(names)}")

# ========== 练习5：色彩分类 ==========
print("\n4. 色彩分类（按 RGB 亮度）：")


def brightness(rgb: tuple) -> float:
    """计算亮度 0~1"""
    if rgb is None:
        return 0
    return (0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2]) / 255


categories = {}  # dict: 类别名 -> set(颜色名)
for name, hexv in cleaned.items():
    rgb = hex_to_rgb(hexv)
    b = brightness(rgb)
    if b < 0.3:
        cat = "暗色"
    elif b < 0.6:
        cat = "中色"
    else:
        cat = "亮色"
    categories.setdefault(cat, set()).add(name)

for cat in ["暗色", "中色", "亮色"]:
    names = categories.get(cat, set())
    print(f"   {cat}（亮度{['<0.3', '0.3~0.6', '>0.6'][['暗色','中色','亮色'].index(cat)]}）：{', '.join(sorted(names))}")

# ========== 总结 ==========
print()
print(">>> 练习1 核心技能 <<<")
print("✓ 字符串规范化 + set 去重是数据清洗标配")
print("✓ dict 做唯一映射，保留最佳记录")
print("✓ 集合推导式快速筛选缺失项")
print("✓ dict + set 组合做分类聚合")
