Last active
May 12, 2022 04:47
-
-
Save zyr17/ecd6646201b10c27f7124518808e95f5 to your computer and use it in GitHub Desktop.
Genshin Affix Weight by Characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #%% | |
| from pkgutil import get_data | |
| import formulas | |
| import os | |
| import re | |
| # https://bbs.nga.cn/read.php?tid=25843014 | |
| # Modified 优菈 阿贝多 甘雨 八重 魈 丽莎, make final result depends on actual atk.. etc | |
| # https://pan.baidu.com/s/1MClQpeRQPg6onzL2dgZiLw passcode: pxrh | |
| # updated 2.6 | |
| filename = 'Genshin2.5.xlsx' | |
| # elemental recharge weight. As it usually not effect final number, need a special | |
| # weight to evaluate its value. details for function `calc_er_weight` | |
| er_weight = 0.5 | |
| #%% | |
| # consts | |
| sub_attrs = ['hp', 'atk', 'def', 'hpp', 'atkp', 'defp', 'em', 'er', 'cr', 'cd'] | |
| sub_attr_names = [ | |
| ['生命值', '生命'], | |
| ['攻击力', '攻击', '实际攻击'], | |
| ['防御力', '防御'], | |
| ['生命值', '生命'], | |
| ['攻击力', '攻击', '实际攻击'], | |
| ['防御力', '防御'], | |
| ['元素精通', '精通'], | |
| ['充能', '充能效率', '元素充能', '元素充能效率'], | |
| ['暴率', '暴击率'], | |
| ['暴伤', '暴击伤害'] | |
| ] | |
| # characters use Q, but Q is not shown in action | |
| Q_characters = ['云堇', '诺艾尔', '托马', '魈', '雷泽', '空/荧(雷)', '神里绫华', '七七'] | |
| # characters that value is any, which attr is important | |
| any_characters = [ | |
| ['申鹤', 'atk'], | |
| ['云堇', 'def'], | |
| ['五郎', 'er'], | |
| ] | |
| # https://bbs.nga.cn/read.php?tid=24270728 https://bbs.nga.cn/read.php?tid=27497061 | |
| sub_attr_base_one = 0.0389 | |
| sub_attr_base = [7680, 500, 595, 1.5, 1.5, 1.875, 600, 1.66666667, 1, 2] | |
| sub_attr_base = [x * sub_attr_base_one for x in sub_attr_base] | |
| #%% | |
| # functions | |
| def get_data_indices_from_labels(label_line): | |
| # from label line, get indices of different sub_attrs, following with two atk columns | |
| indices = [] | |
| for sub_attr_name in sub_attr_names: | |
| for name in sub_attr_name: | |
| i = -1 | |
| if name in label_line: | |
| i = label_line.index(name) | |
| break | |
| indices.append(i) | |
| for nn in [['数值预估', '伤害预估'], ['角色白值'], ['武器白值']]: | |
| for n in nn: | |
| if n in label_line: | |
| indices.append(label_line.index(n)) | |
| break | |
| return indices | |
| def get_exact_number(label_indices, data_line, solution_line): | |
| # get exact number for one sub_attr | |
| cbase = {} | |
| cbase['atk'] = solution_line[label_indices[-1]] + solution_line[label_indices[-2]] | |
| cbase['hp'] = 0 | |
| cbase['def'] = 0 | |
| for attr in ['hp', 'def']: | |
| if label_indices[sub_attrs.index(attr)] != -1: | |
| # have hp or def, try to get base | |
| data = data_line[label_indices[sub_attrs.index(attr)]] | |
| if data == '': | |
| continue | |
| assert data[0] == '=' # must start with = | |
| while data[0] < '0' or data[0] > '9': | |
| data = data[1:] | |
| cbase[attr] = int(data.split('*')[0].split('+')[0].split('(')[0]) | |
| print(data_line[:4], cbase) | |
| values = [] | |
| for base, name in zip(sub_attr_base, sub_attrs): | |
| if name in ['atkp', 'defp', 'hpp']: | |
| values.append(base * cbase[name[:-1]]) | |
| else: | |
| values.append(base) | |
| return values | |
| def get_improve_percent(excel, label_indices, name, data, solution, up_values): | |
| result_index = label_indices[-3] | |
| def enhance_cr(value, cr = None): | |
| # when critical damage is used in result formula, enhance the result with critical rate | |
| cd_index = label_indices[sub_attrs.index('cd')] | |
| if name[cd_index] in data[result_index]: | |
| print('use critical damage, start enhance') | |
| cd = solution[cd_index] | |
| value /= 1 + cd | |
| cr_index = label_indices[sub_attrs.index('cr')] | |
| if cr is None: | |
| cr = solution[cr_index] | |
| return value * (1 + cr * cd) | |
| return value | |
| current_baseline = enhance_cr(solution[result_index]) | |
| if current_baseline == 'any': | |
| # characters value is any | |
| current_baseline = 0 | |
| for cname, aname in any_characters: | |
| if data[0] == cname: | |
| result_index = label_indices[sub_attrs.index(aname)] | |
| current_baseline = solution[result_index] | |
| break | |
| print('character with any', current_baseline, result_index) | |
| if current_baseline == 0: | |
| current_baseline = 1e-10 | |
| base_dict = dict(zip(name, data)) | |
| improve = [] | |
| for sub, index, value in zip(sub_attrs, label_indices, up_values): | |
| if index == -1 or (sub == 'cd' and '珊瑚宫心海' == solution[0]): | |
| improve.append(0) | |
| continue | |
| # now_dict = base_dict.copy() | |
| # now_dict[name[index]] = solution[index] + value | |
| s_data = solution[index] | |
| if s_data in ['/', 'any', '']: # if any or / or empty, assume is zero | |
| s_data = 0 | |
| res = excel.calculate( | |
| inputs = { | |
| name[index]: s_data + value | |
| }, | |
| outputs = [ name[result_index] ] | |
| ).get(name[result_index]) | |
| try: | |
| res = res.value[0][0] | |
| except: | |
| pass | |
| if sub == 'cr': | |
| res = enhance_cr(res, s_data + value) | |
| else: | |
| res = enhance_cr(res) | |
| imp = (res - current_baseline) / current_baseline | |
| improve.append(imp) | |
| er_index = sub_attrs.index('er') | |
| improve[er_index] = max(improve[er_index], calc_er_weight(label_indices, up_values, solution, improve)) | |
| norm = max(improve) | |
| if norm != 0: | |
| improve = [x / norm for x in improve] | |
| # for name, imp in zip(sub_attr_names, improve): | |
| # print(name[0], imp) | |
| return improve | |
| # Based on er_need_action and main_attr and sub_attr, select characters that | |
| # need elemental recharge. If appear in sub_attr, use number in sub_attr as target, | |
| # else use biggest weight in [hpp, atkp, defp]. Finally, multiply predifined weight. | |
| def calc_er_weight(label_indices, up_values, solution, improvements): | |
| imp = 0 | |
| er_index = label_indices[sub_attrs.index('er')] | |
| if er_index != -1: | |
| imp = up_values[er_index] / solution[er_index] | |
| else: | |
| best = 0 | |
| if 'Q' in ''.join([str(x) for x in solution]) or solution[0] in Q_characters: # if use Q or in whitelist | |
| print('character use Q') | |
| for attr in ['atkp', 'defp', 'hpp']: | |
| i = improvements[sub_attrs.index(attr)] | |
| best = max(best, i) | |
| imp = best | |
| return imp * er_weight | |
| #%% | |
| # read xls | |
| xl_model = formulas.ExcelModel().loads(filename).finish() | |
| # %% | |
| # extract data to arrays | |
| names = [[''] * 26 for _ in range(1000)] | |
| datas = [[''] * 26 for _ in range(1000)] | |
| solutions = [[''] * 26 for _ in range(1000)] | |
| calc_res = dict(xl_model.calculate()) | |
| d = xl_model.to_dict() | |
| for key in d: | |
| if '正表' in key: # only consider main table | |
| columnnum = ord(key.split('!')[-1][0]) - 65 | |
| linenum = int(key.split('!')[-1][1:]) | |
| if linenum > 10: # is data | |
| datas[linenum][columnnum] = d[key] | |
| names[linenum][columnnum] = key | |
| solutions[linenum][columnnum] = calc_res[key].value[0][0] | |
| # %% | |
| # for one line (charactor|weapon|set|mainattr), calculate all improvements | |
| results = {} | |
| for i in range(len(names[:])): | |
| if datas[i][0] == '角色': | |
| label_line = datas[i] | |
| label_indices = get_data_indices_from_labels(label_line) | |
| continue | |
| if datas[i][0] != '': | |
| # real data here | |
| label = '|'.join(datas[i][:4]) | |
| up_values = get_exact_number(label_indices, datas[i], solutions[i]) | |
| # print(label, up_values) | |
| up_percent = get_improve_percent(xl_model, label_indices, names[i], datas[i], solutions[i], up_values) | |
| results[label] = up_percent | |
| #%% | |
| print(results) | |
| # %% | |
| def s_align(s, length): | |
| res = s | |
| minus = 0 | |
| for i in s: | |
| if ord(i) > 128: | |
| minus += 1 | |
| res += ' ' * (length - len(s) - minus) | |
| return res | |
| fl = s_align('名称', 40) | |
| for i in sub_attr_names: | |
| fl += s_align(i[0], 10) | |
| print('-' * 20) | |
| print(fl) | |
| for k in results: | |
| l = s_align(k, 40) | |
| for i in results[k]: | |
| l += '%-10.2f' % i | |
| print(l) | |
| print('-' * 20) | |
| """ | |
| 名称 生命值 攻击力 防御力 生命值 攻击力 防御力 元素精通 充能 暴率 暴伤 | |
| 胡桃|护摩之杖|追忆4|生火暴 0.16 0.14 0.00 0.49 0.29 0.00 1.00 0.00 0.92 0.72 | |
| 胡桃|护摩之杖|追忆4|精火暴 0.20 0.17 0.00 0.62 0.37 0.00 0.68 0.00 1.00 0.78 | |
| 胡桃|匣里灭辰|追忆4|生火暴 0.18 0.20 0.00 0.55 0.33 0.00 0.64 0.00 0.85 1.00 | |
| 胡桃|匣里灭辰|追忆4|精火暴 0.21 0.23 0.00 0.65 0.39 0.00 0.45 0.00 0.85 1.00 | |
| 胡桃|护摩之杖|魔女4|生火暴 0.18 0.15 0.00 0.55 0.32 0.00 0.96 0.00 1.00 0.78 | |
| 胡桃|护摩之杖|魔女4|精火暴 0.21 0.18 0.00 0.64 0.38 0.00 0.62 0.00 1.00 0.78 | |
| 胡桃|匣里灭辰|魔女4|生火暴 0.19 0.21 0.00 0.57 0.35 0.00 0.58 0.00 0.85 1.00 | |
| 胡桃|匣里灭辰|魔女4|精火暴 0.22 0.24 0.00 0.67 0.41 0.00 0.42 0.00 0.85 1.00 | |
| 托马|西风长枪|2旗印2千岩|充生暴 0.48 0.00 0.00 0.98 0.00 0.00 0.00 1.00 0.00 0.00 | |
| 托马|黑缨枪|2旗印2千岩|充生生 0.32 0.00 0.00 0.65 0.00 0.00 0.00 1.00 0.00 0.00 | |
| 宵宫|飞雷之弦振|追忆4|攻火暴 0.00 0.29 0.00 0.00 0.81 0.00 0.00 0.00 1.00 0.94 | |
| 宵宫|弓藏|追忆4|攻火暴 0.00 0.26 0.00 0.00 0.66 0.00 0.00 0.00 0.85 1.00 | |
| 烟绯|四风原典|乐团4|攻火暴 0.00 0.35 0.00 0.00 0.89 0.00 0.93 0.45 0.89 1.00 | |
| 烟绯|流浪乐章|乐团4|攻火暴 0.00 0.38 0.00 0.00 0.85 0.00 0.37 0.43 0.88 1.00 | |
| 可莉|四风原典|魔女4|攻火暴 0.00 0.32 0.00 0.00 0.88 0.00 1.00 0.00 0.87 0.98 | |
| 可莉|流浪乐章|魔女4|攻火暴 0.00 0.35 0.00 0.00 0.87 0.00 0.38 0.00 0.88 1.00 | |
| 迪卢克|狼的末路|魔女4|精火暴 0.00 0.27 0.00 0.00 0.77 0.00 0.62 0.39 0.85 1.00 | |
| 迪卢克|螭骨剑|魔女4|攻火暴 0.00 0.34 0.00 0.00 0.87 0.00 1.00 0.44 0.86 0.93 | |
| 辛焱|无工之剑|2苍白2骑士|攻物暴 0.00 0.20 0.00 0.00 0.51 0.00 0.00 0.25 0.77 1.00 | |
| 辛焱|白影剑|2苍白2骑士|攻物暴 0.00 0.29 0.00 0.00 0.65 0.00 0.00 0.33 0.77 1.00 | |
| 辛焱|祭礼大剑|千岩4|防防防 0.00 0.00 0.40 0.00 0.00 1.00 0.00 0.00 0.00 0.00 | |
| 辛焱|白影剑|千岩4|防防防 0.00 0.00 0.40 0.00 0.00 1.00 0.00 0.00 0.00 0.00 | |
| 安柏|终末嗟叹之诗|宗室4|攻火暴 0.00 0.24 0.00 0.00 0.59 0.00 0.00 0.30 0.77 1.00 | |
| 安柏|阿莫斯之弓|乐团4|攻火暴 0.00 0.23 0.00 0.00 0.57 0.00 0.73 0.00 0.77 1.00 | |
| 香菱|天空之脊|旗印4|充火暴 0.00 0.00 0.00 0.00 0.00 0.00 0.85 0.51 0.80 1.00 | |
| 香菱|天空之脊|旗印4|精火暴 0.00 0.00 0.00 0.00 0.00 0.00 0.56 0.66 0.80 1.00 | |
| 香菱|渔获|旗印4|充火暴 0.00 0.00 0.00 0.00 0.00 0.00 0.86 0.50 0.90 1.00 | |
| 香菱|渔获|旗印4|精火暴 0.00 0.00 0.00 0.00 0.00 0.00 0.57 0.64 0.90 1.00 | |
| 班尼特|风鹰剑|宗室4|充火暴 0.00 0.19 0.00 0.00 0.51 0.00 1.00 0.55 0.77 0.99 | |
| 班尼特|天空之刃|宗室4|充火暴 0.00 0.22 0.00 0.00 0.53 0.00 1.00 0.43 0.77 0.98 | |
| 班尼特|风鹰剑|少女4|充生治 0.39 0.00 0.00 0.94 0.00 0.00 0.00 1.00 0.00 0.00 | |
| 班尼特|天空之刃|少女4|充生治 0.41 0.00 0.00 1.00 0.00 0.00 0.00 0.83 0.00 0.00 | |
| 神里绫人|波乱月白经津|回响4|攻水暴 0.06 0.29 0.00 0.15 0.78 0.00 0.00 0.00 1.00 0.94 | |
| 神里绫人|磐岩结绿|沉沦4|攻水暴 0.13 0.25 0.00 0.34 0.62 0.00 0.00 0.00 1.00 0.83 | |
| 神里绫人|黑剑|回响4|攻水暴 0.06 0.32 0.00 0.17 0.77 0.00 0.00 0.00 1.00 1.00 | |
| 珊瑚宫心海|不灭月华|海染4|生水治 0.38 0.10 0.00 1.00 0.26 0.00 0.00 0.50 0.00 0.00 | |
| 珊瑚宫心海|试做金珀|海染4|生水治 0.38 0.12 0.00 1.00 0.26 0.00 0.00 0.50 0.00 0.00 | |
| 珊瑚宫心海|讨龙英杰谭|千岩4|生生治 0.38 0.00 0.00 1.00 0.00 0.00 0.00 0.00 0.00 0.00 | |
| 珊瑚宫心海|试做金珀|千岩4|生生治 0.38 0.00 0.00 1.00 0.00 0.00 0.00 0.00 0.00 0.00 | |
| 达达利亚|冬极百星|2沉沦2角斗|攻水暴 0.00 0.00 0.00 0.00 0.00 0.00 1.00 0.00 0.77 0.86 | |
| 达达利亚|天空之翼|2沉沦2角斗|攻水暴 0.00 0.25 0.00 0.00 0.73 0.00 1.00 0.36 0.77 0.87 | |
| 达达利亚|弓藏|2沉沦2角斗|攻水暴 0.00 0.25 0.00 0.00 0.60 0.00 1.00 0.30 0.77 0.99 | |
| 行秋|祭礼剑|2沉沦2宗室|攻水暴 0.00 0.34 0.00 0.00 0.67 0.00 0.00 0.61 0.77 1.00 | |
| 行秋|磐岩结绿|旗印4|充水暴 0.07 0.40 0.00 0.15 0.89 0.00 0.00 0.70 0.97 1.00 | |
| 莫娜|流浪乐章|旗印4|攻水暴 0.00 0.32 0.00 0.00 0.76 0.00 1.00 0.30 0.77 0.88 | |
| 莫娜|讨龙英杰谭|宗室4|充水暴 0.00 0.46 0.00 0.00 0.94 0.00 0.00 0.26 0.77 1.00 | |
| 莫娜|试做金珀|宗室4|充水暴 0.00 0.41 0.00 0.00 0.98 0.00 0.00 0.26 0.77 1.00 | |
| 芭芭拉|不灭月华|少女4|生生治 0.52 0.00 0.00 1.00 0.00 0.00 0.00 0.50 0.00 0.00 | |
| 芭芭拉|讨龙英杰谭|少女4|生生治 0.52 0.00 0.00 1.00 0.00 0.00 0.00 0.50 0.00 0.00 | |
| 芭芭拉|试做金珀|少女4|生生治 0.52 0.00 0.00 1.00 0.00 0.00 0.00 0.50 0.00 0.00 | |
| 早柚|狼的末路|翠绿4|精攻治 0.00 0.39 0.00 0.00 1.00 0.00 0.00 0.50 0.00 0.00 | |
| 早柚|西风大剑|翠绿4|精攻治 0.00 0.48 0.00 0.00 1.00 0.00 0.00 0.50 0.00 0.00 | |
| 枫原万叶|苍古自由之誓|翠绿4|精精精 0.00 0.00 0.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 | |
| 枫原万叶|铁蜂刺|翠绿4|精精精 0.00 0.00 0.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 | |
| 魈|和璞鸢|辰砂4|攻风暴 0.00 0.24 0.00 0.00 0.74 0.00 0.00 0.37 0.93 1.00 | |
| 魈|护摩之杖|辰砂4|攻风暴 0.03 0.26 0.00 0.08 0.76 0.00 0.00 0.38 1.00 0.94 | |
| 魈|决斗之枪|辰砂4|攻风暴 0.00 0.30 0.00 0.00 0.72 0.00 0.00 0.36 1.00 0.90 | |
| 温迪|终末嗟叹之诗|翠绿4|精精精 0.00 0.00 0.00 0.00 0.00 0.00 0.73 1.00 0.00 0.00 | |
| 温迪|西风猎弓|翠绿4|精精精 0.00 0.00 0.00 0.00 0.00 0.00 0.94 1.00 0.00 0.00 | |
| 温迪|绝弦|翠绿4|充精精 0.00 0.00 0.00 0.00 0.00 0.00 0.93 1.00 0.00 0.00 | |
| 琴|腐殖之剑|2翠绿2角斗|攻攻治 0.00 0.45 0.00 0.00 1.00 0.00 0.00 0.77 0.00 0.00 | |
| 琴|西风剑|2翠绿2角斗|攻攻治 0.00 0.48 0.00 0.00 1.00 0.00 0.00 0.72 0.00 0.00 | |
| 琴|风鹰剑|2翠绿2角斗|充攻治 0.00 0.37 0.00 0.00 1.00 0.00 0.00 0.64 0.00 0.00 | |
| 砂糖|祭礼残章|翠绿4|充精精 0.00 0.00 0.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 | |
| 砂糖|试做金珀|翠绿4|充精精 0.00 0.00 0.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 | |
| 砂糖|讨龙英杰谭|翠绿4|充精精 0.00 0.00 0.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 | |
| 空/荧(风)|西风剑|翠绿4|精精精 0.00 0.00 0.00 0.00 0.00 0.00 1.00 0.00 0.00 0.00 | |
| 八重神子|神乐之真意|平雷4|攻雷暴 0.00 0.34 0.00 0.00 0.96 0.00 0.50 0.00 1.00 0.94 | |
| 八重神子|天空之卷|平雷4|攻雷暴 0.00 0.25 0.00 0.00 0.75 0.00 0.56 0.00 0.85 1.00 | |
| 八重神子|匣里日月|平雷4|攻雷暴 0.00 0.38 0.00 0.00 0.97 0.00 0.55 0.00 1.00 1.00 | |
| 八重神子|流浪乐章|平雷4|攻雷暴 0.00 0.22 0.00 0.00 0.56 0.00 0.64 0.00 1.00 1.00 | |
| 雷电将军|薙草之稻光|旗印4|充雷暴 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.47 0.77 1.00 | |
| 雷电将军|渔获|旗印4|充攻暴 0.00 0.32 0.00 0.00 0.82 0.00 0.00 0.43 0.90 1.00 | |
| 九条裟罗|天空之翼|旗印4|充雷暴 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.39 1.00 0.98 | |
| 九条裟罗|祭礼弓|旗印4|充雷暴 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.29 0.77 1.00 | |
| 刻晴|雾切之回光|2如雷2角斗|攻雷暴 0.00 0.29 0.00 0.00 0.86 0.00 0.00 0.00 1.00 0.94 | |
| 刻晴|磐岩结绿|2如雷2角斗|攻雷暴 0.00 0.27 0.00 0.00 0.69 0.00 0.00 0.00 1.00 0.76 | |
| 刻晴|匣里龙吟|2如雷2角斗|攻雷暴 0.00 0.28 0.00 0.00 0.70 0.00 0.00 0.00 1.00 1.00 | |
| 雷泽|螭骨剑|角斗4|攻物暴 0.00 0.35 0.00 0.00 0.79 0.00 0.00 0.39 0.88 1.00 | |
| 雷泽|狼的末路|角斗4|攻物暴 0.00 0.22 0.00 0.00 0.55 0.00 0.00 0.27 0.77 1.00 | |
| 菲谢尔|绝弦|2如雷2角斗|攻雷暴 0.00 0.28 0.00 0.00 0.64 0.00 0.00 0.00 0.77 1.00 | |
| 菲谢尔|天空之翼|2如雷2角斗|攻雷暴 0.00 0.27 0.00 0.00 0.75 0.00 0.00 0.00 0.89 1.00 | |
| 丽莎|四风原典|2如雷2角斗|攻雷暴 0.00 0.33 0.00 0.00 0.82 0.00 0.00 0.00 0.89 1.00 | |
| 丽莎|流浪乐章|宗室4|攻雷暴 0.00 0.25 0.00 0.00 0.55 0.00 0.00 0.27 0.88 1.00 | |
| 北斗|狼的末路|旗印4|充雷暴 0.00 0.23 0.00 0.00 0.58 0.00 0.00 0.29 0.77 1.00 | |
| 北斗|螭骨剑|旗印4|充攻暴 0.00 0.32 0.00 0.00 0.70 0.00 0.00 0.32 0.88 1.00 | |
| 空/荧(雷)|西风剑|旗印4|充雷暴 0.00 0.00 0.00 0.00 0.00 0.00 0.00 1.00 0.00 0.00 | |
| 申鹤|息灾|2角斗2追忆|攻攻攻 0.00 0.32 0.00 0.00 1.00 0.00 0.00 0.72 0.00 0.00 | |
| 申鹤|薙草之稻光|2角斗2追忆|攻攻攻 0.00 0.37 0.00 0.00 1.00 0.00 0.00 0.59 0.00 0.00 | |
| 申鹤|天空之脊|2角斗2追忆|攻攻攻 0.00 0.34 0.00 0.00 1.00 0.00 0.00 0.58 0.00 0.00 | |
| 申鹤|西风长枪|2角斗2追忆|攻攻攻 0.00 0.38 0.00 0.00 1.00 0.00 0.00 0.60 0.00 0.00 | |
| 神里绫华|雾切之回光|冰风4|攻冰暴 0.00 0.18 0.00 0.00 0.54 0.00 0.00 0.27 1.00 0.42 | |
| 神里绫华|天目影打刀|冰风4|攻冰暴 0.00 0.19 0.00 0.00 0.46 0.00 0.00 0.23 1.00 0.53 | |
| 优菈|松籁响起之时|苍白4|攻物暴 0.00 0.24 0.00 0.00 0.78 0.00 0.00 0.39 1.00 1.00 | |
| 优菈|狼的末路|苍白4|攻物暴 0.00 0.24 0.00 0.00 0.67 0.00 0.00 0.34 1.00 1.00 | |
| 优菈|螭骨剑|苍白4|攻物暴 0.00 0.35 0.00 0.00 0.89 0.00 0.00 0.45 1.00 0.91 | |
| 甘雨|阿莫斯之弓|冰风4|攻冰暴 0.00 0.14 0.00 0.00 0.40 0.00 0.00 0.00 1.00 0.42 | |
| 甘雨|破魔之弓|冰风4|攻冰暴 0.00 0.16 0.00 0.00 0.38 0.00 0.00 0.00 1.00 0.42 | |
| 甘雨|试做澹月|冰风4|攻冰暴 0.00 0.13 0.00 0.00 0.33 0.00 0.00 0.00 1.00 0.42 | |
| 甘雨|阿莫斯之弓|乐团4|攻冰暴 0.00 0.22 0.00 0.00 0.63 0.00 0.00 0.00 1.00 0.80 | |
| 甘雨|破魔之弓|乐团4|攻冰暴 0.00 0.26 0.00 0.00 0.61 0.00 0.00 0.00 1.00 0.80 | |
| 甘雨|试做澹月|乐团4|攻冰暴 0.00 0.21 0.00 0.00 0.53 0.00 0.00 0.00 1.00 0.80 | |
| 凯亚|西风剑|旗印4|攻冰暴 0.00 0.39 0.00 0.00 0.79 0.00 0.00 0.26 0.93 1.00 | |
| 凯亚|磐岩结绿|旗印4|充冰暴 0.00 0.42 0.00 0.00 0.96 0.00 0.00 0.30 1.00 0.93 | |
| 重云|狼的末路|2冰风2宗室|攻冰暴 0.00 0.23 0.00 0.00 0.57 0.00 0.00 0.29 0.93 1.00 | |
| 重云|螭骨剑|2冰风2宗室|攻冰暴 0.00 0.36 0.00 0.00 0.79 0.00 0.00 0.39 1.00 0.97 | |
| 七七|祭礼剑|海染4|攻攻治 0.00 0.45 0.00 0.00 1.00 0.00 0.00 0.50 0.00 0.00 | |
| 七七|风鹰剑|海染4|攻攻治 0.00 0.35 0.00 0.00 1.00 0.00 0.00 0.50 0.00 0.00 | |
| 七七|笛剑|海染4|攻攻治 0.00 0.42 0.00 0.00 1.00 0.00 0.00 0.50 0.00 0.00 | |
| 迪奥娜|祭礼弓|2少女2千岩|生生生 0.54 0.00 0.00 1.00 0.00 0.00 0.00 0.00 0.00 0.00 | |
| 罗莎莉亚|西风长枪|宗室4|攻冰暴 0.00 0.26 0.00 0.00 0.63 0.00 0.00 0.32 0.59 1.00 | |
| 埃洛伊|西风猎弓|2冰风2角斗|攻冰暴 0.00 0.36 0.00 0.00 0.74 0.00 0.00 0.37 0.93 1.00 | |
| 荒泷一斗|赤角石溃杵|华馆4|防岩暴 0.00 0.13 0.00 0.00 0.30 0.00 0.00 0.15 1.00 0.83 | |
| 荒泷一斗|螭骨剑|华馆4|防岩暴 0.00 0.17 0.00 0.00 0.38 0.00 0.00 0.19 1.00 1.00 | |
| 荒泷一斗|白影剑|华馆4|防岩暴 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.85 1.00 | |
| 五郎|西风猎弓|流放4|充岩暴 0.00 0.00 0.00 0.00 0.00 0.00 0.00 1.00 0.00 0.00 | |
| 阿贝多|辰砂之纺锤|华馆4|防岩暴 0.00 0.00 0.24 0.00 0.00 0.65 0.00 0.00 0.77 1.00 | |
| 阿贝多|辰砂之纺锤|磐岩4|防岩暴 0.00 0.00 0.28 0.00 0.00 0.78 0.00 0.00 0.77 1.00 | |
| 阿贝多|辰砂之纺锤|千岩4|防岩暴 0.00 0.00 0.28 0.00 0.00 0.78 0.00 0.00 0.77 1.00 | |
| 钟离|黑缨枪|千岩4|生生生 0.35 0.00 0.00 1.00 0.00 0.00 0.00 0.00 0.00 0.00 | |
| 钟离|护摩之杖|千岩4|生生生 0.11 0.15 0.00 0.31 0.38 0.00 0.00 0.19 0.78 1.00 | |
| 钟离|护摩之杖|2磐岩2宗室|生岩暴 0.15 0.22 0.00 0.44 0.57 0.00 0.00 0.29 0.89 1.00 | |
| 诺艾尔|赤角石溃杵|华馆4|防岩暴 0.00 0.13 0.00 0.00 0.28 0.00 0.00 0.14 1.00 0.85 | |
| 诺艾尔|螭骨剑|华馆4|防岩暴 0.00 0.15 0.00 0.00 0.32 0.00 0.00 0.16 0.88 1.00 | |
| 诺艾尔|白影剑|华馆4|防岩暴 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.77 1.00 | |
| 凝光|四风原典|2磐岩2角斗|攻岩暴 0.00 0.18 0.00 0.00 0.45 0.00 0.00 0.23 1.00 0.49 | |
| 凝光|尘世之锁|2磐岩2角斗|攻岩暴 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 1.00 0.49 | |
| 凝光|流浪乐章|2磐岩2角斗|攻岩暴 0.00 0.19 0.00 0.00 0.42 0.00 0.00 0.21 1.00 0.44 | |
| 空/荧(岩)|雾切之回光|2磐岩2角斗|攻岩暴0.00 0.27 0.00 0.00 0.72 0.00 0.00 0.36 0.86 1.00 | |
| 空/荧(岩)|磐岩结绿|2磐岩2角斗|攻岩暴 0.00 0.31 0.00 0.00 0.69 0.00 0.00 0.35 0.97 1.00 | |
| 空/荧(岩)|黑剑|2磐岩2角斗|攻岩暴 0.00 0.33 0.00 0.00 0.71 0.00 0.00 0.36 0.88 1.00 | |
| 云堇|薙草之稻光|华馆4|防防防 0.00 0.00 0.43 0.00 0.00 1.00 0.00 0.35 0.00 0.00 | |
| 云堇|天空之脊|华馆4|防防防 0.00 0.00 0.43 0.00 0.00 1.00 0.00 0.37 0.00 0.00 | |
| 云堇|西风长枪|华馆4|防防暴 0.00 0.00 0.43 0.00 0.00 1.00 0.00 0.35 0.00 0.00 | |
| """ | |
| print() | |
| #%% | |
| # show set names | |
| setnames = set() | |
| for key in results: | |
| s = key.split('|')[2] | |
| s = re.split(r'[0-9]', s) | |
| for i in s: | |
| setnames.add(i) | |
| setnames.remove('') | |
| print(setnames) | |
| #%% | |
| # show main names | |
| mainnames = set() | |
| for key in results: | |
| m = key.split('|')[3] | |
| for i in m: | |
| mainnames.add(i) | |
| print(mainnames) | |
| #%% | |
| # get use and not use main for every set | |
| uses = {} | |
| nuses = {} | |
| for key in setnames: | |
| uses[key] = [set(), set(), set()] | |
| nuses[key] = [mainnames.copy(), mainnames.copy(), mainnames.copy()] | |
| for key in results: | |
| s = key.split('|')[2] | |
| s = re.split(r'[0-9]', s) | |
| m = key.split('|')[3] | |
| for i in s: | |
| if len(i) == 0: | |
| continue | |
| for num, j in enumerate(m): | |
| uses[i][num].add(j) | |
| if j in nuses[i][num]: | |
| nuses[i][num].remove(j) | |
| for key in uses: | |
| for num in range(len(uses[key])): | |
| print(key, num, uses[key][num], nuses[key][num]) | |
| #%% | |
| # get max weight from sets | |
| maxw = {} | |
| for s in setnames: | |
| maxw[s] = [0] * 10 | |
| for key in results: | |
| v = results[key] | |
| s = key.split('|')[2] | |
| s = re.split(r'[0-9]', s) | |
| for i in s: | |
| if len(i) == 0: | |
| continue | |
| for j in range(len(v)): | |
| maxw[i][j] = max(v[j], maxw[i][j]) | |
| for s in maxw: | |
| print(s, maxw[s]) | |
| #%% | |
| # get every character possible sets | |
| char2set = {} | |
| for key in results: | |
| c = key.split('|')[0] | |
| s = key.split('|')[2] | |
| s = re.split(r'[0-9]', s) | |
| if c not in char2set: | |
| char2set[c] = set() | |
| for i in s: | |
| char2set[c].add(i) | |
| print(char2set) | |
| #%% | |
| # consts for below | |
| mainname = { | |
| '生': 'hpp', | |
| '攻': 'atkp', | |
| '防': 'defp', | |
| '充': 'er', | |
| '精': 'em', | |
| '暴': 'cr', | |
| '爆': 'cd', | |
| '水': 'hydroDB', | |
| '物': 'physicalDB', | |
| '风': 'anemoDB', | |
| '雷': 'electroDB', | |
| '岩': 'geoDB', | |
| '冰': 'cryoDB', | |
| '火': 'pyroDB', | |
| '治': 'hb', | |
| } | |
| dbname = [ '水', '物', '风', '雷', '岩', '冰', '火' ] | |
| setname = { | |
| '华馆': 'HuskOfOpulentDreams', | |
| '角斗': 'GladiatorsFinale', | |
| '沉沦': 'HeartOfDepth', | |
| '旗印': 'EmblemOfSeveredFate', | |
| '苍白': 'PaleFlame', | |
| '冰风': 'BlizzardStrayer', | |
| '宗室': 'NoblesseOblige', | |
| '海染': 'OceanHuedClam', | |
| '翠绿': 'ViridescentVenerer', | |
| '磐岩': 'ArchaicPetra', | |
| '千岩': 'TenacityOfTheMillelith', | |
| '平雷': 'Thundersoother', | |
| '乐团': 'WanderersTroupe', | |
| '追忆': 'ShimenawasReminiscence', | |
| '骑士': 'BloodstainedChivalry', | |
| '魔女': 'CrimsonWitchOfFlames', | |
| '少女': 'MaidenBeloved', | |
| '如雷': 'ThunderingFury', | |
| # '流放': '', | |
| '流星': 'RetracingBolide', | |
| '渡火': 'Lavawalker', | |
| '辰砂': 'VermillionHereafter', | |
| '余响': 'EchoesOfAnOffering', | |
| } | |
| positions = ["sands", "goblet", "circlet"] | |
| position_names = ["沙", "杯", "头"] | |
| #%% | |
| # count set use time | |
| usetimes = {} | |
| for key in setname: | |
| usetimes[key] = 0 | |
| for key in char2set: | |
| for i in char2set[key]: | |
| if i in usetimes: | |
| usetimes[i] += 1 | |
| print(usetimes) | |
| #%% | |
| # generate filter from weight and main above | |
| import json | |
| used_multiplier = 2 | |
| unused_multiplier = 0 | |
| minkeep = 2 | |
| maxkeep = 5 | |
| flower_minkeep = 10 | |
| flower_maxkeep = 20 | |
| filter_template = '{"main":[],"stars":[],"level":[0,20],"set":[],"position":[],"lock":[],"character":[],"subCount":[],"includeSub":[],"includeSubCount":0,"excludeSub":[],"excludeSubCount":0,"scoreFilters":{"cur":{"value":0,"equation":3},"md":{"value":0,"equation":3},"tot":{"value":0,"equation":3}},"scoreWeight":{"hp":0.3,"atk":0.5,"def":0.3,"hpp":1,"atkp":1,"defp":1,"em":1,"er":1,"cr":1.5,"cd":1.5,"hpprop":0,"defprop":0,"main":0,"set":0},"useRankFilter":true,"rankGroup":{"main":true,"set":true,"position":true},"rankAscend":false,"rankSelectNumber":10,"rankReverseSelect":false,"rankScoreName":"md"}' | |
| results = [{ | |
| 'comment': '先全解锁', | |
| 'lock': 'unlock', | |
| 'showFilter': False, | |
| 'filter': json.loads(filter_template) | |
| }] | |
| results[0]['filter']['useRankFilter'] = False | |
| for sname in setname: | |
| for posnum, [pname, pcommentname] in enumerate(zip(positions, position_names)): | |
| def onefilter(comment, addpos, selectnum, nogroup = False): | |
| filter = json.loads(filter_template) | |
| if nogroup: | |
| filter['rankGroup'] = { | |
| "main":False, | |
| "set":False, | |
| "position":False | |
| } | |
| filter['position'].append(pname) | |
| filter['set'].append(setname[sname]) | |
| if sname in maxw: | |
| for k, v in zip(sub_attrs, maxw[sname]): | |
| filter['scoreWeight'][k] = float('%.2f' % v) | |
| for mname in addpos: | |
| filter['main'].append(mainname[mname]) | |
| if mname == '暴': # critical, also add damage | |
| filter['main'].append('cd') | |
| filter['rankSelectNumber'] = selectnum | |
| return { | |
| 'comment': comment, | |
| 'lock': 'lock', | |
| 'showFilter': False, | |
| 'filter': filter | |
| } | |
| u = set() | |
| nu = mainnames.copy() | |
| nudb = set() | |
| if sname in uses: | |
| u = uses[sname][posnum].copy() | |
| nu = nuses[sname][posnum].copy() | |
| for key in dbname: | |
| if key in nu: | |
| nu.remove(key) | |
| nudb.add(key) | |
| if len(u) > 0: | |
| results.append(onefilter( | |
| '现在用上的' + sname + pcommentname, | |
| u, | |
| min(maxkeep, max(minkeep, usetimes[sname] * used_multiplier)) | |
| )) | |
| if len(nu) > 0: | |
| results.append(onefilter( | |
| '现在用不上的' + sname + pcommentname, | |
| nu, | |
| min(maxkeep, max(minkeep, usetimes[sname] * unused_multiplier)) | |
| )) | |
| """ | |
| if len(nudb) > 0 and pcommentname == '杯': | |
| results.append(onefilter( | |
| '现在用不上的' + sname + '加伤' + pcommentname, | |
| nudb, | |
| min(maxkeep, max(minkeep, usetimes[sname] * unused_multiplier)), | |
| True | |
| )) | |
| """ | |
| filter = json.loads(filter_template) | |
| filter['position'] = ["flower", "plume"] | |
| filter['set'].append(setname[sname]) | |
| if sname in maxw: | |
| for k, v in zip(sub_attrs, maxw[sname]): | |
| filter['scoreWeight'][k] = float('%.2f' % v) | |
| filter['rankSelectNumber'] = min(flower_maxkeep, max(flower_minkeep, usetimes[sname] * used_multiplier)) | |
| results.append({ | |
| 'comment': sname + '花羽', | |
| 'lock': 'lock', | |
| 'showFilter': False, | |
| 'filter': filter | |
| }) | |
| print(json.dumps(results, indent = 2)) | |
| # %% | |
| # lock best out of suit | |
| used_multiplier = 2 | |
| minkeep = 5 | |
| maxkeep = 10 | |
| # get count for every part | |
| mainuses = {} | |
| for key in mainname: | |
| mainuses[key] = [0, 0, 0] | |
| for s in uses: | |
| for snum, mains in enumerate(uses[s]): | |
| for m in mains: | |
| mainuses[m][snum] += 1 | |
| # print(mainuses) | |
| filter_template = '{"main":[],"stars":[],"level":[0,20],"set":[],"position":[],"lock":[],"character":[],"subCount":[],"includeSub":[],"includeSubCount":0,"excludeSub":[],"excludeSubCount":0,"scoreFilters":{"cur":{"value":0,"equation":3},"md":{"value":0,"equation":3},"tot":{"value":0,"equation":3}},"scoreWeight":{"hp":0.3,"atk":0.5,"def":0.3,"hpp":1,"atkp":1,"defp":1,"em":1,"er":1,"cr":1.5,"cd":1.5,"hpprop":0,"defprop":0,"main":0,"set":0},"useRankFilter":true,"rankGroup":{"main":true,"set":true,"position":true},"rankAscend":false,"rankSelectNumber":10,"rankReverseSelect":false,"rankScoreName":"md"}' | |
| # base score, used when no available score | |
| base_score = {"hp":0.3,"atk":0.5,"def":0.3,"hpp":1,"atkp":1,"defp":1,"em":1,"er":1,"cr":1.5,"cd":1.5,"hpprop":0,"defprop":0,"main":0,"set":0} | |
| # simply focus atk | |
| atk_score = {"hp":0,"atk":0.3,"def":0,"hpp":0,"atkp":1,"defp":0,"em":1,"er":1,"cr":2,"cd":2,"hpprop":0,"defprop":0,"main":0,"set":0} | |
| # for non-atk, enumerate hp atk def em, always with er | |
| non_atk_score = {"hp":0,"atk":0,"def":0,"hpp":0,"atkp":0,"defp":0,"em":0,"er":1,"cr":0,"cd":0,"hpprop":0,"defprop":0,"main":0,"set":0} | |
| all_results = [] | |
| atk_main_name = [ '攻', '暴', '水', '物', '风', '雷', '岩', '冰', '火', '精' ] | |
| for mname in mainname: | |
| for pnum, pname in enumerate(position_names): | |
| maddname = mainname[mname] | |
| comment = f'散件{mname}{pname}' | |
| if mname == '爆': | |
| mname = '暴' | |
| if mainuses[mname][pnum] == 0: | |
| continue # not valid position and main | |
| if mname in atk_main_name: | |
| # atk main | |
| filter = json.loads(filter_template) | |
| filter['rankGroup'] = { | |
| "main":False, | |
| "set":False, | |
| "position":False | |
| } | |
| filter['main'].append(maddname) | |
| filter['position'].append(positions[pnum]) | |
| filter['scoreWeight'] = atk_score.copy() | |
| filter['rankSelectNumber'] = min(maxkeep, max(minkeep, mainuses[mname][pnum] * used_multiplier)) | |
| all_results.append({ | |
| 'comment': comment, | |
| 'lock': 'lock', | |
| 'showFilter': False, | |
| 'filter': filter | |
| }) | |
| else: | |
| # other main | |
| for i in ['攻', '防', '生', '精']: | |
| filter = json.loads(filter_template) | |
| filter['rankGroup'] = { | |
| "main":False, | |
| "set":False, | |
| "position":False | |
| } | |
| filter['main'].append(maddname) | |
| filter['position'].append(positions[pnum]) | |
| filter['scoreWeight'] = non_atk_score.copy() | |
| filter['scoreWeight'][mainname[i]] = 1 | |
| if i != '精': | |
| filter['scoreWeight'][mainname[i][:-1]] = 0.5 | |
| filter['rankSelectNumber'] = min(maxkeep, max(minkeep, mainuses[mname][pnum] * used_multiplier)) | |
| all_results.append({ | |
| 'comment': comment + '主' + i, | |
| 'lock': 'lock', | |
| 'showFilter': False, | |
| 'filter': filter | |
| }) | |
| print(json.dumps(all_results, indent = 2)) | |
| #%% | |
| # combine two part | |
| print(json.dumps(results + all_results, indent = 2)) | |
| # %% |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment