1.7.0: New features.
This commit is contained in:
74
scripts/analyze_dmg_per_1k.py
Normal file
74
scripts/analyze_dmg_per_1k.py
Normal file
@@ -0,0 +1,74 @@
|
||||
|
||||
import sqlite3
|
||||
import pandas as pd
|
||||
import os
|
||||
|
||||
# Config
|
||||
L2_DB_PATH = r'database/L2/L2_Main.sqlite'
|
||||
L3_DB_PATH = r'database/L3/L3_Features.sqlite'
|
||||
|
||||
def analyze_team_dmg_per_1k():
|
||||
if not os.path.exists(L3_DB_PATH):
|
||||
print(f"Error: L3 DB not found at {L3_DB_PATH}")
|
||||
return
|
||||
|
||||
conn_l3 = sqlite3.connect(L3_DB_PATH)
|
||||
conn_l2 = sqlite3.connect(L2_DB_PATH)
|
||||
|
||||
print("--- Analysis: Team Dmg/$1k (Economy Efficiency) ---")
|
||||
|
||||
try:
|
||||
# 1. Get all L3 features
|
||||
query = """
|
||||
SELECT f.steam_id_64, f.eco_avg_damage_per_1k, p.username
|
||||
FROM dm_player_features f
|
||||
LEFT JOIN dim_players p ON f.steam_id_64 = p.steam_id_64
|
||||
ORDER BY f.eco_avg_damage_per_1k DESC
|
||||
"""
|
||||
|
||||
# Attach L2 for username lookup
|
||||
# We can't attach across connections easily in sqlite python without ATTACH DATABASE command
|
||||
# So let's fetch L3 first, then map names from L2
|
||||
|
||||
df_l3 = pd.read_sql_query("SELECT steam_id_64, eco_avg_damage_per_1k FROM dm_player_features", conn_l3)
|
||||
|
||||
if df_l3.empty:
|
||||
print("No data in L3 Features.")
|
||||
return
|
||||
|
||||
# Fetch names
|
||||
ids = tuple(df_l3['steam_id_64'].tolist())
|
||||
placeholders = ','.join(['?'] * len(ids))
|
||||
q_names = f"SELECT steam_id_64, username FROM dim_players WHERE steam_id_64 IN ({placeholders})"
|
||||
df_names = pd.read_sql_query(q_names, conn_l2, params=ids)
|
||||
|
||||
# Merge
|
||||
df = df_l3.merge(df_names, on='steam_id_64', how='left')
|
||||
|
||||
# Sort
|
||||
df = df.sort_values('eco_avg_damage_per_1k', ascending=False)
|
||||
|
||||
print(f"{'Rank':<5} {'Player':<20} {'Dmg/$1k':<10}")
|
||||
print("-" * 40)
|
||||
|
||||
for idx, row in df.iterrows():
|
||||
rank = idx + 1 # This index is not rank if we iterated row by row after sort, wait.
|
||||
# reset_index to get rank
|
||||
pass
|
||||
|
||||
df = df.reset_index(drop=True)
|
||||
for idx, row in df.iterrows():
|
||||
name = row['username'] if row['username'] else row['steam_id_64']
|
||||
val = row['eco_avg_damage_per_1k']
|
||||
print(f"#{idx+1:<4} {name:<20} {val:.2f}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
conn_l2.close()
|
||||
conn_l3.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
analyze_team_dmg_per_1k()
|
||||
45
scripts/debug_dist.py
Normal file
45
scripts/debug_dist.py
Normal file
@@ -0,0 +1,45 @@
|
||||
|
||||
import sqlite3
|
||||
import pandas as pd
|
||||
from web.services.feature_service import FeatureService
|
||||
from web.config import Config
|
||||
from web.app import create_app
|
||||
|
||||
def check_distribution():
|
||||
app = create_app()
|
||||
with app.app_context():
|
||||
# Get a player ID from L3
|
||||
conn = sqlite3.connect(Config.DB_L3_PATH)
|
||||
row = conn.execute("SELECT steam_id_64 FROM dm_player_features LIMIT 1").fetchone()
|
||||
if not row:
|
||||
print("No players in L3")
|
||||
return
|
||||
|
||||
sid = row[0]
|
||||
print(f"Checking distribution for {sid}...")
|
||||
|
||||
dist = FeatureService.get_roster_features_distribution(sid)
|
||||
if not dist:
|
||||
print("Distribution returned None")
|
||||
return
|
||||
|
||||
keys_to_check = [
|
||||
'eco_avg_damage_per_1k', # Working
|
||||
'eco_rating_eco_rounds', # Working
|
||||
'eco_kd_ratio', # Broken
|
||||
'eco_avg_rounds', # Broken
|
||||
'pace_avg_time_to_first_contact', # Working
|
||||
'pace_trade_kill_rate', # Working
|
||||
'pace_opening_kill_time', # Broken
|
||||
'pace_avg_life_time' # Broken
|
||||
]
|
||||
|
||||
print(f"{'Key':<35} | {'Present':<7} | {'Value'}")
|
||||
print("-" * 60)
|
||||
for k in keys_to_check:
|
||||
is_present = k in dist
|
||||
val = dist.get(k)
|
||||
print(f"{k:<35} | {str(is_present):<7} | {val}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
check_distribution()
|
||||
94
scripts/debug_jacky.py
Normal file
94
scripts/debug_jacky.py
Normal file
@@ -0,0 +1,94 @@
|
||||
|
||||
import sqlite3
|
||||
import pandas as pd
|
||||
import os
|
||||
|
||||
# Config
|
||||
L2_DB_PATH = r'database/L2/L2_Main.sqlite'
|
||||
|
||||
def debug_player_data(username_pattern='jAckY'):
|
||||
if not os.path.exists(L2_DB_PATH):
|
||||
print(f"Error: L2 DB not found at {L2_DB_PATH}")
|
||||
return
|
||||
|
||||
conn_l2 = sqlite3.connect(L2_DB_PATH)
|
||||
|
||||
print(f"--- Debugging Player: {username_pattern} ---")
|
||||
|
||||
try:
|
||||
# 1. Find the player ID
|
||||
q_id = f"SELECT steam_id_64, username FROM dim_players WHERE username LIKE '%{username_pattern}%'"
|
||||
df_player = pd.read_sql_query(q_id, conn_l2)
|
||||
|
||||
if df_player.empty:
|
||||
print("Player not found.")
|
||||
return
|
||||
|
||||
target_id = df_player.iloc[0]['steam_id_64']
|
||||
name = df_player.iloc[0]['username']
|
||||
print(f"Found: {name} ({target_id})")
|
||||
|
||||
# 2. Check Match Stats (ADR, Rounds)
|
||||
q_matches = f"""
|
||||
SELECT match_id, round_total, adr, (adr * round_total) as damage_calc
|
||||
FROM fact_match_players
|
||||
WHERE steam_id_64 = '{target_id}'
|
||||
"""
|
||||
df_matches = pd.read_sql_query(q_matches, conn_l2)
|
||||
|
||||
total_dmg = df_matches['damage_calc'].sum()
|
||||
total_rounds = df_matches['round_total'].sum()
|
||||
print(f"\nMatch Stats:")
|
||||
print(f"Matches Played: {len(df_matches)}")
|
||||
print(f"Total Rounds: {total_rounds}")
|
||||
print(f"Total Damage (Calc): {total_dmg:,.0f}")
|
||||
|
||||
# 3. Check Economy Stats (Spend)
|
||||
q_eco = f"""
|
||||
SELECT match_id, COUNT(*) as rounds_with_eco, SUM(equipment_value) as spend
|
||||
FROM fact_round_player_economy
|
||||
WHERE steam_id_64 = '{target_id}'
|
||||
GROUP BY match_id
|
||||
"""
|
||||
df_eco = pd.read_sql_query(q_eco, conn_l2)
|
||||
|
||||
total_spend = df_eco['spend'].sum()
|
||||
total_eco_rounds = df_eco['rounds_with_eco'].sum()
|
||||
|
||||
print(f"\nEconomy Stats:")
|
||||
print(f"Matches with Eco Data: {len(df_eco)}")
|
||||
print(f"Rounds with Eco Data: {total_eco_rounds}")
|
||||
print(f"Total Spend: ${total_spend:,.0f}")
|
||||
|
||||
# 4. Compare
|
||||
print(f"\nComparison:")
|
||||
print(f"Rounds in Match Stats: {total_rounds}")
|
||||
print(f"Rounds in Eco Stats: {total_eco_rounds}")
|
||||
|
||||
if total_eco_rounds < total_rounds:
|
||||
print(f"⚠️ WARNING: Missing economy data for {total_rounds - total_eco_rounds} rounds!")
|
||||
|
||||
# Find matches with missing eco data
|
||||
merged = df_matches.merge(df_eco, on='match_id', how='left')
|
||||
missing = merged[merged['spend'].isna() | (merged['spend'] == 0)]
|
||||
|
||||
if not missing.empty:
|
||||
print(f"\nMatches with ZERO spend/Missing Eco:")
|
||||
print(missing[['match_id', 'round_total', 'damage_calc']])
|
||||
|
||||
# Check calculation impact
|
||||
valid_dmg = merged[merged['spend'] > 0]['damage_calc'].sum()
|
||||
print(f"\nRecalculation ignoring missing matches:")
|
||||
print(f"Valid Damage: {valid_dmg:,.0f}")
|
||||
print(f"Total Spend: ${total_spend:,.0f}")
|
||||
if total_spend > 0:
|
||||
new_val = valid_dmg / (total_spend / 1000)
|
||||
print(f"Corrected Dmg/$1k: {new_val:.2f}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
finally:
|
||||
conn_l2.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
debug_player_data()
|
||||
Reference in New Issue
Block a user