# 返回的json文件标识符：
# type：0表示推荐算法返回 1表示兼容性检测返回
# flag：0表示正常返回请求内容 1表示出现错误，为错误报告

import json
import pymysql


class Accessories:
  def __init__(self, name):
    self.name = name
    self.budget = -1
    self.price = -1
    self.link = ''
    self.socket = None
    self.length = None
    self.height = None
    self.size = None
    self.m2Num = None


class AccessoriesList:
  def __init__(self, name):
    self.name = name
    self.budget = -1
    self.price = 0
    self.CPU = Accessories('CPU')
    self.GPU = Accessories('GPU')
    self.case = Accessories('case')
    self.memory = Accessories('memory')
    self.HDD = Accessories('HDD')
    self.SSD = Accessories('SSD')
    self.motherboard = Accessories('motherboard')
    self.powerSupply = Accessories('powerSupply')
    self.CPURadiator = Accessories('CPURadiator')


def parse(questionAnswersData):
  res = {}
  res['version'] = questionAnswersData['version']
  if(questionAnswersData['version'] == 'primary'):
    res['Q1'] = questionAnswersData['Q1']
    res['Q1'][0] = eval(res['Q1'][0])
    res['Q1'][1] = eval(res['Q1'][1])
    res['Q2'] = primaryQuestionDict['Q2'][eval(questionAnswersData['Q2'])]
    res['Q3'] = primaryQuestionDict['Q3'][eval(questionAnswersData['Q3'])]
    res['Q4'] = primaryQuestionDict['Q4'][eval(questionAnswersData['Q4'])]
    res['Q5'] = eval(questionAnswersData['Q5'])
  elif(questionAnswersData['version'] == 'advanced'):
    res['Q1'] = questionAnswersData['Q1']
    res['Q1'][0] = eval(res['Q1'][0])
    res['Q1'][1] = eval(res['Q1'][1])
    res['Q2'] = []
    for i in questionAnswersData['Q2']:
      k = eval(i)
      res['Q2'].append(advancedQuestionDict['Q2'][k])
    res['Q3'] = advancedQuestionDict['Q5'][eval(questionAnswersData['Q3'])]
    res['Q4'] = questionAnswersData['Q4'].split()
    res['Q5'] = advancedQuestionDict['Q5'][eval(questionAnswersData['Q5'])]
    res['Q6'] = questionAnswersData['Q6'].split()
    res['Q7'] = questionAnswersData['Q7'].split()
    res['Q8'] = questionAnswersData['Q8'].split()
    res['Q9'] = questionAnswersData['Q9'].split()
    res['Q10'] = questionAnswersData['Q10'].split()
    res['Q11'] = questionAnswersData['Q11'].split()
    res['Q12'] = questionAnswersData['Q12'].split()
    res['Q13'] = advancedQuestionDict['Q13'][eval(questionAnswersData['Q13'])]
    res['Q14'] = advancedQuestionDict['Q14'][eval(questionAnswersData['Q14'])]
    res['Q15'] = advancedQuestionDict['Q15'][eval(questionAnswersData['Q15'])]
    res['Q16'] = advancedQuestionDict['Q16'][eval(questionAnswersData['Q16'])]
    res['Q17'] = advancedQuestionDict['Q17'][eval(questionAnswersData['Q17'])]
    res['Q18'] = advancedQuestionDict['Q18'][eval(questionAnswersData['Q18'])]
    res['Q19'] = eval(questionAnswersData['Q19'])
    res['Q20'] = advancedQuestionDict['Q20'][eval(questionAnswersData['Q20'])]
    res['Q21'] = advancedQuestionDict['Q21'][eval(questionAnswersData['Q21'])]
  else:
    print('Error: There is no version named', questionAnswersData['version'])
    return None
  return res


