// Same Odds Statistics Section (สถิติอัตราต่อรองในอดีตเดียวกัน) // Uses fixture_analysis_odds_api table (unified API) let sameOddsData = null; let sameOddsApiData = null; // Data from fixture_analysis_odds_api table (unified) let sameOddsLeagueName = null; // League name from thscore_fixture_analyses table let currentOddsType = 2; // 1=1x2, 2=Asian Handicap, 3=Over/Under function getSameOdds(fixtureId, homeTeamName, awayTeamName) { // Single API call for unified odds data (สถิติอัตราต่อรองในอดีตเดียวกัน only) getData('fixtures/' + fixtureId + '/analysis/odds-stats', null, (response) => { if (response?.oddsApi) { sameOddsApiData = response.oddsApi; } if (response?.leagueName) { sameOddsLeagueName = response.leagueName; } // Calculate and render สถิติอัตราต่อรองในอดีตเดียวกัน section calculateSameOddsStats(homeTeamName, awayTeamName); renderSameOdds(); }); } function calculateSameOddsStats(homeTeamName, awayTeamName) { // Uses fixture_analysis_odds_api table data (unified API) // H2H data is NOT a valid fallback - it's a completely different data source if (sameOddsApiData) { calculateSameOddsStatsFromApiData(homeTeamName, awayTeamName); return; } // No same odds data available - hide the section sameOddsData = null; } // Calculate stats from fixture_analysis_odds_api table (unified API) // Data format: ah_all_sum/up/draw/down, ah_main_sum/up/draw/down, ah_same_sum/up/draw/down (same for ou, op) function calculateSameOddsStatsFromApiData(homeTeamName, awayTeamName) { const d = sameOddsApiData; console.log('[SameOdds] API Data:', d); // Helper to calculate percentage const pct = (val, sum) => sum > 0 ? Math.round((val / sum) * 100) : 0; // Build categories from unified API (all, main, same) for each odds type // Each category becomes a column in the chart const buildCategories = (prefix) => { const categories = []; // "รวม" (All) column const allSum = d[`${prefix}_all_sum`] || 0; if (allSum > 0) { categories.push({ home: pct(d[`${prefix}_all_up`] || 0, allSum), draw: pct(d[`${prefix}_all_draw`] || 0, allSum), away: pct(d[`${prefix}_all_down`] || 0, allSum), category: `รวม (${allSum})` }); } // "ลีกหลัก" (Main league) column const mainSum = d[`${prefix}_main_sum`] || 0; if (mainSum > 0) { categories.push({ home: pct(d[`${prefix}_main_up`] || 0, mainSum), draw: pct(d[`${prefix}_main_draw`] || 0, mainSum), away: pct(d[`${prefix}_main_down`] || 0, mainSum), category: `ลีกหลัก (${mainSum})` }); } // "ลีกเดียวกัน" (Same league) column - use actual league name if available const sameSum = d[`${prefix}_same_sum`] || 0; if (sameSum > 0) { const leagueLabel = sameOddsLeagueName || 'ลีกเดียวกัน'; categories.push({ home: pct(d[`${prefix}_same_up`] || 0, sameSum), draw: pct(d[`${prefix}_same_draw`] || 0, sameSum), away: pct(d[`${prefix}_same_down`] || 0, sameSum), category: `${leagueLabel} (${sameSum})` }); } return categories; }; // Build odds display from API values const getOddsDisplay = () => { return { handicap: { home: d.ah_up_odds || '-', odds: d.ah_draw_odds || '-', away: d.ah_down_odds || '-' }, oneXTwo: { home: d.op_up_odds || '-', draw: d.op_draw_odds || '-', away: d.op_down_odds || '-' }, overUnder: { over: d.ou_up_odds || '-', odds: d.ou_draw_odds || '-', under: d.ou_down_odds || '-' } }; }; const currentOdds = getOddsDisplay(); console.log('[SameOdds] currentOdds:', currentOdds); sameOddsData = { homeTeam: homeTeamName, awayTeam: awayTeamName, currentOdds: currentOdds, // stats is array of columns from unified API (all, main, same) stats: { handicap: buildCategories('ah'), oneXTwo: buildCategories('op'), overUnder: buildCategories('ou') }, labels: { handicap: { home: 'เหย้าชนะ', draw: 'เสมอ', away: 'เยือนชนะ' }, oneXTwo: { home: 'เหย้าชนะ', draw: 'เสมอ', away: 'เยือนชนะ' }, overUnder: { home: 'สูง', draw: 'เสมอ', away: 'ต่ำ' } } }; console.log('[SameOdds] sameOddsData.stats:', sameOddsData.stats); } function renderSameOdds() { if (!sameOddsData) return; const data = sameOddsData; const typeKey = currentOddsType === 1 ? 'oneXTwo' : (currentOddsType === 2 ? 'handicap' : 'overUnder'); const columns = data.stats[typeKey]; // Array of columns from database const labels = data.labels[typeKey]; console.log(`[SameOdds RENDER] currentOddsType=${currentOddsType}, typeKey=${typeKey}`); console.log(`[SameOdds RENDER] columns:`, columns); const odds = currentOddsType === 1 ? data.currentOdds.oneXTwo : (currentOddsType === 2 ? data.currentOdds.handicap : data.currentOdds.overUnder); let html = `
`; // Header row with team names html += `
`; html += `
`; html += `

