Jimin Park
commited on
Commit
·
abcb943
1
Parent(s):
a9ac9ac
added model
Browse files- README.md +1 -1
- __pycache__/Leaderboard_scrapper.cpython-312.pyc +0 -0
- __pycache__/Meta_scrapper.cpython-312.pyc +0 -0
- __pycache__/Player_scrapper.cpython-312.pyc +0 -0
- __pycache__/Recent_match_scrapper.cpython-312.pyc +0 -0
- __pycache__/Weekly_meta_scrapper.cpython-312.pyc +0 -0
- __pycache__/connection_check.cpython-312.pyc +0 -0
- __pycache__/feature_eng.cpython-312.pyc +0 -0
- __pycache__/helper.cpython-312.pyc +0 -0
- util/Leaderboard_scrapper.py +144 -0
- util/Meta_scrapper.py +147 -0
- util/Player_scrapper.py +544 -0
- util/Recent_match_scrapper.py +393 -0
- util/Weekly_meta_scrapper.py +92 -0
- util/__pycache__/Leaderboard_scrapper.cpython-312.pyc +0 -0
- util/__pycache__/Meta_scrapper.cpython-312.pyc +0 -0
- util/__pycache__/Player_scrapper.cpython-312.pyc +0 -0
- util/__pycache__/Recent_match_scrapper.cpython-312.pyc +0 -0
- util/__pycache__/Weekly_meta_scrapper.cpython-312.pyc +0 -0
- util/__pycache__/connection_check.cpython-312.pyc +0 -0
- util/__pycache__/feature_eng.cpython-312.pyc +0 -0
- util/__pycache__/helper.cpython-312.pyc +0 -0
- app.py → util/app.py +121 -42
- util/app_training_df_getter.py +388 -0
- util/connection_check.py +63 -0
- util/data/feature_eng_stats.csv +21 -0
- util/data/meta_stats.csv +239 -0
- util/data/player_stats_merged_2025-01-08.csv +21 -0
- util/data/weekly_meta_stats.csv +170 -0
- util/data_type_checking.py +67 -0
- util/feature_eng.py +370 -0
- util/helper.py +1205 -0
- util/main_scrapper.py +36 -0
- util/main_scrapper2.py +46 -0
README.md
CHANGED
|
@@ -5,7 +5,7 @@ colorFrom: blue
|
|
| 5 |
colorTo: red
|
| 6 |
sdk: gradio
|
| 7 |
sdk_version: "4.19.2"
|
| 8 |
-
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
---
|
| 11 |
|
|
|
|
| 5 |
colorTo: red
|
| 6 |
sdk: gradio
|
| 7 |
sdk_version: "4.19.2"
|
| 8 |
+
app_file: util/app.py
|
| 9 |
pinned: false
|
| 10 |
---
|
| 11 |
|
__pycache__/Leaderboard_scrapper.cpython-312.pyc
ADDED
|
Binary file (7.31 kB). View file
|
|
|
__pycache__/Meta_scrapper.cpython-312.pyc
ADDED
|
Binary file (7.57 kB). View file
|
|
|
__pycache__/Player_scrapper.cpython-312.pyc
ADDED
|
Binary file (25.7 kB). View file
|
|
|
__pycache__/Recent_match_scrapper.cpython-312.pyc
ADDED
|
Binary file (18.1 kB). View file
|
|
|
__pycache__/Weekly_meta_scrapper.cpython-312.pyc
ADDED
|
Binary file (4.36 kB). View file
|
|
|
__pycache__/connection_check.cpython-312.pyc
ADDED
|
Binary file (1.46 kB). View file
|
|
|
__pycache__/feature_eng.cpython-312.pyc
ADDED
|
Binary file (14 kB). View file
|
|
|
__pycache__/helper.cpython-312.pyc
ADDED
|
Binary file (46.6 kB). View file
|
|
|
util/Leaderboard_scrapper.py
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
import os
|
| 3 |
+
import time
|
| 4 |
+
from selenium import webdriver
|
| 5 |
+
from selenium.webdriver.chrome.service import Service
|
| 6 |
+
from selenium.webdriver.chrome.options import Options
|
| 7 |
+
from webdriver_manager.chrome import ChromeDriverManager
|
| 8 |
+
from selenium.webdriver.common.by import By
|
| 9 |
+
from selenium.webdriver.support.ui import WebDriverWait
|
| 10 |
+
from selenium.webdriver.support import expected_conditions as EC
|
| 11 |
+
|
| 12 |
+
def scrape_leaderboards(regions=None, pages_per_region=5, output_file=None, delay=2):
|
| 13 |
+
"""
|
| 14 |
+
Scrape leaderboard data from op.gg for specified regions and return as DataFrame.
|
| 15 |
+
|
| 16 |
+
Args:
|
| 17 |
+
regions (list): List of regions to scrape. Defaults to ["kr", "na", "vn", "euw"]
|
| 18 |
+
pages_per_region (int): Number of pages to scrape per region. Defaults to 5
|
| 19 |
+
output_file (str): Path to output file. Defaults to "util/data/leaderboard_data.csv"
|
| 20 |
+
delay (int): Delay between requests in seconds. Defaults to 2
|
| 21 |
+
|
| 22 |
+
Returns:
|
| 23 |
+
pandas.DataFrame: Scraped leaderboard data
|
| 24 |
+
"""
|
| 25 |
+
# Set defaults
|
| 26 |
+
if regions is None:
|
| 27 |
+
regions = ["kr", "na", "vn", "euw"]
|
| 28 |
+
|
| 29 |
+
if output_file is None:
|
| 30 |
+
output_file = os.path.join("util", "data", "leaderboard_data.csv")
|
| 31 |
+
|
| 32 |
+
# Initialize data list to store rows
|
| 33 |
+
leaderboard_data = []
|
| 34 |
+
|
| 35 |
+
try:
|
| 36 |
+
# Setup Chrome options
|
| 37 |
+
chrome_options = Options()
|
| 38 |
+
chrome_options.add_argument("--headless")
|
| 39 |
+
chrome_options.add_argument("--no-sandbox")
|
| 40 |
+
chrome_options.add_argument("--disable-dev-shm-usage")
|
| 41 |
+
chrome_options.add_argument("--disable-gpu")
|
| 42 |
+
chrome_options.add_argument("--disable-logging")
|
| 43 |
+
chrome_options.add_argument("--log-level=3")
|
| 44 |
+
chrome_options.add_argument("--disable-extensions")
|
| 45 |
+
chrome_options.page_load_strategy = 'eager'
|
| 46 |
+
chrome_options.add_argument(
|
| 47 |
+
"user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
|
| 48 |
+
)
|
| 49 |
+
|
| 50 |
+
# Initialize WebDriver
|
| 51 |
+
driver = webdriver.Chrome(
|
| 52 |
+
service=Service(ChromeDriverManager().install()),
|
| 53 |
+
options=chrome_options
|
| 54 |
+
)
|
| 55 |
+
|
| 56 |
+
for region in regions:
|
| 57 |
+
print(f"\nScraping {region.upper()} region...")
|
| 58 |
+
for page in range(1, pages_per_region + 1):
|
| 59 |
+
print(f"Processing page {page}/{pages_per_region}")
|
| 60 |
+
url = f"https://www.op.gg/leaderboards/tier?region={region}&type=ladder&page={page}"
|
| 61 |
+
|
| 62 |
+
try:
|
| 63 |
+
# Access the webpage
|
| 64 |
+
driver.get(url)
|
| 65 |
+
|
| 66 |
+
# Wait for table to load
|
| 67 |
+
table = WebDriverWait(driver, 15).until(
|
| 68 |
+
EC.presence_of_element_located((By.CSS_SELECTOR, "table.css-1l95r9q.e4dns9u11"))
|
| 69 |
+
)
|
| 70 |
+
|
| 71 |
+
# Process rows
|
| 72 |
+
rows = table.find_elements(By.TAG_NAME, "tr")[1:] # Skip header row
|
| 73 |
+
for row in rows:
|
| 74 |
+
try:
|
| 75 |
+
cells = row.find_elements(By.TAG_NAME, "td")
|
| 76 |
+
if len(cells) >= 7:
|
| 77 |
+
# Extract basic data
|
| 78 |
+
summoner = cells[1].text.strip().replace("\n", " ")
|
| 79 |
+
rank = cells[0].text.strip()
|
| 80 |
+
tier = cells[2].text.strip()
|
| 81 |
+
lp = cells[3].text.strip()
|
| 82 |
+
level = cells[5].text.strip()
|
| 83 |
+
|
| 84 |
+
# Extract champion data
|
| 85 |
+
champion_imgs = cells[4].find_elements(By.TAG_NAME, "img")
|
| 86 |
+
champions = [img.get_attribute("alt") for img in champion_imgs]
|
| 87 |
+
champion_data = champions + [""] * (3 - len(champions))
|
| 88 |
+
|
| 89 |
+
# Parse win/loss data
|
| 90 |
+
winrate_text = cells[6].text.strip().split("\n")
|
| 91 |
+
wins = winrate_text[0].rstrip("W") if len(winrate_text) > 0 else ""
|
| 92 |
+
losses = winrate_text[1].rstrip("L") if len(winrate_text) > 1 else ""
|
| 93 |
+
winrate = winrate_text[2] if len(winrate_text) > 2 else ""
|
| 94 |
+
|
| 95 |
+
# Append row data
|
| 96 |
+
leaderboard_data.append({
|
| 97 |
+
"summoner": summoner,
|
| 98 |
+
"region": region,
|
| 99 |
+
"rank": rank,
|
| 100 |
+
"tier": tier,
|
| 101 |
+
"lp": lp,
|
| 102 |
+
"most_champion_1": champion_data[0],
|
| 103 |
+
"most_champion_2": champion_data[1],
|
| 104 |
+
"most_champion_3": champion_data[2],
|
| 105 |
+
"level": level,
|
| 106 |
+
"win": wins,
|
| 107 |
+
"loss": losses,
|
| 108 |
+
"winrate": winrate
|
| 109 |
+
})
|
| 110 |
+
|
| 111 |
+
except Exception as e:
|
| 112 |
+
print(f"Error processing row in {region} page {page}: {e}")
|
| 113 |
+
continue
|
| 114 |
+
|
| 115 |
+
except Exception as e:
|
| 116 |
+
print(f"Error processing {region} page {page}: {e}")
|
| 117 |
+
continue
|
| 118 |
+
|
| 119 |
+
time.sleep(delay)
|
| 120 |
+
|
| 121 |
+
except Exception as e:
|
| 122 |
+
print(f"Fatal error: {e}")
|
| 123 |
+
return None
|
| 124 |
+
|
| 125 |
+
finally:
|
| 126 |
+
driver.quit()
|
| 127 |
+
|
| 128 |
+
# Create DataFrame
|
| 129 |
+
df = pd.DataFrame(leaderboard_data)
|
| 130 |
+
|
| 131 |
+
# Clean and convert data types
|
| 132 |
+
df['lp'] = df['lp'].str.replace(',', '').str.replace('LP', '').astype(float)
|
| 133 |
+
df['level'] = df['level'].astype(int)
|
| 134 |
+
df['win'] = pd.to_numeric(df['win'], errors='coerce')
|
| 135 |
+
df['loss'] = pd.to_numeric(df['loss'], errors='coerce')
|
| 136 |
+
df['winrate'] = df['winrate'].str.rstrip('%').astype(float) / 100
|
| 137 |
+
|
| 138 |
+
# Save to CSV if output_file is specified
|
| 139 |
+
if output_file:
|
| 140 |
+
os.makedirs(os.path.dirname(output_file), exist_ok=True)
|
| 141 |
+
df.to_csv(output_file, index=False)
|
| 142 |
+
print(f"Leaderboard data saved to {output_file}")
|
| 143 |
+
|
| 144 |
+
return df
|
util/Meta_scrapper.py
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import re
|
| 2 |
+
import os
|
| 3 |
+
import pandas as pd
|
| 4 |
+
from selenium import webdriver
|
| 5 |
+
from selenium.webdriver.chrome.service import Service
|
| 6 |
+
from selenium.webdriver.chrome.options import Options
|
| 7 |
+
from webdriver_manager.chrome import ChromeDriverManager
|
| 8 |
+
from selenium.webdriver.common.by import By
|
| 9 |
+
from selenium.webdriver.support.ui import WebDriverWait
|
| 10 |
+
from selenium.webdriver.support import expected_conditions as EC
|
| 11 |
+
|
| 12 |
+
# Constants
|
| 13 |
+
ROLES = ["top", "jungle", "mid", "adc", "support"]
|
| 14 |
+
BASE_URL = "https://www.op.gg/champions?position={role}"
|
| 15 |
+
TIER_COLOR_MAPPING = {
|
| 16 |
+
"#0093FF": 1, # Blue
|
| 17 |
+
"#00BBA3": 2, # Teal
|
| 18 |
+
"#FFB900": 3, # Yellow
|
| 19 |
+
"#9AA4AF": 4, # Gray
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
def setup_driver():
|
| 23 |
+
"""Setup and return a configured Chrome WebDriver with optimized settings"""
|
| 24 |
+
chrome_options = Options()
|
| 25 |
+
chrome_options.add_argument("--headless")
|
| 26 |
+
chrome_options.add_argument("--no-sandbox")
|
| 27 |
+
chrome_options.add_argument("--disable-dev-shm-usage")
|
| 28 |
+
chrome_options.add_argument("--disable-gpu")
|
| 29 |
+
chrome_options.add_argument("--disable-extensions")
|
| 30 |
+
chrome_options.add_argument("--disable-logging")
|
| 31 |
+
chrome_options.add_argument("--log-level=3")
|
| 32 |
+
chrome_options.add_argument("--silent")
|
| 33 |
+
chrome_options.add_argument(
|
| 34 |
+
"user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
|
| 35 |
+
)
|
| 36 |
+
|
| 37 |
+
# Remove log_level parameter from ChromeDriverManager
|
| 38 |
+
service = Service(ChromeDriverManager().install())
|
| 39 |
+
return webdriver.Chrome(service=service, options=chrome_options)
|
| 40 |
+
|
| 41 |
+
def parse_rate(rate_str):
|
| 42 |
+
"""Convert percentage string to float"""
|
| 43 |
+
try:
|
| 44 |
+
return float(rate_str.strip().rstrip('%')) / 100
|
| 45 |
+
except:
|
| 46 |
+
return 0.0
|
| 47 |
+
|
| 48 |
+
def extract_counter_champions(counter_column):
|
| 49 |
+
"""Extract counter champions from column"""
|
| 50 |
+
counter_champions = []
|
| 51 |
+
try:
|
| 52 |
+
counter_list = counter_column.find_elements(By.TAG_NAME, "a")
|
| 53 |
+
for counter in counter_list[:3]:
|
| 54 |
+
img_element = counter.find_element(By.TAG_NAME, "img")
|
| 55 |
+
champion_name = img_element.get_attribute("alt")
|
| 56 |
+
counter_champions.append(champion_name)
|
| 57 |
+
except Exception:
|
| 58 |
+
pass
|
| 59 |
+
return counter_champions + [""] * (3 - len(counter_champions))
|
| 60 |
+
|
| 61 |
+
def get_champion_table_data(driver, url, role):
|
| 62 |
+
"""Extract champion data from a specific role page with optimized parsing"""
|
| 63 |
+
try:
|
| 64 |
+
driver.get(url)
|
| 65 |
+
table = WebDriverWait(driver, 20).until(
|
| 66 |
+
EC.presence_of_element_located((By.CSS_SELECTOR, "#content-container > div.flex.gap-2.md\\:mx-auto.md\\:w-width-limit.mt-2.flex-col.overflow-hidden > div.flex.flex-row-reverse.gap-2 > main > div:nth-child(2) > table"))
|
| 67 |
+
)
|
| 68 |
+
|
| 69 |
+
champions_data = []
|
| 70 |
+
for row in table.find_elements(By.TAG_NAME, "tr"):
|
| 71 |
+
cols = row.find_elements(By.TAG_NAME, "td")
|
| 72 |
+
if len(cols) <= 1:
|
| 73 |
+
continue
|
| 74 |
+
|
| 75 |
+
# Get tier value
|
| 76 |
+
tier_element = cols[2].find_element(By.TAG_NAME, "svg")
|
| 77 |
+
tier = 5
|
| 78 |
+
if tier_element:
|
| 79 |
+
for path in tier_element.find_elements(By.TAG_NAME, "path"):
|
| 80 |
+
fill_color = path.get_attribute("fill")
|
| 81 |
+
if fill_color in TIER_COLOR_MAPPING:
|
| 82 |
+
tier = TIER_COLOR_MAPPING[fill_color]
|
| 83 |
+
break
|
| 84 |
+
|
| 85 |
+
# Extract ban rate
|
| 86 |
+
ban_rate_html = cols[6].get_attribute("innerHTML").strip()
|
| 87 |
+
ban_rate_match = re.search(r"([\d.]+)", ban_rate_html.replace("<!-- -->", ""))
|
| 88 |
+
ban_rate = float(ban_rate_match.group(1)) / 100 if ban_rate_match else 0.0
|
| 89 |
+
|
| 90 |
+
# Get counter champions
|
| 91 |
+
counter1, counter2, counter3 = extract_counter_champions(cols[7])
|
| 92 |
+
|
| 93 |
+
champions_data.append({
|
| 94 |
+
"rank": cols[0].text.strip(),
|
| 95 |
+
"champion": cols[1].text.strip(),
|
| 96 |
+
"tier": tier,
|
| 97 |
+
"role": role,
|
| 98 |
+
"win_rate": parse_rate(cols[4].text),
|
| 99 |
+
"pick_rate": parse_rate(cols[5].text),
|
| 100 |
+
"ban_rate": ban_rate,
|
| 101 |
+
"counter1": counter1,
|
| 102 |
+
"counter2": counter2,
|
| 103 |
+
"counter3": counter3,
|
| 104 |
+
})
|
| 105 |
+
|
| 106 |
+
return champions_data
|
| 107 |
+
|
| 108 |
+
except Exception as e:
|
| 109 |
+
print(f"Error extracting table data for {role}: {e}")
|
| 110 |
+
return []
|
| 111 |
+
|
| 112 |
+
def get_meta_stats():
|
| 113 |
+
"""Main function to scrape champion data with improved error handling and logging"""
|
| 114 |
+
driver = None
|
| 115 |
+
|
| 116 |
+
try:
|
| 117 |
+
driver = setup_driver()
|
| 118 |
+
all_roles_data = []
|
| 119 |
+
|
| 120 |
+
for role in ROLES:
|
| 121 |
+
role_url = BASE_URL.format(role=role)
|
| 122 |
+
role_data = get_champion_table_data(driver, role_url, role)
|
| 123 |
+
all_roles_data.extend(role_data)
|
| 124 |
+
|
| 125 |
+
if not all_roles_data:
|
| 126 |
+
print("No data was collected from any role")
|
| 127 |
+
return pd.DataFrame()
|
| 128 |
+
|
| 129 |
+
df = pd.DataFrame(all_roles_data)
|
| 130 |
+
|
| 131 |
+
# Save data
|
| 132 |
+
save_dir = os.path.join("util", "data")
|
| 133 |
+
os.makedirs(save_dir, exist_ok=True)
|
| 134 |
+
filepath = os.path.join(save_dir, "meta_stats.csv")
|
| 135 |
+
df.to_csv(filepath, index=False)
|
| 136 |
+
print(f"Saved meta stats to {filepath}")
|
| 137 |
+
return df
|
| 138 |
+
|
| 139 |
+
except Exception as e:
|
| 140 |
+
print(f"Error in get_meta_stats: {e}")
|
| 141 |
+
return pd.DataFrame()
|
| 142 |
+
|
| 143 |
+
finally:
|
| 144 |
+
if driver:
|
| 145 |
+
driver.quit()
|
| 146 |
+
|
| 147 |
+
|
util/Player_scrapper.py
ADDED
|
@@ -0,0 +1,544 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import time
|
| 3 |
+
from selenium import webdriver
|
| 4 |
+
from selenium.webdriver.chrome.service import Service
|
| 5 |
+
from selenium.webdriver.chrome.options import Options
|
| 6 |
+
from webdriver_manager.chrome import ChromeDriverManager
|
| 7 |
+
from selenium.webdriver.common.by import By
|
| 8 |
+
from selenium.webdriver.support.ui import WebDriverWait
|
| 9 |
+
from selenium.webdriver.support import expected_conditions as EC
|
| 10 |
+
import pandas as pd
|
| 11 |
+
from helper import format_summoner_name
|
| 12 |
+
|
| 13 |
+
# Constants
|
| 14 |
+
BASE_URL = "https://www.op.gg/summoners/{region}/{username}?queue_type=SOLORANKED"
|
| 15 |
+
MASTERY_URL = "https://www.op.gg/summoners/{region}/{username}/mastery"
|
| 16 |
+
|
| 17 |
+
def setup_driver():
|
| 18 |
+
"""Setup optimized Chrome WebDriver"""
|
| 19 |
+
options = Options()
|
| 20 |
+
options.add_argument("--headless")
|
| 21 |
+
options.add_argument("--no-sandbox")
|
| 22 |
+
options.add_argument("--disable-dev-shm-usage")
|
| 23 |
+
options.add_argument("--disable-gpu")
|
| 24 |
+
options.add_argument("--disable-logging")
|
| 25 |
+
options.add_argument("--log-level=3")
|
| 26 |
+
options.add_argument("--disable-extensions")
|
| 27 |
+
options.page_load_strategy = 'eager'
|
| 28 |
+
options.add_argument(
|
| 29 |
+
"user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
|
| 30 |
+
)
|
| 31 |
+
return webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
|
| 32 |
+
|
| 33 |
+
def wait_and_find_element(driver, selector, timeout=20, description="element"):
|
| 34 |
+
"""Utility function for waiting and finding elements"""
|
| 35 |
+
try:
|
| 36 |
+
element = WebDriverWait(driver, timeout).until(
|
| 37 |
+
EC.presence_of_element_located((By.CSS_SELECTOR, selector))
|
| 38 |
+
)
|
| 39 |
+
return element
|
| 40 |
+
except Exception as e:
|
| 41 |
+
print(f"Error finding {description}: {e}")
|
| 42 |
+
return None
|
| 43 |
+
|
| 44 |
+
def get_recent_stats(stats_box):
|
| 45 |
+
"""Extract recent statistics from stats box"""
|
| 46 |
+
try:
|
| 47 |
+
stats = stats_box.find_element(By.CSS_SELECTOR, "div.stats")
|
| 48 |
+
recent_stats = stats.text.strip().split("\n")
|
| 49 |
+
|
| 50 |
+
# Parse the stats into a structured format
|
| 51 |
+
games_info = recent_stats[0].split() # ['20G', '13W', '7L']
|
| 52 |
+
total_games = int(games_info[0].replace('G', ''))
|
| 53 |
+
wins = int(games_info[1].replace('W', ''))
|
| 54 |
+
losses = int(games_info[2].replace('L', ''))
|
| 55 |
+
|
| 56 |
+
win_rate = float(recent_stats[1].replace('%', '')) / 100
|
| 57 |
+
|
| 58 |
+
kda_parts = recent_stats[2].split(' / ') # ['5.1', '4.0', '7.9']
|
| 59 |
+
kills = float(kda_parts[0])
|
| 60 |
+
deaths = float(kda_parts[1])
|
| 61 |
+
assists = float(kda_parts[2])
|
| 62 |
+
|
| 63 |
+
kda_ratio = float(recent_stats[3].replace(':1', ''))
|
| 64 |
+
kill_participation = float(recent_stats[4].replace('P/Kill ', '').replace('%', '')) / 100
|
| 65 |
+
|
| 66 |
+
recent_stats = {
|
| 67 |
+
"total_games": total_games,
|
| 68 |
+
"wins": wins,
|
| 69 |
+
"losses": losses,
|
| 70 |
+
"win_rate": win_rate,
|
| 71 |
+
"avg_kills": kills,
|
| 72 |
+
"avg_deaths": deaths,
|
| 73 |
+
"avg_assists": assists,
|
| 74 |
+
"kda_ratio": kda_ratio,
|
| 75 |
+
"kill_participation": kill_participation,
|
| 76 |
+
}
|
| 77 |
+
|
| 78 |
+
except Exception as e:
|
| 79 |
+
print(f"Error extracting recent stats: {e}")
|
| 80 |
+
return None
|
| 81 |
+
|
| 82 |
+
return recent_stats
|
| 83 |
+
|
| 84 |
+
def get_recent_champions(stats_box):
|
| 85 |
+
champions = stats_box.find_element(By.CSS_SELECTOR, "div.champions")
|
| 86 |
+
champion_elements = champions.find_elements(By.CSS_SELECTOR, "li")
|
| 87 |
+
|
| 88 |
+
# Initialize flat dictionary with defaults
|
| 89 |
+
recent_champ_stats = {
|
| 90 |
+
"most_champ_1": None, "WR_1": 0.0, "W_1": 0, "L_1": 0, "KDA_1": 0.0,
|
| 91 |
+
"most_champ_2": None, "WR_2": 0.0, "W_2": 0, "L_2": 0, "KDA_2": 0.0,
|
| 92 |
+
"most_champ_3": None, "WR_3": 0.0, "W_3": 0, "L_3": 0, "KDA_3": 0.0
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
for i, champion in enumerate(champion_elements, 1):
|
| 96 |
+
try:
|
| 97 |
+
# Initialize kda for this iteration
|
| 98 |
+
kda = 0.0
|
| 99 |
+
|
| 100 |
+
# Extract champion name and image source
|
| 101 |
+
champ_name = champion.find_element(By.TAG_NAME, "img").get_attribute("alt")
|
| 102 |
+
|
| 103 |
+
# Extract win/lose stats and KDA
|
| 104 |
+
win_lose = champion.find_element(By.CSS_SELECTOR, ".win-lose").text.strip()
|
| 105 |
+
win_rate = float(win_lose.split('%')[0]) / 100 # "75%" -> 0.75
|
| 106 |
+
wins = int(win_lose.split('(')[1].split('W')[0]) # "(3W 1L)" -> 3
|
| 107 |
+
losses = int(win_lose.split('W')[1].split('L')[0]) # "1L)" -> 1
|
| 108 |
+
|
| 109 |
+
# KDA processing with a more precise selector
|
| 110 |
+
try:
|
| 111 |
+
kda_element = champion.find_element(By.CSS_SELECTOR, "div[class*='e1t9nk8i2']")
|
| 112 |
+
if kda_element:
|
| 113 |
+
kda_text = kda_element.text.strip()
|
| 114 |
+
#print(f"Found KDA text for champion {i}: '{kda_text}'") # Debug print
|
| 115 |
+
if kda_text and "KDA" in kda_text:
|
| 116 |
+
kda = float(kda_text.split("KDA")[0].strip())
|
| 117 |
+
#print(f"Parsed KDA value: {kda}") # Debug print
|
| 118 |
+
else:
|
| 119 |
+
print(f"Invalid KDA text format for champion {i}: '{kda_text}'")
|
| 120 |
+
else:
|
| 121 |
+
print(f"No KDA element found for champion {i}")
|
| 122 |
+
except Exception as e:
|
| 123 |
+
print(f"Error processing KDA: {e}")
|
| 124 |
+
kda = 0.0
|
| 125 |
+
|
| 126 |
+
# Update flat dictionary
|
| 127 |
+
recent_champ_stats[f"most_champ_{i}"] = champ_name
|
| 128 |
+
recent_champ_stats[f"WR_{i}"] = win_rate
|
| 129 |
+
recent_champ_stats[f"W_{i}"] = wins
|
| 130 |
+
recent_champ_stats[f"L_{i}"] = losses
|
| 131 |
+
recent_champ_stats[f"KDA_{i}"] = kda
|
| 132 |
+
|
| 133 |
+
except Exception as e:
|
| 134 |
+
print(f"Error processing champion {i}: {e}")
|
| 135 |
+
# Dictionary already has default values for this champion
|
| 136 |
+
continue
|
| 137 |
+
|
| 138 |
+
return recent_champ_stats
|
| 139 |
+
|
| 140 |
+
def get_preferred_role(stats_box):
|
| 141 |
+
# Role priority (higher index = higher priority when tied)
|
| 142 |
+
role_priority = {
|
| 143 |
+
'SUPPORT': 0,
|
| 144 |
+
'ADC': 1,
|
| 145 |
+
'TOP': 2,
|
| 146 |
+
'JUNGLE': 3,
|
| 147 |
+
'MID': 4
|
| 148 |
+
}
|
| 149 |
+
|
| 150 |
+
# Find the positions section
|
| 151 |
+
positions = stats_box.find_element(By.CSS_SELECTOR, "div.positions")
|
| 152 |
+
role_elements = positions.find_elements(By.CSS_SELECTOR, "li")
|
| 153 |
+
|
| 154 |
+
preferred_roles = {
|
| 155 |
+
'TOP': 0.0, 'JUNGLE': 0.0, 'MID': 0.0, 'ADC': 0.0, 'SUPPORT': 0.0,
|
| 156 |
+
'most_role_1': None, 'most_role_2': None,
|
| 157 |
+
'most_role_1_value': 0.0, 'most_role_2_value': 0.0
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
# First, collect all role percentages
|
| 161 |
+
for role in role_elements:
|
| 162 |
+
role_name = role.find_element(By.CSS_SELECTOR, "div.position img").get_attribute("alt")
|
| 163 |
+
percentage = role.find_element(By.CSS_SELECTOR, "div.gauge").get_attribute("style")
|
| 164 |
+
|
| 165 |
+
if percentage:
|
| 166 |
+
percentage_value = percentage.split(":")[1].strip().replace("%", "").strip(';')
|
| 167 |
+
try:
|
| 168 |
+
preferred_roles[role_name] = int(percentage_value)/100
|
| 169 |
+
except ValueError:
|
| 170 |
+
preferred_roles[role_name] = 0
|
| 171 |
+
|
| 172 |
+
# Sort roles by percentage first, then by priority when tied
|
| 173 |
+
sorted_roles = sorted(
|
| 174 |
+
[(role, value) for role, value in preferred_roles.items() if role in role_priority],
|
| 175 |
+
key=lambda x: (x[1], role_priority[x[0]]), # Sort by percentage first, then role priority
|
| 176 |
+
reverse=True
|
| 177 |
+
)
|
| 178 |
+
|
| 179 |
+
# Add top 2 roles if they exist
|
| 180 |
+
if len(sorted_roles) > 0:
|
| 181 |
+
preferred_roles['most_role_1'] = sorted_roles[0][0]
|
| 182 |
+
preferred_roles['most_role_1_value'] = sorted_roles[0][1]
|
| 183 |
+
if len(sorted_roles) > 1:
|
| 184 |
+
preferred_roles['most_role_2'] = sorted_roles[1][0]
|
| 185 |
+
preferred_roles['most_role_2_value'] = sorted_roles[1][1]
|
| 186 |
+
|
| 187 |
+
return preferred_roles
|
| 188 |
+
|
| 189 |
+
def get_weekly_stats(ranked_7d_box):
|
| 190 |
+
# Find the list of champions in the ranked 7d box
|
| 191 |
+
champion_elements = ranked_7d_box.find_elements(By.CSS_SELECTOR, "ul li")[:3]
|
| 192 |
+
|
| 193 |
+
# Initialize flat dictionary with defaults for 3 champions
|
| 194 |
+
weekly_stats = {
|
| 195 |
+
"7d_champ_1": None, "7d_total_1": 0, "7d_W_1": 0, "7d_L_1": 0, "7d_WR_1": 0.0,
|
| 196 |
+
"7d_champ_2": None, "7d_total_2": 0, "7d_W_2": 0, "7d_L_2": 0, "7d_WR_2": 0.0,
|
| 197 |
+
"7d_champ_3": None, "7d_total_3": 0, "7d_W_3": 0, "7d_L_3": 0, "7d_WR_3": 0.0
|
| 198 |
+
}
|
| 199 |
+
|
| 200 |
+
# Find the list of champions and take first 3
|
| 201 |
+
for i, champion in enumerate(champion_elements, 1):
|
| 202 |
+
try:
|
| 203 |
+
# Extract champion name
|
| 204 |
+
champ_name = champion.find_element(By.CSS_SELECTOR, "div.info > div.name > a").text.strip()
|
| 205 |
+
|
| 206 |
+
# Extract wins and losses
|
| 207 |
+
try:
|
| 208 |
+
win_text = champion.find_element(By.XPATH, ".//div[@class='graph']//div[@class='text left']").text.strip()
|
| 209 |
+
loss_text = champion.find_element(By.XPATH, ".//div[@class='graph']//div[@class='text right']").text.strip()
|
| 210 |
+
wins = int(win_text.replace('W', '').strip()) if 'W' in win_text else 0
|
| 211 |
+
losses = int(loss_text.replace('L', '').strip()) if 'L' in loss_text else 0
|
| 212 |
+
except Exception:
|
| 213 |
+
wins = 0
|
| 214 |
+
losses = 0
|
| 215 |
+
|
| 216 |
+
# Calculate total games
|
| 217 |
+
total_games = wins + losses
|
| 218 |
+
|
| 219 |
+
# Extract win rate
|
| 220 |
+
try:
|
| 221 |
+
win_rate_text = champion.find_element(By.CSS_SELECTOR, "div.winratio").text.strip()
|
| 222 |
+
win_rate = float(win_rate_text.replace('%', '').strip()) / 100 if win_rate_text else 0
|
| 223 |
+
except Exception:
|
| 224 |
+
win_rate = 0
|
| 225 |
+
|
| 226 |
+
# Update flat dictionary with dynamic numbering
|
| 227 |
+
weekly_stats[f"7d_champ_{i}"] = champ_name
|
| 228 |
+
weekly_stats[f"7d_total_{i}"] = total_games
|
| 229 |
+
weekly_stats[f"7d_W_{i}"] = wins
|
| 230 |
+
weekly_stats[f"7d_L_{i}"] = losses
|
| 231 |
+
weekly_stats[f"7d_WR_{i}"] = win_rate
|
| 232 |
+
|
| 233 |
+
except Exception as e:
|
| 234 |
+
print(f"Error processing champion {i} in 7d stats: {e}")
|
| 235 |
+
# Add default values for error cases
|
| 236 |
+
weekly_stats[f"7d_champ_{i}"] = None
|
| 237 |
+
weekly_stats[f"7d_total_{i}"] = 0
|
| 238 |
+
weekly_stats[f"7d_W_{i}"] = 0
|
| 239 |
+
weekly_stats[f"7d_L_{i}"] = 0
|
| 240 |
+
weekly_stats[f"7d_WR_{i}"] = 0.0
|
| 241 |
+
|
| 242 |
+
return weekly_stats
|
| 243 |
+
|
| 244 |
+
def get_season_data(season_champ_box):
|
| 245 |
+
# Initialize flat dictionary with defaults for 7 champions
|
| 246 |
+
season_data = {
|
| 247 |
+
"season_champ_1": None, "cs_ssn_1": "0", "cpm_ssn_1": "0", "kda_ssn_1": "0", "k_ssn_1": "0", "d_ssn_1": "0", "a_ssn_1": "0", "wr_ssn_1": 0.0, "games_ssn_1": "0",
|
| 248 |
+
"season_champ_2": None, "cs_ssn_2": "0", "cpm_ssn_2": "0", "kda_ssn_2": "0", "k_ssn_2": "0", "d_ssn_2": "0", "a_ssn_2": "0", "wr_ssn_2": 0.0, "games_ssn_2": "0",
|
| 249 |
+
"season_champ_3": None, "cs_ssn_3": "0", "cpm_ssn_3": "0", "kda_ssn_3": "0", "k_ssn_3": "0", "d_ssn_3": "0", "a_ssn_3": "0", "wr_ssn_3": 0.0, "games_ssn_3": "0",
|
| 250 |
+
"season_champ_4": None, "cs_ssn_4": "0", "cpm_ssn_4": "0", "kda_ssn_4": "0", "k_ssn_4": "0", "d_ssn_4": "0", "a_ssn_4": "0", "wr_ssn_4": 0.0, "games_ssn_4": "0",
|
| 251 |
+
"season_champ_5": None, "cs_ssn_5": "0", "cpm_ssn_5": "0", "kda_ssn_5": "0", "k_ssn_5": "0", "d_ssn_5": "0", "a_ssn_5": "0", "wr_ssn_5": 0.0, "games_ssn_5": "0",
|
| 252 |
+
"season_champ_6": None, "cs_ssn_6": "0", "cpm_ssn_6": "0", "kda_ssn_6": "0", "k_ssn_6": "0", "d_ssn_6": "0", "a_ssn_6": "0", "wr_ssn_6": 0.0, "games_ssn_6": "0",
|
| 253 |
+
"season_champ_7": None, "cs_ssn_7": "0", "cpm_ssn_7": "0", "kda_ssn_7": "0", "k_ssn_7": "0", "d_ssn_7": "0", "a_ssn_7": "0", "wr_ssn_7": 0.0, "games_ssn_7": "0"
|
| 254 |
+
}
|
| 255 |
+
|
| 256 |
+
try:
|
| 257 |
+
# Find all champion boxes directly
|
| 258 |
+
champion_boxes = season_champ_box.find_elements(By.CSS_SELECTOR, "div.champion-box")
|
| 259 |
+
|
| 260 |
+
for i, box in enumerate(champion_boxes[:7], 1):
|
| 261 |
+
try:
|
| 262 |
+
# Extract champion name
|
| 263 |
+
champ_name = box.find_element(By.CSS_SELECTOR, "div.name a").text.strip()
|
| 264 |
+
# Extract CS stats and CPM
|
| 265 |
+
cs_text = box.find_element(By.CSS_SELECTOR, "div.cs").text.strip()
|
| 266 |
+
cs_parts = cs_text.split()
|
| 267 |
+
cs_stats = cs_parts[1] if len(cs_parts) > 1 else "0"
|
| 268 |
+
# Extract CPM from parentheses
|
| 269 |
+
cpm = cs_parts[2].strip('()') if len(cs_parts) > 2 else "0"
|
| 270 |
+
|
| 271 |
+
# Extract KDA ratio
|
| 272 |
+
kda_element = box.find_element(By.CSS_SELECTOR, "div.kda div[class^='css-']")
|
| 273 |
+
kda_text = kda_element.text.strip()
|
| 274 |
+
kda_ratio = kda_text.replace(" KDA", "").replace(":1", "").strip()
|
| 275 |
+
|
| 276 |
+
# Extract K/D/A averages
|
| 277 |
+
kda_detail = box.find_element(By.CSS_SELECTOR, "div.kda div.detail").text.strip()
|
| 278 |
+
k, d, a = map(str.strip, kda_detail.split('/'))
|
| 279 |
+
|
| 280 |
+
# Extract win rate
|
| 281 |
+
win_rate_element = box.find_element(By.CSS_SELECTOR, "div.played div[class^='css-']")
|
| 282 |
+
win_rate_text = win_rate_element.text.strip()
|
| 283 |
+
win_rate = float(win_rate_text.replace('%', '')) / 100
|
| 284 |
+
|
| 285 |
+
# Extract games played
|
| 286 |
+
games_text = box.find_element(By.CSS_SELECTOR, "div.played div.count").text.strip()
|
| 287 |
+
games_played = games_text.replace(" Played", "")
|
| 288 |
+
|
| 289 |
+
# Update flat dictionary
|
| 290 |
+
season_data[f"season_champ_{i}"] = champ_name
|
| 291 |
+
season_data[f"cs_ssn_{i}"] = cs_stats
|
| 292 |
+
season_data[f"cpm_ssn_{i}"] = cpm
|
| 293 |
+
season_data[f"kda_ssn_{i}"] = kda_ratio
|
| 294 |
+
season_data[f"k_ssn_{i}"] = k
|
| 295 |
+
season_data[f"d_ssn_{i}"] = d
|
| 296 |
+
season_data[f"a_ssn_{i}"] = a
|
| 297 |
+
season_data[f"wr_ssn_{i}"] = win_rate
|
| 298 |
+
season_data[f"games_ssn_{i}"] = games_played
|
| 299 |
+
|
| 300 |
+
except Exception as e:
|
| 301 |
+
print(f"Error processing champion {i}: {str(e)}")
|
| 302 |
+
print(f"Error type: {type(e).__name__}")
|
| 303 |
+
|
| 304 |
+
except Exception as e:
|
| 305 |
+
print(f"Error in get_season_data main block: {str(e)}")
|
| 306 |
+
print(f"Error type: {type(e).__name__}")
|
| 307 |
+
|
| 308 |
+
return season_data
|
| 309 |
+
|
| 310 |
+
def get_mastery_data(driver):
|
| 311 |
+
# Initialize dictionary with metadata
|
| 312 |
+
mastery_data = { }
|
| 313 |
+
|
| 314 |
+
try:
|
| 315 |
+
# Wait for container to load
|
| 316 |
+
WebDriverWait(driver, 20).until(
|
| 317 |
+
EC.presence_of_element_located((By.CSS_SELECTOR, "div.css-zefc5s.e1poynyt0"))
|
| 318 |
+
)
|
| 319 |
+
|
| 320 |
+
# Get all champion boxes (limiting to first 16)
|
| 321 |
+
champion_boxes = driver.find_elements(By.CSS_SELECTOR, "div.css-8fea4f.e1poynyt1")[:16]
|
| 322 |
+
|
| 323 |
+
# Process each champion
|
| 324 |
+
for i, champion in enumerate(champion_boxes, 1):
|
| 325 |
+
try:
|
| 326 |
+
name = champion.find_element(By.CSS_SELECTOR, "strong.champion-name").text.strip()
|
| 327 |
+
level = champion.find_element(By.CSS_SELECTOR, "div.champion-level__text > span").text.strip()
|
| 328 |
+
#points = champion.find_element(By.CSS_SELECTOR, "div.champion-point > span").text.strip()
|
| 329 |
+
|
| 330 |
+
mastery_data[f"mastery_champ_{i}"] = name
|
| 331 |
+
mastery_data[f"m_lv_{i}"] = level
|
| 332 |
+
#mastery_data[f"m_points_{i}"] = points.replace(",", "")
|
| 333 |
+
|
| 334 |
+
except Exception as e:
|
| 335 |
+
print(f"Error processing champion {i}: {e}")
|
| 336 |
+
mastery_data[f"mastery_champ_{i}"] = None
|
| 337 |
+
mastery_data[f"m_lv_{i}"] = "0"
|
| 338 |
+
#mastery_data[f"m_points_{i}"] = "0"
|
| 339 |
+
|
| 340 |
+
except Exception as e:
|
| 341 |
+
print(f"Error scraping mastery data: {e}")
|
| 342 |
+
|
| 343 |
+
return mastery_data
|
| 344 |
+
|
| 345 |
+
|
| 346 |
+
def get_player_stats(region, username):
|
| 347 |
+
"""Main function to get player statistics"""
|
| 348 |
+
driver = None
|
| 349 |
+
try:
|
| 350 |
+
driver = setup_driver()
|
| 351 |
+
|
| 352 |
+
# Format URLs
|
| 353 |
+
profile_url = BASE_URL.format(region=region, username=username)
|
| 354 |
+
mastery_url = MASTERY_URL.format(region=region, username=username)
|
| 355 |
+
|
| 356 |
+
# Get main profile data
|
| 357 |
+
driver.get(profile_url)
|
| 358 |
+
|
| 359 |
+
# Find main containers
|
| 360 |
+
main_container = wait_and_find_element(driver, "#content-container")
|
| 361 |
+
if not main_container:
|
| 362 |
+
raise Exception("Could not find main container")
|
| 363 |
+
|
| 364 |
+
stats_box = wait_and_find_element(
|
| 365 |
+
driver,
|
| 366 |
+
"div.stats-box.stats-box--SOLORANKED"
|
| 367 |
+
)
|
| 368 |
+
|
| 369 |
+
season_champ_box = wait_and_find_element(
|
| 370 |
+
driver,
|
| 371 |
+
"div:nth-child(1) > div.css-18w3o0f.ere6j7v0"
|
| 372 |
+
)
|
| 373 |
+
|
| 374 |
+
ranked_7d_box = wait_and_find_element(
|
| 375 |
+
driver,
|
| 376 |
+
"div[class*='efsztyx0']"
|
| 377 |
+
)
|
| 378 |
+
|
| 379 |
+
# Extract all stats
|
| 380 |
+
player_data = {
|
| 381 |
+
'recent_stats': get_recent_stats(stats_box) if stats_box else None,
|
| 382 |
+
'recent_champions': get_recent_champions(stats_box) if stats_box else None,
|
| 383 |
+
'preferred_roles': get_preferred_role(stats_box) if stats_box else None,
|
| 384 |
+
'season_data': get_season_data(season_champ_box) if season_champ_box else None,
|
| 385 |
+
'weekly_stats': get_weekly_stats(ranked_7d_box) if ranked_7d_box else None,
|
| 386 |
+
}
|
| 387 |
+
|
| 388 |
+
# Get mastery data
|
| 389 |
+
driver.get(mastery_url)
|
| 390 |
+
mastery_data = get_mastery_data(driver)
|
| 391 |
+
player_data['mastery_data'] = mastery_data
|
| 392 |
+
|
| 393 |
+
# Create DataFrames
|
| 394 |
+
dfs = {}
|
| 395 |
+
for key, data in player_data.items():
|
| 396 |
+
if data:
|
| 397 |
+
dfs[key] = pd.DataFrame([data])
|
| 398 |
+
|
| 399 |
+
# Add player ID and region to each DataFrame
|
| 400 |
+
for df in dfs.values():
|
| 401 |
+
df.insert(0, 'player_id', username) # Insert player_id as first column
|
| 402 |
+
df.insert(1, 'region', region) # Insert region as second column
|
| 403 |
+
|
| 404 |
+
# Merge all DataFrames into one
|
| 405 |
+
merged_df = None
|
| 406 |
+
for name, df in dfs.items():
|
| 407 |
+
if merged_df is None:
|
| 408 |
+
merged_df = df
|
| 409 |
+
else:
|
| 410 |
+
# Drop common columns except player_id and region
|
| 411 |
+
common_cols = df.columns.intersection(merged_df.columns)
|
| 412 |
+
cols_to_drop = [col for col in common_cols if col not in ['player_id', 'region']]
|
| 413 |
+
df_to_merge = df.drop(columns=cols_to_drop, errors='ignore')
|
| 414 |
+
merged_df = pd.merge(merged_df, df_to_merge, on=['player_id', 'region'], how='outer')
|
| 415 |
+
|
| 416 |
+
# Ensure player_id and region are the first columns in final order
|
| 417 |
+
if merged_df is not None and not merged_df.empty:
|
| 418 |
+
# Get all columns except player_id and region
|
| 419 |
+
other_cols = [col for col in merged_df.columns if col not in ['player_id', 'region']]
|
| 420 |
+
# Reorder columns with player_id and region first
|
| 421 |
+
merged_df = merged_df[['player_id', 'region'] + other_cols]
|
| 422 |
+
|
| 423 |
+
# # Save merged DataFrame
|
| 424 |
+
# save_dir = "util/data"
|
| 425 |
+
# os.makedirs(save_dir, exist_ok=True)
|
| 426 |
+
|
| 427 |
+
# if merged_df is not None and not merged_df.empty:
|
| 428 |
+
# filepath = os.path.join(save_dir, f"player_stats.csv")
|
| 429 |
+
# merged_df.to_csv(filepath, index=False)
|
| 430 |
+
# print(f"Saved player stats to {filepath}")
|
| 431 |
+
|
| 432 |
+
return merged_df, dfs
|
| 433 |
+
|
| 434 |
+
except Exception as e:
|
| 435 |
+
print(f"Error in get_player_stats: {e}")
|
| 436 |
+
return None, {}
|
| 437 |
+
|
| 438 |
+
finally:
|
| 439 |
+
if driver:
|
| 440 |
+
driver.quit()
|
| 441 |
+
|
| 442 |
+
def get_multiple_player_stats(players_df):
|
| 443 |
+
"""
|
| 444 |
+
Get stats for multiple players from a DataFrame
|
| 445 |
+
|
| 446 |
+
Parameters:
|
| 447 |
+
players_df: DataFrame with columns 'region' and 'username'
|
| 448 |
+
"""
|
| 449 |
+
all_merged_dfs = []
|
| 450 |
+
error_players = []
|
| 451 |
+
|
| 452 |
+
save_dir = "util/data"
|
| 453 |
+
os.makedirs(save_dir, exist_ok=True)
|
| 454 |
+
checkpoint_file = os.path.join(save_dir, "player_stats_checkpoint.csv")
|
| 455 |
+
all_merged_dfs = []
|
| 456 |
+
error_players = []
|
| 457 |
+
|
| 458 |
+
# Load checkpoint if exists
|
| 459 |
+
start_idx = 0
|
| 460 |
+
if os.path.exists(checkpoint_file):
|
| 461 |
+
try:
|
| 462 |
+
checkpoint_df = pd.read_csv(checkpoint_file)
|
| 463 |
+
all_merged_dfs = [checkpoint_df]
|
| 464 |
+
# Get the number of players already processed
|
| 465 |
+
processed_players = set(checkpoint_df['player_id'])
|
| 466 |
+
# Filter out already processed players
|
| 467 |
+
players_df = players_df[~players_df['username'].isin(processed_players)]
|
| 468 |
+
print(f"Loaded checkpoint with {len(processed_players)} players already processed")
|
| 469 |
+
except Exception as e:
|
| 470 |
+
print(f"Error loading checkpoint: {e}")
|
| 471 |
+
|
| 472 |
+
print(f"Processing {len(players_df)} remaining players...")
|
| 473 |
+
|
| 474 |
+
for idx, row in players_df.iterrows():
|
| 475 |
+
region = row['region'].lower() # Ensure region is lowercase
|
| 476 |
+
username = row['username']
|
| 477 |
+
|
| 478 |
+
try:
|
| 479 |
+
# Format the username
|
| 480 |
+
formatted_username = format_summoner_name(username)
|
| 481 |
+
print(f"\nProcessing player {idx + 1}/{len(players_df)}: {username} ({region})")
|
| 482 |
+
print(f"Formatted username: {formatted_username}")
|
| 483 |
+
|
| 484 |
+
# Add delay between requests
|
| 485 |
+
if idx > 0:
|
| 486 |
+
time.sleep(2)
|
| 487 |
+
|
| 488 |
+
merged_df, _ = get_player_stats(region, formatted_username)
|
| 489 |
+
if merged_df is not None and not merged_df.empty:
|
| 490 |
+
# Store original username in the DataFrame
|
| 491 |
+
merged_df['player_id'] = username # Store original username
|
| 492 |
+
all_merged_dfs.append(merged_df)
|
| 493 |
+
print(f"Successfully processed {username}")
|
| 494 |
+
|
| 495 |
+
# Save checkpoint every 10 players
|
| 496 |
+
if len(all_merged_dfs) % 10 == 0:
|
| 497 |
+
checkpoint_save = pd.concat(all_merged_dfs, ignore_index=True)
|
| 498 |
+
checkpoint_save.to_csv(checkpoint_file, index=False)
|
| 499 |
+
print(f"Saved checkpoint after processing {len(all_merged_dfs)} players")
|
| 500 |
+
|
| 501 |
+
else:
|
| 502 |
+
print(f"No data found for {username}")
|
| 503 |
+
error_players.append({
|
| 504 |
+
'region': region,
|
| 505 |
+
'username': username,
|
| 506 |
+
'formatted_username': formatted_username,
|
| 507 |
+
'error': 'No data found'
|
| 508 |
+
})
|
| 509 |
+
|
| 510 |
+
except Exception as e:
|
| 511 |
+
print(f"Error processing {username}: {e}")
|
| 512 |
+
error_players.append({
|
| 513 |
+
'region': region,
|
| 514 |
+
'username': username,
|
| 515 |
+
'formatted_username': formatted_username if 'formatted_username' in locals() else 'Error in formatting',
|
| 516 |
+
'error': str(e)
|
| 517 |
+
})
|
| 518 |
+
continue
|
| 519 |
+
|
| 520 |
+
# Combine and save final results
|
| 521 |
+
if all_merged_dfs:
|
| 522 |
+
final_df = pd.concat(all_merged_dfs, ignore_index=True)
|
| 523 |
+
|
| 524 |
+
# Save final combined stats
|
| 525 |
+
filepath = os.path.join(save_dir, "player_stats.csv")
|
| 526 |
+
final_df.to_csv(filepath, index=False)
|
| 527 |
+
print(f"\nSaved combined stats for {len(all_merged_dfs)} players to {filepath}")
|
| 528 |
+
|
| 529 |
+
# Clean up checkpoint file
|
| 530 |
+
if os.path.exists(checkpoint_file):
|
| 531 |
+
os.remove(checkpoint_file)
|
| 532 |
+
print("Removed checkpoint file after successful completion")
|
| 533 |
+
|
| 534 |
+
# Save error log
|
| 535 |
+
if error_players:
|
| 536 |
+
error_df = pd.DataFrame(error_players)
|
| 537 |
+
error_filepath = os.path.join(save_dir, "player_stats_errors.csv")
|
| 538 |
+
error_df.to_csv(error_filepath, index=False)
|
| 539 |
+
print(f"Saved error log to {error_filepath}")
|
| 540 |
+
|
| 541 |
+
return final_df
|
| 542 |
+
else:
|
| 543 |
+
print("\nNo player data was collected")
|
| 544 |
+
return None
|
util/Recent_match_scrapper.py
ADDED
|
@@ -0,0 +1,393 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import time, os
|
| 2 |
+
from selenium import webdriver
|
| 3 |
+
from selenium.webdriver.chrome.service import Service
|
| 4 |
+
from selenium.webdriver.chrome.options import Options
|
| 5 |
+
from selenium.webdriver.common.by import By
|
| 6 |
+
from selenium.webdriver.support.ui import WebDriverWait
|
| 7 |
+
from selenium.webdriver.support import expected_conditions as EC
|
| 8 |
+
import pandas as pd
|
| 9 |
+
from urllib.parse import unquote
|
| 10 |
+
from webdriver_manager.chrome import ChromeDriverManager
|
| 11 |
+
from helper import convert_to_minutes, convert_percentage_to_decimal, convert_tier_to_number, convert_result_to_binary, format_summoner_name, convert_to_displayname
|
| 12 |
+
|
| 13 |
+
def setup_driver():
|
| 14 |
+
options = Options()
|
| 15 |
+
prefs = {
|
| 16 |
+
'profile.default_content_setting_values': {'notifications': 2},
|
| 17 |
+
'profile.managed_default_content_settings': {'images': 2}
|
| 18 |
+
}
|
| 19 |
+
options.add_experimental_option('prefs', prefs)
|
| 20 |
+
options.add_experimental_option('excludeSwitches', ['enable-logging'])
|
| 21 |
+
for arg in ['--headless', '--no-sandbox', '--disable-dev-shm-usage',
|
| 22 |
+
'--disable-gpu', '--window-size=1920,1080']:
|
| 23 |
+
options.add_argument(arg)
|
| 24 |
+
options.add_argument('user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/91.0.4472.124')
|
| 25 |
+
return webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
|
| 26 |
+
|
| 27 |
+
def get_tooltip_date(driver, element):
|
| 28 |
+
try:
|
| 29 |
+
driver.execute_script("""
|
| 30 |
+
arguments[0].scrollIntoView({block: 'center'});
|
| 31 |
+
document.querySelectorAll('span.react-tooltip-lite').forEach(e => e.remove());
|
| 32 |
+
arguments[0].dispatchEvent(new MouseEvent('mouseover', {
|
| 33 |
+
view: window, bubbles: true, cancelable: true
|
| 34 |
+
}));
|
| 35 |
+
""", element)
|
| 36 |
+
time.sleep(0.3)
|
| 37 |
+
return driver.execute_script("""
|
| 38 |
+
return Array.from(document.querySelectorAll('span.react-tooltip-lite'))
|
| 39 |
+
.find(t => t.offsetParent !== null)?.textContent || null;
|
| 40 |
+
""")
|
| 41 |
+
except: return None
|
| 42 |
+
|
| 43 |
+
def extract_match_data(match):
|
| 44 |
+
selectors = {
|
| 45 |
+
'time_stamp': "div.time-stamp > div",
|
| 46 |
+
'game_type': "div.game-type",
|
| 47 |
+
'result': "div.result",
|
| 48 |
+
'length': "div.length",
|
| 49 |
+
'kda': "div.kda",
|
| 50 |
+
'kda_ratio': "div.kda-ratio",
|
| 51 |
+
'cs': "div.cs",
|
| 52 |
+
'avg_tier': "div.avg-tier",
|
| 53 |
+
'laning': "div.laning",
|
| 54 |
+
'kill_participation': "div.p-kill",
|
| 55 |
+
'champion_img': "div.info a.champion img",
|
| 56 |
+
'champion_level': "div.info a.champion span.champion-level"
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
data = {}
|
| 60 |
+
try:
|
| 61 |
+
for key, selector in selectors.items():
|
| 62 |
+
element = match.find_element(By.CSS_SELECTOR, selector)
|
| 63 |
+
if key == 'champion_img':
|
| 64 |
+
data[key] = element.get_attribute('alt')
|
| 65 |
+
elif key == 'laning':
|
| 66 |
+
data[key] = element.text.replace('\n', '') # Remove newlines from laning data
|
| 67 |
+
else:
|
| 68 |
+
data[key] = element.text
|
| 69 |
+
except Exception as e:
|
| 70 |
+
print(f"Error extracting match data: {e}")
|
| 71 |
+
return data
|
| 72 |
+
|
| 73 |
+
def get_players_info(match):
|
| 74 |
+
try:
|
| 75 |
+
players = []
|
| 76 |
+
player_elements = match.find_elements(By.CSS_SELECTOR, "div.css-pp7uqb.e1xevas21")[:10]
|
| 77 |
+
for player in player_elements:
|
| 78 |
+
champion = player.find_element(By.CSS_SELECTOR, "div.icon img").get_attribute("alt")
|
| 79 |
+
href = player.find_element(By.CSS_SELECTOR, "div.name a").get_attribute("href")
|
| 80 |
+
region, name = href.split('/')[-2:]
|
| 81 |
+
# Decode the URL-encoded name
|
| 82 |
+
decoded_name = unquote(name)
|
| 83 |
+
#print(f"Found player: {decoded_name} with champion {champion}")
|
| 84 |
+
players.append({
|
| 85 |
+
"champion": champion,
|
| 86 |
+
"region": region,
|
| 87 |
+
"name": decoded_name
|
| 88 |
+
})
|
| 89 |
+
return players
|
| 90 |
+
except Exception as e:
|
| 91 |
+
print(f"Error getting players info: {e}")
|
| 92 |
+
return []
|
| 93 |
+
|
| 94 |
+
def convert_laning_ratio(laning_str):
|
| 95 |
+
"""Convert laning string (e.g., 'Laning 70:30') to decimal ratio"""
|
| 96 |
+
try:
|
| 97 |
+
# Extract the ratio part (e.g., '70:30' from 'Laning 70:30')
|
| 98 |
+
ratio_part = laning_str.split('Laning')[-1].strip()
|
| 99 |
+
|
| 100 |
+
# Split by ':' and convert to numbers
|
| 101 |
+
first_num, second_num = map(int, ratio_part.split(':'))
|
| 102 |
+
|
| 103 |
+
# Calculate ratio
|
| 104 |
+
if second_num != 0: # Avoid division by zero
|
| 105 |
+
ratio = round(first_num / second_num, 2)
|
| 106 |
+
return ratio
|
| 107 |
+
return 0.0
|
| 108 |
+
except Exception as e:
|
| 109 |
+
print(f"Laning conversion error for '{laning_str}': {e}")
|
| 110 |
+
return 0.0
|
| 111 |
+
|
| 112 |
+
def extract_cs_number(cs_str):
|
| 113 |
+
"""Extract pure CS number from string (e.g., 'CS 123 (7.9)' -> 123)"""
|
| 114 |
+
try:
|
| 115 |
+
# Extract first number from the string
|
| 116 |
+
cs_number = ''.join(filter(str.isdigit, cs_str.split('(')[0]))
|
| 117 |
+
return int(cs_number) if cs_number else 0
|
| 118 |
+
except:
|
| 119 |
+
return 0
|
| 120 |
+
|
| 121 |
+
def extract_cs_per_min(cs_str):
|
| 122 |
+
"""Extract CS per minute from string (e.g., 'CS 123 (7.9)' -> 7.9)"""
|
| 123 |
+
try:
|
| 124 |
+
# Extract number between parentheses
|
| 125 |
+
cs_per_min = cs_str.split('(')[1].split(')')[0]
|
| 126 |
+
return float(cs_per_min)
|
| 127 |
+
except:
|
| 128 |
+
return 0.0
|
| 129 |
+
|
| 130 |
+
def process_match_data(match_data, username, players):
|
| 131 |
+
try:
|
| 132 |
+
# Format username for comparison - ensure it's in display format
|
| 133 |
+
display_name = convert_to_displayname(username)
|
| 134 |
+
#print(f"\nInput username: {username}")
|
| 135 |
+
#print(f"Converted display name: {display_name}")
|
| 136 |
+
|
| 137 |
+
# # Debug print all players and their converted names
|
| 138 |
+
# print("\nAll players:")
|
| 139 |
+
# for p in players:
|
| 140 |
+
# orig_name = p['name']
|
| 141 |
+
# conv_name = convert_to_displayname(orig_name)
|
| 142 |
+
# print(f"Original: {orig_name} -> Converted: {conv_name}")
|
| 143 |
+
|
| 144 |
+
# Find player index using normalized comparison
|
| 145 |
+
player_index = next((i for i, p in enumerate(players)
|
| 146 |
+
if convert_to_displayname(p['name']).lower().replace(' ', '') ==
|
| 147 |
+
display_name.lower().replace(' ', '')), -1)
|
| 148 |
+
|
| 149 |
+
if player_index == -1:
|
| 150 |
+
print(f"\nWarning: Player {display_name} not found in players list")
|
| 151 |
+
print("Available players:", [convert_to_displayname(p['name']) for p in players])
|
| 152 |
+
return None
|
| 153 |
+
|
| 154 |
+
#print(f"\nFound player at index: {player_index}")
|
| 155 |
+
team = "blue" if player_index < 5 else "red"
|
| 156 |
+
#print(f"Team: {team}")
|
| 157 |
+
|
| 158 |
+
|
| 159 |
+
# Modify how teammates and opponents are filtered
|
| 160 |
+
if player_index < 5:
|
| 161 |
+
# Player is on blue team
|
| 162 |
+
teammates = [p for i, p in enumerate(players[:5])
|
| 163 |
+
if i != player_index] # Use index comparison instead of name
|
| 164 |
+
opponents = players[5:] # All red team players
|
| 165 |
+
else:
|
| 166 |
+
# Player is on red team
|
| 167 |
+
teammates = [p for i, p in enumerate(players[5:])
|
| 168 |
+
if i != (player_index - 5)] # Adjust index for red team
|
| 169 |
+
opponents = players[:5] # All blue team players
|
| 170 |
+
|
| 171 |
+
kda_parts = match_data.get('kda', '0/0/0').strip().split('/')
|
| 172 |
+
kills, deaths, assists = [kda_parts[i] if i < len(kda_parts) else "0" for i in range(3)]
|
| 173 |
+
kda_ratio = match_data.get("kda_ratio", "0").strip().replace(":1 KDA", "")
|
| 174 |
+
|
| 175 |
+
kill_participation = convert_percentage_to_decimal(match_data.get("kill_participation", "0%"))
|
| 176 |
+
|
| 177 |
+
laning_ratio = convert_laning_ratio(match_data.get("laning", "0:0"))
|
| 178 |
+
|
| 179 |
+
cs = extract_cs_number(match_data.get("cs", "0"))
|
| 180 |
+
cpm = extract_cs_per_min(match_data.get("cs", "0"))
|
| 181 |
+
|
| 182 |
+
match_length_str = match_data.get("length", "0m 0s")
|
| 183 |
+
match_length_mins = convert_to_minutes(match_length_str)
|
| 184 |
+
|
| 185 |
+
# Convert tier to number
|
| 186 |
+
avg_tier_num = convert_tier_to_number(match_data.get("avg_tier", ""))
|
| 187 |
+
|
| 188 |
+
result_num = convert_result_to_binary(match_data.get("result", ""))
|
| 189 |
+
|
| 190 |
+
match_row = {
|
| 191 |
+
"player_id": display_name, # Use display_name here
|
| 192 |
+
"date": match_data.get("match_date", ""),
|
| 193 |
+
"champion": match_data.get("champion_img", ""),
|
| 194 |
+
"level": match_data.get("champion_level", ""),
|
| 195 |
+
"team": team,
|
| 196 |
+
"result": result_num,
|
| 197 |
+
"match_length_mins": match_length_mins,
|
| 198 |
+
"kill": kills.strip(),
|
| 199 |
+
"death": deaths.strip(),
|
| 200 |
+
"assist": assists.strip(),
|
| 201 |
+
"kda_ratio": kda_ratio,
|
| 202 |
+
"kill_participation": kill_participation,
|
| 203 |
+
"laning": laning_ratio,
|
| 204 |
+
"cs": cs,
|
| 205 |
+
"cs_per_min": cpm,
|
| 206 |
+
"avg_tier": avg_tier_num
|
| 207 |
+
}
|
| 208 |
+
|
| 209 |
+
# Add teammates and opponents with display format
|
| 210 |
+
for i, (team_list, prefix) in enumerate([(teammates, "team"), (opponents, "opp")]):
|
| 211 |
+
for j, player in enumerate(team_list, 1):
|
| 212 |
+
if j <= 5: # Ensure we don't exceed 5 players per team
|
| 213 |
+
match_row[f"{prefix}mates{j}"] = convert_to_displayname(player["name"])
|
| 214 |
+
match_row[f"{prefix}_champ{j}"] = player["champion"]
|
| 215 |
+
|
| 216 |
+
return match_row
|
| 217 |
+
except Exception as e:
|
| 218 |
+
print(f"Error processing match: {e}")
|
| 219 |
+
return None
|
| 220 |
+
|
| 221 |
+
def get_matches_stats(region, username, max_retries=2):
|
| 222 |
+
"""
|
| 223 |
+
Get match stats for a single player with retry mechanism
|
| 224 |
+
"""
|
| 225 |
+
driver = None
|
| 226 |
+
retry_count = 0
|
| 227 |
+
|
| 228 |
+
while retry_count <= max_retries:
|
| 229 |
+
try:
|
| 230 |
+
driver = setup_driver()
|
| 231 |
+
driver.set_page_load_timeout(20) # Set page load timeout
|
| 232 |
+
|
| 233 |
+
url = f"https://www.op.gg/summoners/{region}/{username}?queue_type=SOLORANKED"
|
| 234 |
+
print(f"Accessing URL: {url}")
|
| 235 |
+
driver.get(url)
|
| 236 |
+
|
| 237 |
+
matches_container = WebDriverWait(driver, 20).until(
|
| 238 |
+
EC.presence_of_element_located((By.CSS_SELECTOR, "div.css-1jxewmm.ek41ybw0"))
|
| 239 |
+
)
|
| 240 |
+
|
| 241 |
+
matches_data = []
|
| 242 |
+
match_elements = matches_container.find_elements(By.CSS_SELECTOR, "div.css-j7qwjs.ery81n90")
|
| 243 |
+
|
| 244 |
+
#print(f"Found {len(match_elements)} matches")
|
| 245 |
+
|
| 246 |
+
for i, match in enumerate(match_elements, 1):
|
| 247 |
+
try:
|
| 248 |
+
match_data = extract_match_data(match)
|
| 249 |
+
players = get_players_info(match)
|
| 250 |
+
match_data['match_date'] = get_tooltip_date(
|
| 251 |
+
driver,
|
| 252 |
+
match.find_element(By.CSS_SELECTOR, "div.time-stamp > div")
|
| 253 |
+
)
|
| 254 |
+
|
| 255 |
+
processed_data = process_match_data(match_data, username, players)
|
| 256 |
+
if processed_data:
|
| 257 |
+
matches_data.append(processed_data)
|
| 258 |
+
except Exception as e:
|
| 259 |
+
print(f"Error processing match {i}: {e}")
|
| 260 |
+
continue
|
| 261 |
+
|
| 262 |
+
if matches_data:
|
| 263 |
+
return pd.DataFrame(matches_data)
|
| 264 |
+
else:
|
| 265 |
+
raise Exception("No valid matches found")
|
| 266 |
+
|
| 267 |
+
except Exception as e:
|
| 268 |
+
retry_count += 1
|
| 269 |
+
print(f"Attempt {retry_count} failed: {e}")
|
| 270 |
+
if retry_count <= max_retries:
|
| 271 |
+
print(f"Retrying... ({retry_count}/{max_retries})")
|
| 272 |
+
time.sleep(5) # Wait 5 seconds before retrying
|
| 273 |
+
else:
|
| 274 |
+
print(f"Max retries reached")
|
| 275 |
+
return pd.DataFrame()
|
| 276 |
+
|
| 277 |
+
finally:
|
| 278 |
+
if driver:
|
| 279 |
+
driver.quit()
|
| 280 |
+
|
| 281 |
+
return pd.DataFrame()
|
| 282 |
+
|
| 283 |
+
def get_multiple_matches_stats(players_df):
|
| 284 |
+
"""
|
| 285 |
+
Get match stats for multiple players from a DataFrame
|
| 286 |
+
|
| 287 |
+
Parameters:
|
| 288 |
+
players_df: DataFrame with columns 'region' and 'username'
|
| 289 |
+
"""
|
| 290 |
+
save_dir = "util/data"
|
| 291 |
+
os.makedirs(save_dir, exist_ok=True)
|
| 292 |
+
checkpoint_file = os.path.join(save_dir, "recent_matches_checkpoint.csv")
|
| 293 |
+
all_matches_dfs = []
|
| 294 |
+
error_players = []
|
| 295 |
+
|
| 296 |
+
# Load checkpoint if exists
|
| 297 |
+
start_idx = 0
|
| 298 |
+
if os.path.exists(checkpoint_file):
|
| 299 |
+
try:
|
| 300 |
+
checkpoint_df = pd.read_csv(checkpoint_file)
|
| 301 |
+
all_matches_dfs = [checkpoint_df]
|
| 302 |
+
# Get the number of players already processed
|
| 303 |
+
processed_players = set(checkpoint_df['player_id'])
|
| 304 |
+
# Filter out already processed players
|
| 305 |
+
players_df = players_df[~players_df['username'].isin(processed_players)]
|
| 306 |
+
print(f"Loaded checkpoint with {len(processed_players)} players already processed")
|
| 307 |
+
except Exception as e:
|
| 308 |
+
print(f"Error loading checkpoint: {e}")
|
| 309 |
+
|
| 310 |
+
print(f"Processing matches for {len(players_df)} remaining players...")
|
| 311 |
+
|
| 312 |
+
for idx, row in players_df.iterrows():
|
| 313 |
+
region = row['region'].lower() # Ensure region is lowercase
|
| 314 |
+
username = row['username']
|
| 315 |
+
|
| 316 |
+
try:
|
| 317 |
+
# Format the username
|
| 318 |
+
formatted_username = format_summoner_name(username)
|
| 319 |
+
print(f"\nProcessing matches for player {idx + 1}/{len(players_df)}: {username} ({region})")
|
| 320 |
+
#print(f"Formatted username: {formatted_username}")
|
| 321 |
+
|
| 322 |
+
# Add delay between requests
|
| 323 |
+
if idx > 0:
|
| 324 |
+
time.sleep(2)
|
| 325 |
+
|
| 326 |
+
matches_df = get_matches_stats(region, formatted_username)
|
| 327 |
+
|
| 328 |
+
if matches_df is not None and not matches_df.empty:
|
| 329 |
+
# Add player identification columns
|
| 330 |
+
matches_df['player_id'] = username # Original username
|
| 331 |
+
matches_df['region'] = region
|
| 332 |
+
all_matches_dfs.append(matches_df)
|
| 333 |
+
print(f"Successfully processed matches for {username}")
|
| 334 |
+
#print(f"Found {len(matches_df)} matches")
|
| 335 |
+
|
| 336 |
+
# Save checkpoint every 5 players
|
| 337 |
+
if len(all_matches_dfs) % 5 == 0:
|
| 338 |
+
checkpoint_save = pd.concat(all_matches_dfs, ignore_index=True)
|
| 339 |
+
checkpoint_save.to_csv(checkpoint_file, index=False)
|
| 340 |
+
print(f"Saved checkpoint after processing {len(all_matches_dfs)} players")
|
| 341 |
+
|
| 342 |
+
else:
|
| 343 |
+
print(f"No match data found for {username}")
|
| 344 |
+
error_players.append({
|
| 345 |
+
'region': region,
|
| 346 |
+
'username': username,
|
| 347 |
+
'formatted_username': formatted_username,
|
| 348 |
+
'error': 'No match data found'
|
| 349 |
+
})
|
| 350 |
+
|
| 351 |
+
except Exception as e:
|
| 352 |
+
print(f"Error processing matches for {username}: {e}")
|
| 353 |
+
error_players.append({
|
| 354 |
+
'region': region,
|
| 355 |
+
'username': username,
|
| 356 |
+
'formatted_username': formatted_username if 'formatted_username' in locals() else 'Error in formatting',
|
| 357 |
+
'error': str(e)
|
| 358 |
+
})
|
| 359 |
+
continue
|
| 360 |
+
|
| 361 |
+
# Combine all match stats
|
| 362 |
+
if all_matches_dfs:
|
| 363 |
+
final_df = pd.concat(all_matches_dfs, ignore_index=True)
|
| 364 |
+
|
| 365 |
+
filepath = os.path.join(save_dir, f"recent_matches.csv")
|
| 366 |
+
final_df.to_csv(filepath, index=False)
|
| 367 |
+
print(f"\nSaved combined match stats for {len(all_matches_dfs)} players to {filepath}")
|
| 368 |
+
|
| 369 |
+
# Clean up checkpoint file
|
| 370 |
+
if os.path.exists(checkpoint_file):
|
| 371 |
+
os.remove(checkpoint_file)
|
| 372 |
+
print("Removed checkpoint file after successful completion")
|
| 373 |
+
|
| 374 |
+
# Save error log if any errors occurred
|
| 375 |
+
if error_players:
|
| 376 |
+
error_df = pd.DataFrame(error_players)
|
| 377 |
+
error_filepath = os.path.join(save_dir, f"recent_matches_error.csv")
|
| 378 |
+
error_df.to_csv(error_filepath, index=False)
|
| 379 |
+
print(f"Saved error log to {error_filepath}")
|
| 380 |
+
|
| 381 |
+
# Print summary
|
| 382 |
+
print("\nSummary:")
|
| 383 |
+
print(f"Total players processed: {len(players_df)}")
|
| 384 |
+
print(f"Successful: {len(all_matches_dfs)}")
|
| 385 |
+
print(f"Failed: {len(error_players)}")
|
| 386 |
+
print(f"Total matches collected: {len(final_df)}")
|
| 387 |
+
|
| 388 |
+
return final_df
|
| 389 |
+
else:
|
| 390 |
+
print("\nNo match data was collected")
|
| 391 |
+
return None
|
| 392 |
+
|
| 393 |
+
|
util/Weekly_meta_scrapper.py
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import pandas as pd
|
| 3 |
+
from selenium import webdriver
|
| 4 |
+
from selenium.webdriver.chrome.service import Service
|
| 5 |
+
from selenium.webdriver.chrome.options import Options
|
| 6 |
+
from webdriver_manager.chrome import ChromeDriverManager
|
| 7 |
+
from selenium.webdriver.common.by import By
|
| 8 |
+
from selenium.webdriver.support.ui import WebDriverWait
|
| 9 |
+
from selenium.webdriver.support import expected_conditions as EC
|
| 10 |
+
from helper import convert_percentage_to_decimal
|
| 11 |
+
|
| 12 |
+
def setup_driver():
|
| 13 |
+
"""Setup and return a configured Chrome WebDriver with optimized settings"""
|
| 14 |
+
chrome_options = Options()
|
| 15 |
+
chrome_options.add_argument("--headless")
|
| 16 |
+
chrome_options.add_argument("--no-sandbox")
|
| 17 |
+
chrome_options.add_argument("--disable-dev-shm-usage")
|
| 18 |
+
chrome_options.add_argument("--disable-gpu")
|
| 19 |
+
chrome_options.add_argument("--disable-extensions")
|
| 20 |
+
chrome_options.add_argument("--disable-logging")
|
| 21 |
+
chrome_options.add_argument("--log-level=3")
|
| 22 |
+
chrome_options.add_argument("--silent")
|
| 23 |
+
chrome_options.page_load_strategy = 'eager'
|
| 24 |
+
chrome_options.add_argument(
|
| 25 |
+
"user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
|
| 26 |
+
)
|
| 27 |
+
|
| 28 |
+
service = Service(ChromeDriverManager().install())
|
| 29 |
+
return webdriver.Chrome(service=service, options=chrome_options)
|
| 30 |
+
|
| 31 |
+
def get_weekly_meta():
|
| 32 |
+
BASE_URL = "https://www.op.gg/statistics/champions?tier=challenger&period=week&mode=ranked"
|
| 33 |
+
driver = setup_driver()
|
| 34 |
+
|
| 35 |
+
try:
|
| 36 |
+
driver.get(BASE_URL)
|
| 37 |
+
table = WebDriverWait(driver, 20).until(
|
| 38 |
+
EC.presence_of_element_located((By.CSS_SELECTOR, "#content-container > div:nth-child(2) > table"))
|
| 39 |
+
)
|
| 40 |
+
|
| 41 |
+
# Extract table rows
|
| 42 |
+
rows = table.find_elements(By.TAG_NAME, "tr")
|
| 43 |
+
|
| 44 |
+
# Define the column order
|
| 45 |
+
columns = ["rank", "champion", "games", "KDA", "WR", "pick", "ban", "cs", "gold"]
|
| 46 |
+
|
| 47 |
+
data = []
|
| 48 |
+
for row in rows[1:]: # Skip the header row
|
| 49 |
+
cells = row.find_elements(By.TAG_NAME, "td")
|
| 50 |
+
row_data = [cell.text for cell in cells]
|
| 51 |
+
|
| 52 |
+
if len(row_data) >= len(columns):
|
| 53 |
+
# Remove ":1" from KDA format
|
| 54 |
+
row_data[3] = row_data[3].replace(":1", "")
|
| 55 |
+
# Convert WR, pick, and ban percentages to decimals
|
| 56 |
+
row_data[4] = convert_percentage_to_decimal(row_data[4])
|
| 57 |
+
row_data[5] = convert_percentage_to_decimal(row_data[5])
|
| 58 |
+
row_data[6] = convert_percentage_to_decimal(row_data[6])
|
| 59 |
+
# Remove commas from the gold values
|
| 60 |
+
row_data[8] = int(row_data[8].replace(",", ""))
|
| 61 |
+
|
| 62 |
+
data.append(row_data[:len(columns)])
|
| 63 |
+
|
| 64 |
+
# Create a DataFrame with the extracted data
|
| 65 |
+
df = pd.DataFrame(data, columns=columns)
|
| 66 |
+
|
| 67 |
+
# Ensure the directory exists
|
| 68 |
+
os.makedirs('./util/data', exist_ok=True)
|
| 69 |
+
|
| 70 |
+
# Define the save path
|
| 71 |
+
save_path = "./util/data/weekly_meta_stats.csv"
|
| 72 |
+
|
| 73 |
+
# Automatically save the DataFrame to a CSV file in the specified directory
|
| 74 |
+
df.to_csv(save_path, index=False)
|
| 75 |
+
|
| 76 |
+
# Print confirmation message
|
| 77 |
+
print(f"Saved weekly meta to {save_path}")
|
| 78 |
+
|
| 79 |
+
return df
|
| 80 |
+
|
| 81 |
+
except Exception as e:
|
| 82 |
+
print(f"Error: {e}")
|
| 83 |
+
return None
|
| 84 |
+
|
| 85 |
+
finally:
|
| 86 |
+
driver.quit()
|
| 87 |
+
|
| 88 |
+
# if __name__ == "__main__":
|
| 89 |
+
# weekly_meta_data = get_weekly_meta()
|
| 90 |
+
|
| 91 |
+
# if weekly_meta_data is not None:
|
| 92 |
+
# print(weekly_meta_data)
|
util/__pycache__/Leaderboard_scrapper.cpython-312.pyc
ADDED
|
Binary file (7.32 kB). View file
|
|
|
util/__pycache__/Meta_scrapper.cpython-312.pyc
ADDED
|
Binary file (7.58 kB). View file
|
|
|
util/__pycache__/Player_scrapper.cpython-312.pyc
ADDED
|
Binary file (25.7 kB). View file
|
|
|
util/__pycache__/Recent_match_scrapper.cpython-312.pyc
ADDED
|
Binary file (18.1 kB). View file
|
|
|
util/__pycache__/Weekly_meta_scrapper.cpython-312.pyc
ADDED
|
Binary file (4.37 kB). View file
|
|
|
util/__pycache__/connection_check.cpython-312.pyc
ADDED
|
Binary file (1.47 kB). View file
|
|
|
util/__pycache__/feature_eng.cpython-312.pyc
ADDED
|
Binary file (14 kB). View file
|
|
|
util/__pycache__/helper.cpython-312.pyc
ADDED
|
Binary file (46.6 kB). View file
|
|
|
app.py → util/app.py
RENAMED
|
@@ -5,79 +5,124 @@ import requests
|
|
| 5 |
import xgboost as xgb
|
| 6 |
from huggingface_hub import hf_hub_download
|
| 7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
# Download the model from Hugging Face Hub
|
| 9 |
model_path = hf_hub_download(
|
| 10 |
repo_id="ivwhy/champion-predictor-model", # Replace with your model repo
|
| 11 |
filename="champion_predictor.json" # Replace with your model filename
|
|
|
|
| 12 |
)
|
| 13 |
model = xgb.Booster()
|
| 14 |
model.load_model(model_path)
|
| 15 |
|
| 16 |
-
# Rest of your code remains the same as before, but remove demo.launch()
|
| 17 |
# Define your interface
|
| 18 |
with gr.Blocks() as demo:
|
| 19 |
# Assuming you have these helper functions implemented
|
| 20 |
-
def
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
return {
|
| 24 |
-
'wins': 120,
|
| 25 |
-
'losses': 80,
|
| 26 |
-
'winrate': '60%',
|
| 27 |
-
'favorite_champions': ['Ahri', 'Zed', 'Yasuo']
|
| 28 |
-
}
|
| 29 |
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
# Placeholder - implement actual API call
|
| 33 |
-
return pd.DataFrame({
|
| 34 |
-
'champion': ['Ahri', 'Zed', 'Yasuo'],
|
| 35 |
-
'result': ['Win', 'Loss', 'Win'],
|
| 36 |
-
'kda': ['8/2/10', '4/5/3', '12/3/7']
|
| 37 |
-
})
|
| 38 |
|
| 39 |
-
def prepare_features(player_name, champions):
|
| 40 |
-
"""Prepare features for model prediction"""
|
| 41 |
-
# Placeholder - implement actual feature engineering
|
| 42 |
-
features = [] # Transform champions into model features
|
| 43 |
-
return pd.DataFrame([features])
|
| 44 |
|
| 45 |
# Load the model from Hugging Face
|
| 46 |
model = xgb.Booster() # Initialize model
|
| 47 |
-
|
| 48 |
|
| 49 |
-
|
| 50 |
CHAMPIONS = [
|
| 51 |
-
"Aatrox", "Ahri", "Akali", "Alistar", "Amumu",
|
| 52 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
]
|
| 54 |
|
| 55 |
-
|
|
|
|
| 56 |
"""Display player statistics and recent matches"""
|
| 57 |
-
if not
|
| 58 |
-
return "Please enter a player
|
| 59 |
-
|
| 60 |
-
stats = get_player_stats(player_name)
|
| 61 |
-
recent = get_recent_matches(player_name)
|
| 62 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
stats_html = f"""
|
| 64 |
<div style='padding: 20px; background: #f5f5f5; border-radius: 10px;'>
|
| 65 |
-
<h3>Player Stats: {
|
| 66 |
<p>Wins: {stats['wins']} | Losses: {stats['losses']}</p>
|
| 67 |
<p>Winrate: {stats['winrate']}</p>
|
| 68 |
<p>Favorite Champions: {', '.join(stats['favorite_champions'])}</p>
|
| 69 |
</div>
|
| 70 |
"""
|
| 71 |
|
| 72 |
-
return stats_html
|
| 73 |
|
| 74 |
-
def predict_champion(
|
| 75 |
"""Make prediction based on selected champions"""
|
| 76 |
-
if not
|
| 77 |
return "Please fill in all fields"
|
| 78 |
|
| 79 |
# Prepare features
|
| 80 |
-
features =
|
| 81 |
|
| 82 |
# Make prediction
|
| 83 |
prediction = model.predict(features)
|
|
@@ -92,7 +137,7 @@ with gr.Blocks() as demo:
|
|
| 92 |
gr.Markdown("# League of Legends Champion Prediction")
|
| 93 |
|
| 94 |
with gr.Row():
|
| 95 |
-
|
| 96 |
show_button = gr.Button("Show Stats")
|
| 97 |
|
| 98 |
with gr.Row():
|
|
@@ -112,15 +157,49 @@ with gr.Blocks() as demo:
|
|
| 112 |
# Set up event handlers
|
| 113 |
show_button.click(
|
| 114 |
fn=show_stats,
|
| 115 |
-
inputs=[
|
| 116 |
outputs=[stats_output, recent_matches]
|
| 117 |
)
|
| 118 |
|
| 119 |
predict_button.click(
|
| 120 |
fn=predict_champion,
|
| 121 |
-
inputs=[
|
| 122 |
outputs=prediction_output
|
| 123 |
)
|
| 124 |
|
| 125 |
# Add this line at the end
|
| 126 |
-
demo.queue() # Enable queuing for better handling of multiple users
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
import xgboost as xgb
|
| 6 |
from huggingface_hub import hf_hub_download
|
| 7 |
|
| 8 |
+
from Recent_match_scrapper import get_multiple_matches_stats
|
| 9 |
+
from Meta_scrapper import get_meta_stats
|
| 10 |
+
from Leaderboard_scrapper import scrape_leaderboards
|
| 11 |
+
from connection_check import check_connection
|
| 12 |
+
from helper import merge_stats, filter_leaderboard, get_player_list
|
| 13 |
+
from Player_scrapper import get_multiple_player_stats, get_player_stats
|
| 14 |
+
from feature_eng import create_champion_features
|
| 15 |
+
from Weekly_meta_scrapper import get_weekly_meta
|
| 16 |
+
from app_training_df_getter import create_app_user_training_df
|
| 17 |
+
from sklearn.metrics import top_k_accuracy_score
|
| 18 |
+
|
| 19 |
+
import os
|
| 20 |
+
import time
|
| 21 |
+
from selenium import webdriver
|
| 22 |
+
from selenium.webdriver.chrome.service import Service
|
| 23 |
+
from selenium.webdriver.chrome.options import Options
|
| 24 |
+
from webdriver_manager.chrome import ChromeDriverManager
|
| 25 |
+
from selenium.webdriver.common.by import By
|
| 26 |
+
from selenium.webdriver.support.ui import WebDriverWait
|
| 27 |
+
from selenium.webdriver.support import expected_conditions as EC
|
| 28 |
+
import pandas as pd
|
| 29 |
+
from helper import format_summoner_name
|
| 30 |
+
|
| 31 |
# Download the model from Hugging Face Hub
|
| 32 |
model_path = hf_hub_download(
|
| 33 |
repo_id="ivwhy/champion-predictor-model", # Replace with your model repo
|
| 34 |
filename="champion_predictor.json" # Replace with your model filename
|
| 35 |
+
|
| 36 |
)
|
| 37 |
model = xgb.Booster()
|
| 38 |
model.load_model(model_path)
|
| 39 |
|
|
|
|
| 40 |
# Define your interface
|
| 41 |
with gr.Blocks() as demo:
|
| 42 |
# Assuming you have these helper functions implemented
|
| 43 |
+
def get_user_training_df(player_opgg_url):
|
| 44 |
+
|
| 45 |
+
training_df = create_app_user_training_df(player_opgg_url)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
|
| 47 |
+
return training_df
|
| 48 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
|
| 51 |
# Load the model from Hugging Face
|
| 52 |
model = xgb.Booster() # Initialize model
|
| 53 |
+
model.load_model("ivwhy/champion-predictor-model") # Load your model
|
| 54 |
|
| 55 |
+
# Define champion list for dropdowns
|
| 56 |
CHAMPIONS = [
|
| 57 |
+
"Aatrox", "Ahri", "Akali", "Akshan", "Alistar", "Amumu", "Anivia", "Annie", "Aphelios", "Ashe",
|
| 58 |
+
"Aurelion Sol", "Azir", "Bard", "Bel'Veth", "Blitzcrank", "Brand", "Braum", "Caitlyn", "Camille",
|
| 59 |
+
"Cassiopeia", "Cho'Gath", "Corki", "Darius", "Diana", "Dr. Mundo", "Draven", "Ekko", "Elise",
|
| 60 |
+
"Evelynn", "Ezreal", "Fiddlesticks", "Fiora", "Fizz", "Galio", "Gangplank", "Garen", "Gnar",
|
| 61 |
+
"Gragas", "Graves", "Gwen", "Hecarim", "Heimerdinger", "Illaoi", "Irelia", "Ivern", "Janna",
|
| 62 |
+
"Jarvan IV", "Jax", "Jayce", "Jhin", "Jinx", "Kai'Sa", "Kalista", "Karma", "Karthus", "Kassadin",
|
| 63 |
+
"Katarina", "Kayle", "Kayn", "Kennen", "Kha'Zix", "Kindred", "Kled", "Kog'Maw", "KSante", "LeBlanc",
|
| 64 |
+
"Lee Sin", "Leona", "Lillia", "Lissandra", "Lucian", "Lulu", "Lux", "Malphite", "Malzahar", "Maokai",
|
| 65 |
+
"Master Yi", "Milio", "Miss Fortune", "Mordekaiser", "Morgana", "Naafiri", "Nami", "Nasus", "Nautilus",
|
| 66 |
+
"Neeko", "Nidalee", "Nilah", "Nocturne", "Nunu & Willump", "Olaf", "Orianna", "Ornn", "Pantheon",
|
| 67 |
+
"Poppy", "Pyke", "Qiyana", "Quinn", "Rakan", "Rammus", "Rek'Sai", "Rell", "Renata Glasc", "Renekton",
|
| 68 |
+
"Rengar", "Riven", "Rumble", "Ryze", "Samira", "Sejuani", "Senna", "Seraphine", "Sett", "Shaco",
|
| 69 |
+
"Shen", "Shyvana", "Singed", "Sion", "Sivir", "Skarner", "Sona", "Soraka", "Swain", "Sylas",
|
| 70 |
+
"Syndra", "Tahm Kench", "Taliyah", "Talon", "Taric", "Teemo", "Thresh", "Tristana", "Trundle",
|
| 71 |
+
"Tryndamere", "Twisted Fate", "Twitch", "Udyr", "Urgot", "Varus", "Vayne", "Veigar", "Vel'Koz",
|
| 72 |
+
"Vex", "Vi", "Viego", "Viktor", "Vladimir", "Volibear", "Warwick", "Wukong", "Xayah", "Xerath",
|
| 73 |
+
"Xin Zhao", "Yasuo", "Yone", "Yorick", "Yuumi", "Zac", "Zed", "Zeri", "Ziggs", "Zilean", "Zoe", "Zyra"
|
| 74 |
]
|
| 75 |
|
| 76 |
+
|
| 77 |
+
def show_stats(player_opgg_url):
|
| 78 |
"""Display player statistics and recent matches"""
|
| 79 |
+
if not player_opgg_url:
|
| 80 |
+
return "Please enter a player link to OPGG", None
|
|
|
|
|
|
|
|
|
|
| 81 |
|
| 82 |
+
training_features = get_user_training_df(player_opgg_url)
|
| 83 |
+
|
| 84 |
+
# Assume `training_features` is the DataFrame provided
|
| 85 |
+
# Calculate total wins and losses
|
| 86 |
+
wins = training_features['result'].sum()
|
| 87 |
+
losses = len(training_features) - wins
|
| 88 |
+
|
| 89 |
+
# Calculate winrate
|
| 90 |
+
winrate = f"{(wins / len(training_features)) * 100:.0f}%"
|
| 91 |
+
|
| 92 |
+
# Calculate favorite champions
|
| 93 |
+
favorite_champions = (
|
| 94 |
+
training_features['champion']
|
| 95 |
+
.value_counts()
|
| 96 |
+
.head(3)
|
| 97 |
+
.index.tolist()
|
| 98 |
+
)
|
| 99 |
+
|
| 100 |
+
# Create the summary dictionary
|
| 101 |
+
summary_data = {
|
| 102 |
+
'wins': wins,
|
| 103 |
+
'losses': losses,
|
| 104 |
+
'winrate': winrate,
|
| 105 |
+
'favorite_champions': favorite_champions
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
stats_html = f"""
|
| 109 |
<div style='padding: 20px; background: #f5f5f5; border-radius: 10px;'>
|
| 110 |
+
<h3>Player Stats: {player_opgg_url}</h3>
|
| 111 |
<p>Wins: {stats['wins']} | Losses: {stats['losses']}</p>
|
| 112 |
<p>Winrate: {stats['winrate']}</p>
|
| 113 |
<p>Favorite Champions: {', '.join(stats['favorite_champions'])}</p>
|
| 114 |
</div>
|
| 115 |
"""
|
| 116 |
|
| 117 |
+
return stats_html
|
| 118 |
|
| 119 |
+
def predict_champion(player_opgg_url, *champions):
|
| 120 |
"""Make prediction based on selected champions"""
|
| 121 |
+
if not player_opgg_url or None in champions:
|
| 122 |
return "Please fill in all fields"
|
| 123 |
|
| 124 |
# Prepare features
|
| 125 |
+
features = get_user_training_df(player_opgg_url, champions)
|
| 126 |
|
| 127 |
# Make prediction
|
| 128 |
prediction = model.predict(features)
|
|
|
|
| 137 |
gr.Markdown("# League of Legends Champion Prediction")
|
| 138 |
|
| 139 |
with gr.Row():
|
| 140 |
+
player_opgg_url = gr.Textbox(label="OPGG Player URL")
|
| 141 |
show_button = gr.Button("Show Stats")
|
| 142 |
|
| 143 |
with gr.Row():
|
|
|
|
| 157 |
# Set up event handlers
|
| 158 |
show_button.click(
|
| 159 |
fn=show_stats,
|
| 160 |
+
inputs=[player_opgg_url],
|
| 161 |
outputs=[stats_output, recent_matches]
|
| 162 |
)
|
| 163 |
|
| 164 |
predict_button.click(
|
| 165 |
fn=predict_champion,
|
| 166 |
+
inputs=[player_opgg_url] + champion_dropdowns,
|
| 167 |
outputs=prediction_output
|
| 168 |
)
|
| 169 |
|
| 170 |
# Add this line at the end
|
| 171 |
+
demo.queue() # Enable queuing for better handling of multiple users
|
| 172 |
+
|
| 173 |
+
|
| 174 |
+
|
| 175 |
+
|
| 176 |
+
''' code graveyard
|
| 177 |
+
|
| 178 |
+
def get_player_stats(player_opgg_url):
|
| 179 |
+
"""Get player statistics from API"""
|
| 180 |
+
# Placeholder - implement actual API call
|
| 181 |
+
|
| 182 |
+
return {
|
| 183 |
+
'wins': 120,
|
| 184 |
+
'losses': 80,
|
| 185 |
+
'winrate': '60%',
|
| 186 |
+
'favorite_champions': ['Ahri', 'Zed', 'Yasuo']
|
| 187 |
+
}
|
| 188 |
+
|
| 189 |
+
def get_recent_matches(player_opgg_url):
|
| 190 |
+
"""Get recent match history"""
|
| 191 |
+
# Placeholder - implement actual API call
|
| 192 |
+
return pd.DataFrame({
|
| 193 |
+
'champion': ['Ahri', 'Zed', 'Yasuo'],
|
| 194 |
+
'result': ['Win', 'Loss', 'Win'],
|
| 195 |
+
'kda': ['8/2/10', '4/5/3', '12/3/7']
|
| 196 |
+
})
|
| 197 |
+
|
| 198 |
+
def prepare_features(player_opgg_url, champions):
|
| 199 |
+
"""Prepare features for model prediction"""
|
| 200 |
+
# Placeholder - implement actual feature engineering
|
| 201 |
+
features = [] # Transform champions into model features
|
| 202 |
+
return pd.DataFrame([features])
|
| 203 |
+
|
| 204 |
+
|
| 205 |
+
'''
|
util/app_training_df_getter.py
ADDED
|
@@ -0,0 +1,388 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from Recent_match_scrapper import get_multiple_matches_stats, get_matches_stats
|
| 2 |
+
import os
|
| 3 |
+
import pandas as pd
|
| 4 |
+
import numpy as np
|
| 5 |
+
from Meta_scrapper import get_meta_stats
|
| 6 |
+
from Leaderboard_scrapper import scrape_leaderboards
|
| 7 |
+
from connection_check import check_connection
|
| 8 |
+
from helper import merge_stats, filter_leaderboard, get_player_list, process_kda_perfect, ChampionConverter
|
| 9 |
+
from Player_scrapper import get_multiple_player_stats, get_player_stats
|
| 10 |
+
from feature_eng import create_champion_features
|
| 11 |
+
from Weekly_meta_scrapper import get_weekly_meta
|
| 12 |
+
import pandas as pd
|
| 13 |
+
import re
|
| 14 |
+
|
| 15 |
+
# ============================================ my functions =========================================================
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def create_champion_features_and_return_df(merged_player_stats=None, meta_stats=None, weekly_meta=None, debug=None, consider_team_comp=True, test_mode=False):
|
| 19 |
+
"""
|
| 20 |
+
Create features for champion prediction using player data.
|
| 21 |
+
Champion names will be used as column headers.
|
| 22 |
+
Uses pd.concat to avoid DataFrame fragmentation.
|
| 23 |
+
"""
|
| 24 |
+
try:
|
| 25 |
+
if merged_player_stats is None:
|
| 26 |
+
print("Loading merged player stats...")
|
| 27 |
+
input_file = os.path.join("util", "data", "player_stats_merged.csv")
|
| 28 |
+
merged_player_stats = pd.read_csv(input_file, low_memory=False)
|
| 29 |
+
|
| 30 |
+
#processing kda value
|
| 31 |
+
merged_player_stats = process_kda_perfect(merged_player_stats)
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
if test_mode:
|
| 35 |
+
print("Test mode: Using only first 100 rows")
|
| 36 |
+
merged_player_stats = merged_player_stats.head(100)
|
| 37 |
+
|
| 38 |
+
if meta_stats is None:
|
| 39 |
+
print("Loading meta stats...")
|
| 40 |
+
meta_file = os.path.join("util", "data", "meta_stats.csv")
|
| 41 |
+
meta_stats = pd.read_csv(meta_file, low_memory=False)
|
| 42 |
+
|
| 43 |
+
if weekly_meta is None:
|
| 44 |
+
print("Loading weekly meta stats...")
|
| 45 |
+
weekly_file = os.path.join("util", "data", "weekly_meta_stats.csv")
|
| 46 |
+
weekly_meta = pd.read_csv(weekly_file, low_memory=False)
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
# Initialize variables
|
| 50 |
+
debug_data = []
|
| 51 |
+
original_columns = merged_player_stats.columns.tolist()
|
| 52 |
+
feature_dict = {}
|
| 53 |
+
|
| 54 |
+
# Copy original columns
|
| 55 |
+
for col in merged_player_stats.columns:
|
| 56 |
+
feature_dict[col] = merged_player_stats[col].values.copy()
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
# Initialize the champion converter
|
| 60 |
+
converter = ChampionConverter()
|
| 61 |
+
all_champions = converter.champions
|
| 62 |
+
#total_champions = len(converter.champions)
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
# Get low tier champions and counter information
|
| 67 |
+
tier_penalties = {3: 0.9, 4: 0.85, 5: 0.8}
|
| 68 |
+
|
| 69 |
+
# Create tier_map as a dictionary of lists
|
| 70 |
+
tier_map = {}
|
| 71 |
+
for _, row in meta_stats.iterrows():
|
| 72 |
+
champ = row['champion']
|
| 73 |
+
tier = row['tier']
|
| 74 |
+
if pd.notna(tier):
|
| 75 |
+
if champ in tier_map:
|
| 76 |
+
tier_map[champ].append(tier)
|
| 77 |
+
else:
|
| 78 |
+
tier_map[champ] = [tier]
|
| 79 |
+
|
| 80 |
+
counter_map = {}
|
| 81 |
+
for _, row in meta_stats.iterrows():
|
| 82 |
+
if pd.notna(row['counter1']):
|
| 83 |
+
champ = row['champion']
|
| 84 |
+
counters = [row['counter1'], row['counter2'], row['counter3']]
|
| 85 |
+
if champ in counter_map:
|
| 86 |
+
counter_map[champ].extend([c for c in counters if pd.notna(c)])
|
| 87 |
+
else:
|
| 88 |
+
counter_map[champ] = [c for c in counters if pd.notna(c)]
|
| 89 |
+
|
| 90 |
+
# Ensure unique counters and remove duplicates
|
| 91 |
+
for champ, counters in counter_map.items():
|
| 92 |
+
counter_map[champ] = list(set(counters))
|
| 93 |
+
|
| 94 |
+
# Move 'champion' column to the first position
|
| 95 |
+
cols = ['champion'] + [col for col in merged_player_stats if col != 'champion']
|
| 96 |
+
merged_player_stats = merged_player_stats[cols]
|
| 97 |
+
|
| 98 |
+
# Define importance weights
|
| 99 |
+
weights = {
|
| 100 |
+
'recent': 0.3, # Last 20 games
|
| 101 |
+
'weekly': 0.4, # Last 7 days
|
| 102 |
+
'meta': 0.2, # Only from weekly_stats
|
| 103 |
+
'season': 0.06, # Current season
|
| 104 |
+
'mastery': 0.04 # All-time mastery
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
# Process rows in batches
|
| 108 |
+
batch_size = 100
|
| 109 |
+
total_rows = len(merged_player_stats)
|
| 110 |
+
|
| 111 |
+
print(f"Total rows: {total_rows}")
|
| 112 |
+
|
| 113 |
+
for batch_start in range(0, total_rows, batch_size):
|
| 114 |
+
batch_end = min(batch_start + batch_size, total_rows)
|
| 115 |
+
batch_rows = merged_player_stats.iloc[batch_start:batch_end]
|
| 116 |
+
print(f"\nProcessing rows {batch_start} to {batch_end} ({batch_start/total_rows*100:.2f}% complete)")
|
| 117 |
+
|
| 118 |
+
# Initialize batch scores dictionary
|
| 119 |
+
batch_scores = {champion: np.zeros(len(batch_rows)) for champion in all_champions}
|
| 120 |
+
|
| 121 |
+
# Process each row in this batch
|
| 122 |
+
for batch_idx, (idx, row) in enumerate(batch_rows.iterrows()):
|
| 123 |
+
# Process each champion for this row
|
| 124 |
+
for champion in all_champions:
|
| 125 |
+
# Initialize scores for this champion and row
|
| 126 |
+
champion_scores = {
|
| 127 |
+
'recent_score': 0,
|
| 128 |
+
'weekly_score': 0,
|
| 129 |
+
'meta_score': 0,
|
| 130 |
+
'season_score': 0,
|
| 131 |
+
'mastery_score': 0
|
| 132 |
+
}
|
| 133 |
+
|
| 134 |
+
# Store debug info if needed
|
| 135 |
+
base_score_before_penalty = 0
|
| 136 |
+
counter_penalty = 0
|
| 137 |
+
counter_debug = []
|
| 138 |
+
|
| 139 |
+
# 1. Recent Performance
|
| 140 |
+
for i in range(1, 4):
|
| 141 |
+
if row.get(f'most_champ_{i}') == champion:
|
| 142 |
+
wr = float(row[f'WR_{i}']) if pd.notna(row[f'WR_{i}']) else 0
|
| 143 |
+
kda = float(row[f'KDA_{i}']) if pd.notna(row[f'KDA_{i}']) else 0
|
| 144 |
+
wins = float(row[f'W_{i}']) if pd.notna(row[f'W_{i}']) else 0
|
| 145 |
+
losses = float(row[f'L_{i}']) if pd.notna(row[f'L_{i}']) else 0
|
| 146 |
+
games = wins + losses
|
| 147 |
+
total_games = float(row['total_games']) if pd.notna(row['total_games']) else 20
|
| 148 |
+
|
| 149 |
+
performance_quality = (
|
| 150 |
+
(wr * 0.7) +
|
| 151 |
+
(min(kda, 10) / 10 * 0.3)
|
| 152 |
+
)
|
| 153 |
+
|
| 154 |
+
games_factor = min(games / 5, 1.0)
|
| 155 |
+
games_ratio = games / total_games
|
| 156 |
+
|
| 157 |
+
if games >= 5:
|
| 158 |
+
if performance_quality < 0.4:
|
| 159 |
+
performance_quality *= 0.8
|
| 160 |
+
elif performance_quality > 0.7:
|
| 161 |
+
performance_quality *= 1.2
|
| 162 |
+
|
| 163 |
+
champion_scores['recent_score'] = (
|
| 164 |
+
performance_quality * (0.7 + (0.3 * games_factor))
|
| 165 |
+
) * (1 + games_ratio * 0.2)
|
| 166 |
+
break # Exit loop once found
|
| 167 |
+
|
| 168 |
+
# 2. Weekly Performance
|
| 169 |
+
for i in range(1, 4):
|
| 170 |
+
if row.get(f'7d_champ_{i}') == champion:
|
| 171 |
+
weekly_wins = float(row[f'7d_W_{i}']) if pd.notna(row[f'7d_W_{i}']) else 0
|
| 172 |
+
weekly_losses = float(row[f'7d_L_{i}']) if pd.notna(row[f'7d_L_{i}']) else 0
|
| 173 |
+
weekly_games = float(row[f'7d_total_{i}']) if pd.notna(row[f'7d_total_{i}']) else 0
|
| 174 |
+
weekly_wr = float(row[f'7d_WR_{i}']) if pd.notna(row[f'7d_WR_{i}']) else 0
|
| 175 |
+
profile_wr = float(row['win_rate']) if pd.notna(row['win_rate']) else 0.5
|
| 176 |
+
|
| 177 |
+
if weekly_games > 0:
|
| 178 |
+
wr_trend = (weekly_wr - profile_wr) / profile_wr if profile_wr > 0 else 0
|
| 179 |
+
weekly_intensity = min(weekly_games / 10, 1.0)
|
| 180 |
+
win_ratio = weekly_wins / weekly_games if weekly_games > 0 else 0
|
| 181 |
+
|
| 182 |
+
weekly_performance = (
|
| 183 |
+
(weekly_wr * 0.4) +
|
| 184 |
+
(max(min(wr_trend, 1), -1) * 0.2) +
|
| 185 |
+
(weekly_intensity * 0.2) +
|
| 186 |
+
(win_ratio * 0.2)
|
| 187 |
+
)
|
| 188 |
+
|
| 189 |
+
if weekly_games >= 5:
|
| 190 |
+
if weekly_performance < 0.4:
|
| 191 |
+
weekly_performance *= 0.8
|
| 192 |
+
elif weekly_performance > 0.7:
|
| 193 |
+
weekly_performance *= 1.2
|
| 194 |
+
|
| 195 |
+
champion_scores['weekly_score'] = weekly_performance * (
|
| 196 |
+
0.7 + (0.3 * min(weekly_games / 5, 1.0))
|
| 197 |
+
)
|
| 198 |
+
break # Exit loop once found
|
| 199 |
+
|
| 200 |
+
# 3. Meta Score
|
| 201 |
+
if champion in weekly_meta['champion'].values:
|
| 202 |
+
weekly_row = weekly_meta[weekly_meta['champion'] == champion].iloc[0]
|
| 203 |
+
rank = weekly_row['rank']
|
| 204 |
+
games = weekly_row['games']
|
| 205 |
+
pick_rate = weekly_row['pick']
|
| 206 |
+
ban_rate = weekly_row['ban']
|
| 207 |
+
|
| 208 |
+
weight = (
|
| 209 |
+
1 / rank * 0.5 +
|
| 210 |
+
games / 100 * 0.3 +
|
| 211 |
+
pick_rate * 0.1 -
|
| 212 |
+
ban_rate * 0.1
|
| 213 |
+
)
|
| 214 |
+
|
| 215 |
+
champion_scores['meta_score'] = weight
|
| 216 |
+
|
| 217 |
+
# 4. Season Performance
|
| 218 |
+
for i in range(1, 8):
|
| 219 |
+
if row.get(f'season_champ_{i}') == champion:
|
| 220 |
+
wr = float(row[f'wr_ssn_{i}']) if pd.notna(row[f'wr_ssn_{i}']) else 0
|
| 221 |
+
games = float(row[f'games_ssn_{i}']) if pd.notna(row[f'games_ssn_{i}']) else 0
|
| 222 |
+
kda = float(row[f'kda_ssn_{i}']) if pd.notna(row[f'kda_ssn_{i}']) else 0
|
| 223 |
+
|
| 224 |
+
champion_scores['season_score'] = (
|
| 225 |
+
wr * 0.7 +
|
| 226 |
+
(kda / 10) * 0.3
|
| 227 |
+
) * (games / 100)
|
| 228 |
+
break # Exit loop once found
|
| 229 |
+
|
| 230 |
+
# 5. Mastery Score
|
| 231 |
+
for i in range(1, 17):
|
| 232 |
+
if row.get(f'mastery_champ_{i}') == champion:
|
| 233 |
+
mastery = float(row[f'm_lv_{i}']) if pd.notna(row[f'm_lv_{i}']) else 0
|
| 234 |
+
champion_scores['mastery_score'] = mastery / 7
|
| 235 |
+
break # Exit loop once found
|
| 236 |
+
|
| 237 |
+
# Calculate base score for this champion and row
|
| 238 |
+
base_score = (
|
| 239 |
+
champion_scores['recent_score'] * weights['recent'] +
|
| 240 |
+
champion_scores['weekly_score'] * weights['weekly'] +
|
| 241 |
+
champion_scores['meta_score'] * weights['meta'] +
|
| 242 |
+
champion_scores['season_score'] * weights['season'] +
|
| 243 |
+
champion_scores['mastery_score'] * weights['mastery']
|
| 244 |
+
)
|
| 245 |
+
|
| 246 |
+
|
| 247 |
+
# Store the pre-penalty score for debugging
|
| 248 |
+
base_score_before_penalty = base_score
|
| 249 |
+
|
| 250 |
+
# Apply tier penalties
|
| 251 |
+
if champion in tier_map:
|
| 252 |
+
highest_tier = min(tier_map[champion])
|
| 253 |
+
if highest_tier in tier_penalties:
|
| 254 |
+
base_score *= tier_penalties[highest_tier]
|
| 255 |
+
|
| 256 |
+
# Process team composition and counter penalties
|
| 257 |
+
if consider_team_comp:
|
| 258 |
+
# Check team champions
|
| 259 |
+
for i in range(1, 5):
|
| 260 |
+
team_col = f'team_champ{i}'
|
| 261 |
+
if team_col in row and pd.notna(row[team_col]):
|
| 262 |
+
if row[team_col] == champion:
|
| 263 |
+
base_score = 0
|
| 264 |
+
break
|
| 265 |
+
|
| 266 |
+
# Only check opponents if base_score isn't already 0
|
| 267 |
+
if base_score != 0:
|
| 268 |
+
counter_penalty = 0
|
| 269 |
+
counter_debug = [] # For debug information
|
| 270 |
+
|
| 271 |
+
for i in range(1, 6):
|
| 272 |
+
opp_col = f'opp_champ{i}'
|
| 273 |
+
if opp_col in row and pd.notna(row[opp_col]):
|
| 274 |
+
opp_champ = row[opp_col]
|
| 275 |
+
if opp_champ == champion:
|
| 276 |
+
base_score = 0
|
| 277 |
+
break
|
| 278 |
+
if champion in counter_map and opp_champ in counter_map[champion]:
|
| 279 |
+
counter_penalty += 0.1
|
| 280 |
+
counter_debug.append(opp_champ)
|
| 281 |
+
|
| 282 |
+
if counter_penalty > 0:
|
| 283 |
+
base_score = base_score * (1 - counter_penalty)
|
| 284 |
+
|
| 285 |
+
# Store the final score for this champion and row
|
| 286 |
+
batch_scores[champion][batch_idx] = max(base_score, 0)
|
| 287 |
+
|
| 288 |
+
# Collect debug data if this is the debug champion
|
| 289 |
+
if debug == champion:
|
| 290 |
+
counter_list = []
|
| 291 |
+
for i in range(1, 6):
|
| 292 |
+
opp_col = f'opp_champ{i}'
|
| 293 |
+
if opp_col in row and pd.notna(row[opp_col]):
|
| 294 |
+
if champion in counter_map and row[opp_col] in counter_map[champion]:
|
| 295 |
+
counter_list.append(row[opp_col])
|
| 296 |
+
|
| 297 |
+
debug_row = {
|
| 298 |
+
'champion': row['champion'],
|
| 299 |
+
'recent_score': champion_scores['recent_score'],
|
| 300 |
+
'weekly_score': champion_scores['weekly_score'],
|
| 301 |
+
'meta_score': champion_scores['meta_score'],
|
| 302 |
+
'base_score': base_score_before_penalty,
|
| 303 |
+
'final_score': base_score,
|
| 304 |
+
'counter_penalty': counter_penalty if consider_team_comp else 0,
|
| 305 |
+
'final_score_actual': feature_dict[row['champion']][idx] if row['champion'] in feature_dict else base_score,
|
| 306 |
+
'counter_list_debug': counter_list
|
| 307 |
+
}
|
| 308 |
+
debug_data.append(debug_row)
|
| 309 |
+
|
| 310 |
+
# Update feature_dict with batch results
|
| 311 |
+
for champion in batch_scores:
|
| 312 |
+
if champion not in feature_dict:
|
| 313 |
+
feature_dict[champion] = np.zeros(total_rows)
|
| 314 |
+
feature_dict[champion][batch_start:batch_end] = batch_scores[champion]
|
| 315 |
+
|
| 316 |
+
# Save after each batch with timestamp
|
| 317 |
+
temp_df = pd.DataFrame({
|
| 318 |
+
**{col: feature_dict[col] for col in original_columns}, # Original columns first
|
| 319 |
+
**{champion: feature_dict[champion] for champion in all_champions} # Then champion columns
|
| 320 |
+
})
|
| 321 |
+
|
| 322 |
+
batch_save_file = os.path.join("util", "data", f"feature_eng_stats.csv")
|
| 323 |
+
temp_df.to_csv(batch_save_file, index=False)
|
| 324 |
+
print(f"Saved batch progress to {batch_save_file}")
|
| 325 |
+
|
| 326 |
+
if debug:
|
| 327 |
+
print(f"{debug} is countered by: {counter_map[debug]}")
|
| 328 |
+
|
| 329 |
+
# Process debug data if any
|
| 330 |
+
if debug:
|
| 331 |
+
debug_df = pd.DataFrame(debug_data)
|
| 332 |
+
print("\nDebug Data:")
|
| 333 |
+
print(debug_df)
|
| 334 |
+
|
| 335 |
+
# Create final DataFrame
|
| 336 |
+
champion_features = pd.DataFrame(feature_dict)
|
| 337 |
+
|
| 338 |
+
# Create the final DataFrame by combining original data with new features
|
| 339 |
+
features = pd.concat([
|
| 340 |
+
merged_player_stats[original_columns], # Keep all original columns
|
| 341 |
+
champion_features[[col for col in champion_features.columns if col not in original_columns]] # Only new champion columns
|
| 342 |
+
], axis=1)
|
| 343 |
+
|
| 344 |
+
# Move the champion column to be the first column
|
| 345 |
+
if 'champion' in features.columns:
|
| 346 |
+
columns = ['champion'] + [col for col in features.columns if col != 'champion']
|
| 347 |
+
features = features[columns]
|
| 348 |
+
|
| 349 |
+
# Print confirmation message
|
| 350 |
+
print(f"Saved features in data frame.")
|
| 351 |
+
|
| 352 |
+
return features
|
| 353 |
+
|
| 354 |
+
except Exception as e:
|
| 355 |
+
print(f"\nError occurred: {str(e)}")
|
| 356 |
+
return None
|
| 357 |
+
|
| 358 |
+
def create_app_user_training_df(url):
|
| 359 |
+
|
| 360 |
+
# EXAMPLE OF INPUT: url = "https://www.op.gg/summoners/euw/Agurin-EUW?queue_type=SOLORANKED"
|
| 361 |
+
|
| 362 |
+
match = re.search(r"/summoners/(\w+)/([\w\-]+)\?", url)
|
| 363 |
+
if match:
|
| 364 |
+
region = match.group(1)
|
| 365 |
+
username = match.group(2)
|
| 366 |
+
print(f"Region: {region}, Username: {username}")
|
| 367 |
+
|
| 368 |
+
|
| 369 |
+
recent_stats = get_matches_stats(region, username)
|
| 370 |
+
# Replace " #" with "-" in the player_id column
|
| 371 |
+
recent_stats['player_id'] = recent_stats['player_id'].str.replace(" #", "-", regex=False)
|
| 372 |
+
|
| 373 |
+
player_stats = get_player_stats(region, username)
|
| 374 |
+
|
| 375 |
+
merged_stats = merge_stats(recent_stats, player_stats)
|
| 376 |
+
print("merged stats:\n")
|
| 377 |
+
print(merge_stats)
|
| 378 |
+
|
| 379 |
+
#save to feature_eng_stats.csv
|
| 380 |
+
training_features = create_champion_features_and_return_df(merged_player_stats=merged_stats, debug=None, consider_team_comp=True, test_mode=False)
|
| 381 |
+
return training_features
|
| 382 |
+
|
| 383 |
+
# ========================================= end of my functions =====================================================
|
| 384 |
+
|
| 385 |
+
# meta_stats = get_meta_stats()
|
| 386 |
+
# print(meta_stats)
|
| 387 |
+
|
| 388 |
+
|
util/connection_check.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import csv
|
| 2 |
+
import time
|
| 3 |
+
import requests
|
| 4 |
+
from urllib.parse import quote
|
| 5 |
+
|
| 6 |
+
# Input file path
|
| 7 |
+
input_file = "util/data/lb_filtered.csv"
|
| 8 |
+
|
| 9 |
+
# List to store failed summoner names
|
| 10 |
+
failed_summoners = []
|
| 11 |
+
|
| 12 |
+
# Function to check if the URL is accessible
|
| 13 |
+
def check_connection(region, summoner):
|
| 14 |
+
# Format the summoner name: Replace spaces with '-' and '#' with '-'
|
| 15 |
+
formatted_summoner = summoner.replace(" ", "-").replace("#", "-")
|
| 16 |
+
|
| 17 |
+
# Encode the summoner name to handle special characters like Korean or other symbols
|
| 18 |
+
formatted_summoner = quote(formatted_summoner)
|
| 19 |
+
|
| 20 |
+
# Construct the full URL: region is correctly placed before the summoner name
|
| 21 |
+
url = f"https://www.op.gg/summoners/{region}/{formatted_summoner}?queue_type=SOLORANKED"
|
| 22 |
+
|
| 23 |
+
try:
|
| 24 |
+
# Send a GET request to the URL
|
| 25 |
+
response = requests.get(url)
|
| 26 |
+
|
| 27 |
+
# Check if the response status is 200 (OK)
|
| 28 |
+
if response.status_code == 200:
|
| 29 |
+
print(f"Connection successful to {url}")
|
| 30 |
+
return True
|
| 31 |
+
else:
|
| 32 |
+
print(f"Failed to connect to {url}. Status code: {response.status_code}")
|
| 33 |
+
return False
|
| 34 |
+
except requests.exceptions.RequestException as e:
|
| 35 |
+
print(f"Error connecting to {url}: {e}")
|
| 36 |
+
return False
|
| 37 |
+
|
| 38 |
+
# # Open the input CSV file
|
| 39 |
+
# with open(input_file, mode="r", encoding="utf-8") as infile:
|
| 40 |
+
# csv_reader = csv.reader(infile)
|
| 41 |
+
# header = next(csv_reader) # Skip the header row
|
| 42 |
+
|
| 43 |
+
# # Process each row in the CSV file
|
| 44 |
+
# for row in csv_reader:
|
| 45 |
+
# region = row[1].strip() # Get region from the first column
|
| 46 |
+
# summoner = row[0].strip() # Get summoner name from the second column
|
| 47 |
+
|
| 48 |
+
# # Check connection for the region and summoner
|
| 49 |
+
# if not check_connection(region, summoner):
|
| 50 |
+
# failed_summoners.append(summoner)
|
| 51 |
+
|
| 52 |
+
# # Pause for a short time between requests to avoid overloading the server
|
| 53 |
+
# time.sleep(2)
|
| 54 |
+
|
| 55 |
+
# # Print out failed summoner names if any
|
| 56 |
+
# if failed_summoners:
|
| 57 |
+
# print("\nFailed to connect to the following summoners:")
|
| 58 |
+
# for summoner in failed_summoners:
|
| 59 |
+
# print(summoner)
|
| 60 |
+
# else:
|
| 61 |
+
# print("\nAll connections were successful.")
|
| 62 |
+
|
| 63 |
+
# print("Connection check completed.")
|
util/data/feature_eng_stats.csv
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
player_id,region,date,champion,level,team,result,match_length_mins,kill,death,assist,kda_ratio,kill_participation,laning,cs,cs_per_min,avg_tier,teammates1,team_champ1,teammates2,team_champ2,teammates3,team_champ3,teammates4,team_champ4,oppmates1,opp_champ1,oppmates2,opp_champ2,oppmates3,opp_champ3,oppmates4,opp_champ4,oppmates5,opp_champ5,total_games,wins,losses,win_rate,avg_kills,avg_deaths,avg_assists,kda_ratio_profile,kill_participation_profile,most_champ_1,WR_1,W_1,L_1,KDA_1,most_champ_2,WR_2,W_2,L_2,KDA_2,most_champ_3,WR_3,W_3,L_3,KDA_3,TOP,JUNGLE,MID,ADC,SUPPORT,most_role_1,most_role_2,most_role_1_value,most_role_2_value,season_champ_1,cs_ssn_1,cpm_ssn_1,kda_ssn_1,k_ssn_1,d_ssn_1,a_ssn_1,wr_ssn_1,games_ssn_1,season_champ_2,cs_ssn_2,cpm_ssn_2,kda_ssn_2,k_ssn_2,d_ssn_2,a_ssn_2,wr_ssn_2,games_ssn_2,season_champ_3,cs_ssn_3,cpm_ssn_3,kda_ssn_3,k_ssn_3,d_ssn_3,a_ssn_3,wr_ssn_3,games_ssn_3,season_champ_4,cs_ssn_4,cpm_ssn_4,kda_ssn_4,k_ssn_4,d_ssn_4,a_ssn_4,wr_ssn_4,games_ssn_4,season_champ_5,cs_ssn_5,cpm_ssn_5,kda_ssn_5,k_ssn_5,d_ssn_5,a_ssn_5,wr_ssn_5,games_ssn_5,season_champ_6,cs_ssn_6,cpm_ssn_6,kda_ssn_6,k_ssn_6,d_ssn_6,a_ssn_6,wr_ssn_6,games_ssn_6,season_champ_7,cs_ssn_7,cpm_ssn_7,kda_ssn_7,k_ssn_7,d_ssn_7,a_ssn_7,wr_ssn_7,games_ssn_7,7d_champ_1,7d_total_1,7d_W_1,7d_L_1,7d_WR_1,7d_champ_2,7d_total_2,7d_W_2,7d_L_2,7d_WR_2,7d_champ_3,7d_total_3,7d_W_3,7d_L_3,7d_WR_3,mastery_champ_1,m_lv_1,mastery_champ_2,m_lv_2,mastery_champ_3,m_lv_3,mastery_champ_4,m_lv_4,mastery_champ_5,m_lv_5,mastery_champ_6,m_lv_6,mastery_champ_7,m_lv_7,mastery_champ_8,m_lv_8,mastery_champ_9,m_lv_9,mastery_champ_10,m_lv_10,mastery_champ_11,m_lv_11,mastery_champ_12,m_lv_12,mastery_champ_13,m_lv_13,mastery_champ_14,m_lv_14,mastery_champ_15,m_lv_15,mastery_champ_16,m_lv_16,Aatrox,Ahri,Akali,Akshan,Alistar,Ambessa,Amumu,Anivia,Annie,Aphelios,Ashe,Aurelion Sol,Aurora,Azir,Bard,Bel'Veth,Blitzcrank,Brand,Braum,Briar,Caitlyn,Camille,Cassiopeia,Cho'Gath,Corki,Darius,Diana,Dr. Mundo,Draven,Ekko,Elise,Evelynn,Ezreal,Fiddlesticks,Fiora,Fizz,Galio,Gangplank,Garen,Gnar,Gragas,Graves,Gwen,Hecarim,Heimerdinger,Hwei,Illaoi,Irelia,Ivern,Janna,Jarvan IV,Jax,Jayce,Jhin,Jinx,K'Sante,Kai'Sa,Kalista,Karma,Karthus,Kassadin,Katarina,Kayle,Kayn,Kennen,Kha'Zix,Kindred,Kled,Kog'Maw,LeBlanc,Lee Sin,Leona,Lillia,Lissandra,Lucian,Lulu,Lux,Malphite,Malzahar,Maokai,Master Yi,Milio,Miss Fortune,Mordekaiser,Morgana,Naafiri,Nami,Nasus,Nautilus,Neeko,Nidalee,Nilah,Nocturne,Nunu & Willump,Olaf,Orianna,Ornn,Pantheon,Poppy,Pyke,Qiyana,Quinn,Rakan,Rammus,Rek'Sai,Rell,Renata Glasc,Renekton,Rengar,Riven,Rumble,Ryze,Samira,Sejuani,Senna,Seraphine,Sett,Shaco,Shen,Shyvana,Singed,Sion,Sivir,Skarner,Smolder,Sona,Soraka,Swain,Sylas,Syndra,Tahm Kench,Taliyah,Talon,Taric,Teemo,Thresh,Tristana,Trundle,Tryndamere,Twisted Fate,Twitch,Udyr,Urgot,Varus,Vayne,Veigar,Vel'Koz,Vex,Vi,Viego,Viktor,Vladimir,Volibear,Warwick,Wukong,Xayah,Xerath,Xin Zhao,Yasuo,Yone,Yorick,Yuumi,Zac,Zed,Zeri,Ziggs,Zilean,Zoe,Zyra
|
| 2 |
+
Agurin-EUW,euw,"Sun, Jan 5, 2025 6:25 PM",Jarvan IV,16,blue,1,26.68,9,2,19,14.0,0.67,1.08,183,6.9,2,skygge kriger #EUV,Rumble,성진우 #789,Vladimir,JEZUUU #0814,Yasuo,Papadodi #1010,Lulu,the inescapable #EUW,Maokai,edge of night #999,Kindred,Macaquiño #GAP,LeBlanc,Wanna be a pro #03120,Corki,Walid Georgey #EUW,Rell,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0,0.11383934426229508,0.32318367346938776,0.19435304347826085,0.003040336134453781,0.07462158415841585,0.009793636363636234,0.0001757142857142885,0.02706225165562915,0.022872147239263806,0.11887238095238094,0.08014285714285707,0.060601764705882355,0.10053333333333336,0.11204658536585367,0.28042,0.12472359550561801,0.14949,0.14558326278659614,0.09564000000000002,0.06285470085470087,0.1776823529411764,0.2269628571428571,0.029494444444444448,0.0789936507936508,0.0,0.0,0.2994142857142857,0.10848695652173915,0.0,0.20505185185185193,1.5788843958188155,0.2125009523809524,0.6752314285714287,0.0,0.0052499999999999995,0.037664415584415585,0.2163641025641026,0.07816271186440678,0.14430505263157895,0.2668461538461539,0.22659214285714285,0.49085,0.13604625,0.013109090909090916,0.0241679746835443,0.25233,0.0,0.2964923076923078,0.049657674418604664,0.13181290322580644,1.3217776953613445,0.1085672727272727,0.5364771428571429,0.6668666666666667,0.3157333333333334,0.37839999999999996,0.287661935483871,0.0953066666666667,0.3240156445714286,0.0,0.02140645161290322,0.0,0.03248357142857143,0.028233786407766977,0.07952651162790698,1.1184574571428572,0.0,0.03188603773584906,0.05807114093959731,0.0,0.5258000000000002,0.12630055555555558,0.08244909090909093,0.09255750000000001,0.1480488311688312,0.0,0.23643000000000006,0.0,0.01380975609756098,0.0,0.04587567567567568,0.035337421487603306,0.11078039215686274,0.02524102564102564,0.0,0.026839006211180128,0.18164927536231884,0.0,0.23344400000000007,0.2888510229218329,0.09398000000000001,0.0,0.3908067906921944,0.03370090090090089,0.0464123076923077,0.15542328358208957,0.028084931506849327,0.1338443389830509,0.3205411764705883,0.0,0.07963456790123458,0.010558843373493977,0.2898910344827586,0.03812181818181819,0.023729927007299263,0.0,0.060766500000000015,0.19474545454545455,0.0,0.047811724137931055,0.0,0.10606382978723405,0.04298074074074075,0.02798151079136691,0.15588760563380283,0.10673636363636366,0.07191428571428571,0.0,0.08626206896551725,0.28839116883116883,0.05303217391304348,0.05372068965517241,0.07618125,0.0,0.12963842105263157,0.19873636363636363,0.06274568807339448,0.15544363636363637,0.46191111111111116,0.19127272727272726,0.06470422535211266,0.2996571428571428,0.18210270270270268,0.06730866141732285,0.0734526315789474,0.11976986301369862,0.1494712857142857,0.10112538461538462,0.055889370629370626,0.04235210526315789,0.051068231292517016,0.004684955752212394,0.04743829787234045,0.2973836842105263,0.04035187969924811,0.03941967213114755,0.03712064516129032,0.0,0.13844842105263158,1.0648,0.2742,0.0,0.11894942528735633,0.05994626865671641,0.9992375885714286,0.0937211214953271,0.15617647058823528,0.13391111111111112,0.0,0.5096700000000001,0.038388235294117654,0.0,0.07933015384615384,0.009325581395348781,0.0841147169811321,0.14101384615384618,0.04188557142857143,0.048898901098901104,0.1943050549450549
|
| 3 |
+
Agurin-EUW,euw,"Sun, Jan 5, 2025 5:48 PM",Wukong,16,red,1,28.68,3,5,11,2.8,0.47,1.33,220,7.7,2,S8DiamondDog #EUW,Yasuo,Owen Mcdade #BLACK,Fiora,AllYouHadToDoWas #Stay,Karthus,Depressed Loser #ff15,LeBlanc,Drali #Drali,K'Sante,Kiki #COYG,Viego,222 #EUW3,Syndra,JEZUUU #0814,Xayah,grisha turbina #ADHD,Sona,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0,0.11383934426229508,0.32318367346938776,0.2159478260869565,0.003040336134453781,0.07462158415841585,0.010881818181818038,0.0001757142857142885,0.02706225165562915,0.022872147239263806,0.11887238095238094,0.08014285714285707,0.060601764705882355,0.10053333333333336,0.11204658536585367,0.28042,0.12472359550561801,0.14949,0.14558326278659614,0.09564000000000002,0.06285470085470087,0.1776823529411764,0.25218095238095234,0.029494444444444448,0.0789936507936508,0.1869333333333333,0.0,0.2994142857142857,0.10848695652173915,0.0,0.20505185185185193,1.5788843958188155,0.2125009523809524,0.6752314285714287,0.0,0.0,0.037664415584415585,0.2163641025641026,0.07816271186440678,0.16033894736842105,0.2668461538461539,0.2517690476190476,0.49085,0.13604625,0.013109090909090916,0.0241679746835443,0.28036666666666665,0.0,0.2964923076923078,0.049657674418604664,0.1186316129032258,1.3217776953613445,0.1085672727272727,0.5364771428571429,0.6668666666666667,0.3157333333333334,0.0,0.287661935483871,0.0953066666666667,0.3600173828571429,0.0,0.02140645161290322,0.0,0.03609285714285714,0.03137087378640775,0.07952651162790698,1.1184574571428572,0.09357652173913049,0.03188603773584906,0.05807114093959731,0.0,0.5258000000000002,0.12630055555555558,0.08244909090909093,0.10284166666666668,0.1480488311688312,0.17259999999999998,0.26270000000000004,0.0,0.01380975609756098,0.2749276595744681,0.04587567567567568,0.03926380165289256,0.11078039215686274,0.02524102564102564,0.0,0.026839006211180128,0.18164927536231884,0.0,0.2593822222222223,0.2888510229218329,0.09398000000000001,0.0,0.3908067906921944,0.03370090090090089,0.0464123076923077,0.15542328358208957,0.028084931506849327,0.1673054237288136,0.28848705882352943,0.0,0.07963456790123458,0.011732048192771086,0.2609019310344827,0.03812181818181819,0.023729927007299263,0.2623725,0.06751833333333335,0.19474545454545455,0.0,0.0531241379310345,0.15295135135135138,0.10606382978723405,0.04298074074074075,0.02798151079136691,0.15588760563380283,0.10673636363636366,0.07191428571428571,0.0,0.08626206896551725,0.28839116883116883,0.05303217391304348,0.05372068965517241,0.07618125,0.0,0.12963842105263157,0.0,0.06274568807339448,0.13989927272727273,0.46191111111111116,0.0,0.06470422535211266,0.2996571428571428,0.18210270270270268,0.06730866141732285,0.0734526315789474,0.11976986301369862,0.1660792063492063,0.10112538461538462,0.055889370629370626,0.04235210526315789,0.051068231292517016,0.004684955752212394,0.04743829787234045,0.2973836842105263,0.04035187969924811,0.03941967213114755,0.04124516129032258,0.0,0.13844842105263158,0.0,0.2742,0.043024337349397604,0.11894942528735633,0.05994626865671641,0.9992375885714286,0.0,0.15617647058823528,0.13391111111111112,0.0,0.5096700000000001,0.038388235294117654,0.0,0.08814461538461538,0.009325581395348781,0.0841147169811321,0.14101384615384618,0.04188557142857143,0.048898901098901104,0.1943050549450549
|
| 4 |
+
Agurin-EUW,euw,"Sun, Jan 5, 2025 5:10 PM",Wukong,12,blue,0,20.65,6,4,2,2.0,0.57,0.89,153,7.4,2,Novachrono #Back,Cho'Gath,2025 #favo,Gragas,Jeyrus #Jey,Corki,Papadodi #1010,Lulu,S8DiamondDog #EUW,Dr. Mundo,Thomas Shelby #SOLOQ,Vi,222 #EUW3,Ekko,JEZUUU #0814,Caitlyn,Pablo #boda,Bard,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0,0.11383934426229508,0.32318367346938776,0.2159478260869565,0.003040336134453781,0.07462158415841585,0.010881818181818038,0.0001757142857142885,0.02706225165562915,0.022872147239263806,0.11887238095238094,0.08014285714285707,0.060601764705882355,0.10053333333333336,0.11204658536585367,0.0,0.12472359550561801,0.14949,0.14558326278659614,0.09564000000000002,0.06285470085470087,0.0,0.25218095238095234,0.029494444444444448,0.0,0.0,0.0,0.2694728571428571,0.0,0.0,0.0,1.5788843958188155,0.2125009523809524,0.6752314285714287,0.0,0.0052499999999999995,0.037664415584415585,0.2163641025641026,0.07816271186440678,0.16033894736842105,0.2668461538461539,0.0,0.49085,0.13604625,0.013109090909090916,0.0241679746835443,0.28036666666666665,0.0,0.2964923076923078,0.049657674418604664,0.13181290322580644,1.3217776953613445,0.1085672727272727,0.5364771428571429,0.6668666666666667,0.3157333333333334,0.37839999999999996,0.287661935483871,0.0953066666666667,0.3600173828571429,0.0,0.02140645161290322,0.0,0.03609285714285714,0.03137087378640775,0.07157386046511628,1.1184574571428572,0.09357652173913049,0.03188603773584906,0.05807114093959731,0.0,0.5258000000000002,0.12630055555555558,0.08244909090909093,0.10284166666666668,0.1480488311688312,0.0,0.26270000000000004,0.0,0.01380975609756098,0.2749276595744681,0.04587567567567568,0.03926380165289256,0.11078039215686274,0.02524102564102564,0.0,0.026839006211180128,0.18164927536231884,0.0,0.2593822222222223,0.2888510229218329,0.09398000000000001,0.0,0.3908067906921944,0.03370090090090089,0.0464123076923077,0.15542328358208957,0.025276438356164395,0.15057488135593225,0.3205411764705883,0.0,0.07963456790123458,0.011732048192771086,0.2898910344827586,0.03430963636363637,0.021356934306569337,0.2623725,0.06751833333333335,0.19474545454545455,0.0,0.0531241379310345,0.15295135135135138,0.10606382978723405,0.04298074074074075,0.02518335971223022,0.15588760563380283,0.10673636363636366,0.07191428571428571,0.0,0.08626206896551725,0.28839116883116883,0.05303217391304348,0.04834862068965517,0.07618125,0.0,0.12963842105263157,0.19873636363636363,0.06274568807339448,0.15544363636363637,0.46191111111111116,0.17214545454545455,0.06470422535211266,0.2696914285714285,0.18210270270270268,0.06730866141732285,0.0734526315789474,0.11976986301369862,0.1660792063492063,0.10112538461538462,0.055889370629370626,0.04235210526315789,0.051068231292517016,0.004684955752212394,0.04743829787234045,0.2973836842105263,0.04035187969924811,0.03941967213114755,0.04124516129032258,0.0,0.0,1.0648,0.24678,0.043024337349397604,0.11894942528735633,0.05994626865671641,0.9992375885714286,0.0937211214953271,0.15617647058823528,0.13391111111111112,0.40376190476190477,0.5096700000000001,0.038388235294117654,0.0,0.08814461538461538,0.008393023255813903,0.0841147169811321,0.14101384615384618,0.04653952380952381,0.048898901098901104,0.1943050549450549
|
| 5 |
+
Agurin-EUW,euw,"Sun, Jan 5, 2025 4:30 PM",Elise,15,blue,1,24.22,10,3,6,5.33,0.62,1.08,194,8.0,2,SatØrius #EUW,Rumble,AbbedaggÆ #EUW,Jayce,Kite Machine #EUW,Jhin,Vento #TAIF,Bard,KOI Spooder #1352,K'Sante,NazgulsBlade #LOTR,Skarner,TwitchTVxKenzuke #EUW,Aurora,Unkn0wn #EUW11,Ezreal,Paolocannone #EUW,Karma,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0,0.11383934426229508,0.32318367346938776,0.2159478260869565,0.003040336134453781,0.07462158415841585,0.010881818181818038,0.0001757142857142885,0.02706225165562915,0.022872147239263806,0.11887238095238094,0.08014285714285707,0.060601764705882355,0.0,0.11204658536585367,0.0,0.12472359550561801,0.14949,0.14558326278659614,0.09564000000000002,0.06285470085470087,0.1776823529411764,0.25218095238095234,0.029494444444444448,0.0789936507936508,0.1869333333333333,0.0,0.2994142857142857,0.10848695652173915,0.0,0.20505185185185193,1.5788843958188155,0.2125009523809524,0.0,0.0,0.0052499999999999995,0.037664415584415585,0.2163641025641026,0.07816271186440678,0.16033894736842105,0.2668461538461539,0.22659214285714285,0.49085,0.13604625,0.013109090909090916,0.0241679746835443,0.28036666666666665,0.0,0.2964923076923078,0.049657674418604664,0.13181290322580644,1.3217776953613445,0.1085672727272727,0.0,0.0,0.3157333333333334,0.0,0.287661935483871,0.0953066666666667,0.0,0.0,0.02140645161290322,0.0,0.03609285714285714,0.03137087378640775,0.07952651162790698,1.1184574571428572,0.09357652173913049,0.03188603773584906,0.05807114093959731,0.0,0.5258000000000002,0.12630055555555558,0.08244909090909093,0.10284166666666668,0.1480488311688312,0.17259999999999998,0.26270000000000004,0.0,0.01380975609756098,0.2749276595744681,0.04587567567567568,0.03926380165289256,0.11078039215686274,0.02524102564102564,0.0,0.026839006211180128,0.18164927536231884,0.0,0.2593822222222223,0.2888510229218329,0.09398000000000001,0.0,0.3908067906921944,0.03370090090090089,0.0464123076923077,0.15542328358208957,0.028084931506849327,0.1673054237288136,0.3205411764705883,0.0,0.07167111111111112,0.011732048192771086,0.2898910344827586,0.03812181818181819,0.023729927007299263,0.2623725,0.06751833333333335,0.19474545454545455,0.0,0.0531241379310345,0.0,0.10606382978723405,0.04298074074074075,0.02798151079136691,0.15588760563380283,0.10673636363636366,0.07191428571428571,0.0,0.08626206896551725,0.28839116883116883,0.05303217391304348,0.05372068965517241,0.07618125,0.0,0.12963842105263157,0.19873636363636363,0.06274568807339448,0.15544363636363637,0.46191111111111116,0.19127272727272726,0.06470422535211266,0.2996571428571428,0.18210270270270268,0.06730866141732285,0.0734526315789474,0.11976986301369862,0.1660792063492063,0.10112538461538462,0.055889370629370626,0.04235210526315789,0.051068231292517016,0.004684955752212394,0.0426944680851064,0.2973836842105263,0.04035187969924811,0.03941967213114755,0.04124516129032258,0.0,0.13844842105263158,1.0648,0.2742,0.043024337349397604,0.11894942528735633,0.05994626865671641,0.9992375885714286,0.0937211214953271,0.15617647058823528,0.13391111111111112,0.40376190476190477,0.5096700000000001,0.038388235294117654,0.0,0.08814461538461538,0.009325581395348781,0.0841147169811321,0.14101384615384618,0.04653952380952381,0.048898901098901104,0.1943050549450549
|
| 6 |
+
Agurin-EUW,euw,"Sun, Jan 5, 2025 1:34 AM",Wukong,14,blue,0,26.37,7,10,4,1.1,0.65,0.89,169,6.4,2,Vandett0 #ETABL,Teemo,Grunge #010,Yone,222 #EUW3,Ekko,Crixus #ARENA,Leona,SenSen #EUWFR,Nidalee,AllYouHadToDoWas #Stay,Karthus,SRTSS #EUW,Corki,Keduii #GOAT,Caitlyn,Sergeant Sona #KJP,Sona,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0,0.11383934426229508,0.32318367346938776,0.2159478260869565,0.003040336134453781,0.07462158415841585,0.009793636363636234,0.00015814285714285965,0.02706225165562915,0.022872147239263806,0.11887238095238094,0.07212857142857136,0.060601764705882355,0.10053333333333336,0.11204658536585367,0.28042,0.12472359550561801,0.14949,0.13102493650793653,0.09564000000000002,0.06285470085470087,0.0,0.25218095238095234,0.029494444444444448,0.0789936507936508,0.0,0.0,0.2994142857142857,0.10848695652173915,0.0,0.0,1.5788843958188155,0.2125009523809524,0.6077082857142858,0.0,0.0052499999999999995,0.037664415584415585,0.2163641025641026,0.07816271186440678,0.16033894736842105,0.2668461538461539,0.2517690476190476,0.49085,0.13604625,0.013109090909090916,0.0241679746835443,0.28036666666666665,0.0,0.2964923076923078,0.049657674418604664,0.1186316129032258,1.3217776953613445,0.1085672727272727,0.5364771428571429,0.6668666666666667,0.3157333333333334,0.37839999999999996,0.25889574193548387,0.0953066666666667,0.3600173828571429,0.0,0.02140645161290322,0.0,0.03248357142857143,0.03137087378640775,0.07952651162790698,1.1184574571428572,0.09357652173913049,0.03188603773584906,0.05226402684563758,0.0,0.5258000000000002,0.0,0.08244909090909093,0.09255750000000001,0.13324394805194809,0.17259999999999998,0.23643000000000006,0.0,0.01380975609756098,0.2749276595744681,0.04587567567567568,0.03926380165289256,0.09970235294117646,0.02524102564102564,0.0,0.026839006211180128,0.18164927536231884,0.0,0.2593822222222223,0.2888510229218329,0.0,0.0,0.3908067906921944,0.03370090090090089,0.0464123076923077,0.15542328358208957,0.028084931506849327,0.1673054237288136,0.28848705882352943,0.0,0.07963456790123458,0.011732048192771086,0.2609019310344827,0.03812181818181819,0.021356934306569337,0.2623725,0.06751833333333335,0.19474545454545455,0.0,0.0531241379310345,0.15295135135135138,0.10606382978723405,0.04298074074074075,0.02798151079136691,0.15588760563380283,0.0960627272727273,0.07191428571428571,0.0,0.08626206896551725,0.28839116883116883,0.05303217391304348,0.05372068965517241,0.07618125,0.0,0.12963842105263157,0.0,0.06274568807339448,0.13989927272727273,0.46191111111111116,0.19127272727272726,0.06470422535211266,0.2996571428571428,0.18210270270270268,0.06730866141732285,0.0,0.11976986301369862,0.13286336507936505,0.10112538461538462,0.055889370629370626,0.04235210526315789,0.04596140816326531,0.004684955752212394,0.04743829787234045,0.2676453157894737,0.04035187969924811,0.035477704918032794,0.04124516129032258,0.0,0.13844842105263158,1.0648,0.24678,0.043024337349397604,0.11894942528735633,0.05994626865671641,0.8993138297142858,0.0937211214953271,0.15617647058823528,0.13391111111111112,0.32300952380952386,0.0,0.038388235294117654,0.0,0.08814461538461538,0.009325581395348781,0.07570324528301889,0.12691246153846156,0.04188557142857143,0.048898901098901104,0.17487454945054942
|
| 7 |
+
Agurin-EUW,euw,"Sun, Jan 5, 2025 12:48 AM",Wukong,17,blue,1,31.83,4,3,4,2.67,0.33,1.13,267,8.4,2,Bobsik #EUW,Camille,SRTSS #EUW,LeBlanc,PsychoZedPlayer #EUW,Hwei,mein herz #197,Janna,Patrick Jane #Tea,Vladimir,Seonsu #Noula,Viego,Odysseus #131,Taliyah,Keduii #GOAT,Ezreal,Crixus #ARENA,Zilean,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0,0.11383934426229508,0.32318367346938776,0.19435304347826085,0.003040336134453781,0.07462158415841585,0.010881818181818038,0.0001757142857142885,0.02706225165562915,0.022872147239263806,0.11887238095238094,0.08014285714285707,0.060601764705882355,0.10053333333333336,0.11204658536585367,0.28042,0.12472359550561801,0.14949,0.14558326278659614,0.09564000000000002,0.06285470085470087,0.1776823529411764,0.0,0.029494444444444448,0.0789936507936508,0.1869333333333333,0.0,0.2994142857142857,0.10848695652173915,0.0,0.20505185185185193,1.5788843958188155,0.19125085714285717,0.0,0.0,0.0052499999999999995,0.037664415584415585,0.2163641025641026,0.07816271186440678,0.16033894736842105,0.2401615384615385,0.2517690476190476,0.49085,0.13604625,0.013109090909090916,0.0241679746835443,0.0,0.0,0.2964923076923078,0.049657674418604664,0.0,1.3217776953613445,0.09771054545454544,0.5364771428571429,0.6668666666666667,0.3157333333333334,0.37839999999999996,0.287661935483871,0.0953066666666667,0.3600173828571429,0.0,0.02140645161290322,0.0,0.03609285714285714,0.03137087378640775,0.07952651162790698,1.1184574571428572,0.09357652173913049,0.03188603773584906,0.05807114093959731,0.0,0.5258000000000002,0.12630055555555558,0.08244909090909093,0.10284166666666668,0.1480488311688312,0.17259999999999998,0.23643000000000006,0.0,0.01380975609756098,0.2749276595744681,0.04587567567567568,0.03926380165289256,0.11078039215686274,0.02524102564102564,0.0,0.026839006211180128,0.18164927536231884,0.0,0.2593822222222223,0.23108081833746633,0.09398000000000001,0.0,0.3908067906921944,0.03370090090090089,0.0464123076923077,0.15542328358208957,0.028084931506849327,0.1673054237288136,0.3205411764705883,0.0,0.07963456790123458,0.011732048192771086,0.2898910344827586,0.03812181818181819,0.023729927007299263,0.2623725,0.06751833333333335,0.19474545454545455,0.0,0.0531241379310345,0.15295135135135138,0.09545744680851065,0.04298074074074075,0.02798151079136691,0.15588760563380283,0.10673636363636366,0.07191428571428571,0.0,0.08626206896551725,0.28839116883116883,0.05303217391304348,0.05372068965517241,0.07618125,0.0,0.12963842105263157,0.19873636363636363,0.06274568807339448,0.15544363636363637,0.41572000000000003,0.19127272727272726,0.06470422535211266,0.0,0.18210270270270268,0.06730866141732285,0.0734526315789474,0.11976986301369862,0.1660792063492063,0.10112538461538462,0.055889370629370626,0.04235210526315789,0.051068231292517016,0.004684955752212394,0.04743829787234045,0.2973836842105263,0.04035187969924811,0.03941967213114755,0.04124516129032258,0.0,0.13844842105263158,0.0,0.2742,0.0,0.11894942528735633,0.05994626865671641,0.9992375885714286,0.0937211214953271,0.15617647058823528,0.13391111111111112,0.3633857142857143,0.5096700000000001,0.038388235294117654,0.0,0.07933015384615384,0.009325581395348781,0.0841147169811321,0.14101384615384618,0.0,0.048898901098901104,0.1943050549450549
|
| 8 |
+
Agurin-EUW,euw,"Sat, Jan 4, 2025 11:56 PM",Wukong,16,red,1,25.28,7,2,7,7.0,0.61,0.89,208,8.2,2,Szygenda #EUW,Aurora,Dr Orange #Caps,Galio,J1HUIV #000,Kalista,ttveminencjasupp #kick,Renata Glasc,Patrick Jane #Tea,Vladimir,Thors Snoresson #3327,Graves,222 #EUW3,Syndra,LeonardoDiCassio #EUW,Caitlyn,Maynter #EUW,Nautilus,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0,0.11383934426229508,0.32318367346938776,0.2159478260869565,0.003040336134453781,0.07462158415841585,0.010881818181818038,0.0001757142857142885,0.02706225165562915,0.022872147239263806,0.11887238095238094,0.08014285714285707,0.060601764705882355,0.0,0.11204658536585367,0.28042,0.12472359550561801,0.14949,0.14558326278659614,0.09564000000000002,0.06285470085470087,0.0,0.25218095238095234,0.029494444444444448,0.0789936507936508,0.1869333333333333,0.0,0.2994142857142857,0.10848695652173915,0.0,0.20505185185185193,1.5788843958188155,0.2125009523809524,0.6752314285714287,0.0,0.0052499999999999995,0.037664415584415585,0.0,0.07816271186440678,0.16033894736842105,0.2401615384615385,0.2517690476190476,0.0,0.13604625,0.013109090909090916,0.0241679746835443,0.28036666666666665,0.0,0.2964923076923078,0.049657674418604664,0.13181290322580644,1.3217776953613445,0.09771054545454544,0.5364771428571429,0.6668666666666667,0.3157333333333334,0.37839999999999996,0.287661935483871,0.0,0.3600173828571429,0.0,0.02140645161290322,0.0,0.03609285714285714,0.03137087378640775,0.07952651162790698,1.1184574571428572,0.09357652173913049,0.03188603773584906,0.05807114093959731,0.0,0.5258000000000002,0.12630055555555558,0.08244909090909093,0.10284166666666668,0.1480488311688312,0.17259999999999998,0.26270000000000004,0.0,0.01380975609756098,0.2749276595744681,0.04587567567567568,0.03926380165289256,0.11078039215686274,0.02524102564102564,0.0,0.026839006211180128,0.18164927536231884,0.0,0.0,0.2599659206296496,0.09398000000000001,0.0,0.3908067906921944,0.03370090090090089,0.0464123076923077,0.15542328358208957,0.028084931506849327,0.1673054237288136,0.3205411764705883,0.0,0.07963456790123458,0.011732048192771086,0.2898910344827586,0.03812181818181819,0.023729927007299263,0.2623725,0.0,0.19474545454545455,0.0,0.0531241379310345,0.15295135135135138,0.10606382978723405,0.04298074074074075,0.02798151079136691,0.15588760563380283,0.10673636363636366,0.07191428571428571,0.0,0.08626206896551725,0.28839116883116883,0.05303217391304348,0.05372068965517241,0.07618125,0.0,0.12963842105263157,0.19873636363636363,0.06274568807339448,0.15544363636363637,0.46191111111111116,0.0,0.06470422535211266,0.2996571428571428,0.18210270270270268,0.06730866141732285,0.0734526315789474,0.11976986301369862,0.1660792063492063,0.10112538461538462,0.055889370629370626,0.04235210526315789,0.051068231292517016,0.004684955752212394,0.04743829787234045,0.2973836842105263,0.04035187969924811,0.03941967213114755,0.04124516129032258,0.0,0.13844842105263158,1.0648,0.2742,0.0,0.11894942528735633,0.05994626865671641,0.9992375885714286,0.0937211214953271,0.15617647058823528,0.13391111111111112,0.40376190476190477,0.5096700000000001,0.038388235294117654,0.0,0.08814461538461538,0.009325581395348781,0.0841147169811321,0.14101384615384618,0.04653952380952381,0.048898901098901104,0.1943050549450549
|
| 9 |
+
Agurin-EUW,euw,"Sat, Jan 4, 2025 10:39 PM",Wukong,13,red,1,21.02,5,1,5,10.0,0.56,1.44,147,7.0,2,Desperate Nasus #EUW,Kayle,Yoo Jonghyuk333 #EUW,Aurora,LeonardoDiCassio #EUW,Viktor,Canam #123,Nami,Makkro #EUW,Ornn,Kiki #COYG,Skarner,SRTSS #EUW,Yone,avarice61 #EUW,Kog'Maw,Sergeant Sona #KJP,Seraphine,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0,0.11383934426229508,0.32318367346938776,0.2159478260869565,0.003040336134453781,0.07462158415841585,0.010881818181818038,0.0001757142857142885,0.02706225165562915,0.022872147239263806,0.11887238095238094,0.08014285714285707,0.060601764705882355,0.0,0.11204658536585367,0.28042,0.12472359550561801,0.14949,0.14558326278659614,0.09564000000000002,0.06285470085470087,0.15991411764705876,0.25218095238095234,0.029494444444444448,0.07109428571428572,0.14954666666666666,0.0,0.2994142857142857,0.10848695652173915,0.0,0.20505185185185193,1.5788843958188155,0.2125009523809524,0.6752314285714287,0.0,0.0052499999999999995,0.037664415584415585,0.2163641025641026,0.07816271186440678,0.16033894736842105,0.2668461538461539,0.22659214285714285,0.49085,0.13604625,0.013109090909090916,0.0241679746835443,0.28036666666666665,0.0,0.2964923076923078,0.049657674418604664,0.13181290322580644,1.3217776953613445,0.1085672727272727,0.5364771428571429,0.60018,0.2841600000000001,0.37839999999999996,0.287661935483871,0.08577600000000003,0.3600173828571429,0.0,0.02140645161290322,0.0,0.0,0.03137087378640775,0.07952651162790698,1.1184574571428572,0.09357652173913049,0.03188603773584906,0.0,0.0,0.5258000000000002,0.12630055555555558,0.08244909090909093,0.10284166666666668,0.1480488311688312,0.17259999999999998,0.26270000000000004,0.0,0.01380975609756098,0.2749276595744681,0.04587567567567568,0.03926380165289256,0.09970235294117646,0.02524102564102564,0.0,0.026839006211180128,0.0,0.0,0.2593822222222223,0.2888510229218329,0.09398000000000001,0.0,0.3908067906921944,0.03370090090090089,0.0464123076923077,0.15542328358208957,0.0,0.1673054237288136,0.3205411764705883,0.0,0.07167111111111112,0.011732048192771086,0.2898910344827586,0.03812181818181819,0.023729927007299263,0.2623725,0.06751833333333335,0.19474545454545455,0.0,0.0531241379310345,0.15295135135135138,0.10606382978723405,0.04298074074074075,0.02798151079136691,0.15588760563380283,0.0,0.07191428571428571,0.0,0.08626206896551725,0.28839116883116883,0.05303217391304348,0.05372068965517241,0.060945000000000006,0.0,0.12963842105263157,0.19873636363636363,0.06274568807339448,0.15544363636363637,0.46191111111111116,0.19127272727272726,0.06470422535211266,0.2996571428571428,0.18210270270270268,0.06730866141732285,0.0734526315789474,0.11976986301369862,0.1660792063492063,0.10112538461538462,0.055889370629370626,0.04235210526315789,0.051068231292517016,0.004684955752212394,0.04743829787234045,0.2973836842105263,0.04035187969924811,0.03941967213114755,0.04124516129032258,0.0,0.13844842105263158,1.0648,0.0,0.043024337349397604,0.11894942528735633,0.05994626865671641,0.9992375885714286,0.0843490093457944,0.15617647058823528,0.13391111111111112,0.40376190476190477,0.0,0.038388235294117654,0.0,0.08814461538461538,0.009325581395348781,0.0841147169811321,0.14101384615384618,0.04653952380952381,0.048898901098901104,0.1943050549450549
|
| 10 |
+
Agurin-EUW,euw,"Sat, Jan 4, 2025 10:04 PM",Elise,17,blue,1,25.4,15,3,6,7.0,0.53,1.56,225,8.9,2,choilot #LOT,Gnar,a winds rhythm #Aang,Yasuo,Boring Cycle #Abner,Swain,ataraxia #7z7,Bard,Riihonen #EUW,Vladimir,AkaManto #LGM,Hecarim,SRTSS #EUW,Yone,Keduii #GOAT,Ashe,Peak Level #123,Zac,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0,0.11383934426229508,0.32318367346938776,0.2159478260869565,0.003040336134453781,0.07462158415841585,0.010881818181818038,0.0001757142857142885,0.02706225165562915,0.022872147239263806,0.11887238095238094,0.0,0.060601764705882355,0.10053333333333336,0.11204658536585367,0.0,0.12472359550561801,0.14949,0.14558326278659614,0.09564000000000002,0.06285470085470087,0.1776823529411764,0.2269628571428571,0.029494444444444448,0.0789936507936508,0.1869333333333333,0.0,0.2994142857142857,0.10848695652173915,0.0,0.20505185185185193,1.5788843958188155,0.2125009523809524,0.6752314285714287,0.0,0.0052499999999999995,0.037664415584415585,0.19472769230769235,0.07816271186440678,0.16033894736842105,0.0,0.2517690476190476,0.49085,0.13604625,0.0,0.0241679746835443,0.28036666666666665,0.0,0.266843076923077,0.049657674418604664,0.13181290322580644,1.3217776953613445,0.09771054545454544,0.5364771428571429,0.6668666666666667,0.3157333333333334,0.37839999999999996,0.287661935483871,0.0953066666666667,0.3600173828571429,0.0,0.02140645161290322,0.0,0.03609285714285714,0.03137087378640775,0.07952651162790698,1.1184574571428572,0.09357652173913049,0.03188603773584906,0.05807114093959731,0.0,0.5258000000000002,0.12630055555555558,0.08244909090909093,0.10284166666666668,0.1480488311688312,0.17259999999999998,0.26270000000000004,0.0,0.01380975609756098,0.2749276595744681,0.04587567567567568,0.03926380165289256,0.11078039215686274,0.02524102564102564,0.0,0.026839006211180128,0.18164927536231884,0.0,0.2593822222222223,0.2599659206296496,0.09398000000000001,0.0,0.3908067906921944,0.03370090090090089,0.0464123076923077,0.15542328358208957,0.028084931506849327,0.1673054237288136,0.3205411764705883,0.0,0.07963456790123458,0.011732048192771086,0.2898910344827586,0.03812181818181819,0.023729927007299263,0.2623725,0.06751833333333335,0.19474545454545455,0.0,0.0531241379310345,0.15295135135135138,0.09545744680851065,0.04298074074074075,0.02798151079136691,0.15588760563380283,0.10673636363636366,0.06472285714285714,0.0,0.08626206896551725,0.28839116883116883,0.05303217391304348,0.05372068965517241,0.07618125,0.0,0.12963842105263157,0.17886272727272726,0.06274568807339448,0.0,0.46191111111111116,0.19127272727272726,0.06470422535211266,0.2996571428571428,0.18210270270270268,0.06730866141732285,0.0734526315789474,0.11976986301369862,0.1660792063492063,0.09101284615384615,0.055889370629370626,0.04235210526315789,0.051068231292517016,0.004684955752212394,0.04743829787234045,0.2973836842105263,0.04035187969924811,0.03941967213114755,0.04124516129032258,0.0,0.13844842105263158,1.0648,0.2742,0.0,0.11894942528735633,0.05994626865671641,0.9992375885714286,0.0937211214953271,0.15617647058823528,0.13391111111111112,0.0,0.0,0.038388235294117654,0.0,0.0,0.009325581395348781,0.0841147169811321,0.14101384615384618,0.04653952380952381,0.048898901098901104,0.1943050549450549
|
| 11 |
+
Agurin-EUW,euw,"Sat, Jan 4, 2025 9:01 PM",Wukong,13,blue,0,27.2,6,11,5,1.0,0.58,0.82,159,5.8,2,Ronaldo Nazário #12345,Irelia,TATA #HOPE,Galio,chöego #EUW,Corki,Sergeant Sona #KJP,Sona,drunkenztain #EUW,Fiddlesticks,Foutriquet #EUW,Jarvan IV,silkysmath #6206,Syndra,Kushala Daora #MHVV,Caitlyn,darkchri99 #EUW,Lux,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0,0.11383934426229508,0.32318367346938776,0.2159478260869565,0.003040336134453781,0.07462158415841585,0.010881818181818038,0.0001757142857142885,0.02706225165562915,0.022872147239263806,0.11887238095238094,0.07212857142857136,0.060601764705882355,0.10053333333333336,0.11204658536585367,0.252378,0.12472359550561801,0.14949,0.13102493650793653,0.09564000000000002,0.06285470085470087,0.0,0.25218095238095234,0.029494444444444448,0.0789936507936508,0.0,0.0,0.2994142857142857,0.10848695652173915,0.0,0.20505185185185193,1.5788843958188155,0.2125009523809524,0.6752314285714287,0.0,0.0052499999999999995,0.037664415584415585,0.0,0.07816271186440678,0.16033894736842105,0.2668461538461539,0.2517690476190476,0.49085,0.13604625,0.013109090909090916,0.0241679746835443,0.28036666666666665,0.0,0.0,0.049657674418604664,0.13181290322580644,0.0,0.1085672727272727,0.5364771428571429,0.6668666666666667,0.2841600000000001,0.37839999999999996,0.287661935483871,0.0953066666666667,0.3240156445714286,0.0,0.02140645161290322,0.0,0.03609285714285714,0.028233786407766977,0.07952651162790698,1.0066117114285715,0.09357652173913049,0.03188603773584906,0.05807114093959731,0.0,0.5258000000000002,0.12630055555555558,0.08244909090909093,0.09255750000000001,0.1480488311688312,0.15533999999999998,0.0,0.0,0.01380975609756098,0.2749276595744681,0.04587567567567568,0.03926380165289256,0.11078039215686274,0.02524102564102564,0.0,0.026839006211180128,0.16348434782608695,0.0,0.2593822222222223,0.2599659206296496,0.09398000000000001,0.0,0.3908067906921944,0.03370090090090089,0.0464123076923077,0.15542328358208957,0.028084931506849327,0.1673054237288136,0.3205411764705883,0.0,0.07963456790123458,0.011732048192771086,0.2898910344827586,0.03812181818181819,0.023729927007299263,0.2623725,0.06751833333333335,0.19474545454545455,0.0,0.0531241379310345,0.15295135135135138,0.10606382978723405,0.04298074074074075,0.02798151079136691,0.15588760563380283,0.10673636363636366,0.07191428571428571,0.0,0.08626206896551725,0.28839116883116883,0.05303217391304348,0.05372068965517241,0.07618125,0.0,0.11667457894736842,0.0,0.06274568807339448,0.1243549090909091,0.46191111111111116,0.0,0.06470422535211266,0.2996571428571428,0.18210270270270268,0.06057779527559057,0.0734526315789474,0.11976986301369862,0.1660792063492063,0.10112538461538462,0.055889370629370626,0.04235210526315789,0.051068231292517016,0.004684955752212394,0.04743829787234045,0.2973836842105263,0.04035187969924811,0.035477704918032794,0.04124516129032258,0.0,0.13844842105263158,1.0648,0.2742,0.043024337349397604,0.11894942528735633,0.05994626865671641,0.9992375885714286,0.0937211214953271,0.15617647058823528,0.13391111111111112,0.40376190476190477,0.5096700000000001,0.038388235294117654,0.0,0.08814461538461538,0.009325581395348781,0.0841147169811321,0.14101384615384618,0.04653952380952381,0.048898901098901104,0.1943050549450549
|
| 12 |
+
Agurin-EUW,euw,"Sat, Jan 4, 2025 8:23 PM",Elise,12,red,0,24.83,1,6,2,0.5,0.2,0.92,163,6.6,2,Bent246 #Bent,Akshan,c0cky movement #tukan,Irelia,fjgyqwjsaqxca #LUDER,Jinx,gummyjuiceULTRA #11cmP,Pyke,أستولفو بن لادن #UwU,Singed,bluerzor #grind,Wukong,나프켈라 #BOAT,Akali,e7c3c0fd cee3 4399 877b baf89c9f6f46 #EUW,Jhin,Sergeant Sona #KJP,Sona,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0,0.11383934426229508,0.32318367346938776,0.0,0.0,0.07462158415841585,0.010881818181818038,0.0001757142857142885,0.02706225165562915,0.022872147239263806,0.11887238095238094,0.08014285714285707,0.060601764705882355,0.0804266666666667,0.11204658536585367,0.28042,0.12472359550561801,0.14949,0.14558326278659614,0.09564000000000002,0.06285470085470087,0.1776823529411764,0.25218095238095234,0.029494444444444448,0.0789936507936508,0.1869333333333333,0.0,0.2994142857142857,0.10848695652173915,0.0,0.20505185185185193,1.5788843958188155,0.2125009523809524,0.6752314285714287,0.0,0.0052499999999999995,0.033897974025974026,0.2163641025641026,0.07816271186440678,0.16033894736842105,0.2668461538461539,0.2517690476190476,0.49085,0.12244162500000001,0.013109090909090916,0.0241679746835443,0.28036666666666665,0.0,0.0,0.049657674418604664,0.1186316129032258,1.3217776953613445,0.1085672727272727,0.5364771428571429,0.0,0.0,0.34056,0.287661935483871,0.0953066666666667,0.3600173828571429,0.0,0.02140645161290322,0.0,0.03609285714285714,0.028233786407766977,0.07952651162790698,1.1184574571428572,0.09357652173913049,0.028697433962264155,0.05807114093959731,0.0,0.5258000000000002,0.12630055555555558,0.08244909090909093,0.10284166666666668,0.1480488311688312,0.17259999999999998,0.26270000000000004,0.0,0.01380975609756098,0.2749276595744681,0.04587567567567568,0.03926380165289256,0.11078039215686274,0.02524102564102564,0.0,0.026839006211180128,0.18164927536231884,0.0,0.2593822222222223,0.2888510229218329,0.09398000000000001,0.0,0.35172611162297496,0.03370090090090089,0.0464123076923077,0.15542328358208957,0.028084931506849327,0.15057488135593225,0.28848705882352943,0.0,0.07963456790123458,0.011732048192771086,0.2609019310344827,0.03812181818181819,0.023729927007299263,0.2623725,0.06751833333333335,0.19474545454545455,0.0,0.0531241379310345,0.15295135135135138,0.10606382978723405,0.04298074074074075,0.02798151079136691,0.15588760563380283,0.10673636363636366,0.07191428571428571,0.0,0.08626206896551725,0.28839116883116883,0.0,0.05372068965517241,0.07618125,0.0,0.12963842105263157,0.0,0.06274568807339448,0.13989927272727273,0.46191111111111116,0.19127272727272726,0.051763380281690134,0.2996571428571428,0.18210270270270268,0.06730866141732285,0.0734526315789474,0.11976986301369862,0.1660792063492063,0.10112538461538462,0.055889370629370626,0.04235210526315789,0.051068231292517016,0.004684955752212394,0.04743829787234045,0.2973836842105263,0.04035187969924811,0.03941967213114755,0.04124516129032258,0.0,0.12460357894736843,1.0648,0.24678,0.03872190361445785,0.11894942528735633,0.05994626865671641,0.0,0.0937211214953271,0.15617647058823528,0.13391111111111112,0.3633857142857143,0.4587030000000001,0.038388235294117654,0.0,0.08814461538461538,0.009325581395348781,0.0841147169811321,0.14101384615384618,0.04188557142857143,0.048898901098901104,0.1943050549450549
|
| 13 |
+
Agurin-EUW,euw,"Sat, Jan 4, 2025 7:42 PM",Wukong,14,blue,1,21.82,5,2,8,6.5,0.39,1.0,174,8.0,2,skygge kriger #EUV,Aatrox,bvffi #meow,Corki,Kushala Daora #MHVV,Hwei,Zoo port #LOL,Zoe,c0cky movement #tukan,Yone,noname #gromp,Taliyah,e7c3c0fd cee3 4399 877b baf89c9f6f46 #EUW,Cho'Gath,twtv exofeng #IWNL,Draven,Sergeant Sona #KJP,Rakan,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0,0.0,0.290865306122449,0.19435304347826085,0.003040336134453781,0.07462158415841585,0.009793636363636234,0.0001757142857142885,0.02706225165562915,0.022872147239263806,0.11887238095238094,0.08014285714285707,0.060601764705882355,0.10053333333333336,0.11204658536585367,0.28042,0.12472359550561801,0.14949,0.14558326278659614,0.09564000000000002,0.06285470085470087,0.1776823529411764,0.25218095238095234,0.029494444444444448,0.0,0.0,0.0,0.2994142857142857,0.10848695652173915,0.0,0.20505185185185193,1.5788843958188155,0.19125085714285717,0.6752314285714287,0.0,0.0052499999999999995,0.037664415584415585,0.2163641025641026,0.0703464406779661,0.16033894736842105,0.2668461538461539,0.22659214285714285,0.49085,0.13604625,0.013109090909090916,0.0241679746835443,0.0,0.0,0.2964923076923078,0.049657674418604664,0.13181290322580644,1.3217776953613445,0.1085672727272727,0.5364771428571429,0.6668666666666667,0.3157333333333334,0.37839999999999996,0.287661935483871,0.0953066666666667,0.3600173828571429,0.0,0.0192658064516129,0.0,0.03609285714285714,0.03137087378640775,0.07952651162790698,1.1184574571428572,0.09357652173913049,0.03188603773584906,0.05807114093959731,0.0,0.5258000000000002,0.12630055555555558,0.08244909090909093,0.09255750000000001,0.1480488311688312,0.17259999999999998,0.23643000000000006,0.0,0.01380975609756098,0.2749276595744681,0.04587567567567568,0.03926380165289256,0.11078039215686274,0.02524102564102564,0.0,0.024155105590062117,0.18164927536231884,0.0,0.2593822222222223,0.2599659206296496,0.09398000000000001,0.0,0.3908067906921944,0.03370090090090089,0.0464123076923077,0.1398809552238806,0.028084931506849327,0.1673054237288136,0.3205411764705883,0.0,0.07963456790123458,0.011732048192771086,0.0,0.03812181818181819,0.023729927007299263,0.2623725,0.06751833333333335,0.19474545454545455,0.0,0.0531241379310345,0.15295135135135138,0.09545744680851065,0.04298074074074075,0.02798151079136691,0.15588760563380283,0.10673636363636366,0.07191428571428571,0.0,0.08626206896551725,0.28839116883116883,0.05303217391304348,0.05372068965517241,0.07618125,0.0,0.12963842105263157,0.19873636363636363,0.06274568807339448,0.15544363636363637,0.41572000000000003,0.19127272727272726,0.06470422535211266,0.0,0.18210270270270268,0.06730866141732285,0.0734526315789474,0.11976986301369862,0.1660792063492063,0.10112538461538462,0.050300433566433565,0.04235210526315789,0.051068231292517016,0.004684955752212394,0.04743829787234045,0.2973836842105263,0.04035187969924811,0.03941967213114755,0.04124516129032258,0.0,0.13844842105263158,1.0648,0.2742,0.03872190361445785,0.11894942528735633,0.05994626865671641,0.9992375885714286,0.0937211214953271,0.15617647058823528,0.13391111111111112,0.3633857142857143,0.0,0.038388235294117654,0.0,0.07933015384615384,0.008393023255813903,0.0841147169811321,0.14101384615384618,0.04653952380952381,0.0,0.1943050549450549
|
| 14 |
+
Agurin-EUW,euw,"Sat, Jan 4, 2025 7:13 PM",Wukong,14,red,0,24.2,3,6,7,1.67,0.53,0.28,172,7.1,2,DREILIX #000,Jayce,Bobsbag #EUW,Gragas,Rafitta #EUW,Corki,eXoValdo #EUW,Brand,e7c3c0fd cee3 4399 877b baf89c9f6f46 #EUW,Sion,wοkeupIikethis #EUW,Viego,Eternal Blizzard #carot,Hwei,PAKO ETERNAL #EUW,Ezreal,Sergeant Sona #KJP,Sona,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0,0.11383934426229508,0.32318367346938776,0.2159478260869565,0.003040336134453781,0.07462158415841585,0.010881818181818038,0.0001757142857142885,0.02706225165562915,0.022872147239263806,0.11887238095238094,0.08014285714285707,0.060601764705882355,0.10053333333333336,0.11204658536585367,0.28042,0.12472359550561801,0.14949,0.0,0.09564000000000002,0.06285470085470087,0.1776823529411764,0.25218095238095234,0.029494444444444448,0.0789936507936508,0.0,0.0,0.2994142857142857,0.10848695652173915,0.0,0.20505185185185193,1.5788843958188155,0.2125009523809524,0.0,0.0,0.0052499999999999995,0.037664415584415585,0.2163641025641026,0.07816271186440678,0.16033894736842105,0.2668461538461539,0.0,0.49085,0.13604625,0.013109090909090916,0.0241679746835443,0.0,0.0,0.2964923076923078,0.049657674418604664,0.1186316129032258,1.3217776953613445,0.1085672727272727,0.0,0.6668666666666667,0.3157333333333334,0.37839999999999996,0.287661935483871,0.0953066666666667,0.3600173828571429,0.0,0.02140645161290322,0.0,0.03609285714285714,0.03137087378640775,0.07952651162790698,1.1184574571428572,0.09357652173913049,0.03188603773584906,0.05807114093959731,0.0,0.5258000000000002,0.12630055555555558,0.08244909090909093,0.10284166666666668,0.1480488311688312,0.17259999999999998,0.26270000000000004,0.0,0.01380975609756098,0.2749276595744681,0.04587567567567568,0.03926380165289256,0.11078039215686274,0.02524102564102564,0.0,0.026839006211180128,0.18164927536231884,0.0,0.2593822222222223,0.2888510229218329,0.09398000000000001,0.0,0.3908067906921944,0.03370090090090089,0.0464123076923077,0.15542328358208957,0.028084931506849327,0.1673054237288136,0.28848705882352943,0.0,0.07963456790123458,0.011732048192771086,0.2609019310344827,0.03812181818181819,0.023729927007299263,0.2623725,0.06751833333333335,0.19474545454545455,0.0,0.0531241379310345,0.15295135135135138,0.10606382978723405,0.04298074074074075,0.02798151079136691,0.15588760563380283,0.10673636363636366,0.07191428571428571,0.0,0.08626206896551725,0.28839116883116883,0.05303217391304348,0.0,0.07618125,0.0,0.12963842105263157,0.0,0.06274568807339448,0.13989927272727273,0.46191111111111116,0.19127272727272726,0.06470422535211266,0.2996571428571428,0.18210270270270268,0.06730866141732285,0.0734526315789474,0.11976986301369862,0.1660792063492063,0.10112538461538462,0.055889370629370626,0.04235210526315789,0.051068231292517016,0.004684955752212394,0.04743829787234045,0.2676453157894737,0.04035187969924811,0.03941967213114755,0.04124516129032258,0.0,0.13844842105263158,0.0,0.2742,0.043024337349397604,0.11894942528735633,0.05994626865671641,0.9992375885714286,0.0937211214953271,0.15617647058823528,0.13391111111111112,0.40376190476190477,0.5096700000000001,0.038388235294117654,0.0,0.08814461538461538,0.009325581395348781,0.0841147169811321,0.14101384615384618,0.04188557142857143,0.048898901098901104,0.1943050549450549
|
| 15 |
+
Agurin-EUW,euw,"Sat, Jan 4, 2025 12:41 AM",Wukong,17,blue,1,34.25,5,11,18,2.09,0.51,0.67,194,5.7,2,batubabaHOPPALA #HOPPA,Riven,Fool Night #Ivy,Veigar,Sintemon #gumo,Ashe,ScoobaTroopah #10000,Blitzcrank,Pablo #boda,Aurora,TWTV DETDERT #12MAJ,Graves,J1HUIV #000,Karma,Mandaryñ #EUW,Corki,erdt #EUW,Leona,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0,0.11383934426229508,0.32318367346938776,0.2159478260869565,0.003040336134453781,0.07462158415841585,0.009793636363636234,0.0001757142857142885,0.02706225165562915,0.022872147239263806,0.11887238095238094,0.0,0.060601764705882355,0.0,0.11204658536585367,0.28042,0.12472359550561801,0.0,0.14558326278659614,0.09564000000000002,0.06285470085470087,0.1776823529411764,0.25218095238095234,0.029494444444444448,0.0789936507936508,0.0,0.0,0.2994142857142857,0.10848695652173915,0.0,0.20505185185185193,1.5788843958188155,0.2125009523809524,0.6752314285714287,0.0,0.0052499999999999995,0.037664415584415585,0.2163641025641026,0.07816271186440678,0.16033894736842105,0.2668461538461539,0.2517690476190476,0.0,0.13604625,0.013109090909090916,0.0241679746835443,0.28036666666666665,0.0,0.2964923076923078,0.049657674418604664,0.13181290322580644,1.3217776953613445,0.1085672727272727,0.5364771428571429,0.6668666666666667,0.3157333333333334,0.37839999999999996,0.287661935483871,0.0953066666666667,0.0,0.0,0.02140645161290322,0.0,0.03248357142857143,0.03137087378640775,0.07952651162790698,1.1184574571428572,0.09357652173913049,0.03188603773584906,0.05807114093959731,0.0,0.5258000000000002,0.0,0.08244909090909093,0.09255750000000001,0.1480488311688312,0.17259999999999998,0.26270000000000004,0.0,0.01380975609756098,0.2749276595744681,0.04587567567567568,0.03926380165289256,0.11078039215686274,0.02524102564102564,0.0,0.026839006211180128,0.18164927536231884,0.0,0.2593822222222223,0.2888510229218329,0.09398000000000001,0.0,0.3908067906921944,0.03370090090090089,0.0464123076923077,0.15542328358208957,0.028084931506849327,0.1673054237288136,0.3205411764705883,0.0,0.07963456790123458,0.011732048192771086,0.2898910344827586,0.03812181818181819,0.023729927007299263,0.2623725,0.06751833333333335,0.19474545454545455,0.0,0.0,0.15295135135135138,0.10606382978723405,0.04298074074074075,0.02798151079136691,0.15588760563380283,0.10673636363636366,0.07191428571428571,0.0,0.08626206896551725,0.28839116883116883,0.05303217391304348,0.05372068965517241,0.07618125,0.0,0.12963842105263157,0.19873636363636363,0.06274568807339448,0.15544363636363637,0.46191111111111116,0.19127272727272726,0.06470422535211266,0.2996571428571428,0.18210270270270268,0.06730866141732285,0.0734526315789474,0.11976986301369862,0.1494712857142857,0.10112538461538462,0.055889370629370626,0.04235210526315789,0.051068231292517016,0.004684955752212394,0.0426944680851064,0.2973836842105263,0.04035187969924811,0.0,0.04124516129032258,0.0,0.13844842105263158,1.0648,0.2742,0.043024337349397604,0.11894942528735633,0.05994626865671641,0.9992375885714286,0.0937211214953271,0.15617647058823528,0.13391111111111112,0.3633857142857143,0.5096700000000001,0.038388235294117654,0.0,0.08814461538461538,0.009325581395348781,0.0841147169811321,0.14101384615384618,0.04653952380952381,0.048898901098901104,0.1943050549450549
|
| 16 |
+
Agurin-EUW,euw,"Fri, Jan 3, 2025 11:54 PM",Wukong,15,red,1,23.03,7,3,5,4.0,0.48,1.56,197,8.6,2,Fool Night #Ivy,Aurora,Dr Orange #Caps,Sylas,Sintemon #gumo,Ashe,ScoobaTroopah #10000,Blitzcrank,modernillo #moder,Ambessa,Eternal Blizzard #carot,Viego,J1HUIV #000,Karma,Beanovich #bean,Varus,niudefuwuqi2007 #8085,Braum,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0,0.11383934426229508,0.32318367346938776,0.2159478260869565,0.003040336134453781,0.07462158415841585,0.0,0.0001757142857142885,0.02706225165562915,0.022872147239263806,0.11887238095238094,0.0,0.060601764705882355,0.0,0.11204658536585367,0.28042,0.12472359550561801,0.0,0.14558326278659614,0.0,0.06285470085470087,0.1776823529411764,0.25218095238095234,0.029494444444444448,0.0789936507936508,0.1869333333333333,0.0,0.2994142857142857,0.10848695652173915,0.0,0.20505185185185193,1.5788843958188155,0.2125009523809524,0.6752314285714287,0.0,0.0052499999999999995,0.037664415584415585,0.2163641025641026,0.07816271186440678,0.16033894736842105,0.2668461538461539,0.2517690476190476,0.49085,0.13604625,0.013109090909090916,0.0241679746835443,0.28036666666666665,0.0,0.2964923076923078,0.049657674418604664,0.13181290322580644,1.3217776953613445,0.1085672727272727,0.5364771428571429,0.6668666666666667,0.3157333333333334,0.37839999999999996,0.287661935483871,0.0953066666666667,0.0,0.0,0.02140645161290322,0.0,0.03609285714285714,0.03137087378640775,0.07952651162790698,1.1184574571428572,0.09357652173913049,0.03188603773584906,0.05807114093959731,0.0,0.5258000000000002,0.12630055555555558,0.08244909090909093,0.10284166666666668,0.1480488311688312,0.17259999999999998,0.26270000000000004,0.0,0.01380975609756098,0.2749276595744681,0.04587567567567568,0.03926380165289256,0.11078039215686274,0.02524102564102564,0.0,0.026839006211180128,0.18164927536231884,0.0,0.2593822222222223,0.2888510229218329,0.09398000000000001,0.0,0.3908067906921944,0.03370090090090089,0.0464123076923077,0.15542328358208957,0.028084931506849327,0.15057488135593225,0.3205411764705883,0.0,0.07963456790123458,0.011732048192771086,0.2898910344827586,0.03812181818181819,0.023729927007299263,0.2623725,0.06751833333333335,0.19474545454545455,0.0,0.0531241379310345,0.15295135135135138,0.10606382978723405,0.04298074074074075,0.02798151079136691,0.15588760563380283,0.10673636363636366,0.07191428571428571,0.0,0.08626206896551725,0.28839116883116883,0.05303217391304348,0.05372068965517241,0.07618125,0.0,0.12963842105263157,0.19873636363636363,0.06274568807339448,0.15544363636363637,0.0,0.19127272727272726,0.06470422535211266,0.2996571428571428,0.18210270270270268,0.06730866141732285,0.0734526315789474,0.11976986301369862,0.1660792063492063,0.10112538461538462,0.055889370629370626,0.04235210526315789,0.051068231292517016,0.004684955752212394,0.04743829787234045,0.0,0.04035187969924811,0.03941967213114755,0.04124516129032258,0.0,0.13844842105263158,0.0,0.2742,0.043024337349397604,0.11894942528735633,0.05994626865671641,0.9992375885714286,0.0937211214953271,0.15617647058823528,0.13391111111111112,0.40376190476190477,0.5096700000000001,0.038388235294117654,0.0,0.08814461538461538,0.009325581395348781,0.0841147169811321,0.14101384615384618,0.04653952380952381,0.048898901098901104,0.1943050549450549
|
| 17 |
+
Agurin-EUW,euw,"Fri, Jan 3, 2025 11:23 PM",Jarvan IV,17,blue,1,31.22,1,4,20,5.25,0.54,0.67,217,7.0,2,Vertigo #4810,Ambessa,LëFacteur Chance #EUW,Akali,Chrisberg #6103,Corki,raikooooo #EUW,Blitzcrank,modernillo #moder,Gragas,mikusik998 #gaz,Bel'Veth,Imma touch you #131,Hwei,Beanovich #bean,Kalista,Jordæn #EUW,Pantheon,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0,0.11383934426229508,0.32318367346938776,0.0,0.003040336134453781,0.07462158415841585,0.0,0.00015814285714285965,0.024356026490066237,0.020584932515337426,0.11887238095238094,0.08014285714285707,0.060601764705882355,0.09048000000000003,0.11204658536585367,0.28042,0.0,0.0,0.14558326278659614,0.09564000000000002,0.05656923076923078,0.1776823529411764,0.25218095238095234,0.029494444444444448,0.0789936507936508,0.0,0.0,0.2694728571428571,0.10848695652173915,0.0,0.18454666666666675,1.4209959562369339,0.2125009523809524,0.6752314285714287,0.0,0.0052499999999999995,0.037664415584415585,0.2163641025641026,0.07816271186440678,0.16033894736842105,0.2668461538461539,0.0,0.49085,0.12244162500000001,0.013109090909090916,0.0241679746835443,0.0,0.0,0.2964923076923078,0.049657674418604664,0.13181290322580644,1.1895999258252101,0.1085672727272727,0.5364771428571429,0.6668666666666667,0.3157333333333334,0.37839999999999996,0.287661935483871,0.0,0.3600173828571429,0.0,0.02140645161290322,0.0,0.03609285714285714,0.03137087378640775,0.07952651162790698,1.1184574571428572,0.09357652173913049,0.03188603773584906,0.05807114093959731,0.0,0.5258000000000002,0.12630055555555558,0.08244909090909093,0.10284166666666668,0.1480488311688312,0.17259999999999998,0.26270000000000004,0.0,0.01380975609756098,0.2749276595744681,0.04587567567567568,0.03926380165289256,0.11078039215686274,0.02524102564102564,0.0,0.026839006211180128,0.18164927536231884,0.0,0.2593822222222223,0.2888510229218329,0.09398000000000001,0.0,0.3908067906921944,0.026960720720720713,0.0464123076923077,0.15542328358208957,0.028084931506849327,0.0,0.3205411764705883,0.0,0.07963456790123458,0.011732048192771086,0.2898910344827586,0.03430963636363637,0.023729927007299263,0.2623725,0.06751833333333335,0.19474545454545455,0.0,0.0531241379310345,0.15295135135135138,0.09545744680851065,0.04298074074074075,0.02798151079136691,0.15588760563380283,0.10673636363636366,0.07191428571428571,0.0,0.08626206896551725,0.259552051948052,0.05303217391304348,0.05372068965517241,0.07618125,0.0,0.12963842105263157,0.19873636363636363,0.06274568807339448,0.15544363636363637,0.46191111111111116,0.19127272727272726,0.06470422535211266,0.2996571428571428,0.14568216216216215,0.06730866141732285,0.0734526315789474,0.11976986301369862,0.1660792063492063,0.10112538461538462,0.055889370629370626,0.04235210526315789,0.051068231292517016,0.004684955752212394,0.04743829787234045,0.2676453157894737,0.04035187969924811,0.03941967213114755,0.04124516129032258,0.0,0.13844842105263158,0.95832,0.2742,0.043024337349397604,0.1070544827586207,0.05994626865671641,0.9992375885714286,0.0937211214953271,0.15617647058823528,0.12052000000000002,0.40376190476190477,0.5096700000000001,0.038388235294117654,0.0,0.08814461538461538,0.009325581395348781,0.0841147169811321,0.14101384615384618,0.04653952380952381,0.048898901098901104,0.1943050549450549
|
| 18 |
+
Agurin-EUW,euw,"Fri, Jan 3, 2025 10:40 PM",Elise,16,red,1,29.27,6,3,18,8.0,0.71,1.27,197,6.7,2,blueskies777 #EUW,Renekton,Return to dust #Dust,Viktor,Beanovich #bean,Jinx,twojstary2komary #win,Rakan,나프켈라 #BOAT,Jax,bluerzor #grind,Skarner,LëFacteur Chance #EUW,Akali,Dr Mango #Hans,Kalista,Sergeant Sona #KJP,Lulu,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0,0.11383934426229508,0.32318367346938776,0.0,0.003040336134453781,0.07462158415841585,0.010881818181818038,0.0001757142857142885,0.02706225165562915,0.022872147239263806,0.11887238095238094,0.08014285714285707,0.060601764705882355,0.09048000000000003,0.11204658536585367,0.28042,0.12472359550561801,0.14949,0.14558326278659614,0.09564000000000002,0.05656923076923078,0.1776823529411764,0.25218095238095234,0.029494444444444448,0.0789936507936508,0.1869333333333333,0.0,0.2994142857142857,0.10848695652173915,0.0,0.20505185185185193,1.5788843958188155,0.2125009523809524,0.6752314285714287,0.0,0.0052499999999999995,0.033897974025974026,0.2163641025641026,0.07816271186440678,0.16033894736842105,0.2668461538461539,0.22659214285714285,0.49085,0.13604625,0.013109090909090916,0.0241679746835443,0.28036666666666665,0.0,0.2964923076923078,0.049657674418604664,0.13181290322580644,1.1895999258252101,0.0,0.5364771428571429,0.6668666666666667,0.0,0.37839999999999996,0.287661935483871,0.0,0.3600173828571429,0.0,0.02140645161290322,0.0,0.03609285714285714,0.03137087378640775,0.07952651162790698,1.1184574571428572,0.09357652173913049,0.028697433962264155,0.05807114093959731,0.0,0.5258000000000002,0.12630055555555558,0.08244909090909093,0.10284166666666668,0.1480488311688312,0.0,0.26270000000000004,0.0,0.01380975609756098,0.2749276595744681,0.04587567567567568,0.03926380165289256,0.11078039215686274,0.02524102564102564,0.0,0.026839006211180128,0.18164927536231884,0.0,0.2593822222222223,0.2888510229218329,0.09398000000000001,0.0,0.3908067906921944,0.03370090090090089,0.0464123076923077,0.15542328358208957,0.028084931506849327,0.1673054237288136,0.3205411764705883,0.0,0.07167111111111112,0.011732048192771086,0.0,0.03812181818181819,0.023729927007299263,0.2623725,0.06751833333333335,0.0,0.0,0.0531241379310345,0.15295135135135138,0.10606382978723405,0.04298074074074075,0.02798151079136691,0.15588760563380283,0.10673636363636366,0.07191428571428571,0.0,0.08626206896551725,0.28839116883116883,0.05303217391304348,0.05372068965517241,0.07618125,0.0,0.12963842105263157,0.19873636363636363,0.06274568807339448,0.15544363636363637,0.46191111111111116,0.19127272727272726,0.06470422535211266,0.2996571428571428,0.18210270270270268,0.06730866141732285,0.0734526315789474,0.11976986301369862,0.1660792063492063,0.10112538461538462,0.055889370629370626,0.04235210526315789,0.051068231292517016,0.004684955752212394,0.04743829787234045,0.2973836842105263,0.04035187969924811,0.03941967213114755,0.04124516129032258,0.0,0.13844842105263158,1.0648,0.0,0.03872190361445785,0.1070544827586207,0.05994626865671641,0.9992375885714286,0.0937211214953271,0.15617647058823528,0.12052000000000002,0.40376190476190477,0.5096700000000001,0.038388235294117654,0.0,0.08814461538461538,0.009325581395348781,0.0841147169811321,0.14101384615384618,0.04653952380952381,0.048898901098901104,0.1943050549450549
|
| 19 |
+
Agurin-EUW,euw,"Fri, Jan 3, 2025 9:59 PM",Wukong,15,red,1,23.2,10,3,4,4.67,0.54,1.38,203,8.8,2,yuqi #golem,Galio,Mein Königreich #917n3,Sylas,batubabaHOPPALA #HOPPA,Varus,MORG3NSHTERN #EUW,Rakan,KOI Spooder #1352,Rumble,mikusik998 #gaz,Bel'Veth,RKR #123,Viktor,supershy #jblss,Ashe,Drututts Lisp #EUW,Gragas,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0,0.11383934426229508,0.32318367346938776,0.2159478260869565,0.003040336134453781,0.07462158415841585,0.010881818181818038,0.0001757142857142885,0.024356026490066237,0.020584932515337426,0.11887238095238094,0.0,0.060601764705882355,0.09048000000000003,0.11204658536585367,0.28042,0.0,0.14949,0.14558326278659614,0.09564000000000002,0.06285470085470087,0.1776823529411764,0.25218095238095234,0.029494444444444448,0.0789936507936508,0.16823999999999997,0.0,0.2994142857142857,0.10848695652173915,0.0,0.20505185185185193,1.5788843958188155,0.2125009523809524,0.6752314285714287,0.0,0.0052499999999999995,0.037664415584415585,0.0,0.07816271186440678,0.16033894736842105,0.2668461538461539,0.0,0.49085,0.10883700000000002,0.013109090909090916,0.0241679746835443,0.25233,0.0,0.2964923076923078,0.049657674418604664,0.13181290322580644,1.1895999258252101,0.1085672727272727,0.5364771428571429,0.6668666666666667,0.2841600000000001,0.37839999999999996,0.287661935483871,0.0953066666666667,0.3600173828571429,0.0,0.02140645161290322,0.0,0.03609285714285714,0.03137087378640775,0.07952651162790698,1.1184574571428572,0.09357652173913049,0.03188603773584906,0.05807114093959731,0.0,0.5258000000000002,0.12630055555555558,0.08244909090909093,0.10284166666666668,0.1480488311688312,0.17259999999999998,0.26270000000000004,0.0,0.01380975609756098,0.2749276595744681,0.04587567567567568,0.03926380165289256,0.11078039215686274,0.02524102564102564,0.0,0.026839006211180128,0.18164927536231884,0.0,0.2593822222222223,0.2888510229218329,0.09398000000000001,0.0,0.3908067906921944,0.0303308108108108,0.0464123076923077,0.15542328358208957,0.028084931506849327,0.1673054237288136,0.3205411764705883,0.0,0.07963456790123458,0.011732048192771086,0.0,0.03812181818181819,0.023729927007299263,0.2623725,0.06751833333333335,0.19474545454545455,0.0,0.0531241379310345,0.0,0.10606382978723405,0.03868266666666668,0.02798151079136691,0.15588760563380283,0.10673636363636366,0.07191428571428571,0.0,0.08626206896551725,0.259552051948052,0.05303217391304348,0.05372068965517241,0.068563125,0.0,0.12963842105263157,0.19873636363636363,0.06274568807339448,0.15544363636363637,0.0,0.19127272727272726,0.06470422535211266,0.2996571428571428,0.16389243243243243,0.06730866141732285,0.0734526315789474,0.11976986301369862,0.1660792063492063,0.10112538461538462,0.055889370629370626,0.04235210526315789,0.051068231292517016,0.004684955752212394,0.04743829787234045,0.0,0.04035187969924811,0.03941967213114755,0.04124516129032258,0.0,0.13844842105263158,0.95832,0.0,0.043024337349397604,0.11894942528735633,0.05994626865671641,0.9992375885714286,0.0843490093457944,0.15617647058823528,0.13391111111111112,0.40376190476190477,0.5096700000000001,0.038388235294117654,0.0,0.08814461538461538,0.009325581395348781,0.0841147169811321,0.12691246153846156,0.04653952380952381,0.048898901098901104,0.1943050549450549
|
| 20 |
+
Agurin-EUW,euw,"Fri, Jan 3, 2025 9:13 PM",Elise,16,red,1,28.07,8,2,12,10.0,0.51,0.75,207,7.4,1,washed úp #EUW,Gwen,SMRADOCH RANDOM #EUW,Ziggs,RKR #123,Ashe,Frank Castle #2610,Blitzcrank,Shourdy #EUW,K'Sante,Purple Place #Moe,Rengar,WORLDS2025 #AIS,Irelia,Odysseus #131,Taliyah,Sergeant Sona #KJP,Sona,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0,0.10245540983606558,0.32318367346938776,0.19435304347826085,0.003040336134453781,0.07462158415841585,0.009793636363636234,0.0001757142857142885,0.02706225165562915,0.022872147239263806,0.11887238095238094,0.0,0.060601764705882355,0.09048000000000003,0.11204658536585367,0.28042,0.12472359550561801,0.0,0.13102493650793653,0.09564000000000002,0.06285470085470087,0.1776823529411764,0.25218095238095234,0.029494444444444448,0.0789936507936508,0.1869333333333333,0.0,0.2994142857142857,0.10848695652173915,0.0,0.18454666666666675,1.5788843958188155,0.19125085714285717,0.6752314285714287,0.0,0.0052499999999999995,0.037664415584415585,0.2163641025641026,0.07816271186440678,0.16033894736842105,0.2668461538461539,0.2517690476190476,0.49085,0.0,0.013109090909090916,0.0241679746835443,0.28036666666666665,0.0,0.0,0.049657674418604664,0.1186316129032258,1.3217776953613445,0.1085672727272727,0.4828294285714286,0.6668666666666667,0.3157333333333334,0.0,0.287661935483871,0.0953066666666667,0.3600173828571429,0.0,0.02140645161290322,0.0,0.03609285714285714,0.03137087378640775,0.07952651162790698,1.1184574571428572,0.09357652173913049,0.03188603773584906,0.05807114093959731,0.0,0.5258000000000002,0.12630055555555558,0.08244909090909093,0.10284166666666668,0.1480488311688312,0.17259999999999998,0.23643000000000006,0.0,0.01380975609756098,0.2749276595744681,0.04587567567567568,0.03926380165289256,0.11078039215686274,0.02524102564102564,0.0,0.026839006211180128,0.18164927536231884,0.0,0.2593822222222223,0.2599659206296496,0.09398000000000001,0.0,0.3908067906921944,0.03370090090090089,0.0464123076923077,0.15542328358208957,0.028084931506849327,0.1673054237288136,0.28848705882352943,0.0,0.07963456790123458,0.011732048192771086,0.2609019310344827,0.03812181818181819,0.023729927007299263,0.2623725,0.06751833333333335,0.19474545454545455,0.0,0.0531241379310345,0.15295135135135138,0.08485106382978724,0.04298074074074075,0.02798151079136691,0.15588760563380283,0.10673636363636366,0.07191428571428571,0.0,0.08626206896551725,0.28839116883116883,0.05303217391304348,0.05372068965517241,0.07618125,0.0,0.12963842105263157,0.0,0.06274568807339448,0.13989927272727273,0.41572000000000003,0.19127272727272726,0.06470422535211266,0.0,0.16389243243243243,0.06730866141732285,0.0734526315789474,0.11976986301369862,0.1660792063492063,0.10112538461538462,0.055889370629370626,0.04235210526315789,0.051068231292517016,0.004684955752212394,0.04743829787234045,0.2973836842105263,0.04035187969924811,0.03941967213114755,0.04124516129032258,0.0,0.13844842105263158,1.0648,0.24678,0.043024337349397604,0.11894942528735633,0.05994626865671641,0.9992375885714286,0.0937211214953271,0.15617647058823528,0.13391111111111112,0.3633857142857143,0.4587030000000001,0.038388235294117654,0.0,0.07933015384615384,0.009325581395348781,0.0841147169811321,0.0,0.04188557142857143,0.048898901098901104,0.17487454945054942
|
| 21 |
+
Agurin-EUW,euw,"Fri, Jan 3, 2025 8:38 PM",Wukong,12,red,0,21.68,3,5,7,2.0,0.48,0.67,141,6.5,2,e7c3c0fd cee3 4399 877b baf89c9f6f46 #EUW,Volibear,wymówkomat #escik,Ahri,Percy Magic #1234,Kalista,cross the edge #fear,Nautilus,ΑrchΦiend #666,Aatrox,Razørk Activoo #razzz,Xin Zhao,yebit #haha,Taliyah,RKR #123,Ashe,Shourdy #EUW,Sylas,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0,0.0,0.0,0.19435304347826085,0.003040336134453781,0.07462158415841585,0.010881818181818038,0.0001757142857142885,0.02706225165562915,0.022872147239263806,0.11887238095238094,0.0,0.060601764705882355,0.10053333333333336,0.11204658536585367,0.28042,0.12472359550561801,0.14949,0.14558326278659614,0.09564000000000002,0.06285470085470087,0.1776823529411764,0.25218095238095234,0.029494444444444448,0.0789936507936508,0.1869333333333333,0.0,0.2994142857142857,0.10848695652173915,0.0,0.20505185185185193,1.5788843958188155,0.19125085714285717,0.6752314285714287,0.0,0.0052499999999999995,0.037664415584415585,0.2163641025641026,0.07816271186440678,0.16033894736842105,0.2668461538461539,0.2517690476190476,0.49085,0.13604625,0.013109090909090916,0.0241679746835443,0.28036666666666665,0.0,0.2964923076923078,0.049657674418604664,0.13181290322580644,1.3217776953613445,0.1085672727272727,0.5364771428571429,0.6668666666666667,0.3157333333333334,0.37839999999999996,0.287661935483871,0.0,0.3600173828571429,0.0,0.02140645161290322,0.0,0.03609285714285714,0.03137087378640775,0.07952651162790698,1.1184574571428572,0.09357652173913049,0.03188603773584906,0.05807114093959731,0.0,0.5258000000000002,0.12630055555555558,0.08244909090909093,0.10284166666666668,0.1480488311688312,0.17259999999999998,0.23643000000000006,0.0,0.01380975609756098,0.2749276595744681,0.04587567567567568,0.03926380165289256,0.11078039215686274,0.02524102564102564,0.0,0.026839006211180128,0.18164927536231884,0.0,0.0,0.2599659206296496,0.09398000000000001,0.0,0.3908067906921944,0.03370090090090089,0.0464123076923077,0.15542328358208957,0.028084931506849327,0.1673054237288136,0.3205411764705883,0.0,0.07963456790123458,0.011732048192771086,0.2898910344827586,0.03812181818181819,0.023729927007299263,0.2623725,0.06751833333333335,0.19474545454545455,0.0,0.0531241379310345,0.15295135135135138,0.09545744680851065,0.04298074074074075,0.02798151079136691,0.15588760563380283,0.10673636363636366,0.07191428571428571,0.0,0.08626206896551725,0.28839116883116883,0.05303217391304348,0.05372068965517241,0.07618125,0.0,0.12963842105263157,0.19873636363636363,0.05647111926605503,0.15544363636363637,0.0,0.19127272727272726,0.06470422535211266,0.0,0.18210270270270268,0.06730866141732285,0.0734526315789474,0.11976986301369862,0.1660792063492063,0.10112538461538462,0.055889370629370626,0.04235210526315789,0.051068231292517016,0.004684955752212394,0.04743829787234045,0.2973836842105263,0.04035187969924811,0.03941967213114755,0.04124516129032258,0.0,0.13844842105263158,1.0648,0.2742,0.043024337349397604,0.0,0.05994626865671641,0.9992375885714286,0.0937211214953271,0.15617647058823528,0.0,0.3633857142857143,0.5096700000000001,0.038388235294117654,0.0,0.07933015384615384,0.008393023255813903,0.0841147169811321,0.14101384615384618,0.04653952380952381,0.048898901098901104,0.17487454945054942
|
util/data/meta_stats.csv
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
rank,champion,tier,role,win_rate,pick_rate,ban_rate,counter1,counter2,counter3
|
| 2 |
+
1,Irelia,1,top,0.5186,0.0576,0.0956,Warwick,Volibear,Zac
|
| 3 |
+
2,Maokai,1,top,0.5162,0.0622,0.032799999999999996,Heimerdinger,Olaf,Mordekaiser
|
| 4 |
+
3,Warwick,1,top,0.5251,0.0305,0.08380000000000001,Cassiopeia,Teemo,Heimerdinger
|
| 5 |
+
4,Aatrox,1,top,0.5024000000000001,0.0855,0.1023,Cassiopeia,Warwick,Irelia
|
| 6 |
+
5,Riven,1,top,0.5138,0.052000000000000005,0.027000000000000003,Quinn,Maokai,Kennen
|
| 7 |
+
6,Gragas,1,top,0.5123,0.0492,0.0229,Cho'Gath,Vayne,Maokai
|
| 8 |
+
7,Darius,1,top,0.5056,0.0623,0.1333,Cassiopeia,Teemo,Wukong
|
| 9 |
+
8,Malphite,1,top,0.5131,0.044199999999999996,0.0617,Maokai,Dr. Mundo,Tahm Kench
|
| 10 |
+
9,Volibear,1,top,0.509,0.0489,0.0338,Quinn,Teemo,Kennen
|
| 11 |
+
10,Mordekaiser,2,top,0.5064,0.048,0.0575,Cassiopeia,Heimerdinger,Vayne
|
| 12 |
+
11,Cho'Gath,2,top,0.5186999999999999,0.028399999999999998,0.0044,Olaf,Ornn,Dr. Mundo
|
| 13 |
+
12,Ornn,2,top,0.5117,0.0388,0.005600000000000001,Warwick,Tryndamere,Dr. Mundo
|
| 14 |
+
13,Camille,2,top,0.5105,0.04019999999999999,0.0189,Zac,Ryze,Teemo
|
| 15 |
+
14,Renekton,2,top,0.4997,0.0588,0.048499999999999995,Cassiopeia,Teemo,Warwick
|
| 16 |
+
15,Tahm Kench,2,top,0.5106,0.0329,0.040999999999999995,Wukong,Heimerdinger,Singed
|
| 17 |
+
16,Dr. Mundo,2,top,0.5082,0.037000000000000005,0.0195,Riven,Udyr,Warwick
|
| 18 |
+
17,Teemo,2,top,0.515,0.0255,0.033,Ryze,Olaf,Cassiopeia
|
| 19 |
+
18,Sett,2,top,0.5025999999999999,0.0444,0.0088,Zac,Warwick,Volibear
|
| 20 |
+
19,Shen,2,top,0.5103,0.0313,0.0038,Cassiopeia,Teemo,Tryndamere
|
| 21 |
+
20,K'Sante,2,top,0.48979999999999996,0.0704,0.07730000000000001,Singed,Kayle,Kennen
|
| 22 |
+
21,Fiora,2,top,0.5038,0.0366,0.0584,Quinn,Ryze,Warwick
|
| 23 |
+
22,Kayle,2,top,0.5155,0.0217,0.006500000000000001,Ryze,Malphite,Cassiopeia
|
| 24 |
+
23,Gnar,2,top,0.4986,0.0455,0.0195,Quinn,Vladimir,Malphite
|
| 25 |
+
24,Ambessa,3,top,0.4866,0.054299999999999994,0.2948,Warwick,Camille,Irelia
|
| 26 |
+
25,Poppy,3,top,0.5157,0.0181,0.0285,Warwick,Cassiopeia,Darius
|
| 27 |
+
26,Gwen,3,top,0.5065999999999999,0.0288,0.0245,Warwick,Singed,Viktor
|
| 28 |
+
27,Viktor,3,top,0.4988,0.0178,0.0348,Tryndamere,Kled,Irelia
|
| 29 |
+
28,Vladimir,3,top,0.5093,0.022400000000000003,0.0182,Cassiopeia,Nasus,Akali
|
| 30 |
+
29,Urgot,3,top,0.511,0.0217,0.0036,Cassiopeia,Aurora,Olaf
|
| 31 |
+
30,Sion,3,top,0.4982,0.0377,0.004699999999999999,Riven,Dr. Mundo,Gwen
|
| 32 |
+
31,Trundle,3,top,0.5136999999999999,0.018600000000000002,0.0042,Heimerdinger,Zac,Quinn
|
| 33 |
+
32,Garen,3,top,0.494,0.043899999999999995,0.0212,Camille,Maokai,Kayle
|
| 34 |
+
33,Singed,3,top,0.5135000000000001,0.0177,0.0025,Vayne,Trundle,Ryze
|
| 35 |
+
34,Jax,3,top,0.4892,0.05,0.0716,Cassiopeia,Heimerdinger,Vladimir
|
| 36 |
+
35,Olaf,3,top,0.5164,0.015300000000000001,0.0095,Vayne,Heimerdinger,Kayle
|
| 37 |
+
36,Tryndamere,3,top,0.5062,0.0231,0.0134,Warwick,Volibear,Cho'Gath
|
| 38 |
+
37,Cassiopeia,3,top,0.5281,0.0075,0.0045000000000000005,Kled,Garen,Udyr
|
| 39 |
+
38,Yorick,3,top,0.5009,0.0258,0.0262,Warwick,Kayle,Tryndamere
|
| 40 |
+
39,Kennen,3,top,0.5122,0.015300000000000001,0.0087,Udyr,Galio,Dr. Mundo
|
| 41 |
+
40,Zac,3,top,0.517,0.011699999999999999,0.0069,Galio,Volibear,Riven
|
| 42 |
+
41,Nasus,3,top,0.4988,0.027000000000000003,0.0321,Ryze,Zac,Heimerdinger
|
| 43 |
+
42,Jayce,3,top,0.4826,0.054900000000000004,0.0172,Quinn,Tahm Kench,Irelia
|
| 44 |
+
43,Gangplank,3,top,0.49420000000000003,0.0322,0.011899999999999999,Quinn,Cho'Gath,Tahm Kench
|
| 45 |
+
44,Pantheon,3,top,0.5027,0.0206,0.0048,Heimerdinger,Maokai,Malphite
|
| 46 |
+
45,Ryze,3,top,0.5169,0.0108,0.0013,Zac,Irelia,Pantheon
|
| 47 |
+
46,Kled,3,top,0.5111,0.014199999999999999,0.005,Camille,Akali,Riven
|
| 48 |
+
47,Wukong,3,top,0.513,0.0118,0.005,Cassiopeia,Singed,Ryze
|
| 49 |
+
48,Yone,3,top,0.4765,0.055099999999999996,0.0432,Irelia,Riven,Wukong
|
| 50 |
+
49,Illaoi,4,top,0.494,0.0235,0.0508,Heimerdinger,Kayle,Teemo
|
| 51 |
+
50,Aurora,4,top,0.4936,0.0191,0.0414,Irelia,Akali,Wukong
|
| 52 |
+
51,Yasuo,4,top,0.485,0.023799999999999998,0.0385,Singed,Cassiopeia,Riven
|
| 53 |
+
52,Heimerdinger,4,top,0.5097999999999999,0.009300000000000001,0.0044,Galio,Ryze,Cassiopeia
|
| 54 |
+
53,Quinn,4,top,0.512,0.0076,0.0024,Olaf,Malphite,Maokai
|
| 55 |
+
54,Akali,4,top,0.4924,0.015600000000000001,0.019299999999999998,Galio,Poppy,Maokai
|
| 56 |
+
55,Sylas,4,top,0.4874,0.0159,0.0152,Urgot,Poppy,Kled
|
| 57 |
+
1,Warwick,1,jungle,0.5162,0.0556,0.1527,Rek'Sai,Ivern,Nunu & Willump
|
| 58 |
+
2,Wukong,1,jungle,0.5143,0.066,0.0281,Zyra,Karthus,Ivern
|
| 59 |
+
3,Viego,1,jungle,0.5003,0.16820000000000002,0.1338,Rammus,Qiyana,Bel'Veth
|
| 60 |
+
4,Nocturne,1,jungle,0.5117,0.0575,0.0784,Udyr,Gwen,Wukong
|
| 61 |
+
5,Graves,1,jungle,0.5017,0.1361,0.19190000000000002,Gwen,Rammus,Qiyana
|
| 62 |
+
6,Kayn,1,jungle,0.509,0.0733,0.0512,Kindred,Fiddlesticks,Wukong
|
| 63 |
+
7,Kha'Zix,1,jungle,0.5083,0.0729,0.0632,Fiddlesticks,Zyra,Shaco
|
| 64 |
+
8,Shaco,1,jungle,0.5115,0.0466,0.12990000000000002,Briar,Karthus,Graves
|
| 65 |
+
9,Nunu & Willump,1,jungle,0.5162,0.0333,0.0069,Qiyana,Pantheon,Bel'Veth
|
| 66 |
+
10,Lee Sin,1,jungle,0.4966,0.1702,0.1137,Shaco,Rek'Sai,Warwick
|
| 67 |
+
11,Ekko,1,jungle,0.509,0.055,0.0103,Pantheon,Ivern,Rengar
|
| 68 |
+
12,Elise,2,jungle,0.5056,0.0487,0.055099999999999996,Nocturne,Qiyana,Shaco
|
| 69 |
+
13,Bel'Veth,2,jungle,0.5117,0.026099999999999998,0.0444,Sejuani,Ivern,Rek'Sai
|
| 70 |
+
14,Jarvan IV,2,jungle,0.5036999999999999,0.0558,0.014199999999999999,Gwen,Jax,Bel'Veth
|
| 71 |
+
15,Xin Zhao,2,jungle,0.5078,0.0359,0.0053,Pantheon,Jax,Udyr
|
| 72 |
+
16,Fiddlesticks,2,jungle,0.5114,0.0246,0.0137,Nunu & Willump,Rammus,Shaco
|
| 73 |
+
17,Skarner,2,jungle,0.5056,0.0393,0.0883,Lillia,Gwen,Udyr
|
| 74 |
+
18,Hecarim,2,jungle,0.5039,0.0466,0.0327,Ivern,Volibear,Udyr
|
| 75 |
+
19,Briar,2,jungle,0.5093,0.0258,0.0252,Pantheon,Jax,Teemo
|
| 76 |
+
20,Diana,2,jungle,0.5025999999999999,0.0464,0.0139,Warwick,Qiyana,Dr. Mundo
|
| 77 |
+
21,Rek'Sai,2,jungle,0.5138,0.0158,0.006500000000000001,Dr. Mundo,Karthus,Volibear
|
| 78 |
+
22,Udyr,2,jungle,0.5093,0.0233,0.0242,Qiyana,Briar,Poppy
|
| 79 |
+
23,Master Yi,2,jungle,0.5017,0.0454,0.0704,Shaco,Elise,Warwick
|
| 80 |
+
24,Karthus,2,jungle,0.5064,0.028300000000000002,0.059500000000000004,Shyvana,Ivern,Volibear
|
| 81 |
+
25,Kindred,3,jungle,0.5008,0.0392,0.029300000000000003,Ivern,Qiyana,Elise
|
| 82 |
+
26,Vi,3,jungle,0.4951,0.0647,0.0171,Dr. Mundo,Rek'Sai,Wukong
|
| 83 |
+
27,Ivern,3,jungle,0.5114,0.0131,0.0051,Amumu,Briar,Nunu & Willump
|
| 84 |
+
28,Gwen,3,jungle,0.5114,0.0115,0.0098,Bel'Veth,Master Yi,Qiyana
|
| 85 |
+
29,Talon,3,jungle,0.5046,0.0215,0.0066,Bel'Veth,Pantheon,Rengar
|
| 86 |
+
30,Rammus,3,jungle,0.5081,0.0139,0.0282,Pantheon,Lillia,Dr. Mundo
|
| 87 |
+
31,Volibear,3,jungle,0.5033,0.0197,0.013600000000000001,Jax,Ivern,Pantheon
|
| 88 |
+
32,Zyra,3,jungle,0.5047999999999999,0.015,0.009000000000000001,Gwen,Karthus,Rengar
|
| 89 |
+
33,Amumu,3,jungle,0.4988,0.0273,0.0154,Zed,Pantheon,Karthus
|
| 90 |
+
34,Evelynn,3,jungle,0.5008,0.0217,0.0329,Taliyah,Briar,Teemo
|
| 91 |
+
35,Nidalee,3,jungle,0.4927,0.0449,0.0321,Rammus,Briar,Nocturne
|
| 92 |
+
36,Taliyah,3,jungle,0.5034000000000001,0.016200000000000003,0.0045000000000000005,Dr. Mundo,Zed,Qiyana
|
| 93 |
+
37,Zac,3,jungle,0.4949,0.0346,0.0206,Ivern,Qiyana,Taliyah
|
| 94 |
+
38,Shyvana,3,jungle,0.5039,0.0148,0.003,Nunu & Willump,Bel'Veth,Udyr
|
| 95 |
+
39,Lillia,3,jungle,0.49520000000000003,0.033,0.0326,Qiyana,Talon,Briar
|
| 96 |
+
40,Zed,3,jungle,0.5005,0.014199999999999999,0.0305,Dr. Mundo,Xin Zhao,Master Yi
|
| 97 |
+
41,Rengar,3,jungle,0.4925,0.0317,0.0484,Rammus,Gwen,Jax
|
| 98 |
+
42,Pantheon,3,jungle,0.5055,0.0072,0.0016,Dr. Mundo,Lillia,Wukong
|
| 99 |
+
43,Qiyana,4,jungle,0.5056,0.0063,0.0015,Volibear,Skarner,Shaco
|
| 100 |
+
44,Poppy,4,jungle,0.4965,0.0088,0.013999999999999999,Rammus,Warwick,Shaco
|
| 101 |
+
45,Gragas,4,jungle,0.4843,0.0288,0.0134,Poppy,Nocturne,Skarner
|
| 102 |
+
46,Sejuani,4,jungle,0.484,0.0248,0.0029,Qiyana,Rek'Sai,Dr. Mundo
|
| 103 |
+
47,Jax,4,jungle,0.49670000000000003,0.005600000000000001,0.008100000000000001,Amumu,Udyr,Nunu & Willump
|
| 104 |
+
48,Dr. Mundo,4,jungle,0.4962,0.0051,0.0027,Qiyana,Ivern,Gwen
|
| 105 |
+
49,Teemo,4,jungle,0.48710000000000003,0.0111,0.0144,Qiyana,Zyra,Gwen
|
| 106 |
+
50,Ambessa,5,jungle,0.43770000000000003,0.0096,0.052199999999999996,Rammus,Master Yi,Rek'Sai
|
| 107 |
+
1,Viktor,1,mid,0.5057,0.1827,0.3603,Akali,Ekko,Xerath
|
| 108 |
+
2,Vex,1,mid,0.5247999999999999,0.0337,0.0524,Cho'Gath,Annie,Corki
|
| 109 |
+
3,Ahri,1,mid,0.5082,0.0971,0.0415,Cho'Gath,Akshan,Cassiopeia
|
| 110 |
+
4,Sylas,2,mid,0.4999,0.1033,0.099,Taliyah,Garen,Vex
|
| 111 |
+
5,Galio,2,mid,0.5094,0.0525,0.0364,Garen,Swain,Lux
|
| 112 |
+
6,Anivia,2,mid,0.5211,0.0216,0.0147,Gragas,Garen,Neeko
|
| 113 |
+
7,Irelia,2,mid,0.5115999999999999,0.037200000000000004,0.0622,Vex,Malphite,Galio
|
| 114 |
+
8,Akali,2,mid,0.503,0.07200000000000001,0.08960000000000001,Twisted Fate,Akshan,Taliyah
|
| 115 |
+
9,Katarina,2,mid,0.5039,0.0616,0.067,Kayle,Malphite,Cho'Gath
|
| 116 |
+
10,Lux,2,mid,0.5093,0.0394,0.015700000000000002,Naafiri,Aurelion Sol,Taliyah
|
| 117 |
+
11,Taliyah,2,mid,0.5206000000000001,0.0177,0.0049,Annie,Kayle,Fizz
|
| 118 |
+
12,Hwei,2,mid,0.503,0.0587,0.0553,Malphite,Katarina,Talon
|
| 119 |
+
13,Syndra,2,mid,0.5013000000000001,0.061,0.038,Ekko,Katarina,Aurelion Sol
|
| 120 |
+
14,Talon,2,mid,0.5112,0.0287,0.0089,Malphite,Garen,Kayle
|
| 121 |
+
15,Aurora,2,mid,0.5015,0.0518,0.11259999999999999,Vel'Koz,Vex,Gragas
|
| 122 |
+
16,Lissandra,2,mid,0.5096,0.0316,0.014499999999999999,Cho'Gath,Corki,Lux
|
| 123 |
+
17,Malzahar,2,mid,0.5067,0.0368,0.0359,Kayle,Garen,Swain
|
| 124 |
+
18,Akshan,2,mid,0.5127,0.0227,0.0207,Anivia,Kayle,Annie
|
| 125 |
+
19,Qiyana,2,mid,0.5132,0.022000000000000002,0.0054,Neeko,Garen,Vel'Koz
|
| 126 |
+
20,Veigar,2,mid,0.5092,0.0285,0.005699999999999999,Cassiopeia,Naafiri,Xerath
|
| 127 |
+
21,Ekko,2,mid,0.5074000000000001,0.030899999999999997,0.0058,Garen,Qiyana,Kassadin
|
| 128 |
+
22,Cassiopeia,2,mid,0.5166,0.015700000000000002,0.0096,Neeko,Talon,Vel'Koz
|
| 129 |
+
23,Vel'Koz,2,mid,0.5186999999999999,0.013300000000000001,0.0028000000000000004,Naafiri,Ziggs,Katarina
|
| 130 |
+
24,Xerath,2,mid,0.5059,0.0319,0.0253,Garen,Naafiri,Fizz
|
| 131 |
+
25,Yasuo,2,mid,0.4921,0.077,0.1255,Annie,Taliyah,Vex
|
| 132 |
+
26,Diana,2,mid,0.5091,0.024700000000000003,0.0074,Pantheon,Neeko,Brand
|
| 133 |
+
27,Ryze,2,mid,0.5083,0.0271,0.0033,Cassiopeia,Neeko,Taliyah
|
| 134 |
+
28,Zoe,2,mid,0.5088,0.0241,0.0102,Naafiri,Garen,Malzahar
|
| 135 |
+
29,Zed,2,mid,0.4941,0.059000000000000004,0.1274,Kayle,Cho'Gath,Akshan
|
| 136 |
+
30,Kassadin,2,mid,0.5061,0.0265,0.031,Brand,Naafiri,Cho'Gath
|
| 137 |
+
31,Garen,3,mid,0.5259,0.0053,0.0026,Annie,Ryze,Aurelion Sol
|
| 138 |
+
32,Vladimir,3,mid,0.5017,0.0326,0.026699999999999998,Anivia,Cho'Gath,Vel'Koz
|
| 139 |
+
33,Aurelion Sol,3,mid,0.5081,0.019799999999999998,0.0070999999999999995,Vel'Koz,Zed,Fizz
|
| 140 |
+
34,Fizz,3,mid,0.5024000000000001,0.0297,0.0335,Akali,Garen,Neeko
|
| 141 |
+
35,Naafiri,3,mid,0.5157,0.01,0.0040999999999999995,Cho'Gath,Neeko,Kayle
|
| 142 |
+
36,Neeko,3,mid,0.5201,0.0063,0.002,Taliyah,Lissandra,Vladimir
|
| 143 |
+
37,Twisted Fate,3,mid,0.5003,0.026600000000000002,0.0023,Naafiri,Neeko,Diana
|
| 144 |
+
38,Orianna,3,mid,0.49369999999999997,0.0429,0.0079,Ziggs,Garen,Cho'Gath
|
| 145 |
+
39,Annie,3,mid,0.512,0.0102,0.0016,Neeko,Gragas,Talon
|
| 146 |
+
40,Gragas,3,mid,0.5106,0.0102,0.0048,Cho'Gath,Vel'Koz,Naafiri
|
| 147 |
+
41,Yone,3,mid,0.48229999999999995,0.0746,0.0588,Cho'Gath,Vex,Akshan
|
| 148 |
+
42,Cho'Gath,3,mid,0.5186,0.0051,0.0008,Ziggs,Vel'Koz,Qiyana
|
| 149 |
+
43,LeBlanc,3,mid,0.48700000000000004,0.0484,0.17420000000000002,Garen,Naafiri,Pantheon
|
| 150 |
+
44,Malphite,3,mid,0.5108,0.0076,0.010700000000000001,Cassiopeia,Lissandra,Sylas
|
| 151 |
+
45,Kayle,3,mid,0.5129,0.006500000000000001,0.0019,Neeko,Annie,Corki
|
| 152 |
+
46,Swain,3,mid,0.4966,0.0177,0.0105,Kayle,Cassiopeia,Xerath
|
| 153 |
+
47,Pantheon,4,mid,0.5075,0.0066,0.0015,Vel'Koz,Swain,Anivia
|
| 154 |
+
48,Ambessa,4,mid,0.4959,0.0069,0.038,Cho'Gath,Corki,Malphite
|
| 155 |
+
49,Azir,4,mid,0.48590000000000005,0.0222,0.003,Annie,Kayle,Neeko
|
| 156 |
+
50,Jayce,4,mid,0.4842,0.0213,0.0067,Naafiri,Brand,Vel'Koz
|
| 157 |
+
51,Brand,4,mid,0.5028,0.0051,0.0026,Garen,Anivia,Irelia
|
| 158 |
+
52,Ziggs,4,mid,0.4899,0.0066,0.0017000000000000001,Brand,Neeko,Garen
|
| 159 |
+
53,Corki,4,mid,0.4808,0.0096,0.0089,Garen,Cho'Gath,Gragas
|
| 160 |
+
54,Smolder,5,mid,0.4278,0.0166,0.0068000000000000005,Neeko,Diana,Kayle
|
| 161 |
+
1,Viktor,1,adc,0.5273,0.022099999999999998,0.044000000000000004,Vayne,Karthus,Yasuo
|
| 162 |
+
2,Nilah,1,adc,0.5359,0.018600000000000002,0.035,Veigar,Hwei,Brand
|
| 163 |
+
3,Jinx,1,adc,0.5055,0.2144,0.0426,Lux,Seraphine,Viktor
|
| 164 |
+
4,Miss Fortune,1,adc,0.5194,0.0662,0.0068000000000000005,Karthus,Seraphine,Yasuo
|
| 165 |
+
5,Ashe,1,adc,0.5045000000000001,0.16219999999999998,0.182,Karthus,Lux,Nilah
|
| 166 |
+
6,Kog'Maw,2,adc,0.5257999999999999,0.0256,0.0172,Karthus,Seraphine,Ziggs
|
| 167 |
+
7,Jhin,2,adc,0.5006,0.1929,0.038,Yasuo,Nilah,Seraphine
|
| 168 |
+
8,Vayne,2,adc,0.5156000000000001,0.0472,0.026099999999999998,Nilah,Veigar,Miss Fortune
|
| 169 |
+
9,Caitlyn,2,adc,0.4954,0.1984,0.2798,Lux,Seraphine,Brand
|
| 170 |
+
10,Corki,2,adc,0.5082,0.0674,0.063,Veigar,Kog'Maw,Seraphine
|
| 171 |
+
11,Karthus,2,adc,0.5359,0.0059,0.0127,Nilah,Hwei,Vayne
|
| 172 |
+
12,Seraphine,2,adc,0.5292,0.0101,0.0022,Veigar,Brand,Karthus
|
| 173 |
+
13,Sivir,2,adc,0.5102,0.049699999999999994,0.009300000000000001,Viktor,Seraphine,Kog'Maw
|
| 174 |
+
14,Draven,2,adc,0.5057,0.062400000000000004,0.2262,Lux,Seraphine,Swain
|
| 175 |
+
15,Lux,2,adc,0.5274,0.009899999999999999,0.0039000000000000003,Karthus,Ziggs,Lucian
|
| 176 |
+
16,Hwei,2,adc,0.5232,0.013500000000000002,0.0128,Viktor,Brand,Sivir
|
| 177 |
+
17,Ezreal,3,adc,0.4907,0.1653,0.0509,Karthus,Nilah,Yasuo
|
| 178 |
+
18,Ziggs,3,adc,0.5165,0.020499999999999997,0.0053,Yasuo,Karthus,Viktor
|
| 179 |
+
19,Xayah,3,adc,0.5086999999999999,0.0398,0.0058,Viktor,Miss Fortune,Kog'Maw
|
| 180 |
+
20,Lucian,3,adc,0.5034000000000001,0.0603,0.0089,Karthus,Brand,Nilah
|
| 181 |
+
21,Yasuo,3,adc,0.519,0.0106,0.0174,Nilah,Karthus,Corki
|
| 182 |
+
22,Brand,4,adc,0.5242,0.0078000000000000005,0.0040999999999999995,Karthus,Lux,Yasuo
|
| 183 |
+
23,Swain,4,adc,0.514,0.0155,0.009300000000000001,Veigar,Vayne,Lux
|
| 184 |
+
24,Kai'Sa,4,adc,0.4892,0.1195,0.017,Karthus,Nilah,Veigar
|
| 185 |
+
25,Tristana,4,adc,0.5049,0.0342,0.0037,Karthus,Yasuo,Corki
|
| 186 |
+
26,Varus,4,adc,0.4951,0.0719,0.0111,Hwei,Ziggs,Karthus
|
| 187 |
+
27,Veigar,4,adc,0.5214,0.0067,0.0013,Karthus,Lux,Ziggs
|
| 188 |
+
28,Smolder,4,adc,0.4941,0.061900000000000004,0.025699999999999997,Brand,Lux,Yasuo
|
| 189 |
+
29,Twitch,4,adc,0.5011,0.0323,0.0141,Karthus,Nilah,Yasuo
|
| 190 |
+
30,Zeri,5,adc,0.4985,0.0285,0.003,Karthus,Brand,Swain
|
| 191 |
+
31,Samira,5,adc,0.49219999999999997,0.034300000000000004,0.052199999999999996,Veigar,Viktor,Nilah
|
| 192 |
+
32,Aphelios,5,adc,0.4851,0.0452,0.0070999999999999995,Brand,Nilah,Yasuo
|
| 193 |
+
33,Kalista,5,adc,0.4828,0.0209,0.0054,Kog'Maw,Brand,Miss Fortune
|
| 194 |
+
1,Lulu,1,support,0.5163,0.1495,0.1777,Fiddlesticks,Tahm Kench,Elise
|
| 195 |
+
2,Nami,1,support,0.5131,0.10339999999999999,0.0101,Fiddlesticks,Elise,Galio
|
| 196 |
+
3,Janna,2,support,0.5168,0.060700000000000004,0.0213,Zoe,Blitzcrank,Sona
|
| 197 |
+
4,Tahm Kench,2,support,0.5175,0.0508,0.06269999999999999,Elise,Janna,Taric
|
| 198 |
+
5,Thresh,2,support,0.5049,0.1288,0.0546,Elise,Taric,Vel'Koz
|
| 199 |
+
6,Poppy,2,support,0.5196999999999999,0.034300000000000004,0.0535,Taric,Elise,Sona
|
| 200 |
+
7,Braum,3,support,0.5111,0.062,0.054400000000000004,Senna,Vel'Koz,Taric
|
| 201 |
+
8,Pyke,3,support,0.5035000000000001,0.0806,0.3077,Elise,Maokai,LeBlanc
|
| 202 |
+
9,Senna,3,support,0.5104,0.0594,0.017,Elise,Vel'Koz,Neeko
|
| 203 |
+
10,Taric,3,support,0.527,0.0174,0.0036,Fiddlesticks,Soraka,Janna
|
| 204 |
+
11,Rell,3,support,0.5133,0.0464,0.0232,Taric,Janna,Poppy
|
| 205 |
+
12,Soraka,3,support,0.5122,0.049100000000000005,0.018600000000000002,Elise,Galio,Sylas
|
| 206 |
+
13,Karma,3,support,0.5018,0.0965,0.0398,Fiddlesticks,Maokai,Pyke
|
| 207 |
+
14,Sona,3,support,0.5184000000000001,0.0263,0.0012,Zac,Elise,Camille
|
| 208 |
+
15,Vel'Koz,3,support,0.5149,0.030600000000000002,0.0064,Camille,Elise,LeBlanc
|
| 209 |
+
16,Bard,3,support,0.5091,0.044199999999999996,0.0060999999999999995,Elise,Fiddlesticks,Tahm Kench
|
| 210 |
+
17,Milio,3,support,0.5046,0.0593,0.0326,Maokai,Tahm Kench,Blitzcrank
|
| 211 |
+
18,Elise,3,support,0.5292,0.0077,0.0086,Galio,Neeko,Pantheon
|
| 212 |
+
19,Maokai,3,support,0.5118,0.027999999999999997,0.0146,Taric,Galio,Elise
|
| 213 |
+
20,Leona,4,support,0.49829999999999997,0.0572,0.0496,Galio,Janna,Taric
|
| 214 |
+
21,Zilean,4,support,0.5074000000000001,0.028900000000000002,0.008100000000000001,Galio,LeBlanc,Sona
|
| 215 |
+
22,Blitzcrank,4,support,0.49560000000000004,0.0604,0.1734,Elise,Taric,Braum
|
| 216 |
+
23,Lux,4,support,0.4925,0.0703,0.0275,Shen,Poppy,LeBlanc
|
| 217 |
+
24,Zyra,4,support,0.5045000000000001,0.030899999999999997,0.0182,Taric,Sylas,Tahm Kench
|
| 218 |
+
25,Xerath,4,support,0.5003,0.039,0.0304,Elise,Shen,Zoe
|
| 219 |
+
26,Rakan,4,support,0.4982,0.046900000000000004,0.0063,Sona,Elise,Janna
|
| 220 |
+
27,Nautilus,4,support,0.48840000000000006,0.0814,0.12380000000000001,Taric,Renata Glasc,Rell
|
| 221 |
+
28,Morgana,4,support,0.4997,0.0353,0.1139,Shaco,Sona,Xerath
|
| 222 |
+
29,Seraphine,4,support,0.4984,0.0374,0.008,Elise,Vel'Koz,Poppy
|
| 223 |
+
30,Yuumi,4,support,0.4888,0.0588,0.07200000000000001,Taric,Rell,Braum
|
| 224 |
+
31,Neeko,4,support,0.5045000000000001,0.0196,0.0063,Fiddlesticks,Camille,Janna
|
| 225 |
+
32,Pantheon,4,support,0.5011,0.019299999999999998,0.0044,Taric,LeBlanc,Braum
|
| 226 |
+
33,Alistar,4,support,0.4918,0.0365,0.0124,Janna,Soraka,Morgana
|
| 227 |
+
34,Renata Glasc,4,support,0.4984,0.0213,0.0037,Vel'Koz,Xerath,Maokai
|
| 228 |
+
35,LeBlanc,5,support,0.5043,0.0095,0.0336,Taric,Galio,Fiddlesticks
|
| 229 |
+
36,Brand,5,support,0.4968,0.0192,0.0098,Galio,Camille,Shaco
|
| 230 |
+
37,Shaco,5,support,0.4976,0.014199999999999999,0.0391,Hwei,Zoe,Lulu
|
| 231 |
+
38,Sylas,5,support,0.4971,0.014199999999999999,0.0134,Poppy,Renata Glasc,Taric
|
| 232 |
+
39,Galio,5,support,0.5039,0.008199999999999999,0.0055000000000000005,Zac,Milio,Janna
|
| 233 |
+
40,Zoe,5,support,0.5001,0.009899999999999999,0.0040999999999999995,Taric,Elise,Poppy
|
| 234 |
+
41,Fiddlesticks,5,support,0.5071,0.0052,0.0028000000000000004,Maokai,Poppy,Brand
|
| 235 |
+
42,Shen,5,support,0.5006,0.0058,0.0007000000000000001,Galio,Taric,Swain
|
| 236 |
+
43,Camille,5,support,0.4991,0.0059,0.0027,Galio,Elise,LeBlanc
|
| 237 |
+
44,Swain,5,support,0.47609999999999997,0.022799999999999997,0.0134,Fiddlesticks,Sona,Vel'Koz
|
| 238 |
+
45,Hwei,5,support,0.48840000000000006,0.0087,0.008,LeBlanc,Zoe,Taric
|
| 239 |
+
46,Zac,5,support,0.4827,0.0054,0.0031,Taric,LeBlanc,Poppy
|
util/data/player_stats_merged_2025-01-08.csv
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
player_id,region,date,champion,level,team,result,match_length_mins,kill,death,assist,kda_ratio,kill_participation,laning,cs,cs_per_min,avg_tier,teammates1,team_champ1,teammates2,team_champ2,teammates3,team_champ3,teammates4,team_champ4,oppmates1,opp_champ1,oppmates2,opp_champ2,oppmates3,opp_champ3,oppmates4,opp_champ4,oppmates5,opp_champ5,total_games,wins,losses,win_rate,avg_kills,avg_deaths,avg_assists,kda_ratio_profile,kill_participation_profile,most_champ_1,WR_1,W_1,L_1,KDA_1,most_champ_2,WR_2,W_2,L_2,KDA_2,most_champ_3,WR_3,W_3,L_3,KDA_3,TOP,JUNGLE,MID,ADC,SUPPORT,most_role_1,most_role_2,most_role_1_value,most_role_2_value,season_champ_1,cs_ssn_1,cpm_ssn_1,kda_ssn_1,k_ssn_1,d_ssn_1,a_ssn_1,wr_ssn_1,games_ssn_1,season_champ_2,cs_ssn_2,cpm_ssn_2,kda_ssn_2,k_ssn_2,d_ssn_2,a_ssn_2,wr_ssn_2,games_ssn_2,season_champ_3,cs_ssn_3,cpm_ssn_3,kda_ssn_3,k_ssn_3,d_ssn_3,a_ssn_3,wr_ssn_3,games_ssn_3,season_champ_4,cs_ssn_4,cpm_ssn_4,kda_ssn_4,k_ssn_4,d_ssn_4,a_ssn_4,wr_ssn_4,games_ssn_4,season_champ_5,cs_ssn_5,cpm_ssn_5,kda_ssn_5,k_ssn_5,d_ssn_5,a_ssn_5,wr_ssn_5,games_ssn_5,season_champ_6,cs_ssn_6,cpm_ssn_6,kda_ssn_6,k_ssn_6,d_ssn_6,a_ssn_6,wr_ssn_6,games_ssn_6,season_champ_7,cs_ssn_7,cpm_ssn_7,kda_ssn_7,k_ssn_7,d_ssn_7,a_ssn_7,wr_ssn_7,games_ssn_7,7d_champ_1,7d_total_1,7d_W_1,7d_L_1,7d_WR_1,7d_champ_2,7d_total_2,7d_W_2,7d_L_2,7d_WR_2,7d_champ_3,7d_total_3,7d_W_3,7d_L_3,7d_WR_3,mastery_champ_1,m_lv_1,mastery_champ_2,m_lv_2,mastery_champ_3,m_lv_3,mastery_champ_4,m_lv_4,mastery_champ_5,m_lv_5,mastery_champ_6,m_lv_6,mastery_champ_7,m_lv_7,mastery_champ_8,m_lv_8,mastery_champ_9,m_lv_9,mastery_champ_10,m_lv_10,mastery_champ_11,m_lv_11,mastery_champ_12,m_lv_12,mastery_champ_13,m_lv_13,mastery_champ_14,m_lv_14,mastery_champ_15,m_lv_15,mastery_champ_16,m_lv_16
|
| 2 |
+
Agurin-EUW,euw,"Sun, Jan 5, 2025 6:25 PM",Jarvan IV,16,blue,1,26.68,9,2,19,14.00,0.67,1.08,183,6.9,2,skygge kriger #EUV,Rumble,성진우 #789,Vladimir,JEZUUU #0814,Yasuo,Papadodi #1010,Lulu,the inescapable #EUW,Maokai,edge of night #999,Kindred,Macaquiño #GAP,LeBlanc,Wanna be a pro #03120,Corki,Walid Georgey #EUW,Rell,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0
|
| 3 |
+
Agurin-EUW,euw,"Sun, Jan 5, 2025 5:48 PM",Wukong,16,red,1,28.68,3,5,11,2.80,0.47,1.33,220,7.7,2,S8DiamondDog #EUW,Yasuo,Owen Mcdade #BLACK,Fiora,AllYouHadToDoWas #Stay,Karthus,Depressed Loser #ff15,LeBlanc,Drali #Drali,K'Sante,Kiki #COYG,Viego,222 #EUW3,Syndra,JEZUUU #0814,Xayah,grisha turbina #ADHD,Sona,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0
|
| 4 |
+
Agurin-EUW,euw,"Sun, Jan 5, 2025 5:10 PM",Wukong,12,blue,0,20.65,6,4,2,2.00,0.57,0.89,153,7.4,2,Novachrono #Back,Cho'Gath,2025 #favo,Gragas,Jeyrus #Jey,Corki,Papadodi #1010,Lulu,S8DiamondDog #EUW,Dr. Mundo,Thomas Shelby #SOLOQ,Vi,222 #EUW3,Ekko,JEZUUU #0814,Caitlyn,Pablo #boda,Bard,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0
|
| 5 |
+
Agurin-EUW,euw,"Sun, Jan 5, 2025 4:30 PM",Elise,15,blue,1,24.22,10,3,6,5.33,0.62,1.08,194,8.0,2,SatØrius #EUW,Rumble,AbbedaggÆ #EUW,Jayce,Kite Machine #EUW,Jhin,Vento #TAIF,Bard,KOI Spooder #1352,K'Sante,NazgulsBlade #LOTR,Skarner,TwitchTVxKenzuke #EUW,Aurora,Unkn0wn #EUW11,Ezreal,Paolocannone #EUW,Karma,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0
|
| 6 |
+
Agurin-EUW,euw,"Sun, Jan 5, 2025 1:34 AM",Wukong,14,blue,0,26.37,7,10,4,1.10,0.65,0.89,169,6.4,2,Vandett0 #ETABL,Teemo,Grunge #010,Yone,222 #EUW3,Ekko,Crixus #ARENA,Leona,SenSen #EUWFR,Nidalee,AllYouHadToDoWas #Stay,Karthus,SRTSS #EUW,Corki,Keduii #GOAT,Caitlyn,Sergeant Sona #KJP,Sona,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0
|
| 7 |
+
Agurin-EUW,euw,"Sun, Jan 5, 2025 12:48 AM",Wukong,17,blue,1,31.83,4,3,4,2.67,0.33,1.13,267,8.4,2,Bobsik #EUW,Camille,SRTSS #EUW,LeBlanc,PsychoZedPlayer #EUW,Hwei,mein herz #197,Janna,Patrick Jane #Tea,Vladimir,Seonsu #Noula,Viego,Odysseus #131,Taliyah,Keduii #GOAT,Ezreal,Crixus #ARENA,Zilean,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0
|
| 8 |
+
Agurin-EUW,euw,"Sat, Jan 4, 2025 11:56 PM",Wukong,16,red,1,25.28,7,2,7,7.00,0.61,0.89,208,8.2,2,Szygenda #EUW,Aurora,Dr Orange #Caps,Galio,J1HUIV #000,Kalista,ttveminencjasupp #kick,Renata Glasc,Patrick Jane #Tea,Vladimir,Thors Snoresson #3327,Graves,222 #EUW3,Syndra,LeonardoDiCassio #EUW,Caitlyn,Maynter #EUW,Nautilus,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0
|
| 9 |
+
Agurin-EUW,euw,"Sat, Jan 4, 2025 10:39 PM",Wukong,13,red,1,21.02,5,1,5,10.00,0.56,1.44,147,7.0,2,Desperate Nasus #EUW,Kayle,Yoo Jonghyuk333 #EUW,Aurora,LeonardoDiCassio #EUW,Viktor,Canam #123,Nami,Makkro #EUW,Ornn,Kiki #COYG,Skarner,SRTSS #EUW,Yone,avarice61 #EUW,Kog'Maw,Sergeant Sona #KJP,Seraphine,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0
|
| 10 |
+
Agurin-EUW,euw,"Sat, Jan 4, 2025 10:04 PM",Elise,17,blue,1,25.4,15,3,6,7.00,0.53,1.56,225,8.9,2,choilot #LOT,Gnar,a winds rhythm #Aang,Yasuo,Boring Cycle #Abner,Swain,ataraxia #7z7,Bard,Riihonen #EUW,Vladimir,AkaManto #LGM,Hecarim,SRTSS #EUW,Yone,Keduii #GOAT,Ashe,Peak Level #123,Zac,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0
|
| 11 |
+
Agurin-EUW,euw,"Sat, Jan 4, 2025 9:01 PM",Wukong,13,blue,0,27.2,6,11,5,1.00,0.58,0.82,159,5.8,2,Ronaldo Nazário #12345,Irelia,TATA #HOPE,Galio,chöego #EUW,Corki,Sergeant Sona #KJP,Sona,drunkenztain #EUW,Fiddlesticks,Foutriquet #EUW,Jarvan IV,silkysmath #6206,Syndra,Kushala Daora #MHVV,Caitlyn,darkchri99 #EUW,Lux,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0
|
| 12 |
+
Agurin-EUW,euw,"Sat, Jan 4, 2025 8:23 PM",Elise,12,red,0,24.83,1,6,2,0.50,0.2,0.92,163,6.6,2,Bent246 #Bent,Akshan,c0cky movement #tukan,Irelia,fjgyqwjsaqxca #LUDER,Jinx,gummyjuiceULTRA #11cmP,Pyke,أستولفو بن لادن #UwU,Singed,bluerzor #grind,Wukong,나프켈라 #BOAT,Akali,e7c3c0fd cee3 4399 877b baf89c9f6f46 #EUW,Jhin,Sergeant Sona #KJP,Sona,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0
|
| 13 |
+
Agurin-EUW,euw,"Sat, Jan 4, 2025 7:42 PM",Wukong,14,blue,1,21.82,5,2,8,6.50,0.39,1.0,174,8.0,2,skygge kriger #EUV,Aatrox,bvffi #meow,Corki,Kushala Daora #MHVV,Hwei,Zoo port #LOL,Zoe,c0cky movement #tukan,Yone,noname #gromp,Taliyah,e7c3c0fd cee3 4399 877b baf89c9f6f46 #EUW,Cho'Gath,twtv exofeng #IWNL,Draven,Sergeant Sona #KJP,Rakan,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0
|
| 14 |
+
Agurin-EUW,euw,"Sat, Jan 4, 2025 7:13 PM",Wukong,14,red,0,24.2,3,6,7,1.67,0.53,0.28,172,7.1,2,DREILIX #000,Jayce,Bobsbag #EUW,Gragas,Rafitta #EUW,Corki,eXoValdo #EUW,Brand,e7c3c0fd cee3 4399 877b baf89c9f6f46 #EUW,Sion,wοkeupIikethis #EUW,Viego,Eternal Blizzard #carot,Hwei,PAKO ETERNAL #EUW,Ezreal,Sergeant Sona #KJP,Sona,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0
|
| 15 |
+
Agurin-EUW,euw,"Sat, Jan 4, 2025 12:41 AM",Wukong,17,blue,1,34.25,5,11,18,2.09,0.51,0.67,194,5.7,2,batubabaHOPPALA #HOPPA,Riven,Fool Night #Ivy,Veigar,Sintemon #gumo,Ashe,ScoobaTroopah #10000,Blitzcrank,Pablo #boda,Aurora,TWTV DETDERT #12MAJ,Graves,J1HUIV #000,Karma,Mandaryñ #EUW,Corki,erdt #EUW,Leona,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0
|
| 16 |
+
Agurin-EUW,euw,"Fri, Jan 3, 2025 11:54 PM",Wukong,15,red,1,23.03,7,3,5,4.00,0.48,1.56,197,8.6,2,Fool Night #Ivy,Aurora,Dr Orange #Caps,Sylas,Sintemon #gumo,Ashe,ScoobaTroopah #10000,Blitzcrank,modernillo #moder,Ambessa,Eternal Blizzard #carot,Viego,J1HUIV #000,Karma,Beanovich #bean,Varus,niudefuwuqi2007 #8085,Braum,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0
|
| 17 |
+
Agurin-EUW,euw,"Fri, Jan 3, 2025 11:23 PM",Jarvan IV,17,blue,1,31.22,1,4,20,5.25,0.54,0.67,217,7.0,2,Vertigo #4810,Ambessa,LëFacteur Chance #EUW,Akali,Chrisberg #6103,Corki,raikooooo #EUW,Blitzcrank,modernillo #moder,Gragas,mikusik998 #gaz,Bel'Veth,Imma touch you #131,Hwei,Beanovich #bean,Kalista,Jordæn #EUW,Pantheon,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0
|
| 18 |
+
Agurin-EUW,euw,"Fri, Jan 3, 2025 10:40 PM",Elise,16,red,1,29.27,6,3,18,8.00,0.71,1.27,197,6.7,2,blueskies777 #EUW,Renekton,Return to dust #Dust,Viktor,Beanovich #bean,Jinx,twojstary2komary #win,Rakan,나프켈라 #BOAT,Jax,bluerzor #grind,Skarner,LëFacteur Chance #EUW,Akali,Dr Mango #Hans,Kalista,Sergeant Sona #KJP,Lulu,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0
|
| 19 |
+
Agurin-EUW,euw,"Fri, Jan 3, 2025 9:59 PM",Wukong,15,red,1,23.2,10,3,4,4.67,0.54,1.38,203,8.8,2,yuqi #golem,Galio,Mein Königreich #917n3,Sylas,batubabaHOPPALA #HOPPA,Varus,MORG3NSHTERN #EUW,Rakan,KOI Spooder #1352,Rumble,mikusik998 #gaz,Bel'Veth,RKR #123,Viktor,supershy #jblss,Ashe,Drututts Lisp #EUW,Gragas,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0
|
| 20 |
+
Agurin-EUW,euw,"Fri, Jan 3, 2025 9:13 PM",Elise,16,red,1,28.07,8,2,12,10.00,0.51,0.75,207,7.4,1,washed úp #EUW,Gwen,SMRADOCH RANDOM #EUW,Ziggs,RKR #123,Ashe,Frank Castle #2610,Blitzcrank,Shourdy #EUW,K'Sante,Purple Place #Moe,Rengar,WORLDS2025 #AIS,Irelia,Odysseus #131,Taliyah,Sergeant Sona #KJP,Sona,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0
|
| 21 |
+
Agurin-EUW,euw,"Fri, Jan 3, 2025 8:38 PM",Wukong,12,red,0,21.68,3,5,7,2.00,0.48,0.67,141,6.5,2,e7c3c0fd cee3 4399 877b baf89c9f6f46 #EUW,Volibear,wymówkomat #escik,Ahri,Percy Magic #1234,Kalista,cross the edge #fear,Nautilus,ΑrchΦiend #666,Aatrox,Razørk Activoo #razzz,Xin Zhao,yebit #haha,Taliyah,RKR #123,Ashe,Shourdy #EUW,Sylas,20,14,6,0.7,6.1,4.5,8.5,3.24,0.53,Wukong,0.62,8,5,2.39,Elise,0.8,4,1,4.94,Jarvan IV,1.0,2,0,8.17,0.0,1.0,0.0,0.0,0.0,JUNGLE,MID,1.0,0.0,Wukong,198,7.2,2.99,6.2,4.6,7.6,0.61,193,Elise,195.4,7.2,3.1,6.7,4.5,7.2,0.58,138,Neeko,205.5,7.7,3.26,6.5,4.1,6.9,0.49,82,Jarvan IV,196.2,7,3.94,5.8,4.6,12.4,0.55,65,Karma,165.5,6.6,1.92,2.9,5.5,7.7,0.55,60,Kha'Zix,213.1,7.8,2.35,5.4,5.2,6.8,0.45,42,Nocturne,194.1,7.6,2.86,4.9,4.4,7.5,0.53,34,Wukong,27,18,9,0.67,Jarvan IV,9,6,3,0.67,Elise,8,5,3,0.63,Elise,170,Kha'Zix,162,Jarvan IV,129,Shyvana,51,Nocturne,46,Evelynn,40,Wukong,28,Ezreal,25,Brand,25,Diana,16,Karma,15,Gragas,13,Zyra,12,Neeko,12,Ahri,10,,0
|
util/data/weekly_meta_stats.csv
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
rank,champion,games,KDA,WR,pick,ban,cs,gold
|
| 2 |
+
1,Viego,760,3.17,52.63,27.68,2.24,178.06,11606
|
| 3 |
+
2,Viktor,750,2.41,49.47,27.32,38.61,207.51,11291
|
| 4 |
+
3,Corki,593,2.53,52.61,2.16,12.27,213.81,11783
|
| 5 |
+
4,Ezreal,559,2.67,50.63,20.36,8.01,200.67,11262
|
| 6 |
+
5,Lee Sin,532,3.46,54.14,19.38,10.05,164.78,11453
|
| 7 |
+
6,Jhin,507,3.28,53.65,18.47,1.17,200.76,12199
|
| 8 |
+
7,Jayce,504,2.05,48.81,18.36,4.39,196.81,11154
|
| 9 |
+
8,Yone,485,1.95,48.66,17.67,4.53,214.17,11573
|
| 10 |
+
9,Sylas,469,2.4,50.75,17.08,8.61,158.36,10355
|
| 11 |
+
10,K'Sante,468,2.52,53.21,17.05,12.67,184.34,10361
|
| 12 |
+
11,Ambessa,462,2.14,4.87,16.83,30.54,185,10813
|
| 13 |
+
12,Aurora,445,2.66,47.64,16.21,24.95,194.38,11137
|
| 14 |
+
13,Irelia,411,1.64,49.88,14.97,12.86,219.41,12287
|
| 15 |
+
14,Ashe,406,2.49,47.29,14.79,23.32,193.82,10898
|
| 16 |
+
15,Wukong,399,2.9,51.88,14.53,8.29,177.15,11337
|
| 17 |
+
16,Graves,394,2.96,52.54,14.35,1.94,199.89,12615
|
| 18 |
+
17,Caitlyn,351,2.45,53.28,12.79,14.73,209.86,12096
|
| 19 |
+
18,Nautilus,342,2.53,49.42,12.46,7.74,25.32,7240
|
| 20 |
+
19,Varus,337,2.49,52.82,12.28,5.16,195.14,11350
|
| 21 |
+
20,Skarner,332,3.82,53.92,12.09,26.68,143.07,10124
|
| 22 |
+
21,Yasuo,327,1.68,48.32,11.91,1.77,212.88,11655
|
| 23 |
+
22,Renekton,313,2.16,48.24,1.14,1.02,203.99,11361
|
| 24 |
+
23,Akali,306,2.63,47.71,11.15,9.75,186.42,11203
|
| 25 |
+
24,Hwei,306,2.6,46.08,11.15,6.52,192.2,10838
|
| 26 |
+
25,Lulu,305,3.37,52.46,11.11,11.83,32.77,7476
|
| 27 |
+
26,Gnar,292,1.97,45.55,10.64,6.25,195.43,11034
|
| 28 |
+
27,Pyke,273,2.38,47.25,9.94,45.36,40.46,9196
|
| 29 |
+
28,Karma,270,3.22,55.93,9.83,3.19,44.89,8080
|
| 30 |
+
29,Rakan,270,3.24,4.63,9.83,1.05,27.77,7221
|
| 31 |
+
30,Jinx,268,2.28,44.03,9.76,2.18,199.54,11034
|
| 32 |
+
31,Kai'Sa,266,2.71,47.37,9.69,0.91,208.07,11989
|
| 33 |
+
32,Rell,265,3.24,49.06,9.65,3.18,23.9,7443
|
| 34 |
+
33,Jax,264,2.07,56.82,9.62,11.66,183.78,11208
|
| 35 |
+
34,Poppy,262,2.46,51.15,9.54,1.52,56.66,8261
|
| 36 |
+
35,Taliyah,257,2.69,50.58,9.36,2.23,199.33,11689
|
| 37 |
+
36,Bard,254,3.67,53.54,9.25,1.43,26.46,7628
|
| 38 |
+
37,Talon,249,2.9,54.62,9.07,7.57,202.84,12227
|
| 39 |
+
38,Vi,228,2.97,46.93,0.83,0.11,165.43,10646
|
| 40 |
+
39,Galio,222,3.01,55.41,8.09,4.06,161.87,9825
|
| 41 |
+
40,Lux,222,3.17,5.36,8.09,1.74,132.95,9845
|
| 42 |
+
41,Elise,222,2.77,52.25,8.09,10.29,122.33,10790
|
| 43 |
+
42,Camille,218,2.14,54.59,7.94,1.99,169.03,11136
|
| 44 |
+
43,Zed,212,2.77,0.5,7.72,13.73,200.28,12429
|
| 45 |
+
44,Syndra,211,2.59,53.08,7.69,4.57,208.25,11529
|
| 46 |
+
45,Nidalee,210,3.45,0.5,7.65,8.84,170.11,11411
|
| 47 |
+
46,Kindred,210,2.57,47.14,7.65,8.86,174.7,11719
|
| 48 |
+
47,Maokai,208,2.16,45.19,7.58,0.18,110.61,8332
|
| 49 |
+
48,Gragas,205,2.4,49.27,7.47,4.85,169.43,10303
|
| 50 |
+
49,Ahri,202,3.17,52.97,7.36,0.22,196.68,11003
|
| 51 |
+
50,Draven,199,2.14,48.74,7.25,33.07,200.71,13185
|
| 52 |
+
51,Jarvan IV,195,3.69,51.79,0.71,1.72,161.92,10821
|
| 53 |
+
52,Zyra,192,3.16,55.21,6.99,5.48,188.71,11473
|
| 54 |
+
53,Neeko,190,2.81,52.63,6.92,1.18,63.94,8500
|
| 55 |
+
54,Ekko,185,3.05,50.27,6.83,2.22,197.31,11848
|
| 56 |
+
55,Sona,184,3.19,53.26,6.79,1.36,26.69,7799
|
| 57 |
+
56,Diana,177,2.59,57.63,6.45,1.45,192.18,11840
|
| 58 |
+
57,Garen,169,2.25,52.66,6.16,2.41,205.02,11777
|
| 59 |
+
58,Riven,160,2.22,51.25,5.83,8.06,200.78,11609
|
| 60 |
+
59,Pantheon,160,2.16,40.63,5.83,1.42,147.55,10426
|
| 61 |
+
60,Braum,159,3.08,50.94,5.79,5.33,23.71,7133
|
| 62 |
+
61,Aatrox,158,2.08,4.81,5.76,4.89,177.53,10395
|
| 63 |
+
62,Janna,155,3.88,53.55,5.72,3.86,24.06,7465
|
| 64 |
+
63,Tristana,153,2.63,55.56,5.64,0.54,207.52,12824
|
| 65 |
+
64,Gwen,153,1.81,40.52,5.57,2.68,191.23,11212
|
| 66 |
+
65,Zac,150,3.37,54.67,5.46,5.14,144.34,9863
|
| 67 |
+
66,Swain,148,2.87,51.35,5.46,1.34,180.99,10870
|
| 68 |
+
67,Orianna,144,3.18,56.25,5.25,1.01,197.33,10605
|
| 69 |
+
68,Blitzcrank,144,2.66,52.08,5.25,0.85,23.44,7164
|
| 70 |
+
69,Nami,144,3.87,49.31,5.25,0.56,23.22,7603
|
| 71 |
+
70,Kha'Zix,142,2.85,45.77,5.17,0.35,170.93,11456
|
| 72 |
+
71,Senna,141,2.96,54.61,5.14,0.78,31.61,8331
|
| 73 |
+
72,Leona,141,2.55,47.52,5.14,2.01,25.09,7187
|
| 74 |
+
73,Thresh,139,3.11,49.64,5.06,3.31,26.56,7183
|
| 75 |
+
74,Rumble,136,2.24,44.85,4.95,1.45,186.17,10817
|
| 76 |
+
75,Kalista,134,2.39,43.28,4.88,3.01,202.46,12187
|
| 77 |
+
76,Smolder,133,2.36,45.11,4.84,1.27,223.16,12163
|
| 78 |
+
77,Lucian,127,2.51,52.76,4.63,0.28,208.8,11887
|
| 79 |
+
78,Ziggs,127,2.99,50.39,4.63,0.67,215.27,11706
|
| 80 |
+
79,LeBlanc,124,2.48,41.94,4.52,22.71,156.94,9891
|
| 81 |
+
80,Fiora,123,1.92,57.72,4.48,7.97,207.29,12135
|
| 82 |
+
81,Qiyana,120,2.75,61.67,4.37,4.05,180.3,11951
|
| 83 |
+
82,Azir,119,2.34,53.78,4.33,1.37,212.93,11549
|
| 84 |
+
83,Vladimir,119,2.65,44.54,4.33,5.57,201.12,11094
|
| 85 |
+
84,Aphelios,118,2.29,49.15,4.35,0.52,202.92,11660
|
| 86 |
+
85,Xerath,117,3.64,53.85,4.26,0.02,154.71,10485
|
| 87 |
+
86,Kennen,113,2.28,57.52,4.12,3.15,188.5,11130
|
| 88 |
+
87,Volibear,110,2.08,47.27,4.06,1.47,181.27,10689
|
| 89 |
+
88,Seraphine,109,3.09,54.13,4.02,2.01,90.32,8859
|
| 90 |
+
89,Bel'Veth,109,3.04,48.62,3.97,1.06,176.42,11627
|
| 91 |
+
90,Xin Zhao,105,2.92,54.29,3.82,0.33,164.17,10876
|
| 92 |
+
91,Zoe,102,2.97,52.94,3.72,4.39,106.28,9690
|
| 93 |
+
92,Dr. Mundo,95,2.52,44.21,3.46,0.94,195.67,11028
|
| 94 |
+
93,Darius,94,1.99,51.06,3.42,8.42,199.72,11408
|
| 95 |
+
94,Ryze,92,2.35,54.35,3.35,0.86,214.32,11409
|
| 96 |
+
95,Teemo,91,2.28,57.14,3.31,2.42,206.65,11535
|
| 97 |
+
96,Lissandra,91,2.71,50.55,3.31,0.95,179.89,10267
|
| 98 |
+
97,Nocturne,91,3.11,46.15,3.31,0.16,177.43,11299
|
| 99 |
+
98,Karthus,90,2.39,44.44,3.28,12.85,197.17,12214
|
| 100 |
+
99,Lillia,89,3.35,58.43,3.24,1.38,190.69,11350
|
| 101 |
+
100,Rengar,89,2.38,44.94,3.24,20.09,176.18,11359
|
| 102 |
+
101,Alistar,89,2.79,4.27,3.24,1.57,22.94,6940
|
| 103 |
+
102,Miss Fortune,88,2.79,46.59,3.21,0.36,213.86,11953
|
| 104 |
+
103,Kayn,86,2.67,55.81,3.13,4.19,184.67,11786
|
| 105 |
+
104,Trundle,86,1.51,0.5,3.17,0.18,204.58,12245
|
| 106 |
+
105,Zilean,85,3.14,47.06,0.31,0.17,92.91,7722
|
| 107 |
+
106,Zeri,84,2.4,40.48,3.06,0.37,224.45,12286
|
| 108 |
+
107,Xayah,83,2.44,45.78,3.02,0.35,221.17,12281
|
| 109 |
+
108,Samira,80,2.29,51.25,2.91,2.67,183.21,12175
|
| 110 |
+
109,Soraka,80,3.09,46.25,2.91,1.87,39.89,7706
|
| 111 |
+
110,Hecarim,79,2.9,43.04,2.88,4.64,193.19,11339
|
| 112 |
+
111,Nunu & Willump,78,2.43,33.33,2.84,3.54,142.21,9073
|
| 113 |
+
112,Kayle,77,2.25,49.35,0.28,0.83,225.47,12285
|
| 114 |
+
113,Udyr,74,2.82,5.27,2.73,4.76,179.85,10322
|
| 115 |
+
114,Fiddlesticks,73,2.83,57.53,2.66,5.58,74.84,9529
|
| 116 |
+
115,Shaco,73,2.5,49.32,2.66,9.15,121.48,10403
|
| 117 |
+
116,Shen,72,2.93,52.78,2.66,0.55,131.83,8504
|
| 118 |
+
117,Briar,71,2.54,56.34,2.62,1.65,154.52,11786
|
| 119 |
+
118,Gangplank,70,2.24,61.43,2.58,0.38,206.49,12713
|
| 120 |
+
119,Akshan,69,2.94,49.28,2.51,4.47,190.16,12380
|
| 121 |
+
120,Renata Glasc,67,2.98,52.24,2.44,0.52,28.27,7606
|
| 122 |
+
121,Milio,67,4.03,47.76,2.44,2.31,24.31,7352
|
| 123 |
+
122,Veigar,65,2.52,58.46,0.24,0.26,204.69,12145
|
| 124 |
+
123,Yuumi,65,4.28,43.08,2.37,5.03,15.05,7028
|
| 125 |
+
124,Kassadin,64,2.87,54.69,2.33,3.22,192.22,11845
|
| 126 |
+
125,Katarina,63,2.73,55.56,2.29,5.67,186.57,12147
|
| 127 |
+
126,Cho'Gath,63,2.45,53.97,2.29,0.27,189.78,10459
|
| 128 |
+
127,Taric,63,2.39,46.03,2.29,0.48,43.49,7062
|
| 129 |
+
128,Sivir,61,2.58,50.82,2.22,0.28,231.49,12104
|
| 130 |
+
129,Ivern,61,4.63,49.18,2.22,1.33,137.18,9604
|
| 131 |
+
130,Olaf,58,2.06,53.45,2.14,1.34,195.36,11604
|
| 132 |
+
131,Malphite,58,2.29,53.45,2.11,5.63,169.38,9948
|
| 133 |
+
132,Rammus,58,3.44,51.72,2.11,1.77,158.72,10681
|
| 134 |
+
133,Vayne,58,2.15,0.5,2.11,1.87,189.76,11569
|
| 135 |
+
134,Warwick,58,1.89,37.93,2.11,0.89,168.67,11066
|
| 136 |
+
135,Evelynn,57,3.79,63.16,2.08,3.45,156.91,10804
|
| 137 |
+
136,Aurelion Sol,57,3.56,57.89,2.08,0.46,206.32,11735
|
| 138 |
+
137,Rek'Sai,57,3.68,52.63,0.21,0.77,179.51,12298
|
| 139 |
+
138,Singed,57,2.03,42.11,2.08,0.88,172.35,9992
|
| 140 |
+
139,Sejuani,55,3,49.09,0.02,0.06,139.36,9399
|
| 141 |
+
140,Sett,55,1.84,47.27,2.03,0.12,179.38,11512
|
| 142 |
+
141,Urgot,54,2.02,0.5,1.97,0.99,193.78,11833
|
| 143 |
+
142,Tahm Kench,51,2.43,4.51,1.88,0.21,54.86,8513
|
| 144 |
+
143,Tryndamere,50,1.95,0.58,1.82,0.25,240.58,13679
|
| 145 |
+
144,Cassiopeia,50,1.95,0.4,1.82,1.88,197.78,11455
|
| 146 |
+
145,Sion,48,1.54,47.92,1.75,0.24,211.04,12066
|
| 147 |
+
146,Ornn,46,2.83,5.87,0.17,0.18,169.59,9579
|
| 148 |
+
147,Twitch,46,2.84,54.35,1.68,0.09,162.09,12261
|
| 149 |
+
148,Master Yi,45,2.25,51.11,1.66,0.75,177.09,12508
|
| 150 |
+
149,Kog'Maw,45,1.93,28.89,1.66,0.14,195.02,11113
|
| 151 |
+
150,Vex,44,2.63,56.82,0.16,1.66,189.75,11082
|
| 152 |
+
151,Anivia,41,2.61,41.46,1.51,1.42,195.22,11045
|
| 153 |
+
152,Twisted Fate,39,2.2,51.28,1.44,0.29,187.26,11260
|
| 154 |
+
153,Yorick,39,1.43,43.59,1.42,0.49,186.97,10508
|
| 155 |
+
154,Fizz,39,2.51,43.59,1.44,0.55,154.77,10855
|
| 156 |
+
155,Vel'Koz,35,3.03,0.6,1.29,0.31,167.91,11602
|
| 157 |
+
156,Mordekaiser,32,2.22,59.38,1.18,0.91,174.25,10702
|
| 158 |
+
157,Nilah,31,2.14,58.06,1.13,3.41,201.23,12587
|
| 159 |
+
158,Heimerdinger,31,1.99,41.94,1.14,0.68,169.45,9619
|
| 160 |
+
159,Kled,30,2.26,66.67,1.11,0.27,188.8,12340
|
| 161 |
+
160,Morgana,27,3.25,55.56,0.98,1.99,114.81,9350
|
| 162 |
+
161,Naafiri,26,1.9,42.31,0.95,0.27,161.38,9767
|
| 163 |
+
162,Brand,25,2.16,0.44,0.91,0.27,138.92,9463
|
| 164 |
+
163,Annie,24,2.44,58.33,0.89,0.37,167,10856
|
| 165 |
+
164,Malzahar,23,2.23,47.83,0.84,0.87,203.39,10805
|
| 166 |
+
165,Shyvana,23,2.89,47.83,0.85,0.12,209.39,12167
|
| 167 |
+
166,Quinn,21,1.95,52.38,0.76,0.73,157.57,11228
|
| 168 |
+
167,Nasus,20,2.08,0.5,0.73,1.62,184.05,10645
|
| 169 |
+
168,Amumu,17,1.72,29.41,0.62,1.15,125.41,8739
|
| 170 |
+
169,Illaoi,16,1.95,31.25,0.59,1.11,211.13,12318
|
util/data_type_checking.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import pandas as pd
|
| 3 |
+
|
| 4 |
+
def check_data_loading(file_path):
|
| 5 |
+
"""
|
| 6 |
+
Debug function to check how the data is being loaded with proper encoding
|
| 7 |
+
"""
|
| 8 |
+
# Try different encodings
|
| 9 |
+
encodings = ['utf-8', 'utf-8-sig', 'latin1', 'ISO-8859-1']
|
| 10 |
+
|
| 11 |
+
for encoding in encodings:
|
| 12 |
+
try:
|
| 13 |
+
print(f"\nTrying encoding: {encoding}")
|
| 14 |
+
|
| 15 |
+
# Read raw data first
|
| 16 |
+
with open(file_path, 'r', encoding=encoding) as f:
|
| 17 |
+
raw_lines = f.readlines()[:5] # First 5 lines
|
| 18 |
+
print("Raw data first 5 lines:")
|
| 19 |
+
for line in raw_lines:
|
| 20 |
+
print(line.strip())
|
| 21 |
+
|
| 22 |
+
# Now read with pandas
|
| 23 |
+
df = pd.read_csv(file_path, encoding=encoding)
|
| 24 |
+
|
| 25 |
+
# Check champion-related columns
|
| 26 |
+
champ_cols = [col for col in df.columns if '7d_champ' in col]
|
| 27 |
+
print("\nChampion columns:")
|
| 28 |
+
for col in champ_cols:
|
| 29 |
+
print(f"\n{col} unique values:")
|
| 30 |
+
print(df[col].value_counts().head())
|
| 31 |
+
print(f"Data type: {df[col].dtype}")
|
| 32 |
+
|
| 33 |
+
# Check specific row data
|
| 34 |
+
print("\nSample row check:")
|
| 35 |
+
sample_row = df.iloc[0]
|
| 36 |
+
for col in ['7d_champ_1', '7d_champ_2', '7d_champ_3']:
|
| 37 |
+
print(f"{col}: {sample_row[col]} (type: {type(sample_row[col])})")
|
| 38 |
+
|
| 39 |
+
print(f"\nSuccessfully read file with {encoding} encoding")
|
| 40 |
+
return df
|
| 41 |
+
|
| 42 |
+
except UnicodeDecodeError:
|
| 43 |
+
print(f"Failed to read with {encoding} encoding")
|
| 44 |
+
continue
|
| 45 |
+
except Exception as e:
|
| 46 |
+
print(f"Error with {encoding} encoding: {str(e)}")
|
| 47 |
+
continue
|
| 48 |
+
|
| 49 |
+
raise ValueError("Could not read file with any of the attempted encodings")
|
| 50 |
+
|
| 51 |
+
# Use this function in your main code
|
| 52 |
+
try:
|
| 53 |
+
#input_file = os.path.join("util", "data", f"player_stats_merged_2025-01-05_1.csv")
|
| 54 |
+
input_file = os.path.join("util", "data", f"training_feature.csv")
|
| 55 |
+
print(f"Checking file: {input_file}")
|
| 56 |
+
df_check = check_data_loading(input_file)
|
| 57 |
+
|
| 58 |
+
# Additional validation
|
| 59 |
+
print("\nDataFrame Info:")
|
| 60 |
+
print(df_check.info())
|
| 61 |
+
|
| 62 |
+
print("\nSample of champion columns:")
|
| 63 |
+
champ_cols = [col for col in df_check.columns if 'champ' in col.lower()]
|
| 64 |
+
print(df_check[champ_cols].head())
|
| 65 |
+
|
| 66 |
+
except Exception as e:
|
| 67 |
+
print(f"Error: {str(e)}")
|
util/feature_eng.py
ADDED
|
@@ -0,0 +1,370 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import pandas as pd
|
| 3 |
+
import numpy as np
|
| 4 |
+
from helper import ChampionConverter, process_kda_perfect
|
| 5 |
+
|
| 6 |
+
def create_champion_features(merged_player_stats=None, meta_stats=None, weekly_meta=None, debug=None, consider_team_comp=True, test_mode=False):
|
| 7 |
+
"""
|
| 8 |
+
Create features for champion prediction using player data.
|
| 9 |
+
Champion names will be used as column headers.
|
| 10 |
+
Uses pd.concat to avoid DataFrame fragmentation.
|
| 11 |
+
"""
|
| 12 |
+
try:
|
| 13 |
+
if merged_player_stats is None:
|
| 14 |
+
print("Loading merged player stats...")
|
| 15 |
+
input_file = os.path.join("util", "data", "player_stats_merged.csv")
|
| 16 |
+
merged_player_stats = pd.read_csv(input_file, low_memory=False)
|
| 17 |
+
|
| 18 |
+
#processing kda value
|
| 19 |
+
merged_player_stats = process_kda_perfect(merged_player_stats)
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
if test_mode:
|
| 23 |
+
print("Test mode: Using only first 100 rows")
|
| 24 |
+
merged_player_stats = merged_player_stats.head(100)
|
| 25 |
+
|
| 26 |
+
if meta_stats is None:
|
| 27 |
+
print("Loading meta stats...")
|
| 28 |
+
meta_file = os.path.join("util", "data", "meta_stats.csv")
|
| 29 |
+
meta_stats = pd.read_csv(meta_file, low_memory=False)
|
| 30 |
+
|
| 31 |
+
if weekly_meta is None:
|
| 32 |
+
print("Loading weekly meta stats...")
|
| 33 |
+
weekly_file = os.path.join("util", "data", "weekly_meta_stats.csv")
|
| 34 |
+
weekly_meta = pd.read_csv(weekly_file, low_memory=False)
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
# Initialize variables
|
| 38 |
+
debug_data = []
|
| 39 |
+
original_columns = merged_player_stats.columns.tolist()
|
| 40 |
+
feature_dict = {}
|
| 41 |
+
|
| 42 |
+
# Copy original columns
|
| 43 |
+
for col in merged_player_stats.columns:
|
| 44 |
+
feature_dict[col] = merged_player_stats[col].values.copy()
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
# Initialize the champion converter
|
| 48 |
+
converter = ChampionConverter()
|
| 49 |
+
all_champions = converter.champions
|
| 50 |
+
#total_champions = len(converter.champions)
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
# Get low tier champions and counter information
|
| 55 |
+
tier_penalties = {3: 0.9, 4: 0.85, 5: 0.8}
|
| 56 |
+
|
| 57 |
+
# Create tier_map as a dictionary of lists
|
| 58 |
+
tier_map = {}
|
| 59 |
+
for _, row in meta_stats.iterrows():
|
| 60 |
+
champ = row['champion']
|
| 61 |
+
tier = row['tier']
|
| 62 |
+
if pd.notna(tier):
|
| 63 |
+
if champ in tier_map:
|
| 64 |
+
tier_map[champ].append(tier)
|
| 65 |
+
else:
|
| 66 |
+
tier_map[champ] = [tier]
|
| 67 |
+
|
| 68 |
+
counter_map = {}
|
| 69 |
+
for _, row in meta_stats.iterrows():
|
| 70 |
+
if pd.notna(row['counter1']):
|
| 71 |
+
champ = row['champion']
|
| 72 |
+
counters = [row['counter1'], row['counter2'], row['counter3']]
|
| 73 |
+
if champ in counter_map:
|
| 74 |
+
counter_map[champ].extend([c for c in counters if pd.notna(c)])
|
| 75 |
+
else:
|
| 76 |
+
counter_map[champ] = [c for c in counters if pd.notna(c)]
|
| 77 |
+
|
| 78 |
+
# Ensure unique counters and remove duplicates
|
| 79 |
+
for champ, counters in counter_map.items():
|
| 80 |
+
counter_map[champ] = list(set(counters))
|
| 81 |
+
|
| 82 |
+
# Move 'champion' column to the first position
|
| 83 |
+
cols = ['champion'] + [col for col in merged_player_stats if col != 'champion']
|
| 84 |
+
merged_player_stats = merged_player_stats[cols]
|
| 85 |
+
|
| 86 |
+
# Define importance weights
|
| 87 |
+
weights = {
|
| 88 |
+
'recent': 0.3, # Last 20 games
|
| 89 |
+
'weekly': 0.4, # Last 7 days
|
| 90 |
+
'meta': 0.2, # Only from weekly_stats
|
| 91 |
+
'season': 0.06, # Current season
|
| 92 |
+
'mastery': 0.04 # All-time mastery
|
| 93 |
+
}
|
| 94 |
+
|
| 95 |
+
# Process rows in batches
|
| 96 |
+
batch_size = 100
|
| 97 |
+
total_rows = len(merged_player_stats)
|
| 98 |
+
|
| 99 |
+
print(f"Total rows: {total_rows}")
|
| 100 |
+
|
| 101 |
+
for batch_start in range(0, total_rows, batch_size):
|
| 102 |
+
batch_end = min(batch_start + batch_size, total_rows)
|
| 103 |
+
batch_rows = merged_player_stats.iloc[batch_start:batch_end]
|
| 104 |
+
print(f"\nProcessing rows {batch_start} to {batch_end} ({batch_start/total_rows*100:.2f}% complete)")
|
| 105 |
+
|
| 106 |
+
# Initialize batch scores dictionary
|
| 107 |
+
batch_scores = {champion: np.zeros(len(batch_rows)) for champion in all_champions}
|
| 108 |
+
|
| 109 |
+
# Process each row in this batch
|
| 110 |
+
for batch_idx, (idx, row) in enumerate(batch_rows.iterrows()):
|
| 111 |
+
# Process each champion for this row
|
| 112 |
+
for champion in all_champions:
|
| 113 |
+
# Initialize scores for this champion and row
|
| 114 |
+
champion_scores = {
|
| 115 |
+
'recent_score': 0,
|
| 116 |
+
'weekly_score': 0,
|
| 117 |
+
'meta_score': 0,
|
| 118 |
+
'season_score': 0,
|
| 119 |
+
'mastery_score': 0
|
| 120 |
+
}
|
| 121 |
+
|
| 122 |
+
# Store debug info if needed
|
| 123 |
+
base_score_before_penalty = 0
|
| 124 |
+
counter_penalty = 0
|
| 125 |
+
counter_debug = []
|
| 126 |
+
|
| 127 |
+
# 1. Recent Performance
|
| 128 |
+
for i in range(1, 4):
|
| 129 |
+
if row.get(f'most_champ_{i}') == champion:
|
| 130 |
+
wr = float(row[f'WR_{i}']) if pd.notna(row[f'WR_{i}']) else 0
|
| 131 |
+
kda = float(row[f'KDA_{i}']) if pd.notna(row[f'KDA_{i}']) else 0
|
| 132 |
+
wins = float(row[f'W_{i}']) if pd.notna(row[f'W_{i}']) else 0
|
| 133 |
+
losses = float(row[f'L_{i}']) if pd.notna(row[f'L_{i}']) else 0
|
| 134 |
+
games = wins + losses
|
| 135 |
+
total_games = float(row['total_games']) if pd.notna(row['total_games']) else 20
|
| 136 |
+
|
| 137 |
+
performance_quality = (
|
| 138 |
+
(wr * 0.7) +
|
| 139 |
+
(min(kda, 10) / 10 * 0.3)
|
| 140 |
+
)
|
| 141 |
+
|
| 142 |
+
games_factor = min(games / 5, 1.0)
|
| 143 |
+
games_ratio = games / total_games
|
| 144 |
+
|
| 145 |
+
if games >= 5:
|
| 146 |
+
if performance_quality < 0.4:
|
| 147 |
+
performance_quality *= 0.8
|
| 148 |
+
elif performance_quality > 0.7:
|
| 149 |
+
performance_quality *= 1.2
|
| 150 |
+
|
| 151 |
+
champion_scores['recent_score'] = (
|
| 152 |
+
performance_quality * (0.7 + (0.3 * games_factor))
|
| 153 |
+
) * (1 + games_ratio * 0.2)
|
| 154 |
+
break # Exit loop once found
|
| 155 |
+
|
| 156 |
+
# 2. Weekly Performance
|
| 157 |
+
for i in range(1, 4):
|
| 158 |
+
if row.get(f'7d_champ_{i}') == champion:
|
| 159 |
+
weekly_wins = float(row[f'7d_W_{i}']) if pd.notna(row[f'7d_W_{i}']) else 0
|
| 160 |
+
weekly_losses = float(row[f'7d_L_{i}']) if pd.notna(row[f'7d_L_{i}']) else 0
|
| 161 |
+
weekly_games = float(row[f'7d_total_{i}']) if pd.notna(row[f'7d_total_{i}']) else 0
|
| 162 |
+
weekly_wr = float(row[f'7d_WR_{i}']) if pd.notna(row[f'7d_WR_{i}']) else 0
|
| 163 |
+
profile_wr = float(row['win_rate']) if pd.notna(row['win_rate']) else 0.5
|
| 164 |
+
|
| 165 |
+
if weekly_games > 0:
|
| 166 |
+
wr_trend = (weekly_wr - profile_wr) / profile_wr if profile_wr > 0 else 0
|
| 167 |
+
weekly_intensity = min(weekly_games / 10, 1.0)
|
| 168 |
+
win_ratio = weekly_wins / weekly_games if weekly_games > 0 else 0
|
| 169 |
+
|
| 170 |
+
weekly_performance = (
|
| 171 |
+
(weekly_wr * 0.4) +
|
| 172 |
+
(max(min(wr_trend, 1), -1) * 0.2) +
|
| 173 |
+
(weekly_intensity * 0.2) +
|
| 174 |
+
(win_ratio * 0.2)
|
| 175 |
+
)
|
| 176 |
+
|
| 177 |
+
if weekly_games >= 5:
|
| 178 |
+
if weekly_performance < 0.4:
|
| 179 |
+
weekly_performance *= 0.8
|
| 180 |
+
elif weekly_performance > 0.7:
|
| 181 |
+
weekly_performance *= 1.2
|
| 182 |
+
|
| 183 |
+
champion_scores['weekly_score'] = weekly_performance * (
|
| 184 |
+
0.7 + (0.3 * min(weekly_games / 5, 1.0))
|
| 185 |
+
)
|
| 186 |
+
break # Exit loop once found
|
| 187 |
+
|
| 188 |
+
# 3. Meta Score
|
| 189 |
+
if champion in weekly_meta['champion'].values:
|
| 190 |
+
weekly_row = weekly_meta[weekly_meta['champion'] == champion].iloc[0]
|
| 191 |
+
rank = weekly_row['rank']
|
| 192 |
+
games = weekly_row['games']
|
| 193 |
+
pick_rate = weekly_row['pick']
|
| 194 |
+
ban_rate = weekly_row['ban']
|
| 195 |
+
|
| 196 |
+
weight = (
|
| 197 |
+
1 / rank * 0.5 +
|
| 198 |
+
games / 100 * 0.3 +
|
| 199 |
+
pick_rate * 0.1 -
|
| 200 |
+
ban_rate * 0.1
|
| 201 |
+
)
|
| 202 |
+
|
| 203 |
+
champion_scores['meta_score'] = weight
|
| 204 |
+
|
| 205 |
+
# 4. Season Performance
|
| 206 |
+
for i in range(1, 8):
|
| 207 |
+
if row.get(f'season_champ_{i}') == champion:
|
| 208 |
+
wr = float(row[f'wr_ssn_{i}']) if pd.notna(row[f'wr_ssn_{i}']) else 0
|
| 209 |
+
games = float(row[f'games_ssn_{i}']) if pd.notna(row[f'games_ssn_{i}']) else 0
|
| 210 |
+
kda = float(row[f'kda_ssn_{i}']) if pd.notna(row[f'kda_ssn_{i}']) else 0
|
| 211 |
+
|
| 212 |
+
champion_scores['season_score'] = (
|
| 213 |
+
wr * 0.7 +
|
| 214 |
+
(kda / 10) * 0.3
|
| 215 |
+
) * (games / 100)
|
| 216 |
+
break # Exit loop once found
|
| 217 |
+
|
| 218 |
+
# 5. Mastery Score
|
| 219 |
+
for i in range(1, 17):
|
| 220 |
+
if row.get(f'mastery_champ_{i}') == champion:
|
| 221 |
+
mastery = float(row[f'm_lv_{i}']) if pd.notna(row[f'm_lv_{i}']) else 0
|
| 222 |
+
champion_scores['mastery_score'] = mastery / 7
|
| 223 |
+
break # Exit loop once found
|
| 224 |
+
|
| 225 |
+
# Calculate base score for this champion and row
|
| 226 |
+
base_score = (
|
| 227 |
+
champion_scores['recent_score'] * weights['recent'] +
|
| 228 |
+
champion_scores['weekly_score'] * weights['weekly'] +
|
| 229 |
+
champion_scores['meta_score'] * weights['meta'] +
|
| 230 |
+
champion_scores['season_score'] * weights['season'] +
|
| 231 |
+
champion_scores['mastery_score'] * weights['mastery']
|
| 232 |
+
)
|
| 233 |
+
|
| 234 |
+
|
| 235 |
+
# Store the pre-penalty score for debugging
|
| 236 |
+
base_score_before_penalty = base_score
|
| 237 |
+
|
| 238 |
+
# Apply tier penalties
|
| 239 |
+
if champion in tier_map:
|
| 240 |
+
highest_tier = min(tier_map[champion])
|
| 241 |
+
if highest_tier in tier_penalties:
|
| 242 |
+
base_score *= tier_penalties[highest_tier]
|
| 243 |
+
|
| 244 |
+
# Process team composition and counter penalties
|
| 245 |
+
if consider_team_comp:
|
| 246 |
+
# Check team champions
|
| 247 |
+
for i in range(1, 5):
|
| 248 |
+
team_col = f'team_champ{i}'
|
| 249 |
+
if team_col in row and pd.notna(row[team_col]):
|
| 250 |
+
if row[team_col] == champion:
|
| 251 |
+
base_score = 0
|
| 252 |
+
break
|
| 253 |
+
|
| 254 |
+
# Only check opponents if base_score isn't already 0
|
| 255 |
+
if base_score != 0:
|
| 256 |
+
counter_penalty = 0
|
| 257 |
+
counter_debug = [] # For debug information
|
| 258 |
+
|
| 259 |
+
for i in range(1, 6):
|
| 260 |
+
opp_col = f'opp_champ{i}'
|
| 261 |
+
if opp_col in row and pd.notna(row[opp_col]):
|
| 262 |
+
opp_champ = row[opp_col]
|
| 263 |
+
if opp_champ == champion:
|
| 264 |
+
base_score = 0
|
| 265 |
+
break
|
| 266 |
+
if champion in counter_map and opp_champ in counter_map[champion]:
|
| 267 |
+
counter_penalty += 0.1
|
| 268 |
+
counter_debug.append(opp_champ)
|
| 269 |
+
|
| 270 |
+
if counter_penalty > 0:
|
| 271 |
+
base_score = base_score * (1 - counter_penalty)
|
| 272 |
+
|
| 273 |
+
# Store the final score for this champion and row
|
| 274 |
+
batch_scores[champion][batch_idx] = max(base_score, 0)
|
| 275 |
+
|
| 276 |
+
# Collect debug data if this is the debug champion
|
| 277 |
+
if debug == champion:
|
| 278 |
+
counter_list = []
|
| 279 |
+
for i in range(1, 6):
|
| 280 |
+
opp_col = f'opp_champ{i}'
|
| 281 |
+
if opp_col in row and pd.notna(row[opp_col]):
|
| 282 |
+
if champion in counter_map and row[opp_col] in counter_map[champion]:
|
| 283 |
+
counter_list.append(row[opp_col])
|
| 284 |
+
|
| 285 |
+
debug_row = {
|
| 286 |
+
'champion': row['champion'],
|
| 287 |
+
'recent_score': champion_scores['recent_score'],
|
| 288 |
+
'weekly_score': champion_scores['weekly_score'],
|
| 289 |
+
'meta_score': champion_scores['meta_score'],
|
| 290 |
+
'base_score': base_score_before_penalty,
|
| 291 |
+
'final_score': base_score,
|
| 292 |
+
'counter_penalty': counter_penalty if consider_team_comp else 0,
|
| 293 |
+
'final_score_actual': feature_dict[row['champion']][idx] if row['champion'] in feature_dict else base_score,
|
| 294 |
+
'counter_list_debug': counter_list
|
| 295 |
+
}
|
| 296 |
+
debug_data.append(debug_row)
|
| 297 |
+
|
| 298 |
+
# Update feature_dict with batch results
|
| 299 |
+
for champion in batch_scores:
|
| 300 |
+
if champion not in feature_dict:
|
| 301 |
+
feature_dict[champion] = np.zeros(total_rows)
|
| 302 |
+
feature_dict[champion][batch_start:batch_end] = batch_scores[champion]
|
| 303 |
+
|
| 304 |
+
# Save after each batch with timestamp
|
| 305 |
+
temp_df = pd.DataFrame({
|
| 306 |
+
**{col: feature_dict[col] for col in original_columns}, # Original columns first
|
| 307 |
+
**{champion: feature_dict[champion] for champion in all_champions} # Then champion columns
|
| 308 |
+
})
|
| 309 |
+
|
| 310 |
+
batch_save_file = os.path.join("util", "data", f"feature_eng_stats.csv")
|
| 311 |
+
temp_df.to_csv(batch_save_file, index=False)
|
| 312 |
+
print(f"Saved batch progress to {batch_save_file}")
|
| 313 |
+
|
| 314 |
+
if debug:
|
| 315 |
+
print(f"{debug} is countered by: {counter_map[debug]}")
|
| 316 |
+
|
| 317 |
+
# Process debug data if any
|
| 318 |
+
if debug:
|
| 319 |
+
debug_df = pd.DataFrame(debug_data)
|
| 320 |
+
print("\nDebug Data:")
|
| 321 |
+
print(debug_df)
|
| 322 |
+
|
| 323 |
+
# Create final DataFrame
|
| 324 |
+
champion_features = pd.DataFrame(feature_dict)
|
| 325 |
+
|
| 326 |
+
# Create the final DataFrame by combining original data with new features
|
| 327 |
+
features = pd.concat([
|
| 328 |
+
merged_player_stats[original_columns], # Keep all original columns
|
| 329 |
+
champion_features[[col for col in champion_features.columns if col not in original_columns]] # Only new champion columns
|
| 330 |
+
], axis=1)
|
| 331 |
+
|
| 332 |
+
# Move the champion column to be the first column
|
| 333 |
+
if 'champion' in features.columns:
|
| 334 |
+
columns = ['champion'] + [col for col in features.columns if col != 'champion']
|
| 335 |
+
features = features[columns]
|
| 336 |
+
|
| 337 |
+
# Save to CSV with current date in filename
|
| 338 |
+
output_file = os.path.join("util", "data", f"feature_eng_stats.csv")
|
| 339 |
+
os.makedirs(os.path.dirname(output_file), exist_ok=True)
|
| 340 |
+
features.to_csv(output_file, index=False)
|
| 341 |
+
|
| 342 |
+
# Print confirmation message
|
| 343 |
+
print(f"Saved features to {output_file}")
|
| 344 |
+
|
| 345 |
+
return features
|
| 346 |
+
|
| 347 |
+
except Exception as e:
|
| 348 |
+
print(f"\nError occurred: {str(e)}")
|
| 349 |
+
return None
|
| 350 |
+
|
| 351 |
+
if __name__ == "__main__":
|
| 352 |
+
try:
|
| 353 |
+
input_file = os.path.join("util", "data", f"player_stats_merged_2025-01-05.csv")
|
| 354 |
+
merged_stats = pd.read_csv(input_file)
|
| 355 |
+
|
| 356 |
+
features = create_champion_features(
|
| 357 |
+
merged_player_stats=merged_stats,
|
| 358 |
+
debug='Viktor',
|
| 359 |
+
consider_team_comp=True,
|
| 360 |
+
test_mode=True
|
| 361 |
+
)
|
| 362 |
+
|
| 363 |
+
if features is not None:
|
| 364 |
+
print("\nProcessing completed successfully!")
|
| 365 |
+
print(f"Generated features for {len(features)} rows")
|
| 366 |
+
else:
|
| 367 |
+
print("\nProcessing failed or was interrupted.")
|
| 368 |
+
|
| 369 |
+
except Exception as e:
|
| 370 |
+
print(f"\nFatal error: {str(e)}")
|
util/helper.py
ADDED
|
@@ -0,0 +1,1205 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
from datetime import datetime
|
| 3 |
+
import os
|
| 4 |
+
import numpy as np
|
| 5 |
+
from urllib.parse import quote, unquote
|
| 6 |
+
|
| 7 |
+
class ChampionConverter:
|
| 8 |
+
def __init__(self):
|
| 9 |
+
self.champions = [
|
| 10 |
+
"Aatrox", "Ahri", "Akali", "Akshan", "Alistar", "Ambessa", "Amumu", "Anivia", "Annie", "Aphelios", "Ashe", "Aurelion Sol",
|
| 11 |
+
"Aurora", "Azir", "Bard", "Bel'Veth", "Blitzcrank", "Brand", "Braum", "Briar", "Caitlyn", "Camille", "Cassiopeia", "Cho'Gath",
|
| 12 |
+
"Corki", "Darius", "Diana", "Dr. Mundo", "Draven", "Ekko", "Elise", "Evelynn", "Ezreal", "Fiddlesticks", "Fiora", "Fizz", "Galio",
|
| 13 |
+
"Gangplank", "Garen", "Gnar", "Gragas", "Graves", "Gwen", "Hecarim", "Heimerdinger", "Hwei", "Illaoi", "Irelia", "Ivern", "Janna",
|
| 14 |
+
"Jarvan IV", "Jax", "Jayce", "Jhin", "Jinx", "K'Sante", "Kai'Sa", "Kalista", "Karma", "Karthus", "Kassadin", "Katarina", "Kayle",
|
| 15 |
+
"Kayn", "Kennen", "Kha'Zix", "Kindred", "Kled", "Kog'Maw", "LeBlanc", "Lee Sin", "Leona", "Lillia", "Lissandra", "Lucian", "Lulu",
|
| 16 |
+
"Lux", "Malphite", "Malzahar", "Maokai", "Master Yi", "Milio", "Miss Fortune", "Mordekaiser", "Morgana", "Naafiri", "Nami", "Nasus",
|
| 17 |
+
"Nautilus", "Neeko", "Nidalee", "Nilah", "Nocturne", "Nunu & Willump", "Olaf", "Orianna", "Ornn", "Pantheon", "Poppy", "Pyke",
|
| 18 |
+
"Qiyana", "Quinn", "Rakan", "Rammus", "Rek'Sai", "Rell", "Renata Glasc", "Renekton", "Rengar", "Riven", "Rumble", "Ryze", "Samira",
|
| 19 |
+
"Sejuani", "Senna", "Seraphine", "Sett", "Shaco", "Shen", "Shyvana", "Singed", "Sion", "Sivir", "Skarner", "Smolder", "Sona",
|
| 20 |
+
"Soraka", "Swain", "Sylas", "Syndra", "Tahm Kench", "Taliyah", "Talon", "Taric", "Teemo", "Thresh", "Tristana", "Trundle",
|
| 21 |
+
"Tryndamere", "Twisted Fate", "Twitch", "Udyr", "Urgot", "Varus", "Vayne", "Veigar", "Vel'Koz", "Vex", "Vi", "Viego", "Viktor",
|
| 22 |
+
"Vladimir", "Volibear", "Warwick", "Wukong", "Xayah", "Xerath", "Xin Zhao", "Yasuo", "Yone", "Yorick", "Yuumi", "Zac", "Zed",
|
| 23 |
+
"Zeri", "Ziggs", "Zilean", "Zoe", "Zyra"
|
| 24 |
+
]
|
| 25 |
+
|
| 26 |
+
self.champion_to_number = {champion: i for i, champion in enumerate(self.champions, start=1)}
|
| 27 |
+
self.number_to_champion = {i: champion for i, champion in enumerate(self.champions, start=1)}
|
| 28 |
+
|
| 29 |
+
def champion_to_num(self, champion_name):
|
| 30 |
+
return self.champion_to_number.get(champion_name, None)
|
| 31 |
+
|
| 32 |
+
def num_to_champion(self, number):
|
| 33 |
+
return self.number_to_champion.get(number, None)
|
| 34 |
+
|
| 35 |
+
def convert_date(date_str):
|
| 36 |
+
"""Convert datetime string to Unix timestamp"""
|
| 37 |
+
try:
|
| 38 |
+
if pd.isna(date_str):
|
| 39 |
+
return None
|
| 40 |
+
return pd.to_datetime(date_str).timestamp()
|
| 41 |
+
except:
|
| 42 |
+
return None
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def convert_to_minutes(time_str):
|
| 46 |
+
"""Convert time string (e.g., '15m 10s') to minutes (float)"""
|
| 47 |
+
try:
|
| 48 |
+
minutes = seconds = 0
|
| 49 |
+
parts = time_str.lower().split()
|
| 50 |
+
for part in parts:
|
| 51 |
+
if 'm' in part:
|
| 52 |
+
minutes = float(part.replace('m', ''))
|
| 53 |
+
elif 's' in part:
|
| 54 |
+
seconds = float(part.replace('s', ''))
|
| 55 |
+
return round(minutes + seconds/60, 2)
|
| 56 |
+
except:
|
| 57 |
+
return 0.0
|
| 58 |
+
|
| 59 |
+
def convert_percentage_to_decimal(percentage_str):
|
| 60 |
+
"""Convert percentage string (e.g., 'P/Kill 43%') to decimal (0.43)"""
|
| 61 |
+
try:
|
| 62 |
+
# Extract number from string and convert to decimal
|
| 63 |
+
num = float(''.join(filter(str.isdigit, percentage_str))) / 100
|
| 64 |
+
return round(num, 2)
|
| 65 |
+
except:
|
| 66 |
+
return 0.0
|
| 67 |
+
|
| 68 |
+
def convert_tier_to_number(tier_str):
|
| 69 |
+
"""
|
| 70 |
+
Convert tier string to number:
|
| 71 |
+
Challenger -> 1
|
| 72 |
+
Grandmaster -> 2
|
| 73 |
+
Master -> 3
|
| 74 |
+
Others -> 4
|
| 75 |
+
"""
|
| 76 |
+
tier_map = {
|
| 77 |
+
'challenger': 1,
|
| 78 |
+
'grandmaster': 2,
|
| 79 |
+
'master': 3
|
| 80 |
+
}
|
| 81 |
+
# Convert to lowercase and return mapped value or 4 for any other tier
|
| 82 |
+
return tier_map.get(tier_str.lower().strip(), 4)
|
| 83 |
+
|
| 84 |
+
def convert_result_to_binary(result_str):
|
| 85 |
+
"""
|
| 86 |
+
Convert match result to binary:
|
| 87 |
+
Victory -> 1
|
| 88 |
+
Defeat -> 0
|
| 89 |
+
"""
|
| 90 |
+
return 1 if result_str.lower().strip() == 'victory' else 0
|
| 91 |
+
|
| 92 |
+
def merge_stats(recent_stats, player_stats, current_time =None):
|
| 93 |
+
"""
|
| 94 |
+
Merge recent match stats with player profile stats and save to CSV.
|
| 95 |
+
Only keeps rows where matches exist in both DataFrames.
|
| 96 |
+
|
| 97 |
+
Args:
|
| 98 |
+
recent_stats (DataFrame/dict): Recent match statistics
|
| 99 |
+
player_stats (DataFrame/tuple): Player profile statistics
|
| 100 |
+
|
| 101 |
+
Returns:
|
| 102 |
+
DataFrame: Combined statistics
|
| 103 |
+
"""
|
| 104 |
+
try:
|
| 105 |
+
if current_time is None:
|
| 106 |
+
current_time = datetime.utcnow().strftime("%Y-%m-%d")
|
| 107 |
+
|
| 108 |
+
# Convert recent_stats to DataFrame if it's not already
|
| 109 |
+
if not isinstance(recent_stats, pd.DataFrame):
|
| 110 |
+
recent_df = pd.DataFrame(recent_stats)
|
| 111 |
+
else:
|
| 112 |
+
recent_df = recent_stats
|
| 113 |
+
|
| 114 |
+
# Handle player_stats based on its type
|
| 115 |
+
if isinstance(player_stats, tuple):
|
| 116 |
+
# If it's a tuple (merged_df, dfs), use the merged_df
|
| 117 |
+
player_df = player_stats[0]
|
| 118 |
+
elif isinstance(player_stats, pd.DataFrame):
|
| 119 |
+
player_df = player_stats
|
| 120 |
+
else:
|
| 121 |
+
raise ValueError("Invalid player_stats format")
|
| 122 |
+
|
| 123 |
+
# Ensure player_id exists in both DataFrames
|
| 124 |
+
if 'player_id' not in recent_df.columns:
|
| 125 |
+
recent_df['player_id'] = player_df['player_id'].iloc[0]
|
| 126 |
+
|
| 127 |
+
# Print info before merge
|
| 128 |
+
print(f"\nBefore merge:")
|
| 129 |
+
print(f"Recent stats rows: {len(recent_df)}")
|
| 130 |
+
print(f"Player stats rows: {len(player_df)}")
|
| 131 |
+
print(f"Unique players in recent stats: {recent_df['player_id'].nunique()}")
|
| 132 |
+
print(f"Unique players in player stats: {player_df['player_id'].nunique()}")
|
| 133 |
+
|
| 134 |
+
# Merge DataFrames with inner join
|
| 135 |
+
merged_df = pd.merge(
|
| 136 |
+
recent_df,
|
| 137 |
+
player_df,
|
| 138 |
+
on='player_id',
|
| 139 |
+
how='inner', # Changed from 'left' to 'inner'
|
| 140 |
+
suffixes=('', '_profile')
|
| 141 |
+
)
|
| 142 |
+
|
| 143 |
+
# Print info after merge
|
| 144 |
+
print(f"\nAfter merge:")
|
| 145 |
+
print(f"Merged stats rows: {len(merged_df)}")
|
| 146 |
+
print(f"Unique players in merged stats: {merged_df['player_id'].nunique()}")
|
| 147 |
+
|
| 148 |
+
# Reorder columns to ensure player_id and region are first
|
| 149 |
+
cols = merged_df.columns.tolist()
|
| 150 |
+
cols = ['player_id'] + [col for col in cols if col != 'player_id']
|
| 151 |
+
if 'region' in cols:
|
| 152 |
+
cols.remove('region')
|
| 153 |
+
cols.insert(1, 'region')
|
| 154 |
+
merged_df = merged_df[cols]
|
| 155 |
+
|
| 156 |
+
# Create directory if it doesn't exist
|
| 157 |
+
save_dir = "util/data"
|
| 158 |
+
os.makedirs(save_dir, exist_ok=True)
|
| 159 |
+
|
| 160 |
+
# Save to CSV
|
| 161 |
+
filename = f"player_stats_merged_{current_time}.csv"
|
| 162 |
+
filepath = os.path.join(save_dir, filename)
|
| 163 |
+
merged_df.to_csv(filepath, index=False)
|
| 164 |
+
print(f"\nSuccessfully saved merged stats to {filepath}")
|
| 165 |
+
|
| 166 |
+
return merged_df
|
| 167 |
+
|
| 168 |
+
except Exception as e:
|
| 169 |
+
print(f"Error in merge_stats: {e}")
|
| 170 |
+
return None
|
| 171 |
+
|
| 172 |
+
|
| 173 |
+
def filter_leaderboard(df, tiers=None):
|
| 174 |
+
"""
|
| 175 |
+
Filter leaderboard DataFrame to keep only specific tiers.
|
| 176 |
+
|
| 177 |
+
Args:
|
| 178 |
+
df (pandas.DataFrame): Input leaderboard DataFrame
|
| 179 |
+
tiers (list): List of tiers to keep. Defaults to ["CHALLENGER", "GRANDMASTER"]
|
| 180 |
+
timestamp (str): Current timestamp in UTC
|
| 181 |
+
scraper_user (str): Current user's login
|
| 182 |
+
|
| 183 |
+
Returns:
|
| 184 |
+
pandas.DataFrame: Filtered leaderboard data
|
| 185 |
+
"""
|
| 186 |
+
try:
|
| 187 |
+
# Set default tiers if none provided
|
| 188 |
+
if tiers is None:
|
| 189 |
+
tiers = ["CHALLENGER", "GRANDMASTER"]
|
| 190 |
+
|
| 191 |
+
# Convert tiers to uppercase for consistency
|
| 192 |
+
tiers = [tier.upper() for tier in tiers]
|
| 193 |
+
|
| 194 |
+
# Validate input DataFrame
|
| 195 |
+
required_cols = ["tier", "summoner", "region"]
|
| 196 |
+
if not all(col in df.columns for col in required_cols):
|
| 197 |
+
raise ValueError(f"DataFrame must contain columns: {required_cols}")
|
| 198 |
+
|
| 199 |
+
# Create copy to avoid modifying original DataFrame
|
| 200 |
+
filtered_df = df.copy()
|
| 201 |
+
|
| 202 |
+
# Convert tier column to uppercase for consistent filtering
|
| 203 |
+
filtered_df['tier'] = filtered_df['tier'].str.upper()
|
| 204 |
+
|
| 205 |
+
# Filter by specified tiers
|
| 206 |
+
filtered_df = filtered_df[filtered_df['tier'].isin(tiers)]
|
| 207 |
+
|
| 208 |
+
|
| 209 |
+
# Sort by region and tier
|
| 210 |
+
filtered_df = filtered_df.sort_values(['region', 'tier', 'rank'])
|
| 211 |
+
|
| 212 |
+
# Reset index
|
| 213 |
+
filtered_df = filtered_df.reset_index(drop=True)
|
| 214 |
+
|
| 215 |
+
# Save to CSV
|
| 216 |
+
output_file = os.path.join("util", "data", "lb_filtered.csv")
|
| 217 |
+
os.makedirs(os.path.dirname(output_file), exist_ok=True)
|
| 218 |
+
filtered_df.to_csv(output_file, index=False)
|
| 219 |
+
|
| 220 |
+
print(f"\nFiltered leaderboard to {len(tiers)} tiers: {', '.join(tiers)}")
|
| 221 |
+
print(f"Remaining entries: {len(filtered_df)}")
|
| 222 |
+
print(f"Saved filtered leaderboard to {output_file}")
|
| 223 |
+
|
| 224 |
+
# Print summary statistics
|
| 225 |
+
print("\nSummary by region and tier:")
|
| 226 |
+
summary = filtered_df.groupby(['region', 'tier']).size().unstack(fill_value=0)
|
| 227 |
+
print(summary)
|
| 228 |
+
|
| 229 |
+
return filtered_df
|
| 230 |
+
|
| 231 |
+
except Exception as e:
|
| 232 |
+
print(f"Error filtering leaderboard: {e}")
|
| 233 |
+
return None
|
| 234 |
+
|
| 235 |
+
def format_summoner_name(summoner):
|
| 236 |
+
"""
|
| 237 |
+
Format summoner name for URL usage
|
| 238 |
+
|
| 239 |
+
Parameters:
|
| 240 |
+
summoner: str - Original summoner name
|
| 241 |
+
|
| 242 |
+
Returns:
|
| 243 |
+
str - Formatted summoner name
|
| 244 |
+
"""
|
| 245 |
+
if not summoner:
|
| 246 |
+
raise ValueError("Summoner name cannot be empty")
|
| 247 |
+
|
| 248 |
+
# Remove leading/trailing whitespace
|
| 249 |
+
summoner = summoner.strip()
|
| 250 |
+
|
| 251 |
+
# Replace spaces and special characters
|
| 252 |
+
formatted_summoner = summoner.replace(" ", "-").replace("#", "-")
|
| 253 |
+
|
| 254 |
+
# Handle other special characters through URL encoding
|
| 255 |
+
formatted_summoner = quote(formatted_summoner)
|
| 256 |
+
|
| 257 |
+
return formatted_summoner
|
| 258 |
+
|
| 259 |
+
def convert_to_displayname(name):
|
| 260 |
+
"""
|
| 261 |
+
Convert a summoner name to display format
|
| 262 |
+
Examples:
|
| 263 |
+
marthinsurya-NA -> marthinsurya #NA
|
| 264 |
+
toplane%20kid-EUW77 -> toplane kid #EUW77
|
| 265 |
+
Walid-Georgey-EUW -> Walid Georgey #EUW
|
| 266 |
+
Current%20User-KR -> Current User #KR
|
| 267 |
+
"""
|
| 268 |
+
try:
|
| 269 |
+
if not name:
|
| 270 |
+
return ""
|
| 271 |
+
|
| 272 |
+
# First decode URL encoding
|
| 273 |
+
decoded = unquote(name)
|
| 274 |
+
|
| 275 |
+
# Remove any trailing hyphens
|
| 276 |
+
decoded = decoded.rstrip('-')
|
| 277 |
+
|
| 278 |
+
# Split by last hyphen to separate name and region
|
| 279 |
+
if '-' in decoded:
|
| 280 |
+
parts = decoded.rsplit('-', 1)
|
| 281 |
+
base_name = parts[0] # Everything before last hyphen
|
| 282 |
+
region = parts[1]
|
| 283 |
+
|
| 284 |
+
# Replace remaining hyphens in base_name with spaces
|
| 285 |
+
base_name = base_name.replace('-', ' ')
|
| 286 |
+
|
| 287 |
+
# Clean up any double spaces
|
| 288 |
+
base_name = ' '.join(filter(None, base_name.split()))
|
| 289 |
+
|
| 290 |
+
return f"{base_name} #{region}"
|
| 291 |
+
|
| 292 |
+
return decoded.replace('-', ' ')
|
| 293 |
+
except Exception as e:
|
| 294 |
+
print(f"Error converting name '{name}': {e}")
|
| 295 |
+
return name
|
| 296 |
+
|
| 297 |
+
|
| 298 |
+
|
| 299 |
+
def get_player_list(leaderboard=None):
|
| 300 |
+
"""
|
| 301 |
+
Convert leaderboard data into proper player list format for API calls.
|
| 302 |
+
|
| 303 |
+
Args:
|
| 304 |
+
leaderboard (DataFrame): Input leaderboard DataFrame containing summoner and region
|
| 305 |
+
|
| 306 |
+
Returns:
|
| 307 |
+
DataFrame: Formatted player list with region and username columns
|
| 308 |
+
"""
|
| 309 |
+
try:
|
| 310 |
+
|
| 311 |
+
if leaderboard is None:
|
| 312 |
+
leaderboard_file = os.path.join("util", "data", "lb_filtered.csv")
|
| 313 |
+
leaderboard = pd.read_csv(leaderboard_file)
|
| 314 |
+
|
| 315 |
+
# Rename summoner column to username
|
| 316 |
+
leaderboard = leaderboard.rename(columns={'summoner': 'username'})
|
| 317 |
+
|
| 318 |
+
# Select only region and username columns in correct order
|
| 319 |
+
player_list = leaderboard[['region', 'username']]
|
| 320 |
+
|
| 321 |
+
print(f"Successfully processed {len(player_list)} players")
|
| 322 |
+
return player_list
|
| 323 |
+
|
| 324 |
+
except Exception as e:
|
| 325 |
+
print(f"Error processing leaderboard: {e}")
|
| 326 |
+
return None
|
| 327 |
+
|
| 328 |
+
def process_kda_perfect(df):
|
| 329 |
+
"""
|
| 330 |
+
Process KDA values in the DataFrame, replacing 'Perfect' with appropriate values.
|
| 331 |
+
"""
|
| 332 |
+
try:
|
| 333 |
+
# Create a copy to avoid modifying the original dataframe
|
| 334 |
+
df = df.copy()
|
| 335 |
+
|
| 336 |
+
# Function to safely convert to numeric
|
| 337 |
+
def safe_convert(x):
|
| 338 |
+
if isinstance(x, (int, float)):
|
| 339 |
+
return x
|
| 340 |
+
if isinstance(x, str) and x.lower() == 'perfect':
|
| 341 |
+
return 6
|
| 342 |
+
try:
|
| 343 |
+
return float(x)
|
| 344 |
+
except:
|
| 345 |
+
return None
|
| 346 |
+
|
| 347 |
+
# 1. Process KDA_1, KDA_2, KDA_3
|
| 348 |
+
for col in ['KDA_1', 'KDA_2', 'KDA_3']:
|
| 349 |
+
if col in df.columns:
|
| 350 |
+
df[col] = df[col].apply(safe_convert)
|
| 351 |
+
|
| 352 |
+
# 2. Process kda_ssn_1 to kda_ssn_7
|
| 353 |
+
for i in range(1, 8):
|
| 354 |
+
col = f'kda_ssn_{i}'
|
| 355 |
+
if col in df.columns:
|
| 356 |
+
perfect_mask = df[col].astype(str).str.contains('perfect', case=False)
|
| 357 |
+
if perfect_mask.any():
|
| 358 |
+
kills_col, assists_col = f'k_ssn_{i}', f'a_ssn_{i}'
|
| 359 |
+
if kills_col in df.columns and assists_col in df.columns:
|
| 360 |
+
df.loc[perfect_mask, col] = df.loc[perfect_mask].apply(
|
| 361 |
+
lambda row: pd.to_numeric(row[kills_col], errors='coerce') +
|
| 362 |
+
pd.to_numeric(row[assists_col], errors='coerce'),
|
| 363 |
+
axis=1
|
| 364 |
+
)
|
| 365 |
+
else:
|
| 366 |
+
df.loc[perfect_mask, col] = 6
|
| 367 |
+
df[col] = pd.to_numeric(df[col], errors='coerce')
|
| 368 |
+
|
| 369 |
+
# 3. Process kda_ratio_profile
|
| 370 |
+
if 'kda_ratio_profile' in df.columns:
|
| 371 |
+
perfect_mask = df['kda_ratio_profile'].astype(str).str.contains('perfect', case=False)
|
| 372 |
+
if perfect_mask.any():
|
| 373 |
+
df.loc[perfect_mask, 'kda_ratio_profile'] = df.loc[perfect_mask].apply(
|
| 374 |
+
lambda row: pd.to_numeric(row['avg_kills'], errors='coerce') +
|
| 375 |
+
pd.to_numeric(row['avg_assists'], errors='coerce'),
|
| 376 |
+
axis=1
|
| 377 |
+
)
|
| 378 |
+
df['kda_ratio_profile'] = pd.to_numeric(df['kda_ratio_profile'], errors='coerce')
|
| 379 |
+
|
| 380 |
+
# 4. Process remaining kda_ratio columns
|
| 381 |
+
other_cols = [col for col in df.columns if 'kda_ratio' in col.lower()
|
| 382 |
+
and col != 'kda_ratio_profile'
|
| 383 |
+
and col not in [f'kda_ssn_{i}' for i in range(1, 8)]]
|
| 384 |
+
|
| 385 |
+
for col in other_cols:
|
| 386 |
+
perfect_mask = df[col].astype(str).str.contains('perfect', case=False)
|
| 387 |
+
if perfect_mask.any():
|
| 388 |
+
prefix = col.split('kda_ratio')[0]
|
| 389 |
+
kills_col, assists_col = f"{prefix}kills", f"{prefix}assists"
|
| 390 |
+
if kills_col in df.columns and assists_col in df.columns:
|
| 391 |
+
df.loc[perfect_mask, col] = df.loc[perfect_mask].apply(
|
| 392 |
+
lambda row: pd.to_numeric(row[kills_col], errors='coerce') +
|
| 393 |
+
pd.to_numeric(row[assists_col], errors='coerce'),
|
| 394 |
+
axis=1
|
| 395 |
+
)
|
| 396 |
+
else:
|
| 397 |
+
df.loc[perfect_mask, col] = 6
|
| 398 |
+
df[col] = pd.to_numeric(df[col], errors='coerce')
|
| 399 |
+
|
| 400 |
+
return df
|
| 401 |
+
|
| 402 |
+
except Exception as e:
|
| 403 |
+
print(f"Error in process_kda_perfect: {str(e)}")
|
| 404 |
+
return df
|
| 405 |
+
|
| 406 |
+
|
| 407 |
+
def check_mixed_types(df):
|
| 408 |
+
"""
|
| 409 |
+
Check and print dataframe column types, inconsistencies, and basic statistics
|
| 410 |
+
"""
|
| 411 |
+
# Get type information
|
| 412 |
+
dtype_info = pd.DataFrame({
|
| 413 |
+
'dtype': df.dtypes,
|
| 414 |
+
'non_null': df.count(),
|
| 415 |
+
'null_count': df.isnull().sum(),
|
| 416 |
+
'unique_values': [df[col].nunique() for col in df.columns]
|
| 417 |
+
})
|
| 418 |
+
|
| 419 |
+
# Add sample of unique values for each column
|
| 420 |
+
dtype_info['sample_values'] = [df[col].dropna().sample(min(3, len(df[col].dropna()))).tolist()
|
| 421 |
+
if len(df[col].dropna()) > 0 else []
|
| 422 |
+
for col in df.columns]
|
| 423 |
+
|
| 424 |
+
# Check for mixed types in object columns
|
| 425 |
+
mixed_type_cols = []
|
| 426 |
+
for col in df.select_dtypes(include=['object']):
|
| 427 |
+
types = df[col].apply(type).unique()
|
| 428 |
+
if len(types) > 1:
|
| 429 |
+
mixed_type_cols.append({
|
| 430 |
+
'column': col,
|
| 431 |
+
'types': [t.__name__ for t in types],
|
| 432 |
+
'samples': df[col].dropna().sample(min(3, len(df[col].dropna()))).tolist()
|
| 433 |
+
})
|
| 434 |
+
|
| 435 |
+
print("=== DataFrame Overview ===")
|
| 436 |
+
print(f"Shape: {df.shape}")
|
| 437 |
+
print("\n=== Data Types Summary ===")
|
| 438 |
+
print(df.dtypes.value_counts())
|
| 439 |
+
|
| 440 |
+
if mixed_type_cols:
|
| 441 |
+
print("\n=== Mixed Type Columns ===")
|
| 442 |
+
for col_info in mixed_type_cols:
|
| 443 |
+
print(f"\nColumn: {col_info['column']}")
|
| 444 |
+
print(f"Types found: {col_info['types']}")
|
| 445 |
+
print(f"Sample values: {col_info['samples']}")
|
| 446 |
+
|
| 447 |
+
return dtype_info
|
| 448 |
+
|
| 449 |
+
def check_nan_float(df, column_name):
|
| 450 |
+
float_mask = df[column_name].apply(lambda x: isinstance(x, float))
|
| 451 |
+
is_nan_mask = df[column_name].isna()
|
| 452 |
+
|
| 453 |
+
# Check if all float values are NaN
|
| 454 |
+
all_floats_are_nan = (float_mask == is_nan_mask).all()
|
| 455 |
+
print(f"Are all float values NaN? {all_floats_are_nan}")
|
| 456 |
+
|
| 457 |
+
# Double check by comparing counts
|
| 458 |
+
print(f"Number of float values: {float_mask.sum()}")
|
| 459 |
+
print(f"Number of NaN values: {is_nan_mask.sum()}")
|
| 460 |
+
|
| 461 |
+
def convert_team_colors(df):
|
| 462 |
+
"""
|
| 463 |
+
Convert 'team' column values from 'blue'/'red' to 1/2
|
| 464 |
+
|
| 465 |
+
Parameters:
|
| 466 |
+
df (pandas.DataFrame): Input DataFrame with 'team' column
|
| 467 |
+
|
| 468 |
+
Returns:
|
| 469 |
+
pandas.DataFrame: DataFrame with converted team values
|
| 470 |
+
"""
|
| 471 |
+
df = df.copy()
|
| 472 |
+
|
| 473 |
+
if 'team' not in df.columns:
|
| 474 |
+
raise ValueError("Column 'team' not found in DataFrame")
|
| 475 |
+
|
| 476 |
+
# Create mapping dictionary
|
| 477 |
+
team_mapping = {
|
| 478 |
+
'blue': 1,
|
| 479 |
+
'red': 2
|
| 480 |
+
}
|
| 481 |
+
|
| 482 |
+
# Convert team colors to numbers
|
| 483 |
+
df['team'] = df['team'].map(team_mapping, na_action='ignore')
|
| 484 |
+
|
| 485 |
+
return df
|
| 486 |
+
|
| 487 |
+
def convert_region(df):
|
| 488 |
+
"""
|
| 489 |
+
Convert 'region' column values to numeric:
|
| 490 |
+
kr -> 1
|
| 491 |
+
euw -> 2
|
| 492 |
+
vn -> 3
|
| 493 |
+
na -> 4
|
| 494 |
+
|
| 495 |
+
Parameters:
|
| 496 |
+
df (pandas.DataFrame): Input DataFrame with 'region' column
|
| 497 |
+
|
| 498 |
+
Returns:
|
| 499 |
+
pandas.DataFrame: DataFrame with converted region values
|
| 500 |
+
"""
|
| 501 |
+
df = df.copy()
|
| 502 |
+
|
| 503 |
+
if 'region' not in df.columns:
|
| 504 |
+
raise ValueError("Column 'region' not found in DataFrame")
|
| 505 |
+
|
| 506 |
+
# Create mapping dictionary
|
| 507 |
+
region_mapping = {
|
| 508 |
+
'kr': 1,
|
| 509 |
+
'euw': 2,
|
| 510 |
+
'vn': 3,
|
| 511 |
+
'na': 4
|
| 512 |
+
}
|
| 513 |
+
|
| 514 |
+
# Convert regions to numbers, keeping NA as NA
|
| 515 |
+
df['region'] = df['region'].map(region_mapping, na_action='ignore')
|
| 516 |
+
|
| 517 |
+
return df
|
| 518 |
+
|
| 519 |
+
def convert_champion_columns(df):
|
| 520 |
+
"""
|
| 521 |
+
Convert all champion-related columns to numbers using ChampionConverter
|
| 522 |
+
|
| 523 |
+
Parameters:
|
| 524 |
+
df (pandas.DataFrame): Input DataFrame
|
| 525 |
+
|
| 526 |
+
Returns:
|
| 527 |
+
pandas.DataFrame: DataFrame with converted champion values
|
| 528 |
+
"""
|
| 529 |
+
df = df.copy()
|
| 530 |
+
|
| 531 |
+
# Initialize champion converter
|
| 532 |
+
converter = ChampionConverter()
|
| 533 |
+
|
| 534 |
+
# Get all champion-related columns
|
| 535 |
+
champion_columns = [col for col in df.columns if 'champ' in col.lower()]
|
| 536 |
+
|
| 537 |
+
for col in champion_columns:
|
| 538 |
+
# Convert champion names to numbers
|
| 539 |
+
df[col] = df[col].map(converter.champion_to_num, na_action='ignore')
|
| 540 |
+
|
| 541 |
+
return df
|
| 542 |
+
|
| 543 |
+
def convert_date_column(df):
|
| 544 |
+
"""
|
| 545 |
+
Convert date column from string format to Unix timestamp
|
| 546 |
+
Handles missing values (NaT, None, NaN)
|
| 547 |
+
|
| 548 |
+
Parameters:
|
| 549 |
+
df (pandas.DataFrame): Input DataFrame with 'date' column
|
| 550 |
+
|
| 551 |
+
Returns:
|
| 552 |
+
pandas.DataFrame: DataFrame with converted date values
|
| 553 |
+
"""
|
| 554 |
+
df = df.copy()
|
| 555 |
+
|
| 556 |
+
if 'date' not in df.columns:
|
| 557 |
+
raise ValueError("Column 'date' not found in DataFrame")
|
| 558 |
+
|
| 559 |
+
# Convert dates to timestamps
|
| 560 |
+
df['date'] = df['date'].apply(convert_date)
|
| 561 |
+
|
| 562 |
+
return df
|
| 563 |
+
|
| 564 |
+
def convert_role_columns(df):
|
| 565 |
+
"""
|
| 566 |
+
Convert role columns to numbers:
|
| 567 |
+
TOP -> 1, MID -> 2, ADC -> 3, JUNGLE -> 4, SUPPORT -> 5
|
| 568 |
+
|
| 569 |
+
Parameters:
|
| 570 |
+
df (pandas.DataFrame): Input DataFrame
|
| 571 |
+
|
| 572 |
+
Returns:
|
| 573 |
+
pandas.DataFrame: DataFrame with converted role values
|
| 574 |
+
"""
|
| 575 |
+
df = df.copy()
|
| 576 |
+
|
| 577 |
+
# Define role mapping
|
| 578 |
+
role_mapping = {
|
| 579 |
+
'TOP': 1,
|
| 580 |
+
'MID': 2,
|
| 581 |
+
'ADC': 3,
|
| 582 |
+
'JUNGLE': 4,
|
| 583 |
+
'SUPPORT': 5
|
| 584 |
+
}
|
| 585 |
+
|
| 586 |
+
# Role columns to convert
|
| 587 |
+
role_columns = ['most_role_1', 'most_role_2']
|
| 588 |
+
|
| 589 |
+
|
| 590 |
+
for col in role_columns:
|
| 591 |
+
if col in df.columns:
|
| 592 |
+
# Convert roles to numbers
|
| 593 |
+
df[col] = df[col].map(role_mapping, na_action='ignore')
|
| 594 |
+
|
| 595 |
+
else:
|
| 596 |
+
print(f"Warning: Column {col} not found in DataFrame")
|
| 597 |
+
|
| 598 |
+
return df
|
| 599 |
+
|
| 600 |
+
def convert_id_columns(df):
|
| 601 |
+
"""
|
| 602 |
+
Drop ID-related columns (player_id, teammates1-4, oppmates1-5)
|
| 603 |
+
|
| 604 |
+
Parameters:
|
| 605 |
+
df (pandas.DataFrame): Input DataFrame
|
| 606 |
+
|
| 607 |
+
Returns:
|
| 608 |
+
pandas.DataFrame: DataFrame with ID columns dropped
|
| 609 |
+
"""
|
| 610 |
+
df = df.copy()
|
| 611 |
+
|
| 612 |
+
# Specific ID columns to drop
|
| 613 |
+
id_columns = (
|
| 614 |
+
['player_id', 'region_profile'] +
|
| 615 |
+
[f'teammates{i}' for i in range(1, 5)] + # teammates1 to teammates4
|
| 616 |
+
[f'oppmates{i}' for i in range(1, 6)] # oppmates1 to oppmates5
|
| 617 |
+
)
|
| 618 |
+
|
| 619 |
+
|
| 620 |
+
# Verify columns exist and drop them
|
| 621 |
+
existing_columns = [col for col in id_columns if col in df.columns]
|
| 622 |
+
if len(existing_columns) != len(id_columns):
|
| 623 |
+
missing = set(id_columns) - set(existing_columns)
|
| 624 |
+
print(f"Note: Some columns were not found in DataFrame: {missing}")
|
| 625 |
+
|
| 626 |
+
# Drop the columns
|
| 627 |
+
df = df.drop(columns=existing_columns)
|
| 628 |
+
|
| 629 |
+
return df
|
| 630 |
+
|
| 631 |
+
def remove_match_stats(df):
|
| 632 |
+
"""
|
| 633 |
+
Remove match-specific statistics to prevent future data leakage.
|
| 634 |
+
|
| 635 |
+
Parameters:
|
| 636 |
+
df (pandas.DataFrame): Input DataFrame
|
| 637 |
+
|
| 638 |
+
Returns:
|
| 639 |
+
pandas.DataFrame: DataFrame with match-specific columns removed
|
| 640 |
+
"""
|
| 641 |
+
# List of columns that contain match-specific information
|
| 642 |
+
match_stat_columns = [
|
| 643 |
+
'level', # Champion level
|
| 644 |
+
'result', # Match outcome (target variable)
|
| 645 |
+
'match_length_mins',# Match duration
|
| 646 |
+
'kill', # Kills in the match
|
| 647 |
+
'death', # Deaths in the match
|
| 648 |
+
'assist', # Assists in the match
|
| 649 |
+
'kda_ratio', # KDA ratio for the match
|
| 650 |
+
'kill_participation',# Kill participation in the match
|
| 651 |
+
'laning', # Laning phase performance
|
| 652 |
+
'cs', # Creep score in the match
|
| 653 |
+
'cs_per_min' # CS per minute in the match
|
| 654 |
+
]
|
| 655 |
+
|
| 656 |
+
# Create a copy of the dataframe
|
| 657 |
+
df_clean = df.copy()
|
| 658 |
+
|
| 659 |
+
# Remove match-specific columns
|
| 660 |
+
columns_to_drop = [col for col in match_stat_columns if col in df_clean.columns]
|
| 661 |
+
df_clean = df_clean.drop(columns=columns_to_drop)
|
| 662 |
+
|
| 663 |
+
return df_clean
|
| 664 |
+
|
| 665 |
+
def convert_df(df):
|
| 666 |
+
"""
|
| 667 |
+
Master function to handle all conversions for training DataFrame
|
| 668 |
+
|
| 669 |
+
Includes:
|
| 670 |
+
- Team color conversion (blue/red to 1/2)
|
| 671 |
+
- Region conversion (kr/euw/vn/na to 1/2/3/4)
|
| 672 |
+
- Champion conversion (champion names to numbers)
|
| 673 |
+
- Date conversion (string to Unix timestamp)
|
| 674 |
+
- Role conversion (TOP/MID/ADC/JUNGLE/SUPPORT to 1/2/3/4/5)
|
| 675 |
+
- Drop ID columns (player_id, teammates1-4, oppmates1-5, region_profile)
|
| 676 |
+
|
| 677 |
+
Parameters:
|
| 678 |
+
df (pandas.DataFrame): Input training DataFrame
|
| 679 |
+
|
| 680 |
+
Returns:
|
| 681 |
+
pandas.DataFrame: Processed DataFrame with all conversions
|
| 682 |
+
"""
|
| 683 |
+
df = df.copy()
|
| 684 |
+
|
| 685 |
+
# Drop rows where champion is NA
|
| 686 |
+
initial_rows = len(df)
|
| 687 |
+
df = df.dropna(subset=['champion'])
|
| 688 |
+
rows_dropped = initial_rows - len(df)
|
| 689 |
+
print(f"Dropped {rows_dropped} rows with NA champion values")
|
| 690 |
+
|
| 691 |
+
# Sequential conversions
|
| 692 |
+
conversions = [
|
| 693 |
+
convert_team_colors, # Convert blue/red to 1/2
|
| 694 |
+
convert_region, # Convert kr/euw/vn/na to 1/2/3/4
|
| 695 |
+
convert_champion_columns, # Convert champion names to numbers
|
| 696 |
+
convert_date_column, # Convert dates to timestamps
|
| 697 |
+
convert_role_columns, # Convert roles to 1-5
|
| 698 |
+
convert_id_columns, # Drop ID-related columns
|
| 699 |
+
remove_match_stats # Remove match-specific columns
|
| 700 |
+
]
|
| 701 |
+
|
| 702 |
+
## Apply each conversion function in sequence
|
| 703 |
+
for convert_func in conversions:
|
| 704 |
+
try:
|
| 705 |
+
print(f"Applying {convert_func.__name__}...")
|
| 706 |
+
df = convert_func(df)
|
| 707 |
+
except Exception as e:
|
| 708 |
+
print(f"Error in {convert_func.__name__}: {str(e)}")
|
| 709 |
+
raise
|
| 710 |
+
|
| 711 |
+
return df
|
| 712 |
+
|
| 713 |
+
|
| 714 |
+
def get_top_champion_scores(df, n=5):
|
| 715 |
+
"""
|
| 716 |
+
Get top n champion scores from a DataFrame
|
| 717 |
+
|
| 718 |
+
Parameters:
|
| 719 |
+
df: pandas DataFrame containing champion scores
|
| 720 |
+
n: number of top champions to return (default 5)
|
| 721 |
+
|
| 722 |
+
Returns:
|
| 723 |
+
pandas DataFrame with original data plus top n champion scores and their names
|
| 724 |
+
"""
|
| 725 |
+
try:
|
| 726 |
+
converter = ChampionConverter()
|
| 727 |
+
df = df.copy()
|
| 728 |
+
|
| 729 |
+
# Get all champion columns (from Aatrox to Zyra)
|
| 730 |
+
champion_start = df.columns.get_loc('Aatrox')
|
| 731 |
+
champion_end = df.columns.get_loc('Zyra') + 1
|
| 732 |
+
champion_cols = df.columns[champion_start:champion_end]
|
| 733 |
+
|
| 734 |
+
# Convert scores to numeric, replacing non-numeric values with 0
|
| 735 |
+
champion_scores = df[champion_cols].apply(pd.to_numeric, errors='coerce').fillna(0)
|
| 736 |
+
|
| 737 |
+
# Get indices of top n values for each row
|
| 738 |
+
top_n_indices = champion_scores.apply(lambda x: pd.Series(x.nlargest(n).index), axis=1)
|
| 739 |
+
top_n_values = champion_scores.apply(lambda x: pd.Series(x.nlargest(n).values), axis=1)
|
| 740 |
+
|
| 741 |
+
# Create new columns for champion names and scores
|
| 742 |
+
for i in range(n):
|
| 743 |
+
# Champion scores
|
| 744 |
+
df[f'{i+1}_champ_score'] = top_n_values.iloc[:, i].astype(float)
|
| 745 |
+
|
| 746 |
+
# Champion names (converted to numbers)
|
| 747 |
+
champ_names = top_n_indices.iloc[:, i]
|
| 748 |
+
df[f'{i+1}_champ_name'] = champ_names.map(
|
| 749 |
+
lambda x: int(converter.champion_to_num(x)) if pd.notnull(x) else -1
|
| 750 |
+
)
|
| 751 |
+
|
| 752 |
+
return df
|
| 753 |
+
|
| 754 |
+
except Exception as e:
|
| 755 |
+
print(f"Error in get_top_champion_scores: {str(e)}")
|
| 756 |
+
# Return original DataFrame with default values in case of error
|
| 757 |
+
for i in range(1, n + 1):
|
| 758 |
+
df[f'{i}_champ_score'] = 0.0
|
| 759 |
+
df[f'{i}_champ_name'] = -1
|
| 760 |
+
return df
|
| 761 |
+
|
| 762 |
+
def check_datatypes(df):
|
| 763 |
+
datatype= pd.DataFrame({
|
| 764 |
+
'dtype': df.dtypes,
|
| 765 |
+
'unique_values': df.nunique()
|
| 766 |
+
})
|
| 767 |
+
|
| 768 |
+
print(datatype)
|
| 769 |
+
return datatype
|
| 770 |
+
|
| 771 |
+
def calculate_champ_variety_score(df):
|
| 772 |
+
df = df.copy() # Create a copy to avoid warnings
|
| 773 |
+
|
| 774 |
+
# Create a list of champion columns we want to check
|
| 775 |
+
champ_columns = [
|
| 776 |
+
'most_champ_1', 'most_champ_2', 'most_champ_3',
|
| 777 |
+
'7d_champ_1', '7d_champ_2', '7d_champ_3'
|
| 778 |
+
]
|
| 779 |
+
|
| 780 |
+
# Filter to only include columns that exist in the DataFrame
|
| 781 |
+
existing_columns = [col for col in champ_columns if col in df.columns]
|
| 782 |
+
|
| 783 |
+
# Function to count unique non-NaN values
|
| 784 |
+
def count_unique_champions(row):
|
| 785 |
+
# Get all values that are not NaN
|
| 786 |
+
valid_champions = row[existing_columns].dropna()
|
| 787 |
+
# Count unique values
|
| 788 |
+
return len(set(valid_champions))
|
| 789 |
+
|
| 790 |
+
# Calculate the score for each row
|
| 791 |
+
df['champ_variety_score'] = df.apply(count_unique_champions, axis=1)
|
| 792 |
+
|
| 793 |
+
return df
|
| 794 |
+
|
| 795 |
+
def calculate_playstyle(df):
|
| 796 |
+
df = df.copy()
|
| 797 |
+
|
| 798 |
+
# Playstyle categorization (0-5)
|
| 799 |
+
conditions = [
|
| 800 |
+
# 0: Assassin/Carry (high kills, high KDA, high kill participation)
|
| 801 |
+
(df['avg_kills'] > df['avg_assists']) &
|
| 802 |
+
(df['kda_ratio_profile'] > 3) &
|
| 803 |
+
(df['kill_participation_profile'] > 0.6),
|
| 804 |
+
|
| 805 |
+
# 1: Support/Utility (high assists, good KDA, high kill participation)
|
| 806 |
+
(df['avg_assists'] > df['avg_kills']) &
|
| 807 |
+
(df['kda_ratio_profile'] > 2.5) &
|
| 808 |
+
(df['kill_participation_profile'] > 0.55),
|
| 809 |
+
|
| 810 |
+
# 2: Tank/Initiator (moderate deaths, high assists, high kill participation)
|
| 811 |
+
(df['avg_deaths'] > 3) &
|
| 812 |
+
(df['avg_assists'] > df['avg_kills']) &
|
| 813 |
+
(df['kill_participation_profile'] > 0.5),
|
| 814 |
+
|
| 815 |
+
# 3: Split-pusher (lower kill participation, good KDA)
|
| 816 |
+
(df['kill_participation_profile'] < 0.5) &
|
| 817 |
+
(df['kda_ratio_profile'] > 2),
|
| 818 |
+
|
| 819 |
+
# 4: Aggressive/Fighter (high kills and deaths, high kill participation)
|
| 820 |
+
(df['avg_kills'] > 3) &
|
| 821 |
+
(df['avg_deaths'] > 4) &
|
| 822 |
+
(df['kill_participation_profile'] > 0.55)
|
| 823 |
+
]
|
| 824 |
+
|
| 825 |
+
values = [0, 1, 2, 3, 4] # Numeric values for each playstyle
|
| 826 |
+
df['playstyle'] = np.select(conditions, values, default=5)
|
| 827 |
+
|
| 828 |
+
return df
|
| 829 |
+
|
| 830 |
+
def get_most_role_3(df):
|
| 831 |
+
df = df.copy()
|
| 832 |
+
|
| 833 |
+
# Role mapping
|
| 834 |
+
role_mapping = {
|
| 835 |
+
'TOP': 1,
|
| 836 |
+
'MID': 2,
|
| 837 |
+
'ADC': 3,
|
| 838 |
+
'JUNGLE': 4,
|
| 839 |
+
'SUPPORT': 5
|
| 840 |
+
}
|
| 841 |
+
|
| 842 |
+
def get_third_role_info(row):
|
| 843 |
+
# Create dictionary of role values excluding most_role_1 and most_role_2
|
| 844 |
+
role_values = {
|
| 845 |
+
'TOP': row['TOP'],
|
| 846 |
+
'JUNGLE': row['JUNGLE'],
|
| 847 |
+
'MID': row['MID'],
|
| 848 |
+
'ADC': row['ADC'],
|
| 849 |
+
'SUPPORT': row['SUPPORT']
|
| 850 |
+
}
|
| 851 |
+
|
| 852 |
+
# Remove most_role_1 and most_role_2 from consideration
|
| 853 |
+
role_values.pop(row['most_role_1'], None)
|
| 854 |
+
role_values.pop(row['most_role_2'], None)
|
| 855 |
+
|
| 856 |
+
# Find highest remaining role and its value
|
| 857 |
+
if role_values:
|
| 858 |
+
third_role, third_value = max(role_values.items(), key=lambda x: x[1])
|
| 859 |
+
return role_mapping[third_role], third_value
|
| 860 |
+
return 0, 0.0 # Default values if no third role found
|
| 861 |
+
|
| 862 |
+
# Add both most_role_3 and most_role_3_value
|
| 863 |
+
df[['most_role_3', 'most_role_3_value']] = df.apply(get_third_role_info, axis=1, result_type='expand')
|
| 864 |
+
|
| 865 |
+
return df
|
| 866 |
+
|
| 867 |
+
def calculate_role_specialization(df):
|
| 868 |
+
df = df.copy()
|
| 869 |
+
|
| 870 |
+
# Define conditions for role specialization
|
| 871 |
+
conditions = [
|
| 872 |
+
# 0: Pure Specialist (one dominant role)
|
| 873 |
+
(df['most_role_1_value'] > 0.6),
|
| 874 |
+
|
| 875 |
+
# 1: Strong Dual Role (two significant roles)
|
| 876 |
+
(df['most_role_1_value'] <= 0.6) &
|
| 877 |
+
(df['most_role_2_value'] >= 0.3),
|
| 878 |
+
|
| 879 |
+
# 2: Primary Role with Backups (moderate first role, has backups)
|
| 880 |
+
(df['most_role_1_value'] <= 0.6) &
|
| 881 |
+
(df['most_role_2_value'] < 0.3) &
|
| 882 |
+
(df['most_role_1_value'] > 0.3) &
|
| 883 |
+
(df['most_role_3_value'] > 0.1), # Has a viable third role
|
| 884 |
+
|
| 885 |
+
# 3: Role Swapper (moderate first role, low others)
|
| 886 |
+
(df['most_role_1_value'] <= 0.6) &
|
| 887 |
+
(df['most_role_2_value'] < 0.3) &
|
| 888 |
+
(df['most_role_1_value'] > 0.3) &
|
| 889 |
+
(df['most_role_3_value'] <= 0.1), # No viable third role
|
| 890 |
+
|
| 891 |
+
# 4: True Flex (plays multiple roles evenly)
|
| 892 |
+
(df['most_role_1_value'] <= 0.3) &
|
| 893 |
+
(df['most_role_1_value'] > 0) &
|
| 894 |
+
(df['most_role_3_value'] >= 0.15) # Significant third role
|
| 895 |
+
]
|
| 896 |
+
|
| 897 |
+
# 5 will be No Preference/Undefined (very low values or missing data)
|
| 898 |
+
values = [0, 1, 2, 3, 4] # Numeric values for each category
|
| 899 |
+
df['role_specialization'] = np.select(conditions, values, default=5)
|
| 900 |
+
|
| 901 |
+
return df
|
| 902 |
+
|
| 903 |
+
def calculate_champion_loyalty(df):
|
| 904 |
+
df = df.copy()
|
| 905 |
+
|
| 906 |
+
def get_loyalty_scores(row):
|
| 907 |
+
try:
|
| 908 |
+
# Get champions lists, handle potential NaN/None values (only top 2)
|
| 909 |
+
recent_champs = [
|
| 910 |
+
row['most_champ_1'] if pd.notna(row['most_champ_1']) else None,
|
| 911 |
+
row['most_champ_2'] if pd.notna(row['most_champ_2']) else None
|
| 912 |
+
]
|
| 913 |
+
|
| 914 |
+
# Include all 7 season champions
|
| 915 |
+
season_champs = []
|
| 916 |
+
season_games = []
|
| 917 |
+
for i in range(1, 8):
|
| 918 |
+
champ = row[f'season_champ_{i}'] if pd.notna(row[f'season_champ_{i}']) else None
|
| 919 |
+
games = row[f'games_ssn_{i}'] if pd.notna(row[f'games_ssn_{i}']) else 0
|
| 920 |
+
if champ is not None:
|
| 921 |
+
season_champs.append(champ)
|
| 922 |
+
season_games.append(games)
|
| 923 |
+
|
| 924 |
+
# Add individual champion loyalty flags (only top 2)
|
| 925 |
+
champ_loyalty_flags = {
|
| 926 |
+
'recent_champ_1_loyal': 1 if (pd.notna(row['most_champ_1']) and
|
| 927 |
+
row['most_champ_1'] in season_champs) else 0,
|
| 928 |
+
'recent_champ_2_loyal': 1 if (pd.notna(row['most_champ_2']) and
|
| 929 |
+
row['most_champ_2'] in season_champs) else 0
|
| 930 |
+
}
|
| 931 |
+
|
| 932 |
+
# Remove None values from recent champions
|
| 933 |
+
recent_champs = [c for c in recent_champs if c is not None]
|
| 934 |
+
|
| 935 |
+
# If no valid champions, return defaults
|
| 936 |
+
if not recent_champs or not season_champs:
|
| 937 |
+
return {
|
| 938 |
+
'loyalty_score': 0,
|
| 939 |
+
'confidence_score': 0,
|
| 940 |
+
**champ_loyalty_flags
|
| 941 |
+
}
|
| 942 |
+
|
| 943 |
+
# Calculate games played for recent champions (only top 2)
|
| 944 |
+
recent_games = [
|
| 945 |
+
(row['W_1'] + row['L_1']) if pd.notna(row['most_champ_1']) else 0,
|
| 946 |
+
(row['W_2'] + row['L_2']) if pd.notna(row['most_champ_2']) else 0
|
| 947 |
+
]
|
| 948 |
+
|
| 949 |
+
total_recent_games = sum(recent_games)
|
| 950 |
+
total_season_games = sum(season_games)
|
| 951 |
+
|
| 952 |
+
if total_recent_games == 0:
|
| 953 |
+
return {
|
| 954 |
+
'loyalty_score': 0,
|
| 955 |
+
'confidence_score': 0,
|
| 956 |
+
**champ_loyalty_flags
|
| 957 |
+
}
|
| 958 |
+
|
| 959 |
+
# Calculate overlap score with enhanced weights
|
| 960 |
+
loyalty_score = 0
|
| 961 |
+
for idx, champ in enumerate(recent_champs):
|
| 962 |
+
if champ in season_champs:
|
| 963 |
+
season_idx = season_champs.index(champ)
|
| 964 |
+
|
| 965 |
+
recent_weight = recent_games[idx] / total_recent_games
|
| 966 |
+
season_weight = season_games[season_idx] / total_season_games
|
| 967 |
+
position_weight = 1.7 if idx == 0 else 1.3 # Adjusted weights for 2 champions
|
| 968 |
+
seasonal_position_weight = 1.3 if season_idx < 3 else 1.0
|
| 969 |
+
|
| 970 |
+
combined_weight = (
|
| 971 |
+
recent_weight * 0.6 +
|
| 972 |
+
season_weight * 0.4
|
| 973 |
+
) * position_weight * seasonal_position_weight
|
| 974 |
+
|
| 975 |
+
loyalty_score += combined_weight
|
| 976 |
+
|
| 977 |
+
# Calculate confidence score (adjusted for 2 champions)
|
| 978 |
+
confidence_score = 0
|
| 979 |
+
confidence_score += 0.5 if pd.notna(row['most_champ_1']) else 0 # Increased weight for main
|
| 980 |
+
confidence_score += 0.2 if pd.notna(row['most_champ_2']) else 0 # Increased weight for second
|
| 981 |
+
confidence_score += sum(0.1 for i in range(1, 4) if pd.notna(row[f'season_champ_{i}']))
|
| 982 |
+
confidence_score += sum(0.05 for i in range(4, 8) if pd.notna(row[f'season_champ_{i}']))
|
| 983 |
+
|
| 984 |
+
recent_games = sum((row[f'W_{i}'] + row[f'L_{i}']) if pd.notna(row[f'most_champ_{i}']) else 0
|
| 985 |
+
for i in range(1, 3)) # Only top 2
|
| 986 |
+
confidence_score += min(0.1, recent_games / 100)
|
| 987 |
+
|
| 988 |
+
return {
|
| 989 |
+
'loyalty_score': round(min(loyalty_score, 1.0), 3),
|
| 990 |
+
'confidence_score': round(min(confidence_score, 1.0), 3),
|
| 991 |
+
**champ_loyalty_flags
|
| 992 |
+
}
|
| 993 |
+
|
| 994 |
+
except Exception as e:
|
| 995 |
+
print(f"Error calculating loyalty scores: {e}")
|
| 996 |
+
return {
|
| 997 |
+
'loyalty_score': 0,
|
| 998 |
+
'confidence_score': 0,
|
| 999 |
+
'recent_champ_1_loyal': 0,
|
| 1000 |
+
'recent_champ_2_loyal': 0
|
| 1001 |
+
}
|
| 1002 |
+
|
| 1003 |
+
# Apply calculations and expand results to columns
|
| 1004 |
+
results = df.apply(get_loyalty_scores, axis=1)
|
| 1005 |
+
|
| 1006 |
+
# Convert results to new columns
|
| 1007 |
+
df['champion_loyalty_score'] = results.apply(lambda x: x['loyalty_score'])
|
| 1008 |
+
df['loyalty_confidence_score'] = results.apply(lambda x: x['confidence_score'])
|
| 1009 |
+
df['recent_champ_1_loyal'] = results.apply(lambda x: x['recent_champ_1_loyal'])
|
| 1010 |
+
df['recent_champ_2_loyal'] = results.apply(lambda x: x['recent_champ_2_loyal'])
|
| 1011 |
+
|
| 1012 |
+
return df
|
| 1013 |
+
|
| 1014 |
+
def optimize_feature_dtypes(df):
|
| 1015 |
+
"""
|
| 1016 |
+
Optimize data types for feature columns using unsigned integers for non-negative values
|
| 1017 |
+
"""
|
| 1018 |
+
df = df.copy()
|
| 1019 |
+
|
| 1020 |
+
# Very small range integers (< 10 unique values) to uint8 (0 to 255)
|
| 1021 |
+
category_cols = {
|
| 1022 |
+
'region': 4, # 4 unique values
|
| 1023 |
+
'team': 2, # 2 unique values
|
| 1024 |
+
'champ_variety_score': 6, # 6 unique values
|
| 1025 |
+
'playstyle': 6, # 6 unique values
|
| 1026 |
+
'most_role_1': 5, # 5 unique values
|
| 1027 |
+
'most_role_2': 5, # 5 unique values
|
| 1028 |
+
'most_role_3': 5, # 5 unique values
|
| 1029 |
+
'role_specialization': 5, # 5 unique values
|
| 1030 |
+
'recent_champ_1_loyal':2, # 2 unique values
|
| 1031 |
+
'recent_champ_2_loyal':2 # 2 unique values
|
| 1032 |
+
}
|
| 1033 |
+
|
| 1034 |
+
for col, n_unique in category_cols.items():
|
| 1035 |
+
if col in df.columns:
|
| 1036 |
+
if df[col].isna().any():
|
| 1037 |
+
# For columns with NaN, ensure proper handling
|
| 1038 |
+
df[col] = df[col].astype('category')
|
| 1039 |
+
# Fill NaN with a new category if needed
|
| 1040 |
+
df[col] = df[col].cat.add_categories(['Unknown']).fillna('Unknown')
|
| 1041 |
+
else:
|
| 1042 |
+
df[col] = df[col].astype('category') # Regular unsigned integer
|
| 1043 |
+
|
| 1044 |
+
# Medium range integers (< 200 unique values) to UInt8 (0 to 255)
|
| 1045 |
+
champion_cols = [
|
| 1046 |
+
'champion', # 168 unique
|
| 1047 |
+
'team_champ1', # 149 unique
|
| 1048 |
+
'team_champ2', # 154 unique
|
| 1049 |
+
'team_champ3', # 143 unique
|
| 1050 |
+
'team_champ4', # 140 unique
|
| 1051 |
+
'opp_champ1', # 144 unique
|
| 1052 |
+
'opp_champ2', # 82 unique
|
| 1053 |
+
'opp_champ3', # 145 unique
|
| 1054 |
+
'opp_champ4', # 119 unique
|
| 1055 |
+
'opp_champ5', # 110 unique
|
| 1056 |
+
'most_champ_1', # 138 unique
|
| 1057 |
+
'most_champ_2', # 134 unique
|
| 1058 |
+
'season_champ1', # 139 unique
|
| 1059 |
+
'season_champ2', # 129 unique
|
| 1060 |
+
'season_champ3', # 132 unique
|
| 1061 |
+
'1_champ_name', # 114 unique
|
| 1062 |
+
'2_champ_name', # 114 unique
|
| 1063 |
+
'3_champ_name', # 112 unique
|
| 1064 |
+
'4_champ_name', # 111 unique
|
| 1065 |
+
'5_champ_name' # 113 unique
|
| 1066 |
+
]
|
| 1067 |
+
|
| 1068 |
+
for col in champion_cols:
|
| 1069 |
+
if col in df.columns:
|
| 1070 |
+
df[col] = df[col].astype('UInt8') # All champion IDs can fit in UInt8
|
| 1071 |
+
|
| 1072 |
+
# Float32 columns (performance metrics and ratios)
|
| 1073 |
+
float32_cols = [
|
| 1074 |
+
'most_role_1_value', # 15 unique
|
| 1075 |
+
'most_role_2_value', # 11 unique
|
| 1076 |
+
'most_role_3_value', # 15 unique
|
| 1077 |
+
'avg_kills', # 92 unique
|
| 1078 |
+
'avg_deaths', # 58 unique
|
| 1079 |
+
'avg_assists', # 132 unique
|
| 1080 |
+
'kda_ratio_profile', # 286 unique
|
| 1081 |
+
'kill_participation_profile', # 37 unique
|
| 1082 |
+
'WR_1', # 64 unique
|
| 1083 |
+
'WR_2', # 23 unique
|
| 1084 |
+
'WR_3', # 10 unique
|
| 1085 |
+
'champion_loyalty_score', # 156 unique
|
| 1086 |
+
'loyalty_confidence_score' # 5 unique
|
| 1087 |
+
]
|
| 1088 |
+
|
| 1089 |
+
for col in float32_cols:
|
| 1090 |
+
if col in df.columns:
|
| 1091 |
+
df[col] = df[col].astype('float32')
|
| 1092 |
+
|
| 1093 |
+
return df
|
| 1094 |
+
|
| 1095 |
+
def remove_unwanted_columns(df):
|
| 1096 |
+
"""
|
| 1097 |
+
Removes specified columns from the DataFrame
|
| 1098 |
+
|
| 1099 |
+
Args:
|
| 1100 |
+
df (pd.DataFrame): Input DataFrame
|
| 1101 |
+
|
| 1102 |
+
Returns:
|
| 1103 |
+
pd.DataFrame: DataFrame with specified columns removed
|
| 1104 |
+
"""
|
| 1105 |
+
df = df.copy()
|
| 1106 |
+
|
| 1107 |
+
# Define columns to remove
|
| 1108 |
+
columns_to_remove = (
|
| 1109 |
+
# Time and basic stats
|
| 1110 |
+
['date'] +
|
| 1111 |
+
['total_games', 'wins', 'losses', 'win_rate'] +
|
| 1112 |
+
['WR_1', 'WR_2', 'WR_3'] +
|
| 1113 |
+
['most_champ_3'] +
|
| 1114 |
+
['W_1', 'L_1', 'KDA_1', 'W_2', 'L_2', 'KDA_2', 'W_3', 'L_3', 'KDA_3'] +
|
| 1115 |
+
|
| 1116 |
+
# Roles
|
| 1117 |
+
['TOP', 'JUNGLE', 'MID', 'ADC', 'SUPPORT'] +
|
| 1118 |
+
|
| 1119 |
+
# Season and weekly stats
|
| 1120 |
+
['cs_ssn_1', 'cpm_ssn_1', 'kda_ssn_1', 'k_ssn_1', 'd_ssn_1', 'a_ssn_1', 'wr_ssn_1', 'games_ssn_1',
|
| 1121 |
+
'cs_ssn_2', 'cpm_ssn_2', 'kda_ssn_2', 'k_ssn_2', 'd_ssn_2', 'a_ssn_2', 'wr_ssn_2', 'games_ssn_2',
|
| 1122 |
+
'cs_ssn_3', 'cpm_ssn_3', 'kda_ssn_3', 'k_ssn_3', 'd_ssn_3', 'a_ssn_3', 'wr_ssn_3', 'games_ssn_3',
|
| 1123 |
+
'season_champ_4', 'cs_ssn_4', 'cpm_ssn_4', 'kda_ssn_4', 'k_ssn_4', 'd_ssn_4', 'a_ssn_4', 'wr_ssn_4', 'games_ssn_4',
|
| 1124 |
+
'season_champ_5', 'cs_ssn_5', 'cpm_ssn_5', 'kda_ssn_5', 'k_ssn_5', 'd_ssn_5', 'a_ssn_5', 'wr_ssn_5', 'games_ssn_5',
|
| 1125 |
+
'season_champ_6', 'cs_ssn_6', 'cpm_ssn_6', 'kda_ssn_6', 'k_ssn_6', 'd_ssn_6', 'a_ssn_6', 'wr_ssn_6', 'games_ssn_6',
|
| 1126 |
+
'season_champ_7', 'cs_ssn_7', 'cpm_ssn_7', 'kda_ssn_7', 'k_ssn_7', 'd_ssn_7', 'a_ssn_7', 'wr_ssn_7', 'games_ssn_7'] +
|
| 1127 |
+
|
| 1128 |
+
# Weekly stats
|
| 1129 |
+
['7d_champ_1', '7d_total_1', '7d_WR_1', '7d_champ_2', '7d_total_2', '7d_WR_2',
|
| 1130 |
+
'7d_champ_3', '7d_total_3', '7d_WR_3'] +
|
| 1131 |
+
['7d_W_1', '7d_L_1', '7d_W_2', '7d_L_2', '7d_W_3', '7d_L_3'] +
|
| 1132 |
+
|
| 1133 |
+
# Mastery stats
|
| 1134 |
+
['mastery_champ_1', 'm_lv_1', 'mastery_champ_2', 'm_lv_2', 'mastery_champ_3', 'm_lv_3',
|
| 1135 |
+
'mastery_champ_4', 'm_lv_4', 'mastery_champ_5', 'm_lv_5', 'mastery_champ_6', 'm_lv_6',
|
| 1136 |
+
'mastery_champ_7', 'm_lv_7', 'mastery_champ_8', 'm_lv_8', 'mastery_champ_9', 'm_lv_9',
|
| 1137 |
+
'mastery_champ_10', 'm_lv_10', 'mastery_champ_11', 'm_lv_11', 'mastery_champ_12', 'm_lv_12',
|
| 1138 |
+
'mastery_champ_13', 'm_lv_13', 'mastery_champ_14', 'm_lv_14', 'mastery_champ_15', 'm_lv_15',
|
| 1139 |
+
'mastery_champ_16', 'm_lv_16'] +
|
| 1140 |
+
|
| 1141 |
+
# Champion scores and others
|
| 1142 |
+
['1_champ_score', '2_champ_score', '3_champ_score', '4_champ_score', '5_champ_score'] +
|
| 1143 |
+
['avg_tier', 'team'] +
|
| 1144 |
+
|
| 1145 |
+
# Champions individual score
|
| 1146 |
+
["Aatrox", "Ahri", "Akali", "Akshan", "Alistar", "Ambessa", "Amumu", "Anivia", "Annie", "Aphelios",
|
| 1147 |
+
"Ashe", "Aurelion Sol", "Aurora", "Azir", "Bard", "Bel'Veth", "Blitzcrank", "Brand", "Braum",
|
| 1148 |
+
"Briar", "Caitlyn", "Camille", "Cassiopeia", "Cho'Gath", "Corki", "Darius", "Diana", "Dr. Mundo",
|
| 1149 |
+
"Draven", "Ekko", "Elise", "Evelynn", "Ezreal", "Fiddlesticks", "Fiora", "Fizz", "Galio",
|
| 1150 |
+
"Gangplank", "Garen", "Gnar", "Gragas", "Graves", "Gwen", "Hecarim", "Heimerdinger", "Hwei",
|
| 1151 |
+
"Illaoi", "Irelia", "Ivern", "Janna", "Jarvan IV", "Jax", "Jayce", "Jhin", "Jinx", "K'Sante",
|
| 1152 |
+
"Kai'Sa", "Kalista", "Karma", "Karthus", "Kassadin", "Katarina", "Kayle", "Kayn", "Kennen",
|
| 1153 |
+
"Kha'Zix", "Kindred", "Kled", "Kog'Maw", "LeBlanc", "Lee Sin", "Leona", "Lillia", "Lissandra",
|
| 1154 |
+
"Lucian", "Lulu", "Lux", "Malphite", "Malzahar", "Maokai", "Master Yi", "Milio", "Miss Fortune",
|
| 1155 |
+
"Mordekaiser", "Morgana", "Naafiri", "Nami", "Nasus", "Nautilus", "Neeko", "Nidalee", "Nilah",
|
| 1156 |
+
"Nocturne", "Nunu & Willump", "Olaf", "Orianna", "Ornn", "Pantheon", "Poppy", "Pyke", "Qiyana",
|
| 1157 |
+
"Quinn", "Rakan", "Rammus", "Rek'Sai", "Rell", "Renata Glasc", "Renekton", "Rengar", "Riven",
|
| 1158 |
+
"Rumble", "Ryze", "Samira", "Sejuani", "Senna", "Seraphine", "Sett", "Shaco", "Shen", "Shyvana",
|
| 1159 |
+
"Singed", "Sion", "Sivir", "Skarner", "Smolder", "Sona", "Soraka", "Swain", "Sylas", "Syndra",
|
| 1160 |
+
"Tahm Kench", "Taliyah", "Talon", "Taric", "Teemo", "Thresh", "Tristana", "Trundle", "Tryndamere",
|
| 1161 |
+
"Twisted Fate", "Twitch", "Udyr", "Urgot", "Varus", "Vayne", "Veigar", "Vel'Koz", "Vex", "Vi",
|
| 1162 |
+
"Viego", "Viktor", "Vladimir", "Volibear", "Warwick", "Wukong", "Xayah", "Xerath", "Xin Zhao",
|
| 1163 |
+
"Yasuo", "Yone", "Yorick", "Yuumi", "Zac", "Zed", "Zeri", "Ziggs", "Zilean", "Zoe", "Zyra"]
|
| 1164 |
+
)
|
| 1165 |
+
|
| 1166 |
+
# Remove columns that exist in the DataFrame
|
| 1167 |
+
columns_to_remove = [col for col in columns_to_remove if col in df.columns]
|
| 1168 |
+
|
| 1169 |
+
# Drop the columns
|
| 1170 |
+
df = df.drop(columns=columns_to_remove)
|
| 1171 |
+
|
| 1172 |
+
# Print info about removed columns
|
| 1173 |
+
print(f"Removed {len(columns_to_remove)} columns")
|
| 1174 |
+
print(f"Remaining columns: {len(df.columns)}")
|
| 1175 |
+
|
| 1176 |
+
return df
|
| 1177 |
+
|
| 1178 |
+
|
| 1179 |
+
def apply_feature_engineering(df, n=5):
|
| 1180 |
+
"""
|
| 1181 |
+
Performs feature engineering pipeline
|
| 1182 |
+
"""
|
| 1183 |
+
df = df.copy()
|
| 1184 |
+
|
| 1185 |
+
# Engineering pipeline
|
| 1186 |
+
transformations = [
|
| 1187 |
+
calculate_champ_variety_score,
|
| 1188 |
+
calculate_playstyle,
|
| 1189 |
+
get_most_role_3,
|
| 1190 |
+
calculate_role_specialization,
|
| 1191 |
+
calculate_champion_loyalty,
|
| 1192 |
+
lambda x: get_top_champion_scores(x, n), # Add top 5 champions
|
| 1193 |
+
remove_unwanted_columns,
|
| 1194 |
+
optimize_feature_dtypes
|
| 1195 |
+
]
|
| 1196 |
+
|
| 1197 |
+
for transform in transformations:
|
| 1198 |
+
try:
|
| 1199 |
+
print(f"Applying {transform.__name__}...")
|
| 1200 |
+
df = transform(df)
|
| 1201 |
+
except Exception as e:
|
| 1202 |
+
print(f"Error in {transform.__name__}: {str(e)}")
|
| 1203 |
+
raise
|
| 1204 |
+
|
| 1205 |
+
return df
|
util/main_scrapper.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from Recent_match_scrapper import get_multiple_matches_stats
|
| 2 |
+
from Meta_scrapper import get_meta_stats
|
| 3 |
+
from Leaderboard_scrapper import scrape_leaderboards
|
| 4 |
+
from connection_check import check_connection
|
| 5 |
+
from helper import merge_stats, filter_leaderboard, get_player_list
|
| 6 |
+
from Player_scrapper import get_multiple_player_stats
|
| 7 |
+
from feature_eng import create_champion_features
|
| 8 |
+
from Weekly_meta_scrapper import get_weekly_meta
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
#check_connection(region="euw", summoner="Szygenda #EUW")
|
| 12 |
+
|
| 13 |
+
meta_stats = get_meta_stats() #save to meta_stats.csv
|
| 14 |
+
weekly_meta_stats = get_weekly_meta() #save to weekly_meta_stats.csv
|
| 15 |
+
|
| 16 |
+
leaderboard = scrape_leaderboards( #save to leaderboard_data.csv
|
| 17 |
+
regions=["kr", "euw", "vn", "na"],
|
| 18 |
+
pages_per_region=5
|
| 19 |
+
)
|
| 20 |
+
|
| 21 |
+
filtered_lb = filter_leaderboard( #save to lb_filtered.csv
|
| 22 |
+
df=leaderboard,
|
| 23 |
+
tiers=["CHALLENGER"]
|
| 24 |
+
)
|
| 25 |
+
|
| 26 |
+
#player_list = get_player_list(filtered_lb)
|
| 27 |
+
#player_list = get_player_list() # without arg, it will read from lb_filtered.csv
|
| 28 |
+
|
| 29 |
+
player_stats = get_multiple_player_stats(player_list) #save to player_stats.csv
|
| 30 |
+
recent_stats = get_multiple_matches_stats(player_list) #save to recent_stats.csv
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
merged_stats = merge_stats(recent_stats, player_stats) #save to player_stats_merged.csv
|
| 34 |
+
|
| 35 |
+
#feature engineering
|
| 36 |
+
training_features = create_champion_features(merged_stats, meta_stats, weekly_meta_stats, consider_team_comp=True) #save to feature_eng_stats.csv
|
util/main_scrapper2.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from Recent_match_scrapper import get_multiple_matches_stats
|
| 2 |
+
from Meta_scrapper import get_meta_stats
|
| 3 |
+
from Leaderboard_scrapper import scrape_leaderboards
|
| 4 |
+
from connection_check import check_connection
|
| 5 |
+
from helper import merge_stats, filter_leaderboard, get_player_list
|
| 6 |
+
from Player_scrapper import get_multiple_player_stats, get_player_stats
|
| 7 |
+
from feature_eng import create_champion_features
|
| 8 |
+
from Weekly_meta_scrapper import get_weekly_meta
|
| 9 |
+
import pandas as pd
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
#check_connection(region="euw", summoner="Szygenda #EUW")
|
| 13 |
+
|
| 14 |
+
meta_stats = get_meta_stats() #save to meta_stats.csv
|
| 15 |
+
|
| 16 |
+
#weekly_meta_stats = get_weekly_meta() #save to weekly_meta_stats.csv
|
| 17 |
+
|
| 18 |
+
#leaderboard = scrape_leaderboards( #save to leaderboard_data.csv
|
| 19 |
+
# regions=["kr", "euw", "vn", "na"],
|
| 20 |
+
# pages_per_region=5
|
| 21 |
+
#)
|
| 22 |
+
|
| 23 |
+
#filtered_lb = filter_leaderboard( #save to lb_filtered.csv
|
| 24 |
+
# df=leaderboard,
|
| 25 |
+
# tiers=["CHALLENGER"]
|
| 26 |
+
# )
|
| 27 |
+
|
| 28 |
+
#filtered_lb = pd.read_csv("util/data/lb_filtered_custom_2.csv")
|
| 29 |
+
#player_list = get_player_list(filtered_lb)
|
| 30 |
+
#player_list = get_player_list() # without arg, it will read from lb_filtered.csv
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
##single player test
|
| 34 |
+
lb_for_single = pd.read_csv("util/data/lb_filtered_for_single.csv")
|
| 35 |
+
player_list = get_player_list(lb_for_single)
|
| 36 |
+
|
| 37 |
+
player_stats = get_multiple_player_stats(player_list) #save to player_stats.csv
|
| 38 |
+
recent_stats = get_multiple_matches_stats(player_list) #save to recent_stats.csv
|
| 39 |
+
|
| 40 |
+
recent_stats = pd.read_csv("util/data/recent_matches.csv")
|
| 41 |
+
player_stats = pd.read_csv("util/data/player_stats.csv")
|
| 42 |
+
merged_stats = merge_stats(recent_stats, player_stats) #save to player_stats_merged.csv
|
| 43 |
+
|
| 44 |
+
#feature engineering
|
| 45 |
+
merged_stats = pd.read_csv("util/data/player_stats_merged_2025-01-07.csv")
|
| 46 |
+
training_features = create_champion_features(merged_player_stats=merged_stats, debug=None, consider_team_comp=True, test_mode=False) #save to feature_eng_stats.csv
|