프로젝트의 흥미도도 유지하면서 조금 큰 데이터도 다루면서 속도나 비용에 대한 고민을 느껴보자해서 라이엇 API를 이용해서 op.gg와 비슷하지만 조금은 다른 웹 프로그램을 개발해보고자 한다. 배틀그라운드나 FC온라인 여러 게임들을 해볼까 했지만 일단 국내 게임사는 매우 불친절하다. RIOT이 대중적이면서 kaggle에도 대회가 존재하니 최적의 선택인 것 같다
목적은 솔랭 플레이어 개인에 좀 더 초점을 맞춘, 전적검색이 주 목적이 아닌 전적분석을 목표로 한다. 예측은 후 순위 프로젝트이고, 우선은 솔랭경기들에 대한 분석 및 제공이다.
전적검색 사이트에서 처음 유저들의 경험은 소환사명 입력 및 검색시도가 있겠다. 이것을 도와주는 API가 SUMMENOR-V4이다.
최근 롤이 닉네임 시스템이 변경되면서, 고유한 닉네임이 아닌 중복 닉네임을 허용했고 대신 태그규칙을 걸어서 고유성을 확보했다.
Faker의 솔로랭크 닉네임인 Hide on bush만 10000명이 넘는다. 대신 초기 닉네임 주인에게는 KR1이라는 태그가 자동부여되는 듯 하다. 하여튼 닉네임+태그 규칙이 생겼고
많은 전적 검색사이트는 이제 태그까지 적지 않는다면 검색이 되지 않는다. 근데 신기한 것은 op.gg는 검색결과를 전부 가지고 있어서인지는 모르겠으나 닉네임만 쳐도 추가보기 기능으로 선택이 가능하다. 이까지 구현하려면 미리 존재하는 빅데이터가 필요하기에 나 또한 닉네임+태그 규칙으로 검색기능을 만들 것이다.
먼저 검사할 것이 있었다. 띄어쓰기 와 대문자를 구분하지 않는다는 것을 바로 확인할 수 있었다. 그리고 닉네임만 입력하고 그 닉네임이 존재한다면 #KR1이 우선순위로 검색된다. 즉 hideonbush = Hide on bush = hideonbush#KR1 = Hide on bush#KR1 이다.
summonerName은 게임 안에서 직접적으로 사용하는 닉네임이다. 이것을 검색하면
다음과 같은 정보가 나온다. 여기서 중요하게 사용할 것은 puuid이다.
매치에 대한 정보를 주는 MATCH-V5이다.
첫번째 엔드포인트는 puuid로 하여금 matchid(해당 summoner의 여러개 매치에 대한 id)를 반환한다. matchid를 활용해서 아래의 두 엔드포인트에 접근하면 해당 단일 매치에 대한 정보와, 해당 단일 매치의 시간의 흐름에 대한 정보를 준다.
시간의 흐름에 대한 정보를 주는게 이 프로젝트를 하는 이유이기도 한데, 현재 OP.GG는 이 API를 활용해서
다음과 같은 매치 안에서 챔피언들의 점수흐름을 나타낸다. 시작점수는 항상 5점이고 최종 점수는 마지막 점수를 기준으로 하는 것을 보니 기준 점수가 5점이고 시간의 흐름에 따라 자신의 점수가 상승하거나 하락하는 등의 특정한 로직(분석)에 의해 점수의 흐름이 나타나는 듯 하다.
점수의 흐름을 통해 1인분 이상, 불굴의 의지, 팀차이 등등 여러 카테고리를 만들어서 해당 매치에서의 자신의 영향도를 볼 수 있다.
OP.GG는 이러한 지표를 베타버전으로 서비스 하고 있다.
{
"metadata": {
"dataVersion": "2",
"matchId": "KR_6961713821",
"participants": [
"onzpaKK-V4BWINOlxzE6UmOjE13H1SlUXJabHDI4E1SYmNH_DkC65uWUzedqjqPyrF7KSK-kXN9i8g",
외 9명
]
},
"info": {
"endOfGameResult": "GameComplete",
# 게임 픽창 시간(유닉스 시간)
"gameCreation": 1708703810434,
# 게임 시간(초 단위)
"gameDuration": 1410,
# 게임 끝난 시간(유닉스 시간)
"gameEndTimestamp": 1708705237955,
# 게임 id
"gameId": 6961713821,
# 게임 모드(CLASSIC = 5대5)
"gameMode": "CLASSIC",
# 게임 이름?
"gameName": "teambuilder-match-6961713821",
# 인게임 시작
"gameStartTimestamp": 1708703827638,
# 게임 타입
"gameType": "MATCHED_GAME",
# 버전 = 14.4패치
"gameVersion": "14.4.561.3953",
# 맵 id (11이 소환사의 협곡)
"mapId": 11,
# 참가자 정보
"participants": [
{
# 올인 핑
"allInPings": 0,
# 도움 핑
"assistMePings": 7,
# 어시스트 수
"assists": 2,
# 바론 막타
"baronKills": 0,
# 기본 핑
"basicPings": 0,
# 현상금 레벨
"bountyLevel": 0,
"challenges": {
# 연속 어시스트 기록
"12AssistStreakCount": 0,
# 스킬 사용 횟수
"abilityUses": 268,
# 15분 전 에이스 횟수
"acesBefore15Minutes": 0,
# 정글 몹 처치
"alliedJungleMonsterKills": 0,
# 바론 막타
"baronTakedowns": 0,
"blastConeOppositeOpponentCount": 0,
# 생성 현상금
"bountyGold": 0,
# 뺏은 버프 횟수
"buffsStolen": 0,
# 서폿 템 유무
"completeSupportQuestInTime": 0,
# 공격적 와드 장악력 "controlWardTimeCoverageInRiverOrEnemyHalf": 0.7095672615944019,
# 제어 와드
"controlWardsPlaced": 1,
# DPM
"damagePerMinute": 865.0203906284592,
# 팀내 데미지 받은 비중
"damageTakenOnTeamPercentage": 0.24315185057986916,
# 전령 관련같은데...
"dancedWithRiftHerald": 0,
# 적 챔프에게 죽은 횟수
"deathsByEnemyChamps": 10
# 매우 짧은 거리에서 스킬 피한 횟수
"dodgeSkillShotsSmallWindow": 0,
# 두번 연속 에이스
"doubleAces": 0,
# 용 처치 횟수(킬, 어시 포함)
"dragonTakedowns": 0,
# 라인전 시작전 골드, 경험치 이득보고 시작(인베이드 이득, True of False)
"earlyLaningPhaseGoldExpAdvantage": 1,
# 힐, 실드량
"effectiveHealAndShielding": 0,
"elderDragonKillsWithOpposingSoul": 0,
"elderDragonMultikills": 0,
# cc기 맞춘 횟수 "enemyChampionImmobilizations": 38,
# 적 정글 몬스터 킬
"enemyJungleMonsterKills": 0,
# 적 정글러 근처에서 에픽몬스터 처치횟수(스틸횟수)
"epicMonsterKillsNearEnemyJungler": 0,
# 에픽 몬스터 생성후 30초이내에 처치 "epicMonsterKillsWithin30SecondsOfSpawn": 0,
# 에픽 몬스터(바론, 용, 블루, 레드)스틸 횟수
"epicMonsterSteals": 0,
# 에픽 몬스터 스마이트 없이 스틸
"epicMonsterStolenWithoutSmite": 0,
# 첫 타워 깼는지 (팀 전체가 1)
"firstTurretKilled": 1,
# 첫 타워 깬 시점
"firstTurretKilledTime": 821.3447503,
# 우리팀 데스없이 상대방 전멸
"flawlessAces": 0,
# 상대팀 전멸시킨 횟수
"fullTeamTakedown": 0,
# 전체 게임 시간
"gameLength": 1410.5417132,
"getTakedownsInAllLanesEarlyJungleAsLaner": 0,
# GPM
"goldPerMinute": 391.2527333411794,
"hadOpenNexus": 0,
# 자신의 cc기를 활용해 팀원과 같이 적을 죽인 횟수
"immobilizeAndKillWithAlly": 0,
# 첫 버프 먹은 수 ( max = 4)
"initialBuffCount": 0,
# 첫 바위 게 먹은 수 ( max = 2)
"initialCrabCount": 0,
# 10분 이전 정글 몹으로만 cs
"jungleCsBefore10Minutes": 0,
# 적 정글러 에픽 건드리는데 우리가 죽임 "junglerTakedownsNearDamagedEpicMonster": 0,
# 광 타임 끝나기전 터렛 부쉈는 지 "kTurretsDestroyedBeforePlatesFall": 0,
# KDA
"kda": 0.6,
# 암살
"killAfterHiddenWithAlly": 0,
# 킬 관여율
"killParticipation": 0.2857142857142857,
"killedChampTookFullTeamDamageSurvived": 0,
# "학살중입니다 콜 횟수"
"killingSprees": 0,
# 다이브 성공 횟수
"killsNearEnemyTurret": 1,
"killsOnOtherLanesEarlyJungleAsLaner": 0,
"killsOnRecentlyHealedByAramPack": 0,
# 다이브 받아쳐서 킬한 횟 수
"killsUnderOwnTurret": 1,
# 에픽 몬스터 딜과 합작 킬
"killsWithHelpFromEpicMonster": 0,
# 그랩류 같은 것으로 우리팀에게 끌어와서 킬
"knockEnemyIntoTeamAndKill": 2,
# 극초반 스킬샷 적중횟수
"landSkillShotsEarlyGame": 6,
# 10분전 라인 미니언
"laneMinionsFirst10Minutes": 81,
# 라인 초반 강한 이점
"laningPhaseGoldExpAdvantage": 0,
# 전설입니다 콜 횟수
"legendaryCount": 0,
# 코어 아이템 목록
"legendaryItemUsed": [
3142,
3004
],
# 억제기 잃었음
"lostAnInhibitor": 0,
# 최고로 낸 cs차이
"maxCsAdvantageOnLaneOpponent": 34,
# 이상한듯 수치가 안나옴.
"maxKillDeficit": 0,
# 맞 라인 상대에 대해 최대 레벨 차이
"maxLevelLeadLaneOpponent": 2,
# 메자이 풀스텍 채웠는지
"mejaisFullStackInTime": 0,
# 얼마나 적 정글 침범했는지 퍼센트로 나옴(음수로)
"moreEnemyJungleThanOpponent": 0,
# 한 스펠로 다수의 킬 만들어냄
"multiKillOneSpell": 0,
# 전령으로 한번에 여러개 타워 처치
"multiTurretRiftHeraldCount": 0,
# 멀티킬
"multikills": 0,
# 공격적인 플래쉬로 여러 킬 횟수 "multikillsAfterAggressiveFlash": 0,
# 10분이내 타워 처치
"outerTurretExecutesBefore10Minutes": 0,
# 수적으로 열세일 때 킬
"outnumberedKills": 0,
# 수적으로 열세일 때 넥서스 처치
"outnumberedNexusKill": 0,
# 드래곤 영혼 획득
"perfectDragonSoulsTaken": 0,
# 팀 노데스
"perfectGame": 0,
# 협력 킬포인트 생산 횟수
"pickKillWithAlly": 3,
# 의미없는 데이터
"playedChampSelectPosition": 1,
# 버려
"poroExplosions": 0,
# 클린즈 사용 횟수
"quickCleanse": 0,
"quickFirstTurret": 0,
# 빠른 솔로킬
"quickSoloKills": 0,
# 전령 처치횟수
"riftHeraldTakedowns": 0,
# 팀원 살려준 횟수
"saveAllyFromDeath": 0,
# 바위 게 컨트롤 횟수
"scuttleCrabKills": 0,
# 피한 스킬 샷
"skillshotsDodged": 2,
# 맞춘 스킬 샷
"skillshotsHit": 15,
# 버려
"snowballsHit": 0,
# 혼자 바론 킬
"soloBaronKills": 0,
# 솔로킬
"soloKills": 3,
# 일반와드 설치 횟수
"stealthWardsPlaced": 8,
# 한자리수 hp로 살아감
"survivedSingleDigitHpCount": 0,
# cc기 3개이상 맞고 살아감 "survivedThreeImmobilizesInFight": 2,
# 첫번째 포탑 파괴 or 파괴될 때 적 사냥
"takedownOnFirstTurret": 0,
# 킬 + 어시
"takedowns": 6,
# 레벨업 활용해서 적 처치 관여 "takedownsAfterGainingLevelAdvantage": 0,
# 정글 미니언 스폰전에 적 처치관여(인베이드)
"takedownsBeforeJungleMinionSpawn": 0,
# 10분 전 적 처치관여 횟수
"takedownsFirstXMinutes": 4,
# 라인 뒷 골목에서 적 처치관여
"takedownsInAlcove": 0,
# 우물 킬
"takedownsInEnemyFountain": 0,
# 바론 먹은 횟수
"teamBaronKills": 0,
# 팀내 데미지 비중
"teamDamagePercentage": 0.26852989743228145,
# 팀 장로 드래곤
"teamElderDragonKills": 0,
# 팀 전령
"teamRiftHeraldKills": 0,
# 텔포로 적 처치관여
"teleportTakedowns": 1,
# 큰 데미지 입고도 살아감
"tookLargeDamageSurvived": 0,
# 광 몇개 캤는지
"turretPlatesTaken": 2,
# 타워 몇개 부셨는지 관여
"turretTakedowns": 0,
# 전령으로 타워 몇개 부셨는지
"turretsTakenWithRiftHerald": 0,
# 3초안에 20개이상 미니언 처치
"twentyMinionsIn3SecondsCount": 0,
# 와드 두개를 한번의 렌즈로 지움
"twoWardsOneSweeperCount": 0,
# 언씬리콜인데 다 0뜸 쓰지말자
"unseenRecalls": 0,
# 시야점수 이점 (음수면 진거)
"visionScoreAdvantageLaneOpponent": 0.01774919033050537,
# VPM
"visionScorePerMinute": 0.8887097165781768,
# 와드 처치 횟수
"wardTakedowns": 3,
# 와드 처치 횟수 20분전
"wardTakedownsBefore20M": 3,
# 와드 처치 방어
"wardsGuarded": 0
},
# 챔프 경험치
"champExperience": 10777,
# 챔프 레벨
"champLevel": 13,
# 챔프 id
"championId": 126,
# 챔프 이름 : 제이스
"championName": "Jayce",
# 챔피언 교체(스왑)
"championTransform": 0,
# 명령 핑 횟수
"commandPings": 2,
"consumablesPurchased": 2,
# 건축물 딜(억제기 타워 넥서스)
"damageDealtToBuildings": 1376,
# 오브젝트 딜
"damageDealtToObjectives": 2081,
# 타워 딜
"damageDealtToTurrets": 1376,
"damageSelfMitigated": 10640,
# 위험 핑
"dangerPings": 0,
# 데스 수
"deaths": 10,
# 핑와 설치 수
"detectorWardsPlaced": 1,
# 더블 킬
"doubleKills": 0,
# 드래곤 막타
"dragonKills": 0,
"eligibleForProgression": true,
# 미아 핑
"enemyMissingPings": 22,
# 적 와드 핑
"enemyVisionPings": 1,
# 퍼블 어시
"firstBloodAssist": false,
# 퍼블 킬
"firstBloodKill": false,
# 타워 퍼블 어시스트
"firstTowerAssist": false,
# 타워 퍼블 킬
"firstTowerKill": false,
# 15분 서렌 쳐서 졌나?
"gameEndedInEarlySurrender": false,
# 서렌 쳐서 졌나?
"gameEndedInSurrender": true,
# 후퇴 핑
"getBackPings": 1,
# 획득 골드
"goldEarned": 9197,
# 사용 골드
"goldSpent": 7725,
# 유지 핑
"holdPings": 0,
# 개인 포지션 : 탑
"individualPosition": "TOP",
# 억제기
"inhibitorKills": 0,
"inhibitorTakedowns": 0,
"inhibitorsLost": 0,
"item0": 3142,
"item1": 3042,
"item2": 1083,
"item3": 1036,
"item4": 1055,
"item5": 3158,
"item6": 3340,
"itemsPurchased": 16,
# 킬링스프리 횟수
"killingSprees": 0,
# 킬
"kills": 4,
"lane": "MIDDLE",
"largestCriticalStrike": 0,
"largestKillingSpree": 0,
"largestMultiKill": 1,
"longestTimeSpentLiving": 284,
# AP딜
"magicDamageDealt": 10672,
# 챔프에 가한 AP딜
"magicDamageDealtToChampions": 3924,
"magicDamageTaken": 10672,
"missions": {
"playerScore0": 0,
"playerScore1": 0,
"playerScore10": 0,
"playerScore11": 0,
"playerScore2": 0,
"playerScore3": 0,
"playerScore4": 0,
"playerScore5": 0,
"playerScore6": 0,
"playerScore7": 0,
"playerScore8": 0,
"playerScore9": 0
},
"needVisionPings": 0,
"neutralMinionsKilled": 0,
"nexusKills": 0,
"nexusLost": 0,
"nexusTakedowns": 0,
"objectivesStolen": 0,
"objectivesStolenAssists": 0,
"onMyWayPings": 9,
"participantId": 1,
"pentaKills": 0,
"perks": {
"statPerks": {
"defense": 5001,
"flex": 5008,
"offense": 5008
},
"styles": [
{
"description": "primaryStyle",
"selections": [
{
"perk": 8230,
"var1": 14,
"var2": 0,
"var3": 0
},
{
"perk": 8226,
"var1": 250,
"var2": 736,
"var3": 0
},
{
"perk": 8233,
"var1": 13,
"var2": 40,
"var3": 0
},
{
"perk": 8236,
"var1": 14,
"var2": 0,
"var3": 0
}
],
"style": 8200
},
{
"description": "subStyle",
"selections": [
{
"perk": 8345,
"var1": 3,
"var2": 0,
"var3": 0
},
{
"perk": 8304,
"var1": 9,
"var2": 0,
"var3": 0
}
],
"style": 8300
}
]
},
# AD딜
"physicalDamageDealt": 90436,
# 챔피언에게 가한 AD딜
"physicalDamageDealtToChampions": 16411,
"physicalDamageTaken": 10849,
"placement": 0,
"playerAugment1": 0,
"playerAugment2": 0,
"playerAugment3": 0,
"playerAugment4": 0,
"playerScore0": 0,
"playerScore1": 0,
"playerScore10": 0,
"playerScore11": 0,
"playerScore2": 0,
"playerScore3": 0,
"playerScore4": 0,
"playerScore5": 0,
"playerScore6": 0,
"playerScore7": 0,
"playerScore8": 0,
"playerScore9": 0,
"playerSubteamId": 0,
"profileIcon": 5634,
"pushPings": 0,
"puuid": "onzpaKK-V4BWINOlxzE6UmOjE13H1SlUXJabHDI4E1SYmNH_DkC65uWUzedqjqPyrF7KSK-kXN9i8g",
"quadraKills": 0,
"riotIdGameName": "\uc5c4\ub3c4\ub0a0\ub4dc",
"riotIdTagline": "KR1",
"role": "DUO",
"sightWardsBoughtInGame": 0,
"spell1Casts": 87,
"spell2Casts": 51,
"spell3Casts": 53,
"spell4Casts": 77,
"subteamPlacement": 0,
"summoner1Casts": 4,
"summoner1Id": 12,
"summoner2Casts": 3,
"summoner2Id": 4,
"summonerId": "K4p6x2KSZJZB6TMV57fmMOg5OEjeONKZo0H4w7uVRP-DE6g",
"summonerLevel": 214,
"summonerName": "\uc5c4\ub3c4\ub0a0\ub4dc",
"teamEarlySurrendered": false,
"teamId": 100,
"teamPosition": "TOP",
# cc건 시간 (초)
"timeCCingOthers": 15,
"timePlayed": 1410,
"totalAllyJungleMinionsKilled": 0,
"totalDamageDealt": 101372,
"totalDamageDealtToChampions": 20335,
"totalDamageShieldedOnTeammates": 0,
"totalDamageTaken": 22304,
"totalEnemyJungleMinionsKilled": 0,
"totalHeal": 860,
"totalHealsOnTeammates": 0,
"totalMinionsKilled": 177,
"totalTimeCCDealt": 108,
"totalTimeSpentDead": 282,
"totalUnitsHealed": 1,
"tripleKills": 0,
"trueDamageDealt": 263,
"trueDamageDealtToChampions": 0,
"trueDamageTaken": 782,
"turretKills": 0,
"turretTakedowns": 0,
"turretsLost": 6,
"unrealKills": 0,
"visionClearedPings": 0,
"visionScore": 20,
"visionWardsBoughtInGame": 1,
"wardsKilled": 3,
"wardsPlaced": 9,
"win": false
},
/////////////// 그 다음 9명 정보/////////////
riot이 데이터에 대한 설명이 너무 부실해서 직접 해석을 해야했다. 생각보다 다양하고 특이한 데이터들을 제공하는 것을 알 수 있었고 여러 지표를 사용해서 효과적인 분석정보를 만들 수 있을 것 같다. 데이터 레코드들을 해석을 위해 플레이어 10명에 대한 데이터를 모두 비교/대조 하며 데이터를 해석했다.
매치 타임 라인의 경우 약 60000밀리초(1분)단위로 10명에 대한 데이터가 생성된다. 이 경우 데이터가 너무 많아 따로 포스팅에 올리진 않을 것이다. op.gg의 경우에도 1분 단위로 score를 업데이트 하는 것을 알 수 있다.
라이엇에서 따로 변수 설명을 제공 안해주나요?