def check(questionAnswers):
  errorInf = {'type': 0, 'flag': 1, 'errorList': []}
  if(questionAnswers['Q1'][1] < 1500):
    inf = 'Error： 给出预算上限太低，无法生成配置单'
    errorInf['errorList'].append(inf)

  if(questionAnswers['Q1'][0] > 150000):
    inf = 'Error： 给出预算下限太高，无法生成配置单'
    errorInf['errorList'].append(inf)

  if(questionAnswers['version'] == 'primary'):
    if((questionAnswers['Q5']*100) % 25 != 0):
      inf = 'Error： 给出硬盘容量不是0.25的整数倍，无法生成配置单'
      errorInf['errorList'].append(inf)

  elif(questionAnswers['version'] == 'advanced'):
    # 连接数据库
    db = pymysql.connect("localhost", "root", "08239015",
                         "computer_accessories")
    # 使用cursor()方法创建一个游标对象
    cursor = db.cursor()

    # Q2
    if('无特殊要求' in questionAnswers['Q2'] and len(questionAnswers['Q2']) > 1):
      inf = 'Error： Q2既有高性能要求，又无特殊要求，产生冲突，无法生成配置单'
      errorInf['errorList'].append(inf)

    # Q4
    cursor.execute("SELECT brand FROM motherboard")
    data = cursor.fetchall()
    for brand in questionAnswers['Q4']:
      if((brand.upper(),) not in data):
        inf = 'Error： 数据库中没有%s品牌，无法生成配置单' % brand
        errorInf['errorList'].append(inf)

    # Q6
    cursor.execute("SELECT brand,card_type FROM graphics_card")
    data = cursor.fetchall()
    for brand in questionAnswers['Q6']:
      if((brand.upper(), questionAnswers['Q5'].upper()) not in data):
        inf = 'Error： 数据库中没有%s %s品牌，无法生成配置单' % questionAnswers['Q5'], brand
        errorInf['errorList'].append(inf)

    # Q7
    cursor.execute("SELECT brand FROM memory")
    data = cursor.fetchall()
    # print(data)
    for brand in questionAnswers['Q7']:
      if((brand.upper(),) not in data):
        inf = 'Error： 数据库中没有%s品牌，无法生成配置单' % brand
        errorInf['errorList'].append(inf)

    # Q8
    cursor.execute("SELECT brand FROM ssd")
    data = cursor.fetchall()
    # print(data)
    for brand in questionAnswers['Q8']:
      # print(brand.upper())
      if((brand.upper(),) not in data):
        inf = 'Error： 数据库中没有%s品牌，无法生成配置单' % brand
        errorInf['errorList'].append(inf)

    # Q9
    cursor.execute("SELECT brand FROM hdd")
    data = cursor.fetchall()
    for brand in questionAnswers['Q9']:
      if((brand.upper(),) not in data):
        inf = 'Error： 数据库中没有%s品牌，无法生成配置单' % brand
        errorInf['errorList'].append(inf)

    # Q10
    cursor.execute("SELECT brand FROM computer_case")
    data = cursor.fetchall()
    for brand in questionAnswers['Q10']:
      if((brand.upper(),) not in data):
        inf = 'Error： 数据库中没有%s品牌，无法生成配置单' % brand
        errorInf['errorList'].append(inf)

    # Q11
    cursor.execute("SELECT brand FROM cpu_radiator")
    data = cursor.fetchall()
    for brand in questionAnswers['Q11']:
      if((brand.upper(),) not in data):
        inf = 'Error： 数据库中没有%s品牌，无法生成配置单' % brand
        errorInf['errorList'].append(inf)

    # Q12
    cursor.execute("SELECT brand FROM power_supply")
    data = cursor.fetchall()
    for brand in questionAnswers['Q12']:
      if((brand.upper(),) not in data):
        inf = 'Error： 数据库中没有%s品牌，无法生成配置单' % brand
        errorInf['errorList'].append(inf)

    # Q19
    if((questionAnswers['Q19']*100) % 25 != 0):
      inf = 'Error： 给出硬盘容量不是0.25的整数倍，无法生成配置单'
      errorInf['errorList'].append(inf)

    # 关闭游标和数据库的连接
    cursor.close()
    db.close()

  if(errorInf['errorList'] != []):
    # 返回报错信息
    res = open('result.json', 'w', encoding='utf-8')
    print(errorInf)
    json.dump(errorInf, res, ensure_ascii=False)
    res.close()
    exit(0)


def calculateBudget(listX, CPUPercent, motherboardPercent, memoryPercent, SSDPercent, GPUPercent, casePercent,
                    powerSupplyPercent, CPURadiatorPercent, HDDPercent):
  listX.CPU.budget = round(CPUPercent * listX.budget)
  listX.motherboard.budget = round(motherboardPercent * listX.budget)
  listX.memory.budget = round(memoryPercent * listX.budget)
  listX.SSD.budget = round(SSDPercent * listX.budget)
  listX.GPU.budget = round(GPUPercent * listX.budget)
  listX.case.budget = round(casePercent * listX.budget)
  listX.powerSupply.budget = round(powerSupplyPercent * listX.budget)
  listX.CPURadiator.budget = round(CPURadiatorPercent * listX.budget)
  listX.HDD.budget = round(HDDPercent * listX.budget)
  return listX


