Files
gridpilot.gg/core/racing/application/use-cases/TeamRatingIntegrationAdapter.ts
2026-01-16 16:46:57 +01:00

142 lines
4.2 KiB
TypeScript

import type { TeamRaceResultsProvider } from '../ports/TeamRaceResultsProvider';
import type { TeamRatingEventRepository } from '@core/racing/domain/repositories/TeamRatingEventRepository';
import type { TeamRatingRepository } from '@core/racing/domain/repositories/TeamRatingRepository';
import { TeamDrivingRatingEventFactory } from '@core/racing/domain/services/TeamDrivingRatingEventFactory';
import { AppendTeamRatingEventsUseCase } from './AppendTeamRatingEventsUseCase';
/**
* Integration Adapter: TeamRatingIntegrationAdapter
*
* Minimal integration with race flow.
* Can be called from CompleteRaceUseCase to record team ratings.
*
* Usage in CompleteRaceUseCase:
* ```typescript
* // After race completion
* const teamRatingAdapter = new TeamRatingIntegrationAdapter(
* teamRaceResultsProvider,
* ratingEventRepository,
* ratingRepository
* );
*
* await teamRatingAdapter.recordTeamRatings(raceId);
* ```
*/
export class TeamRatingIntegrationAdapter {
private appendUseCase: AppendTeamRatingEventsUseCase;
constructor(
private readonly teamRaceResultsProvider: TeamRaceResultsProvider,
ratingEventRepository: TeamRatingEventRepository,
ratingRepository: TeamRatingRepository,
) {
this.appendUseCase = new AppendTeamRatingEventsUseCase(
ratingEventRepository,
ratingRepository
);
}
/**
* Record team ratings for a completed race.
* Returns true if successful, false otherwise.
*/
async recordTeamRatings(raceId: string): Promise<boolean> {
try {
// Get team race results
const teamRaceResults = await this.teamRaceResultsProvider.getTeamRaceResults(raceId);
if (!teamRaceResults || teamRaceResults.results.length === 0) {
return true; // No team results to process
}
// Create rating events
const eventsByTeam = TeamDrivingRatingEventFactory.createDrivingEventsFromRace(teamRaceResults);
if (eventsByTeam.size === 0) {
return true; // No events generated
}
// Process each team
for (const [teamId, events] of eventsByTeam) {
try {
await this.appendUseCase.execute(events);
} catch (error) {
console.error(`Failed to record team ratings for team ${teamId}:`, error);
return false;
}
}
return true;
} catch (error) {
console.error('Failed to record team ratings:', error);
return false;
}
}
/**
* Record team ratings with detailed output.
*/
async recordTeamRatingsWithDetails(raceId: string): Promise<{
success: boolean;
eventsCreated: number;
teamsUpdated: string[];
errors: string[];
}> {
const errors: string[] = [];
const teamsUpdated: string[] = [];
let totalEventsCreated = 0;
try {
const teamRaceResults = await this.teamRaceResultsProvider.getTeamRaceResults(raceId);
if (!teamRaceResults || teamRaceResults.results.length === 0) {
return {
success: true,
eventsCreated: 0,
teamsUpdated: [],
errors: [],
};
}
const eventsByTeam = TeamDrivingRatingEventFactory.createDrivingEventsFromRace(teamRaceResults);
if (eventsByTeam.size === 0) {
return {
success: true,
eventsCreated: 0,
teamsUpdated: [],
errors: [],
};
}
for (const [teamId, events] of eventsByTeam) {
try {
await this.appendUseCase.execute(events);
teamsUpdated.push(teamId);
totalEventsCreated += events.length;
} catch (error) {
const errorMsg = `Failed to process events for team ${teamId}: ${error instanceof Error ? error.message : 'Unknown error'}`;
errors.push(errorMsg);
}
}
return {
success: errors.length === 0,
eventsCreated: totalEventsCreated,
teamsUpdated,
errors,
};
} catch (error) {
const errorMsg = `Failed to record team ratings: ${error instanceof Error ? error.message : 'Unknown error'}`;
errors.push(errorMsg);
return {
success: false,
eventsCreated: 0,
teamsUpdated: [],
errors,
};
}
}
}