pablogrois Claude Opus 4.8 commited on
Commit
c54a6f2
·
1 Parent(s): ebbb798

Pool de ligas por categoría (Ponderación Ligas) en secciones 2, 3.5, 4, 5, 6

Browse files

Nueva tabla vendor/data/league_categories.json (categoría→ligas, de la columna Categoria
de Ponderación Ligas). El endpoint /api/team-vars/options la expone; el front la ofrece
como opción en cada input de pool de ligas: al elegir p.ej. "Ligas TOP" se agregan todas
sus ligas (∩ las disponibles en esa sección). En 2/3.5 (pool liga-temporada) expande a
todos los pares liga-temporada de esas ligas. Ignora la ponderación numérica por ahora.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

src/racing_reports/api/routes_team_vars.py CHANGED
@@ -53,6 +53,7 @@ def options() -> dict:
53
  "leagues": team_vars.league_seasons(),
54
  "variables": team_vars.variables_info(), # [{name, label, tipo}]
55
  "types": team_vars.types(), # {tipo: [columnas]}
 
56
  }
57
 
58
 
 
53
  "leagues": team_vars.league_seasons(),
54
  "variables": team_vars.variables_info(), # [{name, label, tipo}]
55
  "types": team_vars.types(), # {tipo: [columnas]}
56
+ "league_categories": team_vars.league_categories(), # {categoria: [ligas]}
57
  }
58
 
59
 
src/racing_reports/team_vars.py CHANGED
@@ -101,6 +101,20 @@ def types() -> dict[str, list[str]]:
101
  return dict(sorted(out.items()))
102
 
103
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  def league_seasons() -> dict[str, list[str]]:
105
  """{liga: [temporadas]} disponibles en el agregado."""
106
  d = _df()
 
101
  return dict(sorted(out.items()))
102
 
103
 
104
+ _CATS_PATH = vendor_env.DATA_DIR / "league_categories.json"
105
+
106
+
107
+ def league_categories() -> dict[str, list[str]]:
108
+ """{categoria: [ligas]} de la tabla Ponderación Ligas (para el pool por categoría)."""
109
+ with _LOCK:
110
+ d = _DICT_CACHE.get("cats")
111
+ if d is None:
112
+ import json
113
+ d = json.loads(_CATS_PATH.read_text(encoding="utf-8")) if _CATS_PATH.exists() else {}
114
+ _DICT_CACHE["cats"] = d
115
+ return d
116
+
117
+
118
  def league_seasons() -> dict[str, list[str]]:
119
  """{liga: [temporadas]} disponibles en el agregado."""
120
  d = _df()
src/racing_reports/web/templates/home.html CHANGED
@@ -282,6 +282,7 @@
282
  <template x-for="v in tvVarLabels" :key="v"><option :value="v"></option></template>
283
  </datalist>
284
  <datalist id="tv-ls-list">
 
285
  <template x-for="o in tvLsOptions" :key="o.value"><option :value="o.label"></option></template>
286
  </datalist>
287
  <!-- Pool por liga-temporada -->
@@ -639,7 +640,7 @@
639
  <label class="block text-xs text-gray-400 mb-1">Pool: sumar liga</label>
640
  <input list="ejligalist" x-model="ejPoolLigaIn" @change="ejAddPoolLiga()" placeholder="Liga…"
641
  class="bg-ink-800 border border-ink-600 rounded-lg px-3 py-2 text-sm w-52">
642
- <datalist id="ejligalist"><template x-for="l in ejLeagueList" :key="'pl'+l"><option :value="l"></option></template></datalist>
643
  </div>
644
  <div>
645
  <label class="block text-xs text-gray-400 mb-1">Sumar y marcar equipo</label>
@@ -707,7 +708,7 @@
707
  <label class="block text-xs text-gray-400 mb-1">Pool: sumar liga</label>
708
  <input list="lbligalist" x-model="lbPoolLigaIn" @change="lbAddPoolLiga()" placeholder="Liga…"
