├── .DS_Store
├── .gitignore
├── .idea
├── TFT.iml
├── misc.xml
├── modules.xml
├── vcs.xml
└── workspace.xml
├── LICENSE
├── README.md
├── config
└── app.yaml
├── data
├── .DS_Store
├── avatar
│ ├── 00Varus.png
│ ├── 01Elise.png
│ ├── 02Morgana.png
│ ├── 03Evelynn.png
│ ├── 04Aatrox.png
│ ├── 05Brand.png
│ ├── 06Swain.png
│ ├── 07Shyvana.png
│ ├── 08Aurelion Sol.png
│ ├── 09Pantheon.png
│ ├── 10Yasuo.png
│ ├── 11Braum.png
│ ├── 12Lissandra.png
│ ├── 13Ashe.png
│ ├── 14Volibear.png
│ ├── 15Sejuani.png
│ ├── 16Anivia.png
│ ├── 17Blitzcrank.png
│ ├── 18Darius.png
│ ├── 19Katarina.png
│ ├── 20Draven.png
│ ├── 21Fiora.png
│ ├── 22Garen.png
│ ├── 23Vayne.png
│ ├── 24Lucian.png
│ ├── 25Leona.png
│ ├── 26Kayle.png
│ ├── 27Shen.png
│ ├── 28Zed.png
│ ├── 29Kennen.png
│ ├── 30Akali.png
│ ├── 31Graves.png
│ ├── 32Pyke.png
│ ├── 33Twist Fate.png
│ ├── 34Gangplank.png
│ ├── 35Miss Fortune.png
│ ├── 36Mordekaiser.png
│ ├── 37Kindred.png
│ ├── 38Karthus.png
│ ├── 39Warwick.png
│ ├── 40Nidalee.png
│ ├── 41Ahri.png
│ ├── 42Rengar.png
│ ├── 43Gnar.png
│ ├── 44Kha'Zix.png
│ ├── 45Kassadin.png
│ ├── 46Rek'Sai.png
│ ├── 47Cho'Gath.png
│ ├── 48Kaisa.png
│ ├── 49Tristana.png
│ ├── 50Lulu.png
│ ├── 51Poppy.png
│ ├── 52Veigar.png
│ ├── 53Camille.png
│ ├── 54jayce.png
│ ├── 55VI.png
│ └── 56Jinx.png
├── champions.json
├── champions_graph.json
├── final_result
│ ├── total_strength
│ │ ├── final_result6.json
│ │ ├── final_result7.json
│ │ ├── final_result8.json
│ │ └── final_result9.json
│ └── trait_num
│ │ ├── final_result6.json
│ │ ├── final_result7.json
│ │ ├── final_result8.json
│ │ └── final_result9.json
├── language.json
├── output
│ ├── total_strength
│ │ ├── champions_comb10.json
│ │ ├── champions_comb3.json
│ │ ├── champions_comb4.json
│ │ ├── champions_comb5.json
│ │ ├── champions_comb6.json
│ │ ├── champions_comb7.json
│ │ ├── champions_comb8.json
│ │ └── champions_comb9.json
│ └── trait_num
│ │ ├── champions_comb10.json
│ │ ├── champions_comb6.json
│ │ ├── champions_comb7.json
│ │ ├── champions_comb8.json
│ │ └── champions_comb9.json
├── trait_graph.png
├── trait_icons
│ ├── Assassin.png
│ ├── Blademaster.png
│ ├── Brawler.png
│ ├── Demon.png
│ ├── Dragon.png
│ ├── Elementalist.png
│ ├── Exile.png
│ ├── Glacial.png
│ ├── Guardian.png
│ ├── Gunslinger.png
│ ├── Hextech.png
│ ├── Imperial.png
│ ├── Knight.png
│ ├── Ninja.png
│ ├── Noble.png
│ ├── Phantom.png
│ ├── Pirate.png
│ ├── Ranger.png
│ ├── Robot.png
│ ├── Shapeshifter.png
│ ├── Sorcerer.png
│ ├── Void.png
│ ├── Wild.png
│ └── Yordle.png
└── traits.json
├── evaluate
└── evaluation.go
├── globals
└── global.go
├── main.go
├── models
├── champions.go
├── metrics.go
└── traits.go
├── python_scripts
├── deduplicate.py
├── download.py
├── graph_visualisation.py
├── scrape.py
├── scrape_icon.py
├── traits.py
├── translate.py
├── visualise_champions.py
└── visualise_trait_graph.py
├── search
├── graph.go
├── search.go
└── traverse.go
├── utils
├── extend.go
├── math.go
└── translate.go
└── visualisation
├── champion_graph.html
└── graph.json
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/.DS_Store
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .idea
3 |
--------------------------------------------------------------------------------
/.idea/TFT.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
168 |
169 |
170 |
171 | https://goproxy.cn,direct
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 韦子扬
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | > 本文希望读者玩过云顶之弈,不懂编程的可以直接拉到最下面去看结论,懂编程的希望你了解递归、分治、图、堆这些基本概念,并掌握Python或者Go语言。
2 | 代码已公开在github上:[https://github.com/weiziyoung/TFT](https://github.com/weiziyoung/TFT) ,转载请注明来源。
3 |
4 | 今天是11月11日,首先恭喜FPX一顿摧枯拉朽横扫G2, 拿下S赛冠军!证明了LPL是世界第一赛区,也让电竞作为一种赛事在这代人心中铭记。本届S赛结束,也就意味着,S8告一段落,S9即将上线。而云顶之弈作为今年刚出的新模式,在上周11月6日也发布了S2元素崛起版本,一时间各种打法也是层出不穷,小编我也是一名忠实的云顶之弈玩家,但目前还没有玩过S2版本,主要想把这篇文章先写好分享给想读的人。
5 |
6 | 其实早在今年暑假刚出这个新模式,大家都还不会玩,还在摸索各种阵容的时候,我就在思考一件事——如何通过编程的手段搜索到6人口、7人口、8人口甚至9人口时凑到的最多的羁绊?这种想法来源于一个惨痛的经历,就是我第一次玩的时候,大概只凑出来了一个3贵族2骑士羁绊,就草草第七名带走了...当时就觉得这个游戏太难了,这么多卡片怎么能全记住?除了英雄之外,还有装备合成也跟英雄联盟差的很远,但玩个两三局,大概就明白:
7 |
8 | 这个游戏想吃鸡有三个核心——**羁绊**、**英雄等级**、**装备**, 三个核心有两个占优势,基本可以达到前四,三个都占优势,就稳定吃鸡了。这里我们主要讨论的就是去搜索**羁绊**,从而在这个维度上不吃亏。而装备这块比较靠脸,所以不做讨论,英雄等级这块其实可以根据每张卡在每个阶段出现的概率来估算出来这个阵容成型的难易程度,但是在本片博客里不做讨论,这里只讨论一个问题,就是**羁绊**。
9 |
10 | # 文章大纲
11 | - 云顶之弈游戏简介
12 | - 基本算法思路
13 | - 准备实验数据
14 | - 排列组合的原理和实现
15 | - 用图降低搜索复杂度
16 | - 评估函数的设计和实现
17 | - 最小堆维护Top 100阵容
18 | - 结果展示
19 | - 分析与总结
20 |
21 | # 云顶之弈游戏简介
22 | 一般读到这里的读者应该都玩过云顶之弈,但为了照顾有些只打匹配排位从不下棋的同学,这里还是简单介绍一下这个游戏机制。
23 | 
24 |
25 | - 方框`1`所在的是小小英雄,就是召唤师啦,好看用的。
26 | - 方框`2`是你目前的队伍,这个队伍可以由不同英雄组成,但是队伍规模取决于你等级的高低。
27 | - 方框`3`是你候选区的英雄,放一些你暂时不想上场的英雄,当然这个区域大多数是用来合成英雄的,3个相同1星英雄可以合成成2星,3个相同2星英雄可以合成为3星。当然我们这里不讨论如何优化英雄等级的话题。
28 | - 方框`4`是发牌员给你发的牌,还有你目前有多少钱,每回合发牌员会给你发5张牌,你需要用金币去购买,这里只需要记住一点,星级越高的英雄越难抽到,并且也越强。
29 | - 方框`5`就是我们的核心——羁绊了,它是根据场上的英雄的种族和职业所确定的,比如目前场上小炮和男枪可以组成一个枪手的buff,这个Buff可以使得枪手在攻击时造成2个目标伤害,而劫的话自己是个忍者,所以可以组成一个忍者buff,它可以提升自己暴击几率和攻击速度。每个羁绊都有自己的效果,同时,羁绊也有自己的等级,比如当你只有2个枪手的时候,你的枪手能够同时造成2个敌人的伤害,而4个枪手的时候,你可以再攻击时同时造成3个目标的伤害;同时羁绊也有范围,有的羁绊只对单个人有效,比如双帝国、三贵族、单忍者,大多数羁绊对同种族的有效,比如狂野、枪手、剑士,少数羁绊对队伍里所有英雄都有效,比如骑士、法师。
30 |
31 | 具体的S1版本英雄羁绊图如下(有一些后期英雄没加上去,比如潘森、卡萨、海克斯):
32 | 
33 |
34 | 总共是56只英雄,大多英雄拥有一个种族,一个职业,船长的职业既是剑士也是枪手,纳尔的种族既是约德尔人也是狂野。一般来说,这个游戏在七人口时阵容成型,这个阶段基本能看出谁胜谁负,所以我们的目的就是选7个英雄,组成羁绊上最强的阵容。
35 |
36 | # 基本算法思路
37 |
38 | 就像之前所说的,我们的目的是在56个英雄里选n个英雄,然后从里面选出羁绊最强的前K个。这句话可以拆分为这三个问题:
39 | 1. 首先,如何让计算机去自动把所有组合的可能性一个不拉地遍历出来?不重复也不漏检?
40 | 2. 其次,给定一个阵容,如何去评判羁绊的强度?
41 | 3. 第三,怎么去保存前K个羁绊最强的结果?
42 |
43 | 对于第一个问题来说,很多编程语言都有combination的拓展库,方便程序员求出一个列表的元素所有的组合可能性。但是这个是个好的方案嘛?真的可行嘛?如果不可行,怎么去优化?
44 |
45 | 对于第二个问题来说,我们在评估一个东西,或者说量化一个东西的时候,应该采用哪些指标?羁绊多是不是意味着羁绊就强?如果不是的话,是否需要引入主观性的一些指标,比如单个羁绊对英雄的增益程度?另外这个羁绊好成型嘛?是不是容易在组建的半路上暴毙?这些都是需要注意的问题。
46 |
47 | 对于第三个问题来说,看起来很容易,但排序真的可行吗?由于我们搜索的结果多达几百万个的阵容组合,全部排序后再取前K个现实嘛?
48 |
49 | # 准备实验数据
50 | 本次主要使用语言为Go,并且用Python做一些脚本辅助我们做一些分析,之所以采用Go来写核心代码,是因为这种上百万轮次的搜索,Go往往比Python能快出一个数量级,同时Go工程化之类的也做的更好一些,语法也不至于像C++和Java那样繁琐。
51 |
52 | 程序 = 算法 + 数据。数据是一切的基石,要实现我们这次的目标,我们至少需要拥有两个数据:英雄数据、羁绊数据。在国外英雄联盟官网上,我们可以找到这个页面:[TFT GAMEPLAY GUIDE](https://na.leagueoflegends.com/en/news/game-updates/gameplay/teamfight-tactics-gameplay-guide?utm_source=web&utm_medium=web&utm_campaign=tft-microsite-2019),接下来只要用Python 的BeautifulSoup包吧页面解析出来就可以了,大概20行代码就可以搞定了,由于思路比较简单,这里就不放代码了,给个链接自己看:[python_scripts/scrape.py](https://github.com/weiziyoung/TFT/blob/master/python_scripts/scrape.py)。
53 |
54 | 如下所示,这里我们需要记录英雄的元数据包括:名字、头像、费用、种族和职业,总共56个英雄,这里不展示了。需要的自己去取:[data/champions.json](https://github.com/weiziyoung/TFT/blob/master/data/champions.json)
55 | ```json
56 | {
57 | "name": "Varus",
58 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Varus.png&resize=64:",
59 | "price": 2,
60 | "origin": ["demon"],
61 | "class": ["ranger"]
62 | },
63 | ```
64 |
65 | 另外是羁绊数据,这个数据可以从英雄数据里面整理出来,同时也要我们自己手填一些数据,以**恶魔**为例:
66 | ```json
67 | {
68 | "name": "demon",
69 | "bonus_num": [2,4,6],
70 | "scope": [2,2,2],
71 | "champions": [
72 | "Varus","Elise","Morgana","Evelynn",
73 | "Aatrox","Brand","Swain"]
74 | },
75 | ```
76 | 恶魔羁绊需要在2只时触发,且在4,6时羁绊进阶,那`bonus_num`就是`[2,4,6]`,而恶魔羁绊无论多少级,都是只有同种族的受益,所以范围序号是`2`,具体范围序号含义我们定义如下
77 | 1. `1`代表只有一个英雄能吃到这个羁绊buff的效果,典型的比如3贵族、2帝国。
78 | 2. `2`代表持有该羁绊的能够吃到这个buff效果,大多数羁绊都属于这个效果,比如恶魔、冰川、狂野、变形者、刺客、枪手、剑士、4帝国等等。
79 | 3. `3`代表队伍全部都可以吃到这个buff,比如6贵族、骑士、法师这些。
80 | 4. `4`代表一个特殊的羁绊范围,就是护卫了,护卫是除了护卫本身,其周围的人都能吃到buff。
81 |
82 | `champions`就是持有这个羁绊的所有英雄了,全部羁绊数据在这里:[data/traits.json](https://github.com/weiziyoung/TFT/blob/master/data/traits.json)。这就是我们现在所能拿到的所有客观数据,不掺杂任何拍脑袋给的主观权重。实际上在评估时,这种数据越多越好,主观性太强的指标例如英雄强度、羁绊强度这种,公说公有理,婆说婆有理,很难有客观的结论,尽量少引入到评价体系中。
83 |
84 | # 排列组合的原理和实现
85 | 现在我们有所有英雄了,作为召唤师,我觉得很有必要把它们一字排开欣赏欣赏...毕竟S2就看不到他们的绝大多数了。
86 | 
87 | 所以我们的任务就是从55个英雄里面挑出8个英雄,让他们的羁绊数量最多。所以这是一个排列组合里的组合问题,可以根据公式求出组合数量:
88 | $$ C_{n}^{m}=\frac{n!}{m!(n-m)!} $$
89 | 其中`n`等于55,`m`等于8,也就是八人口时,需要搜索`231917400`个不重复的可能性。
90 | ## 如何实现组合呢
91 | 最经典的思路就是分治了,看个简单的问题,比如对`[a,b,c,d,e]`求个数为3的所有组合。那么,我们首先会先把`a`取出来,问题简化成了对`[b,c,d,e]`求个数为2的所有组合。其次,我们把`b`取出来,问题简化成了对`[c,d,e]`求个数为1的所有组合,这时候问题就简单了.示意图如下:
92 | 
93 | 红框表示你现在已经选择的字母,红框下面的数字代表需要继续进行组合的元素,到三层结束。
94 | Python实现代码,非常短小精干,需要仔细品味和研读,理解递归、分治的优雅:
95 | ```Python
96 | def combine(data, step, selected_data, target_num):
97 | if len(selected_data) == target_num: # 递归的结束条件:已选择的元素数量等于目标数量
98 | print(selected_data)
99 | return
100 | if step == len(data): # 游标到头了还没找出来,就结束吧
101 | return
102 | selected_data.append(data[step]) # 选择当前元素把她加到已选择的队伍里
103 | combine(data, step + 1, selected_data, target_num) # 将游标推进,进入递归去找下一层
104 | selected_data.pop() # 把选择过的元素踢出去
105 | combine(data, step + 1, selected_data, target_num) #在不选择刚才被踢出去的元素情况下继续递归
106 | if __name__ == '__main__':
107 | data = ['a','b','c','d', 'e']
108 | combine(data, 0, [], 3)
109 | ```
110 | 理解了上面这个代码,换个变量名,加入evaluate函数,就可以用于搜索我们的全羁绊了。
111 | ```Python
112 | def combine(champions, step ,combo, max_num):
113 | if len(combo) == max_num: # 如果队伍到了最大的人口,就进行评估
114 | evaluate(combo)
115 | return
116 | if step == len(combo):
117 | return
118 | combo.append(champions[step]) # 把游标所指定的英雄加到队伍里面去
119 | combine(champions, step + 1, combo, max_num) # 游标往前进,继续抓壮丁
120 | combo.pop() # 把刚才指定的英雄踢出去
121 | combine(champions, step+1, combo, max_num) # 再继续往前进抓壮丁
122 |
123 | def evaluate(combo):
124 | # 这里写给定一个阵容,怎么去评估它的强度,应该返回一个数值,或者是多个维度的评分结构体。
125 | # 往后再议
126 | pass
127 |
128 | def init_champions():
129 | # 这里从json里读数据,代码略
130 | pass
131 |
132 | if __name__ == "__main__":
133 | champions = init_champions() # 把英雄数据导入进去,每个英雄应该是个结构体,或者是个字典。
134 | combine(champions, 0, [], 7)
135 | ```
136 | 跑了一下,自行感受一下Python🐌蜗牛一般的速度吧:
137 | 
138 | 平均每秒遍历`36979`个结点,搜索6人口的最优羁绊竟然要花14分钟,作为一个堆效率有追求的程序员,怎么能够容忍这种事情出现??我只想对这个结果说:
139 | 
140 | 所以接下来就没有Python代码了,同样的算法用Go跑的话,速度是每秒大约20w个结点, 大概是Python的7倍左右,如果用C++来写会更快,但如果让我用C++来写可能要明年你们才能看到我这篇文章了,所以程序员要在开发效率和运行速度中取得一个平衡:
141 | 
142 |
143 | # 用图降低搜索复杂度
144 | ## 穷举法的弊端
145 | 由之前的公式:
146 |
147 | $$ C_{n}^{m}=\frac{n!}{m!(n-m)!} $$
148 |
149 | 我们可以算出,八人口需要搜索`231917400`个结点,用Python搜索大概需要1.7个小时左右,用Golang搜索大概需要20分钟,速度还是很不够看,从语言上已经优化不了了,那就从算法上进行优化。
150 |
151 | 结合这个游戏,仔细思考一下我们是否真的需要对56个英雄都组合一遍呢?这么看不够直观,我举个非常简单的栗子
152 | 
153 | 给定图上的五只英雄:蜘蛛、盖伦、浪人、维鲁斯、豹女、寒冰,选出三个英雄,目标是让他们组成的羁绊数量最大,用大脑去看,那结果一定是“蜘蛛、维鲁斯、寒冰”,但是,我们模拟之前穷举法的过程,首先选出蜘蛛,其次选择第二位的盖伦,如果真的有人会在拿到蜘蛛的情况下去第二位去选择盖伦凑羁绊,大概会让人觉得:
154 | 
155 | ## 基于羁绊的思路
156 | 正常的人拿完蜘蛛,下一步一定是拿维鲁斯或者豹女,拿维鲁斯因为刚好可以凑一个恶魔,维鲁斯又是一个比较强的打工二费卡,何乐而不为?拿豹女是因为后面可能可以凑3换型,能凑出3换型,前期坦度是妥妥的,所以我们在拿到蜘蛛的情况下,不可能去考虑下一步拿盖伦和狼人,在下一步拿到维鲁斯的情况下,去考虑豹女和寒冰,(思考一下为什么要考虑豹女?),这样我们就达到了最多羁绊:双恶魔加双寒冰。综上,我们简化搜索的主要逻辑就是**每次只选择与他能产生羁绊的对象**,基于这个想法,我们的搜索就变成:
157 | 
158 |
159 | 而图就是用来描述每个对象之间关系的一种数据结构,在这里,图用来描述英雄之间的羁绊关系,而图的表示方法有两种:邻接矩阵法和邻接表法,两者的取舍取决于图的稀疏程度。将上面官方给的羁绊-英雄图转个方式就得到了英雄-羁绊邻接矩阵图(57*57的矩阵,有相同羁绊则输出1, 没有则输出0)由图中可以看出,该矩阵为稀疏矩阵,所以我们后面用邻接表法来表示该矩阵):
160 | 
161 | 另外,所有的英雄都和机器人、浪人、忍者有羁绊,因为队伍里只要添上它们任何中的一个,都可以为羁绊数+1,符合我们的优化预期。亚索在这里不是孤儿了。
162 | 
163 |
164 | 那么怎么利用这个信息去优化我们的算法呢?这需要进一步地去理解“组合”搜索究竟做了什么?是否可以用图的方式来进行组合搜索?答案是肯定的,以刚才组合`a,b,c,d,e`选出3个进行组合为例,换个思路来想这个事,实际上他们彼此之间也可以用有向图来表示:
165 | 
166 | 所以之前那个组合示意图,也可以这么理解:
167 | 
168 | 综上所述,对于组合而言,我们只要把每个结点指向起后面的所有结点,然后用普通的图搜索,就可以得到组合的结果。
169 | 而利用羁绊图,我们可以不用把每个结点指向后面的所有结点,相反,我们只要把每个结点指向后面所有能跟当前组合产生羁绊的结点就可以了,注意!不能只考虑和当前结点产生羁绊,而要考虑队伍里所有英雄所拥有的所有结点,否则会漏搜索!我们优化的初衷是,保证搜索结果不变的情况下,减少不必要的搜索,而不能漏搜索。
170 | 因此核心搜索代码如下:
171 | ```go
172 | type Graph map[int][]int
173 |
174 | // GenerateGraph 生成羁绊图
175 | func GenerateGraph(championList models.ChampionList) Graph{
176 | graph := make(Graph)
177 | positionMap := make(map[string]int)
178 | for index, champion := range championList {
179 | positionMap[champion.Name] = index
180 | }
181 | for no, champion := range championList {
182 | // children 排序
183 | children := make([]int, 0, 30)
184 | // 加入相同职业的英雄
185 | classes := champion.Class
186 | for _, class := range classes {
187 | sameClassChampions := globals.TraitDict[class].Champions
188 | for _, champion := range sameClassChampions {
189 | index := positionMap[champion]
190 | if index > no{
191 | children = append(children, index)
192 | }
193 | }
194 | }
195 | // 加入相同种族的英雄
196 | origins := champion.Origin
197 | for _, origin := range origins {
198 | sameOriginChampions := globals.TraitDict[origin].Champions
199 | for _, champion := range sameOriginChampions {
200 | index := positionMap[champion]
201 | if index > no {
202 | children = append(children, index)
203 | }
204 | }
205 | }
206 | // 加入1羁绊的英雄
207 | for _, championName := range globals.OneTraitChampionNameList {
208 | index := positionMap[championName]
209 | if index > no {
210 | children = append(children, index)
211 | }
212 | }
213 | // 对index从小到大排序
214 | sort.Ints(children)
215 | children = utils.Deduplicate(children)
216 | graph[no] = children
217 | }
218 | return graph
219 | }
220 |
221 |
222 | // Traverse 图遍历,
223 | // championList, 英雄列表,固定不变。 graph 羁绊图,也是固定不变。node 为当前的结点, selected 为已选择的英雄, oldChildren是父节点的children
224 | func Traverse(championList models.ChampionList, graph Graph, node int, selected []int, oldChildren []int) {
225 | selected = append(selected, node)
226 | if len(selected) == lim {
227 | combo := make(models.ChampionList, lim)
228 | for index, no := range selected {
229 | unit := championList[no]
230 | combo[index] = unit
231 | }
232 | metric := evaluate.Evaluate(combo)
233 | heap.Push(&Result, metric)
234 |
235 | // 超过最大就pop
236 | if len(Result) == globals.Global.MaximumHeap {
237 | heap.Remove(&Result, 0)
238 | }
239 | return
240 | }
241 | newChildren := graph[node]
242 | children := append(oldChildren, newChildren...)
243 | sort.Ints(children)
244 | children = utils.DeduplicateAndFilter(children, node)
245 | copyChildren := make([]int, len(children), 50)
246 | copy(copyChildren, children)
247 | for _, child := range children {
248 | copySelected := make([]int, len(selected), lim)
249 | copy(copySelected, selected)
250 | Traverse(championList, graph, child, copySelected, copyChildren)
251 | }
252 | }
253 | // TraitBasedGraphSearch 基于羁绊图的图搜索
254 | func TraitBasedGraphSearch(championList models.ChampionList, teamSize int) models.ComboMetricHeap {
255 | graph := GenerateGraph(championList)
256 | lim = teamSize
257 |
258 | heap.Init(&Result)
259 | startPoints := getSlice(0, len(championList)-teamSize + 1)
260 | for _,startNode := range startPoints{
261 | Traverse(championList, graph, startNode, make([]int, 0, teamSize), make([]int, 0, 57))
262 | }
263 | return Result
264 | }
265 | ```
266 | 用这种方法所产生的有向图如下图所示(这里顺手安利一个网络图可视化的js库[antv-G6](https://www.yuque.com/antv/g6/ie7zi7)),大幅度简化了初始的搜索图(自行想象一下所有结点连接所有后续结点密密麻麻的效果图)。
267 |
268 | 
269 | 实际上,我认为这种启发式搜索,有点A star搜索的意思在里面,核心思想就是讲后续children进行排序,将预期离目标结果近的放在前面。这里做的极端了一些,我们把没有产生羁绊的后续结点全部咔嚓了,但实际上这并不会造成漏检(读者可以自己实验一下)
270 |
271 | 最后,比较一下基于羁绊图的结点搜索数量和不基于羁绊图的结点搜索数量,横坐标是人口,纵坐标是结点数量,注意一下纵坐标的跨度,是指数级别的。
272 | 
273 | 所以到这里,这篇博客的核心部分就讲完了,基本思想就是利用现有的知识(英雄之间产生的羁绊)来大幅度简化搜索。
274 |
275 | # 评估函数的设计与实现
276 | 之前我们一直都没有实现评估函数,其实这个评估函数的设计是非常灵活的,也是玩家可以加入自己玩游戏的经验的一部分。这里我们用4个指标来描述阵容强度:
277 | ```go
278 | type ComboMetric struct {
279 | // 英雄组合
280 | Combo []string `json:"combo"`
281 | // 队伍总羁绊数量 = sigma{羁绊} * 羁绊等级
282 | TraitNum int `json:"trait_num"`
283 | // 具体羁绊
284 | TraitDetail map[string]int `json:"trait_detail"`
285 | // 总英雄收益羁绊数量 = sigma{羁绊} 羁绊范围 * 羁绊等级
286 | TotalTraitNum int `json:"total_trait_num"`
287 | // 当前阵容羁绊强度 = sigma{羁绊} 羁绊范围 * 羁绊强度
288 | TotalTraitStrength float32 `json:"total_trait_strength"`
289 | // 当前阵容强度 = sigma{英雄} 英雄强度 * 羁绊强度
290 | TotalStrength float64 `json:"total_strength"`
291 | }
292 | ```
293 |
294 | - 队伍总羁绊数量: 这个是最好理解的,你可以理解为你左侧边栏有多少个羁绊,也就是这个部分,谁不喜欢亮刷刷的一排羁绊呢?看的就很舒服。注意,像6恶魔这种算3个羁绊,而不能只算1个羁绊,6贵族算2个羁绊。这也是我们最开始的motivation,就是寻找怎么能让左边的羁绊灯亮的最多。
295 | 
296 |
297 | - 英雄总收益羁绊数量: 这个也是好理解的,灯亮的多并不代表强,我的经验告诉我,往往吃鸡的阵容,灯亮的往往并不多,有时候甚至就三四个,因此需要引入其他衡量标准。因为不同羁绊有不同的收益范围,所以这个指标就是计算的就是每个羁绊羁绊收益范围乘以它等级的总和。6贵族羁绊之所以挺强,强的不在于它单个属性有多强,而在于它产生了单个buff到群体buff的一个质变,骑士Buff好用也是这个道理,为什么大家都喜欢用骑士过渡,甚至到后面主流吃鸡阵容就包括骑士+枪呢?本质上就是因为骑士能够提供全队伍的收益,而不是只针对本种族的收益。
298 |
299 | - 当前阵容羁绊强度: 这个指标开始就加入人为指标了,也就是其输出取决于玩家对羁绊的理解,这个指标引入了羁绊强度这个概念,这个参数是指:当英雄拥有该羁绊时,能够比不拥有羁绊时强多少倍,比如在这里我设置贵族buff可以让英雄强1.8倍,双恶魔buff能让英雄强1.3倍,龙buff能够直接增强2倍...具体可以看我[data/traits.json](https://github.com/weiziyoung/TFT/blob/master/data/traits.json)文件。
300 |
301 | - 当前阵容整体强度: 这个跟上一版差别就在于考虑了英雄的等级,比如同样是双骑士,你拿个盖伦加诺手,肯定比不上你拿个波比加猪妹。这里为了简化情景,所以设定,2星英雄比1星英雄强1.25倍,3星又比2星强1.25倍...以此类推,最后5星英雄大约比1星英雄强2.5倍,如果你觉得这个数值低了,可以自己在配置文件里面调整。
302 |
303 | 最后我们的evaluate评估函数如下,注意一个问题,就是忍者buff的奇异设定,游戏规定,忍者Buff只在1和4的时触发,在2,3时会熄灭,这不同于其他任何一个羁绊规则,所以要拎出来单独处理一下:
304 | ```go
305 | // Evaluate 评估当前组合的羁绊数量、单位收益羁绊总数、羁绊强度
306 | func Evaluate(combo []models.ChampionDict) models.ComboMetric {
307 | var traitDetail = make(map[string]int)
308 |
309 | comboName := make([]string, 0, len(combo))
310 | traitNum := 0
311 | totalTraitNum := 0
312 | totalTraitStrength := float32(0.0)
313 |
314 | // 初始化英雄强度向量
315 | unitsStrength := make([]float64, len(combo), len(combo))
316 | traitChampionsDict := make(map[string][]int)
317 | for index, unit := range combo {
318 | comboName = append(comboName, unit.Name)
319 | unitStrength := math.Pow(globals.Global.GainLevel, float64(unit.Price-1))
320 | unitsStrength[index] = unitStrength
321 | for _, origin := range unit.Origin {
322 | traitChampionsDict[origin] = append(traitChampionsDict[origin], index)
323 | }
324 | for _, class := range unit.Class {
325 | traitChampionsDict[class] = append(traitChampionsDict[class], index)
326 | }
327 | }
328 |
329 | for trait, champions := range traitChampionsDict {
330 | num := len(champions)
331 | bonusRequirement := globals.TraitDict[trait].BonusNum
332 | var bonusLevel = len(bonusRequirement)
333 | for index, requirement := range bonusRequirement {
334 | if requirement > num {
335 | bonusLevel = index
336 | break
337 | }
338 | }
339 |
340 | // 忍者只有在1只和4只时触发,其他不触发
341 | if trait == "ninja" && 1 < num && num < 4 {
342 | bonusLevel = 0
343 | }
344 | if bonusLevel > 0 {
345 | traitDetail[trait] = bonusRequirement[bonusLevel-1]
346 | bonusScope := globals.TraitDict[trait].Scope[bonusLevel-1]
347 | traitNum += bonusLevel
348 | bonusStrength := globals.TraitDict[trait].Strength[bonusLevel-1]
349 | benefitedNum := 0
350 | switch bonusScope {
351 | case 1:
352 | {
353 | benefitedNum = 1 // 单体Buff,例如 机器人、浪人、三贵族、双帝国
354 | for _, champion := range champions {
355 | unitsStrength[champion] *= float64(bonusStrength)
356 | }
357 | }
358 | case 2:
359 | {
360 | benefitedNum = num // 对同一种族的Buff,大多数羁绊都是这种
361 | for _, champion := range champions {
362 | unitsStrength[champion] *= float64(bonusStrength)
363 | }
364 | }
365 | case 3:
366 | {
367 | benefitedNum = len(combo) // 群体Buff,如骑士、六贵族、四帝国
368 | for index, _ := range unitsStrength {
369 | unitsStrength[index] *= float64(bonusStrength)
370 | }
371 | }
372 | case 4:
373 | {
374 | benefitedNum = len(combo) - 2 // 护卫Buff,比较特殊,除护卫本身外,其他均能吃到buff
375 | for index, _ := range unitsStrength {
376 | isGuard := false
377 | for _, champion := range champions {
378 | if index == champion {
379 | isGuard = true
380 | break
381 | }
382 | }
383 | if !isGuard {
384 | unitsStrength[index] *= float64(bonusStrength)
385 | }
386 | }
387 | }
388 | }
389 | totalTraitNum += bonusLevel * benefitedNum
390 | totalTraitStrength += float32(benefitedNum) * bonusStrength
391 | }
392 | }
393 | metric := models.ComboMetric{
394 | Combo: comboName,
395 | TraitNum: traitNum,
396 | TotalTraitNum: totalTraitNum,
397 | TraitDetail: traitDetail,
398 | TotalTraitStrength: totalTraitStrength,
399 | TotalStrength: utils.Sum(unitsStrength),
400 | }
401 | return metric
402 | }
403 |
404 | ```
405 |
406 | # 最小堆维护Top 100阵容
407 | 之前也提到了,我们每次搜索都是对上千万乃至上亿的叶子结点进行评估,那么如何取出评估结点的前100名呢?我们会想到把结果存起来,然后排序,但这么做可行嘛?
408 |
409 | 想一下我们十人口进行搜索,总共搜索了25844630个结点,假设每存一个metric需要消耗1kb,那最后把它们全部存下来,大约需要24G,记住这是存在内存里的哦,而不是在硬盘上的噢,正常PC的内存条能有16G很不错了吧,更何况还要跑个操作系统在上面,所以这个方案一定是不行的,那有什么更好的方案呢?
410 |
411 | 这就需要联系我上个月写的博客,[详解数据结构——堆](https://zhuanlan.zhihu.com/p/85518062),这篇博文里我们讲到利用堆,我们只需要在内存里开辟堆长度大小的空间即可,比如我们想保留前100个结果,那我们只要开辟100k的内存即可,而每次插入删除,都是`log n`的复杂度,非常快。
412 |
413 | 而保留前K个结果,需要使用的是最小堆,golang里集成了堆的数据结构,只需要重写它的一些接口就可以用了,所以我们的ComboMetric完整版实现就是这样,具体用起来就是每次都push,满了就把堆顶pop出来即可,最后剩下来的就是前K个结果,把它们最后排个序即可:
414 | ```go
415 | package models
416 |
417 | type ComboMetric struct {
418 | // 英雄组合
419 | Combo []string `json:"combo"`
420 | // 队伍总羁绊数量 = sigma{羁绊} * 羁绊等级
421 | TraitNum int `json:"trait_num"`
422 | // 具体羁绊
423 | TraitDetail map[string]int `json:"trait_detail"`
424 | // 总英雄收益羁绊数量 = sigma{羁绊} 羁绊范围 * 羁绊等级
425 | TotalTraitNum int `json:"total_trait_num"`
426 | // 当前阵容羁绊强度 = sigma{羁绊} 羁绊范围 * 羁绊强度
427 | TotalTraitStrength float32 `json:"total_trait_strength"`
428 | // 当前阵容强度 = sigma{英雄} 英雄强度 * 羁绊强度
429 | TotalStrength float64 `json:"total_strength"`
430 | }
431 |
432 | // 定义一个最小堆,保留前K个羁绊
433 | type ComboMetricHeap []ComboMetric
434 |
435 | func (h ComboMetricHeap) Len() int {
436 | return len(h)
437 | }
438 |
439 | func (h ComboMetricHeap) Less(i,j int) bool {
440 | return h[i].TotalStrength < h[j].TotalStrength
441 | }
442 |
443 | func (h ComboMetricHeap) Swap(i, j int) {
444 | h[i], h[j] = h[j], h[i]
445 | }
446 |
447 | func (h *ComboMetricHeap) Push(x interface{}) {
448 | *h = append(*h, x.(ComboMetric))
449 | }
450 |
451 | func (h *ComboMetricHeap) Pop() interface{} {
452 | old := *h
453 | n := len(old)
454 | x := old[n-1]
455 | *h = old[0 : n-1]
456 | return x
457 | }
458 |
459 | ```
460 |
461 | # 结果展示
462 | 这篇博客最最重要的环节要来了,我们需要检验,计算机搜索出来的最强阵容,是否和S1版本的吃鸡阵容是相符的。全部结果文件在[result](https://github.com/weiziyoung/TFT/tree/master/data/final_result)里,读者也可以自己把代码下下来编译跑一下。
463 |
464 | 另外因为很多阵容之间的区别仅仅是换了一个相同羁绊的英雄,或者改了一个小羁绊,所以我们这里对搜索结果做了一个很简单的去重融合,当两个阵容羁绊相似度过高时进行合并,相似度可以用[Jaccard similarity coefficient](https://en.wikipedia.org/wiki/Jaccard_index) 来计算集合之间的相似度,如果相似度大于0.7,则认为属于同一套阵容:
465 | 
466 |
467 | ## 羁绊数最多的阵容
468 | 首先我们看不可能有错的一个指标——羁绊数。直观来说,就是搜索出让左边的羁绊灯亮最多的阵容(这种阵容不一定强)
469 | - 六人口
470 | ```json
471 | {
472 | "combo": ["艾希","狗熊","机器人","劫","螳螂","卡萨"],
473 | "trait_num": 7,
474 | "trait_detail": {
475 | "冰川": 2,
476 | "刺客": 3,
477 | "忍者": 1,
478 | "斗士": 2,
479 | "机器人": 1,
480 | "游侠": 2,
481 | "虚空": 2
482 | },
483 | "total_trait_num": 12,
484 | "total_trait_strength": 16.4,
485 | "total_strength": 19.052499984405003
486 | },
487 | ```
488 | 总羁绊数达到了7个羁绊,注意这是6人口,正常咱们玩自走棋,6人口大约是4个羁绊数左右,毕竟阵容还没成型,但是实际上6人口在不用铲子的情况下最多可以有7个羁绊。
489 |
490 | - 七人口
491 | ```json
492 | {
493 | "combo": [
494 | "狗熊","猪妹","机器人","慎","船长","卡密尔","金克斯"
495 | ],
496 | "trait_num": 7,
497 | "trait_detail": {
498 | "冰川": 2,
499 | "剑士": 3,
500 | "忍者": 1,
501 | "斗士": 2,
502 | "机器人": 1,
503 | "枪手": 2,
504 | "海克斯": 2
505 | },
506 | "total_trait_num": 17,
507 | "total_trait_strength": 22.6,
508 | "total_strength": 21.726248967722068
509 | },
510 | ```
511 | 七人口最大羁绊数竟然还是7。不过不同于6人口只有一种组合能达到7羁绊,七人口前100个中基本都达到了7羁绊。
512 |
513 | - 八人口
514 | ```json
515 | {
516 | "combo": [
517 | "艾希", "狗熊","机器人","劫","螳螂","挖掘机",
518 | "大虫子","卡萨"
519 | ],
520 | "trait_num": 9,
521 | "trait_detail": {
522 | "冰川": 2,
523 | "刺客": 3,
524 | "忍者": 1,
525 | "斗士": 4,
526 | "机器人": 1,
527 | "游侠": 2,
528 | "虚空": 4
529 | },
530 | "total_trait_num": 25,
531 | "total_trait_strength": 24.4,
532 | "total_strength": 27.058749668872913
533 | }
534 | ```
535 | 总共是9个羁绊,看着阵容好像是虚空斗刺哈哈哈,但虚空斗刺没有艾希。这套阵容强度看上去还是可以的。
536 |
537 | - 九人口
538 | ```json
539 | {
540 | "combo": [
541 | "狗熊","猪妹","机器人","盖伦","薇恩","天使","劫","螳螂","卡萨"
542 | ],
543 | "trait_num": 9,
544 | "trait_detail": {
545 | "冰川": 2,
546 | "刺客": 3,
547 | "忍者": 1,
548 | "斗士": 2,
549 | "机器人": 1,
550 | "游侠": 2,
551 | "虚空": 2,
552 | "贵族": 3,
553 | "骑士": 2
554 | },
555 | "total_trait_num": 22,
556 | "total_trait_strength": 28.55,
557 | "total_strength": 31.621585006726214
558 | }
559 | ```
560 | 总之我没看过亮9栈灯的阵容,看样子挺花哨的,但这个阵容其实不妥的。羁绊只是吃鸡的一小部分,实际上更多的需要依靠英雄等级、装备、输出和坦克的组合。
561 |
562 | - 十人口
563 | ```json
564 | {
565 | "combo": [
566 | "维鲁斯","乌鸦","亚索","机器人","诺手","天使",
567 | "阿卡丽","螳螂","挖掘机","卡萨"
568 | ],
569 | "trait_num": 10,
570 | "trait_detail": {
571 | "刺客": 3,"帝国": 2,"忍者": 1,"恶魔": 2,
572 | "斗士": 2,"机器人": 1,"浪人": 1,"游侠": 2,
573 | "虚空": 2,"骑士": 2
574 | },
575 | "total_trait_num": 24,
576 | "total_trait_strength": 31,
577 | "total_strength": 37.67076561712962
578 | }
579 | ```
580 | 亮了10栈灯,这种阵容基本看看就好,不可能成型并且吃鸡的,因为这是个有5个5费卡的阵容。
581 |
582 | ## 强度最高的阵容
583 | 正如之前说的,羁绊多阵容并不一定强,所以一定要结合英雄等级、羁绊强度、羁绊范围这些来算,这里英雄等级的增益和羁绊强度都是具有主观判断在里面的,而且算上这些指标实际上也是不够的,看下计算出的阵容就知道了:
584 |
585 | - 六人口
586 | ```json
587 | {
588 | "combo": [
589 | "潘森","布隆","丽桑卓","狗熊","冰鸟","凯南"
590 | ],
591 | "trait_num": 5,
592 | "trait_detail": {
593 | "元素师": 3,
594 | "冰川": 4,
595 | "忍者": 1,
596 | "护卫": 2
597 | },
598 | "total_trait_num": 14,
599 | "total_trait_strength": 15.2,
600 | "total_strength": 30.272461525164545
601 | },
602 | ```
603 | 这看上去是一个冰川元素阵容,游戏刚出的时候,这套阵容还是很容易吃鸡的,主要就是利用丽桑卓和冰鸟都是冰川+元素,导致这套阵容又有控制又有坦度,在以前谁都不会玩这个游戏的年代很容易吃鸡,小编我第一次吃鸡用的就是冰川元素流。但冰川元素逐渐没落了,原因就是后来大家都会玩这个游戏了,导致游戏节奏加快,而这个阵容一个最大的缺点就是成型有点困难,猪妹和冰鸟都不是那么容易抽到的,前期靠布隆一个坦度点是肯定不够的。
604 |
605 | - 七人口
606 | ```json
607 | {
608 | "combo": [
609 | "莫甘娜","龙王","潘森","日女","天使","铁男","死歌"
610 | ],
611 | "trait_num": 5,
612 | "trait_detail": {
613 | "幽灵": 2,"护卫": 2,"法师": 3,"骑士": 2,"龙": 2
614 | },
615 | "total_trait_num": 22,
616 | "total_trait_strength": 29.9,
617 | "total_strength": 40.17980836913922
618 | },
619 | ```
620 | 这个看上去是护卫龙,但又不太像,因为护卫龙好像没有人配法师的,但这不是最重要的,最重要的是,这套阵容太不容易成型了!!因为我们的评价指标里没有考虑羁绊的成型难易度,导致它更偏好等级高的英雄,强度看上去还可以,有输出有坦克,但有谁7人口能凑出来3个五星,2个四星呢?
621 |
622 | - 八人口
623 | ```json
624 | {
625 | "combo": [
626 | "龙王","潘森","布隆","丽桑卓","冰鸟",
627 | "凯南","露露","小法"
628 | ],
629 | "trait_num": 7,
630 | "trait_detail": {
631 | "元素师": 3,"冰川": 2,"忍者": 1,
632 | "护卫": 2,"法师": 3,"约德尔": 3,
633 | "龙": 2
634 | },
635 | "total_trait_num": 24,
636 | "total_trait_strength": 34.100002,
637 | "total_strength": 50.979002334643155
638 | }
639 | ```
640 | 跟上面有点像(其实我不太清楚为什么七八人口都是护卫龙),这套阵容其实是缺乏坦度的hhh还不容易成型。所以我们的评估指标还是有问题哈哈哈,看到这套阵容人傻了。
641 |
642 | - 九人口
643 | ```json
644 | {
645 | "combo": [
646 | "潘森","亚索","剑姬","盖伦",
647 | "薇恩","卢锡安","日女","天使","船长"
648 | ],
649 | "trait_num": 7,
650 | "trait_detail": {
651 | "剑士": 3,"护卫": 2,"枪手": 2,
652 | "浪人": 1,"贵族": 6,"骑士": 2
653 | },
654 | "total_trait_num": 47,
655 | "total_trait_strength": 54.249996,
656 | "total_strength": 61.73055001568699
657 | }
658 | ```
659 | 这套阵容我还是用过的,能不能吃鸡要看装备,亚索能2星并且吃到装备基本能吃鸡,吃不到装备就很缺乏输出,据说也可以把装备给船长养船长这个点,不过没试过。九人口贵族崛起大概是因为贵族的全范围buff比较给力。
660 |
661 | # 分析与总结
662 |
663 | ## 贡献
664 | 直到云顶之弈S1结束,网上并没有一篇用图搜索来组建羁绊阵容的文章,这篇文章就当是弥补这一块的空白吧,它从另一个角度去为我们推荐了阵容。核心思想就是利用英雄之间的相互羁绊来简化暴力搜索。
665 |
666 | ## 缺陷
667 |
668 | 实际上我觉得在评估阵容强度的时候,模型还是过于粗糙的,具体表现如下:
669 |
670 | 1. **首先忽视了坦度和输出的配合这个维度**。导致有些推荐阵容全是坦克没有输出,有些阵容只有输出没有坦克。
671 |
672 |
673 | 2. **其次忽视了羁绊之间的克制关系**。可以看到七八人口的时候,计算出来的都是以护卫龙为核心的阵容,因为护卫羁绊提供的收益范围很大,但前提条件是你把英雄都集中放护卫周围,但这种方法实际上是被海克斯完克的,所以在实际时间上,护卫buff的收益并没有这里计算中的那么大。
674 |
675 | 3. **忽略了阵过渡的平滑程度**。这是这里存在的最大问题,由于我们在评价阵容的时候,给高等级英雄倾向了一些权重,导致阵容中会有数量较多的高费英雄,实际上不考虑阵容成型难易程度的推荐就是在耍流氓。比如潘森刚出来的时候,很多人推荐贵族护卫龙,实际应用上效果并不好。
676 |
677 | 4. **没有考虑英雄升星的难易程度**。这个实际上跟上面是一种问题,我在搜索结果里找赌刺的阵容,直接被排名拍到了40多名,但赌刺绝对是6人口的T1阵容,这里面的原因就是刺客的卡费普遍是低的,导致在这套算法里赚不到便宜,但其实低费卡更容易到三星,而三星低费卡的强度是高于高费卡的,尤其是像三星劫这样的英雄。
678 | 
679 |
680 | 5. **没有考虑金铲铲**。因为简化问题,这里没有考虑金铲铲,如果考虑金铲铲的话,搜索空间将会变得极其庞大,相当于为每个英雄都给配剑士、刺客、骑士、冰川、约德尔、恶魔这些羁绊。这些加上去以后,复杂度也就跟全搜索差不多了。
681 |
682 | ## 踩坑记录
683 |
684 | 1. Golang append函数,函数原型如下:
685 | ```go
686 | func append(slice []Type, elems ...Type) []Type
687 | ```
688 | 从原型上看是传入一个切片,和若干需要加入的元素,返回一个切片。但实际上传入的slice切片在运行的过程中会被修改,返回的那个切片实际上就是你传入的slice切片。所以在使用golang里面的append函数的时候,记得把接受变量设置成你传入的第一个slice变量,或者使用前对slice进行copy。
689 |
690 | 2. 保留前K大个数实际上要用小顶堆,而不是想当然地使用大顶堆。
691 |
692 | 3. 在考虑当前英雄的后续结点的时候,不能只考虑当前英雄的羁绊,而要考虑队伍里所有英雄的羁绊,否则会漏检。
--------------------------------------------------------------------------------
/config/app.yaml:
--------------------------------------------------------------------------------
1 | maximum_heap : 256
2 | gain_level : 1.25
3 | evaluation: "trait_num"
4 | trait_path: "data/traits.json"
5 | champion_path: "data/champions.json"
6 | language_path: "data/language.json"
7 | output_path: "data/output/trait_num/"
--------------------------------------------------------------------------------
/data/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/.DS_Store
--------------------------------------------------------------------------------
/data/avatar/00Varus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/00Varus.png
--------------------------------------------------------------------------------
/data/avatar/01Elise.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/01Elise.png
--------------------------------------------------------------------------------
/data/avatar/02Morgana.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/02Morgana.png
--------------------------------------------------------------------------------
/data/avatar/03Evelynn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/03Evelynn.png
--------------------------------------------------------------------------------
/data/avatar/04Aatrox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/04Aatrox.png
--------------------------------------------------------------------------------
/data/avatar/05Brand.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/05Brand.png
--------------------------------------------------------------------------------
/data/avatar/06Swain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/06Swain.png
--------------------------------------------------------------------------------
/data/avatar/07Shyvana.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/07Shyvana.png
--------------------------------------------------------------------------------
/data/avatar/08Aurelion Sol.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/08Aurelion Sol.png
--------------------------------------------------------------------------------
/data/avatar/09Pantheon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/09Pantheon.png
--------------------------------------------------------------------------------
/data/avatar/10Yasuo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/10Yasuo.png
--------------------------------------------------------------------------------
/data/avatar/11Braum.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/11Braum.png
--------------------------------------------------------------------------------
/data/avatar/12Lissandra.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/12Lissandra.png
--------------------------------------------------------------------------------
/data/avatar/13Ashe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/13Ashe.png
--------------------------------------------------------------------------------
/data/avatar/14Volibear.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/14Volibear.png
--------------------------------------------------------------------------------
/data/avatar/15Sejuani.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/15Sejuani.png
--------------------------------------------------------------------------------
/data/avatar/16Anivia.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/16Anivia.png
--------------------------------------------------------------------------------
/data/avatar/17Blitzcrank.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/17Blitzcrank.png
--------------------------------------------------------------------------------
/data/avatar/18Darius.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/18Darius.png
--------------------------------------------------------------------------------
/data/avatar/19Katarina.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/19Katarina.png
--------------------------------------------------------------------------------
/data/avatar/20Draven.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/20Draven.png
--------------------------------------------------------------------------------
/data/avatar/21Fiora.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/21Fiora.png
--------------------------------------------------------------------------------
/data/avatar/22Garen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/22Garen.png
--------------------------------------------------------------------------------
/data/avatar/23Vayne.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/23Vayne.png
--------------------------------------------------------------------------------
/data/avatar/24Lucian.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/24Lucian.png
--------------------------------------------------------------------------------
/data/avatar/25Leona.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/25Leona.png
--------------------------------------------------------------------------------
/data/avatar/26Kayle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/26Kayle.png
--------------------------------------------------------------------------------
/data/avatar/27Shen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/27Shen.png
--------------------------------------------------------------------------------
/data/avatar/28Zed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/28Zed.png
--------------------------------------------------------------------------------
/data/avatar/29Kennen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/29Kennen.png
--------------------------------------------------------------------------------
/data/avatar/30Akali.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/30Akali.png
--------------------------------------------------------------------------------
/data/avatar/31Graves.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/31Graves.png
--------------------------------------------------------------------------------
/data/avatar/32Pyke.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/32Pyke.png
--------------------------------------------------------------------------------
/data/avatar/33Twist Fate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/33Twist Fate.png
--------------------------------------------------------------------------------
/data/avatar/34Gangplank.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/34Gangplank.png
--------------------------------------------------------------------------------
/data/avatar/35Miss Fortune.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/35Miss Fortune.png
--------------------------------------------------------------------------------
/data/avatar/36Mordekaiser.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/36Mordekaiser.png
--------------------------------------------------------------------------------
/data/avatar/37Kindred.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/37Kindred.png
--------------------------------------------------------------------------------
/data/avatar/38Karthus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/38Karthus.png
--------------------------------------------------------------------------------
/data/avatar/39Warwick.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/39Warwick.png
--------------------------------------------------------------------------------
/data/avatar/40Nidalee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/40Nidalee.png
--------------------------------------------------------------------------------
/data/avatar/41Ahri.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/41Ahri.png
--------------------------------------------------------------------------------
/data/avatar/42Rengar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/42Rengar.png
--------------------------------------------------------------------------------
/data/avatar/43Gnar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/43Gnar.png
--------------------------------------------------------------------------------
/data/avatar/44Kha'Zix.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/44Kha'Zix.png
--------------------------------------------------------------------------------
/data/avatar/45Kassadin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/45Kassadin.png
--------------------------------------------------------------------------------
/data/avatar/46Rek'Sai.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/46Rek'Sai.png
--------------------------------------------------------------------------------
/data/avatar/47Cho'Gath.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/47Cho'Gath.png
--------------------------------------------------------------------------------
/data/avatar/48Kaisa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/48Kaisa.png
--------------------------------------------------------------------------------
/data/avatar/49Tristana.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/49Tristana.png
--------------------------------------------------------------------------------
/data/avatar/50Lulu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/50Lulu.png
--------------------------------------------------------------------------------
/data/avatar/51Poppy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/51Poppy.png
--------------------------------------------------------------------------------
/data/avatar/52Veigar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/52Veigar.png
--------------------------------------------------------------------------------
/data/avatar/53Camille.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/53Camille.png
--------------------------------------------------------------------------------
/data/avatar/54jayce.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/54jayce.png
--------------------------------------------------------------------------------
/data/avatar/55VI.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/55VI.png
--------------------------------------------------------------------------------
/data/avatar/56Jinx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/avatar/56Jinx.png
--------------------------------------------------------------------------------
/data/champions.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "Varus",
4 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Varus.png&resize=64:",
5 | "price": 2,
6 | "origin": [
7 | "demon"
8 | ],
9 | "class": [
10 | "ranger"
11 | ]
12 | },
13 | {
14 | "name": "Elise",
15 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Elise.png&resize=64:",
16 | "price": 1,
17 | "origin": [
18 | "demon"
19 | ],
20 | "class": [
21 | "shapeshifter"
22 | ]
23 | },
24 | {
25 | "name": "Morgana",
26 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Morgana.png&resize=64:",
27 | "price": 3,
28 | "origin": [
29 | "demon"
30 | ],
31 | "class": [
32 | "sorcerer"
33 | ]
34 | },
35 | {
36 | "name": "Evelynn",
37 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Evelynn.png&resize=64:",
38 | "price": 3,
39 | "origin": [
40 | "demon"
41 | ],
42 | "class": [
43 | "assassin"
44 | ]
45 | },
46 | {
47 | "name": "Aatrox",
48 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Aatrox.png&resize=64:",
49 | "price": 3,
50 | "origin": [
51 | "demon"
52 | ],
53 | "class": [
54 | "blademaster"
55 | ]
56 | },
57 | {
58 | "name": "Brand",
59 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Brand.png&resize=64:",
60 | "price": 4,
61 | "origin": [
62 | "demon"
63 | ],
64 | "class": [
65 | "elementalist"
66 | ]
67 | },
68 | {
69 | "name": "Swain",
70 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Swain.png&resize=64:",
71 | "price": 5,
72 | "origin": [
73 | "demon",
74 | "imperial"
75 | ],
76 | "class": [
77 | "shapeshifter"
78 | ]
79 | },
80 | {
81 | "name": "Shyvana",
82 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Shyvana.png&resize=64:",
83 | "price": 3,
84 | "origin": [
85 | "dragon"
86 | ],
87 | "class": [
88 | "shapeshifter"
89 | ]
90 | },
91 | {
92 | "name": "Aurelion Sol",
93 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/AurelionSol.png&resize=64:",
94 | "price": 4,
95 | "origin": [
96 | "dragon"
97 | ],
98 | "class": [
99 | "sorcerer"
100 | ]
101 | },
102 | {
103 | "name": "Pantheon",
104 | "avatar": "http://game.gtimg.cn/images/lol/tft/cham-icons/80.png",
105 | "price": 5,
106 | "origin": [
107 | "dragon"
108 | ],
109 | "class": [
110 | "guardian"
111 | ]
112 | },
113 | {
114 | "name": "Yasuo",
115 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Yasuo.png&resize=64:",
116 | "price": 5,
117 | "origin": [
118 | "exile"
119 | ],
120 | "class": [
121 | "blademaster"
122 | ]
123 | },
124 | {
125 | "name": "Braum",
126 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Braum.png&resize=64:",
127 | "price": 2,
128 | "origin": [
129 | "glacial"
130 | ],
131 | "class": [
132 | "guardian"
133 | ]
134 | },
135 | {
136 | "name": "Lissandra",
137 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Lissandra.png&resize=64:",
138 | "price": 2,
139 | "origin": [
140 | "glacial"
141 | ],
142 | "class": [
143 | "elementalist"
144 | ]
145 | },
146 | {
147 | "name": "Ashe",
148 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Ashe.png&resize=64:",
149 | "price": 3,
150 | "origin": [
151 | "glacial"
152 | ],
153 | "class": [
154 | "ranger"
155 | ]
156 | },
157 | {
158 | "name": "Volibear",
159 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Volibear.png&resize=64:",
160 | "price": 3,
161 | "origin": [
162 | "glacial"
163 | ],
164 | "class": [
165 | "brawler"
166 | ]
167 | },
168 | {
169 | "name": "Sejuani",
170 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Sejuani.png&resize=64:",
171 | "price": 4,
172 | "origin": [
173 | "glacial"
174 | ],
175 | "class": [
176 | "knight"
177 | ]
178 | },
179 | {
180 | "name": "Anivia",
181 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Anivia.png&resize=64:",
182 | "price": 5,
183 | "origin": [
184 | "glacial"
185 | ],
186 | "class": [
187 | "elementalist"
188 | ]
189 | },
190 | {
191 | "name": "Blitzcrank",
192 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Blitzcrank.png&resize=64:",
193 | "price": 2,
194 | "origin": [
195 | "robot"
196 | ],
197 | "class": [
198 | "brawler"
199 | ]
200 | },
201 | {
202 | "name": "Darius",
203 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Darius.png&resize=64:",
204 | "price": 1,
205 | "origin": [
206 | "imperial"
207 | ],
208 | "class": [
209 | "knight"
210 | ]
211 | },
212 | {
213 | "name": "Katarina",
214 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Katarina.png&resize=64:",
215 | "price": 3,
216 | "origin": [
217 | "imperial"
218 | ],
219 | "class": [
220 | "assassin"
221 | ]
222 | },
223 | {
224 | "name": "Draven",
225 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Draven.png&resize=64:",
226 | "price": 4,
227 | "origin": [
228 | "imperial"
229 | ],
230 | "class": [
231 | "blademaster"
232 | ]
233 | },
234 | {
235 | "name": "Fiora",
236 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Fiora.png&resize=64:",
237 | "price": 1,
238 | "origin": [
239 | "noble"
240 | ],
241 | "class": [
242 | "blademaster"
243 | ]
244 | },
245 | {
246 | "name": "Garen",
247 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Garen.png&resize=64:",
248 | "price": 1,
249 | "origin": [
250 | "noble"
251 | ],
252 | "class": [
253 | "knight"
254 | ]
255 | },
256 | {
257 | "name": "Vayne",
258 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Vayne.png&resize=64:",
259 | "price": 1,
260 | "origin": [
261 | "noble"
262 | ],
263 | "class": [
264 | "ranger"
265 | ]
266 | },
267 | {
268 | "name": "Lucian",
269 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Lucian.png&resize=64:",
270 | "price": 2,
271 | "origin": [
272 | "noble"
273 | ],
274 | "class": [
275 | "gunslinger"
276 | ]
277 | },
278 | {
279 | "name": "Leona",
280 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Leona.png&resize=64:",
281 | "price": 4,
282 | "origin": [
283 | "noble"
284 | ],
285 | "class": [
286 | "guardian"
287 | ]
288 | },
289 | {
290 | "name": "Kayle",
291 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Kayle.png&resize=64:",
292 | "price": 5,
293 | "origin": [
294 | "noble"
295 | ],
296 | "class": [
297 | "knight"
298 | ]
299 | },
300 | {
301 | "name": "Shen",
302 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Shen.png&resize=64:",
303 | "price": 2,
304 | "origin": [
305 | "ninja"
306 | ],
307 | "class": [
308 | "blademaster"
309 | ]
310 | },
311 | {
312 | "name": "Zed",
313 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Zed.png&resize=64:",
314 | "price": 2,
315 | "origin": [
316 | "ninja"
317 | ],
318 | "class": [
319 | "assassin"
320 | ]
321 | },
322 | {
323 | "name": "Kennen",
324 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Kennen.png&resize=64:",
325 | "price": 3,
326 | "origin": [
327 | "ninja",
328 | "yordle"
329 | ],
330 | "class": [
331 | "elementalist"
332 | ]
333 | },
334 | {
335 | "name": "Akali",
336 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Akali.png&resize=64:",
337 | "price": 4,
338 | "origin": [
339 | "ninja"
340 | ],
341 | "class": [
342 | "assassin"
343 | ]
344 | },
345 | {
346 | "name": "Graves",
347 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Graves.png&resize=64:",
348 | "price": 1,
349 | "origin": [
350 | "pirate"
351 | ],
352 | "class": [
353 | "gunslinger"
354 | ]
355 | },
356 | {
357 | "name": "Pyke",
358 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Pyke.png&resize=64:",
359 | "price": 2,
360 | "origin": [
361 | "pirate"
362 | ],
363 | "class": [
364 | "assassin"
365 | ]
366 | },
367 | {
368 | "name": "Twist Fate",
369 | "avatar": "http://game.gtimg.cn/images/lol/tft/cham-icons/4.png",
370 | "price": 2,
371 | "origin": [
372 | "pirate"
373 | ],
374 | "class": [
375 | "sorcerer"
376 | ]
377 | },
378 | {
379 | "name": "Gangplank",
380 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Gangplank.png&resize=64:",
381 | "price": 3,
382 | "origin": [
383 | "pirate"
384 | ],
385 | "class": [
386 | "blademaster",
387 | "gunslinger"
388 | ]
389 | },
390 | {
391 | "name": "Miss Fortune",
392 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/MissFortune.png&resize=64:",
393 | "price": 5,
394 | "origin": [
395 | "pirate"
396 | ],
397 | "class": [
398 | "gunslinger"
399 | ]
400 | },
401 | {
402 | "name": "Mordekaiser",
403 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Mordekaiser.png&resize=64:",
404 | "price": 1,
405 | "origin": [
406 | "phantom"
407 | ],
408 | "class": [
409 | "knight"
410 | ]
411 | },
412 | {
413 | "name": "Kindred",
414 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Kindred.png&resize=64:",
415 | "price": 4,
416 | "origin": [
417 | "phantom"
418 | ],
419 | "class": [
420 | "ranger"
421 | ]
422 | },
423 | {
424 | "name": "Karthus",
425 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Karthus.png&resize=64:",
426 | "price": 5,
427 | "origin": [
428 | "phantom"
429 | ],
430 | "class": [
431 | "sorcerer"
432 | ]
433 | },
434 | {
435 | "name": "Warwick",
436 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Warwick.png&resize=64:",
437 | "price": 1,
438 | "origin": [
439 | "wild"
440 | ],
441 | "class": [
442 | "brawler"
443 | ]
444 | },
445 | {
446 | "name": "Nidalee",
447 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Nidalee.png&resize=64:",
448 | "price": 1,
449 | "origin": [
450 | "wild"
451 | ],
452 | "class": [
453 | "shapeshifter"
454 | ]
455 | },
456 | {
457 | "name": "Ahri",
458 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Ahri.png&resize=64:",
459 | "price": 2,
460 | "origin": [
461 | "wild"
462 | ],
463 | "class": [
464 | "sorcerer"
465 | ]
466 | },
467 | {
468 | "name": "Rengar",
469 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Rengar.png&resize=64:",
470 | "price": 3,
471 | "origin": [
472 | "wild"
473 | ],
474 | "class": [
475 | "assassin"
476 | ]
477 | },
478 | {
479 | "name": "Gnar",
480 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Gnar.png&resize=64:",
481 | "price": 4,
482 | "origin": [
483 | "wild",
484 | "yordle"
485 | ],
486 | "class": [
487 | "shapeshifter"
488 | ]
489 | },
490 | {
491 | "name": "Kha'Zix",
492 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Khazix.png&resize=64:",
493 | "price": 1,
494 | "origin": [
495 | "void"
496 | ],
497 | "class": [
498 | "assassin"
499 | ]
500 | },
501 | {
502 | "name": "Kassadin",
503 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Kassadin.png&resize=64:",
504 | "price": 1,
505 | "origin": [
506 | "void"
507 | ],
508 | "class": [
509 | "sorcerer"
510 | ]
511 | },
512 | {
513 | "name": "Rek'Sai",
514 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/RekSai.png&resize=64:",
515 | "price": 2,
516 | "origin": [
517 | "void"
518 | ],
519 | "class": [
520 | "brawler"
521 | ]
522 | },
523 | {
524 | "name": "Cho'Gath",
525 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Chogath.png&resize=64:",
526 | "price": 4,
527 | "origin": [
528 | "void"
529 | ],
530 | "class": [
531 | "brawler"
532 | ]
533 | },
534 | {
535 | "name": "Kaisa",
536 | "avatar": "http://game.gtimg.cn/images/lol/tft/cham-icons/145.png",
537 | "price": 5,
538 | "origin": [
539 | "void"
540 | ],
541 | "class": [
542 | "assassin",
543 | "ranger"
544 | ]
545 | },
546 | {
547 | "name": "Tristana",
548 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Tristana.png&resize=64:",
549 | "price": 1,
550 | "origin": [
551 | "yordle"
552 | ],
553 | "class": [
554 | "gunslinger"
555 | ]
556 | },
557 | {
558 | "name": "Lulu",
559 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Lulu.png&resize=64:",
560 | "price": 2,
561 | "origin": [
562 | "yordle"
563 | ],
564 | "class": [
565 | "sorcerer"
566 | ]
567 | },
568 | {
569 | "name": "Poppy",
570 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Poppy.png&resize=64:",
571 | "price": 3,
572 | "origin": [
573 | "yordle"
574 | ],
575 | "class": [
576 | "knight"
577 | ]
578 | },
579 | {
580 | "name": "Veigar",
581 | "avatar": "https://am-a.akamaihd.net/image?f=https://news-a.akamaihd.net/public/images/articles/2019/june/tftcompendium/Champions/Veigar.png&resize=64:",
582 | "price": 3,
583 | "origin": [
584 | "yordle"
585 | ],
586 | "class": [
587 | "sorcerer"
588 | ]
589 | },
590 | {
591 | "name": "Camille",
592 | "avatar": "http://game.gtimg.cn/images/lol/tft/cham-icons/164.png",
593 | "price": 1,
594 | "origin": [
595 | "Hextech"
596 | ],
597 | "class": [
598 | "blademaster"
599 | ]
600 | },
601 | {
602 | "name": "Jayce",
603 | "avatar": "http://game.gtimg.cn/images/lol/tft/cham-icons/126.png",
604 | "price": 2,
605 | "origin": [
606 | "Hextech"
607 | ],
608 | "class": [
609 | "shapeshifter"
610 | ]
611 | },
612 | {
613 | "name": "VI",
614 | "avatar": "http://game.gtimg.cn/images/lol/tft/cham-icons/254.png",
615 | "price": 3,
616 | "origin": [
617 | "Hextech"
618 | ],
619 | "class": [
620 | "brawler"
621 | ]
622 | },
623 | {
624 | "name": "Jinx",
625 | "avatar": "http://game.gtimg.cn/images/lol/tft/cham-icons/222.png",
626 | "price": 4,
627 | "origin": [
628 | "Hextech"
629 | ],
630 | "class": [
631 | "gunslinger"
632 | ]
633 | }
634 | ]
--------------------------------------------------------------------------------
/data/champions_graph.json:
--------------------------------------------------------------------------------
1 | {
2 | "0": [
3 | 1,
4 | 2,
5 | 3,
6 | 4,
7 | 5,
8 | 6,
9 | 10,
10 | 13,
11 | 17,
12 | 23,
13 | 27,
14 | 28,
15 | 29,
16 | 30,
17 | 37,
18 | 48
19 | ],
20 | "1": [
21 | 2,
22 | 3,
23 | 4,
24 | 5,
25 | 6,
26 | 7,
27 | 10,
28 | 17,
29 | 27,
30 | 28,
31 | 29,
32 | 30,
33 | 40,
34 | 43
35 | ],
36 | "10": [
37 | 17,
38 | 20,
39 | 21,
40 | 27,
41 | 28,
42 | 29,
43 | 30,
44 | 34,
45 | 53
46 | ],
47 | "11": [
48 | 12,
49 | 13,
50 | 14,
51 | 15,
52 | 16,
53 | 17,
54 | 25,
55 | 27,
56 | 28,
57 | 29,
58 | 30
59 | ],
60 | "12": [
61 | 13,
62 | 14,
63 | 15,
64 | 16,
65 | 17,
66 | 27,
67 | 28,
68 | 29,
69 | 30
70 | ],
71 | "13": [
72 | 14,
73 | 15,
74 | 16,
75 | 17,
76 | 23,
77 | 27,
78 | 28,
79 | 29,
80 | 30,
81 | 37,
82 | 48
83 | ],
84 | "14": [
85 | 15,
86 | 16,
87 | 17,
88 | 27,
89 | 28,
90 | 29,
91 | 30,
92 | 39,
93 | 46,
94 | 47,
95 | 54
96 | ],
97 | "15": [
98 | 16,
99 | 17,
100 | 18,
101 | 22,
102 | 26,
103 | 27,
104 | 28,
105 | 29,
106 | 30,
107 | 36,
108 | 51
109 | ],
110 | "16": [
111 | 17,
112 | 27,
113 | 28,
114 | 29,
115 | 30
116 | ],
117 | "17": [
118 | 27,
119 | 28,
120 | 29,
121 | 30,
122 | 39,
123 | 46,
124 | 47,
125 | 54
126 | ],
127 | "18": [
128 | 19,
129 | 20,
130 | 22,
131 | 26,
132 | 27,
133 | 28,
134 | 29,
135 | 30,
136 | 36,
137 | 51
138 | ],
139 | "19": [
140 | 20,
141 | 27,
142 | 28,
143 | 29,
144 | 30,
145 | 32,
146 | 42,
147 | 44,
148 | 48
149 | ],
150 | "2": [
151 | 3,
152 | 4,
153 | 5,
154 | 6,
155 | 8,
156 | 10,
157 | 17,
158 | 27,
159 | 28,
160 | 29,
161 | 30,
162 | 33,
163 | 38,
164 | 41,
165 | 45,
166 | 50,
167 | 52
168 | ],
169 | "20": [
170 | 21,
171 | 27,
172 | 28,
173 | 29,
174 | 30,
175 | 34,
176 | 53
177 | ],
178 | "21": [
179 | 22,
180 | 23,
181 | 24,
182 | 25,
183 | 26,
184 | 27,
185 | 28,
186 | 29,
187 | 30,
188 | 34,
189 | 53
190 | ],
191 | "22": [
192 | 23,
193 | 24,
194 | 25,
195 | 26,
196 | 27,
197 | 28,
198 | 29,
199 | 30,
200 | 36,
201 | 51
202 | ],
203 | "23": [
204 | 24,
205 | 25,
206 | 26,
207 | 27,
208 | 28,
209 | 29,
210 | 30,
211 | 37,
212 | 48
213 | ],
214 | "24": [
215 | 25,
216 | 26,
217 | 27,
218 | 28,
219 | 29,
220 | 30,
221 | 36,
222 | 51
223 | ],
224 | "25": [
225 | 26,
226 | 27,
227 | 28,
228 | 29,
229 | 30
230 | ],
231 | "26": [
232 | 27,
233 | 28,
234 | 29,
235 | 30,
236 | 36,
237 | 51
238 | ],
239 | "27": [
240 | 28,
241 | 29,
242 | 30,
243 | 34,
244 | 53
245 | ],
246 | "28": [
247 | 29,
248 | 30,
249 | 32,
250 | 42,
251 | 44,
252 | 48
253 | ],
254 | "29": [
255 | 30,
256 | 43,
257 | 49,
258 | 50,
259 | 51,
260 | 52
261 | ],
262 | "3": [
263 | 4,
264 | 5,
265 | 6,
266 | 10,
267 | 17,
268 | 19,
269 | 27,
270 | 28,
271 | 29,
272 | 30,
273 | 32,
274 | 42,
275 | 44,
276 | 48
277 | ],
278 | "30": [
279 | 32,
280 | 42,
281 | 44,
282 | 48
283 | ],
284 | "31": [
285 | 32,
286 | 33,
287 | 34,
288 | 35,
289 | 36,
290 | 51
291 | ],
292 | "32": [
293 | 33,
294 | 34,
295 | 35,
296 | 42,
297 | 44,
298 | 48
299 | ],
300 | "33": [
301 | 34,
302 | 35,
303 | 38,
304 | 41,
305 | 45,
306 | 50,
307 | 52
308 | ],
309 | "34": [
310 | 35,
311 | 36,
312 | 51,
313 | 53
314 | ],
315 | "35": [
316 | 36,
317 | 51
318 | ],
319 | "36": [
320 | 37,
321 | 38,
322 | 51
323 | ],
324 | "37": [
325 | 38,
326 | 48
327 | ],
328 | "38": [
329 | 41,
330 | 45,
331 | 50,
332 | 52
333 | ],
334 | "39": [
335 | 40,
336 | 41,
337 | 42,
338 | 43,
339 | 46,
340 | 47,
341 | 54
342 | ],
343 | "4": [
344 | 5,
345 | 6,
346 | 10,
347 | 17,
348 | 20,
349 | 21,
350 | 27,
351 | 28,
352 | 29,
353 | 30,
354 | 34,
355 | 53
356 | ],
357 | "40": [
358 | 41,
359 | 42,
360 | 43
361 | ],
362 | "41": [
363 | 42,
364 | 43,
365 | 45,
366 | 50,
367 | 52
368 | ],
369 | "42": [
370 | 43,
371 | 44,
372 | 48
373 | ],
374 | "43": [
375 | 49,
376 | 50,
377 | 51,
378 | 52
379 | ],
380 | "44": [
381 | 45,
382 | 46,
383 | 47,
384 | 48
385 | ],
386 | "45": [
387 | 46,
388 | 47,
389 | 48,
390 | 50,
391 | 52
392 | ],
393 | "46": [
394 | 47,
395 | 48,
396 | 54
397 | ],
398 | "47": [
399 | 48,
400 | 54
401 | ],
402 | "48": null,
403 | "49": [
404 | 50,
405 | 51,
406 | 52
407 | ],
408 | "5": [
409 | 6,
410 | 10,
411 | 12,
412 | 16,
413 | 17,
414 | 27,
415 | 28,
416 | 29,
417 | 30
418 | ],
419 | "50": [
420 | 51,
421 | 52
422 | ],
423 | "51": [
424 | 52
425 | ],
426 | "52": null,
427 | "53": [
428 | 54,
429 | 55
430 | ],
431 | "54": [
432 | 55
433 | ],
434 | "55": null,
435 | "6": [
436 | 7,
437 | 10,
438 | 17,
439 | 18,
440 | 19,
441 | 20,
442 | 27,
443 | 28,
444 | 29,
445 | 30,
446 | 40,
447 | 43
448 | ],
449 | "7": [
450 | 8,
451 | 9,
452 | 10,
453 | 17,
454 | 27,
455 | 28,
456 | 29,
457 | 30,
458 | 40,
459 | 43
460 | ],
461 | "8": [
462 | 9,
463 | 10,
464 | 17,
465 | 27,
466 | 28,
467 | 29,
468 | 30,
469 | 33,
470 | 38,
471 | 41,
472 | 45,
473 | 50,
474 | 52
475 | ],
476 | "9": [
477 | 10,
478 | 11,
479 | 17,
480 | 25,
481 | 27,
482 | 28,
483 | 29,
484 | 30
485 | ]
486 | }
--------------------------------------------------------------------------------
/data/final_result/total_strength/final_result6.json:
--------------------------------------------------------------------------------
1 | [
2 | "[('元素师', 3), ('冰川', 2), ('龙', 2), ('护卫', 2), ('忍者', 1)]",
3 | "[('忍者', 1), ('元素师', 3), ('护卫', 2), ('冰川', 4)]",
4 | "[('元素师', 3), ('冰川', 2), ('浪人', 1), ('护卫', 2), ('忍者', 1)]",
5 | "[('游侠', 2), ('冰川', 2), ('龙', 2), ('幽灵', 2), ('护卫', 2)]",
6 | "[('浪人', 1), ('枪手', 2), ('龙', 2), ('护卫', 2)]",
7 | "[('变形者', 3), ('帝国', 2), ('恶魔', 2), ('龙', 2), ('护卫', 2)]",
8 | "[('幽灵', 2), ('骑士', 2), ('龙', 2), ('护卫', 2)]",
9 | "[('虚空', 2), ('龙', 2), ('刺客', 3), ('护卫', 2), ('忍者', 1)]",
10 | "[('枪手', 2), ('剑士', 3), ('浪人', 1), ('护卫', 2), ('忍者', 1)]",
11 | "[('法师', 3), ('浪人', 1), ('龙', 2), ('护卫', 2)]",
12 | "[('游侠', 2), ('冰川', 2), ('浪人', 1), ('幽灵', 2), ('护卫', 2)]",
13 | "[('浪人', 1), ('贵族', 3), ('龙', 2), ('护卫', 2)]",
14 | "[('骑士', 2), ('冰川', 2), ('龙', 2), ('浪人', 1), ('护卫', 2)]",
15 | "[('元素师', 3), ('冰川', 2), ('机器人', 1), ('护卫', 2), ('忍者', 1)]",
16 | "[('枪手', 2), ('剑士', 3), ('浪人', 1), ('护卫', 2), ('海克斯', 2)]",
17 | "[('浪人', 1), ('幽灵', 2), ('骑士', 2), ('护卫', 2)]",
18 | "[('贵族', 3), ('骑士', 4), ('冰川', 2), ('护卫', 2)]",
19 | "[('枪手', 2), ('帝国', 2), ('剑士', 3), ('恶魔', 2), ('浪人', 1)]",
20 | "[('骑士', 2), ('幽灵', 2), ('冰川', 2), ('护卫', 2)]",
21 | "[('约德尔', 3), ('龙', 2), ('法师', 3), ('护卫', 2), ('忍者', 1)]",
22 | "[('虚空', 2), ('刺客', 3), ('浪人', 1), ('护卫', 2), ('忍者', 1)]",
23 | "[('浪人', 1), ('剑士', 3), ('贵族', 3), ('护卫', 2)]",
24 | "[('浪人', 1), ('骑士', 2), ('贵族', 3), ('护卫', 2)]",
25 | "[('游侠', 2), ('虚空', 2), ('冰川', 2), ('刺客', 3), ('护卫', 2), ('忍者', 1)]",
26 | "[('元素师', 3), ('骑士', 2), ('帝国', 2), ('恶魔', 2), ('冰川', 2)]",
27 | "[('浪人', 1), ('帝国', 2), ('龙', 2), ('护卫', 2)]",
28 | "[('约德尔', 3), ('元素师', 3), ('恶魔', 2), ('法师', 3), ('忍者', 1)]",
29 | "[('变形者', 3), ('恶魔', 2), ('龙', 2), ('浪人', 1), ('护卫', 2)]",
30 | "[('约德尔', 3), ('元素师', 3), ('骑士', 2), ('冰川', 2), ('忍者', 1)]",
31 | "[('枪手', 2), ('帝国', 2), ('剑士', 3), ('浪人', 1), ('海克斯', 2)]",
32 | "[('剑士', 3), ('龙', 2), ('浪人', 1), ('护卫', 2), ('忍者', 1)]",
33 | "[('贵族', 3), ('骑士', 2), ('冰川', 2), ('护卫', 2)]",
34 | "[('斗士', 2), ('虚空', 2), ('冰川', 2), ('龙', 2), ('护卫', 2)]",
35 | "[('游侠', 2), ('幽灵', 2), ('骑士', 2), ('护卫', 2)]",
36 | "[('枪手', 2), ('帝国', 2), ('剑士', 3), ('浪人', 1), ('忍者', 1)]",
37 | "[('幽灵', 2), ('骑士', 2), ('元素师', 3), ('冰川', 2)]",
38 | "[('骑士', 2), ('贵族', 3), ('龙', 2), ('护卫', 2)]",
39 | "[('忍者', 1), ('枪手', 2), ('龙', 2), ('护卫', 2)]",
40 | "[('骑士', 2), ('冰川', 2), ('龙', 2), ('护卫', 2), ('忍者', 1)]",
41 | "[('骑士', 2), ('帝国', 2), ('冰川', 2), ('龙', 2), ('护卫', 2)]",
42 | "[('斗士', 2), ('虚空', 2), ('龙', 2), ('机器人', 1), ('护卫', 2)]",
43 | "[('枪手', 2), ('帝国', 2), ('剑士', 3), ('机器人', 1), ('浪人', 1)]",
44 | "[('元素师', 3), ('帝国', 2), ('恶魔', 2), ('浪人', 1), ('忍者', 1)]",
45 | "[('元素师', 3), ('冰川', 2), ('护卫', 2)]",
46 | "[('冰川', 2), ('龙', 2), ('浪人', 1), ('护卫', 2), ('忍者', 1)]",
47 | "[('忍者', 1), ('元素师', 3), ('骑士', 2), ('冰川', 4)]",
48 | "[('浪人', 1), ('枪手', 2), ('剑士', 3), ('龙', 2)]",
49 | "[('忍者', 1), ('虚空', 2), ('刺客', 6)]",
50 | "[('游侠', 2), ('法师', 3), ('幽灵', 2), ('虚空', 2)]",
51 | "[('骑士', 2), ('浪人', 1), ('元素师', 3), ('冰川', 2)]",
52 | "[('机器人', 1), ('贵族', 3), ('龙', 2), ('护卫', 2)]",
53 | "[('游侠', 2), ('冰川', 2), ('龙', 2), ('浪人', 1), ('护卫', 2)]",
54 | "[('元素师', 3), ('恶魔', 2), ('冰川', 2), ('浪人', 1), ('忍者', 1)]",
55 | "[('骑士', 2), ('贵族', 3), ('帝国', 2), ('剑士', 3), ('浪人', 1)]",
56 | "[('法师', 3), ('枪手', 2), ('海盗', 3), ('龙', 2)]",
57 | "[('变形者', 3), ('恶魔', 2), ('冰川', 2), ('龙', 2), ('护卫', 2)]",
58 | "[('骑士', 2), ('冰川', 2), ('龙', 2), ('机器人', 1), ('护卫', 2)]",
59 | "[('游侠', 2), ('骑士', 2), ('幽灵', 2), ('贵族', 3)]",
60 | "[('忍者', 1), ('浪人', 1), ('贵族', 3), ('护卫', 2)]",
61 | "[('贵族', 3), ('骑士', 2), ('斗士', 2), ('冰川', 2), ('机器人', 1), ('护卫', 2)]",
62 | "[('忍者', 1), ('帝国', 2), ('龙', 2), ('护卫', 2)]",
63 | "[('约德尔', 3), ('枪手', 2), ('骑士', 2), ('贵族', 3), ('忍者', 1)]",
64 | "[('冰川', 2), ('龙', 2), ('机器人', 1), ('浪人', 1), ('护卫', 2)]",
65 | "[('斗士', 2), ('虚空', 2), ('冰川', 2), ('浪人', 1), ('护卫', 2)]",
66 | "[('元素师', 3), ('虚空', 2), ('冰川', 2), ('刺客', 3), ('忍者', 1)]",
67 | "[('幽灵', 2), ('贵族', 3), ('骑士', 4)]",
68 | "[('虚空', 2), ('浪人', 1), ('龙', 2), ('护卫', 2)]",
69 | "[('忍者', 1), ('枪手', 2), ('元素师', 3), ('冰川', 2)]",
70 | "[('变形者', 3), ('恶魔', 2), ('龙', 2), ('护卫', 2), ('忍者', 1)]",
71 | "[('骑士', 2), ('帝国', 2), ('恶魔', 2), ('法师', 3), ('幽灵', 2)]"
72 | ]
--------------------------------------------------------------------------------
/data/final_result/total_strength/final_result7.json:
--------------------------------------------------------------------------------
1 | [
2 | "[('法师', 3), ('骑士', 2), ('龙', 2), ('护卫', 2), ('幽灵', 2)]",
3 | "[('冰川', 2), ('法师', 3), ('游侠', 2), ('龙', 2), ('护卫', 2), ('幽灵', 2)]",
4 | "[('骑士', 2), ('元素师', 3), ('忍者', 1), ('冰川', 4), ('护卫', 2)]",
5 | "[('冰川', 2), ('贵族', 3), ('骑士', 4), ('护卫', 2), ('幽灵', 2)]",
6 | "[('元素师', 3), ('忍者', 1), ('冰川', 4), ('龙', 2), ('护卫', 2)]",
7 | "[('枪手', 2), ('忍者', 1), ('剑士', 3), ('浪人', 1), ('龙', 2), ('护卫', 2)]",
8 | "[('冰川', 2), ('元素师', 3), ('忍者', 1), ('浪人', 1), ('龙', 2), ('护卫', 2)]",
9 | "[('元素师', 3), ('忍者', 1), ('冰川', 4), ('浪人', 1), ('护卫', 2)]",
10 | "[('骑士', 2), ('浪人', 1), ('龙', 2), ('护卫', 2), ('幽灵', 2)]",
11 | "[('骑士', 2), ('贵族', 3), ('浪人', 1), ('护卫', 2), ('幽灵', 2)]",
12 | "[('冰川', 2), ('元素师', 3), ('恶魔', 2), ('龙', 2), ('护卫', 2)]",
13 | "[('冰川', 2), ('骑士', 2), ('龙', 2), ('护卫', 2), ('幽灵', 2)]",
14 | "[('冰川', 2), ('帝国', 2), ('变形者', 3), ('骑士', 2), ('恶魔', 2), ('龙', 2), ('护卫', 2)]",
15 | "[('法师', 3), ('虚空', 2), ('浪人', 1), ('龙', 2), ('护卫', 2)]",
16 | "[('骑士', 2), ('贵族', 3), ('浪人', 1), ('龙', 2), ('护卫', 2)]",
17 | "[('帝国', 2), ('变形者', 3), ('恶魔', 2), ('浪人', 1), ('龙', 2), ('护卫', 2)]",
18 | "[('帝国', 2), ('龙', 2), ('护卫', 2), ('枪手', 2)]",
19 | "[('龙', 2), ('护卫', 2), ('枪手', 2), ('浪人', 1)]",
20 | "[('冰川', 2), ('约德尔', 3), ('元素师', 3), ('忍者', 1), ('护卫', 2)]",
21 | "[('法师', 3), ('约德尔', 3), ('忍者', 1), ('浪人', 1), ('龙', 2), ('护卫', 2)]",
22 | "[('游侠', 2), ('护卫', 2), ('幽灵', 2), ('骑士', 2)]",
23 | "[('冰川', 2), ('帝国', 2), ('贵族', 3), ('骑士', 4), ('护卫', 2)]",
24 | "[('忍者', 1), ('刺客', 3), ('虚空', 2), ('浪人', 1), ('龙', 2), ('护卫', 2)]",
25 | "[('元素师', 3), ('忍者', 1), ('冰川', 4), ('斗士', 2), ('护卫', 2), ('机器人', 1)]",
26 | "[('帝国', 2), ('骑士', 2), ('贵族', 3), ('龙', 2), ('护卫', 2)]",
27 | "[('骑士', 2), ('贵族', 3), ('剑士', 3), ('浪人', 1), ('护卫', 2)]",
28 | "[('贵族', 3), ('剑士', 3), ('浪人', 1), ('龙', 2), ('护卫', 2)]",
29 | "[('冰川', 2), ('护卫', 2), ('游侠', 4), ('幽灵', 2)]",
30 | "[('法师', 3), ('恶魔', 2), ('浪人', 1), ('龙', 2), ('护卫', 2)]",
31 | "[('冰川', 2), ('游侠', 2), ('忍者', 1), ('刺客', 3), ('虚空', 2), ('龙', 2), ('护卫', 2)]",
32 | "[('冰川', 2), ('骑士', 2), ('浪人', 1), ('护卫', 2), ('幽灵', 2)]",
33 | "[('冰川', 2), ('骑士', 2), ('浪人', 1), ('龙', 2), ('护卫', 2)]",
34 | "[('帝国', 2), ('刺客', 6), ('忍者', 1), ('恶魔', 2), ('虚空', 2)]",
35 | "[('护卫', 2), ('幽灵', 2), ('枪手', 2), ('浪人', 1)]",
36 | "[('冰川', 2), ('游侠', 2), ('骑士', 2), ('贵族', 3), ('护卫', 2), ('幽灵', 2)]",
37 | "[('帝国', 2), ('法师', 3), ('骑士', 2), ('恶魔', 2), ('龙', 2), ('幽灵', 2)]",
38 | "[('游侠', 2), ('骑士', 2), ('贵族', 3), ('冰川', 4), ('护卫', 2)]",
39 | "[('帝国', 2), ('骑士', 2), ('龙', 2), ('护卫', 2), ('幽灵', 2)]",
40 | "[('帝国', 2), ('刺客', 3), ('虚空', 2), ('龙', 2), ('护卫', 2)]",
41 | "[('帝国', 2), ('剑士', 3), ('浪人', 1), ('龙', 2), ('护卫', 2)]",
42 | "[('帝国', 2), ('骑士', 2), ('浪人', 1), ('龙', 2), ('护卫', 2)]",
43 | "[('冰川', 2), ('骑士', 2), ('忍者', 1), ('刺客', 3), ('虚空', 2), ('护卫', 2)]",
44 | "[('海克斯', 2), ('枪手', 2), ('剑士', 3), ('浪人', 1), ('护卫', 2)]",
45 | "[('骑士', 2), ('龙', 2), ('护卫', 2), ('机器人', 1), ('幽灵', 2)]",
46 | "[('游侠', 2), ('元素师', 3), ('忍者', 1), ('冰川', 4), ('护卫', 2)]",
47 | "[('冰川', 2), ('游侠', 2), ('浪人', 1), ('护卫', 2), ('幽灵', 2)]",
48 | "[('冰川', 2), ('枪手', 2), ('元素师', 3), ('忍者', 1), ('剑士', 3), ('浪人', 1)]",
49 | "[('法师', 3), ('幽灵', 2), ('恶魔', 2), ('虚空', 2), ('游侠', 4)]",
50 | "[('冰川', 2), ('枪手', 2), ('剑士', 3), ('浪人', 1), ('护卫', 2)]",
51 | "[('帝国', 2), ('枪手', 2), ('剑士', 3), ('浪人', 1), ('龙', 2)]",
52 | "[('冰川', 2), ('法师', 3), ('约德尔', 3), ('元素师', 3), ('忍者', 1), ('恶魔', 2)]"
53 | ]
--------------------------------------------------------------------------------
/data/final_result/total_strength/final_result8.json:
--------------------------------------------------------------------------------
1 | [
2 | "[('忍者', 1), ('护卫', 2), ('冰川', 2), ('龙', 2), ('约德尔', 3), ('法师', 3), ('元素师', 3)]",
3 | "[('护卫', 2), ('冰川', 2), ('虚空', 2), ('龙', 2), ('游侠', 2), ('法师', 3), ('幽灵', 2)]",
4 | "[('骑士', 2), ('护卫', 2), ('龙', 2), ('帝国', 2), ('法师', 3), ('恶魔', 2), ('幽灵', 2)]",
5 | "[('骑士', 2), ('护卫', 2), ('虚空', 2), ('龙', 2), ('法师', 3), ('幽灵', 2)]",
6 | "[('骑士', 2), ('护卫', 2), ('冰川', 2), ('浪人', 1), ('龙', 2), ('法师', 3), ('幽灵', 2)]",
7 | "[('骑士', 2), ('忍者', 1), ('护卫', 2), ('龙', 2), ('冰川', 4), ('元素师', 3)]",
8 | "[('护卫', 2), ('浪人', 1), ('龙', 2), ('剑士', 3), ('枪手', 2), ('帝国', 2)]",
9 | "[('骑士', 2), ('护卫', 2), ('冰川', 2), ('浪人', 1), ('剑士', 3), ('枪手', 2), ('帝国', 2)]",
10 | "[('护卫', 2), ('冰川', 2), ('骑士', 4), ('幽灵', 2), ('贵族', 3)]",
11 | "[('护卫', 2), ('龙', 2), ('变形者', 3), ('枪手', 2), ('帝国', 2), ('恶魔', 2)]",
12 | "[('护卫', 2), ('浪人', 1), ('龙', 2), ('海盗', 3), ('枪手', 2), ('法师', 3)]",
13 | "[('骑士', 2), ('护卫', 2), ('冰川', 2), ('游侠', 4), ('幽灵', 2), ('贵族', 3)]",
14 | "[('忍者', 1), ('护卫', 2), ('冰川', 2), ('龙', 2), ('变形者', 3), ('恶魔', 2), ('元素师', 3)]",
15 | "[('骑士', 2), ('护卫', 2), ('浪人', 1), ('龙', 2), ('幽灵', 2), ('贵族', 3)]",
16 | "[('骑士', 2), ('护卫', 2), ('龙', 2), ('变形者', 3), ('帝国', 2), ('恶魔', 2), ('贵族', 3)]",
17 | "[('忍者', 1), ('护卫', 2), ('浪人', 1), ('龙', 2), ('剑士', 3), ('枪手', 2), ('贵族', 3)]",
18 | "[('护卫', 2), ('龙', 2), ('骑士', 4), ('帝国', 2), ('贵族', 3)]",
19 | "[('贵族', 3), ('护卫', 2), ('骑士', 6), ('冰川', 2)]",
20 | "[('骑士', 2), ('浪人', 1), ('贵族', 6), ('剑士', 3), ('枪手', 2)]",
21 | "[('骑士', 2), ('护卫', 2), ('龙', 2), ('游侠', 2), ('幽灵', 2)]",
22 | "[('护卫', 2), ('浪人', 1), ('龙', 2), ('枪手', 2), ('幽灵', 2)]",
23 | "[('骑士', 2), ('忍者', 1), ('护卫', 2), ('浪人', 1), ('剑士', 3), ('幽灵', 2), ('贵族', 3)]",
24 | "[('骑士', 2), ('护卫', 2), ('冰川', 2), ('龙', 2), ('枪手', 2), ('帝国', 2)]",
25 | "[('骑士', 2), ('护卫', 2), ('冰川', 2), ('浪人', 1), ('龙', 2), ('变形者', 3), ('帝国', 2), ('恶魔', 2)]",
26 | "[('忍者', 1), ('护卫', 2), ('龙', 2), ('法师', 3), ('恶魔', 2), ('元素师', 3)]"
27 | ]
--------------------------------------------------------------------------------
/data/final_result/total_strength/final_result9.json:
--------------------------------------------------------------------------------
1 | [
2 | "[('骑士', 2), ('剑士', 3), ('浪人', 1), ('枪手', 2), ('贵族', 6), ('护卫', 2)]",
3 | "[('骑士', 2), ('贵族', 3), ('冰川', 4), ('枪手', 2), ('忍者', 1), ('元素师', 3), ('护卫', 2)]",
4 | "[('骑士', 2), ('龙', 2), ('法师', 3), ('游侠', 2), ('虚空', 2), ('护卫', 2), ('冰川', 2), ('幽灵', 2)]",
5 | "[('贵族', 3), ('冰川', 4), ('忍者', 1), ('元素师', 3), ('护卫', 2), ('骑士', 4)]",
6 | "[('龙', 2), ('法师', 3), ('虚空', 2), ('冰川', 2), ('护卫', 2), ('游侠', 4), ('幽灵', 2)]",
7 | "[('龙', 2), ('约德尔', 3), ('法师', 3), ('冰川', 4), ('忍者', 1), ('元素师', 3), ('护卫', 2)]",
8 | "[('恶魔', 2), ('龙', 2), ('约德尔', 3), ('法师', 3), ('忍者', 1), ('元素师', 3), ('护卫', 2), ('冰川', 2)]",
9 | "[('贵族', 3), ('骑士', 6), ('护卫', 2), ('冰川', 2), ('幽灵', 2)]",
10 | "[('骑士', 2), ('龙', 2), ('贵族', 3), ('浪人', 1), ('法师', 3), ('护卫', 2), ('幽灵', 2)]",
11 | "[('龙', 2), ('剑士', 3), ('变形者', 3), ('浪人', 1), ('帝国', 2), ('枪手', 2), ('护卫', 2), ('恶魔', 2)]",
12 | "[('骑士', 2), ('龙', 2), ('法师', 3), ('帝国', 2), ('护卫', 2), ('恶魔', 2), ('幽灵', 2)]",
13 | "[('骑士', 2), ('龙', 2), ('剑士', 3), ('浪人', 1), ('帝国', 2), ('枪手', 2), ('护卫', 2), ('冰川', 2)]",
14 | "[('约德尔', 3), ('贵族', 3), ('枪手', 2), ('忍者', 1), ('护卫', 2), ('骑士', 4), ('冰川', 2)]",
15 | "[('骑士', 2), ('龙', 2), ('浪人', 1), ('贵族', 6), ('护卫', 2)]",
16 | "[('龙', 2), ('浪人', 1), ('法师', 3), ('枪手', 2), ('护卫', 2), ('幽灵', 2)]",
17 | "[('龙', 2), ('法师', 3), ('护卫', 2), ('骑士', 4), ('冰川', 2), ('幽灵', 2)]",
18 | "[('贵族', 3), ('帝国', 2), ('骑士', 6), ('护卫', 2), ('冰川', 2)]",
19 | "[('龙', 2), ('贵族', 3), ('变形者', 3), ('帝国', 2), ('护卫', 2), ('骑士', 4), ('恶魔', 2)]",
20 | "[('骑士', 2), ('贵族', 3), ('剑士', 3), ('浪人', 1), ('枪手', 2), ('忍者', 1), ('护卫', 2)]",
21 | "[('骑士', 2), ('龙', 2), ('冰川', 4), ('帝国', 2), ('元素师', 3), ('护卫', 2), ('恶魔', 2)]",
22 | "[('龙', 2), ('贵族', 3), ('帝国', 2), ('护卫', 2), ('骑士', 4), ('幽灵', 2)]",
23 | "[('骑士', 2), ('龙', 2), ('浪人', 1), ('法师', 3), ('冰川', 2), ('护卫', 2), ('恶魔', 2), ('幽灵', 2)]",
24 | "[('骑士', 2), ('龙', 2), ('浪人', 1), ('冰川', 4), ('忍者', 1), ('元素师', 3), ('护卫', 2)]",
25 | "[('骑士', 2), ('贵族', 3), ('冰川', 2), ('护卫', 2), ('游侠', 4), ('幽灵', 2)]",
26 | "[('贵族', 3), ('游侠', 2), ('护卫', 2), ('骑士', 4), ('冰川', 2), ('幽灵', 2)]",
27 | "[('龙', 2), ('剑士', 3), ('浪人', 1), ('法师', 3), ('海盗', 3), ('枪手', 2), ('护卫', 2), ('恶魔', 2)]",
28 | "[('龙', 2), ('剑士', 3), ('浪人', 1), ('法师', 3), ('海克斯', 2), ('枪手', 2), ('护卫', 2)]",
29 | "[('骑士', 2), ('斗士', 2), ('龙', 2), ('法师', 3), ('虚空', 2), ('机器人', 1), ('护卫', 2), ('幽灵', 2)]",
30 | "[('恶魔', 2), ('骑士', 2), ('龙', 2), ('帝国', 2), ('忍者', 1), ('元素师', 3), ('护卫', 2), ('冰川', 2)]",
31 | "[('龙', 2), ('浪人', 1), ('法师', 3), ('忍者', 1), ('元素师', 3), ('护卫', 2), ('恶魔', 2)]",
32 | "[('骑士', 2), ('剑士', 3), ('浪人', 1), ('枪手', 2), ('忍者', 1), ('护卫', 2), ('冰川', 2), ('幽灵', 2)]",
33 | "[('骑士', 2), ('龙', 2), ('法师', 3), ('狂野', 2), ('护卫', 2), ('冰川', 2), ('幽灵', 2)]",
34 | "[('骑士', 2), ('冰川', 6), ('忍者', 1), ('元素师', 3), ('护卫', 2)]",
35 | "[('骑士', 2), ('龙', 2), ('法师', 3), ('冰川', 4), ('护卫', 2), ('幽灵', 2)]",
36 | "[('龙', 2), ('浪人', 1), ('海盗', 3), ('法师', 3), ('虚空', 2), ('枪手', 2), ('护卫', 2)]",
37 | "[('骑士', 2), ('剑士', 3), ('帝国', 2), ('枪手', 2), ('贵族', 6)]",
38 | "[('骑士', 2), ('斗士', 2), ('贵族', 3), ('冰川', 4), ('忍者', 1), ('机器人', 1), ('元素师', 3), ('护卫', 2)]",
39 | "[('骑士', 2), ('龙', 2), ('贵族', 6), ('机器人', 1), ('护卫', 2)]",
40 | "[('骑士', 2), ('龙', 2), ('法师', 3), ('虚空', 2), ('忍者', 1), ('护卫', 2), ('幽灵', 2)]",
41 | "[('龙', 2), ('浪人', 1), ('法师', 3), ('游侠', 2), ('护卫', 2), ('冰川', 2), ('幽灵', 2)]",
42 | "[('骑士', 2), ('浪人', 1), ('游侠', 2), ('贵族', 6), ('护卫', 2)]",
43 | "[('龙', 2), ('剑士', 3), ('浪人', 1), ('帝国', 2), ('枪手', 2), ('忍者', 1), ('护卫', 2)]",
44 | "[('骑士', 2), ('约德尔', 3), ('冰川', 4), ('忍者', 1), ('元素师', 3), ('护卫', 2)]",
45 | "[('骑士', 2), ('龙', 2), ('贵族', 3), ('剑士', 3), ('浪人', 1), ('帝国', 2), ('护卫', 2)]",
46 | "[('龙', 2), ('变形者', 3), ('恶魔', 4), ('忍者', 1), ('元素师', 3), ('护卫', 2), ('冰川', 2)]",
47 | "[('贵族', 3), ('冰川', 4), ('护卫', 2), ('骑士', 4), ('幽灵', 2)]",
48 | "[('骑士', 2), ('龙', 2), ('约德尔', 3), ('贵族', 3), ('枪手', 2), ('忍者', 1), ('护卫', 2)]",
49 | "[('骑士', 2), ('龙', 2), ('贵族', 3), ('剑士', 3), ('浪人', 1), ('忍者', 1), ('护卫', 2), ('幽灵', 2)]",
50 | "[('龙', 2), ('法师', 3), ('刺客', 3), ('虚空', 2), ('帝国', 2), ('护卫', 2), ('恶魔', 2)]",
51 | "[('骑士', 2), ('龙', 2), ('贵族', 3), ('变形者', 3), ('浪人', 1), ('帝国', 2), ('护卫', 2), ('恶魔', 2)]",
52 | "[('贵族', 3), ('骑士', 6), ('机器人', 1), ('护卫', 2), ('冰川', 2)]",
53 | "[('骑士', 2), ('龙', 2), ('枪手', 2), ('忍者', 1), ('护卫', 2), ('冰川', 2), ('幽灵', 2)]",
54 | "[('贵族', 3), ('剑士', 3), ('浪人', 1), ('帝国', 2), ('护卫', 2), ('骑士', 4), ('冰川', 2)]",
55 | "[('龙', 2), ('贵族', 3), ('剑士', 3), ('浪人', 1), ('海克斯', 2), ('枪手', 2), ('忍者', 1), ('护卫', 2)]",
56 | "[('龙', 2), ('剑士', 3), ('变形者', 3), ('浪人', 1), ('恶魔', 4), ('帝国', 2), ('护卫', 2)]",
57 | "[('龙', 2), ('法师', 3), ('忍者', 1), ('机器人', 1), ('元素师', 3), ('护卫', 2), ('冰川', 2)]",
58 | "[('贵族', 3), ('刺客', 3), ('帝国', 2), ('忍者', 1), ('护卫', 2), ('骑士', 4), ('冰川', 2)]",
59 | "[('贵族', 3), ('浪人', 1), ('枪手', 2), ('忍者', 1), ('护卫', 2), ('剑士', 6)]",
60 | "[('骑士', 2), ('浪人', 1), ('忍者', 1), ('贵族', 6), ('护卫', 2)]",
61 | "[('骑士', 2), ('龙', 2), ('约德尔', 3), ('法师', 3), ('帝国', 2), ('忍者', 1), ('护卫', 2), ('恶魔', 2)]",
62 | "[('龙', 2), ('变形者', 3), ('帝国', 2), ('枪手', 2), ('冰川', 2), ('护卫', 2), ('恶魔', 2)]",
63 | "[('骑士', 2), ('浪人', 1), ('枪手', 2), ('护卫', 2), ('幽灵', 2)]",
64 | "[('恶魔', 2), ('龙', 2), ('变形者', 3), ('浪人', 1), ('忍者', 1), ('元素师', 3), ('护卫', 2), ('冰川', 2)]",
65 | "[('骑士', 2), ('龙', 2), ('约德尔', 3), ('浪人', 1), ('法师', 3), ('忍者', 1), ('护卫', 2), ('冰川', 2)]",
66 | "[('龙', 2), ('约德尔', 3), ('变形者', 3), ('法师', 3), ('忍者', 1), ('护卫', 2), ('恶魔', 2)]",
67 | "[('枪手', 2), ('护卫', 2), ('贵族', 6), ('骑士', 2)]",
68 | "[('骑士', 2), ('约德尔', 3), ('贵族', 3), ('游侠', 2), ('枪手', 2), ('忍者', 1), ('护卫', 2), ('冰川', 2)]"
69 | ]
--------------------------------------------------------------------------------
/data/final_result/trait_num/final_result6.json:
--------------------------------------------------------------------------------
1 | [
2 | "[('忍者', 1), ('冰川', 2), ('刺客', 3), ('游侠', 2), ('机器人', 1), ('虚空', 2), ('斗士', 2)]",
3 | "[('虚空', 4), ('忍者', 1), ('刺客', 3), ('机器人', 1), ('斗士', 2)]",
4 | "[('恶魔', 2), ('忍者', 1), ('刺客', 3), ('机器人', 1), ('虚空', 2), ('斗士', 2)]",
5 | "[('忍者', 1), ('冰川', 2), ('刺客', 3), ('游侠', 2), ('虚空', 2), ('护卫', 2)]",
6 | "[('忍者', 1), ('贵族', 3), ('刺客', 3), ('游侠', 2), ('骑士', 2), ('虚空', 2)]",
7 | "[('恶魔', 2), ('帝国', 2), ('忍者', 1), ('刺客', 3), ('游侠', 2), ('机器人', 1)]",
8 | "[('恶魔', 2), ('元素师', 3), ('忍者', 1), ('冰川', 2), ('机器人', 1), ('斗士', 2)]",
9 | "[('冰川', 2), ('游侠', 2), ('机器人', 1), ('虚空', 2), ('斗士', 2), ('护卫', 2)]",
10 | "[('贵族', 3), ('冰川', 2), ('骑士', 2), ('机器人', 1), ('斗士', 2), ('护卫', 2)]",
11 | "[('恶魔', 2), ('游侠', 2), ('浪人', 1), ('机器人', 1), ('虚空', 2), ('斗士', 2)]",
12 | "[('忍者', 1), ('刺客', 3), ('游侠', 2), ('浪人', 1), ('机器人', 1), ('虚空', 2)]",
13 | "[('恶魔', 2), ('帝国', 2), ('剑士', 3), ('忍者', 1), ('浪人', 1), ('机器人', 1)]",
14 | "[('忍者', 1), ('冰川', 2), ('龙', 2), ('机器人', 1), ('斗士', 2), ('护卫', 2)]",
15 | "[('恶魔', 2), ('剑士', 3), ('忍者', 1), ('冰川', 2), ('游侠', 2), ('浪人', 1)]",
16 | "[('恶魔', 2), ('帝国', 2), ('骑士', 2), ('游侠', 2), ('浪人', 1), ('幽灵', 2)]",
17 | "[('剑士', 3), ('忍者', 1), ('海克斯', 2), ('浪人', 1), ('机器人', 1), ('斗士', 2)]",
18 | "[('狂野', 2), ('刺客', 3), ('游侠', 2), ('机器人', 1), ('虚空', 2), ('斗士', 2)]",
19 | "[('变形者', 3), ('恶魔', 2), ('狂野', 2), ('浪人', 1), ('机器人', 1), ('斗士', 2)]",
20 | "[('冰川', 2), ('斗士', 4), ('游侠', 2), ('机器人', 1), ('虚空', 2)]",
21 | "[('虚空', 4), ('忍者', 1), ('刺客', 3), ('游侠', 2), ('斗士', 2)]",
22 | "[('恶魔', 2), ('虚空', 4), ('刺客', 3), ('游侠', 2), ('斗士', 2)]",
23 | "[('恶魔', 2), ('帝国', 2), ('刺客', 3), ('游侠', 2), ('浪人', 1), ('虚空', 2)]",
24 | "[('变形者', 3), ('恶魔', 2), ('帝国', 2), ('狂野', 2), ('忍者', 1), ('刺客', 3)]",
25 | "[('斗士', 4), ('海克斯', 2), ('浪人', 1), ('机器人', 1), ('虚空', 2)]",
26 | "[('元素师', 3), ('冰川', 4), ('忍者', 1), ('机器人', 1), ('斗士', 2)]",
27 | "[('冰川', 2), ('骑士', 2), ('游侠', 2), ('机器人', 1), ('幽灵', 2), ('斗士', 2)]",
28 | "[('变形者', 3), ('恶魔', 2), ('帝国', 2), ('约德尔', 3), ('忍者', 1), ('骑士', 2)]",
29 | "[('恶魔', 2), ('帝国', 2), ('元素师', 3), ('忍者', 1), ('冰川', 2), ('骑士', 2)]",
30 | "[('冰川', 2), ('斗士', 4), ('机器人', 1), ('虚空', 2), ('护卫', 2)]",
31 | "[('剑士', 3), ('忍者', 1), ('贵族', 3), ('骑士', 2), ('浪人', 1), ('机器人', 1)]",
32 | "[('狂野', 2), ('斗士', 4), ('浪人', 1), ('机器人', 1), ('虚空', 2)]",
33 | "[('虚空', 4), ('忍者', 1), ('刺客', 3), ('浪人', 1), ('斗士', 2)]",
34 | "[('帝国', 2), ('忍者', 1), ('冰川', 2), ('刺客', 3), ('游侠', 2), ('骑士', 2)]"
35 | ]
--------------------------------------------------------------------------------
/data/final_result/trait_num/final_result7.json:
--------------------------------------------------------------------------------
1 | [
2 | "[('忍者', 1), ('冰川', 2), ('剑士', 3), ('海克斯', 2), ('枪手', 2), ('机器人', 1), ('斗士', 2)]",
3 | "[('骑士', 2), ('忍者', 1), ('冰川', 2), ('虚空', 2), ('刺客', 3), ('机器人', 1), ('斗士', 2)]",
4 | "[('忍者', 1), ('浪人', 1), ('冰川', 2), ('虚空', 2), ('护卫', 2), ('刺客', 3), ('游侠', 2)]",
5 | "[('斗士', 4), ('狂野', 2), ('虚空', 4), ('刺客', 3), ('机器人', 1)]",
6 | "[('游侠', 2), ('忍者', 1), ('虚空', 2), ('狂野', 2), ('刺客', 3), ('机器人', 1), ('斗士', 2)]",
7 | "[('恶魔', 2), ('忍者', 1), ('浪人', 1), ('虚空', 2), ('刺客', 3), ('机器人', 1), ('斗士', 2)]",
8 | "[('骑士', 2), ('忍者', 1), ('剑士', 3), ('帝国', 2), ('海克斯', 2), ('机器人', 1), ('斗士', 2)]",
9 | "[('恶魔', 2), ('忍者', 1), ('冰川', 2), ('帝国', 2), ('元素师', 3), ('机器人', 1), ('斗士', 2)]",
10 | "[('游侠', 2), ('浪人', 1), ('冰川', 2), ('虚空', 2), ('护卫', 2), ('机器人', 1), ('斗士', 2)]",
11 | "[('忍者', 1), ('斗士', 4), ('虚空', 4), ('刺客', 3), ('机器人', 1)]",
12 | "[('恶魔', 2), ('游侠', 2), ('浪人', 1), ('虚空', 2), ('帝国', 2), ('机器人', 1), ('斗士', 2)]",
13 | "[('恶魔', 2), ('忍者', 1), ('虚空', 2), ('帝国', 2), ('刺客', 3), ('机器人', 1), ('游侠', 2)]",
14 | "[('恶魔', 2), ('变形者', 3), ('忍者', 1), ('浪人', 1), ('龙', 2), ('剑士', 3), ('帝国', 2)]",
15 | "[('恶魔', 2), ('浪人', 1), ('剑士', 3), ('帝国', 2), ('海克斯', 2), ('机器人', 1), ('斗士', 2)]",
16 | "[('游侠', 2), ('忍者', 1), ('虚空', 4), ('刺客', 3), ('机器人', 1), ('斗士', 2)]",
17 | "[('恶魔', 2), ('变形者', 3), ('忍者', 1), ('狂野', 2), ('帝国', 2), ('刺客', 3), ('机器人', 1)]",
18 | "[('恶魔', 2), ('忍者', 1), ('浪人', 1), ('虚空', 2), ('剑士', 3), ('帝国', 2), ('刺客', 3)]",
19 | "[('忍者', 1), ('浪人', 1), ('龙', 2), ('剑士', 3), ('海克斯', 2), ('机器人', 1), ('斗士', 2)]",
20 | "[('忍者', 1), ('浪人', 1), ('冰川', 2), ('龙', 2), ('护卫', 2), ('机器人', 1), ('斗士', 2)]",
21 | "[('冰川', 2), ('虚空', 2), ('斗士', 4), ('护卫', 2), ('龙', 2), ('机器人', 1)]",
22 | "[('恶魔', 2), ('忍者', 1), ('浪人', 1), ('冰川', 2), ('剑士', 3), ('机器人', 1), ('斗士', 2)]",
23 | "[('恶魔', 2), ('游侠', 2), ('冰川', 2), ('虚空', 2), ('元素师', 3), ('机器人', 1), ('斗士', 2)]",
24 | "[('骑士', 2), ('恶魔', 2), ('浪人', 1), ('帝国', 2), ('机器人', 1), ('游侠', 2), ('幽灵', 2)]",
25 | "[('骑士', 2), ('恶魔', 2), ('变形者', 3), ('冰川', 2), ('龙', 2), ('护卫', 2), ('帝国', 2)]",
26 | "[('恶魔', 2), ('变形者', 3), ('浪人', 1), ('狂野', 2), ('帝国', 2), ('机器人', 1), ('斗士', 2)]",
27 | "[('恶魔', 2), ('海盗', 3), ('忍者', 1), ('浪人', 1), ('剑士', 3), ('枪手', 2), ('刺客', 3)]",
28 | "[('骑士', 2), ('恶魔', 2), ('忍者', 1), ('浪人', 1), ('剑士', 3), ('帝国', 2), ('机器人', 1)]",
29 | "[('恶魔', 2), ('冰川', 2), ('虚空', 2), ('斗士', 4), ('机器人', 1), ('游侠', 2)]",
30 | "[('恶魔', 2), ('法师', 3), ('虚空', 2), ('斗士', 2), ('狂野', 2), ('机器人', 1), ('游侠', 2)]",
31 | "[('恶魔', 2), ('忍者', 1), ('浪人', 1), ('冰川', 2), ('元素师', 3), ('机器人', 1), ('游侠', 2)]",
32 | "[('恶魔', 2), ('忍者', 1), ('冰川', 2), ('虚空', 2), ('刺客', 3), ('元素师', 3), ('游侠', 2)]",
33 | "[('恶魔', 2), ('游侠', 2), ('帝国', 2), ('虚空', 4), ('刺客', 3), ('斗士', 2)]",
34 | "[('恶魔', 2), ('变形者', 3), ('冰川', 2), ('龙', 2), ('护卫', 2), ('机器人', 1), ('斗士', 2)]",
35 | "[('骑士', 2), ('恶魔', 2), ('变形者', 3), ('忍者', 1), ('浪人', 1), ('帝国', 2), ('约德尔', 3)]",
36 | "[('恶魔', 2), ('变形者', 3), ('虚空', 2), ('斗士', 4), ('狂野', 2), ('机器人', 1)]",
37 | "[('骑士', 2), ('恶魔', 2), ('忍者', 1), ('浪人', 1), ('冰川', 2), ('帝国', 2), ('元素师', 3)]"
38 | ]
--------------------------------------------------------------------------------
/data/final_result/trait_num/final_result8.json:
--------------------------------------------------------------------------------
1 | [
2 | "[('斗士', 4), ('刺客', 3), ('忍者', 1), ('机器人', 1), ('冰川', 2), ('游侠', 2), ('虚空', 4)]",
3 | "[('刺客', 3), ('虚空', 2), ('忍者', 1), ('骑士', 2), ('帝国', 2), ('冰川', 2), ('机器人', 1), ('斗士', 2)]",
4 | "[('狂野', 2), ('斗士', 4), ('刺客', 3), ('忍者', 1), ('机器人', 1), ('虚空', 4)]",
5 | "[('刺客', 3), ('浪人', 1), ('忍者', 1), ('机器人', 1), ('虚空', 2), ('游侠', 2), ('恶魔', 2), ('斗士', 2)]",
6 | "[('变形者', 3), ('狂野', 2), ('剑士', 3), ('浪人', 1), ('忍者', 1), ('机器人', 1), ('恶魔', 2), ('斗士', 2)]",
7 | "[('冰川', 4), ('元素师', 3), ('忍者', 1), ('机器人', 1), ('游侠', 2), ('恶魔', 2), ('斗士', 2)]",
8 | "[('刺客', 3), ('机器人', 1), ('帝国', 2), ('游侠', 2), ('虚空', 4), ('恶魔', 2), ('斗士', 2)]",
9 | "[('刺客', 3), ('浪人', 1), ('忍者', 1), ('游侠', 2), ('虚空', 4), ('恶魔', 2), ('斗士', 2)]",
10 | "[('幽灵', 2), ('剑士', 3), ('浪人', 1), ('骑士', 2), ('忍者', 1), ('帝国', 2), ('游侠', 2), ('恶魔', 2)]",
11 | "[('变形者', 3), ('护卫', 2), ('骑士', 2), ('忍者', 1), ('龙', 2), ('帝国', 2), ('冰川', 2), ('恶魔', 2)]",
12 | "[('剑士', 3), ('浪人', 1), ('忍者', 1), ('帝国', 2), ('冰川', 2), ('机器人', 1), ('恶魔', 2), ('斗士', 2)]",
13 | "[('刺客', 3), ('贵族', 3), ('骑士', 2), ('忍者', 1), ('游侠', 2), ('虚空', 4), ('斗士', 2)]",
14 | "[('忍者', 1), ('法师', 3), ('机器人', 1), ('冰川', 2), ('约德尔', 3), ('游侠', 2), ('恶魔', 2), ('斗士', 2)]",
15 | "[('刺客', 3), ('元素师', 3), ('浪人', 1), ('忍者', 1), ('冰川', 2), ('虚空', 2), ('游侠', 2), ('恶魔', 2)]",
16 | "[('元素师', 3), ('虚空', 2), ('忍者', 1), ('冰川', 2), ('机器人', 1), ('游侠', 2), ('恶魔', 2), ('斗士', 2)]",
17 | "[('刺客', 3), ('浪人', 1), ('骑士', 2), ('忍者', 1), ('帝国', 2), ('虚空', 2), ('游侠', 2), ('恶魔', 2)]",
18 | "[('变形者', 3), ('护卫', 2), ('忍者', 1), ('龙', 2), ('冰川', 2), ('机器人', 1), ('恶魔', 2), ('斗士', 2)]",
19 | "[('变形者', 3), ('狂野', 2), ('刺客', 3), ('浪人', 1), ('忍者', 1), ('帝国', 2), ('机器人', 1), ('恶魔', 2)]",
20 | "[('变形者', 3), ('狂野', 2), ('刺客', 3), ('虚空', 2), ('帝国', 2), ('机器人', 1), ('恶魔', 2), ('斗士', 2)]",
21 | "[('枪手', 2), ('刺客', 3), ('剑士', 3), ('浪人', 1), ('忍者', 1), ('海盗', 3), ('机器人', 1), ('恶魔', 2)]",
22 | "[('刺客', 3), ('游侠', 4), ('虚空', 2), ('忍者', 1), ('机器人', 1), ('冰川', 2), ('斗士', 2)]",
23 | "[('变形者', 3), ('狂野', 2), ('斗士', 4), ('虚空', 2), ('机器人', 1), ('帝国', 2), ('恶魔', 2)]",
24 | "[('变形者', 3), ('狂野', 2), ('骑士', 2), ('机器人', 1), ('帝国', 2), ('约德尔', 3), ('恶魔', 2), ('斗士', 2)]",
25 | "[('剑士', 3), ('海克斯', 2), ('骑士', 2), ('忍者', 1), ('帝国', 2), ('冰川', 2), ('机器人', 1), ('斗士', 2)]",
26 | "[('狂野', 2), ('浪人', 1), ('法师', 3), ('机器人', 1), ('虚空', 2), ('游侠', 2), ('恶魔', 2), ('斗士', 2)]",
27 | "[('刺客', 3), ('剑士', 3), ('浪人', 1), ('恶魔', 4), ('忍者', 1), ('帝国', 2), ('游侠', 2)]",
28 | "[('枪手', 2), ('剑士', 3), ('海克斯', 2), ('忍者', 1), ('机器人', 1), ('冰川', 2), ('游侠', 2), ('斗士', 2)]",
29 | "[('变形者', 3), ('剑士', 3), ('浪人', 1), ('忍者', 1), ('龙', 2), ('帝国', 2), ('机器人', 1), ('恶魔', 2)]",
30 | "[('变形者', 3), ('剑士', 3), ('浪人', 1), ('海克斯', 2), ('帝国', 2), ('机器人', 1), ('恶魔', 2), ('斗士', 2)]",
31 | "[('变形者', 3), ('浪人', 1), ('骑士', 2), ('忍者', 1), ('机器人', 1), ('帝国', 2), ('约德尔', 3), ('恶魔', 2)]",
32 | "[('刺客', 3), ('剑士', 3), ('浪人', 1), ('虚空', 2), ('帝国', 2), ('机器人', 1), ('恶魔', 2), ('斗士', 2)]"
33 | ]
--------------------------------------------------------------------------------
/data/final_result/trait_num/final_result9.json:
--------------------------------------------------------------------------------
1 | [
2 | "[('剑士', 3), ('贵族', 3), ('斗士', 2), ('机器人', 1), ('忍者', 1), ('骑士', 4), ('帝国', 2), ('冰川', 2)]",
3 | "[('斗士', 4), ('骑士', 2), ('机器人', 1), ('忍者', 1), ('虚空', 4), ('刺客', 3), ('冰川', 2)]",
4 | "[('斗士', 4), ('海克斯', 2), ('机器人', 1), ('忍者', 1), ('游侠', 2), ('虚空', 4), ('刺客', 3)]",
5 | "[('恶魔', 2), ('斗士', 2), ('元素师', 3), ('机器人', 1), ('浪人', 1), ('忍者', 1), ('冰川', 4), ('游侠', 2)]",
6 | "[('恶魔', 2), ('刺客', 3), ('虚空', 2), ('斗士', 2), ('机器人', 1), ('浪人', 1), ('忍者', 1), ('游侠', 2), ('帝国', 2)]",
7 | "[('贵族', 3), ('斗士', 2), ('机器人', 1), ('枪手', 2), ('忍者', 1), ('骑士', 4), ('约德尔', 3), ('冰川', 2)]",
8 | "[('斗士', 4), ('法师', 3), ('恶魔', 2), ('虚空', 2), ('狂野', 2), ('机器人', 1), ('游侠', 2), ('冰川', 2)]",
9 | "[('恶魔', 2), ('元素师', 3), ('斗士', 2), ('忍者', 1), ('游侠', 2), ('虚空', 4), ('刺客', 3), ('冰川', 2)]",
10 | "[('剑士', 3), ('恶魔', 2), ('骑士', 2), ('机器人', 1), ('浪人', 1), ('忍者', 1), ('幽灵', 2), ('游侠', 2), ('帝国', 2)]",
11 | "[('剑士', 3), ('骑士', 2), ('海克斯', 2), ('斗士', 2), ('机器人', 1), ('忍者', 1), ('游侠', 2), ('帝国', 2), ('冰川', 2)]",
12 | "[('骑士', 2), ('贵族', 3), ('虚空', 2), ('斗士', 2), ('机器人', 1), ('忍者', 1), ('游侠', 2), ('刺客', 3), ('冰川', 2)]",
13 | "[('斗士', 4), ('恶魔', 2), ('狂野', 2), ('机器人', 1), ('游侠', 2), ('虚空', 4), ('刺客', 3)]",
14 | "[('法师', 3), ('恶魔', 2), ('狂野', 2), ('机器人', 1), ('斗士', 2), ('游侠', 2), ('护卫', 2), ('龙', 2), ('冰川', 2)]",
15 | "[('斗士', 4), ('骑士', 2), ('刺客', 3), ('虚空', 2), ('机器人', 1), ('忍者', 1), ('帝国', 2), ('冰川', 2)]",
16 | "[('剑士', 3), ('刺客', 3), ('虚空', 2), ('浪人', 1), ('忍者', 1), ('游侠', 2), ('帝国', 2), ('恶魔', 4)]",
17 | "[('恶魔', 2), ('虚空', 2), ('机器人', 1), ('斗士', 2), ('变形者', 3), ('狂野', 4), ('游侠', 2), ('刺客', 3)]",
18 | "[('剑士', 3), ('斗士', 2), ('机器人', 1), ('浪人', 1), ('游侠', 2), ('帝国', 2), ('冰川', 2), ('恶魔', 4)]",
19 | "[('剑士', 3), ('恶魔', 2), ('海克斯', 2), ('斗士', 2), ('机器人', 1), ('枪手', 2), ('忍者', 1), ('游侠', 2), ('冰川', 2)]",
20 | "[('恶魔', 2), ('斗士', 2), ('机器人', 1), ('忍者', 1), ('游侠', 2), ('护卫', 2), ('刺客', 3), ('冰川', 2), ('龙', 2)]",
21 | "[('剑士', 3), ('恶魔', 2), ('斗士', 2), ('浪人', 1), ('忍者', 1), ('游侠', 2), ('虚空', 4), ('刺客', 3)]",
22 | "[('剑士', 3), ('恶魔', 2), ('海克斯', 2), ('元素师', 3), ('斗士', 2), ('机器人', 1), ('浪人', 1), ('忍者', 1), ('冰川', 2)]",
23 | "[('恶魔', 2), ('虚空', 2), ('狂野', 2), ('斗士', 2), ('元素师', 3), ('机器人', 1), ('游侠', 2), ('刺客', 3), ('冰川', 2)]",
24 | "[('剑士', 3), ('虚空', 2), ('斗士', 2), ('机器人', 1), ('浪人', 1), ('忍者', 1), ('游侠', 2), ('恶魔', 4)]",
25 | "[('剑士', 3), ('狂野', 2), ('斗士', 2), ('变形者', 3), ('机器人', 1), ('浪人', 1), ('忍者', 1), ('恶魔', 4)]",
26 | "[('恶魔', 2), ('虚空', 2), ('斗士', 2), ('机器人', 1), ('游侠', 4), ('忍者', 1), ('刺客', 3), ('冰川', 2)]",
27 | "[('法师', 3), ('恶魔', 2), ('斗士', 2), ('机器人', 1), ('忍者', 1), ('游侠', 2), ('虚空', 4), ('刺客', 3)]",
28 | "[('剑士', 3), ('恶魔', 2), ('虚空', 2), ('狂野', 2), ('机器人', 1), ('斗士', 2), ('浪人', 1), ('游侠', 2), ('刺客', 3)]",
29 | "[('骑士', 2), ('恶魔', 2), ('斗士', 2), ('元素师', 3), ('机器人', 1), ('冰川', 4), ('幽灵', 2), ('游侠', 2)]",
30 | "[('剑士', 3), ('恶魔', 2), ('骑士', 2), ('贵族', 3), ('枪手', 2), ('浪人', 1), ('忍者', 1), ('游侠', 2), ('帝国', 2)]",
31 | "[('骑士', 2), ('恶魔', 2), ('刺客', 3), ('斗士', 2), ('忍者', 1), ('游侠', 2), ('虚空', 4), ('帝国', 2)]",
32 | "[('剑士', 3), ('骑士', 2), ('浪人', 1), ('忍者', 1), ('游侠', 2), ('帝国', 2), ('冰川', 2), ('恶魔', 4)]",
33 | "[('剑士', 3), ('恶魔', 2), ('骑士', 2), ('贵族', 3), ('虚空', 2), ('浪人', 1), ('忍者', 1), ('游侠', 2), ('刺客', 3)]",
34 | "[('恶魔', 2), ('虚空', 2), ('元素师', 3), ('机器人', 1), ('浪人', 1), ('忍者', 1), ('游侠', 2), ('刺客', 3), ('冰川', 2)]",
35 | "[('斗士', 4), ('恶魔', 2), ('虚空', 2), ('机器人', 1), ('元素师', 3), ('冰川', 4), ('游侠', 2)]",
36 | "[('骑士', 2), ('恶魔', 2), ('贵族', 3), ('斗士', 2), ('元素师', 3), ('机器人', 1), ('忍者', 1), ('游侠', 2), ('冰川', 2)]",
37 | "[('剑士', 3), ('恶魔', 2), ('浪人', 1), ('忍者', 1), ('游侠', 2), ('护卫', 2), ('帝国', 2), ('冰川', 2), ('龙', 2)]",
38 | "[('剑士', 3), ('恶魔', 2), ('骑士', 2), ('海克斯', 2), ('斗士', 2), ('机器人', 1), ('浪人', 1), ('忍者', 1), ('帝国', 2)]"
39 | ]
--------------------------------------------------------------------------------
/data/language.json:
--------------------------------------------------------------------------------
1 | {
2 | "demon": "恶魔",
3 | "imperial": "帝国",
4 | "dragon": "龙",
5 | "exile": "浪人",
6 | "glacial": "冰川",
7 | "robot": "机器人",
8 | "noble": "贵族",
9 | "ninja": "忍者",
10 | "yordle": "约德尔",
11 | "pirate": "海盗",
12 | "phantom": "幽灵",
13 | "wild": "狂野",
14 | "void": "虚空",
15 | "Hextech": "海克斯",
16 | "ranger": "游侠",
17 | "shapeshifter": "变形者",
18 | "sorcerer": "法师",
19 | "assassin": "刺客",
20 | "blademaster": "剑士",
21 | "elementalist": "元素师",
22 | "guardian": "护卫",
23 | "brawler": "斗士",
24 | "knight": "骑士",
25 | "gunslinger": "枪手",
26 | "Varus": "维鲁斯",
27 | "Elise": "蜘蛛",
28 | "Morgana": "莫甘娜",
29 | "Evelynn": "寡妇",
30 | "Aatrox": "剑魔",
31 | "Brand": "火男",
32 | "Swain": "乌鸦",
33 | "Shyvana": "龙女",
34 | "Aurelion Sol": "龙王",
35 | "Pantheon": "潘森",
36 | "Yasuo": "亚索",
37 | "Braum": "布隆",
38 | "Lissandra": "丽桑卓",
39 | "Ashe": "艾希",
40 | "Volibear": "狗熊",
41 | "Sejuani": "猪妹",
42 | "Anivia": "冰鸟",
43 | "Blitzcrank": "机器人",
44 | "Darius": "诺手",
45 | "Katarina": "卡特",
46 | "Draven": "德莱文",
47 | "Fiora": "剑姬",
48 | "Garen": "盖伦",
49 | "Vayne": "薇恩",
50 | "Lucian": "卢锡安",
51 | "Leona": "日女",
52 | "Kayle": "天使",
53 | "Shen": "慎",
54 | "Zed": "劫",
55 | "Kennen": "凯南",
56 | "Akali": "阿卡丽",
57 | "Graves": "男枪",
58 | "Pyke": "派克",
59 | "Twist Fate": "卡牌",
60 | "Gangplank": "船长",
61 | "Miss Fortune": "好运姐",
62 | "Mordekaiser": "铁男",
63 | "Kindred": "千珏",
64 | "Karthus": "死歌",
65 | "Warwick": "狼人",
66 | "Nidalee": "豹女",
67 | "Ahri": "狐狸",
68 | "Rengar": "狮子狗",
69 | "Gnar": "纳尔",
70 | "Kha'Zix": "螳螂",
71 | "Kassadin": "卡萨丁",
72 | "Rek'Sai": "挖掘机",
73 | "Cho'Gath": "大虫子",
74 | "Kaisa": "卡萨",
75 | "Tristana": "小炮",
76 | "Lulu": "露露",
77 | "Poppy": "波比",
78 | "Veigar": "小法",
79 | "Camille": "卡密尔",
80 | "jayce": "杰斯",
81 | "VI": "蔚",
82 | "Jinx": "金克斯"
83 | }
--------------------------------------------------------------------------------
/data/trait_graph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_graph.png
--------------------------------------------------------------------------------
/data/trait_icons/Assassin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Assassin.png
--------------------------------------------------------------------------------
/data/trait_icons/Blademaster.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Blademaster.png
--------------------------------------------------------------------------------
/data/trait_icons/Brawler.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Brawler.png
--------------------------------------------------------------------------------
/data/trait_icons/Demon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Demon.png
--------------------------------------------------------------------------------
/data/trait_icons/Dragon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Dragon.png
--------------------------------------------------------------------------------
/data/trait_icons/Elementalist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Elementalist.png
--------------------------------------------------------------------------------
/data/trait_icons/Exile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Exile.png
--------------------------------------------------------------------------------
/data/trait_icons/Glacial.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Glacial.png
--------------------------------------------------------------------------------
/data/trait_icons/Guardian.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Guardian.png
--------------------------------------------------------------------------------
/data/trait_icons/Gunslinger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Gunslinger.png
--------------------------------------------------------------------------------
/data/trait_icons/Hextech.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Hextech.png
--------------------------------------------------------------------------------
/data/trait_icons/Imperial.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Imperial.png
--------------------------------------------------------------------------------
/data/trait_icons/Knight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Knight.png
--------------------------------------------------------------------------------
/data/trait_icons/Ninja.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Ninja.png
--------------------------------------------------------------------------------
/data/trait_icons/Noble.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Noble.png
--------------------------------------------------------------------------------
/data/trait_icons/Phantom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Phantom.png
--------------------------------------------------------------------------------
/data/trait_icons/Pirate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Pirate.png
--------------------------------------------------------------------------------
/data/trait_icons/Ranger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Ranger.png
--------------------------------------------------------------------------------
/data/trait_icons/Robot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Robot.png
--------------------------------------------------------------------------------
/data/trait_icons/Shapeshifter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Shapeshifter.png
--------------------------------------------------------------------------------
/data/trait_icons/Sorcerer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Sorcerer.png
--------------------------------------------------------------------------------
/data/trait_icons/Void.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Void.png
--------------------------------------------------------------------------------
/data/trait_icons/Wild.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Wild.png
--------------------------------------------------------------------------------
/data/trait_icons/Yordle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/weiziyoung/TFT/5f4448dccc2afcd75c52de39e603ef066c7c4166/data/trait_icons/Yordle.png
--------------------------------------------------------------------------------
/data/traits.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "demon",
4 | "bonus_num": [
5 | 2,
6 | 4,
7 | 6
8 | ],
9 | "scope": [
10 | 2,
11 | 2,
12 | 2
13 | ],
14 | "strength": [
15 | 1.2,
16 | 1.52,
17 | 1.66
18 | ],
19 | "champions": [
20 | "Varus",
21 | "Elise",
22 | "Morgana",
23 | "Evelynn",
24 | "Aatrox",
25 | "Brand",
26 | "Swain"
27 | ]
28 | },
29 | {
30 | "name": "imperial",
31 | "bonus_num": [
32 | 2,
33 | 4
34 | ],
35 | "scope": [
36 | 1,
37 | 2
38 | ],
39 | "strength": [
40 | 1.7,
41 | 1.7
42 | ],
43 | "champions": [
44 | "Swain",
45 | "Darius",
46 | "Katarina",
47 | "Draven"
48 | ]
49 | },
50 | {
51 | "name": "dragon",
52 | "bonus_num": [
53 | 2
54 | ],
55 | "scope": [
56 | 2
57 | ],
58 | "strength": [
59 | 1.8
60 | ],
61 | "champions": [
62 | "Shyvana",
63 | "Aurelion Sol",
64 | "Pantheon"
65 | ]
66 | },
67 | {
68 | "name": "exile",
69 | "bonus_num": [
70 | 1
71 | ],
72 | "scope": [
73 | 1
74 | ],
75 | "strength": [
76 | 1.6
77 | ],
78 | "champions": [
79 | "Yasuo"
80 | ]
81 | },
82 | {
83 | "name": "glacial",
84 | "bonus_num": [
85 | 2,
86 | 4,
87 | 6
88 | ],
89 | "scope": [
90 | 2,
91 | 2,
92 | 2
93 | ],
94 | "strength": [
95 | 1.3,
96 | 1.45,
97 | 1.67
98 | ],
99 | "champions": [
100 | "Braum",
101 | "Lissandra",
102 | "Ashe",
103 | "Volibear",
104 | "Sejuani",
105 | "Anivia"
106 | ]
107 | },
108 | {
109 | "name": "robot",
110 | "bonus_num": [
111 | 1
112 | ],
113 | "scope": [
114 | 1
115 | ],
116 | "strength": [
117 | 1.7
118 | ],
119 | "champions": [
120 | "Blitzcrank"
121 | ]
122 | },
123 | {
124 | "name": "noble",
125 | "bonus_num": [
126 | 3,
127 | 6
128 | ],
129 | "scope": [
130 | 1,
131 | 3
132 | ],
133 | "strength": [
134 | 1.8,
135 | 1.8
136 | ],
137 | "champions": [
138 | "Fiora",
139 | "Garen",
140 | "Vayne",
141 | "Lucian",
142 | "Leona",
143 | "Kayle"
144 | ]
145 | },
146 | {
147 | "name": "ninja",
148 | "bonus_num": [
149 | 1,
150 | 4
151 | ],
152 | "scope": [
153 | 1,
154 | 2
155 | ],
156 | "strength": [
157 | 1.4,
158 | 1.75
159 | ],
160 | "champions": [
161 | "Shen",
162 | "Zed",
163 | "Kennen",
164 | "Akali"
165 | ]
166 | },
167 | {
168 | "name": "yordle",
169 | "bonus_num": [
170 | 3,
171 | 6,
172 | 9
173 | ],
174 | "scope": [
175 | 2,
176 | 2,
177 | 2
178 | ],
179 | "strength": [
180 | 1.4,
181 | 1.86,
182 | 2.5
183 | ],
184 | "champions": [
185 | "Kennen",
186 | "Gnar",
187 | "Tristana",
188 | "Lulu",
189 | "Poppy",
190 | "Veigar"
191 | ]
192 | },
193 | {
194 | "name": "pirate",
195 | "bonus_num": [
196 | 3
197 | ],
198 | "scope": [
199 | 1
200 | ],
201 | "strength": [
202 | 1
203 | ],
204 | "champions": [
205 | "Graves",
206 | "Pyke",
207 | "Twist Fate",
208 | "Gangplank",
209 | "Miss Fortune"
210 | ]
211 | },
212 | {
213 | "name": "phantom",
214 | "bonus_num": [
215 | 2
216 | ],
217 | "scope": [
218 | 1
219 | ],
220 | "strength": [
221 | 2
222 | ],
223 | "champions": [
224 | "Mordekaiser",
225 | "Kindred",
226 | "Karthus"
227 | ]
228 | },
229 | {
230 | "name": "wild",
231 | "bonus_num": [
232 | 2,
233 | 4
234 | ],
235 | "scope": [
236 | 2,
237 | 3
238 | ],
239 | "strength": [
240 | 1.2,
241 | 1.2
242 | ],
243 | "champions": [
244 | "Warwick",
245 | "Nidalee",
246 | "Ahri",
247 | "Rengar",
248 | "Gnar"
249 | ]
250 | },
251 | {
252 | "name": "void",
253 | "bonus_num": [
254 | 2,
255 | 4
256 | ],
257 | "scope": [
258 | 1,
259 | 2
260 | ],
261 | "strength": [
262 | 1.6,
263 | 1.6
264 | ],
265 | "champions": [
266 | "Kha'Zix",
267 | "Kassadin",
268 | "Rek'Sai",
269 | "Cho'Gath",
270 | "Kaisa"
271 | ]
272 | },
273 | {
274 | "name": "Hextech",
275 | "bonus_num": [
276 | 2,
277 | 4
278 | ],
279 | "scope": [
280 | 1,
281 | 2
282 | ],
283 | "strength": [
284 | 1.5,
285 | 1.5
286 | ],
287 | "champions": [
288 | "Camille",
289 | "VI",
290 | "Jinx"
291 | ]
292 | },
293 | {
294 | "name": "ranger",
295 | "bonus_num": [
296 | 2,
297 | 4
298 | ],
299 | "scope": [
300 | 2,
301 | 2
302 | ],
303 | "strength": [
304 | 1.25,
305 | 1.65
306 | ],
307 | "champions": [
308 | "Varus",
309 | "Ashe",
310 | "Vayne",
311 | "Kindred",
312 | "Kaisa"
313 | ]
314 | },
315 | {
316 | "name": "shapeshifter",
317 | "bonus_num": [
318 | 3,
319 | 6
320 | ],
321 | "scope": [
322 | 2,
323 | 2
324 | ],
325 | "strength": [
326 | 1.4,
327 | 1.8
328 | ],
329 | "champions": [
330 | "Elise",
331 | "Swain",
332 | "Shyvana",
333 | "Nidalee",
334 | "Gnar"
335 | ]
336 | },
337 | {
338 | "name": "sorcerer",
339 | "bonus_num": [
340 | 3,
341 | 6,
342 | 9
343 | ],
344 | "scope": [
345 | 3,
346 | 3,
347 | 3
348 | ],
349 | "strength": [
350 | 1.25,
351 | 1.61,
352 | 2.1
353 | ],
354 | "champions": [
355 | "Morgana",
356 | "Aurelion Sol",
357 | "Twist Fate",
358 | "Karthus",
359 | "Ahri",
360 | "Kassadin",
361 | "Lulu",
362 | "Veigar"
363 | ]
364 | },
365 | {
366 | "name": "assassin",
367 | "bonus_num": [
368 | 3,
369 | 6,
370 | 9
371 | ],
372 | "scope": [
373 | 2,
374 | 2,
375 | 2
376 | ],
377 | "strength": [
378 | 1.4,
379 | 2,
380 | 2.2
381 | ],
382 | "champions": [
383 | "Evelynn",
384 | "Katarina",
385 | "Zed",
386 | "Akali",
387 | "Pyke",
388 | "Rengar",
389 | "Kha'Zix",
390 | "Kaisa"
391 | ]
392 | },
393 | {
394 | "name": "blademaster",
395 | "bonus_num": [
396 | 3,
397 | 6,
398 | 9
399 | ],
400 | "scope": [
401 | 2,
402 | 2,
403 | 2
404 | ],
405 | "strength": [
406 | 1.3,
407 | 1.6,
408 | 2.2
409 | ],
410 | "champions": [
411 | "Aatrox",
412 | "Yasuo",
413 | "Draven",
414 | "Fiora",
415 | "Shen",
416 | "Gangplank",
417 | "Camille"
418 | ]
419 | },
420 | {
421 | "name": "elementalist",
422 | "bonus_num": [
423 | 3
424 | ],
425 | "scope": [
426 | 1
427 | ],
428 | "strength": [
429 | 2
430 | ],
431 | "champions": [
432 | "Brand",
433 | "Lissandra",
434 | "Anivia",
435 | "Kennen"
436 | ]
437 | },
438 | {
439 | "name": "guardian",
440 | "bonus_num": [
441 | 2
442 | ],
443 | "scope": [
444 | 4
445 | ],
446 | "strength": [
447 | 1.5
448 | ],
449 | "champions": [
450 | "Pantheon",
451 | "Braum",
452 | "Leona"
453 | ]
454 | },
455 | {
456 | "name": "brawler",
457 | "bonus_num": [
458 | 2,
459 | 4,
460 | 6
461 | ],
462 | "scope": [
463 | 2,
464 | 2,
465 | 2
466 | ],
467 | "strength": [
468 | 1.2,
469 | 1.4,
470 | 1.7
471 | ],
472 | "champions": [
473 | "Volibear",
474 | "Blitzcrank",
475 | "Warwick",
476 | "Rek'Sai",
477 | "Cho'Gath",
478 | "VI"
479 | ]
480 | },
481 | {
482 | "name": "knight",
483 | "bonus_num": [
484 | 2,
485 | 4,
486 | 6
487 | ],
488 | "scope": [
489 | 3,
490 | 3,
491 | 3
492 | ],
493 | "strength": [
494 | 1.15,
495 | 1.35,
496 | 1.85
497 | ],
498 | "champions": [
499 | "Sejuani",
500 | "Darius",
501 | "Garen",
502 | "Kayle",
503 | "Mordekaiser",
504 | "Poppy"
505 | ]
506 | },
507 | {
508 | "name": "gunslinger",
509 | "bonus_num": [
510 | 2,
511 | 4,
512 | 6
513 | ],
514 | "scope": [
515 | 3,
516 | 3,
517 | 3
518 | ],
519 | "strength": [
520 | 1.3,
521 | 1.6,
522 | 1.9
523 | ],
524 | "champions": [
525 | "Sejuani",
526 | "Darius",
527 | "Garen",
528 | "Kayle",
529 | "Mordekaiser",
530 | "Poppy"
531 | ]
532 | }
533 | ]
--------------------------------------------------------------------------------
/evaluate/evaluation.go:
--------------------------------------------------------------------------------
1 | package evaluate
2 |
3 | import (
4 | "TFT/globals"
5 | "TFT/models"
6 | "TFT/utils"
7 | "math"
8 | )
9 |
10 | // Evaluate 评估当前组合的羁绊数量、单位收益羁绊总数、羁绊强度
11 | func Evaluate(combo []models.ChampionDict) models.ComboMetric {
12 | var traitDetail = make(map[string]int)
13 |
14 | comboName := make([]string, 0, len(combo))
15 | traitNum := 0
16 | totalTraitNum := 0
17 | totalTraitStrength := float32(0.0)
18 |
19 | // 初始化英雄强度向量
20 | unitsStrength := make([]float64, len(combo), len(combo))
21 | traitChampionsDict := make(map[string][]int)
22 | for index, unit := range combo {
23 | comboName = append(comboName, unit.Name)
24 | unitStrength := math.Pow(globals.Global.GainLevel, float64(unit.Price-1))
25 | unitsStrength[index] = unitStrength
26 | for _, origin := range unit.Origin {
27 | traitChampionsDict[origin] = append(traitChampionsDict[origin], index)
28 | }
29 | for _, class := range unit.Class {
30 | traitChampionsDict[class] = append(traitChampionsDict[class], index)
31 | }
32 | }
33 |
34 | for trait, champions := range traitChampionsDict {
35 | num := len(champions)
36 | bonusRequirement := globals.TraitDict[trait].BonusNum
37 | var bonusLevel = len(bonusRequirement)
38 | for index, requirement := range bonusRequirement {
39 | if requirement > num {
40 | bonusLevel = index
41 | break
42 | }
43 | }
44 |
45 | // 忍者只有在1只和4只时触发,其他不触发
46 | if trait == "ninja" && 1 < num && num < 4 {
47 | bonusLevel = 0
48 | }
49 | if bonusLevel > 0 {
50 | traitDetail[trait] = bonusRequirement[bonusLevel-1]
51 | bonusScope := globals.TraitDict[trait].Scope[bonusLevel-1]
52 | traitNum += bonusLevel
53 | bonusStrength := globals.TraitDict[trait].Strength[bonusLevel-1]
54 | benefitedNum := 0
55 | switch bonusScope {
56 | case 1:
57 | {
58 | benefitedNum = 1 // 单体Buff,例如 机器人、浪人、三贵族、双帝国
59 | for _, champion := range champions {
60 | unitsStrength[champion] *= float64(bonusStrength)
61 | }
62 | }
63 | case 2:
64 | {
65 | benefitedNum = num // 对同一种族的Buff,大多数羁绊都是这种
66 | for _, champion := range champions {
67 | unitsStrength[champion] *= float64(bonusStrength)
68 | }
69 | }
70 | case 3:
71 | {
72 | benefitedNum = len(combo) // 群体Buff,如骑士、六贵族、四帝国
73 | for index, _ := range unitsStrength {
74 | unitsStrength[index] *= float64(bonusStrength)
75 | }
76 | }
77 | case 4:
78 | {
79 | benefitedNum = len(combo) - 2 // 护卫Buff,比较特殊,除护卫本身外,其他均能吃到buff
80 | for index, _ := range unitsStrength {
81 | isGuard := false
82 | for _, champion := range champions {
83 | if index == champion {
84 | isGuard = true
85 | break
86 | }
87 | }
88 | if !isGuard {
89 | unitsStrength[index] *= float64(bonusStrength)
90 | }
91 | }
92 | }
93 | }
94 | totalTraitNum += bonusLevel * benefitedNum
95 | totalTraitStrength += float32(benefitedNum) * bonusStrength
96 | }
97 | }
98 | metric := models.ComboMetric{
99 | Combo: comboName,
100 | TraitNum: traitNum,
101 | TotalTraitNum: totalTraitNum,
102 | TraitDetail: traitDetail,
103 | TotalTraitStrength: totalTraitStrength,
104 | TotalStrength: utils.Sum(unitsStrength),
105 | }
106 | return metric
107 | }
108 |
--------------------------------------------------------------------------------
/globals/global.go:
--------------------------------------------------------------------------------
1 | package globals
2 |
3 | import (
4 | "TFT/models"
5 | "encoding/json"
6 | "github.com/go-yaml/yaml"
7 | "github.com/schollz/progressbar"
8 | "io/ioutil"
9 | "os"
10 | )
11 |
12 | var (
13 | traitList models.TraitList
14 | ChampionList models.ChampionList
15 | OneTraitChampionNameList []string
16 | TraitDict map[string]models.Trait
17 | ChampionDict map[string]models.Champion
18 | TranslateDict map[string]string
19 | Bar *progressbar.ProgressBar
20 | Counter int64
21 | Global GlobalStruct
22 | )
23 |
24 | type GlobalStruct struct {
25 | TraitPath string `yaml:"trait_path"`
26 | ChampionPath string `yaml:"champion_path"`
27 | LanguagePath string `yaml:"language_path"`
28 | OutPutPath string `yaml:"output_path"`
29 | GainLevel float64 `yaml:"gain_level"`
30 | MaximumHeap int `yaml:"maximum_heap"`
31 | Evaluation string `yaml:"evaluation"`
32 | }
33 |
34 | func init() {
35 | // 读取配置文件
36 | content, _ := ioutil.ReadFile("config/app.yaml")
37 | err := yaml.Unmarshal(content, &Global)
38 | // Init traits file
39 | traitsFile, err := os.Open(Global.TraitPath)
40 | if err != nil {
41 | panic("Open traits file fail!")
42 | }
43 | Counter = 0
44 | jsonParser := json.NewDecoder(traitsFile)
45 | if err = jsonParser.Decode(&traitList); err != nil {
46 | panic(err.Error())
47 | }
48 | TraitDict = make(map[string]models.Trait)
49 | for _, trait := range traitList {
50 | TraitDict[trait.Name] = models.Trait{
51 | BonusNum: trait.BonusNum,
52 | Scope: trait.Scope,
53 | Champions: trait.Champions,
54 | Strength: trait.Strength,
55 | }
56 | }
57 | // Init champion file
58 | championFile, err := os.Open(Global.ChampionPath)
59 | if err != nil {
60 | panic("Open champion file fail!")
61 | }
62 | jsonParser = json.NewDecoder(championFile)
63 | if err = jsonParser.Decode(&ChampionList); err != nil {
64 | panic(err.Error())
65 | }
66 |
67 | translateFile, err := os.Open(Global.LanguagePath)
68 | if err != nil {
69 | panic("Open language file fail")
70 | }
71 | jsonParser = json.NewDecoder(translateFile)
72 | if err = jsonParser.Decode(&TranslateDict); err != nil {
73 | panic(err.Error())
74 | }
75 | ChampionDict = make(map[string]models.Champion)
76 | for _, champion := range ChampionList {
77 | ChampionDict[champion.Name] = models.Champion{
78 | Avatar: champion.Avatar,
79 | Price: champion.Price,
80 | Origin: champion.Origin,
81 | Class: champion.Class,
82 | }
83 | }
84 | for _, trait := range traitList {
85 | if trait.BonusNum[0] == 1 {
86 | OneTraitChampionNameList = append(OneTraitChampionNameList, trait.Champions...)
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "TFT/globals"
5 | "TFT/search"
6 | "TFT/utils"
7 | "encoding/json"
8 | "fmt"
9 | "os"
10 | "sort"
11 | "strconv"
12 | "time"
13 | )
14 |
15 | func start(teamSize int){
16 | start := time.Now()
17 | result := search.TraitBasedGraphSearch(globals.ChampionList, int(teamSize))
18 | elapsed := time.Since(start)
19 | fmt.Println("人口:",teamSize,
20 | "共耗时:", elapsed.Seconds(), "s",
21 | "平均每秒遍历组合数:", float64(globals.Counter)/elapsed.Seconds(),
22 | "共搜索结点个数:", globals.Counter)
23 |
24 | // 排序
25 | sort.Slice(result, func(i, j int)bool{
26 | return result[i].TotalStrength > result[j].TotalStrength
27 | })
28 | utils.Translate(&result)
29 | jsonString, err := json.MarshalIndent(&result, "", " ")
30 | if err != nil {
31 | fmt.Println(err.Error())
32 | }
33 | dstFile, err := os.Create(globals.Global.OutPutPath+"champions_comb"+strconv.Itoa(teamSize)+".json")
34 | if err != nil {
35 | panic("打开文件句柄失败")
36 | }
37 | _, err = dstFile.WriteString(string(jsonString))
38 | if err != nil {
39 | panic("写入文件失败")
40 | }
41 | }
42 |
43 | func main() {
44 | start(7)
45 | }
--------------------------------------------------------------------------------
/models/champions.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | type Champion struct {
4 | Avatar string `json:"avatar"`
5 | Price int `json:"price"`
6 | Origin []string `json:"origin"`
7 | Class []string `json:"class"`
8 | }
9 |
10 | type ChampionDict struct {
11 | Name string `json:"name"`
12 | *Champion
13 | }
14 |
15 | type ChampionList []ChampionDict
16 |
--------------------------------------------------------------------------------
/models/metrics.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | type ComboMetric struct {
4 | // 英雄组合
5 | Combo []string `json:"combo"`
6 | // 队伍总羁绊数量 = sigma{羁绊} * 羁绊等级
7 | TraitNum int `json:"trait_num"`
8 | // 具体羁绊
9 | TraitDetail map[string]int `json:"trait_detail"`
10 | // 总英雄收益羁绊数量 = sigma{羁绊} 羁绊范围 * 羁绊等级
11 | TotalTraitNum int `json:"total_trait_num"`
12 | // 当前阵容羁绊强度 = sigma{羁绊} 羁绊范围 * 羁绊强度
13 | TotalTraitStrength float32 `json:"total_trait_strength"`
14 | // 当前阵容强度 = sigma{英雄} 英雄强度 * 羁绊强度
15 | TotalStrength float64 `json:"total_strength"`
16 | }
17 |
18 | // 定义一个最小堆,保留前K个羁绊
19 | type ComboMetricHeap []ComboMetric
20 |
21 | func (h ComboMetricHeap) Len() int {
22 | return len(h)
23 | }
24 |
25 | func (h ComboMetricHeap) Less(i,j int) bool {
26 | return h[i].TotalStrength < h[j].TotalStrength
27 | }
28 |
29 | func (h ComboMetricHeap) Swap(i, j int) {
30 | h[i], h[j] = h[j], h[i]
31 | }
32 |
33 | func (h *ComboMetricHeap) Push(x interface{}) {
34 | *h = append(*h, x.(ComboMetric))
35 | }
36 |
37 | func (h *ComboMetricHeap) Pop() interface{} {
38 | old := *h
39 | n := len(old)
40 | x := old[n-1]
41 | *h = old[0 : n-1]
42 | return x
43 | }
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/models/traits.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | type Trait struct{
4 | BonusNum []int `json:"bonus_num"`
5 | Scope []int `json:"scope"`
6 | Champions []string `json:"champions"`
7 | Strength []float32 `json:"strength"`
8 | }
9 |
10 | type TraitDict struct {
11 | Name string `json:"name"`
12 | *Trait
13 | }
14 |
15 | type TraitList []TraitDict
--------------------------------------------------------------------------------
/python_scripts/deduplicate.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 |
4 | # jaccard 相似度
5 | def diff_set(set1 :set, set2 :set) -> float:
6 | return len(set1 & set2) / len(set1 | set2)
7 |
8 |
9 | def setify(combo:dict) -> set:
10 | trait_detail = combo['trait_detail']
11 | result_set = set()
12 | for trait, num in trait_detail.items():
13 | result_set.add((trait, num,))
14 | return result_set
15 |
16 |
17 | if __name__ == "__main__":
18 | num = 9
19 | with open(f'../data/output/total_strength/champions_comb{num}.json', 'r') as f:
20 | combos = json.load(f)
21 |
22 | trait_list = [setify(combos[0])]
23 | for combo in combos[1:]:
24 | combo_set = setify(combo)
25 | for trait_set in trait_list:
26 | # 如果相似度大于80%就是相同体系羁绊
27 | sim = diff_set(trait_set, combo_set)
28 | if sim >= 0.7:
29 | break
30 | else:
31 | trait_list.append(combo_set)
32 | result = [str(list(each)) for each in trait_list]
33 | with open(f"../data/final_result/total_strength/final_result{num}.json", 'w') as f:
34 | json.dump(result, f, indent='\t', ensure_ascii=False)
35 |
--------------------------------------------------------------------------------
/python_scripts/download.py:
--------------------------------------------------------------------------------
1 | import requests
2 | import os
3 | import json
4 | import cv2
5 |
6 | os.chdir('../data')
7 | if __name__ == "__main__":
8 | with open('champions.json', 'r') as f:
9 | champions = json.load(f)
10 | for n, each in enumerate(champions):
11 | filename = 'avatar/'+each['name']+'.png'
12 | if not os.path.exists(filename):
13 | url = each['avatar']
14 | url = url.replace('resize=64', 'resize=120')
15 | response = requests.get(url)
16 | with open(filename, 'wb') as fp:
17 | fp.write(response.content)
18 | image = cv2.imread(filename)
19 | image = cv2.resize(image, (60, 60))
20 | cv2.imwrite('avatar/'+str(n).zfill(2)+each['name']+'.png', image)
21 |
--------------------------------------------------------------------------------
/python_scripts/graph_visualisation.py:
--------------------------------------------------------------------------------
1 | import json
2 | import os
3 |
4 | os.chdir("../data")
5 |
6 | if __name__ == "__main__":
7 | with open("language.json", "r") as f:
8 | translate_dict = json.load(f)
9 | with open("champions_graph.json", "r") as f:
10 | champions_graph = json.load(f)
11 | with open("champions.json", "r") as f:
12 | champions_list = json.load(f)
13 |
14 | # Generate nodes
15 | node_list = []
16 | for n, champion in enumerate(champions_list):
17 | node = dict()
18 | node['id'] = str(n)
19 | node["name"] = translate_dict[str(champion['name'])]
20 | node["cluster"] = translate_dict[champion["origin"][0]]
21 | node["value"] = champion["price"]*5
22 | node_list.append(node)
23 |
24 | # Generate edges
25 | edge_list = []
26 | for from_node, to_nodes in champions_graph.items():
27 | if to_nodes:
28 | for to_node in to_nodes:
29 | edge = dict()
30 | edge['source'] = str(from_node)
31 | edge['target'] = str(to_node)
32 | edge['sourceWeight'] = 10
33 | edge['targetWeight'] = 0
34 | edge_list.append(edge)
35 |
36 | total_dict = {
37 | "nodes": node_list,
38 | "edges": edge_list
39 | }
40 | with open("graph.json", 'w') as f:
41 | json.dump(total_dict, f, indent="\t", ensure_ascii=False)
--------------------------------------------------------------------------------
/python_scripts/scrape.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2019/10/29 11:19 PM
3 | # @Author : weiziyang
4 | # @FileName: scrape.py
5 | # @Software: PyCharm
6 | import os
7 | import json
8 | import time
9 | import requests
10 | from bs4 import BeautifulSoup
11 |
12 | response = requests.get('https://na.leagueoflegends.com/en/news/game-updates/gameplay/teamfight-tactics-gameplay-guide?utm_source=web&utm_medium=web&utm_campaign=tft-microsite-2019#patch-champion-compendium')
13 | soup = BeautifulSoup(response.text, 'lxml')
14 | block = soup.find('div', attrs={'id': 'champion-compendium-slideshow'})
15 | boxes = block.findAll('div', attrs={'class': 'content-border'})
16 |
17 | champion_list = list()
18 |
19 | for box in boxes:
20 | avatar_url = box.find('a', attrs={'class': 'reference-link'}).find('img')['src']
21 | name = box.find('h4', attrs={'class': 'change-title'}).getText()
22 | price = box.find('p', attrs={'class': 'summary price'}).getText().replace('gold', '')
23 | h4 = box.findAll('h4', attrs={'class': 'ability-title'})
24 | origin = []
25 | Class = []
26 | for each in h4[1:]:
27 | text = each.getText()
28 | if 'Origin' in text:
29 | origin.append(text.replace('Origin', '').strip().lower())
30 | elif 'Class' in text:
31 | Class.append(text.replace('Class', '').strip().lower())
32 | champion = {
33 | 'name': name.strip(),
34 | 'avatar': avatar_url,
35 | 'price': int(price.strip()),
36 | 'origin': origin,
37 | 'class': Class
38 | }
39 | champion_list.append(champion)
40 |
41 | with open('data.json', 'w') as f:
42 | json.dump(champion_list, f, indent='\t')
43 |
44 |
--------------------------------------------------------------------------------
/python_scripts/scrape_icon.py:
--------------------------------------------------------------------------------
1 | import os
2 | import json
3 | import requests
4 | from bs4 import BeautifulSoup
5 |
6 | response = requests.get('https://na.leagueoflegends.com/en/news/game-updates/gameplay/teamfight-tactics-gameplay-guide?utm_source=web&utm_medium=web&utm_campaign=tft-microsite-2019#patch-champion-compendium')
7 | soup = BeautifulSoup(response.text, 'lxml')
8 |
9 | icons = soup.find_all('div', attrs={'class': "tft-icon-container"})
10 | result = {}
11 | for icon in icons:
12 | url = icon.find("img")['src']
13 | trait = icon.find('h4').getText()
14 | result[trait] = url
15 | result['Hextech'] = "http://game.gtimg.cn/images/lol/act/a20190702loltftwf/icon-hks.png"
16 |
17 | os.chdir('../data/trait_icons')
18 | for name, url in result.items():
19 | response = requests.get(url)
20 | with open(name+'.png', 'wb') as f:
21 | f.write(response.content)
22 |
--------------------------------------------------------------------------------
/python_scripts/traits.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2019/10/31 12:58 AM
3 | # @Author : weiziyang
4 | # @FileName: traits.py
5 | # @Software: PyCharm
6 | import json
7 |
8 | ONLY_ONE = 1
9 | SAME_ORIGIN = 2
10 | ALL = 3
11 | NINJIA = 12
12 | BOOST = 23
13 | SUPERBOOST = 13
14 | GUARD = 4
15 |
16 |
17 | if __name__ == "__main__":
18 | with open('champions_data.json', 'r') as f:
19 | champion_list = json.load(f)
20 | origin_dict = dict()
21 | class_dict = dict()
22 | for champion in champion_list:
23 | origins = champion['origin']
24 | for origin in origins:
25 | if origin_dict.get(origin):
26 | origin_dict[origin]['champions'].append(champion['name'])
27 | else:
28 | origin_dict[origin] = {
29 | 'bonus_num': [],
30 | 'scope': 2,
31 | 'strength': 1,
32 | 'champions': [champion['name']]
33 | }
34 | classes = champion['class']
35 | for _class in classes:
36 | if class_dict.get(_class):
37 | class_dict[_class]['champions'].append(champion['name'])
38 | else:
39 | class_dict[_class] = {
40 | 'bonus_num': [],
41 | 'scope': 2,
42 | 'strength': 1,
43 | 'champions': [champion['name']]
44 | }
45 |
46 | trait_dict = {}
47 | trait_dict.update(origin_dict)
48 | trait_dict.update(class_dict)
49 |
50 | with open('traits_data.json', 'w') as f:
51 | json.dump(trait_dict, f, indent='\t')
52 |
--------------------------------------------------------------------------------
/python_scripts/translate.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 | # with open('../data/traits.json', 'r') as f:
4 | # champion_list = json.load(f)
5 | #
6 | # name_list = []
7 | # for each in champion_list:
8 | # name_list.append({each['name']: ""})
9 | #
10 | # with open('../data/language.json', 'w') as f:
11 | # json.dump(name_list, f, indent='\t', ensure_ascii=False)
12 | dic = {}
13 |
14 | with open("../data/language.json", 'r') as f:
15 | l = json.load(f)
16 |
17 | for each in l:
18 | key = list(each.keys())[0]
19 | value = list(each.values())[0]
20 | dic[key] = value
21 |
22 | with open("../data/language_copy.json", "w") as f:
23 | json.dump(dic, f, indent='\t', ensure_ascii=False)
--------------------------------------------------------------------------------
/python_scripts/visualise_champions.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | import os
3 | import numpy as np
4 |
5 | os.chdir('../data')
6 | width = 60*56
7 | height = 60
8 | avatars = [each for each in sorted(os.listdir('avatar'), key=lambda a:int(a[:2]))if not each.startswith('.')]
9 | canvas = np.zeros((height, width, 3))
10 |
11 | for n, avatar in enumerate(avatars):
12 | path = os.path.join('avatar', avatar)
13 | img = plt.imread(path)
14 | canvas[:, 60*n:60*(n+1), :] = img
15 |
16 | plt.imsave('canvas.png', canvas)
--------------------------------------------------------------------------------
/python_scripts/visualise_trait_graph.py:
--------------------------------------------------------------------------------
1 | import os
2 | import json
3 | import numpy as np
4 | import cv2
5 | import matplotlib.pyplot as plt
6 |
7 | os.chdir('..')
8 | with open('data/champions.json') as f:
9 | champions = json.load(f)
10 | trait_graph = [["" for _ in range(len(champions))] for each in range(len(champions))]
11 |
12 | prior_trait = {'ninja', 'exile', 'robot'}
13 | for y, champion_a in enumerate(champions):
14 | origins = champion_a['origin']
15 | classes = champion_a['class']
16 | champion_a_traits = set(origins + classes)
17 | for x, champion_b in enumerate(champions):
18 | if x == y:
19 | trait_graph[y][x] = "same"
20 | continue
21 | origins = champion_b['origin']
22 | classes = champion_b['class']
23 | champion_b_traits = set(origins + classes)
24 | # 两个英雄共同的羁绊
25 | common_traits = (champion_a_traits & champion_b_traits)
26 | # 是否存在忍者、浪人、机器人
27 | if common_traits:
28 | extra_traits = set()
29 | else:
30 | extra_traits = (champion_b_traits | champion_a_traits) & prior_trait
31 | all_traits = common_traits | extra_traits
32 | if all_traits:
33 | trait_graph[y][x] = str(','.join(list(all_traits)))
34 |
35 | champions_num = len(champions)
36 | size = 40
37 | width = size + champions_num * size * 2 + size
38 | height = size + champions_num * size + size
39 | canvas = np.zeros((height, width, 3))*255
40 | start_point = (size, size)
41 |
42 | # 首先画英雄
43 | file_names = sorted([each for each in os.listdir('data/avatar') if not each.startswith('.')], key=lambda a: int(a[:2]))
44 | file_names = [os.path.join('data', 'avatar', each) for each in file_names]
45 | for n, file_name in enumerate(file_names):
46 | img = cv2.cvtColor(cv2.imread(file_name), cv2.COLOR_BGR2RGB)
47 | resized_img = cv2.resize(img, (size, size))
48 | # 先画横向的
49 | y = 0
50 | x = size + size * 2 * n
51 | canvas[y:y+size, x:x+size, :] = resized_img
52 | canvas[:, x+size:x+size+1, :] = np.ones((height, 1, 3))*255
53 | # 再画纵向的
54 | x = 0
55 | y = size + size * n
56 | canvas[y:y+size, x:x+size, :] = resized_img
57 | canvas[y+size:y+size+1, :, :] = np.ones((1, width, 3))*255
58 |
59 | # 载入羁绊
60 | trait_file_names = [each for each in os.listdir('data/trait_icons') if not each.startswith('.')]
61 | name = [each.split('.')[0].lower() for each in trait_file_names]
62 | trait_icon_dict = {}
63 | for n, trait_file in enumerate(trait_file_names):
64 | img = cv2.cvtColor(cv2.imread(os.path.join('data', 'trait_icons', trait_file)), cv2.COLOR_BGR2RGB)
65 | resized_img = cv2.resize(img, (size, size))
66 | trait_icon_dict[name[n]] = resized_img
67 | trait_icon_dict['Hextech'] = trait_icon_dict['hextech']
68 | # 再画羁绊
69 | for row in range(len(trait_graph)):
70 | for col in range((len(trait_graph))):
71 | content = trait_graph[row][col]
72 | if content and content != 'same':
73 | traits = content.split(',')
74 | for index, trait in enumerate(traits):
75 | icon = trait_icon_dict[trait]
76 | y = size + row * size
77 | if index == 0:
78 | x = size + 2 * col * size
79 | if index == 1:
80 | x = size + 2 * col * size + size
81 | canvas[y:y+size, x:x+size] = trait_icon_dict[trait]
82 |
83 | cv2.imwrite("data/trait_graph.png", canvas)
--------------------------------------------------------------------------------
/search/graph.go:
--------------------------------------------------------------------------------
1 | package search
2 |
3 | import (
4 | "TFT/globals"
5 | "TFT/models"
6 | "TFT/utils"
7 | "sort"
8 | )
9 |
10 | type Graph map[int][]int
11 |
12 | // GenerateGraph 生成羁绊图
13 | func GenerateGraph(championList models.ChampionList) Graph{
14 | graph := make(Graph)
15 | positionMap := make(map[string]int)
16 | for index, champion := range championList {
17 | positionMap[champion.Name] = index
18 | }
19 | for no, champion := range championList {
20 | // children 排序
21 | children := make([]int, 0, 30)
22 | // 加入相同职业的英雄
23 | classes := champion.Class
24 | for _, class := range classes {
25 | sameClassChampions := globals.TraitDict[class].Champions
26 | for _, champion := range sameClassChampions {
27 | index := positionMap[champion]
28 | if index > no{
29 | children = append(children, index)
30 | }
31 | }
32 | }
33 | // 加入相同种族的英雄
34 | origins := champion.Origin
35 | for _, origin := range origins {
36 | sameOriginChampions := globals.TraitDict[origin].Champions
37 | for _, champion := range sameOriginChampions {
38 | index := positionMap[champion]
39 | if index > no {
40 | children = append(children, index)
41 | }
42 | }
43 | }
44 | // 加入1羁绊的英雄
45 | for _, championName := range globals.OneTraitChampionNameList {
46 | index := positionMap[championName]
47 | if index > no {
48 | children = append(children, index)
49 | }
50 | }
51 | // 对index从小到大排序
52 | sort.Ints(children)
53 | children = utils.Deduplicate(children)
54 | graph[no] = children
55 | }
56 | return graph
57 | }
--------------------------------------------------------------------------------
/search/search.go:
--------------------------------------------------------------------------------
1 | package search
2 |
3 | import (
4 | "TFT/globals"
5 | "TFT/models"
6 | "container/heap"
7 | )
8 |
9 | var lim int
10 | var Result = make(models.ComboMetricHeap, 0, globals.Global.MaximumHeap)
11 |
12 | // getSlice 与python range(x,y)相同效果
13 | func getSlice(start int, end int) []int {
14 | rangeList := make([]int, end-start)
15 | for i := start; i < end; i++ {
16 | rangeList[i-start] = i
17 | }
18 | return rangeList
19 | }
20 |
21 |
22 | // TraitBasedGraphSearch 基于羁绊图的图搜索
23 | func TraitBasedGraphSearch(championList models.ChampionList, teamSize int) models.ComboMetricHeap {
24 | graph := GenerateGraph(championList)
25 | lim = teamSize
26 |
27 | heap.Init(&Result)
28 | startPoints := getSlice(0, len(championList)-teamSize + 1)
29 | for _,startNode := range startPoints{
30 | Traverse(championList, graph, startNode, make([]int, 0, teamSize), make([]int, 0, 57))
31 | }
32 |
33 | return Result
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/search/traverse.go:
--------------------------------------------------------------------------------
1 | package search
2 |
3 | import (
4 | "TFT/evaluate"
5 | "TFT/globals"
6 | "TFT/models"
7 | "TFT/utils"
8 | "container/heap"
9 | "fmt"
10 | "sort"
11 | )
12 |
13 | // Traverse 图遍历,
14 | // championList, 英雄列表,固定不变。 graph 羁绊图,也是固定不变。node 为当前的结点, selected 为已选择的英雄, oldChildren是父节点的children
15 | func Traverse(championList models.ChampionList, graph Graph, node int, selected []int, oldChildren []int) {
16 | selected = append(selected, node)
17 | if len(selected) == lim {
18 | combo := make(models.ChampionList, lim)
19 | for index, no := range selected {
20 | unit := championList[no]
21 | combo[index] = unit
22 | }
23 | globals.Counter += 1
24 | if globals.Counter%100000 == 0 {
25 | fmt.Println(globals.Counter)
26 | }
27 | metric := evaluate.Evaluate(combo)
28 | heap.Push(&Result, metric)
29 |
30 | // 超过最大就pop
31 | if len(Result) == globals.Global.MaximumHeap {
32 | heap.Remove(&Result, 0)
33 | }
34 | return
35 | }
36 | newChildren := graph[node]
37 | children := append(oldChildren, newChildren...)
38 | sort.Ints(children)
39 | children = utils.DeduplicateAndFilter(children, node)
40 | // 注意这里children在后面会因为append方法原地操作其内部元素,因此需要拷贝一下
41 | copyChildren := make([]int, len(children), 50)
42 | copy(copyChildren, children)
43 | for _, child := range children {
44 | // selected 也是同理
45 | copySelected := make([]int, len(selected), lim)
46 | copy(copySelected, selected)
47 | Traverse(championList, graph, child, copySelected, copyChildren)
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/utils/extend.go:
--------------------------------------------------------------------------------
1 | package utils
2 |
3 | // Contain 相当于 python 的 in
4 | func Contain(container []int, object int) bool{
5 | for _,candidate:=range container{
6 | if candidate == object{
7 | return true
8 | }
9 | }
10 | return false
11 | }
12 |
13 | // DeduplicateAndFilter 去重并且过滤比当前英雄位置先的英雄
14 | func DeduplicateAndFilter(list []int, node int)[]int{
15 | var lastOne int
16 | var resultList []int
17 | lastOne = 65535
18 | for _, item:=range list{
19 | if item > node && item != lastOne{
20 | resultList = append(resultList, item)
21 | lastOne = item
22 | }
23 | }
24 | return resultList
25 | }
26 |
27 | // Deduplicate 去重
28 | func Deduplicate(list []int) []int{
29 | var lastOne int
30 | var resultList []int
31 | lastOne = 65535
32 | for _, item:=range list{
33 | if item != lastOne{
34 | resultList = append(resultList, item)
35 | lastOne = item
36 | }
37 | }
38 | return resultList
39 | }
40 |
41 | // IsEqual 判断两个切片是否相等
42 | func IsEqual(list1 []int, list2 []int) bool{
43 | if len(list1)!=len(list2){
44 | return false
45 | }
46 | for i:=0;i
2 |
3 |
4 |
5 | Arc Diagram 弧线图
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
24 |
150 |
151 |
--------------------------------------------------------------------------------
/visualisation/graph.json:
--------------------------------------------------------------------------------
1 | {
2 | "nodes": [
3 | {
4 | "id": "0",
5 | "name": "维鲁斯",
6 | "cluster": "恶魔",
7 | "value": 10
8 | },
9 | {
10 | "id": "1",
11 | "name": "蜘蛛",
12 | "cluster": "恶魔",
13 | "value": 5
14 | },
15 | {
16 | "id": "2",
17 | "name": "莫甘娜",
18 | "cluster": "恶魔",
19 | "value": 15
20 | },
21 | {
22 | "id": "3",
23 | "name": "寡妇",
24 | "cluster": "恶魔",
25 | "value": 15
26 | },
27 | {
28 | "id": "4",
29 | "name": "剑魔",
30 | "cluster": "恶魔",
31 | "value": 15
32 | },
33 | {
34 | "id": "5",
35 | "name": "火男",
36 | "cluster": "恶魔",
37 | "value": 20
38 | },
39 | {
40 | "id": "6",
41 | "name": "乌鸦",
42 | "cluster": "恶魔",
43 | "value": 25
44 | },
45 | {
46 | "id": "7",
47 | "name": "龙女",
48 | "cluster": "龙",
49 | "value": 15
50 | },
51 | {
52 | "id": "8",
53 | "name": "龙王",
54 | "cluster": "龙",
55 | "value": 20
56 | },
57 | {
58 | "id": "9",
59 | "name": "潘森",
60 | "cluster": "龙",
61 | "value": 25
62 | },
63 | {
64 | "id": "10",
65 | "name": "亚索",
66 | "cluster": "浪人",
67 | "value": 25
68 | },
69 | {
70 | "id": "11",
71 | "name": "布隆",
72 | "cluster": "冰川",
73 | "value": 10
74 | },
75 | {
76 | "id": "12",
77 | "name": "丽桑卓",
78 | "cluster": "冰川",
79 | "value": 10
80 | },
81 | {
82 | "id": "13",
83 | "name": "艾希",
84 | "cluster": "冰川",
85 | "value": 15
86 | },
87 | {
88 | "id": "14",
89 | "name": "狗熊",
90 | "cluster": "冰川",
91 | "value": 15
92 | },
93 | {
94 | "id": "15",
95 | "name": "猪妹",
96 | "cluster": "冰川",
97 | "value": 20
98 | },
99 | {
100 | "id": "16",
101 | "name": "冰鸟",
102 | "cluster": "冰川",
103 | "value": 25
104 | },
105 | {
106 | "id": "17",
107 | "name": "机器人",
108 | "cluster": "机器人",
109 | "value": 10
110 | },
111 | {
112 | "id": "18",
113 | "name": "诺手",
114 | "cluster": "帝国",
115 | "value": 5
116 | },
117 | {
118 | "id": "19",
119 | "name": "卡特",
120 | "cluster": "帝国",
121 | "value": 15
122 | },
123 | {
124 | "id": "20",
125 | "name": "德莱文",
126 | "cluster": "帝国",
127 | "value": 20
128 | },
129 | {
130 | "id": "21",
131 | "name": "剑姬",
132 | "cluster": "贵族",
133 | "value": 5
134 | },
135 | {
136 | "id": "22",
137 | "name": "盖伦",
138 | "cluster": "贵族",
139 | "value": 5
140 | },
141 | {
142 | "id": "23",
143 | "name": "薇恩",
144 | "cluster": "贵族",
145 | "value": 5
146 | },
147 | {
148 | "id": "24",
149 | "name": "卢锡安",
150 | "cluster": "贵族",
151 | "value": 10
152 | },
153 | {
154 | "id": "25",
155 | "name": "日女",
156 | "cluster": "贵族",
157 | "value": 20
158 | },
159 | {
160 | "id": "26",
161 | "name": "天使",
162 | "cluster": "贵族",
163 | "value": 25
164 | },
165 | {
166 | "id": "27",
167 | "name": "慎",
168 | "cluster": "忍者",
169 | "value": 10
170 | },
171 | {
172 | "id": "28",
173 | "name": "劫",
174 | "cluster": "忍者",
175 | "value": 10
176 | },
177 | {
178 | "id": "29",
179 | "name": "凯南",
180 | "cluster": "忍者",
181 | "value": 15
182 | },
183 | {
184 | "id": "30",
185 | "name": "阿卡丽",
186 | "cluster": "忍者",
187 | "value": 20
188 | },
189 | {
190 | "id": "31",
191 | "name": "男枪",
192 | "cluster": "海盗",
193 | "value": 5
194 | },
195 | {
196 | "id": "32",
197 | "name": "派克",
198 | "cluster": "海盗",
199 | "value": 10
200 | },
201 | {
202 | "id": "33",
203 | "name": "卡牌",
204 | "cluster": "海盗",
205 | "value": 10
206 | },
207 | {
208 | "id": "34",
209 | "name": "船长",
210 | "cluster": "海盗",
211 | "value": 15
212 | },
213 | {
214 | "id": "35",
215 | "name": "好运姐",
216 | "cluster": "海盗",
217 | "value": 25
218 | },
219 | {
220 | "id": "36",
221 | "name": "铁男",
222 | "cluster": "幽灵",
223 | "value": 5
224 | },
225 | {
226 | "id": "37",
227 | "name": "千珏",
228 | "cluster": "幽灵",
229 | "value": 20
230 | },
231 | {
232 | "id": "38",
233 | "name": "死歌",
234 | "cluster": "幽灵",
235 | "value": 25
236 | },
237 | {
238 | "id": "39",
239 | "name": "狼人",
240 | "cluster": "狂野",
241 | "value": 5
242 | },
243 | {
244 | "id": "40",
245 | "name": "豹女",
246 | "cluster": "狂野",
247 | "value": 5
248 | },
249 | {
250 | "id": "41",
251 | "name": "狐狸",
252 | "cluster": "狂野",
253 | "value": 10
254 | },
255 | {
256 | "id": "42",
257 | "name": "狮子狗",
258 | "cluster": "狂野",
259 | "value": 15
260 | },
261 | {
262 | "id": "43",
263 | "name": "纳尔",
264 | "cluster": "狂野",
265 | "value": 20
266 | },
267 | {
268 | "id": "44",
269 | "name": "螳螂",
270 | "cluster": "虚空",
271 | "value": 5
272 | },
273 | {
274 | "id": "45",
275 | "name": "卡萨丁",
276 | "cluster": "虚空",
277 | "value": 5
278 | },
279 | {
280 | "id": "46",
281 | "name": "挖掘机",
282 | "cluster": "虚空",
283 | "value": 10
284 | },
285 | {
286 | "id": "47",
287 | "name": "大虫子",
288 | "cluster": "虚空",
289 | "value": 20
290 | },
291 | {
292 | "id": "48",
293 | "name": "卡萨",
294 | "cluster": "虚空",
295 | "value": 25
296 | },
297 | {
298 | "id": "49",
299 | "name": "小炮",
300 | "cluster": "约德尔",
301 | "value": 5
302 | },
303 | {
304 | "id": "50",
305 | "name": "露露",
306 | "cluster": "约德尔",
307 | "value": 10
308 | },
309 | {
310 | "id": "51",
311 | "name": "波比",
312 | "cluster": "约德尔",
313 | "value": 15
314 | },
315 | {
316 | "id": "52",
317 | "name": "小法",
318 | "cluster": "约德尔",
319 | "value": 15
320 | },
321 | {
322 | "id": "53",
323 | "name": "卡密尔",
324 | "cluster": "海克斯",
325 | "value": 5
326 | },
327 | {
328 | "id": "54",
329 | "name": "蔚",
330 | "cluster": "海克斯",
331 | "value": 15
332 | },
333 | {
334 | "id": "55",
335 | "name": "金克斯",
336 | "cluster": "海克斯",
337 | "value": 20
338 | }
339 | ],
340 | "edges": [
341 | {
342 | "source": "0",
343 | "target": "1",
344 | "sourceWeight": 10,
345 | "targetWeight": 0
346 | },
347 | {
348 | "source": "0",
349 | "target": "2",
350 | "sourceWeight": 10,
351 | "targetWeight": 0
352 | },
353 | {
354 | "source": "0",
355 | "target": "3",
356 | "sourceWeight": 10,
357 | "targetWeight": 0
358 | },
359 | {
360 | "source": "0",
361 | "target": "4",
362 | "sourceWeight": 10,
363 | "targetWeight": 0
364 | },
365 | {
366 | "source": "0",
367 | "target": "5",
368 | "sourceWeight": 10,
369 | "targetWeight": 0
370 | },
371 | {
372 | "source": "0",
373 | "target": "6",
374 | "sourceWeight": 10,
375 | "targetWeight": 0
376 | },
377 | {
378 | "source": "0",
379 | "target": "10",
380 | "sourceWeight": 10,
381 | "targetWeight": 0
382 | },
383 | {
384 | "source": "0",
385 | "target": "13",
386 | "sourceWeight": 10,
387 | "targetWeight": 0
388 | },
389 | {
390 | "source": "0",
391 | "target": "17",
392 | "sourceWeight": 10,
393 | "targetWeight": 0
394 | },
395 | {
396 | "source": "0",
397 | "target": "23",
398 | "sourceWeight": 10,
399 | "targetWeight": 0
400 | },
401 | {
402 | "source": "0",
403 | "target": "27",
404 | "sourceWeight": 10,
405 | "targetWeight": 0
406 | },
407 | {
408 | "source": "0",
409 | "target": "28",
410 | "sourceWeight": 10,
411 | "targetWeight": 0
412 | },
413 | {
414 | "source": "0",
415 | "target": "29",
416 | "sourceWeight": 10,
417 | "targetWeight": 0
418 | },
419 | {
420 | "source": "0",
421 | "target": "30",
422 | "sourceWeight": 10,
423 | "targetWeight": 0
424 | },
425 | {
426 | "source": "0",
427 | "target": "37",
428 | "sourceWeight": 10,
429 | "targetWeight": 0
430 | },
431 | {
432 | "source": "0",
433 | "target": "48",
434 | "sourceWeight": 10,
435 | "targetWeight": 0
436 | },
437 | {
438 | "source": "1",
439 | "target": "2",
440 | "sourceWeight": 10,
441 | "targetWeight": 0
442 | },
443 | {
444 | "source": "1",
445 | "target": "3",
446 | "sourceWeight": 10,
447 | "targetWeight": 0
448 | },
449 | {
450 | "source": "1",
451 | "target": "4",
452 | "sourceWeight": 10,
453 | "targetWeight": 0
454 | },
455 | {
456 | "source": "1",
457 | "target": "5",
458 | "sourceWeight": 10,
459 | "targetWeight": 0
460 | },
461 | {
462 | "source": "1",
463 | "target": "6",
464 | "sourceWeight": 10,
465 | "targetWeight": 0
466 | },
467 | {
468 | "source": "1",
469 | "target": "7",
470 | "sourceWeight": 10,
471 | "targetWeight": 0
472 | },
473 | {
474 | "source": "1",
475 | "target": "10",
476 | "sourceWeight": 10,
477 | "targetWeight": 0
478 | },
479 | {
480 | "source": "1",
481 | "target": "17",
482 | "sourceWeight": 10,
483 | "targetWeight": 0
484 | },
485 | {
486 | "source": "1",
487 | "target": "27",
488 | "sourceWeight": 10,
489 | "targetWeight": 0
490 | },
491 | {
492 | "source": "1",
493 | "target": "28",
494 | "sourceWeight": 10,
495 | "targetWeight": 0
496 | },
497 | {
498 | "source": "1",
499 | "target": "29",
500 | "sourceWeight": 10,
501 | "targetWeight": 0
502 | },
503 | {
504 | "source": "1",
505 | "target": "30",
506 | "sourceWeight": 10,
507 | "targetWeight": 0
508 | },
509 | {
510 | "source": "1",
511 | "target": "40",
512 | "sourceWeight": 10,
513 | "targetWeight": 0
514 | },
515 | {
516 | "source": "1",
517 | "target": "43",
518 | "sourceWeight": 10,
519 | "targetWeight": 0
520 | },
521 | {
522 | "source": "10",
523 | "target": "17",
524 | "sourceWeight": 10,
525 | "targetWeight": 0
526 | },
527 | {
528 | "source": "10",
529 | "target": "20",
530 | "sourceWeight": 10,
531 | "targetWeight": 0
532 | },
533 | {
534 | "source": "10",
535 | "target": "21",
536 | "sourceWeight": 10,
537 | "targetWeight": 0
538 | },
539 | {
540 | "source": "10",
541 | "target": "27",
542 | "sourceWeight": 10,
543 | "targetWeight": 0
544 | },
545 | {
546 | "source": "10",
547 | "target": "28",
548 | "sourceWeight": 10,
549 | "targetWeight": 0
550 | },
551 | {
552 | "source": "10",
553 | "target": "29",
554 | "sourceWeight": 10,
555 | "targetWeight": 0
556 | },
557 | {
558 | "source": "10",
559 | "target": "30",
560 | "sourceWeight": 10,
561 | "targetWeight": 0
562 | },
563 | {
564 | "source": "10",
565 | "target": "34",
566 | "sourceWeight": 10,
567 | "targetWeight": 0
568 | },
569 | {
570 | "source": "10",
571 | "target": "53",
572 | "sourceWeight": 10,
573 | "targetWeight": 0
574 | },
575 | {
576 | "source": "11",
577 | "target": "12",
578 | "sourceWeight": 10,
579 | "targetWeight": 0
580 | },
581 | {
582 | "source": "11",
583 | "target": "13",
584 | "sourceWeight": 10,
585 | "targetWeight": 0
586 | },
587 | {
588 | "source": "11",
589 | "target": "14",
590 | "sourceWeight": 10,
591 | "targetWeight": 0
592 | },
593 | {
594 | "source": "11",
595 | "target": "15",
596 | "sourceWeight": 10,
597 | "targetWeight": 0
598 | },
599 | {
600 | "source": "11",
601 | "target": "16",
602 | "sourceWeight": 10,
603 | "targetWeight": 0
604 | },
605 | {
606 | "source": "11",
607 | "target": "17",
608 | "sourceWeight": 10,
609 | "targetWeight": 0
610 | },
611 | {
612 | "source": "11",
613 | "target": "25",
614 | "sourceWeight": 10,
615 | "targetWeight": 0
616 | },
617 | {
618 | "source": "11",
619 | "target": "27",
620 | "sourceWeight": 10,
621 | "targetWeight": 0
622 | },
623 | {
624 | "source": "11",
625 | "target": "28",
626 | "sourceWeight": 10,
627 | "targetWeight": 0
628 | },
629 | {
630 | "source": "11",
631 | "target": "29",
632 | "sourceWeight": 10,
633 | "targetWeight": 0
634 | },
635 | {
636 | "source": "11",
637 | "target": "30",
638 | "sourceWeight": 10,
639 | "targetWeight": 0
640 | },
641 | {
642 | "source": "12",
643 | "target": "13",
644 | "sourceWeight": 10,
645 | "targetWeight": 0
646 | },
647 | {
648 | "source": "12",
649 | "target": "14",
650 | "sourceWeight": 10,
651 | "targetWeight": 0
652 | },
653 | {
654 | "source": "12",
655 | "target": "15",
656 | "sourceWeight": 10,
657 | "targetWeight": 0
658 | },
659 | {
660 | "source": "12",
661 | "target": "16",
662 | "sourceWeight": 10,
663 | "targetWeight": 0
664 | },
665 | {
666 | "source": "12",
667 | "target": "17",
668 | "sourceWeight": 10,
669 | "targetWeight": 0
670 | },
671 | {
672 | "source": "12",
673 | "target": "27",
674 | "sourceWeight": 10,
675 | "targetWeight": 0
676 | },
677 | {
678 | "source": "12",
679 | "target": "28",
680 | "sourceWeight": 10,
681 | "targetWeight": 0
682 | },
683 | {
684 | "source": "12",
685 | "target": "29",
686 | "sourceWeight": 10,
687 | "targetWeight": 0
688 | },
689 | {
690 | "source": "12",
691 | "target": "30",
692 | "sourceWeight": 10,
693 | "targetWeight": 0
694 | },
695 | {
696 | "source": "13",
697 | "target": "14",
698 | "sourceWeight": 10,
699 | "targetWeight": 0
700 | },
701 | {
702 | "source": "13",
703 | "target": "15",
704 | "sourceWeight": 10,
705 | "targetWeight": 0
706 | },
707 | {
708 | "source": "13",
709 | "target": "16",
710 | "sourceWeight": 10,
711 | "targetWeight": 0
712 | },
713 | {
714 | "source": "13",
715 | "target": "17",
716 | "sourceWeight": 10,
717 | "targetWeight": 0
718 | },
719 | {
720 | "source": "13",
721 | "target": "23",
722 | "sourceWeight": 10,
723 | "targetWeight": 0
724 | },
725 | {
726 | "source": "13",
727 | "target": "27",
728 | "sourceWeight": 10,
729 | "targetWeight": 0
730 | },
731 | {
732 | "source": "13",
733 | "target": "28",
734 | "sourceWeight": 10,
735 | "targetWeight": 0
736 | },
737 | {
738 | "source": "13",
739 | "target": "29",
740 | "sourceWeight": 10,
741 | "targetWeight": 0
742 | },
743 | {
744 | "source": "13",
745 | "target": "30",
746 | "sourceWeight": 10,
747 | "targetWeight": 0
748 | },
749 | {
750 | "source": "13",
751 | "target": "37",
752 | "sourceWeight": 10,
753 | "targetWeight": 0
754 | },
755 | {
756 | "source": "13",
757 | "target": "48",
758 | "sourceWeight": 10,
759 | "targetWeight": 0
760 | },
761 | {
762 | "source": "14",
763 | "target": "15",
764 | "sourceWeight": 10,
765 | "targetWeight": 0
766 | },
767 | {
768 | "source": "14",
769 | "target": "16",
770 | "sourceWeight": 10,
771 | "targetWeight": 0
772 | },
773 | {
774 | "source": "14",
775 | "target": "17",
776 | "sourceWeight": 10,
777 | "targetWeight": 0
778 | },
779 | {
780 | "source": "14",
781 | "target": "27",
782 | "sourceWeight": 10,
783 | "targetWeight": 0
784 | },
785 | {
786 | "source": "14",
787 | "target": "28",
788 | "sourceWeight": 10,
789 | "targetWeight": 0
790 | },
791 | {
792 | "source": "14",
793 | "target": "29",
794 | "sourceWeight": 10,
795 | "targetWeight": 0
796 | },
797 | {
798 | "source": "14",
799 | "target": "30",
800 | "sourceWeight": 10,
801 | "targetWeight": 0
802 | },
803 | {
804 | "source": "14",
805 | "target": "39",
806 | "sourceWeight": 10,
807 | "targetWeight": 0
808 | },
809 | {
810 | "source": "14",
811 | "target": "46",
812 | "sourceWeight": 10,
813 | "targetWeight": 0
814 | },
815 | {
816 | "source": "14",
817 | "target": "47",
818 | "sourceWeight": 10,
819 | "targetWeight": 0
820 | },
821 | {
822 | "source": "14",
823 | "target": "54",
824 | "sourceWeight": 10,
825 | "targetWeight": 0
826 | },
827 | {
828 | "source": "15",
829 | "target": "16",
830 | "sourceWeight": 10,
831 | "targetWeight": 0
832 | },
833 | {
834 | "source": "15",
835 | "target": "17",
836 | "sourceWeight": 10,
837 | "targetWeight": 0
838 | },
839 | {
840 | "source": "15",
841 | "target": "18",
842 | "sourceWeight": 10,
843 | "targetWeight": 0
844 | },
845 | {
846 | "source": "15",
847 | "target": "22",
848 | "sourceWeight": 10,
849 | "targetWeight": 0
850 | },
851 | {
852 | "source": "15",
853 | "target": "26",
854 | "sourceWeight": 10,
855 | "targetWeight": 0
856 | },
857 | {
858 | "source": "15",
859 | "target": "27",
860 | "sourceWeight": 10,
861 | "targetWeight": 0
862 | },
863 | {
864 | "source": "15",
865 | "target": "28",
866 | "sourceWeight": 10,
867 | "targetWeight": 0
868 | },
869 | {
870 | "source": "15",
871 | "target": "29",
872 | "sourceWeight": 10,
873 | "targetWeight": 0
874 | },
875 | {
876 | "source": "15",
877 | "target": "30",
878 | "sourceWeight": 10,
879 | "targetWeight": 0
880 | },
881 | {
882 | "source": "15",
883 | "target": "36",
884 | "sourceWeight": 10,
885 | "targetWeight": 0
886 | },
887 | {
888 | "source": "15",
889 | "target": "51",
890 | "sourceWeight": 10,
891 | "targetWeight": 0
892 | },
893 | {
894 | "source": "16",
895 | "target": "17",
896 | "sourceWeight": 10,
897 | "targetWeight": 0
898 | },
899 | {
900 | "source": "16",
901 | "target": "27",
902 | "sourceWeight": 10,
903 | "targetWeight": 0
904 | },
905 | {
906 | "source": "16",
907 | "target": "28",
908 | "sourceWeight": 10,
909 | "targetWeight": 0
910 | },
911 | {
912 | "source": "16",
913 | "target": "29",
914 | "sourceWeight": 10,
915 | "targetWeight": 0
916 | },
917 | {
918 | "source": "16",
919 | "target": "30",
920 | "sourceWeight": 10,
921 | "targetWeight": 0
922 | },
923 | {
924 | "source": "17",
925 | "target": "27",
926 | "sourceWeight": 10,
927 | "targetWeight": 0
928 | },
929 | {
930 | "source": "17",
931 | "target": "28",
932 | "sourceWeight": 10,
933 | "targetWeight": 0
934 | },
935 | {
936 | "source": "17",
937 | "target": "29",
938 | "sourceWeight": 10,
939 | "targetWeight": 0
940 | },
941 | {
942 | "source": "17",
943 | "target": "30",
944 | "sourceWeight": 10,
945 | "targetWeight": 0
946 | },
947 | {
948 | "source": "17",
949 | "target": "39",
950 | "sourceWeight": 10,
951 | "targetWeight": 0
952 | },
953 | {
954 | "source": "17",
955 | "target": "46",
956 | "sourceWeight": 10,
957 | "targetWeight": 0
958 | },
959 | {
960 | "source": "17",
961 | "target": "47",
962 | "sourceWeight": 10,
963 | "targetWeight": 0
964 | },
965 | {
966 | "source": "17",
967 | "target": "54",
968 | "sourceWeight": 10,
969 | "targetWeight": 0
970 | },
971 | {
972 | "source": "18",
973 | "target": "19",
974 | "sourceWeight": 10,
975 | "targetWeight": 0
976 | },
977 | {
978 | "source": "18",
979 | "target": "20",
980 | "sourceWeight": 10,
981 | "targetWeight": 0
982 | },
983 | {
984 | "source": "18",
985 | "target": "22",
986 | "sourceWeight": 10,
987 | "targetWeight": 0
988 | },
989 | {
990 | "source": "18",
991 | "target": "26",
992 | "sourceWeight": 10,
993 | "targetWeight": 0
994 | },
995 | {
996 | "source": "18",
997 | "target": "27",
998 | "sourceWeight": 10,
999 | "targetWeight": 0
1000 | },
1001 | {
1002 | "source": "18",
1003 | "target": "28",
1004 | "sourceWeight": 10,
1005 | "targetWeight": 0
1006 | },
1007 | {
1008 | "source": "18",
1009 | "target": "29",
1010 | "sourceWeight": 10,
1011 | "targetWeight": 0
1012 | },
1013 | {
1014 | "source": "18",
1015 | "target": "30",
1016 | "sourceWeight": 10,
1017 | "targetWeight": 0
1018 | },
1019 | {
1020 | "source": "18",
1021 | "target": "36",
1022 | "sourceWeight": 10,
1023 | "targetWeight": 0
1024 | },
1025 | {
1026 | "source": "18",
1027 | "target": "51",
1028 | "sourceWeight": 10,
1029 | "targetWeight": 0
1030 | },
1031 | {
1032 | "source": "19",
1033 | "target": "20",
1034 | "sourceWeight": 10,
1035 | "targetWeight": 0
1036 | },
1037 | {
1038 | "source": "19",
1039 | "target": "27",
1040 | "sourceWeight": 10,
1041 | "targetWeight": 0
1042 | },
1043 | {
1044 | "source": "19",
1045 | "target": "28",
1046 | "sourceWeight": 10,
1047 | "targetWeight": 0
1048 | },
1049 | {
1050 | "source": "19",
1051 | "target": "29",
1052 | "sourceWeight": 10,
1053 | "targetWeight": 0
1054 | },
1055 | {
1056 | "source": "19",
1057 | "target": "30",
1058 | "sourceWeight": 10,
1059 | "targetWeight": 0
1060 | },
1061 | {
1062 | "source": "19",
1063 | "target": "32",
1064 | "sourceWeight": 10,
1065 | "targetWeight": 0
1066 | },
1067 | {
1068 | "source": "19",
1069 | "target": "42",
1070 | "sourceWeight": 10,
1071 | "targetWeight": 0
1072 | },
1073 | {
1074 | "source": "19",
1075 | "target": "44",
1076 | "sourceWeight": 10,
1077 | "targetWeight": 0
1078 | },
1079 | {
1080 | "source": "19",
1081 | "target": "48",
1082 | "sourceWeight": 10,
1083 | "targetWeight": 0
1084 | },
1085 | {
1086 | "source": "2",
1087 | "target": "3",
1088 | "sourceWeight": 10,
1089 | "targetWeight": 0
1090 | },
1091 | {
1092 | "source": "2",
1093 | "target": "4",
1094 | "sourceWeight": 10,
1095 | "targetWeight": 0
1096 | },
1097 | {
1098 | "source": "2",
1099 | "target": "5",
1100 | "sourceWeight": 10,
1101 | "targetWeight": 0
1102 | },
1103 | {
1104 | "source": "2",
1105 | "target": "6",
1106 | "sourceWeight": 10,
1107 | "targetWeight": 0
1108 | },
1109 | {
1110 | "source": "2",
1111 | "target": "8",
1112 | "sourceWeight": 10,
1113 | "targetWeight": 0
1114 | },
1115 | {
1116 | "source": "2",
1117 | "target": "10",
1118 | "sourceWeight": 10,
1119 | "targetWeight": 0
1120 | },
1121 | {
1122 | "source": "2",
1123 | "target": "17",
1124 | "sourceWeight": 10,
1125 | "targetWeight": 0
1126 | },
1127 | {
1128 | "source": "2",
1129 | "target": "27",
1130 | "sourceWeight": 10,
1131 | "targetWeight": 0
1132 | },
1133 | {
1134 | "source": "2",
1135 | "target": "28",
1136 | "sourceWeight": 10,
1137 | "targetWeight": 0
1138 | },
1139 | {
1140 | "source": "2",
1141 | "target": "29",
1142 | "sourceWeight": 10,
1143 | "targetWeight": 0
1144 | },
1145 | {
1146 | "source": "2",
1147 | "target": "30",
1148 | "sourceWeight": 10,
1149 | "targetWeight": 0
1150 | },
1151 | {
1152 | "source": "2",
1153 | "target": "33",
1154 | "sourceWeight": 10,
1155 | "targetWeight": 0
1156 | },
1157 | {
1158 | "source": "2",
1159 | "target": "38",
1160 | "sourceWeight": 10,
1161 | "targetWeight": 0
1162 | },
1163 | {
1164 | "source": "2",
1165 | "target": "41",
1166 | "sourceWeight": 10,
1167 | "targetWeight": 0
1168 | },
1169 | {
1170 | "source": "2",
1171 | "target": "45",
1172 | "sourceWeight": 10,
1173 | "targetWeight": 0
1174 | },
1175 | {
1176 | "source": "2",
1177 | "target": "50",
1178 | "sourceWeight": 10,
1179 | "targetWeight": 0
1180 | },
1181 | {
1182 | "source": "2",
1183 | "target": "52",
1184 | "sourceWeight": 10,
1185 | "targetWeight": 0
1186 | },
1187 | {
1188 | "source": "20",
1189 | "target": "21",
1190 | "sourceWeight": 10,
1191 | "targetWeight": 0
1192 | },
1193 | {
1194 | "source": "20",
1195 | "target": "27",
1196 | "sourceWeight": 10,
1197 | "targetWeight": 0
1198 | },
1199 | {
1200 | "source": "20",
1201 | "target": "28",
1202 | "sourceWeight": 10,
1203 | "targetWeight": 0
1204 | },
1205 | {
1206 | "source": "20",
1207 | "target": "29",
1208 | "sourceWeight": 10,
1209 | "targetWeight": 0
1210 | },
1211 | {
1212 | "source": "20",
1213 | "target": "30",
1214 | "sourceWeight": 10,
1215 | "targetWeight": 0
1216 | },
1217 | {
1218 | "source": "20",
1219 | "target": "34",
1220 | "sourceWeight": 10,
1221 | "targetWeight": 0
1222 | },
1223 | {
1224 | "source": "20",
1225 | "target": "53",
1226 | "sourceWeight": 10,
1227 | "targetWeight": 0
1228 | },
1229 | {
1230 | "source": "21",
1231 | "target": "22",
1232 | "sourceWeight": 10,
1233 | "targetWeight": 0
1234 | },
1235 | {
1236 | "source": "21",
1237 | "target": "23",
1238 | "sourceWeight": 10,
1239 | "targetWeight": 0
1240 | },
1241 | {
1242 | "source": "21",
1243 | "target": "24",
1244 | "sourceWeight": 10,
1245 | "targetWeight": 0
1246 | },
1247 | {
1248 | "source": "21",
1249 | "target": "25",
1250 | "sourceWeight": 10,
1251 | "targetWeight": 0
1252 | },
1253 | {
1254 | "source": "21",
1255 | "target": "26",
1256 | "sourceWeight": 10,
1257 | "targetWeight": 0
1258 | },
1259 | {
1260 | "source": "21",
1261 | "target": "27",
1262 | "sourceWeight": 10,
1263 | "targetWeight": 0
1264 | },
1265 | {
1266 | "source": "21",
1267 | "target": "28",
1268 | "sourceWeight": 10,
1269 | "targetWeight": 0
1270 | },
1271 | {
1272 | "source": "21",
1273 | "target": "29",
1274 | "sourceWeight": 10,
1275 | "targetWeight": 0
1276 | },
1277 | {
1278 | "source": "21",
1279 | "target": "30",
1280 | "sourceWeight": 10,
1281 | "targetWeight": 0
1282 | },
1283 | {
1284 | "source": "21",
1285 | "target": "34",
1286 | "sourceWeight": 10,
1287 | "targetWeight": 0
1288 | },
1289 | {
1290 | "source": "21",
1291 | "target": "53",
1292 | "sourceWeight": 10,
1293 | "targetWeight": 0
1294 | },
1295 | {
1296 | "source": "22",
1297 | "target": "23",
1298 | "sourceWeight": 10,
1299 | "targetWeight": 0
1300 | },
1301 | {
1302 | "source": "22",
1303 | "target": "24",
1304 | "sourceWeight": 10,
1305 | "targetWeight": 0
1306 | },
1307 | {
1308 | "source": "22",
1309 | "target": "25",
1310 | "sourceWeight": 10,
1311 | "targetWeight": 0
1312 | },
1313 | {
1314 | "source": "22",
1315 | "target": "26",
1316 | "sourceWeight": 10,
1317 | "targetWeight": 0
1318 | },
1319 | {
1320 | "source": "22",
1321 | "target": "27",
1322 | "sourceWeight": 10,
1323 | "targetWeight": 0
1324 | },
1325 | {
1326 | "source": "22",
1327 | "target": "28",
1328 | "sourceWeight": 10,
1329 | "targetWeight": 0
1330 | },
1331 | {
1332 | "source": "22",
1333 | "target": "29",
1334 | "sourceWeight": 10,
1335 | "targetWeight": 0
1336 | },
1337 | {
1338 | "source": "22",
1339 | "target": "30",
1340 | "sourceWeight": 10,
1341 | "targetWeight": 0
1342 | },
1343 | {
1344 | "source": "22",
1345 | "target": "36",
1346 | "sourceWeight": 10,
1347 | "targetWeight": 0
1348 | },
1349 | {
1350 | "source": "22",
1351 | "target": "51",
1352 | "sourceWeight": 10,
1353 | "targetWeight": 0
1354 | },
1355 | {
1356 | "source": "23",
1357 | "target": "24",
1358 | "sourceWeight": 10,
1359 | "targetWeight": 0
1360 | },
1361 | {
1362 | "source": "23",
1363 | "target": "25",
1364 | "sourceWeight": 10,
1365 | "targetWeight": 0
1366 | },
1367 | {
1368 | "source": "23",
1369 | "target": "26",
1370 | "sourceWeight": 10,
1371 | "targetWeight": 0
1372 | },
1373 | {
1374 | "source": "23",
1375 | "target": "27",
1376 | "sourceWeight": 10,
1377 | "targetWeight": 0
1378 | },
1379 | {
1380 | "source": "23",
1381 | "target": "28",
1382 | "sourceWeight": 10,
1383 | "targetWeight": 0
1384 | },
1385 | {
1386 | "source": "23",
1387 | "target": "29",
1388 | "sourceWeight": 10,
1389 | "targetWeight": 0
1390 | },
1391 | {
1392 | "source": "23",
1393 | "target": "30",
1394 | "sourceWeight": 10,
1395 | "targetWeight": 0
1396 | },
1397 | {
1398 | "source": "23",
1399 | "target": "37",
1400 | "sourceWeight": 10,
1401 | "targetWeight": 0
1402 | },
1403 | {
1404 | "source": "23",
1405 | "target": "48",
1406 | "sourceWeight": 10,
1407 | "targetWeight": 0
1408 | },
1409 | {
1410 | "source": "24",
1411 | "target": "25",
1412 | "sourceWeight": 10,
1413 | "targetWeight": 0
1414 | },
1415 | {
1416 | "source": "24",
1417 | "target": "26",
1418 | "sourceWeight": 10,
1419 | "targetWeight": 0
1420 | },
1421 | {
1422 | "source": "24",
1423 | "target": "27",
1424 | "sourceWeight": 10,
1425 | "targetWeight": 0
1426 | },
1427 | {
1428 | "source": "24",
1429 | "target": "28",
1430 | "sourceWeight": 10,
1431 | "targetWeight": 0
1432 | },
1433 | {
1434 | "source": "24",
1435 | "target": "29",
1436 | "sourceWeight": 10,
1437 | "targetWeight": 0
1438 | },
1439 | {
1440 | "source": "24",
1441 | "target": "30",
1442 | "sourceWeight": 10,
1443 | "targetWeight": 0
1444 | },
1445 | {
1446 | "source": "24",
1447 | "target": "36",
1448 | "sourceWeight": 10,
1449 | "targetWeight": 0
1450 | },
1451 | {
1452 | "source": "24",
1453 | "target": "51",
1454 | "sourceWeight": 10,
1455 | "targetWeight": 0
1456 | },
1457 | {
1458 | "source": "25",
1459 | "target": "26",
1460 | "sourceWeight": 10,
1461 | "targetWeight": 0
1462 | },
1463 | {
1464 | "source": "25",
1465 | "target": "27",
1466 | "sourceWeight": 10,
1467 | "targetWeight": 0
1468 | },
1469 | {
1470 | "source": "25",
1471 | "target": "28",
1472 | "sourceWeight": 10,
1473 | "targetWeight": 0
1474 | },
1475 | {
1476 | "source": "25",
1477 | "target": "29",
1478 | "sourceWeight": 10,
1479 | "targetWeight": 0
1480 | },
1481 | {
1482 | "source": "25",
1483 | "target": "30",
1484 | "sourceWeight": 10,
1485 | "targetWeight": 0
1486 | },
1487 | {
1488 | "source": "26",
1489 | "target": "27",
1490 | "sourceWeight": 10,
1491 | "targetWeight": 0
1492 | },
1493 | {
1494 | "source": "26",
1495 | "target": "28",
1496 | "sourceWeight": 10,
1497 | "targetWeight": 0
1498 | },
1499 | {
1500 | "source": "26",
1501 | "target": "29",
1502 | "sourceWeight": 10,
1503 | "targetWeight": 0
1504 | },
1505 | {
1506 | "source": "26",
1507 | "target": "30",
1508 | "sourceWeight": 10,
1509 | "targetWeight": 0
1510 | },
1511 | {
1512 | "source": "26",
1513 | "target": "36",
1514 | "sourceWeight": 10,
1515 | "targetWeight": 0
1516 | },
1517 | {
1518 | "source": "26",
1519 | "target": "51",
1520 | "sourceWeight": 10,
1521 | "targetWeight": 0
1522 | },
1523 | {
1524 | "source": "27",
1525 | "target": "28",
1526 | "sourceWeight": 10,
1527 | "targetWeight": 0
1528 | },
1529 | {
1530 | "source": "27",
1531 | "target": "29",
1532 | "sourceWeight": 10,
1533 | "targetWeight": 0
1534 | },
1535 | {
1536 | "source": "27",
1537 | "target": "30",
1538 | "sourceWeight": 10,
1539 | "targetWeight": 0
1540 | },
1541 | {
1542 | "source": "27",
1543 | "target": "34",
1544 | "sourceWeight": 10,
1545 | "targetWeight": 0
1546 | },
1547 | {
1548 | "source": "27",
1549 | "target": "53",
1550 | "sourceWeight": 10,
1551 | "targetWeight": 0
1552 | },
1553 | {
1554 | "source": "28",
1555 | "target": "29",
1556 | "sourceWeight": 10,
1557 | "targetWeight": 0
1558 | },
1559 | {
1560 | "source": "28",
1561 | "target": "30",
1562 | "sourceWeight": 10,
1563 | "targetWeight": 0
1564 | },
1565 | {
1566 | "source": "28",
1567 | "target": "32",
1568 | "sourceWeight": 10,
1569 | "targetWeight": 0
1570 | },
1571 | {
1572 | "source": "28",
1573 | "target": "42",
1574 | "sourceWeight": 10,
1575 | "targetWeight": 0
1576 | },
1577 | {
1578 | "source": "28",
1579 | "target": "44",
1580 | "sourceWeight": 10,
1581 | "targetWeight": 0
1582 | },
1583 | {
1584 | "source": "28",
1585 | "target": "48",
1586 | "sourceWeight": 10,
1587 | "targetWeight": 0
1588 | },
1589 | {
1590 | "source": "29",
1591 | "target": "30",
1592 | "sourceWeight": 10,
1593 | "targetWeight": 0
1594 | },
1595 | {
1596 | "source": "29",
1597 | "target": "43",
1598 | "sourceWeight": 10,
1599 | "targetWeight": 0
1600 | },
1601 | {
1602 | "source": "29",
1603 | "target": "49",
1604 | "sourceWeight": 10,
1605 | "targetWeight": 0
1606 | },
1607 | {
1608 | "source": "29",
1609 | "target": "50",
1610 | "sourceWeight": 10,
1611 | "targetWeight": 0
1612 | },
1613 | {
1614 | "source": "29",
1615 | "target": "51",
1616 | "sourceWeight": 10,
1617 | "targetWeight": 0
1618 | },
1619 | {
1620 | "source": "29",
1621 | "target": "52",
1622 | "sourceWeight": 10,
1623 | "targetWeight": 0
1624 | },
1625 | {
1626 | "source": "3",
1627 | "target": "4",
1628 | "sourceWeight": 10,
1629 | "targetWeight": 0
1630 | },
1631 | {
1632 | "source": "3",
1633 | "target": "5",
1634 | "sourceWeight": 10,
1635 | "targetWeight": 0
1636 | },
1637 | {
1638 | "source": "3",
1639 | "target": "6",
1640 | "sourceWeight": 10,
1641 | "targetWeight": 0
1642 | },
1643 | {
1644 | "source": "3",
1645 | "target": "10",
1646 | "sourceWeight": 10,
1647 | "targetWeight": 0
1648 | },
1649 | {
1650 | "source": "3",
1651 | "target": "17",
1652 | "sourceWeight": 10,
1653 | "targetWeight": 0
1654 | },
1655 | {
1656 | "source": "3",
1657 | "target": "19",
1658 | "sourceWeight": 10,
1659 | "targetWeight": 0
1660 | },
1661 | {
1662 | "source": "3",
1663 | "target": "27",
1664 | "sourceWeight": 10,
1665 | "targetWeight": 0
1666 | },
1667 | {
1668 | "source": "3",
1669 | "target": "28",
1670 | "sourceWeight": 10,
1671 | "targetWeight": 0
1672 | },
1673 | {
1674 | "source": "3",
1675 | "target": "29",
1676 | "sourceWeight": 10,
1677 | "targetWeight": 0
1678 | },
1679 | {
1680 | "source": "3",
1681 | "target": "30",
1682 | "sourceWeight": 10,
1683 | "targetWeight": 0
1684 | },
1685 | {
1686 | "source": "3",
1687 | "target": "32",
1688 | "sourceWeight": 10,
1689 | "targetWeight": 0
1690 | },
1691 | {
1692 | "source": "3",
1693 | "target": "42",
1694 | "sourceWeight": 10,
1695 | "targetWeight": 0
1696 | },
1697 | {
1698 | "source": "3",
1699 | "target": "44",
1700 | "sourceWeight": 10,
1701 | "targetWeight": 0
1702 | },
1703 | {
1704 | "source": "3",
1705 | "target": "48",
1706 | "sourceWeight": 10,
1707 | "targetWeight": 0
1708 | },
1709 | {
1710 | "source": "30",
1711 | "target": "32",
1712 | "sourceWeight": 10,
1713 | "targetWeight": 0
1714 | },
1715 | {
1716 | "source": "30",
1717 | "target": "42",
1718 | "sourceWeight": 10,
1719 | "targetWeight": 0
1720 | },
1721 | {
1722 | "source": "30",
1723 | "target": "44",
1724 | "sourceWeight": 10,
1725 | "targetWeight": 0
1726 | },
1727 | {
1728 | "source": "30",
1729 | "target": "48",
1730 | "sourceWeight": 10,
1731 | "targetWeight": 0
1732 | },
1733 | {
1734 | "source": "31",
1735 | "target": "32",
1736 | "sourceWeight": 10,
1737 | "targetWeight": 0
1738 | },
1739 | {
1740 | "source": "31",
1741 | "target": "33",
1742 | "sourceWeight": 10,
1743 | "targetWeight": 0
1744 | },
1745 | {
1746 | "source": "31",
1747 | "target": "34",
1748 | "sourceWeight": 10,
1749 | "targetWeight": 0
1750 | },
1751 | {
1752 | "source": "31",
1753 | "target": "35",
1754 | "sourceWeight": 10,
1755 | "targetWeight": 0
1756 | },
1757 | {
1758 | "source": "31",
1759 | "target": "36",
1760 | "sourceWeight": 10,
1761 | "targetWeight": 0
1762 | },
1763 | {
1764 | "source": "31",
1765 | "target": "51",
1766 | "sourceWeight": 10,
1767 | "targetWeight": 0
1768 | },
1769 | {
1770 | "source": "32",
1771 | "target": "33",
1772 | "sourceWeight": 10,
1773 | "targetWeight": 0
1774 | },
1775 | {
1776 | "source": "32",
1777 | "target": "34",
1778 | "sourceWeight": 10,
1779 | "targetWeight": 0
1780 | },
1781 | {
1782 | "source": "32",
1783 | "target": "35",
1784 | "sourceWeight": 10,
1785 | "targetWeight": 0
1786 | },
1787 | {
1788 | "source": "32",
1789 | "target": "42",
1790 | "sourceWeight": 10,
1791 | "targetWeight": 0
1792 | },
1793 | {
1794 | "source": "32",
1795 | "target": "44",
1796 | "sourceWeight": 10,
1797 | "targetWeight": 0
1798 | },
1799 | {
1800 | "source": "32",
1801 | "target": "48",
1802 | "sourceWeight": 10,
1803 | "targetWeight": 0
1804 | },
1805 | {
1806 | "source": "33",
1807 | "target": "34",
1808 | "sourceWeight": 10,
1809 | "targetWeight": 0
1810 | },
1811 | {
1812 | "source": "33",
1813 | "target": "35",
1814 | "sourceWeight": 10,
1815 | "targetWeight": 0
1816 | },
1817 | {
1818 | "source": "33",
1819 | "target": "38",
1820 | "sourceWeight": 10,
1821 | "targetWeight": 0
1822 | },
1823 | {
1824 | "source": "33",
1825 | "target": "41",
1826 | "sourceWeight": 10,
1827 | "targetWeight": 0
1828 | },
1829 | {
1830 | "source": "33",
1831 | "target": "45",
1832 | "sourceWeight": 10,
1833 | "targetWeight": 0
1834 | },
1835 | {
1836 | "source": "33",
1837 | "target": "50",
1838 | "sourceWeight": 10,
1839 | "targetWeight": 0
1840 | },
1841 | {
1842 | "source": "33",
1843 | "target": "52",
1844 | "sourceWeight": 10,
1845 | "targetWeight": 0
1846 | },
1847 | {
1848 | "source": "34",
1849 | "target": "35",
1850 | "sourceWeight": 10,
1851 | "targetWeight": 0
1852 | },
1853 | {
1854 | "source": "34",
1855 | "target": "36",
1856 | "sourceWeight": 10,
1857 | "targetWeight": 0
1858 | },
1859 | {
1860 | "source": "34",
1861 | "target": "51",
1862 | "sourceWeight": 10,
1863 | "targetWeight": 0
1864 | },
1865 | {
1866 | "source": "34",
1867 | "target": "53",
1868 | "sourceWeight": 10,
1869 | "targetWeight": 0
1870 | },
1871 | {
1872 | "source": "35",
1873 | "target": "36",
1874 | "sourceWeight": 10,
1875 | "targetWeight": 0
1876 | },
1877 | {
1878 | "source": "35",
1879 | "target": "51",
1880 | "sourceWeight": 10,
1881 | "targetWeight": 0
1882 | },
1883 | {
1884 | "source": "36",
1885 | "target": "37",
1886 | "sourceWeight": 10,
1887 | "targetWeight": 0
1888 | },
1889 | {
1890 | "source": "36",
1891 | "target": "38",
1892 | "sourceWeight": 10,
1893 | "targetWeight": 0
1894 | },
1895 | {
1896 | "source": "36",
1897 | "target": "51",
1898 | "sourceWeight": 10,
1899 | "targetWeight": 0
1900 | },
1901 | {
1902 | "source": "37",
1903 | "target": "38",
1904 | "sourceWeight": 10,
1905 | "targetWeight": 0
1906 | },
1907 | {
1908 | "source": "37",
1909 | "target": "48",
1910 | "sourceWeight": 10,
1911 | "targetWeight": 0
1912 | },
1913 | {
1914 | "source": "38",
1915 | "target": "41",
1916 | "sourceWeight": 10,
1917 | "targetWeight": 0
1918 | },
1919 | {
1920 | "source": "38",
1921 | "target": "45",
1922 | "sourceWeight": 10,
1923 | "targetWeight": 0
1924 | },
1925 | {
1926 | "source": "38",
1927 | "target": "50",
1928 | "sourceWeight": 10,
1929 | "targetWeight": 0
1930 | },
1931 | {
1932 | "source": "38",
1933 | "target": "52",
1934 | "sourceWeight": 10,
1935 | "targetWeight": 0
1936 | },
1937 | {
1938 | "source": "39",
1939 | "target": "40",
1940 | "sourceWeight": 10,
1941 | "targetWeight": 0
1942 | },
1943 | {
1944 | "source": "39",
1945 | "target": "41",
1946 | "sourceWeight": 10,
1947 | "targetWeight": 0
1948 | },
1949 | {
1950 | "source": "39",
1951 | "target": "42",
1952 | "sourceWeight": 10,
1953 | "targetWeight": 0
1954 | },
1955 | {
1956 | "source": "39",
1957 | "target": "43",
1958 | "sourceWeight": 10,
1959 | "targetWeight": 0
1960 | },
1961 | {
1962 | "source": "39",
1963 | "target": "46",
1964 | "sourceWeight": 10,
1965 | "targetWeight": 0
1966 | },
1967 | {
1968 | "source": "39",
1969 | "target": "47",
1970 | "sourceWeight": 10,
1971 | "targetWeight": 0
1972 | },
1973 | {
1974 | "source": "39",
1975 | "target": "54",
1976 | "sourceWeight": 10,
1977 | "targetWeight": 0
1978 | },
1979 | {
1980 | "source": "4",
1981 | "target": "5",
1982 | "sourceWeight": 10,
1983 | "targetWeight": 0
1984 | },
1985 | {
1986 | "source": "4",
1987 | "target": "6",
1988 | "sourceWeight": 10,
1989 | "targetWeight": 0
1990 | },
1991 | {
1992 | "source": "4",
1993 | "target": "10",
1994 | "sourceWeight": 10,
1995 | "targetWeight": 0
1996 | },
1997 | {
1998 | "source": "4",
1999 | "target": "17",
2000 | "sourceWeight": 10,
2001 | "targetWeight": 0
2002 | },
2003 | {
2004 | "source": "4",
2005 | "target": "20",
2006 | "sourceWeight": 10,
2007 | "targetWeight": 0
2008 | },
2009 | {
2010 | "source": "4",
2011 | "target": "21",
2012 | "sourceWeight": 10,
2013 | "targetWeight": 0
2014 | },
2015 | {
2016 | "source": "4",
2017 | "target": "27",
2018 | "sourceWeight": 10,
2019 | "targetWeight": 0
2020 | },
2021 | {
2022 | "source": "4",
2023 | "target": "28",
2024 | "sourceWeight": 10,
2025 | "targetWeight": 0
2026 | },
2027 | {
2028 | "source": "4",
2029 | "target": "29",
2030 | "sourceWeight": 10,
2031 | "targetWeight": 0
2032 | },
2033 | {
2034 | "source": "4",
2035 | "target": "30",
2036 | "sourceWeight": 10,
2037 | "targetWeight": 0
2038 | },
2039 | {
2040 | "source": "4",
2041 | "target": "34",
2042 | "sourceWeight": 10,
2043 | "targetWeight": 0
2044 | },
2045 | {
2046 | "source": "4",
2047 | "target": "53",
2048 | "sourceWeight": 10,
2049 | "targetWeight": 0
2050 | },
2051 | {
2052 | "source": "40",
2053 | "target": "41",
2054 | "sourceWeight": 10,
2055 | "targetWeight": 0
2056 | },
2057 | {
2058 | "source": "40",
2059 | "target": "42",
2060 | "sourceWeight": 10,
2061 | "targetWeight": 0
2062 | },
2063 | {
2064 | "source": "40",
2065 | "target": "43",
2066 | "sourceWeight": 10,
2067 | "targetWeight": 0
2068 | },
2069 | {
2070 | "source": "41",
2071 | "target": "42",
2072 | "sourceWeight": 10,
2073 | "targetWeight": 0
2074 | },
2075 | {
2076 | "source": "41",
2077 | "target": "43",
2078 | "sourceWeight": 10,
2079 | "targetWeight": 0
2080 | },
2081 | {
2082 | "source": "41",
2083 | "target": "45",
2084 | "sourceWeight": 10,
2085 | "targetWeight": 0
2086 | },
2087 | {
2088 | "source": "41",
2089 | "target": "50",
2090 | "sourceWeight": 10,
2091 | "targetWeight": 0
2092 | },
2093 | {
2094 | "source": "41",
2095 | "target": "52",
2096 | "sourceWeight": 10,
2097 | "targetWeight": 0
2098 | },
2099 | {
2100 | "source": "42",
2101 | "target": "43",
2102 | "sourceWeight": 10,
2103 | "targetWeight": 0
2104 | },
2105 | {
2106 | "source": "42",
2107 | "target": "44",
2108 | "sourceWeight": 10,
2109 | "targetWeight": 0
2110 | },
2111 | {
2112 | "source": "42",
2113 | "target": "48",
2114 | "sourceWeight": 10,
2115 | "targetWeight": 0
2116 | },
2117 | {
2118 | "source": "43",
2119 | "target": "49",
2120 | "sourceWeight": 10,
2121 | "targetWeight": 0
2122 | },
2123 | {
2124 | "source": "43",
2125 | "target": "50",
2126 | "sourceWeight": 10,
2127 | "targetWeight": 0
2128 | },
2129 | {
2130 | "source": "43",
2131 | "target": "51",
2132 | "sourceWeight": 10,
2133 | "targetWeight": 0
2134 | },
2135 | {
2136 | "source": "43",
2137 | "target": "52",
2138 | "sourceWeight": 10,
2139 | "targetWeight": 0
2140 | },
2141 | {
2142 | "source": "44",
2143 | "target": "45",
2144 | "sourceWeight": 10,
2145 | "targetWeight": 0
2146 | },
2147 | {
2148 | "source": "44",
2149 | "target": "46",
2150 | "sourceWeight": 10,
2151 | "targetWeight": 0
2152 | },
2153 | {
2154 | "source": "44",
2155 | "target": "47",
2156 | "sourceWeight": 10,
2157 | "targetWeight": 0
2158 | },
2159 | {
2160 | "source": "44",
2161 | "target": "48",
2162 | "sourceWeight": 10,
2163 | "targetWeight": 0
2164 | },
2165 | {
2166 | "source": "45",
2167 | "target": "46",
2168 | "sourceWeight": 10,
2169 | "targetWeight": 0
2170 | },
2171 | {
2172 | "source": "45",
2173 | "target": "47",
2174 | "sourceWeight": 10,
2175 | "targetWeight": 0
2176 | },
2177 | {
2178 | "source": "45",
2179 | "target": "48",
2180 | "sourceWeight": 10,
2181 | "targetWeight": 0
2182 | },
2183 | {
2184 | "source": "45",
2185 | "target": "50",
2186 | "sourceWeight": 10,
2187 | "targetWeight": 0
2188 | },
2189 | {
2190 | "source": "45",
2191 | "target": "52",
2192 | "sourceWeight": 10,
2193 | "targetWeight": 0
2194 | },
2195 | {
2196 | "source": "46",
2197 | "target": "47",
2198 | "sourceWeight": 10,
2199 | "targetWeight": 0
2200 | },
2201 | {
2202 | "source": "46",
2203 | "target": "48",
2204 | "sourceWeight": 10,
2205 | "targetWeight": 0
2206 | },
2207 | {
2208 | "source": "46",
2209 | "target": "54",
2210 | "sourceWeight": 10,
2211 | "targetWeight": 0
2212 | },
2213 | {
2214 | "source": "47",
2215 | "target": "48",
2216 | "sourceWeight": 10,
2217 | "targetWeight": 0
2218 | },
2219 | {
2220 | "source": "47",
2221 | "target": "54",
2222 | "sourceWeight": 10,
2223 | "targetWeight": 0
2224 | },
2225 | {
2226 | "source": "49",
2227 | "target": "50",
2228 | "sourceWeight": 10,
2229 | "targetWeight": 0
2230 | },
2231 | {
2232 | "source": "49",
2233 | "target": "51",
2234 | "sourceWeight": 10,
2235 | "targetWeight": 0
2236 | },
2237 | {
2238 | "source": "49",
2239 | "target": "52",
2240 | "sourceWeight": 10,
2241 | "targetWeight": 0
2242 | },
2243 | {
2244 | "source": "5",
2245 | "target": "6",
2246 | "sourceWeight": 10,
2247 | "targetWeight": 0
2248 | },
2249 | {
2250 | "source": "5",
2251 | "target": "10",
2252 | "sourceWeight": 10,
2253 | "targetWeight": 0
2254 | },
2255 | {
2256 | "source": "5",
2257 | "target": "12",
2258 | "sourceWeight": 10,
2259 | "targetWeight": 0
2260 | },
2261 | {
2262 | "source": "5",
2263 | "target": "16",
2264 | "sourceWeight": 10,
2265 | "targetWeight": 0
2266 | },
2267 | {
2268 | "source": "5",
2269 | "target": "17",
2270 | "sourceWeight": 10,
2271 | "targetWeight": 0
2272 | },
2273 | {
2274 | "source": "5",
2275 | "target": "27",
2276 | "sourceWeight": 10,
2277 | "targetWeight": 0
2278 | },
2279 | {
2280 | "source": "5",
2281 | "target": "28",
2282 | "sourceWeight": 10,
2283 | "targetWeight": 0
2284 | },
2285 | {
2286 | "source": "5",
2287 | "target": "29",
2288 | "sourceWeight": 10,
2289 | "targetWeight": 0
2290 | },
2291 | {
2292 | "source": "5",
2293 | "target": "30",
2294 | "sourceWeight": 10,
2295 | "targetWeight": 0
2296 | },
2297 | {
2298 | "source": "50",
2299 | "target": "51",
2300 | "sourceWeight": 10,
2301 | "targetWeight": 0
2302 | },
2303 | {
2304 | "source": "50",
2305 | "target": "52",
2306 | "sourceWeight": 10,
2307 | "targetWeight": 0
2308 | },
2309 | {
2310 | "source": "51",
2311 | "target": "52",
2312 | "sourceWeight": 10,
2313 | "targetWeight": 0
2314 | },
2315 | {
2316 | "source": "53",
2317 | "target": "54",
2318 | "sourceWeight": 10,
2319 | "targetWeight": 0
2320 | },
2321 | {
2322 | "source": "53",
2323 | "target": "55",
2324 | "sourceWeight": 10,
2325 | "targetWeight": 0
2326 | },
2327 | {
2328 | "source": "54",
2329 | "target": "55",
2330 | "sourceWeight": 10,
2331 | "targetWeight": 0
2332 | },
2333 | {
2334 | "source": "6",
2335 | "target": "7",
2336 | "sourceWeight": 10,
2337 | "targetWeight": 0
2338 | },
2339 | {
2340 | "source": "6",
2341 | "target": "10",
2342 | "sourceWeight": 10,
2343 | "targetWeight": 0
2344 | },
2345 | {
2346 | "source": "6",
2347 | "target": "17",
2348 | "sourceWeight": 10,
2349 | "targetWeight": 0
2350 | },
2351 | {
2352 | "source": "6",
2353 | "target": "18",
2354 | "sourceWeight": 10,
2355 | "targetWeight": 0
2356 | },
2357 | {
2358 | "source": "6",
2359 | "target": "19",
2360 | "sourceWeight": 10,
2361 | "targetWeight": 0
2362 | },
2363 | {
2364 | "source": "6",
2365 | "target": "20",
2366 | "sourceWeight": 10,
2367 | "targetWeight": 0
2368 | },
2369 | {
2370 | "source": "6",
2371 | "target": "27",
2372 | "sourceWeight": 10,
2373 | "targetWeight": 0
2374 | },
2375 | {
2376 | "source": "6",
2377 | "target": "28",
2378 | "sourceWeight": 10,
2379 | "targetWeight": 0
2380 | },
2381 | {
2382 | "source": "6",
2383 | "target": "29",
2384 | "sourceWeight": 10,
2385 | "targetWeight": 0
2386 | },
2387 | {
2388 | "source": "6",
2389 | "target": "30",
2390 | "sourceWeight": 10,
2391 | "targetWeight": 0
2392 | },
2393 | {
2394 | "source": "6",
2395 | "target": "40",
2396 | "sourceWeight": 10,
2397 | "targetWeight": 0
2398 | },
2399 | {
2400 | "source": "6",
2401 | "target": "43",
2402 | "sourceWeight": 10,
2403 | "targetWeight": 0
2404 | },
2405 | {
2406 | "source": "7",
2407 | "target": "8",
2408 | "sourceWeight": 10,
2409 | "targetWeight": 0
2410 | },
2411 | {
2412 | "source": "7",
2413 | "target": "9",
2414 | "sourceWeight": 10,
2415 | "targetWeight": 0
2416 | },
2417 | {
2418 | "source": "7",
2419 | "target": "10",
2420 | "sourceWeight": 10,
2421 | "targetWeight": 0
2422 | },
2423 | {
2424 | "source": "7",
2425 | "target": "17",
2426 | "sourceWeight": 10,
2427 | "targetWeight": 0
2428 | },
2429 | {
2430 | "source": "7",
2431 | "target": "27",
2432 | "sourceWeight": 10,
2433 | "targetWeight": 0
2434 | },
2435 | {
2436 | "source": "7",
2437 | "target": "28",
2438 | "sourceWeight": 10,
2439 | "targetWeight": 0
2440 | },
2441 | {
2442 | "source": "7",
2443 | "target": "29",
2444 | "sourceWeight": 10,
2445 | "targetWeight": 0
2446 | },
2447 | {
2448 | "source": "7",
2449 | "target": "30",
2450 | "sourceWeight": 10,
2451 | "targetWeight": 0
2452 | },
2453 | {
2454 | "source": "7",
2455 | "target": "40",
2456 | "sourceWeight": 10,
2457 | "targetWeight": 0
2458 | },
2459 | {
2460 | "source": "7",
2461 | "target": "43",
2462 | "sourceWeight": 10,
2463 | "targetWeight": 0
2464 | },
2465 | {
2466 | "source": "8",
2467 | "target": "9",
2468 | "sourceWeight": 10,
2469 | "targetWeight": 0
2470 | },
2471 | {
2472 | "source": "8",
2473 | "target": "10",
2474 | "sourceWeight": 10,
2475 | "targetWeight": 0
2476 | },
2477 | {
2478 | "source": "8",
2479 | "target": "17",
2480 | "sourceWeight": 10,
2481 | "targetWeight": 0
2482 | },
2483 | {
2484 | "source": "8",
2485 | "target": "27",
2486 | "sourceWeight": 10,
2487 | "targetWeight": 0
2488 | },
2489 | {
2490 | "source": "8",
2491 | "target": "28",
2492 | "sourceWeight": 10,
2493 | "targetWeight": 0
2494 | },
2495 | {
2496 | "source": "8",
2497 | "target": "29",
2498 | "sourceWeight": 10,
2499 | "targetWeight": 0
2500 | },
2501 | {
2502 | "source": "8",
2503 | "target": "30",
2504 | "sourceWeight": 10,
2505 | "targetWeight": 0
2506 | },
2507 | {
2508 | "source": "8",
2509 | "target": "33",
2510 | "sourceWeight": 10,
2511 | "targetWeight": 0
2512 | },
2513 | {
2514 | "source": "8",
2515 | "target": "38",
2516 | "sourceWeight": 10,
2517 | "targetWeight": 0
2518 | },
2519 | {
2520 | "source": "8",
2521 | "target": "41",
2522 | "sourceWeight": 10,
2523 | "targetWeight": 0
2524 | },
2525 | {
2526 | "source": "8",
2527 | "target": "45",
2528 | "sourceWeight": 10,
2529 | "targetWeight": 0
2530 | },
2531 | {
2532 | "source": "8",
2533 | "target": "50",
2534 | "sourceWeight": 10,
2535 | "targetWeight": 0
2536 | },
2537 | {
2538 | "source": "8",
2539 | "target": "52",
2540 | "sourceWeight": 10,
2541 | "targetWeight": 0
2542 | },
2543 | {
2544 | "source": "9",
2545 | "target": "10",
2546 | "sourceWeight": 10,
2547 | "targetWeight": 0
2548 | },
2549 | {
2550 | "source": "9",
2551 | "target": "11",
2552 | "sourceWeight": 10,
2553 | "targetWeight": 0
2554 | },
2555 | {
2556 | "source": "9",
2557 | "target": "17",
2558 | "sourceWeight": 10,
2559 | "targetWeight": 0
2560 | },
2561 | {
2562 | "source": "9",
2563 | "target": "25",
2564 | "sourceWeight": 10,
2565 | "targetWeight": 0
2566 | },
2567 | {
2568 | "source": "9",
2569 | "target": "27",
2570 | "sourceWeight": 10,
2571 | "targetWeight": 0
2572 | },
2573 | {
2574 | "source": "9",
2575 | "target": "28",
2576 | "sourceWeight": 10,
2577 | "targetWeight": 0
2578 | },
2579 | {
2580 | "source": "9",
2581 | "target": "29",
2582 | "sourceWeight": 10,
2583 | "targetWeight": 0
2584 | },
2585 | {
2586 | "source": "9",
2587 | "target": "30",
2588 | "sourceWeight": 10,
2589 | "targetWeight": 0
2590 | }
2591 | ]
2592 | }
--------------------------------------------------------------------------------