Python实现LOLM 英雄数据对比分析与打法流派建议系统模型
LOLM 英雄数据对比分析与打法流派建议系统由于Riot未开放LOLM实时API代码采用「数据适配器」模式用模拟数据演示完整逻辑可方便替换为真实数据源。数据获取说明当前LOLM数据获取面临以下现状· Riot开放了部分公开API英雄基础数据、历史对局信息但关键的实时BP数据和分路调整被严格限制· 手游数据查询接口尚未完全开放通过game.gtimg.cn域名下的JS文件可获取部分英雄列表和皮肤数据· 第三方平台如LoLMeta App可查看各段位英雄胜率、登场率与禁用率掌上英雄联盟App也提供攻略分页下的段位数据· 英雄评分机制已细化到对线补刀、换血、推线、团战输出占比、承伤比例、控制效果、参团率和视野控制等维度因此代码设计了 LOLMDataProvider 抽象类包含 fetch_champion_stats() 和 fetch_player_hexagon() 两个核心方法便于替换为真实数据源。下方示例使用内置模拟数据。pythonLOLM 英雄数据对比分析与打法流派建议系统功能:1. 不同英雄在多段位下的官方统计数据对比胜率/出场率/禁用率/KDA等2. 玩家六边形能力雷达图可视化与对比3. 基于数据特征自动生成英雄不同流派的精进建议依赖: numpy, matplotlib, pandasimport numpy as npimport matplotlib.pyplot as pltimport pandas as pdfrom abc import ABC, abstractmethodfrom dataclasses import dataclass, fieldfrom typing import Optional# 中文字体配置plt.rcParams[font.sans-serif] [SimHei, Microsoft YaHei, DejaVu Sans]plt.rcParams[axes.unicode_minus] False# # 第一部分数据模型与数据提供器# dataclassclass ChampionStats:单个英雄在特定段位的统计数据champion: strrole: strrank_tier: strwin_rate: float # 胜率 %pick_rate: float # 出场率 %ban_rate: float # 禁用率 %avg_kda: float # 平均KDAavg_damage: float # 场均伤害avg_damage_taken: float # 场均承伤avg_gold: float # 场均经济avg_vision: float # 场均视野得分avg_kill_participation: float # 参团率 %avg_game_duration: float 16.5 # 场均游戏时长(分钟)dataclassclass PlayerHexagon:玩家六边形能力数据player_name: strchampion: strcombat: float # 战斗 (输出击杀)survival: float # 生存 (KDA承伤)farming: float # 发育 (经济补刀)support: float # 支援 (参团率助攻)vision: float # 视野 (视野得分)pushing: float # 推进 (推塔兵线)class LOLMDataProvider(ABC):数据提供器抽象基类 - 替换为真实数据源时继承此类abstractmethoddef fetch_champion_stats(self, champion: str, rank_tier: str) - ChampionStats:...abstractmethoddef fetch_player_hexagon(self, player_name: str, champion: str) - PlayerHexagon:...class MockDataProvider(LOLMDataProvider):模拟数据提供器演示用实际使用时替换为真实API调用def __init__(self):# 模拟英雄基础数据基于版本典型值self._champion_data {薇恩: {ADC: {钻石: ChampionStats(薇恩, ADC, 钻石, 51.8, 12.5, 8.3, 3.2, 18500, 14200, 12800, 22, 62.5),大师: ChampionStats(薇恩, ADC, 大师, 53.4, 14.2, 10.1, 3.5, 19200, 13800, 13100, 25, 64.8),王者: ChampionStats(薇恩, ADC, 王者, 54.7, 16.8, 12.5, 3.8, 20100, 13400, 13500, 28, 67.2),}},劫: {中单: {钻石: ChampionStats(劫, 中单, 钻石, 50.2, 10.8, 15.2, 2.9, 21000, 12500, 13200, 18, 58.3),大师: ChampionStats(劫, 中单, 大师, 52.1, 12.6, 17.8, 3.1, 22300, 12100, 13800, 21, 61.0),王者: ChampionStats(劫, 中单, 王者, 53.5, 14.3, 20.1, 3.4, 23500, 11800, 14200, 24, 63.5),}},韦鲁斯: {ADC: {钻石: ChampionStats(韦鲁斯, ADC, 钻石, 50.5, 8.2, 5.1, 2.8, 19500, 13100, 12500, 19, 60.1),大师: ChampionStats(韦鲁斯, ADC, 大师, 51.9, 9.8, 6.3, 3.0, 20800, 12800, 12900, 22, 62.4),王者: ChampionStats(韦鲁斯, ADC, 王者, 53.2, 11.5, 7.8, 3.3, 21600, 12400, 13300, 26, 65.0),}},}# 模拟玩家六边形数据self._player_data {玩家A_薇恩: PlayerHexagon(玩家A, 薇恩, 92, 58, 88, 65, 42, 78),玩家A_劫: PlayerHexagon(玩家A, 劫, 88, 62, 75, 70, 38, 82),玩家A_韦鲁斯: PlayerHexagon(玩家A, 韦鲁斯, 75, 70, 85, 72, 55, 68),基准_钻石ADC: PlayerHexagon(钻石平均, ADC, 70, 65, 72, 68, 60, 65),基准_大师ADC: PlayerHexagon(大师平均, ADC, 78, 72, 78, 74, 68, 72),基准_王者ADC: PlayerHexagon(王者平均, ADC, 85, 78, 85, 80, 75, 78),}def fetch_champion_stats(self, champion: str, rank_tier: str) - ChampionStats:role_map {薇恩: ADC, 劫: 中单, 韦鲁斯: ADC}role role_map.get(champion, ADC)return self._champion_data[champion][role][rank_tier]def fetch_player_hexagon(self, player_name: str, champion: str) - PlayerHexagon:key f{player_name}_{champion}return self._player_data.get(key, self._player_data[基准_钻石ADC])# # 第二部分数据分析引擎# class ChampionAnalyzer:英雄数据分析引擎def __init__(self, provider: LOLMDataProvider):self.provider providerdef compare_champions(self, champions: list, rank_tiers: list) - pd.DataFrame:多英雄 × 多段位 数据对比返回DataFramerecords []for champ in champions:for tier in rank_tiers:stats self.provider.fetch_champion_stats(champ, tier)records.append({英雄: stats.champion,段位: stats.rank_tier,定位: stats.role,胜率%: stats.win_rate,出场率%: stats.pick_rate,禁用率%: stats.ban_rate,平均KDA: stats.avg_kda,场均伤害: stats.avg_damage,场均承伤: stats.avg_damage_taken,场均经济: stats.avg_gold,场均视野: stats.avg_vision,参团率%: stats.avg_kill_participation,})return pd.DataFrame(records)def get_hexagon_comparison(self, player_name: str,champions: list,benchmark_key: str 基准_钻石ADC) - dict:获取玩家多个英雄的六边形数据 vs 基准数据result {}for champ in champions:result[champ] self.provider.fetch_player_hexagon(player_name, champ)result[_benchmark] self.provider.fetch_player_hexagon(benchmark_key.split(_)[0], benchmark_key.split(_)[1]if _ in benchmark_key else ADC)return result# # 第三部分可视化模块# class LOLMVisualizer:LOLM数据可视化DIMENSIONS [战斗, 生存, 发育, 支援, 视野, 推进]staticmethoddef plot_radar(player_data_list: list, title: str 玩家六边形能力对比,benchmark: Optional[PlayerHexagon] None,figsize: tuple (8, 8)):绘制六边形能力雷达图n_dims len(LOLMVisualizer.DIMENSIONS)angles np.linspace(0, 2 * np.pi, n_dims, endpointFalse)angles_closed np.concatenate((angles, [angles[0]]))fig, ax plt.subplots(figsizefigsize, subplot_kwdict(polarTrue))ax.set_ylim(0, 105)colors [#E74C3C, #3498DB, #2ECC71, #F39C12, #9B59B6]for idx, player in enumerate(player_data_list):values [player.combat, player.survival, player.farming,player.support, player.vision, player.pushing]values_closed np.concatenate((values, [values[0]]))color colors[idx % len(colors)]ax.plot(angles_closed, values_closed, o-, colorcolor,linewidth2, labelf{player.player_name}-{player.champion})ax.fill(angles_closed, values_closed, colorcolor, alpha0.12)# 绘制基准线if benchmark:bm_values [benchmark.combat, benchmark.survival, benchmark.farming,benchmark.support, benchmark.vision, benchmark.pushing]bm_closed np.concatenate((bm_values, [bm_values[0]]))ax.plot(angles_closed, bm_closed, --, colorgray,linewidth1.5, labelf基准线({benchmark.player_name}))# 美化ax.set_thetagrids(angles * 180 / np.pi, LOLMVisualizer.DIMENSIONS, fontsize13)ax.set_rlabel_position(0)ax.set_yticklabels([20, 40, 60, 80, 100], colorgrey, size9)ax.set_title(title, size16, y1.08)ax.legend(locupper right, bbox_to_anchor(1.35, 1.1), fontsize10)ax.grid(True, alpha0.4)plt.tight_layout()plt.savefig(lolm_radar.png, dpi150, bbox_inchestight)plt.show()staticmethoddef plot_winrate_comparison(df: pd.DataFrame, figsize: tuple (12, 6)):绘制多英雄多段位胜率对比柱状图champions df[英雄].unique()tiers df[段位].unique()x np.arange(len(champions))width 0.8 / len(tiers)colors [#3498DB, #E74C3C, #2ECC71]fig, ax plt.subplots(figsizefigsize)for i, tier in enumerate(tiers):tier_df df[df[段位] tier]winrates [tier_df[tier_df[英雄] c][胜率%].values[0]for c in champions]bars ax.bar(x i * width, winrates, width, labeltier,colorcolors[i % len(colors)], alpha0.85)for bar, wr in zip(bars, winrates):ax.text(bar.get_x() bar.get_width() / 2, bar.get_height() 0.3,f{wr:.1f}%, hacenter, vabottom, fontsize9)ax.set_xlabel(英雄, fontsize13)ax.set_ylabel(胜率 (%), fontsize13)ax.set_title(LOLM 不同英雄各段位胜率对比, fontsize16)ax.set_xticks(x width * (len(tiers) - 1) / 2)ax.set_xticklabels(champions, fontsize12)ax.legend(fontsize11)ax.grid(axisy, alpha0.3)ax.set_ylim(0, 65)plt.tight_layout()plt.savefig(lolm_winrate.png, dpi150, bbox_inchestight)plt.show()staticmethoddef plot_hexagon_deviation(player_data: PlayerHexagon,benchmark: PlayerHexagon,figsize: tuple (8, 6)):绘制玩家六边形能力与基准值的偏差图dims LOLMVisualizer.DIMENSIONSplayer_vals [player_data.combat, player_data.survival,player_data.farming, player_data.support,player_data.vision, player_data.pushing]bm_vals [benchmark.combat, benchmark.survival, benchmark.farming,benchmark.support, benchmark.vision, benchmark.pushing]deviations [p - b for p, b in zip(player_vals, bm_vals)]colors [#2ECC71 if d 0 else #E74C3C for d in deviations]fig, ax plt.subplots(figsizefigsize)bars ax.barh(dims, deviations, colorcolors, alpha0.85, height0.6)ax.axvline(0, colorblack, linewidth0.8)for bar, d in zip(bars, deviations):offset 1 if d 0 else -1ax.text(bar.get_width() offset * 0.5, bar.get_y() bar.get_height() / 2,f{d:.0f}, vacenter, fontsize11,haleft if d 0 else right)ax.set_xlabel(与基准值偏差, fontsize12)ax.set_title(f{player_data.player_name}({player_data.champion}) f能力偏差分析, fontsize15)ax.grid(axisx, alpha0.3)plt.tight_layout()plt.savefig(lolm_deviation.png, dpi150, bbox_inchestight)plt.show()# # 第四部分流派建议生成器# class BuildAdvisor:基于英雄数据特征和玩家能力画像自动生成不同流派的精进建议。每个英雄预置多套流派模板通过玩家能力偏差动态筛选和排序。# 流派知识库英雄 - 流派列表BUILD_TEMPLATES {薇恩: [{name: 攻速特效流,key_stats: [combat, farming],description: 核心依赖破败王者之刃鬼索的狂暴之刃智慧末刃三件套百分比真实伤害使薇恩对前排坦克也有稳定输出能力。,runes: 致命节奏 传说血统 骸骨镀层,tips: [对线期利用W技能被动三环快速消耗补刀触发被动获得攻速加成,团战保持后排站位优先攻击距离最近目标触发三环,利用RQ翻滚隐身调整输出位置避免被先手控制,],},{name: 暴击爆发流,key_stats: [combat, survival],description: 出装以无尽之刃疾射火炮幻影之舞为核心追求单次暴击高额爆发适合对方阵容偏脆时使用。,runes: 强攻 凯旋 致命一击,tips: [利用E技能将敌人钉墙后接普攻Q打出爆发连招,避免正面硬拼依靠Q翻滚拉扯等待暴击装备成型,中期配合辅助游走gank利用R隐身绕后切入,],},{name: 半肉生存流,key_stats: [survival, support],description: 在核心装备基础上补出守护天使斯特拉克的挑战护手提升团战容错率适合对方多刺客突进阵容。,runes: 致命节奏 骸骨镀层 过度生长,tips: [对线期更加保守利用Q翻滚躲避关键技能,团战等待对方交出关键技能后再进场输出,站位靠近辅助确保被突进时能第一时间获得保护,],},],劫: [{name: 电刑刺客流,key_stats: [combat],description: 幽梦之灵暮刃赛瑞尔达的怨恨的组合强化单体爆发伤害6级后单杀能力极强。,runes: 电刑 残暴 血统 砍倒,tips: [3级前利用Q技能消耗4级后RWEQ连招一套带走,游走时优先选择无位移的敌方后排目标,注意W影子的位置管理确保有二段位移撤退,],},{name: 半坦战士流,key_stats: [survival, support],description: 在幽梦之灵基础上补出黑色切割者斯特拉克的挑战护手提升持续作战能力和团战生存性。,runes: 征服者 凯旋 骸骨镀层,tips: [利用线上消耗慢慢积累优势不强求单杀,团战切入时机选择在对方控制技能交出后,R技能多用于分割战场而非单纯追求击杀,],},{name: 游走支援流,key_stats: [support, farming],description: 优先做出鞋子附魔幽梦之灵最大化移动速度通过频繁游走帮助边路建立优势。,runes: 电刑 灵巧猎人 血统,tips: [中路快速推线后立即向边路游走,配合打野入侵对方野区利用高机动性压制对方发育,团战前利用R技能威胁对方后排逼迫其站位靠后,],},],韦鲁斯: [{name: 攻速特效流,key_stats: [combat, farming],description: 攻速鞋破败王者之刃鬼索的狂暴之刃卢安娜的飓风依靠普攻快速叠加W枯萎印记对前排后排都有稳定输出。,runes: 致命节奏 残暴 砍倒 骸骨镀层,tips: [对线期利用E技能减速敌人不断普攻挂印记寻找换血机会,团战利用飓风分裂效果同时给多名敌人挂枯萎印记,找机会用WQ引爆印记打出额外伤害,],},{name: 穿甲Poke流,key_stats: [combat, vision],description: 穿甲鞋幽梦之魂魔切赛瑞尔达的怨恨为核心依靠蓄力Q远程压低敌方整体血量适合搭配强开硬辅。,runes: 彗星 法力流系带 超然 焦灼,tips: [团战前不断在安全距离释放Q技能消耗对手血量,利用视野优势在敌方视野盲区蓄力Q提高命中率,逼迫对手放弃资源争夺为团队创造控龙控图机会,],},{name: AP爆发流,key_stats: [combat, support],description: 纳什之牙黄昏与黎明法穿棒灭世者的死亡之帽借助装备特效快速叠加多层枯萎印记大招禁锢后WQ瞬间爆发。,runes: 强攻 战意 砍倒 骸骨镀层,tips: [等待队友完成控制后再打输出切忌先手贸然进场,大招更多用来反打或衔接队友控制不要盲目释放,观察敌方魔抗情况及时调整出装顺序,],},],}classmethoddef generate_advice(cls, player_data: PlayerHexagon,benchmark: PlayerHexagon) - list:根据玩家能力数据自动匹配流派并生成精进建议。返回按契合度排序的流派建议列表。champion player_data.championtemplates cls.BUILD_TEMPLATES.get(champion, [])if not templates:return [{name: 通用建议,description: 暂无该英雄的预设流派数据,tips: [建议参考掌上英雄联盟App或LoLMeta查看最新出装]}]# 计算玩家各维度的偏差player_dims {combat: player_data.combat, survival: player_data.survival,farming: player_data.farming, support: player_data.support,vision: player_data.vision, pushing: player_data.pushing,}bench_dims {combat: benchmark.combat, survival: benchmark.survival,farming: benchmark.farming, support: benchmark.support,vision: benchmark.vision, pushing: benchmark.pushing,}deviations {k: player_dims[k] - bench_dims[k] for k in player_dims}# 为每个流派计算契合度评分scored []for tmpl in templates:score sum(deviations.get(stat, 0) for stat in tmpl[key_stats])# 归一化到 0-100match_score max(0, min(100, 50 score * 0.8))scored.append((match_score, tmpl))scored.sort(keylambda x: x[0], reverseTrue)results []for match_score, tmpl in scored:# 针对关键维度生成个性化偏差提示personalized_tips list(tmpl[tips])for stat in tmpl[key_stats]:dev deviations.get(stat, 0)if dev -10:stat_name {combat: 战斗, survival: 生存, farming: 发育,support: 支援, vision: 视野, pushing: 推进,}.get(stat, stat)personalized_tips.append(f⚠ 你的{stat_name}维度低于同段位平均 {abs(dev):.0f} 分f建议重点练习该维度的相关操作。)results.append({name: tmpl[name],match_score: round(match_score, 1),description: tmpl[description],runes: tmpl[runes],tips: personalized_tips,})return results# # 第五部分主程序# def main():# 1. 初始化provider MockDataProvider()analyzer ChampionAnalyzer(provider)visualizer LOLMVisualizer()print( * 65)print( LOLM 英雄数据对比分析与打法流派建议系统)print( * 65)# 2. 多英雄 × 多段位 数据对比champions [薇恩, 劫, 韦鲁斯]tiers [钻石, 大师, 王者]df analyzer.compare_champions(champions, tiers)print(\n 多英雄各段位数据对比)print(df.to_string(indexFalse))# 3. 胜率对比柱状图print(\n 生成胜率对比图...)visualizer.plot_winrate_comparison(df)# 4. 六边形能力雷达图print(\n️ 生成六边形能力雷达图...)player_name 玩家Aplayer_hexagons []for champ in champions:ph provider.fetch_player_hexagon(player_name, champ)player_hexagons.append(ph)benchmark provider._player_data[基准_大师ADC]visualizer.plot_radar(player_hexagons, titlef{player_name} 多英雄六边形能力对比,benchmarkbenchmark)# 5. 偏差分析图print(\n 生成偏差分析图...)visualizer.plot_hexagon_deviation(player_hexagons[0], benchmark)# 6. 流派建议生成print(\n * 65)print( 打法流派精进建议)print( * 65)for ph in player_hexagons:print(f\n{─ * 50})print(f【{ph.champion}】- 玩家: {ph.player_name})print(f{─ * 50})advices BuildAdvisor.generate_advice(ph, benchmark)for i, adv in enumerate(advices, 1):目前为模型版本仅供参考用详细内容需进一步提升改进。