709
  class="bg-ink-800 border border-ink-600 rounded-lg px-3 py-2 text-sm w-48">
710
- <datalist id="lbligalist"><template x-for="l in lbLeagues" :key="'lbpl'+l"><option :value="l"></option></template></datalist>
711
  </div>
712
  <div>
713
  <label class="block text-xs text-gray-400 mb-1">Sumar y marcar equipo</label>
@@ -871,7 +872,7 @@
871
  <label class="block text-xs text-gray-400 mb-1">Pool: sumar liga</label>
872
  <input list="vsligalist" x-model="vsPoolLigaIn" @change="vsAddPoolLiga()" placeholder="Liga…"
873
  class="bg-ink-800 border border-ink-600 rounded-lg px-3 py-2 text-sm w-48">
874
- <datalist id="vsligalist"><template x-for="l in vsLeagueList" :key="'vspl'+l"><option :value="l"></option></template></datalist>
875
  </div>
876
  <div>
877
  <label class="block text-xs text-gray-400 mb-1">Sumar y marcar equipo</label>
@@ -1168,6 +1169,7 @@
1168
  tvLeagues: {}, tvLeagueList: [], tvLeague: '__all__', tvSeason: '__all__', tvSeasons: [], tvAllSeasons: [],
1169
  tvVarLabels: [], tvLabelToCol: {}, tvColToLabel: {}, tvTypeCols: {}, tvTypeList: [],
1170
  tvSpecs: [{variable:'', direction:'alto'}], tvResult: null, tvLoading: false, tvError: '', tvLoaded: false,
 
1171
  tvLsOptions: [], tvPool: [], tvPoolIn: '', tvTop: '10', // pool por liga-temporada + nº de equipos
1172
  tvsPool: [], tvsPoolIn: '', // pool por liga-temporada (similares)
1173
  tvVarsOpen: true, tvpVarsOpen: true, // desplegables de variables (2 y 3)
@@ -1225,6 +1227,7 @@
1225
  this.tvLabelToCol = {}; this.tvColToLabel = {};
1226
  vinfo.forEach(v=>{ this.tvLabelToCol[v.label]=v.name; this.tvColToLabel[v.name]=v.label; });
1227
  this.tvTypeCols = o.types || {}; this.tvTypeList = Object.keys(this.tvTypeCols);
 
1228
  this.tvLeagueList = Object.keys(this.tvLeagues);
1229
  this.tvAllSeasons = [...new Set([].concat(...Object.values(this.tvLeagues)))].sort().reverse();
1230
  // opciones de pool por liga-temporada (para "Top equipos" y "Similares")
@@ -1357,8 +1360,14 @@
1357
  else { this.tvSpecs[i].variable=''; this.tvError='"'+val+'" no es una variable válida — elegila de la lista.'; }
1358
  },
1359
  // Pool por liga-temporada
1360
- tvAddPool(){ const o=this.tvLsOptions.find(x=>x.label===this.tvPoolIn); if(o && !this.tvPool.some(p=>p.value===o.value)) this.tvPool.push(o); this.tvPoolIn=''; },
1361
- tvsAddPool(){ const o=this.tvLsOptions.find(x=>x.label===this.tvsPoolIn); if(o && !this.tvsPool.some(p=>p.value===o.value)) this.tvsPool.push(o); this.tvsPoolIn=''; },
 
 
 
 
 
 
1362
  async tvSearch(){
1363
  this.tvError=''; this.tvResult=null;
1364
  const specs = this.tvSpecs.filter(s=>s.variable).map(s=>({variable:(this.tvLabelToCol[s.variable]||s.variable), direction:s.direction}));
@@ -1502,10 +1511,14 @@
1502
  await this.$nextTick(); this.lbDraw();
1503
  } catch(e){ this.lbError = 'Error: '+e; }
1504
  },
 
 
 
 
 
 
