rating
This commit is contained in:
@@ -9,6 +9,7 @@ import { RatingUpdateService } from '@core/identity/domain/services/RatingUpdate
|
||||
import { Result } from '@core/shared/application/Result';
|
||||
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
|
||||
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
|
||||
import type { IRaceResultsProvider } from '@core/identity/application/ports/IRaceResultsProvider';
|
||||
|
||||
export interface CompleteRaceWithRatingsInput {
|
||||
raceId: string;
|
||||
@@ -32,6 +33,7 @@ interface DriverRatingProvider {
|
||||
|
||||
/**
|
||||
* Enhanced CompleteRaceUseCase that includes rating updates.
|
||||
* EVOLVED (Slice 7): Now uses ledger-based rating updates for transparency and auditability.
|
||||
*/
|
||||
export class CompleteRaceUseCaseWithRatings {
|
||||
constructor(
|
||||
@@ -42,6 +44,7 @@ export class CompleteRaceUseCaseWithRatings {
|
||||
private readonly driverRatingProvider: DriverRatingProvider,
|
||||
private readonly ratingUpdateService: RatingUpdateService,
|
||||
private readonly output: UseCaseOutputPort<CompleteRaceWithRatingsResult>,
|
||||
private readonly raceResultsProvider?: IRaceResultsProvider, // Optional: for new ledger flow
|
||||
) {}
|
||||
|
||||
async execute(command: CompleteRaceWithRatingsInput): Promise<
|
||||
@@ -93,8 +96,41 @@ export class CompleteRaceUseCaseWithRatings {
|
||||
|
||||
await this.updateStandings(race.leagueId, results);
|
||||
|
||||
// SLICE 7: Use new ledger-based approach if raceResultsProvider is available
|
||||
// This provides backward compatibility while evolving to event-driven architecture
|
||||
try {
|
||||
await this.updateDriverRatings(results, registeredDriverIds.length);
|
||||
if (this.raceResultsProvider) {
|
||||
// NEW LEDGER APPROACH: Use RecordRaceRatingEventsUseCase via RatingUpdateService
|
||||
const raceResultsData = {
|
||||
raceId,
|
||||
results: results.map(result => ({
|
||||
userId: result.driverId.toString(),
|
||||
startPos: result.startPosition.toNumber(),
|
||||
finishPos: result.position.toNumber(),
|
||||
incidents: result.incidents.toNumber(),
|
||||
status: 'finished' as const, // RaceResultGenerator only generates finished results
|
||||
})),
|
||||
};
|
||||
|
||||
try {
|
||||
const ratingResult = await this.ratingUpdateService.recordRaceRatingEvents(
|
||||
raceId,
|
||||
raceResultsData.results
|
||||
);
|
||||
|
||||
if (!ratingResult.success) {
|
||||
console.warn(`[Slice 7] Ledger-based rating update failed for race ${raceId}, falling back to legacy method`);
|
||||
await this.updateDriverRatingsLegacy(results, registeredDriverIds.length);
|
||||
}
|
||||
} catch (error) {
|
||||
// If ledger approach throws error, fall back to legacy method
|
||||
console.warn(`[Slice 7] Ledger-based rating update threw error for race ${raceId}, falling back to legacy method: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||
await this.updateDriverRatingsLegacy(results, registeredDriverIds.length);
|
||||
}
|
||||
} else {
|
||||
// BACKWARD COMPATIBLE: Use legacy direct update approach
|
||||
await this.updateDriverRatingsLegacy(results, registeredDriverIds.length);
|
||||
}
|
||||
} catch (error) {
|
||||
return Result.err({
|
||||
code: 'RATING_UPDATE_FAILED',
|
||||
@@ -161,7 +197,11 @@ export class CompleteRaceUseCaseWithRatings {
|
||||
}
|
||||
}
|
||||
|
||||
private async updateDriverRatings(results: RaceResult[], totalDrivers: number): Promise<void> {
|
||||
/**
|
||||
* Legacy rating update method (BACKWARD COMPATIBLE)
|
||||
* Uses direct updates via RatingUpdateService
|
||||
*/
|
||||
private async updateDriverRatingsLegacy(results: RaceResult[], totalDrivers: number): Promise<void> {
|
||||
const driverResults = results.map((result) => ({
|
||||
driverId: result.driverId.toString(),
|
||||
position: result.position.toNumber(),
|
||||
|
||||
Reference in New Issue
Block a user