177 lines
4.7 KiB
TypeScript
Executable File
177 lines
4.7 KiB
TypeScript
Executable File
import {
|
|
Controller,
|
|
Get,
|
|
Post,
|
|
Body,
|
|
Param,
|
|
HttpCode,
|
|
HttpStatus,
|
|
NotFoundException,
|
|
} from "@nestjs/common";
|
|
import { ApiTags, ApiOperation, ApiResponse, ApiParam } from "@nestjs/swagger";
|
|
import { PredictionsService } from "./predictions.service";
|
|
import {
|
|
MatchPredictionDto,
|
|
PredictionHistoryResponseDto,
|
|
UpcomingPredictionsDto,
|
|
ValueBetDto,
|
|
AIHealthDto,
|
|
} from "./dto";
|
|
import {
|
|
GeneratePredictionDto,
|
|
SmartCouponRequestDto,
|
|
} from "./dto/predictions-request.dto";
|
|
import { Public } from "src/common/decorators";
|
|
|
|
@ApiTags("Predictions")
|
|
@Controller("predictions")
|
|
export class PredictionsController {
|
|
constructor(private readonly predictionsService: PredictionsService) {}
|
|
|
|
/**
|
|
* GET /predictions/health
|
|
* Check AI Engine health status
|
|
*/
|
|
@Get("health")
|
|
@ApiOperation({ summary: "Check AI Engine health status" })
|
|
@ApiResponse({ status: 200, type: AIHealthDto })
|
|
async checkHealth(): Promise<AIHealthDto> {
|
|
return this.predictionsService.checkHealth();
|
|
}
|
|
|
|
/**
|
|
* GET /predictions/upcoming
|
|
* Get predictions for upcoming matches
|
|
*/
|
|
@Get("upcoming")
|
|
@ApiOperation({ summary: "Get predictions for upcoming matches" })
|
|
@ApiResponse({ status: 200, type: UpcomingPredictionsDto })
|
|
async getUpcoming(): Promise<UpcomingPredictionsDto> {
|
|
return this.predictionsService.getUpcomingPredictions();
|
|
}
|
|
|
|
/**
|
|
* GET /predictions/test/:id
|
|
* Refetch match data and get prediction
|
|
*/
|
|
@Get("test/:id")
|
|
@ApiOperation({ summary: "Refetch match data and get prediction" })
|
|
@ApiResponse({
|
|
status: 200,
|
|
description: "Prediction details",
|
|
schema: { type: "object" },
|
|
})
|
|
@ApiParam({ name: "id", description: "Match ID" })
|
|
async getTestPrediction(@Param("id") id: string) {
|
|
return this.predictionsService.testPrediction(id);
|
|
}
|
|
|
|
/**
|
|
* GET /predictions/value-bets
|
|
* Get EV+ betting opportunities
|
|
*/
|
|
@Get("value-bets")
|
|
@ApiOperation({ summary: "Get value betting opportunities (EV+)" })
|
|
@ApiResponse({ status: 200, type: [ValueBetDto] })
|
|
async getValueBets(): Promise<ValueBetDto[]> {
|
|
return this.predictionsService.getValueBets();
|
|
}
|
|
|
|
/**
|
|
* GET /predictions/history
|
|
* Get prediction history and accuracy stats
|
|
*/
|
|
@Get("history")
|
|
@ApiOperation({ summary: "Get prediction history and accuracy statistics" })
|
|
@ApiResponse({ status: 200, type: PredictionHistoryResponseDto })
|
|
async getHistory(): Promise<PredictionHistoryResponseDto> {
|
|
return this.predictionsService.getPredictionHistory();
|
|
}
|
|
|
|
/**
|
|
* GET /predictions/:matchId
|
|
* Get prediction for a specific match
|
|
*/
|
|
@Get(":matchId")
|
|
@Public()
|
|
@ApiOperation({ summary: "Get prediction for a specific match" })
|
|
@ApiParam({ name: "matchId", description: "Match ID" })
|
|
@ApiResponse({
|
|
status: 200,
|
|
description: "Match prediction",
|
|
schema: { type: "object" },
|
|
type: MatchPredictionDto,
|
|
})
|
|
@ApiResponse({ status: 404, description: "Match not found" })
|
|
async getPrediction(
|
|
@Param("matchId") matchId: string,
|
|
): Promise<MatchPredictionDto> {
|
|
const cached = await this.predictionsService.getCachedPrediction(matchId);
|
|
if (cached) {
|
|
return cached;
|
|
}
|
|
|
|
// Get from AI Engine
|
|
const prediction = await this.predictionsService.getPredictionById(matchId);
|
|
|
|
if (!prediction) {
|
|
throw new NotFoundException(`Match not found: ${matchId}`);
|
|
}
|
|
|
|
return prediction;
|
|
}
|
|
|
|
/**
|
|
* POST /predictions/generate
|
|
* Generate prediction with provided match data
|
|
*/
|
|
@Post("generate")
|
|
@HttpCode(HttpStatus.OK)
|
|
@ApiOperation({ summary: "Generate prediction with provided match data" })
|
|
@ApiResponse({ status: 200, type: MatchPredictionDto })
|
|
async generatePrediction(
|
|
@Body() dto: GeneratePredictionDto,
|
|
): Promise<MatchPredictionDto> {
|
|
const prediction = await this.predictionsService.getPredictionWithData({
|
|
matchId: dto.matchId,
|
|
});
|
|
|
|
if (!prediction) {
|
|
throw new NotFoundException("Failed to generate prediction");
|
|
}
|
|
|
|
return prediction;
|
|
}
|
|
|
|
/**
|
|
* POST /predictions/smart-coupon
|
|
* Generate Smart Coupon using AI Engine V20
|
|
*/
|
|
@Post("smart-coupon")
|
|
@HttpCode(HttpStatus.OK)
|
|
@ApiOperation({
|
|
summary: "Generate Smart Coupon with V20 AI recommendations",
|
|
})
|
|
@ApiResponse({
|
|
status: 200,
|
|
description: "Smart coupon generated successfully",
|
|
schema: { type: "object" },
|
|
})
|
|
async generateSmartCoupon(@Body() dto: SmartCouponRequestDto): Promise<any> {
|
|
const coupon = await this.predictionsService.getSmartCoupon(
|
|
dto.matchIds,
|
|
dto.strategy || "BALANCED",
|
|
{
|
|
maxMatches: dto.maxMatches,
|
|
minConfidence: dto.minConfidence,
|
|
},
|
|
);
|
|
|
|
if (!coupon) {
|
|
throw new NotFoundException("Failed to generate Smart Coupon");
|
|
}
|
|
|
|
return coupon;
|
|
}
|
|
}
|