#!usr/bin/env python
# -*- coding:utf-8 -*-


import pandas as pd
import numpy as np
import re
import xlsxwriter


def brand_washing(filepath,thre=0.5,inner_thre=0.8,a=1,sheet_name=0):
    # filepath:文件路径，thre为两个品牌下型号重合率阈值，inner_thre为两个品牌下某条型号内关键词重合率阈值，a为权重调整，sheet_name为表单名
    df = pd.read_excel(filepath, sheet_name=sheet_name, converters = {'产品编码':str})
    # 处理缺失值
    col1=(df['产品品牌'] != '暂无数据') == ((df['产品品牌'] != '无参数，需补充') == (df['产品品牌'].notnull()))
    col2=(df['产品型号'] != '暂无数据') == ((df['产品型号'] != '无参数，需补充') == (df['产品型号'].notnull()))
    result = df.loc[df.index[col1==col2]]
    # 将df数据格式转为字符串
    for i in result.columns:
        result[i] = result[i].astype(str)

    # 创建一个字典，key是品牌名，values是一个列表，列表元素是集合，集合元素是品牌下产品型号的关键字
    standard_library = dict()
    # 将df按品牌分类，按品牌提取每个型号的关键字，放入字典
    brand_type = result.groupby('产品品牌')
    for brand in brand_type:
        result_unique = brand[1]['产品型号'].unique()  # result_unique此时是array，元素是一个品牌名下的型号
        for j in range(len(result_unique)):
            result_unique[j] = result_unique[j].upper().strip()
        result_unique = pd.DataFrame(result_unique)[0].unique()  # 全部变为大写，将大小写归一,result_unique此时是array

        temp_list = []  # 创建一个临时列表用于收集同一品牌下每个型号提取的关键字集合
        for k in result_unique:
            pre_num = re.search(r'([A-Za-z]{0,4})\W?\d+', k)  # pre_num为数字前的关键字
            if pre_num:
                pre_num = [pre_num.group(1)]
            if not pre_num:
                pre_num = []

            num = re.search(r'(\d+)', k)  # num为数字关键字
            if num:
                num = [num.group(1)]  # 如果连续数字超过1处，我们只提取第一处，这个可能有点问题但目前还不知道怎么办
            if not num:  # 如果没有数字，就比较英文单词
                num = re.findall(r'[A-Za-z]+', k)

            pos_num = re.findall(r'\d+([A-Za-z]+)?\W?([0-9]+)?\W?([A-Za-z]+)?\W?([0-9]+)?\W?([A-Za-z]+)?\W?([0-9]+)?\W?([A-Za-z]+)?',
                                 k)  # pos_num为数字后的关键字
            if pos_num:
                pos_num = list(pos_num[0])
                if '升级版' in k:
                    pos_num += '升级版'
                if '专业版' in k:
                    pos_num += '专业版'
                if '教育版' in k:
                    pos_num += '教育版'
                if '+' in k:
                    pos_num += '+'

            combined = pre_num + num + pos_num  # 将关键字列表合并
            while '' in combined:
                combined.remove('')  # 删除空的元素
            if combined:
                if set(combined) not in temp_list:
                    temp_list.append(set(combined))  # 每一条型号的关键词列表变成一个集合，添加到临时列表中
        standard_library[brand[0]] = temp_list  # 将临时列表添加到字典中对应的品牌名下

    # 第一种筛选方法：通过比对两个品牌下每个型号关键字重合度来判断两个品牌是否相似
    related_brand1 = []  # 用于接收相似的品牌名
    tested_brand = []  # 用于接收已经测试过的品牌名
    for brand_i in standard_library:  # brand_i为品牌名
        for brand_j in standard_library:
            if brand_i != brand_j:  # 相同的品牌名不对比
                if set([brand_i, brand_j]) not in tested_brand:  # 对比过的品牌名不对比
                    accuracy_i = 0  # 准确率，每个品牌一更新
                    accuracy_j = 0
                    related_version=[]
                    for version_i in standard_library[brand_i]:  # version_i为品牌下一个产品型号关键字组成的集合
                        for version_j in standard_library[brand_j]:
                            inner_accuracy_i = 0  # 内部准确率，每个型号集合一更新
                            inner_accuracy_j = 0
                            for word_i in version_i:  # word_i为集合内的一个关键字
                                if word_i in version_j:
                                    inner_accuracy_i += (1 / (len(version_i) + a / len(version_i)))  # a为调整权重参数，默认为1
                                    inner_accuracy_j += (1 / (len(version_i) + a / len(version_j)))
                            count = 0
                            if inner_accuracy_i >= inner_thre:  # 如果两个集合内的关键字重合率达到内阈值，则增加对应准确率
                                accuracy_i += (
                                            1 / (len(standard_library[brand_i]) + a / len(standard_library[brand_i])))
                                count += 1
                            if inner_accuracy_j >= inner_thre:
                                accuracy_j += (
                                            1 / (len(standard_library[brand_i]) + a / len(standard_library[brand_i])))
                                count += 1

                            if count != 0:
                                related_version.append([' '.join(version_i), ' '.join(version_j)])
                                break  # 如果有增加准确率，则代表两个集合已匹配成功，不再继续往下找，换brand_i下一个型号集合匹配
                    if accuracy_i >= thre or accuracy_j >= thre:  # 如果任一准确率达到阈值，在相近品牌列表中增加这两个品牌
                        tempo_list=[]
                        tempo_list.extend([brand_i, brand_j, max(accuracy_i, accuracy_j)])
                        tempo_list.extend(related_version)
                        related_brand1.append(tempo_list)

                tested_brand.append(set([brand_i, brand_j]))  # 测试后，在已测试列表中增加测试过的品牌

    # 第二种方法，对比两个品牌名称的关键字，只要有一个重合，就算作两个品牌相似
    brand_kw = {}  # 用于接收品牌名提取的关键字
    for i in brand_type:
        temp_list1 = re.findall(r'([\u4e00-\u9fa5]+)', i[0].upper())  # 提取汉字
        while '新建品牌' in temp_list1:
            temp_list1.remove('新建品牌')  # 去除‘新建品牌’
        temp_list2 = re.findall(r'[A-Za-z]+\W?[A-Za-z]+', i[0].upper())  # 提取英文单词
        brand_kw[i[0]] = temp_list1 + temp_list2

    related_brand2 = []  # 相似品牌
    tested_brand = []  # 测试过的品牌
    for brand_i in brand_kw:
        for brand_j in brand_kw:
            if brand_i != brand_j:
                if set([brand_i, brand_j]) not in tested_brand:
                    for word_i in brand_kw[brand_i]:
                        if word_i in brand_kw[brand_j]:
                            related_brand2.append([brand_i, brand_j])
                        else:
                            continue
                        break  # 跳过两层循环，只要有一个关键字相同就代表品牌类似
                    tested_brand.append(set([brand_i, brand_j]))

    # 第三种方法，对比品牌名和另一个品牌型号关键字，如果有一个重合，就算作两个品牌相似
    type_kw = {}  # 用于接收品牌型号提取的关键字
    for i in brand_type:
        result_unique = i[1]['产品型号'].unique()  # 品牌型号组成的数组，数组内无重复元素
        for k in range(len(result_unique)):
            result_unique[k]=result_unique[k].upper().strip()
        result_unique = pd.DataFrame(result_unique)[0].unique()
        type_kw[i[0]] = result_unique

    related_brand3 = []  # 相似品牌

    for brand_i in brand_kw:
        for brand_j in type_kw:
            brand_list = []
            word_list = []
            if brand_i != brand_j:
                for word_i in brand_kw[brand_i]:
                    for word_j in type_kw[brand_j]:
                        if word_i in word_j:
                            brand_list.extend([brand_i, brand_j])
                            word_list.append([word_i, word_j])
            if brand_list:
                tempo_list=brand_list[:2]
                tempo_list.extend(word_list)
                related_brand3.append(tempo_list)

    # 写入excel
    workbook = xlsxwriter.Workbook('./brand_filter.xlsx')
    bold_format = workbook.add_format({'bold': True})

    # 第一个worksheet
    worksheet = workbook.add_worksheet(name='Sheet1')
    worksheet.write('A1', '品牌A-1', bold_format)
    worksheet.write('B1', '品牌B-1', bold_format)
    worksheet.write('C1', '品牌-1', bold_format)
    worksheet.write('D1', '品牌A-2', bold_format)
    worksheet.write('E1', '品牌B-2', bold_format)
    worksheet.write('F1', '品牌-2', bold_format)
    worksheet.write('G1', '品牌A-3', bold_format)
    worksheet.write('H1', '品牌B-3', bold_format)
    worksheet.write('I1', '品牌-3', bold_format)
    col = 0
    row = 1
    for list_i in related_brand1:
        for brand_i in range(2):
            worksheet.write_string(row, col, list_i[brand_i])
            col += 1
        row += 1
        col = 0

    col = 3
    row = 1

    for list_i in related_brand2:
        for brand_i in range(2):
            worksheet.write_string(row, col, list_i[brand_i])
            col += 1
        row += 1
        col = 3

    col = 6
    row = 1

    for list_i in related_brand3:
        for brand_i in range(2):
            worksheet.write_string(row, col, list_i[brand_i])
            col += 1
        row += 1
        col = 6

    # 第二个worksheet
    worksheet2 = workbook.add_worksheet(name='Sheet2')
    col = 0
    row = 0
    for list_i in related_brand1:
        for brand_i in list_i[:2]:
            worksheet2.write_string(row, col, brand_i)
            row += 1
        row+=1

    row=0

    for list_i in related_brand1:
        col = 1
        for version_list in list_i[3:]:
            for version_i in version_list:
                worksheet2.write_string(row, col, version_i)
                row += 1
            row -= 2
            col += 1
        row += 3


    col=0
    row_marker=row
    for list_i in related_brand3:
        for brand_i in list_i[:2]:
            worksheet2.write_string(row, col, brand_i)
            row += 1
        row+=1

    row=row_marker

    for list_i in related_brand3:
        col = 1
        for version_list in list_i[2:]:
            for version_i in version_list:
                worksheet2.write_string(row, col, version_i)
                row += 1
            row -= 2
            col += 1
        row += 3



    workbook.close()

if __name__ == '__main__':
    filepath = 'E:\\ZDZC\\激光打印机参数确认.xlsx'
    brand_washing(filepath)