def preferParse(preDict, questionAnswers):
  if(questionAnswers['version'] == 'primary'):
    # Q3
    if(questionAnswers['Q3'] == '无光'):
      preDict['CPURadiatorRGB'] = '无'
      preDict['GPURGB'] = '无'
      preDict['memoryVest'] = '马甲条'
    elif(questionAnswers['Q3'] == 'RGB'):
      preDict['CPURadiatorRGB'] = 'RGB'
      preDict['GPURGB'] = '支持RGB'
      preDict['memoryVest'] = 'RGB灯条'
    elif(questionAnswers['Q3'] == 'ARGB'):
      preDict['CPURadiatorRGB'] = 'ARGB'
      preDict['GPURGB'] = '支持RGB'
      preDict['memoryVest'] = 'RGB灯条'

    # Q4
    if(questionAnswers['Q4'] != '无要求'):
      preDict['caseSize'] = questionAnswers['Q4']
      preDict['MBSize'] = questionAnswers['Q4']
      if(preDict['caseSize'] == 'MINI-ITX'):
        preDict['powerSupplySize'] = 'SFX'
      else:
        preDict['powerSupplySize'] = 'ATX'

    # Q5
    if(questionAnswers['Q5'] != None):
      preDict['hardDiskCapacity'] = questionAnswers['Q5']
    else:
      preDict['hardDiskCapacity'] = 0.125

  elif(questionAnswers['version'] == 'advanced'):
    # Q3
    preDict['CPUBrand'] = questionAnswers['Q3']

    # Q4
    brandList = questionAnswers['Q4']
    for brand in brandList:
      preDict['MBBrand'].append(brand)

    # Q5
    preDict['GPUAN'] = questionAnswers['Q5']

    # Q6
    brandList = questionAnswers['Q6']
    for brand in brandList:
      preDict['GPUBrand'].append(brand)

    # Q7
    brandList = questionAnswers['Q7']
    for brand in brandList:
      preDict['memoryBrand'].append(brand)

    # Q8
    brandList = questionAnswers['Q8']
    for brand in brandList:
      preDict['SSDBrand'].append(brand)

    # Q9
    brandList = questionAnswers['Q9']
    for brand in brandList:
      preDict['HDDBrand'].append(brand)

    # Q10
    brandList = questionAnswers['Q10']
    for brand in brandList:
      preDict['caseBrand'].append(brand)

    # Q11
    brandList = questionAnswers['Q11']
    for brand in brandList:
      preDict['CPURadiatorBrand'].append(brand)

    # Q12
    brandList = questionAnswers['Q12']
    for brand in brandList:
      preDict['powerSupplyBrand'].append(brand)

    # Q13
    if(questionAnswers['Q13'] != '无要求'):
      preDict['caseSize'] = questionAnswers['Q13']
      preDict['MBSize'] = questionAnswers['Q13']
      if(preDict['caseSize'] == 'MINI-ITX'):
        preDict['powerSupplySize'] = 'SFX'
      else:
        preDict['powerSupplySize'] = 'ATX'

    # Q14
    preDict['caseTransparent'] = questionAnswers['Q14']

    # Q15
    preDict['CPURadiatorType'] = questionAnswers['Q15']

    # Q16
    preDict['CPURadiatorRGB'] = questionAnswers['Q16']

    # Q17
    preDict['memoryVest'] = questionAnswers['Q17']

    # Q18
    preDict['GPURGB'] = questionAnswers['Q18']

    # Q19
    if(questionAnswers['Q19'] != None):
      preDict['hardDiskCapacity'] = questionAnswers['Q19']
    else:
      preDict['hardDiskCapacity'] = 0.125

    # Q20
    preDict['powerSupplyModule'] = questionAnswers['Q20']

    # Q21
    preDict['memoryCapacity'] = questionAnswers['Q21']

  return preDict