${data.homeTeam}

`; html += `
`; html += `

สถิติอัตราต่อรองในอดีตเดียวกัน

`; html += `
`; html += `

${data.awayTeam}

`; html += `
`; html += `
`; html += `
`; html += `
`; // Content html += `
`; // Tab options html += `
`; html += `
    `; html += `
  • แฮนดิแคปเอเชีย
  • `; html += `
  • 1x2
  • `; html += `
  • สูง/ต่ำ
  • `; html += `
`; html += `
`; // Current odds display html += `
`; if (currentOddsType === 2) { html += `แฮนดิแคปเอเชีย: ${odds.home}${odds.odds}${odds.away}`; } else if (currentOddsType === 1) { html += `1x2: ${odds.home}${odds.draw}${odds.away}`; } else { html += `สูง/ต่ำ: ${odds.over}${odds.odds}${odds.under}`; } html += `
`; // Vertical bars - draw each column from database html += ``; // Legend - always show all 3 (database gives what we need) html += `
`; html += `${labels.home}`; html += `${labels.draw}`; html += `${labels.away}`; html += `(ข้อมูลข้างต้นมีไว้เพื่อการอ้างอิงเท่านั้น โดยอิงจากข้อมูลในอดีต)`; html += `
`; html += `
`; // fx-vote-data html += `
`; // same-odds-section $('#sameOddsSection').html(html); } function renderSameOddsVoteBar(stats, label, labels, oddsType) { // Helper to get bar height - use pixel for 0%, percentage for others const getBarHeight = (val) => val === 0 ? '2px' : `${Math.max(val, 5)}%`; let html = `
  • `; html += `
    `; // Home bar html += `
    `; html += `
    `; html += `${stats.home}%`; html += `
    `; html += `
    `; // Draw bar - always draw (database gives what we need) html += `
    `; html += `
    `; html += `${stats.draw}%`; html += `
    `; html += `
    `; // Away bar html += `
    `; html += `
    `; html += `${stats.away}%`; html += `
    `; html += `
    `; html += `
    `; html += `
    ${label}
    `; html += `
  • `; return html; } function switchSameOddsBar(type) { currentOddsType = type; renderSameOdds(); } // ============================================================================ // Odds Statistics Section (สถิติราคาต่อรอง) // Uses H2H API data (fixture_analysis_h2hs table with odds) // Calculates per-team stats from historical match results // ============================================================================ let oddsStatsData = null; let oddsStatsH2hData = null; // Store H2H data for recalculation function getOddsStats(fixtureId, homeTeamName, awayTeamName) { console.log('[OddsStats] getOddsStats called with fixtureId:', fixtureId); // Fetch from H2H API - contains per-team historical match results with odds getData('fixtures/' + fixtureId + '/analysis/h2h', null, (response) => { console.log('[OddsStats] H2H API response:', response); if (response?.home?.length > 0 || response?.away?.length > 0) { oddsStatsH2hData = response; calculateOddsStatsFromH2hData(response, homeTeamName, awayTeamName); } else { console.log('[OddsStats] No H2H data - hiding section'); $('#oddsStatsSection').html(''); } }, (error) => { console.log('[OddsStats] API error:', error); $('#oddsStatsSection').html(''); }); } // Calculate stats from H2H API data (fixture_analysis_h2hs with odds) // Data structure: home/away arrays with matches, each match has odds array // odds[0] = 1x2 (result_open: W/D/L), odds[1] = AH (result_open: W/D/L), odds[2] = O/U (result_open: O/D/U) // odds[3] = 1x2 half, odds[4] = AH half, odds[5] = O/U half function calculateOddsStatsFromH2hData(data, homeTeamName, awayTeamName) { if (!data) { $('#oddsStatsSection').html(''); return; } // Get checkbox states for filtering const isHalfTime = $('#oddsStatHTSel').is(':checked'); const isOriginalHA = $('#oddsStatHASel').is(':checked'); // Offset for half time (0=full time, 3=half time) const s = isHalfTime ? 3 : 0; // Helper to calculate stats from matches array const calcTeamStats = (matches, teamName, isHomeTeam) => { if (!matches || matches.length === 0) { return null; } // Filter matches if "ทีมเหย้า - ทีมเยือน เดิม" is checked let filteredMatches = matches; if (isOriginalHA) { filteredMatches = matches.filter(m => isHomeTeam ? m.team_home === teamName : m.team_away === teamName ); } // Take up to 21 matches (like thscore) const maxMatches = Math.min(21, filteredMatches.length); const selectedMatches = filteredMatches.slice(0, maxMatches); // Count AH results (from odds[s+1]) let ahWin = 0, ahDraw = 0, ahLose = 0, ahTotal = 0; // Count O/U results (from odds[s+2]) let ouOver = 0, ouDraw = 0, ouUnder = 0, ouTotal = 0; for (const match of selectedMatches) { if (!match.odds) continue; // AH result (index s+1) const ahOdds = match.odds[s + 1]; if (ahOdds && ahOdds.result_open) { ahTotal++; if (ahOdds.result_open === 'W') ahWin++; else if (ahOdds.result_open === 'D') ahDraw++; else if (ahOdds.result_open === 'L') ahLose++; } // O/U result (index s+2) const ouOdds = match.odds[s + 2]; if (ouOdds && ouOdds.result_open) { ouTotal++; if (ouOdds.result_open === 'O') ouOver++; else if (ouOdds.result_open === 'D') ouDraw++; else if (ouOdds.result_open === 'U') ouUnder++; } } // Calculate percentages const pct = (val, total) => total > 0 ? Math.round((val / total) * 100) : 0; return { games: ahTotal, handicap: { win: pct(ahWin, ahTotal), draw: pct(ahDraw, ahTotal), lose: pct(ahLose, ahTotal) }, overUnder: { games: ouTotal, over: pct(ouOver, ouTotal), draw: pct(ouDraw, ouTotal), under: pct(ouUnder, ouTotal) } }; }; // Calculate stats for home team (from 'home' array) and away team (from 'away' array) const homeStats = calcTeamStats(data.home, homeTeamName, true); const awayStats = calcTeamStats(data.away, awayTeamName, false); console.log('[OddsStats] Calculated stats:', { homeStats, awayStats }); if (!homeStats && !awayStats) { $('#oddsStatsSection').html(''); return; } oddsStatsData = { homeTeam: homeTeamName, awayTeam: awayTeamName, stats: { handicap: { homeGames: homeStats?.games || 0, awayGames: awayStats?.games || 0, home: homeStats?.handicap || { win: 0, draw: 0, lose: 0 }, away: awayStats?.handicap || { win: 0, draw: 0, lose: 0 } }, overUnder: { homeGames: homeStats?.overUnder?.games || 0, awayGames: awayStats?.overUnder?.games || 0, home: homeStats?.overUnder || { over: 0, draw: 0, under: 0 }, away: awayStats?.overUnder || { over: 0, draw: 0, under: 0 } } } }; console.log('[OddsStats] Final data:', oddsStatsData); renderOddsStats(); } function renderOddsStats() { if (!oddsStatsData) return; // Get checkbox states const isHalfTime = $('#oddsStatHTSel').is(':checked'); const isOriginalHA = $('#oddsStatHASel').is(':checked'); // Use the stats from oddsStatsData (calculated dynamically with checkbox filters) const stats = oddsStatsData.stats; const data = oddsStatsData; let html = `
    `; // Header row with team names html += `
    `; html += `
    `; html += `

    ${data.homeTeam}

    `; html += `
    `; html += `

    สถิติราคาต่อรอง

    `; html += `
    `; html += `

    ${data.awayTeam}

    `; html += `
    `; html += `
    `; html += `
    `; html += `
    `; // Content html += `
    `; // Checkbox options (preserve checked state) html += `
    `; html += ``; html += ``; html += ``; html += ``; html += `
    `; // Helper to get bar height - use 2px for 0%, percentage for others const getBarHeight = (val) => val === 0 ? '2px' : `${Math.max(val, 5)}%`; // Y-Bar groups using fx-tb-a structure (Asian Handicap and Over/Under side by side) html += ``; // Legend html += `
    `; html += `ทีมเหย้า`; html += `ทีมเยือน`; html += `
    `; html += `
    `; // fx-vote-data html += `
    `; // same-odds-section $('#oddsStatsSection').html(html); } function switchOddsStat() { // Recalculate from H2H data with new checkbox states if (oddsStatsH2hData && oddsStatsData) { calculateOddsStatsFromH2hData(oddsStatsH2hData, oddsStatsData.homeTeam, oddsStatsData.awayTeam); } } // ============================================================================ // League Goal Difference Statistics Section (สถิติผลต่างประตูของลีก) // Uses fixture_analysis_goal_diffs API data // ============================================================================ let goalDiffData = null; let goalDiffRawData = null; function getGoalDiffStats(fixtureId, homeTeamName, awayTeamName) { // Fetch goal diff data from API getData('fixtures/' + fixtureId + '/analysis/goal/diff', null, (data) => { if (!data || !data.goalDiff || data.goalDiff.length === 0) { // No API data, will fall back to H2H calculation later return; } goalDiffRawData = data.goalDiff; processGoalDiffData(homeTeamName, awayTeamName); }, () => { // API fetch failed, will use H2H fallback }); } function processGoalDiffData(homeTeamName, awayTeamName) { if (!goalDiffRawData) return; // Find home and away data const homeData = goalDiffRawData.find(d => d.team === 'home'); const awayData = goalDiffRawData.find(d => d.team === 'away'); if (!homeData && !awayData) return; // Parse count values from database (stored as strings) const parseCount = (val) => parseInt(val) || 0; // Calculate max count for bar height scaling const homeTotal = homeData ? (parseCount(homeData.win_2_plus) + parseCount(homeData.win_1) + parseCount(homeData.draw) + parseCount(homeData.lose_1) + parseCount(homeData.lose_2_plus)) : 0; const awayTotal = awayData ? (parseCount(awayData.win_2_plus) + parseCount(awayData.win_1) + parseCount(awayData.draw) + parseCount(awayData.lose_1) + parseCount(awayData.lose_2_plus)) : 0; const maxTotal = Math.max(homeTotal, awayTotal, 1); goalDiffData = { homeTeam: homeTeamName, awayTeam: awayTeamName, maxTotal: maxTotal, categories: [ { label: 'ชนะ 2 ลูกขึ้นไป', home: homeData ? parseCount(homeData.win_2_plus) : 0, away: awayData ? parseCount(awayData.win_2_plus) : 0 }, { label: 'ชนะ 1 ลูก', home: homeData ? parseCount(homeData.win_1) : 0, away: awayData ? parseCount(awayData.win_1) : 0 }, { label: 'เสมอ', home: homeData ? parseCount(homeData.draw) : 0, away: awayData ? parseCount(awayData.draw) : 0 }, { label: 'แพ้ 1 ลูก', home: homeData ? parseCount(homeData.lose_1) : 0, away: awayData ? parseCount(awayData.lose_1) : 0 }, { label: 'แพ้ 2 ลูกขึ้นไป', home: homeData ? parseCount(homeData.lose_2_plus) : 0, away: awayData ? parseCount(awayData.lose_2_plus) : 0 } ] }; renderGoalDiffStats(); } function renderGoalDiffStats() { if (!goalDiffData) return; const data = goalDiffData; let html = `
    `; // Header row with team names html += `
    `; html += `
    `; html += `

    ${data.homeTeam}

    `; html += `
    `; html += `

    สถิติผลต่างประตูของลีก

    `; html += `
    `; html += `

    ${data.awayTeam}

    `; html += `
    `; html += `
    `; html += `
    `; html += `
    `; // Content html += `
    `; // Vertical bars for goal difference categories html += ``; // Legend html += `
    `; html += `ทีมเหย้า`; html += `ทีมเยือน`; html += `
    `; html += `
    `; // fx-vote-data html += `
    `; // same-odds-section $('#goalDiffSection').html(html); } function renderGoalDiffVoteBar(cat, maxTotal) { // Helper to get bar height - scale based on max total count const getBarHeight = (val) => { if (val === 0) return '2px'; const pct = Math.round((val / maxTotal) * 100); return `${Math.max(pct, 5)}%`; }; let html = `
  • `; html += `
    `; // Home bar (orange) - show count, not percentage html += `
    `; html += `
    `; html += `${cat.home}`; html += `
    `; html += `
    `; // Away bar (purple) - show count, not percentage html += `
    `; html += `
    `; html += `${cat.away}`; html += `
    `; html += `
    `; html += `
    `; html += `
    ${cat.label}
    `; html += `
  • `; return html; }