Spaces:
Sleeping
Sleeping
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
|