154 lines
4.8 KiB
TypeScript
154 lines
4.8 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();
|
|
|
|
const matchId = '30gnuehy43on5orc9n3sh8pw4'; // Valencia vs Celta Vigo - HT/FT test
|
|
|
|
async function getPrediction() {
|
|
console.log('🔮 VQWEN v3 PREDICTION');
|
|
console.log('='.repeat(80));
|
|
|
|
// 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: ${matchId}`);
|
|
await prisma.$disconnect();
|
|
return;
|
|
}
|
|
|
|
console.log(`\n📊 ${match.homeTeam?.name} vs ${match.awayTeam?.name}`);
|
|
console.log(`🏆 League: ${match.league?.name}`);
|
|
console.log(`📅 Match Time: ${new Date(Number(match.mstUtc)).toISOString()}`);
|
|
console.log(`📍 Status: ${match.state} / ${match.substate}`);
|
|
|
|
// Check data availability
|
|
console.log(`\n📦 DATA CHECK:`);
|
|
console.log(` Odds: ${match.odds ? '✅' : '❌'}`);
|
|
console.log(` Lineups: ${match.lineups ? '✅' : '❌'}`);
|
|
console.log(` Sidelined: ${match.sidelined ? '✅' : '❌'}`);
|
|
console.log(` Referee: ${match.refereeName || 'N/A'}`);
|
|
|
|
// Send prediction request
|
|
const aiEngineUrl = 'http://localhost:8007';
|
|
const predictionUrl = `${aiEngineUrl}/v20plus/analyze/${matchId}`;
|
|
|
|
console.log(`\n🤖 Sending to AI Engine...`);
|
|
|
|
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;
|
|
|
|
// Print full JSON
|
|
console.log('='.repeat(80));
|
|
console.log('📊 FULL PREDICTION JSON:');
|
|
console.log('='.repeat(80));
|
|
console.log(JSON.stringify(pkg, null, 2));
|
|
|
|
// Summary
|
|
console.log(`\n${'='.repeat(80)}`);
|
|
console.log('🎯 PREDICTION SUMMARY:');
|
|
console.log('='.repeat(80));
|
|
|
|
const dq = pkg.data_quality;
|
|
console.log(`\n📦 Data Quality: ${dq.label} (${dq.score})`);
|
|
console.log(` Home lineup: ${dq.home_lineup_count}`);
|
|
console.log(` Away lineup: ${dq.away_lineup_count}`);
|
|
console.log(` Source: ${dq.lineup_source}`);
|
|
|
|
const eb = pkg.engine_breakdown;
|
|
console.log(`\n📈 Engine Signals:`);
|
|
console.log(` Team: ${eb.team}%`);
|
|
console.log(` Player: ${eb.player}%`);
|
|
console.log(` Odds: ${eb.odds}%`);
|
|
console.log(` Referee: ${eb.referee}%`);
|
|
|
|
const mp = pkg.main_pick;
|
|
console.log(`\n🥇 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(` Playable: ${mp.playable}`);
|
|
console.log(` Stake: ${mp.stake_units} units`);
|
|
|
|
if (pkg.value_pick) {
|
|
const vp = pkg.value_pick;
|
|
console.log(`\n💎 Value Pick:`);
|
|
console.log(` Market: ${vp.market}`);
|
|
console.log(` Pick: ${vp.pick}`);
|
|
console.log(` Confidence: ${vp.confidence}%`);
|
|
console.log(` Odds: ${vp.odds}`);
|
|
console.log(` Edge: ${(vp.edge * 100).toFixed(2)}%`);
|
|
}
|
|
|
|
const sp = pkg.score_prediction;
|
|
console.log(`\n⚽ Score Prediction:`);
|
|
console.log(` FT: ${sp.ft}`);
|
|
console.log(` HT: ${sp.ht}`);
|
|
console.log(` xG: ${sp.xg_home} - ${sp.xg_away} (Total: ${sp.xg_total})`);
|
|
|
|
console.log(`\n🎲 Top 5 Scores:`);
|
|
pkg.scenario_top5.forEach((s: any, i: number) => {
|
|
console.log(` ${i + 1}. ${s.score} (${s.prob}%)`);
|
|
});
|
|
|
|
const risk = pkg.risk;
|
|
console.log(`\n⚠️ Risk: ${risk.level} (${risk.score}/10)`);
|
|
if (risk.warnings?.length > 0) {
|
|
console.log(` Warnings: ${risk.warnings.join(', ')}`);
|
|
}
|
|
|
|
console.log(`\n💬 Reasoning:`);
|
|
pkg.reasoning_factors.forEach((f: string) => console.log(` - ${f}`));
|
|
|
|
if (pkg.ai_commentary) {
|
|
console.log(`\n💬 AI Commentary:`);
|
|
console.log(` ${pkg.ai_commentary}`);
|
|
}
|
|
|
|
// HT/FT specific check
|
|
console.log(`\n🔍 HT/FT CHECK:`);
|
|
const htft = pkg.market_board?.HTFT;
|
|
if (htft && htft.probs && Object.keys(htft.probs).length > 0) {
|
|
console.log(` ✅ HT/FT PROBS PRESENT:`);
|
|
Object.entries(htft.probs).forEach(([key, val]) => {
|
|
console.log(` ${key}: ${(val as number * 100).toFixed(2)}%`);
|
|
});
|
|
|
|
// Find best HT/FT
|
|
const best = Object.entries(htft.probs).reduce((a, b) => (b[1] as number) > (a[1] as number) ? b : a);
|
|
console.log(`\n 🎯 BEST HT/FT: ${best[0]} (${(best[1] as number * 100).toFixed(2)}%)`);
|
|
} else {
|
|
console.log(` ❌ HT/FT PROBS EMPTY`);
|
|
}
|
|
|
|
await prisma.$disconnect();
|
|
}
|
|
|
|
getPrediction().catch(console.error);
|