5. 타워/챔피언에게 의도적으로 죽은경우

chaechae·2023년 5월 27일
0
post-thumbnail

자!! 이번에는 의도적으로 적에게 죽은 경우 입니다.

이런 경우에도 참 판단하기 애매한 경우입니다. 왜냐하면 영상/채팅을 다 돌려보지 않는 이상 적에게 의도적으로 죽은 건지, 아니면 정말 실력이없어서 죽은건지...🙄

유저를 제재를 하기위해서 판단하는데 굉장히 까다롭단 말이죠. 이렇게 애매한경우 어느정도 사람의 판단이 꼭 필요할거라 생각이 들었습니다. 그래서!!! api에서 제공되는 데이터를 가지고 어떤 지표를 이용해야 이 부분을 판단하는데 도움이 될 수 있을까? 고민을 해봤습니다.

일단 이번 핵심은 유저가 죽은경우 입니다. 그렇기 때문에 유저가 death 했을 경우 남는 데이터를 중점으로 봐야할것입니다.

흠.. 그런데 의도적으로 죽었다는 것을 어떻게 판단할 수 있을까..
의도적으로 죽었다는 건 .. 다시말해 아무런 저항 없이 죽으러 간 경우? 라고 할 수 있지않을까?

전투를 하다보면 상대방과 본인의 공격을 티키타카 하면서 싸울 수 밖에 없습니다. 정상적으로 게임을 플레이 한다면요. 그런데, 만약 의도적으로 적에게 죽는 경우라면, 아무런 저항없이 죽는 경우가 많지 않을까 생각했습니다. 왜냐하면 본인은 싸울 의도가 없으니까요

즉, 한마디로 딜교환을 하지 않았다. !

이와 관련된 데이터를 찾으면 플레이를 하는데 적극적이지 않았음을 어느 정도 증명할 수 있지 않을까 생각했습니다.👀 본격적으로 데이터를 한번 훑어보겠습니다.

받은피해량과 가한피해량

한 매치게임이 끝나고 볼 수 있는 통계창에서 가장 먼저 보는 기록이 바로 '챔피언에게 가한 피해량' 일거라고 생각이 듭니다ㅎㅎ. 특히 공격적인 포지션인 경우, 캐리했다는 큰 지표중 하나로 보기 때문이죠. 하지만 이렇게 게임이 끝나고 한번에 기록되는 값 말고 세부적으로 기록되는 값들이 궁금했습니다.

해당 유저가 죽었는데, 어떻게 저항하고, 어떤 스킬을 썼는지 까지도요.

그리고 그에 대한 데이터가 아래에 있었습니다. 저번에 position 값 들을 모으기위해서 갖고왔던 EVENTS dataframe 기억나시나요 ㅎㅎ? 위 데이터에서 type == 'CAHMPION_KILL' 인 데이터와 필요한 컬럼들을 가져오면 다음과 같습니다.

이 안에 유저가 CHMPION_KILL / ASSIST / DEATH 했을 경우, 아래의 빨간 구역 처럼 'victimDamageDealt' 'victimDamageRecived' 라는 컬럼안에 값들이 생기는데요

  • victimDamageDealt : victimId가 가한 데미지

  • victimDamageRecived : victimId가 받은 데미지

    vicitmId를 기준으로 측정되고 있었고, 한마디로 위 kill log 들이 발생하면서 유저가 어떻게 피해량을 받았는지, 그리고 그 유저가 어떻게 딜교환을 했는지 확인할 수 있었습니다. 데이터를 streamlit 으로 확인해서 [object Object] 형식으로 나오는데,

    각 timestamp에 찍힌 CHAMPION_KILL 데이터들을 풀어서 확인해보면 아래와같이 어떤 챔피언이 어떤 스킬을써서 얼마나 데미지를 입혔는지/ 입었는지 확인할수 있습니다. minion/ turret을 포함해서말이죠!!!

(아쉽게도, 던지는 유저의 매치를 찾지 못해서 일반적인 데이터를 가져왔습니다. 롤 게임유튜버 '해물파전'님의 가장 최근 매치 데이터인데요 ㅎㅎ 챔피언은 야스오로 플레이 하셨네요. )

어떻게 데이터를 정리해야할까?

그렇다면 , 우리가 보려고하는 유저의 participantId가 포함된 데이터를 모두 가져와야합니다.
오늘은 유저가 death한 경우를 가져올겁니다!
( kill/assist를 한 경우에도 나중에 필요한데요! 다음 포스팅에 써보도록 하겠습니다. 오늘은 유저가 받은 피해량을 봐야하니까요! )

