187 lines
6.3 KiB
TypeScript
187 lines
6.3 KiB
TypeScript
import { PrismaClient } from '@prisma/client';
|
|
import * as dotenv from 'dotenv';
|
|
import axios from 'axios';
|
|
|
|
dotenv.config();
|
|
|
|
// BigInt serialization fix
|
|
(BigInt.prototype as any).toJSON = function () {
|
|
return this.toString();
|
|
};
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
// Test with Club Brugge match
|
|
const matchId = '7cnm7h7qbsq2bbaxngusojh90';
|
|
|
|
async function verifyDataUsage() {
|
|
console.log('🔍 VERIFYING DATA USAGE IN AI ENGINE');
|
|
console.log('='.repeat(80));
|
|
|
|
// 1. Fetch match from database
|
|
const match = await prisma.liveMatch.findUnique({
|
|
where: { id: matchId },
|
|
include: {
|
|
homeTeam: true,
|
|
awayTeam: true,
|
|
league: true,
|
|
},
|
|
});
|
|
|
|
if (!match) {
|
|
console.log('❌ Match not found');
|
|
return;
|
|
}
|
|
|
|
console.log(`\n📊 Match: ${match.homeTeam?.name} vs ${match.awayTeam?.name}`);
|
|
console.log(`\n1️⃣ ODDS DATA:`);
|
|
console.log(` Type: ${typeof match.odds}`);
|
|
console.log(` Is null: ${match.odds === null}`);
|
|
|
|
if (match.odds) {
|
|
const oddsStr = typeof match.odds === 'string' ? match.odds : JSON.stringify(match.odds);
|
|
console.log(` Length: ${oddsStr.length} characters`);
|
|
|
|
// Parse and show summary
|
|
try {
|
|
const oddsObj = typeof match.odds === 'string' ? JSON.parse(match.odds) : match.odds;
|
|
const markets = Object.keys(oddsObj);
|
|
console.log(` Markets: ${markets.length}`);
|
|
console.log(` Sample markets: ${markets.slice(0, 5).join(', ')}...`);
|
|
console.log(` ✅ ODDS DATA: PRESENT`);
|
|
} catch (e) {
|
|
console.log(` ❌ ODDS DATA: Invalid JSON`);
|
|
}
|
|
} else {
|
|
console.log(` ❌ ODDS DATA: NULL/MISSING`);
|
|
}
|
|
|
|
console.log(`\n2️⃣ SIDELINED DATA:`);
|
|
console.log(` Type: ${typeof match.sidelined}`);
|
|
console.log(` Is null: ${match.sidelined === null}`);
|
|
|
|
if (match.sidelined) {
|
|
const sidelinedStr = typeof match.sidelined === 'string' ? match.sidelined : JSON.stringify(match.sidelined);
|
|
console.log(` Length: ${sidelinedStr.length} characters`);
|
|
|
|
try {
|
|
const sidelinedObj = typeof match.sidelined === 'string' ? JSON.parse(match.sidelined) : match.sidelined;
|
|
const homeTeam = sidelinedObj.homeTeam || sidelinedObj.home;
|
|
const awayTeam = sidelinedObj.awayTeam || sidelinedObj.away;
|
|
|
|
console.log(` Home team sidelined: ${homeTeam?.totalSidelined || homeTeam?.players?.length || 0}`);
|
|
console.log(` Away team sidelined: ${awayTeam?.totalSidelined || awayTeam?.players?.length || 0}`);
|
|
console.log(` ✅ SIDELINED DATA: PRESENT`);
|
|
} catch (e) {
|
|
console.log(` ❌ SIDELINED DATA: Invalid JSON`);
|
|
}
|
|
} else {
|
|
console.log(` ❌ SIDELINED DATA: NULL/MISSING`);
|
|
}
|
|
|
|
console.log(`\n3️⃣ LINEUP DATA:`);
|
|
console.log(` Type: ${typeof match.lineups}`);
|
|
console.log(` Is null: ${match.lineups === null}`);
|
|
|
|
if (match.lineups) {
|
|
try {
|
|
const lineupsObj = typeof match.lineups === 'string' ? JSON.parse(match.lineups) : match.lineups;
|
|
const homeCount = lineupsObj.stats?.home?.length || 0;
|
|
const awayCount = lineupsObj.stats?.away?.length || 0;
|
|
console.log(` Home lineup: ${homeCount}`);
|
|
console.log(` Away lineup: ${awayCount}`);
|
|
console.log(` ✅ LINEUP DATA: PRESENT`);
|
|
} catch (e) {
|
|
console.log(` ❌ LINEUP DATA: Invalid JSON`);
|
|
}
|
|
} else {
|
|
console.log(` ❌ LINEUP DATA: NULL/MISSING`);
|
|
}
|
|
|
|
// 2. Send prediction request
|
|
console.log(`\n\n🤖 SENDING TO AI ENGINE...`);
|
|
const aiEngineUrl = 'http://localhost:8007';
|
|
const predictionUrl = `${aiEngineUrl}/v20plus/analyze/${matchId}`;
|
|
|
|
const startTime = Date.now();
|
|
const response = await axios.post(predictionUrl, {}, {
|
|
timeout: 120000,
|
|
});
|
|
const elapsed = ((Date.now() - startTime) / 1000).toFixed(2);
|
|
|
|
console.log(`✅ Prediction received in ${elapsed}s\n`);
|
|
|
|
const pkg = response.data;
|
|
|
|
// 3. Verify data quality
|
|
console.log('📊 AI ENGINE DATA QUALITY:');
|
|
const dq = pkg.data_quality;
|
|
console.log(` Label: ${dq.label}`);
|
|
console.log(` Score: ${dq.score}`);
|
|
console.log(` Home lineup count: ${dq.home_lineup_count}`);
|
|
console.log(` Away lineup count: ${dq.away_lineup_count}`);
|
|
console.log(` Lineup source: ${dq.lineup_source}`);
|
|
console.log(` Flags: ${dq.flags.join(', ') || 'None'}`);
|
|
|
|
// 4. Check if odds influenced the prediction
|
|
console.log('\n📈 ENGINE BREAKDOWN (signal weights):');
|
|
const eb = pkg.engine_breakdown;
|
|
if (eb) {
|
|
console.log(` Team signal: ${eb.team}%`);
|
|
console.log(` Player signal: ${eb.player}%`);
|
|
console.log(` Odds signal: ${eb.odds}%`);
|
|
console.log(` Referee signal: ${eb.referee}%`);
|
|
|
|
if (eb.odds > 50) {
|
|
console.log(` ✅ ODDS DATA: USED SIGNIFICANTLY (${eb.odds}%)`);
|
|
} else if (eb.odds > 0) {
|
|
console.log(` ⚠️ ODDS DATA: USED MINIMALLY (${eb.odds}%)`);
|
|
} else {
|
|
console.log(` ❌ ODDS DATA: NOT USED`);
|
|
}
|
|
}
|
|
|
|
// 5. Check sidelined impact
|
|
console.log('\n⚠️ SIDELINED IMPACT:');
|
|
const reasoning = pkg.reasoning_factors || [];
|
|
const hasSidelinedMention = reasoning.some((f: string) =>
|
|
f.toLowerCase().includes('sideline') ||
|
|
f.toLowerCase().includes('injury') ||
|
|
f.toLowerCase().includes('absence') ||
|
|
f.toLowerCase().includes('missing')
|
|
);
|
|
|
|
if (hasSidelinedMention) {
|
|
console.log(` ✅ SIDELINED DATA: MENTIONED IN REASONING`);
|
|
reasoning.forEach((f: string) => {
|
|
if (f.toLowerCase().includes('sideline') ||
|
|
f.toLowerCase().includes('injury') ||
|
|
f.toLowerCase().includes('absence') ||
|
|
f.toLowerCase().includes('missing')) {
|
|
console.log(` - ${f}`);
|
|
}
|
|
});
|
|
} else {
|
|
console.log(` ⚠️ SIDELINED DATA: No explicit mention (but may still be used internally)`);
|
|
console.log(` Reasoning factors: ${reasoning.join(', ')}`);
|
|
}
|
|
|
|
// 6. Main pick summary
|
|
console.log('\n🎯 PREDICTION SUMMARY:');
|
|
const mp = pkg.main_pick;
|
|
console.log(` Market: ${mp.market}`);
|
|
console.log(` Pick: ${mp.pick}`);
|
|
console.log(` Confidence: ${mp.confidence}%`);
|
|
console.log(` Odds: ${mp.odds}`);
|
|
console.log(` Edge: ${(mp.edge * 100).toFixed(2)}%`);
|
|
console.log(` Grade: ${mp.bet_grade}`);
|
|
|
|
console.log('\n' + '='.repeat(80));
|
|
console.log('✅ VERIFICATION COMPLETE');
|
|
console.log('='.repeat(80));
|
|
|
|
await prisma.$disconnect();
|
|
}
|
|
|
|
verifyDataUsage().catch(console.error);
|