def suggest(listX, preDict):
  # 连接数据库
  db = pymysql.connect("localhost", "root", "08239015", "computer_accessories")
  # 使用cursor()方法创建一个游标对象
  cursor = db.cursor()

  # 推荐CPU
  cursor.execute("SELECT * FROM cpu")
  data = cursor.fetchall()
  itemList = []
  for item in data:
    #print(item[7], preDict['CPUBrand'])
    #print(abs(item[5] - listX.CPU.budget))
    # print('\n--------------------------\n')
    if((item[7] == preDict['CPUBrand'] or preDict['CPUBrand'] == None) and abs(item[5] - listX.CPU.budget) <= 100):
      itemList.append(item)
  #print(itemList == [])
  if(itemList == []):
    minD = 9999999
    for item in data:
      if((item[7] == preDict['CPUBrand'] or preDict['CPUBrand'] == None) and abs(item[5] - listX.CPU.budget) <= minD):
        #print(item[1], item[5], minD, abs(item[5] - listX.GPU.budget), minD > abs(item[5] - listX.GPU.budget))
        if(minD > abs(item[5] - listX.CPU.budget)):
          itemList = []
        minD = abs(item[5] - listX.CPU.budget)
        itemList.append(item)
  # print(listX.CPU.budget)
  # for i in itemList:
    #print(i[1], i[5])
  itemList.sort(key=lambda x: (x[15], x[3]*50 + x[2]), reverse=True)
  # print('------------------------------')
  # for i in itemList:
  #print(i[1], i[5])
  # print('\n---------------------------------\n')
  listX.CPU.name = itemList[0][1]
  listX.CPU.price = itemList[0][5]
  listX.CPU.link = itemList[0][6]
  listX.CPU.socket = itemList[0][12]
  listX.price += listX.CPU.price

  # 推荐主板
  cursor.execute("SELECT * FROM motherboard")
  data = cursor.fetchall()
  itemList = []
  for item in data:
    if((item[7] in preDict['MBBrand'] or preDict['MBBrand'] == []) and (item[9] == preDict['MBSize'] or preDict['MBSize'] == None) and item[11] == listX.CPU.socket and abs(item[5] - listX.motherboard.budget) <= 100):
      itemList.append(item)
    #print(preDict['MBSize'], item[9])
    #print(listX.CPU.socket, item[11])
    #print(abs(item[5] - listX.motherboard.budget))
    # print('\n-------------------------------\n')
  if(itemList == []):
    minD = 9999999
    for item in data:
      if((item[7] in preDict['MBBrand'] or preDict['MBBrand'] == []) and (item[9] == preDict['MBSize'] or preDict['MBSize'] == None) and item[11] == listX.CPU.socket and abs(item[5] - listX.motherboard.budget) <= minD):
        if(minD > abs(item[5] - listX.motherboard.budget)):
          itemList = []
        minD = abs(item[5] - listX.motherboard.budget)
        itemList.append(item)
      #print(preDict['MBSize'], item[9])
      #print(listX.CPU.socket, item[11])
      #print(abs(item[5] - listX.motherboard.budget))
      #print((item[9] == preDict['MBSize'] or preDict['MBSize'] == None) and item[11] == listX.CPU.socket and abs(item[5] - listX.motherboard.budget) < minD)
      # print('\n-------------------------------\n')
  itemList.sort(key=lambda x: x[3]*50 + x[2], reverse=True)
  #print(preDict['MBSize'], item[9])
  listX.motherboard.name = itemList[0][1]
  listX.motherboard.price = itemList[0][5]
  listX.motherboard.link = itemList[0][6]
  listX.motherboard.socket = itemList[0][11]
  listX.motherboard.m2Num = itemList[0][12]
  listX.price += listX.motherboard.price

  # 推荐内存
  cursor.execute("SELECT * FROM memory")
  data = cursor.fetchall()
  itemList = []
  for item in data:
    if((item[11] == preDict['memoryVest'] or preDict['memoryVest'] == None) and (item[9] == preDict['memoryCapacity'] or preDict['memoryCapacity'] == None) and (item[7] in preDict['memoryBrand'] or preDict['memoryBrand'] == []) and item[12] == 'DDR4' and abs(item[5] - listX.memory.budget) <= 50):
      itemList.append(item)
  if(itemList == []):
    minD = 9999999
    for item in data:
      # if(item[7] in preDict['memoryBrand']):
        #print(item[11] == preDict['memoryVest'])
        #print(type(item[9]), type(preDict['memoryCapacity']))
        #print(item[7] in preDict['memoryBrand'])
        #print(item[12] == 'DDR4')
        #print(abs(item[5] - listX.memory.budget))
        # print('\n---------------------------\n')
      if((item[11] == preDict['memoryVest'] or preDict['memoryVest'] == None) and (item[9] == preDict['memoryCapacity'] or preDict['memoryCapacity'] == None) and (item[7] in preDict['memoryBrand'] or preDict['memoryBrand'] == []) and item[12] == 'DDR4' and abs(item[5] - listX.memory.budget) <= minD):
        # print(1111)
        if(minD > abs(item[5] - listX.memory.budget)):
          itemList = []
        minD = abs(item[5] - listX.memory.budget)
        itemList.append(item)
  itemList.sort(key=lambda x: x[3]*50 + x[2], reverse=True)
  listX.memory.name = itemList[0][1]
  listX.memory.price = itemList[0][5]
  listX.memory.link = itemList[0][6]
  listX.price += listX.memory.price

  # 推荐GPU
  cursor.execute("SELECT * FROM graphics_card")
  data = cursor.fetchall()
  itemList = []
  for item in data:
    if((item[10] == preDict['GPURGB'] or preDict['GPURGB'] == None) and (item[7] in preDict['GPUBrand'] or preDict['GPUBrand'] == []) and (item[11] == preDict['GPUAN'] or preDict['GPUAN'] == None) and abs(item[5] - listX.GPU.budget) <= 100):
      itemList.append(item)
  if(itemList == []):
    minD = 9999999
    for item in data:
      if((item[10] == preDict['GPURGB'] or preDict['GPURGB'] == None) and (item[7] in preDict['GPUBrand'] or preDict['GPUBrand'] == []) and (item[11] == preDict['GPUAN'] or preDict['GPUAN'] == None) and abs(item[5] - listX.GPU.budget) <= minD):
        if(minD > abs(item[5] - listX.GPU.budget)):
          itemList = []
        minD = abs(item[5] - listX.GPU.budget)
        itemList.append(item)
  itemList.sort(key=lambda x: (x[12], x[3]*50 + x[2]), reverse=True)
  listX.GPU.name = itemList[0][1]
  listX.GPU.price = itemList[0][5]
  listX.GPU.link = itemList[0][6]
  listX.GPU.length = itemList[0][9]
  listX.price += listX.GPU.price

  # 推荐散热器
  cursor.execute("SELECT * FROM cpu_radiator")
  data = cursor.fetchall()
  itemList = []
  typeDict = {0: '风冷', 120: '水冷', 240: '水冷', 280: '水冷', 360: '水冷'}
  for item in data:
    socket = item[9].split('~')
    if((item[11] == preDict['CPURadiatorRGB'] or preDict['CPURadiatorRGB'] == None) and (item[7] in preDict['CPURadiatorBrand'] or preDict['CPURadiatorBrand'] == []) and (typeDict[item[10]] == preDict['CPURadiatorType'] or preDict['CPURadiatorType'] == None) and listX.CPU.socket in socket and abs(item[5] - listX.CPURadiator.budget) <= 50):
      itemList.append(item)
    '''
        if(item[7] in preDict['CPURadiatorBrand']):
            print(preDict['CPURadiatorRGB'], item[11])
            print(preDict['CPURadiatorRGB'] == item[11])
            print(listX.CPU.socket, socket)
            print(listX.CPU.socket in socket)
            print(item[7], preDict['CPURadiatorBrand'])
            print(item[7] in preDict['CPURadiatorBrand'])
            print(typeDict[item[10]], preDict['CPURadiatorType'])
            print(typeDict[item[10]] == preDict['CPURadiatorType'])
            print(abs(item[5] - listX.CPURadiator.budget))
            print('\n-------------------------------\n')  
        '''
  if(itemList == []):
    minD = 9999999
    for item in data:
      socket = item[9].split('~')
      if((item[11] == preDict['CPURadiatorRGB'] or preDict['CPURadiatorRGB'] == None) and (item[7] in preDict['CPURadiatorBrand'] or preDict['CPURadiatorBrand'] == []) and (typeDict[item[10]] == preDict['CPURadiatorType'] or preDict['CPURadiatorType'] == None) and listX.CPU.socket in socket and abs(item[5] - listX.CPURadiator.budget) <= minD):
        if(minD > abs(item[5] - listX.CPURadiator.budget)):
          itemList = []
        minD = abs(item[5] - listX.CPURadiator.budget)
        itemList.append(item)
  itemList.sort(key=lambda x: x[3]*50 + x[2], reverse=True)
  listX.CPURadiator.name = itemList[0][1]
  listX.CPURadiator.price = itemList[0][5]
  listX.CPURadiator.link = itemList[0][6]
  listX.CPURadiator.socket = listX.CPU.socket
  listX.CPURadiator.height = itemList[0][8]
  listX.CPURadiator.size = itemList[0][10]
  listX.price += listX.CPURadiator.price

  # 推荐硬盘
  cursor.execute("SELECT * FROM ssd")
  data1 = cursor.fetchall()
  cursor.execute("SELECT * FROM hdd")
  data2 = cursor.fetchall()
  itemList = []
  if(listX.HDD.budget == 0):
    for item in data1:
      #print(item[8], listX.motherboard.m2Num)
      #print(item[3], preDict['SSDBrand'])
      #print(item[9], preDict['hardDiskCapacity'])
      #print(abs(item[5] - listX.SSD.budget))
      # print('\n---------------------------\n')
      if(item[8] == 'M.2' and listX.motherboard.m2Num == 0):
        continue
      if((item[7] in preDict['SSDBrand'] or preDict['SSDBrand'] == []) and item[9] == preDict['hardDiskCapacity'] and abs(item[5] - listX.SSD.budget) <= 100):
        itemList.append(item)
    if(itemList == []):
      minD = 9999999
      for item in data1:
        if(item[8] == 'M.2' and listX.motherboard.m2Num == 0):
          continue
        if((item[7] in preDict['SSDBrand'] or preDict['SSDBrand'] == []) and item[9] == preDict['hardDiskCapacity'] and abs(item[5] - listX.SSD.budget) <= minD):
          if(minD > abs(item[5] - listX.SSD.budget)):
            itemList = []
          minD = abs(item[5] - listX.SSD.budget)
          itemList.append(item)
    #print(listX.motherboard.name, listX.motherboard.m2Num)
    itemList.sort(key=lambda x: x[3]*50 + x[2], reverse=True)
    listX.SSD.name = itemList[0][1]
    listX.SSD.price = itemList[0][5]
    listX.SSD.link = itemList[0][6]
    listX.price += listX.SSD.price
  else:
    for ssd in data1:
      for hdd in data2:
        if(ssd[8] == 'M.2' and listX.motherboard.m2Num == 0):
          continue
        if((ssd[9] + hdd[10]) == preDict['hardDiskCapacity'] and (ssd[7] in preDict['SSDBrand'] or preDict['SSDBrand'] == []) and (hdd[7] in preDict['HDDBrand'] or preDict['HDDBrand'] == []) and abs((ssd[5]+hdd[5]) - (listX.SSD.budget+listX.HDD.budget)) <= 100):
          itemList.append((ssd, hdd))
    if(itemList == []):
      minD = 9999999
      for ssd in data1:
        for hdd in data2:
          if((ssd[9] + hdd[10]) == preDict['hardDiskCapacity'] and (ssd[7] in preDict['SSDBrand'] or preDict['SSDBrand'] == []) and (hdd[7] in preDict['HDDBrand'] or preDict['HDDBrand'] == []) and abs((ssd[5]+hdd[5]) - (listX.SSD.budget+listX.HDD.budget)) <= minD):
            if(minD > abs((ssd[5]+hdd[5]) - (listX.SSD.budget+listX.HDD.budget))):
              itemList = []
            minD = abs((ssd[5]+hdd[5]) - (listX.SSD.budget+listX.HDD.budget))
            itemList.append((ssd, hdd))
    itemList.sort(key=lambda x: (x[0][3]+x[1][3]) /
                  2 * 50 + x[0][2] + x[1][2], reverse=True)
    listX.SSD.name = itemList[0][0][1]
    listX.SSD.price = itemList[0][0][5]
    listX.SSD.link = itemList[0][0][6]
    listX.price += listX.SSD.price
    listX.HDD.name = itemList[0][1][1]
    listX.HDD.price = itemList[0][1][5]
    listX.HDD.link = itemList[0][1][6]
    listX.price += listX.HDD.price

  # 推荐电源
  cursor.execute("SELECT * FROM power_supply")
  data = cursor.fetchall()
  itemList = []
  for item in data:
    #print(item[11], preDict['powerSupplyModule'])
    #print(item[10], preDict['powerSupplySize'])
    #print(item[7], preDict['powerSupplyBrand'])
    if((item[11] == preDict['powerSupplyModule'] or preDict['powerSupplyModule'] == None) and (item[10] == preDict['powerSupplySize'] or preDict['powerSupplySize'] == None) and (item[7] in preDict['powerSupplyBrand'] or preDict['powerSupplyBrand'] == []) and abs(item[5] - listX.powerSupply.budget) <= 50):
      itemList.append(item)
  if(itemList == []):
    minD = 9999999
    for item in data:
      if((item[12] == preDict['powerSupplyModule'] or preDict['powerSupplyModule'] == None) and (item[10] == preDict['powerSupplySize'] or preDict['powerSupplySize'] == None) and (item[7] in preDict['powerSupplyBrand'] or preDict['powerSupplyBrand'] == []) and abs(item[5] - listX.powerSupply.budget) <= minD):
        if(minD > abs(item[5] - listX.powerSupply.budget)):
          itemList = []
        minD = abs(item[5] - listX.powerSupply.budget)
        itemList.append(item)
  itemList.sort(key=lambda x: x[3]*50 + x[2], reverse=True)
  listX.powerSupply.name = itemList[0][1]
  listX.powerSupply.price = itemList[0][5]
  listX.powerSupply.link = itemList[0][6]
  listX.powerSupply.size = itemList[0][11]
  listX.price += listX.powerSupply.price

  # 推荐机箱
  cursor.execute("SELECT * FROM computer_case")
  data = cursor.fetchall()
  itemList = []
  # print(listX.case.budget)
  for item in data:
    radiatorSize = item[11].split('~')
    for size in radiatorSize:
      if((item[8] == preDict['caseSize'] or preDict['caseSize'] == None) and (item[7] in preDict['caseBrand'] or preDict['caseBrand'] == []) and (item[12] == preDict['caseTransparent'] or preDict['caseTransparent'] == None) and item[9] >= listX.GPU.length and item[10] >= listX.CPURadiator.height and int(size) >= listX.CPURadiator.size and abs(item[5] - listX.case.budget) <= 100):
        itemList.append(item)
  if(itemList == []):
    # print(listX.CPU.name)
    # print(listX.motherboard.name)
    # print(listX.GPU.name)
    # print(listX.CPURadiator.name)
    minD = 9999999
    for item in data:
      radiatorSize = item[11].split('~')
      for size in radiatorSize:
        if((item[8] == preDict['caseSize'] or preDict['caseSize'] == None) and (item[7] in preDict['caseBrand'] or preDict['caseBrand'] == []) and (item[12] == preDict['caseTransparent'] or preDict['caseTransparent'] == None) and item[9] >= listX.GPU.length and item[10] >= listX.CPURadiator.height and int(size) >= listX.CPURadiator.size and abs(item[5] - listX.case.budget) <= minD):
          if(minD > abs(item[5] - listX.case.budget)):
            itemList = []
          minD = abs(item[5] - listX.case.budget)
          itemList.append(item)
      #print(preDict['caseSize'], item[8])
      #print(listX.GPU.length, item[9])
      #print(listX.CPURadiator.height, item[10])
      #print(listX.CPURadiator.size, size)
      #print(abs(item[5] - listX.case.budget))
      # print('\n-------------------------------\n')
  itemList.sort(key=lambda x: x[3]*50 + x[2], reverse=True)
  listX.case.name = itemList[0][1]
  listX.case.price = itemList[0][5]
  listX.case.link = itemList[0][6]
  listX.price += listX.case.price

  return listX