1505
  lbAddPoolLiga(){
1506
- const l=(this.lbPoolLigaIn||'').trim();
1507
- if (l && this.lbLeagues.includes(l) && !this.lbPool.some(p=>p.tipo==='liga'&&p.liga===l))
1508
- this.lbPool.push({tipo:'liga', liga:l, label:'Liga: '+l});
1509
  this.lbPoolLigaIn=''; this.lbDraw();
1510
  },
1511
  lbAddPoolTeam(){
@@ -1843,10 +1856,7 @@
1843
  } catch(e){ this.ejError='Error: '+e; }
1844
  },
1845
  ejAddPoolLiga(){
1846
- const l = (this.ejPoolLigaIn||'').trim();
1847
- if (l && this.ejLeagueList.includes(l) && !this.ejPool.some(p=>p.tipo==='liga'&&p.liga===l)){
1848
- this.ejPool.push({tipo:'liga', liga:l, label:'Liga: '+l});
1849
- }
1850
  this.ejPoolLigaIn=''; this.ejDraw();
1851
  },
1852
  ejAddPoolTeam(){
@@ -1981,9 +1991,7 @@
1981
  } catch(e){ this.vsError='Error: '+e; }
1982
  },
1983
  vsAddPoolLiga(){
1984
- const l=(this.vsPoolLigaIn||'').trim();
1985
- if (l && this.vsLeagueList.includes(l) && !this.vsPool.some(p=>p.tipo==='liga'&&p.liga===l))
1986
- this.vsPool.push({tipo:'liga', liga:l, label:'Liga: '+l});
1987
  this.vsPoolLigaIn=''; this.vsDraw();
1988
  },
1989
  vsAddPoolTeam(){
 
282
  <template x-for="v in tvVarLabels" :key="v"><option :value="v"></option></template>
283
  </datalist>
284
  <datalist id="tv-ls-list">
285
+ <template x-for="c in catList" :key="'tvc'+c"><option :value="c"></option></template>
286
  <template x-for="o in tvLsOptions" :key="o.value"><option :value="o.label"></option></template>
287
  </datalist>
288
  <!-- Pool por liga-temporada -->
 
640
  <label class="block text-xs text-gray-400 mb-1">Pool: sumar liga</label>
641
  <input list="ejligalist" x-model="ejPoolLigaIn" @change="ejAddPoolLiga()" placeholder="Liga…"
642
  class="bg-ink-800 border border-ink-600 rounded-lg px-3 py-2 text-sm w-52">
643
+ <datalist id="ejligalist"><template x-for="c in catList" :key="'ejc'+c"><option :value="c"></option></template><template x-for="l in ejLeagueList" :key="'pl'+l"><option :value="l"></option></template></datalist>
644
  </div>
645
  <div>
646
  <label class="block text-xs text-gray-400 mb-1">Sumar y marcar equipo</label>
 
708
  <label class="block text-xs text-gray-400 mb-1">Pool: sumar liga</label>
709
  <input list="lbligalist" x-model="lbPoolLigaIn" @change="lbAddPoolLiga()" placeholder="Liga…"
710
  class="bg-ink-800 border border-ink-600 rounded-lg px-3 py-2 text-sm w-48">
711
+ <datalist id="lbligalist"><template x-for="c in catList" :key="'lbc'+c"><option :value="c"></option></template><template x-for="l in lbLeagues" :key="'lbpl'+l"><option :value="l"></option></template></datalist>
712
  </div>
713
  <div>
714
  <label class="block text-xs text-gray-400 mb-1">Sumar y marcar equipo</label>
 
872
  <label class="block text-xs text-gray-400 mb-1">Pool: sumar liga</label>
873
  <input list="vsligalist" x-model="vsPoolLigaIn" @change="vsAddPoolLiga()" placeholder="Liga…"
874
  class="bg-ink-800 border border-ink-600 rounded-lg px-3 py-2 text-sm w-48">
875
+ <datalist id="vsligalist"><template x-for="c in catList" :key="'vsc'+c"><option :value="c"></option></template><template x-for="l in vsLeagueList" :key="'vspl'+l"><option :value="l"></option></template></datalist>
876
  </div>
877
  <div>
878
  <label class="block text-xs text-gray-400 mb-1">Sumar y marcar equipo</label>
 
1169
  tvLeagues: {}, tvLeagueList: [], tvLeague: '__all__', tvSeason: '__all__', tvSeasons: [], tvAllSeasons: [],
1170
  tvVarLabels: [], tvLabelToCol: {}, tvColToLabel: {}, tvTypeCols: {}, tvTypeList: [],
1171
  tvSpecs: [{variable:'', direction:'alto'}], tvResult: null, tvLoading: false, tvError: '', tvLoaded: false,
1172
+ catMap: {}, catList: [], // categorías de ligas (Ponderación Ligas)
1173
  tvLsOptions: [], tvPool: [], tvPoolIn: '', tvTop: '10', // pool por liga-temporada + nº de equipos
1174
  tvsPool: [], tvsPoolIn: '', // pool por liga-temporada (similares)
1175
  tvVarsOpen: true, tvpVarsOpen: true, // desplegables de variables (2 y 3)
 
1227
  this.tvLabelToCol = {}; this.tvColToLabel = {};
1228
  vinfo.forEach(v=>{ this.tvLabelToCol[v.label]=v.name; this.tvColToLabel[v.name]=v.label; });
1229
  this.tvTypeCols = o.types || {}; this.tvTypeList = Object.keys(this.tvTypeCols);
1230
+ this.catMap = o.league_categories || {}; this.catList = Object.keys(this.catMap);
1231
  this.tvLeagueList = Object.keys(this.tvLeagues);
1232
  this.tvAllSeasons = [...new Set([].concat(...Object.values(this.tvLeagues)))].sort().reverse();
1233
  // opciones de pool por liga-temporada (para "Top equipos" y "Similares")
 
1360
  else { this.tvSpecs[i].variable=''; this.tvError='"'+val+'" no es una variable válida — elegila de la lista.'; }
1361
  },
