Files
iddaai-be/scripts/prediction-analysis.js
T
fahricansecer 2f0b85a0c7
Deploy Iddaai Backend / build-and-deploy (push) Failing after 18s
first (part 2: other directories)
2026-04-16 15:11:25 +03:00

501 lines
16 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();
async function analyzePredictionProcess() {
console.log('\n========================================');
console.log('🎯 MAÇ TAHMİN SÜRECİ ANALİZİ');
console.log('========================================\n');
// Mevcut maçların tarih aralığı
const oldestMatch = await prisma.match.findFirst({
where: { sport: 'football' },
orderBy: { mstUtc: 'asc' },
});
const newestMatch = await prisma.match.findFirst({
where: { sport: 'football' },
orderBy: { mstUtc: 'desc' },
});
console.log('📅 FUTBOL MAÇ TARİH ARALIĞI:');
console.log(
` En Eski: ${new Date(Number(oldestMatch.mstUtc)).toISOString()}`,
);
console.log(
` En Yeni: ${new Date(Number(newestMatch.mstUtc)).toISOString()}`,
);
// preGame durumundaki maçları bul
const upcomingMatches = await prisma.match.findMany({
where: {
sport: 'football',
state: 'preGame',
},
include: {
homeTeam: true,
awayTeam: true,
league: true,
oddCategories: {
include: { selections: true },
},
aiFeatures: true,
},
take: 5,
orderBy: { mstUtc: 'desc' },
});
console.log(`\n🔴 preGame Durumundaki Maçlar: ${upcomingMatches.length}`);
// Eğer preGame yoksa, son bitmiş maçları al
let selectedMatch = null;
if (upcomingMatches.length > 0) {
selectedMatch = upcomingMatches[0];
} else {
// Son bitmiş futbol maçını al (analiz için)
const recentMatches = await prisma.match.findMany({
where: {
sport: 'football',
state: 'postGame',
scoreHome: { not: null },
scoreAway: { not: null },
},
include: {
homeTeam: true,
awayTeam: true,
league: true,
oddCategories: {
include: { selections: true },
},
aiFeatures: true,
},
take: 1,
orderBy: { mstUtc: 'desc' },
});
if (recentMatches.length > 0) {
selectedMatch = recentMatches[0];
console.log(
'\n⚠️ preGame maçı bulunamadı. Son bitmiş maç analiz edilecek.',
);
}
}
if (!selectedMatch) {
console.log('Analiz edilecek maç bulunamadı.');
await prisma.$disconnect();
return;
}
console.log('\n========================================');
console.log('⚽ SEÇİLEN MAÇ');
console.log('========================================');
console.log(`Maç ID: ${selectedMatch.id}`);
console.log(`Ev Sahibi: ${selectedMatch.homeTeam?.name}`);
console.log(`Deplasman: ${selectedMatch.awayTeam?.name}`);
console.log(`Lig: ${selectedMatch.league?.name}`);
console.log(`Tarih: ${new Date(Number(selectedMatch.mstUtc)).toISOString()}`);
console.log(`Durum: ${selectedMatch.state}`);
if (selectedMatch.scoreHome !== null) {
console.log(
`Skor: ${selectedMatch.scoreHome} - ${selectedMatch.scoreAway}`,
);
}
console.log(`İddaa Kodu: ${selectedMatch.iddaaCode}`);
// =====================================
// ADIM 1: ORAN VERİLERİNİ TOPLA
// =====================================
console.log('\n========================================');
console.log('📊 ADIM 1: ORAN VERİLERİ');
console.log('========================================');
const oddsData = {};
const msCategory = selectedMatch.oddCategories.find((c) =>
c.name?.includes('Maç Sonucu'),
);
if (msCategory) {
for (const sel of msCategory.selections) {
if (sel.name === '1') oddsData.ms_h = parseFloat(sel.oddValue) || 0;
if (sel.name === 'X') oddsData.ms_d = parseFloat(sel.oddValue) || 0;
if (sel.name === '2') oddsData.ms_a = parseFloat(sel.oddValue) || 0;
}
}
const dcCategory = selectedMatch.oddCategories.find((c) =>
c.name?.includes('Çifte Şans'),
);
if (dcCategory) {
for (const sel of dcCategory.selections) {
if (sel.name === '1-X') oddsData.dc_1x = parseFloat(sel.oddValue) || 0;
if (sel.name === 'X-2') oddsData.dc_x2 = parseFloat(sel.oddValue) || 0;
if (sel.name === '1-2') oddsData.dc_12 = parseFloat(sel.oddValue) || 0;
}
}
const ou25Category = selectedMatch.oddCategories.find((c) =>
c.name?.includes('2,5'),
);
if (ou25Category) {
for (const sel of ou25Category.selections) {
if (sel.name === 'Alt') oddsData.ou25_u = parseFloat(sel.oddValue) || 0;
if (sel.name === 'Üst') oddsData.ou25_o = parseFloat(sel.oddValue) || 0;
}
}
const ou15Category = selectedMatch.oddCategories.find((c) =>
c.name?.includes('1,5'),
);
if (ou15Category) {
for (const sel of ou15Category.selections) {
if (sel.name === 'Alt') oddsData.ou15_u = parseFloat(sel.oddValue) || 0;
if (sel.name === 'Üst') oddsData.ou15_o = parseFloat(sel.oddValue) || 0;
}
}
const bttsCategory = selectedMatch.oddCategories.find(
(c) =>
c.name?.toLowerCase().includes('karşılıklı') || c.name?.includes('KG'),
);
if (bttsCategory) {
for (const sel of bttsCategory.selections) {
if (sel.name === 'Var' || sel.name === 'Evet')
oddsData.btts_y = parseFloat(sel.oddValue) || 0;
if (sel.name === 'Yok' || sel.name === 'Hayır')
oddsData.btts_n = parseFloat(sel.oddValue) || 0;
}
}
console.log('Toplanan Oranlar:');
console.log(
` MS (1/X/2): ${oddsData.ms_h || 'N/A'} / ${oddsData.ms_d || 'N/A'} / ${oddsData.ms_a || 'N/A'}`,
);
console.log(
` DC (1X/X2/12): ${oddsData.dc_1x || 'N/A'} / ${oddsData.dc_x2 || 'N/A'} / ${oddsData.dc_12 || 'N/A'}`,
);
console.log(
` 2.5 Alt/Üst: ${oddsData.ou25_u || 'N/A'} / ${oddsData.ou25_o || 'N/A'}`,
);
console.log(
` 1.5 Alt/Üst: ${oddsData.ou15_u || 'N/A'} / ${oddsData.ou15_o || 'N/A'}`,
);
// =====================================
// ADIM 2: TAKIM İSTATİSTİKLERİ
// =====================================
console.log('\n========================================');
console.log('📈 ADIM 2: TAKIM İSTATİSTİKLERİ');
console.log('========================================');
// Ev sahibi son 10 maç
const homeTeamRecentMatches = await prisma.match.findMany({
where: {
OR: [
{ homeTeamId: selectedMatch.homeTeamId },
{ awayTeamId: selectedMatch.homeTeamId },
],
sport: 'football',
state: 'postGame',
scoreHome: { not: null },
scoreAway: { not: null },
},
include: { homeTeam: true, awayTeam: true },
take: 10,
orderBy: { mstUtc: 'desc' },
});
// Ev sahibi istatistik hesapla
let homeWins = 0,
homeDraws = 0,
homeLosses = 0;
let homeGoalsFor = 0,
homeGoalsAgainst = 0;
for (const m of homeTeamRecentMatches) {
const isHome = m.homeTeamId === selectedMatch.homeTeamId;
const gf = isHome ? m.scoreHome : m.scoreAway;
const ga = isHome ? m.scoreAway : m.scoreHome;
homeGoalsFor += gf || 0;
homeGoalsAgainst += ga || 0;
if (gf > ga) homeWins++;
else if (gf < ga) homeLosses++;
else homeDraws++;
}
console.log(`\n🏠 ${selectedMatch.homeTeam?.name} (Ev Sahibi):`);
console.log(` Son 10 Maç: ${homeWins}G ${homeDraws}B ${homeLosses}M`);
console.log(` Gol Averajı: ${homeGoalsFor} attı, ${homeGoalsAgainst} yedi`);
console.log(` Ortalama Gol: ${(homeGoalsFor / 10).toFixed(2)} / maç`);
console.log(
` Ortalama Yenilen: ${(homeGoalsAgainst / 10).toFixed(2)} / maç`,
);
// Deplasman takımı son 10 maç
const awayTeamRecentMatches = await prisma.match.findMany({
where: {
OR: [
{ homeTeamId: selectedMatch.awayTeamId },
{ awayTeamId: selectedMatch.awayTeamId },
],
sport: 'football',
state: 'postGame',
scoreHome: { not: null },
scoreAway: { not: null },
},
include: { homeTeam: true, awayTeam: true },
take: 10,
orderBy: { mstUtc: 'desc' },
});
let awayWins = 0,
awayDraws = 0,
awayLosses = 0;
let awayGoalsFor = 0,
awayGoalsAgainst = 0;
for (const m of awayTeamRecentMatches) {
const isHome = m.homeTeamId === selectedMatch.awayTeamId;
const gf = isHome ? m.scoreHome : m.scoreAway;
const ga = isHome ? m.scoreAway : m.scoreHome;
awayGoalsFor += gf || 0;
awayGoalsAgainst += ga || 0;
if (gf > ga) awayWins++;
else if (gf < ga) awayLosses++;
else awayDraws++;
}
console.log(`\n✈️ ${selectedMatch.awayTeam?.name} (Deplasman):`);
console.log(` Son 10 Maç: ${awayWins}G ${awayDraws}B ${awayLosses}M`);
console.log(` Gol Averajı: ${awayGoalsFor} attı, ${awayGoalsAgainst} yedi`);
console.log(` Ortalama Gol: ${(awayGoalsFor / 10).toFixed(2)} / maç`);
console.log(
` Ortalama Yenilen: ${(awayGoalsAgainst / 10).toFixed(2)} / maç`,
);
// =====================================
// ADIM 3: ELO VE FORM SKORLARI
// =====================================
console.log('\n========================================');
console.log('🤖 ADIM 3: ELO & FORM SKORLARI');
console.log('========================================');
if (selectedMatch.aiFeatures) {
console.log(
`\nEv Sahibi ELO: ${selectedMatch.aiFeatures.homeElo.toFixed(0)}`,
);
console.log(
`Deplasman ELO: ${selectedMatch.aiFeatures.awayElo.toFixed(0)}`,
);
console.log(
`Ev Sahibi Form: ${selectedMatch.aiFeatures.homeFormScore.toFixed(1)}/100`,
);
console.log(
`Deplasman Form: ${selectedMatch.aiFeatures.awayFormScore.toFixed(1)}/100`,
);
console.log(
`Eksik Oyuncu Etkisi: ${selectedMatch.aiFeatures.missingPlayersImpact}`,
);
} else {
console.log('⚠️ AI Features mevcut değil');
}
// =====================================
// ADIM 4: HEAD-TO-HEAD
// =====================================
console.log('\n========================================');
console.log('🔄 ADIM 4: HEAD-TO-HEAD');
console.log('========================================');
const h2hMatches = await prisma.match.findMany({
where: {
OR: [
{
homeTeamId: selectedMatch.homeTeamId,
awayTeamId: selectedMatch.awayTeamId,
},
{
homeTeamId: selectedMatch.awayTeamId,
awayTeamId: selectedMatch.homeTeamId,
},
],
sport: 'football',
state: 'postGame',
},
include: { homeTeam: true, awayTeam: true },
take: 5,
orderBy: { mstUtc: 'desc' },
});
if (h2hMatches.length > 0) {
let h2hHomeWins = 0,
h2hDraws = 0,
h2hAwayWins = 0;
for (const m of h2hMatches) {
const homeTeamIsHome = m.homeTeamId === selectedMatch.homeTeamId;
const winner =
m.scoreHome > m.scoreAway
? 'home'
: m.scoreHome < m.scoreAway
? 'away'
: 'draw';
if (winner === 'draw') h2hDraws++;
else if (
(winner === 'home' && homeTeamIsHome) ||
(winner === 'away' && !homeTeamIsHome)
)
h2hHomeWins++;
else h2hAwayWins++;
console.log(
` ${m.homeTeam?.name} ${m.scoreHome} - ${m.scoreAway} ${m.awayTeam?.name}`,
);
}
console.log(
`\nKarşılıklı: ${selectedMatch.homeTeam?.name} ${h2hHomeWins}G, Beraberlik ${h2hDraws}, ${selectedMatch.awayTeam?.name} ${h2hAwayWins}G`,
);
} else {
console.log('Karşılıklı maç bulunamadı');
}
// =====================================
// ADIM 5: TAHMİN HESAPLAMA
// =====================================
console.log('\n========================================');
console.log('🎯 ADIM 5: TAHMİN HESAPLAMA');
console.log('========================================');
// Basit bir tahmin modeli (AI Engine'den bağımsız)
const homeForm = selectedMatch.aiFeatures?.homeFormScore || 50;
const awayForm = selectedMatch.aiFeatures?.awayFormScore || 50;
const homeElo = selectedMatch.aiFeatures?.homeElo || 1500;
const awayElo = selectedMatch.aiFeatures?.awayElo || 1500;
// Oranları olasılığa çevir
const msHomeProb = oddsData.ms_h ? (1 / oddsData.ms_h) * 100 : 33;
const msDrawProb = oddsData.ms_d ? (1 / oddsData.ms_d) * 100 : 33;
const msAwayProb = oddsData.ms_a ? (1 / oddsData.ms_a) * 100 : 33;
// Normalize et
const totalProb = msHomeProb + msDrawProb + msAwayProb;
const normHomeProb = (msHomeProb / totalProb) * 100;
const normDrawProb = (msDrawProb / totalProb) * 100;
const normAwayProb = (msAwayProb / totalProb) * 100;
console.log('\n📊 Oran Bazlı Olasılıklar:');
console.log(` 1 (Ev): %${normHomeProb.toFixed(1)}`);
console.log(` X (Beraberlik): %${normDrawProb.toFixed(1)}`);
console.log(` 2 (Deplasman): %${normAwayProb.toFixed(1)}`);
// Form bazlı ağırlık
const formDiff = homeForm - awayForm;
const eloDiff = homeElo - awayElo;
console.log(`\n📈 Form Farkı: ${formDiff.toFixed(1)} (Ev lehine pozitif)`);
console.log(`📈 ELO Farkı: ${eloDiff.toFixed(0)} (Ev lehine pozitif)`);
// Tahmin skoru hesapla
let homeScore = normHomeProb + formDiff * 0.3 + eloDiff * 0.02;
let awayScore = normAwayProb - formDiff * 0.3 - eloDiff * 0.02;
let drawScore = normDrawProb;
// Ev sahibi avantajı
homeScore += 5;
console.log(`\n🎯 Tahmin Skorları:`);
console.log(` Ev Sahibi: ${homeScore.toFixed(1)}`);
console.log(` Beraberlik: ${drawScore.toFixed(1)}`);
console.log(` Deplasman: ${awayScore.toFixed(1)}`);
// Final tahmin
const maxScore = Math.max(homeScore, drawScore, awayScore);
let prediction, confidence;
if (maxScore === homeScore) {
prediction = '1 (Ev Sahibi Kazanır)';
confidence = Math.min(95, Math.max(40, homeScore));
} else if (maxScore === awayScore) {
prediction = '2 (Deplasman Kazanır)';
confidence = Math.min(95, Math.max(40, awayScore));
} else {
prediction = 'X (Beraberlik)';
confidence = Math.min(95, Math.max(40, drawScore));
}
// Alt/Üst tahmini
const avgGoals =
((homeGoalsFor + homeGoalsAgainst) / 10 +
(awayGoalsFor + awayGoalsAgainst) / 10) /
2;
const ou25Prediction = avgGoals > 2.5 ? '2.5 ÜST' : '2.5 ALT';
const ou25Confidence = Math.min(85, Math.abs(avgGoals - 2.5) * 20 + 50);
console.log('\n========================================');
console.log('🏆 FİNAL TAHMİN');
console.log('========================================');
console.log(`\n⚽ Maç Sonucu: ${prediction}`);
console.log(` Güven: %${confidence.toFixed(1)}`);
console.log(`\n🎯 2.5 Alt/Üst: ${ou25Prediction}`);
console.log(` Güven: %${ou25Confidence.toFixed(1)}`);
console.log(` Ortalama Gol Beklentisi: ${avgGoals.toFixed(2)}`);
// Risk değerlendirmesi
console.log('\n⚠️ RİSK DEĞERLENDİRMESİ:');
const riskFactors = [];
if (Math.abs(homeForm - awayForm) < 10) {
riskFactors.push('Takımların form durumları yakın - BELIRSIZ');
}
if (
oddsData.ms_h &&
oddsData.ms_a &&
Math.abs(oddsData.ms_h - oddsData.ms_a) < 0.5
) {
riskFactors.push('Oranlar birbirine yakın - ZOR MAÇ');
}
if (h2hMatches.length < 3) {
riskFactors.push('Yeterli H2H verisi yok');
}
if (!selectedMatch.aiFeatures) {
riskFactors.push('AI özellikleri hesaplanmamış');
}
if (riskFactors.length === 0) {
console.log(' ✅ Düşük risk - Yüksek güvenilirlik');
} else {
for (const risk of riskFactors) {
console.log(` ⚠️ ${risk}`);
}
}
// Gerçek sonuç (eğer maç bitmişse)
if (selectedMatch.state === 'postGame' && selectedMatch.scoreHome !== null) {
console.log('\n========================================');
console.log('📊 GERÇEK SONUÇ');
console.log('========================================');
const actualResult =
selectedMatch.scoreHome > selectedMatch.scoreAway
? '1'
: selectedMatch.scoreHome < selectedMatch.scoreAway
? '2'
: 'X';
const totalGoals =
(selectedMatch.scoreHome || 0) + (selectedMatch.scoreAway || 0);
const actualOU = totalGoals > 2.5 ? '2.5 ÜST' : '2.5 ALT';
console.log(
`Skor: ${selectedMatch.scoreHome} - ${selectedMatch.scoreAway}`,
);
console.log(`Sonuç: ${actualResult}`);
console.log(`Alt/Üst: ${actualOU} (${totalGoals} gol)`);
}
await prisma.$disconnect();
}
analyzePredictionProcess().catch((e) => {
console.error('Hata:', e);
process.exit(1);
});