큰 과정은 다음과같습니다.

  • death 로그가 있다는 가정하에, victimId 에서 해당 pariticpantId를 포함하는 데이터를 모두 가져옵니다. ( 위 매치에서 해물파전님의 participantId 는 3 이었습니다.)
  • 해당 유저의 'victimDamageDealt' , 'victimDamageRecived' 를 name(챔피언/미니언/터렛) 별로 damage를 집계 할겁니다.
  • 시각적으로 표현

이제 해당 유저가 '왜 죽었는지' '누구에게 죽었는지', '죽으면서 딜교환을 했는지' 본격적으로 확인 해보겠습니다!

매치에서의 15분

리그 오브 레전드를 한판이라도 해보신 분은 아시겠지만, 크게 라인전과 / 한타로 나뉘어집니다.
본인이 고른 포지션에 맞는 라인에서서 상대방과 라인전을하고 정확하게 정해진건 없지만 "보통 15분" 이후 합류하여 본격적인 팀플레이가 시작됩니다.

라인전 시작하면서 게임을 던졌는지.. 아니면 라인전 이후 (한타전) 에서 유저가 갑자기 마음이 상해서 게임을 던졌었을 수 도 있으니 15분을 기준으로 두고 나눠서 데이터를 보면 좋겠다고 생각이 들었습니다.

데이터 전처리

victimDamageDealt 와 victimDamageRecived 를 풀어줍시다.

# df_k 는 champion_kill 과 관련된 dataframe 입니다.
# 그중 victimId가 해당 유저의 participantId 인것들만 가져와줍니다. (유저의 death )
death_damage = df_k[df_k['victimId'] == summoner_participantId]

def get_damage_logs (death_damage):

    # 내가 죽은경우 받은 피해량을 확인한다.
    death_list = []
    if not death_damage.empty: # death 하지 않은 경우도 있으니
        for d, ts in zip(death_damage['victimDamageReceived'], death_damage['timestamp']): # 15분 전후로 나누기위해서 timestamp 정보가 필요하다.
            df = pd.json_normalize(d)
            df['timestamp'] = ts
            death_list.append(df)

        death_damage_log = pd.concat(death_list, axis=0)
        death_damage_log = death_damage_log[['timestamp','name','spellName','magicDamage','participantId','physicalDamage','trueDamage']]
        death_damage_log['name'] = death_damage_log['name'].replace(to_replace=r'^SRU_.*', value='Minion/Monster', regex=True) 
        # SRU 로 시작하는 것은 MINION 이니, 보기좋게 이름 변경

    else: 
        death_damage_log = pd.DataFrame(columns=['timestamp', 'name', 'spellName', 'magicDamage', 'participantId', 'physicalDamage', 'trueDamage'])


   # 내가 죽었을 때 반격했는지 확인 할 수 있다.
   # 반격하지 않은경우도 있으니 null 값을 생각해줘야한다.
    valid_data = death_damage[~death_damage['victimDamageDealt'].isna()]
    counter_list = []
    if not death_damage.empty:
        for a, ts in zip(valid_data['victimDamageDealt'], valid_data['timestamp']):
            df = pd.json_normalize(a)
            df['timestamp'] = ts
            counter_list.append(df)
        counter_damage_log = pd.concat(counter_list, axis =0)
        counter_damage_log = counter_damage_log[['timestamp','name','spellName','magicDamage','participantId','physicalDamage','trueDamage']]
        counter_damage_log['name'] = counter_damage_log['name'].replace(to_replace=r'^SRU_.*', value='Minion/Monster', regex=True)
    
    else: 
        counter_damage_log = pd.DataFrame()
        
        return death_damage_log, counter_damage_log

전체 / 15분 전후 damage를 집계합니다.

    #전체
    total = damage_counter.groupby('name').agg({'magicDamage': 'sum', 'physicalDamage': 'sum', 'trueDamage': 'sum'}).reset_index()
    total['total'] = total[['magicDamage', 'physicalDamage', 'trueDamage']].sum(axis=1)
    
    #15분전
    before = damage_counter[damage_counter['timestamp'] <= 900000 ].groupby('name').agg({'magicDamage': 'sum', 'physicalDamage': 'sum', 'trueDamage': 'sum'}).reset_index()
    before['total'] = before[['magicDamage', 'physicalDamage', 'trueDamage']].sum(axis=1)
    
    #15분이후
    after = damage_counter[damage_counter['timestamp'] > 900000 ].groupby('name').agg({'magicDamage': 'sum', 'physicalDamage': 'sum', 'trueDamage': 'sum'}).reset_index()
    after['total'] = after[['magicDamage', 'physicalDamage', 'trueDamage']].sum(axis=1)