primaryQuestionDict = {'Q2': ['', '学习、商务办公、轻度娱乐', '3A大作', '网游', '设计'], 'Q3': ['', '无光', 'RGB', 'ARGB'],
                       'Q4': ['', 'E-ATX', 'ATX', 'M-ATX', 'MINI-ITX', '无要求']}
advancedQuestionDict = {'Q2': ['', 'CPU', '显卡', '硬盘', '内存', '主板', '电源', 'CPU散热器', '无特殊要求'], 'Q3': ['', 'INTEL', 'AMD'], 'Q5': ['', 'NVIDIA', 'AMD'],
                        'Q13': ['', 'E-ATX', 'ATX', 'M-ATX', 'MINI-ITX'], 'Q14': ['', 1, 0], 'Q15': ['', '风冷', '水冷'],
                        'Q16': ['', '无', 'RGB', 'ARGB'], 'Q17': ['', '普条', '马甲条', 'RGB灯条'], 'Q18': ['', '无', '支持RGB'],
                        'Q20': ['', '全模组化', '半模组化', '非模组化'], 'Q21': ['', 4, 8, 16, 32, 64, 128]}

questionAnswersFile = open('questionAnswers.json', 'r', encoding='UTF-8')
questionAnswersData = json.load(questionAnswersFile)
questionAnswersFile.close()
# print(questionAnswers)
# 解析问卷数据
questionAnswers = parse(questionAnswersData)
if(questionAnswers == None):
  exit(0)
