Download scoring.py from RRC-ARG/scouting: direct link, hf CLI and curl.
- Browser
- Download file 3.7 kB
-
https://huggingface.co/spaces/RRC-ARG/scouting/resolve/main/scoring.py
- Command line
-
hf download hf://spaces/RRC-ARG/scouting/scoring.py
-
curl -L -o scoring.py https://huggingface.co/spaces/RRC-ARG/scouting/resolve/main/scoring.py
3.7 kB
| """ | |
| Scoring wrapper: takes a filtered DF and tunable weights, returns scored rows. | |
| Reuses the existing functions in scouting_score.py. | |
| """ | |
| import sys | |
| from functools import lru_cache | |
| from pathlib import Path | |
| import pandas as pd | |
| # Allow importing scouting_score.py from the parent directory in dev. In the Docker | |
| # image, scouting_score.py is copied into /app so this is a no-op. | |
| _PARENT = Path(__file__).resolve().parent.parent | |
| if str(_PARENT) not in sys.path: | |
| sys.path.insert(0, str(_PARENT)) | |
| import scouting_score as ss | |
| APP_DIR = Path(__file__).parent | |
| # weights xlsx path — searched in DATA_DIR first, fallback to project root | |
| def _weights_path(): | |
| import os | |
| data_dir = Path(os.environ.get('DATA_DIR', APP_DIR.parent / 'data' / 'clean')) | |
| candidates = [ | |
| data_dir / 'PESOS_POR_VARIABLE.xlsx', | |
| data_dir / 'PESOS POR VARIABLE (BLOQUES).xlsx', | |
| APP_DIR.parent / 'PESOS POR VARIABLE (BLOQUES).xlsx', | |
| ] | |
| for c in candidates: | |
| if c.exists(): | |
| return c | |
| raise FileNotFoundError(f'weights xlsx not found; tried: {candidates}') | |
| def get_block_weights(): | |
| return ss.load_weights(_weights_path()) | |
| def score_with_weights(df: pd.DataFrame, | |
| perf_weight=0.6, prof_weight=0.4, | |
| w_age=0.35, w_eu=0.25, w_league=0.20, w_mv=0.20): | |
| if df.empty: | |
| return df.assign(performance_score=pd.NA, profile_score=pd.NA, | |
| scouting_score=pd.NA, percentile_rank_in_position=pd.NA) | |
| weights = get_block_weights() | |
| df = df.copy() | |
| df['mapped_position'] = df['Posicion'].map(ss.POSITION_MAP) | |
| df = df[df['mapped_position'].notna()].copy() | |
| df = ss.compute_percentile_ranks(df, weights) | |
| df = ss.compute_performance_scores(df, weights) | |
| def age_factor(a): | |
| try: | |
| a = float(a) | |
| except (TypeError, ValueError): | |
| return None | |
| if pd.isna(a): | |
| return None | |
| if a < 23: | |
| return 1.0 | |
| if a <= 25: | |
| return 0.5 | |
| return 0.0 | |
| df['age_factor'] = df['_age_num'].apply(age_factor) | |
| df['eu_nationality_factor'] = df['_eu'].astype(float) | |
| def mv_factor(mv): | |
| if mv is None or pd.isna(mv): | |
| return None | |
| if mv < 3: | |
| return 1.0 | |
| if mv <= 5: | |
| return 0.5 | |
| return -1 | |
| df['market_value_factor'] = df['mv_millions'].apply(mv_factor) | |
| df['league_tier_factor'] = df['Competencia'].map(ss.LEAGUE_TIERS).fillna(ss.DEFAULT_LEAGUE_TIER) | |
| weights_p = {'age': w_age, 'eu_nationality': w_eu, 'league_tier': w_league, 'market_value': w_mv} | |
| def profile_score(row): | |
| comps, w_total = [], 0 | |
| if row['age_factor'] is not None: | |
| comps.append(weights_p['age'] * row['age_factor']); w_total += weights_p['age'] | |
| comps.append(weights_p['eu_nationality'] * row['eu_nationality_factor']); w_total += weights_p['eu_nationality'] | |
| comps.append(weights_p['league_tier'] * row['league_tier_factor']); w_total += weights_p['league_tier'] | |
| if row['market_value_factor'] is not None and row['market_value_factor'] >= 0: | |
| comps.append(weights_p['market_value'] * row['market_value_factor']); w_total += weights_p['market_value'] | |
| return sum(comps) / w_total if w_total else 0 | |
| df['profile_score'] = df.apply(profile_score, axis=1) | |
| df['scouting_score'] = (perf_weight * df['performance_score'].fillna(0) | |
| + prof_weight * df['profile_score'].fillna(0)) | |
| df['percentile_rank_in_position'] = ( | |
| df.groupby(['mapped_position', 'Temporada'])['performance_score'].rank(pct=True) | |
| ) | |
| return df | |