PageSourceSearch

https://www.clubhipico.cl/carreras/wp-content/themes/chs/assets/js/helpers/pronosticos-api-helper.js

js clubhipico.cl collected 2026-09-24 09:49:48 UTC 10,021 bytes, 291 lines download raw bytes

1/**
2 * HELPER: Integración API de Pronósticos
3 * ======================================
4 * 
5 * Este helper gestiona la integración con:
6 * - API NUEVA: /pronosticadores/api/pronosticos/jornada-por-pronosticador
7 * - API LEGACY: /v1/pronosticos/{fecha} (fallback automático)
8 * 
9 * Características:
10 * - Soporta 3-8 pronosticadores dinámicos
11 * - Fallback transparente a API legacy
12 * - Normalización de estructuras de datos
13 * - Manejo de errores robusto
14 * 
15 * @version 1.0.0
16 * @author CHS Portal Team
17 */
18
19(function(window) {
20    'use strict';
21
22    /**
23     * URL base de la nueva API de pronosticadores
24     */
25    const API_BASE_URL = 'https://apiweb.clubhipico.cl/pronosticadores/api/pronosticos';
26    
27    /**
28     * URL base de la API legacy (fallback)
29     */
30    const LEGACY_API_URL = serviceUrl + 'v1/pronosticos';
31
32    /**
33     * Obtiene pronósticos de toda la jornada
34     * 
35     * @param {string} fecha - Fecha en formato YYYY-MM-DD
36     * @returns {Promise<{exito: boolean, datos: Array, esNuevaApi: boolean, error?: string}>}
37     */
38    async function obtenerPronosticosJornada(fecha) {
39        console.log(`[PronosticosAPI] Obteniendo pronósticos para jornada: ${fecha}`);
40        
41        try {
42            // Intentar con la nueva API primero
43            const datosNuevos = await intentarNuevaApi(fecha);
44            
45            if (datosNuevos) {
46                console.log('✓ Pronósticos cargados desde nueva API');
47                return {
48                    exito: true,
49                    datos: datosNuevos,
50                    esNuevaApi: true
51                };
52            }
53            
54            // Si falla, usar API legacy
55            console.warn('→ Intentando con API antigua...');
56            const datosLegacy = await intentarApiLegacy(fecha);
57            
58            console.log('✓ Pronósticos cargados desde API antigua');
59            return {
60                exito: true,
61                datos: datosLegacy,
62                esNuevaApi: false
63            };
64            
65        } catch (error) {
66            console.error('✗ Error al obtener pronósticos:', error);
67            return {
68                exito: false,
69                datos: [],
70                esNuevaApi: false,
71                error: error.message
72            };
73        }
74    }
75
76    /**
77     * Obtiene pronósticos de una carrera específica
78     * 
79     * @param {string} fecha - Fecha en formato YYYY-MM-DD
80     * @param {number} numeroCarrera - Número de carrera
81     * @returns {Promise<{exito: boolean, datos: Array, esNuevaApi: boolean, error?: string}>}
82     */
83    async function obtenerPronosticosCarrera(fecha, numeroCarrera) {
84        console.log(`[PronosticosAPI] Obteniendo pronósticos para carrera ${numeroCarrera} del ${fecha}`);
85        
86        try {
87            // Intentar con la nueva API primero
88            const datosNuevos = await intentarNuevaApi(fecha, numeroCarrera);
89            
90            if (datosNuevos) {
91                console.log('✓ Pronósticos cargados desde nueva API');
92                return {
93                    exito: true,
94                    datos: datosNuevos,
95                    esNuevaApi: true
96                };
97            }
98            
99            // Si falla, usar API legacy
100            console.warn('→ Intentando con API antigua...');
101            const datosLegacy = await intentarApiLegacy(fecha, numeroCarrera);
102            
103            console.log('✓ Pronósticos cargados desde API antigua');
104            return {
105                exito: true,
106                datos: datosLegacy,
107                esNuevaApi: false
108            };
109            
110        } catch (error) {
111            console.error('✗ Error al obtener pronósticos:', error);
112            return {
113                exito: false,
114                datos: [],
115                esNuevaApi: false,
116                error: error.message
117            };
118        }
119    }
120
121    /**
122     * Intenta obtener datos de la nueva API
123     * @private
124     */
125    async function intentarNuevaApi(fecha, numeroCarrera = null) {
126        try {
127            const url = `${API_BASE_URL}
127/jornada-por-pronosticador?fecha=${fecha}`;
128            const response = await fetch(url, {
129                method: 'GET',
130                headers: {
131                    'Content-Type': 'application/json',
132                    'Accept': 'application/json'
133                }
134            });
135
136            if (!response.ok) {
137                throw new Error(`HTTP ${response.status}: ${response.statusText}`);
138            }
139
140            const resultado = await response.json();
141            
142            // Validar estructura de respuesta
143            if (!resultado.success || !Array.isArray(resultado.data)) {
144                throw new Error('Estructura de respuesta inválida');
145            }
146
147            // Normalizar y filtrar si es carrera específica
148            return normalizarPronosticos(resultado, numeroCarrera);
149            
150        } catch (error) {
151            console.warn('[PronosticosAPI] Nueva API no disponible:', error.message);
152            return null;
153        }
154    }
155
156    /**
157     * Intenta obtener datos de la API legacy
158     * @private
159     */
160    async function intentarApiLegacy(fecha, numeroCarrera = null) {
161        const url = numeroCarrera 
162            ? `${LEGACY_API_URL}/${fecha}/${numeroCarrera}`
163            : `${LEGACY_API_URL}/${fecha}`;
164
165        return new Promise((resolve, reject) => {
166            $.ajax({
167                type: 'GET',
168                url: url,
169                success: function(response) {
170                    try {
171                        const datosNormalizados = normalizarPronosticosLegacy(response, numeroCarrera);
172                        resolve(datosNormalizados);
173                    } catch (error) {
174                        reject(error);
175                    }
176                },
177                error: function(xhr, status, error) {
178                    reject(new Error(`Error API Legacy: ${error}`));
179                }
180            });
181        });
182    }
183
184    /**
185     * Normaliza datos de la nueva API al formato esperado
186     * @private
187     */
188    function normalizarPronosticos(resultado, numeroCarrera = null) {
189        if (!resultado.data || !Array.isArray(resultado.data)) {
190            return [];
191        }
192
193        return resultado.data.map(pronosticador => {
194            // Filtrar pronósticos si es carrera específica
195            let pronosticosFiltrados = pronosticador.pronosticos || [];
196            
197            if (numeroCarrera) {
198                pronosticosFiltrados = pronosticosFiltrados.filter(
199                    p => parseInt(p.nroCarrera) === parseInt(numeroCarrera)
200                );
201            }
202
203            return {
204                nombre: pronosticador.nombre || '',
205                alias: pronosticador.alias || '',
206                foto: pronosticador.fotoUrl || '',
207                pronosticos: pronosticosFiltrados.map(p => ({
208                    nroCarrera: parseInt(p.nroCarrera),
209                    cab1: String(p.cab1),
210                    cab2: String(p.cab2),
211                    nombreCab1: p.nombreCab1 || '',
212                    nombreCab2: p.nombreCab2 || ''
213                }))
214            };
215        }).filter(p => p.pronosticos.length > 0);
216    }
217
218    /**
219     * Normaliza datos de la API legacy al formato esperado
220     * @private
221     */
222    function normalizarPronosticosLegacy(response, numeroCarrera = null) {
223        const pronosticadores = [];
224        
225        // Mapeo de nombres legacy a formato nuevo
226        const mapeoPronosticadores = {
227            'pronosticos_ariel': {
228                nombre: 'Ariel Gómez',
229                alias: 'ariel',
230                foto: directory_uri + '/web/assets/images/club/ariel.png'
231            },
232            'pronosticos_felipe': {
233                nombre: 'Felipe Ogrodnik',
234                alias: 'felipe',
235                foto: directory_uri + '/web/assets/images/club/felipe.png'
236            },
237            'pronosticos_mario': {
238                nombre: 'Mario Valdés',
239                alias: 'mario',
240                foto: directory_uri + '/web/assets/images/club/mario.png'
241            },
242	    'pronosticos_nacho_pacheco': {
243                nombre: 'Ignacio Pacheco',
244                alias: 'nacho_pacheco',
245                foto: 'http://pronosticos.clubhipico.cl/wp-content/uploads/2026/04/WhatsApp-Image-2026-04-22-at-13.37.52-2-242x300.jpeg'
246            },
247        };
248
249        // Procesar cada pronosticador
250        Object.keys(mapeoPronosticadores).forEach(key => {
251            if (response[key] && Array.isArray(response[key])) {
252                let pronosticosList = response[key];
253                
254                // Filtrar si es carrera específica
255                if (numeroCarrera) {
256                    pronosticosList = pronosticosList.filter(
257                        p => parseInt(p.numero_carrera) === parseInt(numeroCarrera)
258                    );
259                }
260
261                if (pronosticosList.length > 0) {
262                    pronosticadores.push({
263                        nombre: mapeoPronosticadores[key].nombre,
264                        alias: mapeoPronosticadores[key].alias,
265                        foto: mapeoPronosticadores[key].foto,
266                        pronosticos: pronosticosList.map(p => ({
267                            nroCarrera: parseInt(p.numero_carrera),
268                            cab1: String(p.cab1),
269                            cab2: String(p.cab2),
270                            nombreCab1: p.nombre_cab1 || '',
271                            nombreCab2: p.nombre_cab2 || ''
272                        }))
273                    });
274                }
275            }
276        });
277
278        return pronosticadores;
279    }
280
281    /**
282     * Exportar API pública
283     */
284    window.PronosticosAPI = {
285        obtenerJornada: obtenerPronosticosJornada,
286        obtenerCarrera: obtenerPronosticosCarrera
287    };
288
289    console.log('[PronosticosAPI] Helper cargado correctamente');
290
291})(window);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.