# 检查问卷是否存在问题
check(questionAnswers)

# 建立各配置单对象
listLow = AccessoriesList('listLow')
listMiddle = AccessoriesList('listMiddle')
listHigh = AccessoriesList('listHigh')
# 初始化各配件预算百分比
CPUPercent = 0.222
GPUPercent = 0.295
motherboardPercent = 0.129
memoryPercent = 0.090
SSDPercent = 0.076
casePercent = 0.038
powerSupplyPercent = 0.057
HDDPercent = 0.058
CPURadiatorPercent = 0.035
# 初始化各Flag
preDict = {'caseSize': None, 'hardDiskCapacity': 0.125, 'CPUBrand': None, 'MBBrand': [], 'GPUAN': None, 'MBSize': None,
           'GPUBrand': [], 'memoryBrand': [], 'SSDBrand': [], 'HDDBrand': [], 'caseBrand': [], 'CPURadiatorBrand': [],
           'powerSupplyBrand': [], 'caseTransparent': None, 'CPURadiatorType': None, 'CPURadiatorRGB': None, 'memoryVest': None,
           'GPURGB': None, 'powerSupplyModule': None, 'memoryCapacity': None, 'powerSupplySize': None}

preDict = preferParse(preDict, questionAnswers)

# 根据初学者问卷计算配件预算并进行推荐
if(questionAnswers['version'] == 'primary'):
  # 根据Q1初始化各配置单预算
  budgetLimit = int(questionAnswers['Q1'][0])
  budgetCap = int(questionAnswers['Q1'][1])
  listLow.budget = budgetLimit
  listMiddle.budget = (budgetLimit + budgetCap) / 2
  listHigh.budget = budgetCap

  # 根据Q2分配各配件预算
  if(questionAnswers['Q2'] == '学习、商务办公、轻度娱乐'):
    CPUPercent = 0.237
    motherboardPercent = 0.139
    memoryPercent = 0.092
    SSDPercent = 0.081
    GPUPercent = 0.259
    casePercent = 0.037
    powerSupplyPercent = 0.058
    CPURadiatorPercent = 0.031
    HDDPercent = 0.066
  elif(questionAnswers['Q2'] == '3A大作'):
    CPUPercent = 0.189
    motherboardPercent = 0.115
    memoryPercent = 0.084
    SSDPercent = 0.081
    GPUPercent = 0.344
    casePercent = 0.043
    powerSupplyPercent = 0.056
    CPURadiatorPercent = 0.042
    HDDPercent = 0.046
  elif(questionAnswers['Q2'] == '网游'):
    CPUPercent = 0.213
    motherboardPercent = 0.124
    memoryPercent = 0.084
    SSDPercent = 0.078
    GPUPercent = 0.316
    casePercent = 0.037
    powerSupplyPercent = 0.060
    CPURadiatorPercent = 0.034
    HDDPercent = 0.054
  elif(questionAnswers['Q2'] == '设计'):
    CPUPercent = 0.245
    motherboardPercent = 0.124
    memoryPercent = 0.095
    SSDPercent = 0.069
    GPUPercent = 0.293
    casePercent = 0.033
    powerSupplyPercent = 0.052
    CPURadiatorPercent = 0.031
    HDDPercent = 0.058

  # 根据硬盘容量需求决定是否使用机械硬盘
  if(questionAnswers['Q5'] == None or questionAnswers['Q5'] <= 1):
    CPUPercent += CPUPercent * HDDPercent
    motherboardPercent += motherboardPercent * HDDPercent
    memoryPercent += memoryPercent * HDDPercent
    SSDPercent += SSDPercent * HDDPercent
    GPUPercent += GPUPercent * HDDPercent
    casePercent += casePercent * HDDPercent
    powerSupplyPercent += powerSupplyPercent * HDDPercent
    CPURadiatorPercent += CPURadiatorPercent * HDDPercent
    HDDPercent = 0

