Rank-Analysis 预组队识别(英雄联盟)
1. 前言
LOL-Ranklysis 已经更新到 1.4 版本了,感觉大家的使用和反馈, https://github.com/wnzzer/lol-rank-record-analysis
对于一个英雄联盟战绩查询软件,对预组队(双排,乃至车队)的判断是至关重要的,对于对喷的理由(bushi),对于预组队的针对配合有个提前量的判断,是个非常重要的功能。
2. 功能实现:
首先我们需要知道,通过LOL LCU 接口不提供相关的数据,因此,我们只能通过我们自己判断是否是预组队的逻辑预判他们是不是为预组队。
我们需要知道预组队的前置条件
- 组队最多为 2 - 5 人
- 最多有 4 个队伍
- 好友组队的概率很高
2.1. 判断好友:
我们可以把每局遇到的玩家的 puuid 提取出来,如果在同一局,在同一个队伍超过某个次数,则判断为好友
- 提取对局
func getOneGamePlayers(matchHistory *client.MatchHistory) map[string][]OneGamePlayer {
oneGamePlayerMap := make(map[string][]OneGamePlayer)
for index, games := range matchHistory.Games.Games {
myTeamId := games.Participants[0].TeamId
for i := 0; i < len(games.GameDetail.ParticipantIdentities); i++ {
oneGamePlayerMap[games.GameDetail.ParticipantIdentities[i].Player.Puuid] = append(oneGamePlayerMap[games.GameDetail.ParticipantIdentities[i].Player.Puuid], OneGamePlayer{
Index: index,
GameId: games.GameId,
GameCreatedAt: games.GameCreationDate,
IsMyTeam: myTeamId == games.GameDetail.Participants[i].TeamId,
GameName: games.GameDetail.ParticipantIdentities[i].Player.SummonerName,
TagLine: games.GameDetail.ParticipantIdentities[i].Player.TagLine,
ChampionId: games.GameDetail.Participants[i].ChampionId,
ChampionBase64: client.GetChampionBase64ById(games.GameDetail.Participants[i].ChampionId),
Kills: games.GameDetail.Participants[i].Stats.Kills,
Deaths: games.GameDetail.Participants[i].Stats.Deaths,
Assists: games.GameDetail.Participants[i].Stats.Assists,
Win: games.GameDetail.Participants[i].Stats.Win,
QueueIdCn: client.QueueIdToCn[games.QueueId],
})
}
}
return oneGamePlayerMap
}
- 添加到好友队列,比如大于 3 局为队友的数量
if teamCount >= friendThreshold {
theTeams = append(theTeams, puuid)
}
2.3. 过滤好友队列:
- 我们可以查询本局的十个玩家,每个人的可以的好友队列提取出来之后
- 再与当前对局的玩家取交集,去掉不是该对局的玩家
// 统一处理 TeamOne 和 TeamTwo 的逻辑,把可能的队伍存入 allMaybeTeams
processTeamForMarkers := func(team []SessionSummoner) {
for _, sessionSummoner := range team {
var theTeams []string
for puuid, playRecordArr := range sessionSummoner.UserTag.RecentData.OneGamePlayersMap {
// 如果不在当前对局中,跳过这个玩家的统计
if !currentGamePuuids[puuid] {
continue
}
teamCount := 0
for _, playRecord := range playRecordArr {
if playRecord.IsMyTeam {
teamCount++
}
}
if teamCount >= friendThreshold {
theTeams = append(theTeams, puuid)
}
}
allMaybeTeams = append(allMaybeTeams, theTeams)
}
}
// 分别处理 TeamOne 和 TeamTwo
processTeamForMarkers(sessionData.TeamOne)
processTeamForMarkers(sessionData.TeamTwo)
2.4. 合并子区间
如果两个都是好友,一个人玩的多,一个人玩的少,玩的多的人提供的数据范围可能更大,对于多人组队识别的准确率会更高,因此要合并子区间,保留较大的区间
func removeSubsets(arrays [][]string) [][]string {
// 按数组长度排序,确保先处理较大的数组
sort.Slice(arrays, func(i, j int) bool {
return len(arrays[i]) > len(arrays[j])
})
// 存储去重后的结果
var result [][]string
for _, arr := range arrays {
// 判断当前数组是否被其他数组包含
isSubsetFlag := false
for _, resArr := range result {
if isSubset(arr, resArr) {
isSubsetFlag = true
break
}
}
// 如果当前数组没有被包含,就加入结果
if !isSubsetFlag {
result = append(result, arr)
}
}
return result
}
2.5. 与当前对局同一队伍取交集
虽然我们前面过滤了一遍,但是并不是很严谨,只是粗过滤,实际上,好友也可能排到对面去,因此,我们需要把待映射好友队列,与红蓝两队取交集,理论上交集的结果最多有一队大于 2 个人。就把结果映射上去。
var mergedTeams [][]string
mergedTeams = removeSubsets(allMaybeTeams)
// 标记预组队信息
constIndex := 0
preGroupMakerConsts := []PreGroupMaker{
{Name: "队伍1", Type: "success"},
{Name: "队伍2", Type: "warning"},
{Name: "队伍3", Type: "error"},
{Name: "队伍4", Type: "info"},
}
for _, team := range mergedTeams {
marked := false
intersectionTeamOne := intersection(team, teamOnePuuids)
intersectionTeamTwo := intersection(team, teamTwoPuuids)
if len(intersectionTeamOne) >= theTeamMinSum {
for i := range sessionData.TeamOne {
sessionSummoner := &sessionData.TeamOne[i]
if oneInArr(sessionSummoner.Summoner.Puuid, intersectionTeamOne) && sessionSummoner.PreGroupMarkers.Name == "" {
sessionSummoner.PreGroupMarkers = preGroupMakerConsts[constIndex]
marked = true
}
}
} else if len(intersectionTeamTwo) >= theTeamMinSum {
for i := range sessionData.TeamTwo {
sessionSummoner := &sessionData.TeamTwo[i]
if oneInArr(sessionSummoner.Summoner.Puuid, intersectionTeamTwo) && sessionSummoner.PreGroupMarkers.Name == "" {
sessionSummoner.PreGroupMarkers = preGroupMakerConsts[constIndex]
marked = true
}
}
}
if marked {
constIndex++
}
}
}
这里的 type 用于区分前端显示颜色,无其他用途
3. 后记:
预组队识别是很好用且项目组较繁琐的功能,旨在一步步拆解功能的实现即可,如果想更深的了解这个 lcu 的项目,请前往 https://github.com/wnzzer/lol-rank-record-analysis 了解更多详情哦!