import sys, os
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
rep = chr(0xfffd)
base = 'D:\\Code\\DTU 程序\\STM32F4-Base\\'

fixes = {
    'Drivers\\BSP\\CH395F\\ch395f.c': [
        # Author name
        ('王建' + rep + '? * 创建', '王建锋 * 创建'),
        # Closing parens and punctuation
        ('手册要' + rep + '?SPI', '手册要求 SPI'),
        ('rx_buf[' + rep + '? *', 'rx_buf] *'),
        ('SPI 驱动' + rep + '?DMA TX+RX', 'SPI 驱动) DMA TX+RX'),
        ('SPI 驱动' + rep + '?DMA 传输', 'SPI 驱动) DMA 传输'),
        ('begin() ' + rep + '?ch395f_spi_end', 'begin() 到 ch395f_spi_end'),
        ('begin() ' + rep + '?ch395f_spi_end', 'begin() 到 ch395f_spi_end'),
        ('begin() ' + rep + '?ch395f_spi_end', 'begin() 到 ch395f_spi_end'),
        ('0x57' + rep + '? *', '0x57) *'),
        ('exist() 检' + rep + '? */', 'exist() 检查) */'),
        ('在前，' + rep + '? */', '在前，) */'),
        ('默认' + rep + '?' + rep + '? *', '默认值) *'),
        ('SUCCESS ' + rep + '?CH395F_CMD_RET', 'SUCCESS 或 CH395F_CMD_RET'),
        ('4s' + rep + '? */', '4s) */'),
        ('EEPROM' + rep + '? * 入口参数', 'EEPROM) * 入口参数'),
        ('TE5' + rep + '? */', 'TE5) */'),
        ('手' + rep + '?5.37', '手册 5.37'),
        ('发送启' + rep + '?禁用', '发送启禁用'),
        ('时钟）' + rep + '? *', '时钟）， *'),
        (rep + '?DMA 接收缓冲区偏移', '从 DMA 接收缓冲区偏移'),
        ('0~7' + rep + '? * 返回值', '0~7) * 返回值'),
        ('100ms' + rep + '?=默认', '100ms)=默认'),
        ('次' + rep + '?=默认', '次数=默认'),
        ('最' + rep + '?128', '最大 128'),
        ('+IP' + rep + '? * 限定条件', '+IP) * 限定条件'),
    ],
    'Drivers\\BSP\\CH395F\\ch395f_test.c': [
        ('默' + rep + '?192.168.1.2:8081' + rep + '?', '认 192.168.1.2:8081)'),
        ('默' + rep + '?192.168.1.2:8082' + rep + '?', '认 192.168.1.2:8082)'),
        ('version) ' + rep + '?read-clear', 'version) 即 read-clear'),
        ('创建' + rep + '?UDP', '创建 UDP'),
        ('DHCP ' + rep + '?轮询等待', 'DHCP 并轮询等待'),
        ('= 60000' + rep + '?*/', '= 60000)*/'),
    ],
    'Drivers\\BSP\\GD5F2GQ5UE\\gd5f2gq5ue.c': [
        ('再拉' + rep + '? */', '再拉高 */'),
        ('P_FAIL ' + rep + '? */', 'P_FAIL 位 */'),
        ('E_FAIL ' + rep + '? */', 'E_FAIL 位 */'),
        ('128KB' + rep + '? * 入口参数', '128KB) * 入口参数'),
    ],
    'Drivers\\BSP\\NET\\net_select.c': [
        ('不可' + rep + '? */', '不可写 */'),
        ('可' + rep + '?*/', '可写*/'),
    ],
    'Drivers\\BSP\\SD2506\\sd2506.c': [
        ('BCD ' + rep + '? * 入口参数', 'BCD 码 * 入口参数'),
        ('编码' + rep + '? * 限定条件', '编码) * 限定条件'),
        (rep + '?1AH=80H', '(1AH=80H'),
        ('毫' + rep + '?(raw', '毫秒 (raw'),
        ('SRAM ' + rep + '?2CH~71H', 'SRAM 区 2CH~71H'),
        ('始终' + rep + '?])', '始终为0])'),
        ('CTR2 ' + rep + '?INTAE=1', 'CTR2 的 INTAE=1'),
    ],
    'Drivers\\BSP\\TPAFE5160\\tpafe5160.c': [
        ('ZGT6，并' + rep + '?6位', 'ZGT6，并行 6位'),
        ('驱动' + rep + '?TPAFE5160' + rep + '?', '驱动适配 TPAFE5160'),
        # Fix multiple specific cases
        ('脉冲   ' + rep + '?22ns', '脉冲   约 22ns'),
        ('~6ns)' + rep + '? * 加上', '~6ns)，* 加上'),
        ('已完' + rep + '?GPIO', '已完成 GPIO'),
        # 设置过采样
        ('过采样' + rep + '? * 入口参数', '过采样率 * 入口参数'),
        ('返回值：' + rep + '? * 限定条件：GPIO', '返回值：无 * 限定条件：GPIO'),
        # 下一 - this is tricky, let me look at full context
        ('样本' + rep + '?BUSY', '样本 BUSY'),
        ('下一' + rep + '?BUSY', '下一次 BUSY'),
        # wait conversion
        ('转换完' + rep + '? * 入口参数', '转换完成 * 入口参数'),
        ('转换完' + rep + '? * 返回值', '转换完成 * 返回值'),  # if this pattern exists
        ('转换完成' + rep + '?2 - 超时', '转换完成，2 - 超时'),
        ('下降' + rep + '? */', '下降沿 */'),
        ('空闲' + rep + '?*/', '空闲）*/'),
        ('转换' + rep + '?1 -', '转换中 1 -'),
        # 读取指定通道的转换结果
        ('转换结' + rep + '? * 入口参数', '转换结果 * 入口参数'),
        ('转电压' + rep + '? * 入口参数', '转电压 * 入口参数'),
        ('量程' + rep + '?LSB', '量程，LSB'),
        ('量程' + rep + '?LSB', '量程，LSB'),
        ('引脚' + rep + '?GND', '引脚接 GND'),
        ('RANGE 接 GND ' + rep + '?±5V', 'RANGE 接 GND，±5V'),
        ('转换' + rep + '? * 入口参数', '转换）* 入口参数'),
        ('RD 为低' + rep + '?CS', 'RD 为低，CS'),
        ('通道' + rep + '? uint8_t', '通道数 uint8_t'),
        ('缓冲' + rep + '?      int16_t', '缓冲区      int16_t'),
        ('返回值：' + rep + '? * 限定条件：转换', '返回值：无 * 限定条件：转换'),
        ('主频)' + rep + '? *', '主频)，*'),
        ('数据' + rep + '?DB[15:0]', '数据到 DB[15:0]'),
        ('ISR ' + rep + '?s_buf_b', 'ISR 写 s_buf_b'),
        ('0 = ' + rep + '?B / ' + rep + '?A, 1 = ' + rep + '?A / ' + rep + '?B',
         '0 = 写 B / 读 A, 1 = 写 A / 读 B'),
        ('使能用' + rep + '? * 入口参数', '使能）* 入口参数'),
        ('返回值：' + rep + '? * 限定条件：CubeMX', '返回值：无 * 限定条件：CubeMX'),
        ('仅' + rep + '?irq_disable()', '仅当 irq_disable()'),
        ('返回值：' + rep + '? * 限定条件：已调用', '返回值：无 * 限定条件：已调用'),
        ('启动转换（中断模式' + rep + '? * 入口参数', '启动转换（中断模式）* 入口参数'),
        ('返回值：' + rep + '? * 限定条件：已调用 tpafe5', '返回值：无 * 限定条件：已调用 tpafe5'),
        ('完成后' + rep + '?EXTI 中断', '完成后触发 EXTI 中断'),
        ('数据就绪' + rep + '? - 无新数据', '数据就绪，0 - 无新数据'),
        ('返回值：' + rep + '? * 限定条件：中断', '返回值：无 * 限定条件：中断'),
        ('缓冲' + rep + '? */', '缓冲区 */'),
        ('下降' + rep + '?EXTI', '下降沿 EXTI'),
        ('返回值：' + rep + '? * 限定条件：BUSY', '返回值：无 * 限定条件：BUSY'),
        # Additional tpafe5160 patterns
        ('并' + rep + '?位数据', '并行 16位数据'),
        ('本驱动' + rep + '?AD7606', '本驱动适配 AD7606'),
    ],
}

total_fixed = 0
for fname, file_fixes in fixes.items():
    path = base + fname
    with open(path, 'rb') as f:
        raw = f.read()
    text = raw.decode('utf-8', errors='replace')
    before = text.count(rep)
    
    for needle, replacement in file_fixes:
        while needle in text:
            text = text.replace(needle, replacement)
    
    after = text.count(rep)
    fixed = before - after
    total_fixed += fixed
    print('{}: fixed {} ({} -> {})'.format(fname, fixed, before, after))
    
    with open(path, 'wb') as f:
        f.write(text.encode('utf-8'))

print('\nTotal fixed this pass: {}'.format(total_fixed))

# Show remaining
print('\n=== REMAINING ===')
for fname in fixes:
    path = base + fname
    with open(path, 'rb') as f:
        text = f.read().decode('utf-8', errors='replace')
    remaining = text.count(rep)
    if remaining > 0:
        print('\n--- {} remaining in {} ---'.format(remaining, fname))
        for i, line in enumerate(text.split(chr(10)), 1):
            if rep in line:
                idx = line.index(rep)
                left = line[max(0,idx-30):idx]
                right = line[idx+2:idx+20]
                print('L{}: ...{}[?]{}...'.format(i, left, right))