elif(questionAnswers['version'] == 'advanced'):
  # 根据Q1初始化各配置单预算
  budgetLimit = int(questionAnswers['Q1'][0])
  budgetCap = int(questionAnswers['Q1'][1])
  listLow.budget = budgetLimit
  listMiddle.budget = (budgetLimit + budgetCap) / 2
  listHigh.budget = budgetCap

  # 根据Q2调整各配件预算比例
  extraBudget = 0
  if('CPU' in questionAnswers['Q2']):
    extraBudget += CPUPercent * 0.2
    CPUPercent += CPUPercent * 0.2
  if('显卡' in questionAnswers['Q2']):
    extraBudget += GPUPercent * 0.2
    GPUPercent += GPUPercent * 0.2
  if('硬盘' in questionAnswers['Q2']):
    extraBudget += SSDPercent * 0.2
    extraBudget += HDDPercent * 0.2
    SSDPercent += SSDPercent * 0.2
    HDDPercent += HDDPercent * 0.2
  if('内存' in questionAnswers['Q2']):
    extraBudget += memoryPercent * 0.2
    memoryPercent += memoryPercent * 0.2
  if('主板' in questionAnswers['Q2']):
    extraBudget += motherboardPercent * 0.2
    motherboardPercent += motherboardPercent * 0.2
  if('电源' in questionAnswers['Q2']):
    extraBudget += powerSupplyPercent * 0.2
    powerSupplyPercent += powerSupplyPercent * 0.2
  if('CPU散热器' in questionAnswers['Q2']):
    extraBudget += CPURadiatorPercent * 0.2
    CPURadiatorPercent += CPURadiatorPercent * 0.2

  CPUPercent -= 0.222 * extraBudget
  GPUPercent -= 0.295 * extraBudget
  motherboardPercent -= 0.129 * extraBudget
  memoryPercent -= 0.090 * extraBudget
  SSDPercent -= 0.076 * extraBudget
  casePercent -= 0.038 * extraBudget
  powerSupplyPercent -= 0.057 * extraBudget
  HDDPercent -= 0.058 * extraBudget
  CPURadiatorPercent -= 0.035 * extraBudget

  # 根据硬盘容量需求决定是否使用机械硬盘
  if(questionAnswers['Q5'] == None or questionAnswers['Q19'] <= 1):
    CPUPercent += CPUPercent * HDDPercent
    motherboardPercent += motherboardPercent * HDDPercent
    memoryPercent += memoryPercent * HDDPercent
    SSDPercent += SSDPercent * HDDPercent
    GPUPercent += GPUPercent * HDDPercent
    casePercent += casePercent * HDDPercent
    powerSupplyPercent += powerSupplyPercent * HDDPercent
    CPURadiatorPercent += CPURadiatorPercent * HDDPercent
    HDDPercent = 0