streamlit 시각화

위 이름별로 집계된 데이터를 갖고 streamlit에 plotly 와 nivo.pie 차트를 이용해서 표현해보았는데요. 아래는 완성된 대시보드 입니다.

TOTAL

TAP1 ) TOTAL 부분입니다.

  • 해당유저의 챔피언의 경우 흰색으로, 그리고 상대 챔피언 이외에 몬스터/터렛 의 경우 붉은색으로 구분해주었습니다.
  • 또한 15분전과 15분이후로 누구에 영향을 많이받아 죽었는지 top3를 확인 할 수 있습니다.
  • 전체적인 받은 피해량과 유저가 얼만큼 딜교환을 했는지 한눈에 확인 할 수 있습니다. 타워나 상대 챔피언에게 그냥 죽었다면 확연히 차이가 날겁니다.

의도적으로 적에게 죽었다고 판단되는 한 유저의 데이터를 구해서 가져와봤습니다.
확실히 해당 유저(Irelia)의 딜량이 낮은 것을 보실 수 있습니다.

DAMAGE LOG(15/15)

TAB2 ) 15분 전후의 DAMAGE LOG 입니다.

유저가 죽었을때 마다 흑백화면에서 나오는 그 통계창이 생각나더라구요. 저는 15분을 전후로 받은데미지와 해당 챔피언이 얼만큼 딜을 넣었는지 자세하게 볼 수 있도록 table과 pie 차트로 나타내봤습니다. damage log expander를 여시면 자세한 데이터를 볼 수 있습니다.

고의적으로 죽었다고 판단되는 유저의 라인전(15분이전) 동안 death했을 때 기록된 데이터입니다.
단, 1도 딜교환 하지 않은것을 보실 수 있습니다.

한계점

대략적으로 의도적으로 죽었다는 것을 확인 할 수 있다고 보지만, 여전히 애매한 부분이 남아있었습니다. 해당 유저가 death 했을때 고려해야하는 상황이 다양하기 때문입니다. 분명 위와 같이 유저가 죽었을 때 상대방에게 넣은 damage가 아예 없거나 과도하게 적은 경우 의도적으로 죽은 확률이 높습니다.

하지만 어쩔 수 없이 딜을 못하는 상황도 있기 때문이죠.

예를들어 대부분 탱킹력이 약한 원딜 의 경우, 잘 큰 '암살자'타입의 챔피언에게 딜교환도 하지 못한 체 죽는 경우가 있습니다. 이런 경우 원딜유저의 입장에서 일부러 죽은건 아닌데,, 위 데이터를 판단으로 100% 제재까지 가는건 역시나 무리가 있습니다.
그래서 자동화하기 좀 모시깽이 한 리폿 사유인것같습니다.🤔 (정말 타워에 대놓고 꼴아박는 경우를 제외 하면요? )

그래서 해당사유를 이유로 제재를 가하기 까지 좀 더 종합적인 상황을 보는게 필요하다고 느꼈습니다. 이번 포스팅의 경우 아무래도 '의도적으로 적에게 죽음' 이라는 주제이기 때문에,
유저가 'death' 했을 때 초점으로 맞춰져 있죠. 하지만 여기에 더해서 유저가 적극적으로 게임에 참가했는지 해당 유저의 게임 참여도를 수치화하면 좋겠다는 생각이 들었습니다.

그래서!!

다음 포스팅은 유저의 참여도를 크게 ATTACK OBJECT SUPPORT 로 나뉘어서 참여도, 매치안에서의 기여도를 측정해보려고합니다. 아까 언급한 Kill/ Assist 했을 경우 log에 남는 유저의 스킬 사용도 또한 포함해서요! 아마 마지막 챕터가 되지 않을까 싶습니다. ㅎㅎ

profile
게임 혹은 다양한 컨텐츠가 있는 곳을 좋아합니다. 시리즈를 참고하시면 편하게 글을 보실 수 있습니다🫠

0개의 댓글