lck의 거의 모든 경기를 챙겨보는데, 바람 용이 등장하는 판이 다른 용에 비해 눈에 띌 정도로 많다. 실제로 리그 초반에도 lck 중계진에 의해서 몇 번 언급될 정도로 독특한 통계이다. 그런데 이 영혼용에 대한 통계는 각종 온라인 사이트들에 기록된 매치기록만 봐서는 쉽게 알 수가 없었으므로 직접 2021년 봄 시즌의 용 통계를 작성한다.
누군가는 나와 같은 시도를 했을 것이 분명하므로 깃헙을 먼저 뒤졌더니, 오래 전에 작성된 매치기록들을 긁어오는 스크립트를 발견했다.
이 스크립트를 사용해서 공식매치 기록들을 긁어올 건데, lpl은 링크형식이 다르기도 하고 실제 리그오브레전드 매치기록으로 연결시켜주는 정보들이 없어보였다. 방법을 아는 누군가가 있다면 알려주면 좋겠다.
위의 스크립트에서는 게임데이터 처리하는 부분이 내가 원하던 용 통계가 아니므로 긁어오는 데까지만 쓰자. 주의할 점 하나는 해당 소스코드에 있는 정규표현식이 https와 http 링크가 섞인 것을 고려하지 않아서(gamepedia 같은 사이트에서 실제로 섞여있다) 그냥 아래의 코드로 바꿔주자 (사실 앞부분 그냥 빼도 된다).
var rx = new RegExp(/https?:\/\/matchhistory.na.leagueoflegends.com\/en\/\#match-details\/([^\&"]+)/g),
최종적으로 스크립트를 실행하면 game-uri-cache.txt에 uri들을 저장한다.
다음으로, https://acs.leagueoflegends.com/v1/stats/game/ESPORTSTMNT01/1690549/timeline?gameHash=12e7e73be0bdaa47 이런식으로 긁어온 링크 정보를 acs.leagueoflegends.com/v1/stats/game에 주면 매치 기록에 대한 전체 타임라인 데이터를 준다.
주의해야할 점은 리그오브레전드 로그인한 상태에서 요청을 날려야하는 것 같다. 따라서 리그오브레전드 로그인 한 뒤에 얻어지는 쿠키들인 id_hint와 id_token을 기록해서 스크립트를 완성하도록한다 (둘 다 필요한지 까지는 모른다). 매치의 가공되지 않은 타임라인 데이터를 보면 events라고 기록된 이벤트들에 ELITE_MONSTER_KILL 항목에 용이 잡힌 사실도 기록한다. 'monsterType'이 용인 경우들만 먼저 가져오고 'monsterSubType'은 'AIR_DRAGON', 'WATER_DRAGON', 'FIRE_DRAGON', 'EARTH_DRAGON' 으로 분류되므로 세 번째 용의 타입을 통계냈다. 하지만 이 논리로 세면 문제가 하나 있다. 사실 영혼용이 무엇인지 결정되는 타이밍은 두 번째 용이 잡히고 나서 세 번째 용이 결정되고, 지형이 바뀌면서이다. 하지만 이 장면을 포착하려면 진짜 비디오 돌리는 노가다를 해야해서 귀찮아서 안했다. 실제 2용만 잡혀도 영혼 용이 뭔지 알게되지만 내 스크립트에서는 3용 이하로 잡힌 판은 'NONE'으로 기록한다. 실제 LCK 2021 Spring 에서 3용까지 잡히지 않은 판이 두 판 존재하는데 이 논리에 의해서 영혼용이 결정되지 않은 판만 비디오 돌려봐서 채워넣어도 되지만 하기싫다. 완성된 스크립트는 아래와 같다.
import requests
import json
from functools import reduce
# https://lol.gamepedia.com/LCK/2021_Season/Spring_Season
# dragonSouls are determined by the 3rd dragon
dragonSoulCount = 3
dragonTypes = ['AIR_DRAGON', 'WATER_DRAGON', 'FIRE_DRAGON', 'EARTH_DRAGON', 'NONE']
cookies = {
"id_hint": "id_hint_dummy ",
"id_token": "id_token_dummy"
}
cacheFileName = "game-uri-cache.txt"
def timelineUriCombinator(uri):
# input uri format: ESPORTSTMNT01/1690520?gameHash=04199edf6922bed2
serverAddress = "https://acs.leagueoflegends.com/v1/stats/game/"
return serverAddress + "/timeline?".join(uri.split("?"))
def getTimelineFromServer(timelineUri):
print("requesting to " + timelineUri)
content = requests.get(timelineUri, cookies=cookies).content
return json.loads(content)
def dragonSoul(timeline):
frames = timeline['frames']
events = reduce(lambda x,y: x + y, map(lambda x: x['events'], frames))
dragonKills = list(filter(lambda x: x['monsterType'] == 'DRAGON' if (x['type'] == 'ELITE_MONSTER_KILL') else False, events))
if (len(dragonKills) >= dragonSoulCount):
return dragonKills[dragonSoulCount - 1]['monsterSubType']
else:
return 'NONE'
def soulStats(dragonSouls):
return list(map(lambda dType: {dType: dragonSouls.count(dType)}, dragonTypes))
with open(cacheFileName) as f:
uris = json.loads(f.read())['uris']
print(f"Total games: {len(uris)}")
dragonSouls = list(map(lambda uri: dragonSoul(getTimelineFromServer(timelineUriCombinator(uri))), uris))
print(soulStats(dragonSouls))
LCK | LEC | LCS | |
바람용의 영혼 | 74 | 16 | 21 |
대지용의 영혼 | 39 | 25 | 16 |
화염용의 영혼 | 46 | 20 | 27 |
바다용의 영혼 | 54 | 27 | 26 |
영혼 없음 | 2 | 2 | 0 |
총 게임 수 | 215 | 90 | 90 |
한국리그에 바람용이 많이 나왔던 것은 팩트다
이전 네이버 블로그에 있던 글 하나를 옮기면서 테스트용으로 작성했다.
'게임, 트위치' 카테고리의 다른 글
아프리카tv 동영상 다운로드 (0) | 2023.03.09 |
---|---|
아프리카 댓글 하이라이트 링크 만들기 (0) | 2022.12.23 |
트위치 포인트 자동 파밍 (Twitch point miner) (0) | 2022.06.15 |
Blackcomb 마우스 커서 (0) | 2022.05.24 |
트위치 동영상 다운로드 (2) | 2022.05.21 |