1362
  // Pool por liga-temporada
1363
+ _addPoolLs(inp, pool){
1364
+ const cats=this._catLeagues(inp);
1365
+ const opts = cats ? this.tvLsOptions.filter(o=>cats.includes(o.value.split('|')[0]))
1366
+ : this.tvLsOptions.filter(o=>o.label===inp);
1367
+ for (const o of opts) if(!pool.some(p=>p.value===o.value)) pool.push(o);
1368
+ },
1369
+ tvAddPool(){ this._addPoolLs(this.tvPoolIn, this.tvPool); this.tvPoolIn=''; },
1370
+ tvsAddPool(){ this._addPoolLs(this.tvsPoolIn, this.tvsPool); this.tvsPoolIn=''; },
1371
  async tvSearch(){
1372
  this.tvError=''; this.tvResult=null;
1373
  const specs = this.tvSpecs.filter(s=>s.variable).map(s=>({variable:(this.tvLabelToCol[s.variable]||s.variable), direction:s.direction}));
 
1511
  await this.$nextTick(); this.lbDraw();
1512
  } catch(e){ this.lbError = 'Error: '+e; }
1513
  },
1514
+ _catLeagues(name){ return this.catMap[name] || null; }, // array de ligas si es categoría, si no null
1515
+ _addPoolLigas(inp, avail, pool){
1516
+ const cats=this._catLeagues(inp);
1517
+ const ligas = cats ? cats.filter(l=>avail.includes(l)) : (avail.includes(inp)?[inp]:[]);
1518
+ for (const l of ligas) if(!pool.some(p=>p.tipo==='liga'&&p.liga===l)) pool.push({tipo:'liga', liga:l, label:'Liga: '+l});
1519
+ },
1520
  lbAddPoolLiga(){
1521
+ this._addPoolLigas((this.lbPoolLigaIn||'').trim(), this.lbLeagues, this.lbPool);
 
 
1522
  this.lbPoolLigaIn=''; this.lbDraw();
1523
  },