listLow = calculateBudget(listLow, CPUPercent, motherboardPercent, memoryPercent, SSDPercent, GPUPercent, casePercent,
                          powerSupplyPercent, CPURadiatorPercent, HDDPercent)
listMiddle = calculateBudget(listMiddle, CPUPercent, motherboardPercent, memoryPercent, SSDPercent, GPUPercent, casePercent,
                             powerSupplyPercent, CPURadiatorPercent, HDDPercent)
listHigh = calculateBudget(listHigh, CPUPercent, motherboardPercent, memoryPercent, SSDPercent, GPUPercent, casePercent,
                           powerSupplyPercent, CPURadiatorPercent, HDDPercent)

suggest(listLow, preDict)
suggest(listMiddle, preDict)
suggest(listHigh, preDict)

# 返回配置单
listLowRes = {'CPU': [listLow.CPU.name, listLow.CPU.link, listLow.CPU.price],
              'motherboard': [listLow.motherboard.name, listLow.motherboard.link, listLow.motherboard.price],
              'memory': [listLow.memory.name, listLow.memory.link, listLow.memory.price],
              'SSD': [listLow.SSD.name, listLow.SSD.link, listLow.SSD.price],
              'GPU': [listLow.GPU.name, listLow.GPU.link, listLow.GPU.price],
              'case': [listLow.case.name, listLow.case.link, listLow.case.price],
              'powerSupply': [listLow.powerSupply.name, listLow.powerSupply.link, listLow.powerSupply.price],
              'CPURadiator': [listLow.CPURadiator.name, listLow.CPURadiator.link, listLow.CPURadiator.price],
              'HDD': [listLow.HDD.name, listLow.HDD.link, listLow.HDD.price],
              'totalPrice': listLow.price}

listMiddleRes = {'CPU': [listMiddle.CPU.name, listMiddle.CPU.link, listMiddle.CPU.price],
                 'motherboard': [listMiddle.motherboard.name, listMiddle.motherboard.link, listMiddle.motherboard.price],
                 'memory': [listMiddle.memory.name, listMiddle.memory.link, listMiddle.memory.price],
                 'SSD': [listMiddle.SSD.name, listMiddle.SSD.link, listMiddle.SSD.price],
                 'GPU': [listMiddle.GPU.name, listMiddle.GPU.link, listMiddle.GPU.price],
                 'case': [listMiddle.case.name, listMiddle.case.link, listMiddle.case.price],
                 'powerSupply': [listMiddle.powerSupply.name, listMiddle.powerSupply.link, listMiddle.powerSupply.price],
                 'CPURadiator': [listMiddle.CPURadiator.name, listMiddle.CPURadiator.link, listMiddle.CPURadiator.price],
                 'HDD': [listMiddle.HDD.name, listMiddle.HDD.link, listMiddle.HDD.price],
                 'totalPrice': listMiddle.price}

listHighRes = {'CPU': [listHigh.CPU.name, listHigh.CPU.link, listHigh.CPU.price],
               'motherboard': [listHigh.motherboard.name, listHigh.motherboard.link, listHigh.motherboard.price],
               'memory': [listHigh.memory.name, listHigh.memory.link, listHigh.memory.price],
               'SSD': [listHigh.SSD.name, listHigh.SSD.link, listHigh.SSD.price],
               'GPU': [listHigh.GPU.name, listHigh.GPU.link, listHigh.GPU.price],
               'case': [listHigh.case.name, listHigh.case.link, listHigh.case.price],
               'powerSupply': [listHigh.powerSupply.name, listHigh.powerSupply.link, listHigh.powerSupply.price],
               'CPURadiator': [listHigh.CPURadiator.name, listHigh.CPURadiator.link, listHigh.CPURadiator.price],
               'HDD': [listHigh.HDD.name, listHigh.HDD.link, listHigh.HDD.price],
               'totalPrice': listHigh.price}

resDict = {'type': 0, 'flag': 0, 'result': [
    listLowRes, listMiddleRes, listHighRes]}
res = open('result.json', 'w', encoding='utf-8')
print('First: ')
print(listLowRes['CPU'])
print(listLowRes['motherboard'])
print(listLowRes['memory'])
print(listLowRes['SSD'])
print(listLowRes['GPU'])
print(listLowRes['case'])
print(listLowRes['powerSupply'])
print(listLowRes['CPURadiator'])
print(listLowRes['HDD'])
print(listLowRes['totalPrice'])
print()
print('Second: ')
print(listMiddleRes['CPU'])
print(listMiddleRes['motherboard'])
print(listMiddleRes['memory'])
print(listMiddleRes['SSD'])
print(listMiddleRes['GPU'])
print(listMiddleRes['case'])
print(listMiddleRes['powerSupply'])
print(listMiddleRes['CPURadiator'])
print(listMiddleRes['HDD'])
print(listMiddleRes['totalPrice'])
print()
print('Third: ')
print(listHighRes['CPU'])
print(listHighRes['motherboard'])
print(listHighRes['memory'])
print(listHighRes['SSD'])
print(listHighRes['GPU'])
print(listHighRes['case'])
print(listHighRes['powerSupply'])
print(listHighRes['CPURadiator'])
print(listHighRes['HDD'])
print(listHighRes['totalPrice'])
print()
print(resDict)
json.dump(resDict, res, ensure_ascii=False)
res.close()
