team rating
This commit is contained in:
121
core/racing/application/use-cases/TeamRatingFactoryUseCase.ts
Normal file
121
core/racing/application/use-cases/TeamRatingFactoryUseCase.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* Application Use Case: TeamRatingFactoryUseCase
|
||||
*
|
||||
* Factory use case for creating team rating events from race results.
|
||||
* This replaces direct team rating calculations with event-based approach.
|
||||
* Mirrors the user rating factory pattern.
|
||||
*/
|
||||
|
||||
import type { Logger } from '@core/shared/application';
|
||||
import type { ITeamRaceResultsProvider } from '../ports/ITeamRaceResultsProvider';
|
||||
import { TeamDrivingRatingEventFactory } from '@core/racing/domain/services/TeamDrivingRatingEventFactory';
|
||||
import { TeamRatingEvent } from '@core/racing/domain/entities/TeamRatingEvent';
|
||||
import { TeamRatingEventId } from '@core/racing/domain/value-objects/TeamRatingEventId';
|
||||
import { TeamRatingDimensionKey } from '@core/racing/domain/value-objects/TeamRatingDimensionKey';
|
||||
import { TeamRatingDelta } from '@core/racing/domain/value-objects/TeamRatingDelta';
|
||||
|
||||
export interface TeamRatingFactoryInput {
|
||||
raceId: string;
|
||||
}
|
||||
|
||||
export interface TeamRatingFactoryOutput {
|
||||
success: boolean;
|
||||
raceId: string;
|
||||
events: TeamRatingEvent[];
|
||||
errors: string[];
|
||||
}
|
||||
|
||||
export class TeamRatingFactoryUseCase {
|
||||
constructor(
|
||||
private readonly teamRaceResultsProvider: ITeamRaceResultsProvider,
|
||||
private readonly logger: Logger
|
||||
) {
|
||||
this.logger.info('[TeamRatingFactoryUseCase] Initialized');
|
||||
}
|
||||
|
||||
async execute(input: TeamRatingFactoryInput): Promise<TeamRatingFactoryOutput> {
|
||||
this.logger.debug(`[TeamRatingFactoryUseCase] Creating rating events for race ${input.raceId}`);
|
||||
|
||||
try {
|
||||
// Load team race results
|
||||
const teamRaceResults = await this.teamRaceResultsProvider.getTeamRaceResults(input.raceId);
|
||||
|
||||
if (!teamRaceResults) {
|
||||
return {
|
||||
success: false,
|
||||
raceId: input.raceId,
|
||||
events: [],
|
||||
errors: ['Team race results not found'],
|
||||
};
|
||||
}
|
||||
|
||||
// Use factory to create events
|
||||
const eventsByTeam = TeamDrivingRatingEventFactory.createDrivingEventsFromRace(teamRaceResults);
|
||||
|
||||
// Flatten events from all teams
|
||||
const allEvents: TeamRatingEvent[] = [];
|
||||
for (const [, events] of eventsByTeam) {
|
||||
allEvents.push(...events);
|
||||
}
|
||||
|
||||
if (allEvents.length === 0) {
|
||||
this.logger.info(`[TeamRatingFactoryUseCase] No events generated for race ${input.raceId}`);
|
||||
return {
|
||||
success: true,
|
||||
raceId: input.raceId,
|
||||
events: [],
|
||||
errors: [],
|
||||
};
|
||||
}
|
||||
|
||||
this.logger.info(`[TeamRatingFactoryUseCase] Generated ${allEvents.length} events for race ${input.raceId}`);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
raceId: input.raceId,
|
||||
events: allEvents,
|
||||
errors: [],
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
const errorMsg = `Failed to create rating events: ${error instanceof Error ? error.message : 'Unknown error'}`;
|
||||
this.logger.error('[TeamRatingFactoryUseCase] Error:', error instanceof Error ? error : new Error(String(error)));
|
||||
|
||||
return {
|
||||
success: false,
|
||||
raceId: input.raceId,
|
||||
events: [],
|
||||
errors: [errorMsg],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create team rating events manually (for testing or manual adjustments)
|
||||
*/
|
||||
createManualEvents(
|
||||
teamId: string,
|
||||
dimension: string,
|
||||
delta: number,
|
||||
reason: string,
|
||||
sourceType: 'race' | 'penalty' | 'vote' | 'adminAction' | 'manualAdjustment',
|
||||
sourceId?: string
|
||||
): TeamRatingEvent[] {
|
||||
const source = sourceId ? { type: sourceType, id: sourceId } : { type: sourceType };
|
||||
|
||||
const event = TeamRatingEvent.create({
|
||||
id: TeamRatingEventId.generate(),
|
||||
teamId,
|
||||
dimension: TeamRatingDimensionKey.create(dimension),
|
||||
delta: TeamRatingDelta.create(delta),
|
||||
occurredAt: new Date(),
|
||||
createdAt: new Date(),
|
||||
source: source,
|
||||
reason: { code: reason },
|
||||
visibility: { public: true },
|
||||
version: 1,
|
||||
});
|
||||
|
||||
return [event];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user