1524
  lbAddPoolTeam(){
 
1856
  } catch(e){ this.ejError='Error: '+e; }
1857
  },
1858
  ejAddPoolLiga(){
1859
+ this._addPoolLigas((this.ejPoolLigaIn||'').trim(), this.ejLeagueList, this.ejPool);
 
 
 
1860
  this.ejPoolLigaIn=''; this.ejDraw();
1861
  },
1862
  ejAddPoolTeam(){
 
1991
  } catch(e){ this.vsError='Error: '+e; }
1992
  },
1993
  vsAddPoolLiga(){
1994
+ this._addPoolLigas((this.vsPoolLigaIn||'').trim(), this.vsLeagueList, this.vsPool);
 
 
1995
  this.vsPoolLigaIn=''; this.vsDraw();
1996
  },
1997
  vsAddPoolTeam(){
vendor/data/league_categories.json ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "Ligas TOP": [
3
+ "England Premier League",
4
+ "English Premier League",
5
+ "France Ligue 1",
6
+ "French Ligue 1",
7
+ "German Bundesliga",
8
+ "Germany Bundesliga",
9
+ "Italian Serie A",
10
+ "Italy Serie A",
11
+ "Spain La Liga",
12
+ "Spanish La Liga"
13
+ ],
14
+ "Juveniles": [
15
+ "CONMEBOL Libertadores U20",
16
+ "CONMEBOL U17",
17
+ "CONMEBOL U20",
18
+ "UEFA Under 17 Championship",
19
+ "UEFA Under 19 Championship",
20
+ "UEFA Under 21 Championship",
21
+ "UEFA Under 21 Championship Qualifiers",
22
+ "UEFA Youth League"
23
+ ],
24
+ "Ligas Principales": [
25
+ "Belgian Jupiler Pro League",
26
+ "Danish Superligaen",
27
+ "Dutch Eredivisie",
28
+ "Eredivisie",
29
+ "Jupiler Pro League",
30
+ "Liga Portugal",
31
+ "Norwegian Eliteserien",
32
+ "Portuguese Primeira Liga"
33
+ ],
34
+ "Ligas Secundarias": [
35
+ "Austrian Bundesliga",
36
+ "Belgian Challenger Pro League",
37
+ "Brack Super League",
38
+ "Croatia Prva HNL",
39
+ "Dutch Eerste Divisie",
40
+ "Polish Ekstraklasa",
41
+ "Portuguese Segunda Liga",
42
+ "Swedish Allsvenskan"
43
+ ],
44
+ "Ligas TOP 2ª": [
45
+ "Bundesliga 2",
46
+ "England Championship",
47
+ "English Football League - Championship",
48
+ "French Ligue 2",
49
+ "German Bundesliga Zwei",
50
+ "Italian Serie B",
51
+ "Spanish Segunda Division"
52
+ ],
53
+ "Comp. Europea + Copa": [
54
+ "Europa League",
55
+ "Europe Champions League",
56
+ "Spanish Copa Del Rey",
57
+ "UEFA Champions League",
58
+ "UEFA Conference League",
59
+ "UEFA Europa League"
60
+ ],
61
+ "Ligas Menores": [
62
+ "League One",
63
+ "League Two England",
64
+ "Russia Premier League",
65
+ "Scotland Premiership",
66
+ "Serbian Super Liga",
67
+ "Turkey Super Lig"
68
+ ],
69
+ "Sudamerica + USA": [
70
+ "Brasileirao",
71
+ "Chile Primera",
72
+ "Colombia Primera A Apertura",
73
+ "Ecuador Liga Pro",
74
+ "Liga Profesional Argentina",
75
+ "MLS"
76
+ ],
77
+ "Fifa World Cup": [
78
+ "Fifa World Cup"
79
+ ]
80
+ }