team rating
This commit is contained in:
@@ -6,10 +6,10 @@ import { IDriverRepository } from '@core/racing/domain/repositories/IDriverRepos
|
||||
import { IRaceRegistrationRepository } from '@core/racing/domain/repositories/IRaceRegistrationRepository';
|
||||
import type { ITeamMembershipRepository } from '@core/racing/domain/repositories/ITeamMembershipRepository';
|
||||
import type { ITeamRepository } from '@core/racing/domain/repositories/ITeamRepository';
|
||||
import { IDriverStatsService } from '@core/racing/domain/services/IDriverStatsService';
|
||||
import { IRankingService } from '@core/racing/domain/services/IRankingService';
|
||||
import type { Logger, UseCaseOutputPort } from '@core/shared/application';
|
||||
import type { ISocialGraphRepository } from '@core/social/domain/repositories/ISocialGraphRepository';
|
||||
import type { IResultRepository } from '@core/racing/domain/repositories/IResultRepository';
|
||||
import type { IStandingRepository } from '@core/racing/domain/repositories/IStandingRepository';
|
||||
|
||||
// Import use cases
|
||||
import { CompleteDriverOnboardingUseCase } from '@core/racing/application/use-cases/CompleteDriverOnboardingUseCase';
|
||||
@@ -25,9 +25,18 @@ import { InMemoryImageServiceAdapter } from '@adapters/media/ports/InMemoryImage
|
||||
import { InMemoryNotificationPreferenceRepository } from '@adapters/notifications/persistence/inmemory/InMemoryNotificationPreferenceRepository';
|
||||
import { InMemoryDriverExtendedProfileProvider } from '@adapters/racing/ports/InMemoryDriverExtendedProfileProvider';
|
||||
import { InMemoryDriverRatingProvider } from '@adapters/racing/ports/InMemoryDriverRatingProvider';
|
||||
import { InMemoryDriverStatsService } from '@adapters/racing/services/InMemoryDriverStatsService';
|
||||
import { InMemoryRankingService } from '@adapters/racing/services/InMemoryRankingService';
|
||||
import { IImageServicePort } from '@core/racing/application/ports/IImageServicePort';
|
||||
// Import new use cases
|
||||
import { RankingUseCase } from '@core/racing/application/use-cases/RankingUseCase';
|
||||
import { DriverStatsUseCase } from '@core/racing/application/use-cases/DriverStatsUseCase';
|
||||
// Import new repositories
|
||||
import { InMemoryDriverStatsRepository } from '@adapters/racing/persistence/inmemory/InMemoryDriverStatsRepository';
|
||||
import { InMemoryMediaRepository } from '@adapters/racing/persistence/media/InMemoryMediaRepository';
|
||||
// Import repository tokens
|
||||
import { IDriverStatsRepository } from '@core/racing/domain/repositories/IDriverStatsRepository';
|
||||
import { IMediaRepository } from '@core/racing/domain/repositories/IMediaRepository';
|
||||
// Import use case interfaces
|
||||
import type { IRankingUseCase } from '@core/racing/application/use-cases/IRankingUseCase';
|
||||
import type { IDriverStatsUseCase } from '@core/racing/application/use-cases/IDriverStatsUseCase';
|
||||
|
||||
// Import presenters
|
||||
import { CompleteOnboardingPresenter } from './presenters/CompleteOnboardingPresenter';
|
||||
@@ -39,8 +48,6 @@ import { DriverStatsPresenter } from './presenters/DriverStatsPresenter';
|
||||
|
||||
import {
|
||||
DRIVER_REPOSITORY_TOKEN,
|
||||
RANKING_SERVICE_TOKEN,
|
||||
DRIVER_STATS_SERVICE_TOKEN,
|
||||
DRIVER_RATING_PROVIDER_TOKEN,
|
||||
DRIVER_EXTENDED_PROFILE_PROVIDER_TOKEN,
|
||||
IMAGE_SERVICE_PORT_TOKEN,
|
||||
@@ -62,6 +69,10 @@ import {
|
||||
IS_DRIVER_REGISTERED_FOR_RACE_OUTPUT_PORT_TOKEN,
|
||||
UPDATE_DRIVER_PROFILE_OUTPUT_PORT_TOKEN,
|
||||
GET_PROFILE_OVERVIEW_OUTPUT_PORT_TOKEN,
|
||||
DRIVER_STATS_REPOSITORY_TOKEN,
|
||||
MEDIA_REPOSITORY_TOKEN,
|
||||
RANKING_SERVICE_TOKEN,
|
||||
DRIVER_STATS_SERVICE_TOKEN,
|
||||
} from './DriverTokens';
|
||||
|
||||
export * from './DriverTokens';
|
||||
@@ -73,7 +84,11 @@ export const DriverProviders: Provider[] = [
|
||||
DriverStatsPresenter,
|
||||
CompleteOnboardingPresenter,
|
||||
DriverRegistrationStatusPresenter,
|
||||
DriverPresenter,
|
||||
{
|
||||
provide: DriverPresenter,
|
||||
useFactory: (driverStatsRepository: IDriverStatsRepository) => new DriverPresenter(driverStatsRepository),
|
||||
inject: [DRIVER_STATS_REPOSITORY_TOKEN],
|
||||
},
|
||||
DriverProfilePresenter,
|
||||
|
||||
// Output ports (point to presenters)
|
||||
@@ -110,15 +125,33 @@ export const DriverProviders: Provider[] = [
|
||||
|
||||
// Repositories (racing + social repos are provided by imported persistence modules)
|
||||
{
|
||||
provide: RANKING_SERVICE_TOKEN,
|
||||
useFactory: (logger: Logger) => new InMemoryRankingService(logger),
|
||||
provide: DRIVER_STATS_REPOSITORY_TOKEN,
|
||||
useFactory: (logger: Logger) => new InMemoryDriverStatsRepository(logger),
|
||||
inject: [LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: DRIVER_STATS_SERVICE_TOKEN,
|
||||
useFactory: (logger: Logger) => new InMemoryDriverStatsService(logger),
|
||||
provide: MEDIA_REPOSITORY_TOKEN,
|
||||
useFactory: (logger: Logger) => new InMemoryMediaRepository(logger),
|
||||
inject: [LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: RANKING_SERVICE_TOKEN,
|
||||
useFactory: (
|
||||
standingRepo: IStandingRepository,
|
||||
driverRepo: IDriverRepository,
|
||||
logger: Logger
|
||||
) => new RankingUseCase(standingRepo, driverRepo, logger),
|
||||
inject: ['IStandingRepository', DRIVER_REPOSITORY_TOKEN, LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: DRIVER_STATS_SERVICE_TOKEN,
|
||||
useFactory: (
|
||||
resultRepo: IResultRepository,
|
||||
standingRepo: IStandingRepository,
|
||||
logger: Logger
|
||||
) => new DriverStatsUseCase(resultRepo, standingRepo, logger),
|
||||
inject: ['IResultRepository', 'IStandingRepository', LOGGER_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: DRIVER_RATING_PROVIDER_TOKEN,
|
||||
useFactory: (logger: Logger) => new InMemoryDriverRatingProvider(logger),
|
||||
@@ -145,13 +178,23 @@ export const DriverProviders: Provider[] = [
|
||||
provide: GET_DRIVERS_LEADERBOARD_USE_CASE_TOKEN,
|
||||
useFactory: (
|
||||
driverRepo: IDriverRepository,
|
||||
rankingService: IRankingService,
|
||||
driverStatsService: IDriverStatsService,
|
||||
imageService: IImageServicePort,
|
||||
rankingUseCase: IRankingUseCase,
|
||||
driverStatsUseCase: IDriverStatsUseCase,
|
||||
mediaRepository: IMediaRepository,
|
||||
logger: Logger,
|
||||
output: UseCaseOutputPort<unknown>,
|
||||
) => new GetDriversLeaderboardUseCase(driverRepo, rankingService, driverStatsService, (driverId: string) => Promise.resolve(imageService.getDriverAvatar(driverId)), logger, output),
|
||||
inject: [DRIVER_REPOSITORY_TOKEN, RANKING_SERVICE_TOKEN, DRIVER_STATS_SERVICE_TOKEN, IMAGE_SERVICE_PORT_TOKEN, LOGGER_TOKEN, GET_DRIVERS_LEADERBOARD_OUTPUT_PORT_TOKEN],
|
||||
) => new GetDriversLeaderboardUseCase(
|
||||
driverRepo,
|
||||
rankingUseCase,
|
||||
driverStatsUseCase,
|
||||
async (driverId: string) => {
|
||||
const avatar = await mediaRepository.getDriverAvatar(driverId);
|
||||
return avatar ?? undefined;
|
||||
},
|
||||
logger,
|
||||
output
|
||||
),
|
||||
inject: [DRIVER_REPOSITORY_TOKEN, RANKING_SERVICE_TOKEN, DRIVER_STATS_SERVICE_TOKEN, MEDIA_REPOSITORY_TOKEN, LOGGER_TOKEN, GET_DRIVERS_LEADERBOARD_OUTPUT_PORT_TOKEN],
|
||||
},
|
||||
{
|
||||
provide: GET_TOTAL_DRIVERS_USE_CASE_TOKEN,
|
||||
@@ -183,8 +226,8 @@ export const DriverProviders: Provider[] = [
|
||||
teamMembershipRepository: ITeamMembershipRepository,
|
||||
socialRepository: ISocialGraphRepository,
|
||||
driverExtendedProfileProvider: DriverExtendedProfileProvider,
|
||||
driverStatsService: IDriverStatsService,
|
||||
rankingService: IRankingService,
|
||||
driverStatsUseCase: IDriverStatsUseCase,
|
||||
rankingUseCase: IRankingUseCase,
|
||||
output: UseCaseOutputPort<unknown>,
|
||||
) =>
|
||||
new GetProfileOverviewUseCase(
|
||||
@@ -193,32 +236,8 @@ export const DriverProviders: Provider[] = [
|
||||
teamMembershipRepository,
|
||||
socialRepository,
|
||||
driverExtendedProfileProvider,
|
||||
(driverId: string) => {
|
||||
const stats = driverStatsService.getDriverStats(driverId);
|
||||
if (!stats) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
rating: stats.rating,
|
||||
wins: stats.wins,
|
||||
podiums: stats.podiums,
|
||||
dnfs: (stats as { dnfs?: number }).dnfs ?? 0,
|
||||
totalRaces: stats.totalRaces,
|
||||
avgFinish: null,
|
||||
bestFinish: null,
|
||||
worstFinish: null,
|
||||
overallRank: stats.overallRank,
|
||||
consistency: null,
|
||||
percentile: null,
|
||||
};
|
||||
},
|
||||
() =>
|
||||
rankingService.getAllDriverRankings().map(ranking => ({
|
||||
driverId: ranking.driverId,
|
||||
rating: ranking.rating,
|
||||
overallRank: ranking.overallRank,
|
||||
})),
|
||||
driverStatsUseCase,
|
||||
rankingUseCase,
|
||||
output,
|
||||
),
|
||||
inject: [
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export const DRIVER_REPOSITORY_TOKEN = 'IDriverRepository';
|
||||
export const RANKING_SERVICE_TOKEN = 'IRankingService';
|
||||
export const DRIVER_STATS_SERVICE_TOKEN = 'IDriverStatsService';
|
||||
export const RANKING_SERVICE_TOKEN = 'IRankingUseCase';
|
||||
export const DRIVER_STATS_SERVICE_TOKEN = 'IDriverStatsUseCase';
|
||||
export const DRIVER_RATING_PROVIDER_TOKEN = 'DriverRatingProvider';
|
||||
export const DRIVER_EXTENDED_PROFILE_PROVIDER_TOKEN = 'DriverExtendedProfileProvider';
|
||||
export const IMAGE_SERVICE_PORT_TOKEN = 'IImageServicePort';
|
||||
@@ -13,6 +13,10 @@ export const TEAM_MEMBERSHIP_REPOSITORY_TOKEN = 'ITeamMembershipRepository';
|
||||
export { SOCIAL_GRAPH_REPOSITORY_TOKEN };
|
||||
export const LOGGER_TOKEN = 'Logger';
|
||||
|
||||
// New tokens for clean architecture
|
||||
export const DRIVER_STATS_REPOSITORY_TOKEN = 'IDriverStatsRepository';
|
||||
export const MEDIA_REPOSITORY_TOKEN = 'IMediaRepository';
|
||||
|
||||
export const GET_DRIVERS_LEADERBOARD_USE_CASE_TOKEN = 'GetDriversLeaderboardUseCase';
|
||||
export const GET_TOTAL_DRIVERS_USE_CASE_TOKEN = 'GetTotalDriversUseCase';
|
||||
export const COMPLETE_DRIVER_ONBOARDING_USE_CASE_TOKEN = 'CompleteDriverOnboardingUseCase';
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import { Result } from '@core/shared/application/Result';
|
||||
import type { Driver } from '@core/racing/domain/entities/Driver';
|
||||
import type { GetDriverOutputDTO } from '../dtos/GetDriverOutputDTO';
|
||||
import { DriverStatsStore } from '@adapters/racing/services/DriverStatsStore';
|
||||
import type { IDriverStatsRepository } from '@core/racing/domain/repositories/IDriverStatsRepository';
|
||||
|
||||
export class DriverPresenter {
|
||||
private responseModel: GetDriverOutputDTO | null = null;
|
||||
|
||||
constructor(
|
||||
private readonly driverStatsRepository: IDriverStatsRepository
|
||||
) {}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
present(result: Result<Driver | null, any>): void {
|
||||
if (result.isErr()) {
|
||||
@@ -19,9 +23,8 @@ export class DriverPresenter {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get stats from the store
|
||||
const statsStore = DriverStatsStore.getInstance();
|
||||
const stats = statsStore.getDriverStats(driver.id);
|
||||
// Get stats from repository (synchronously for now, could be async)
|
||||
const stats = this.driverStatsRepository.getDriverStatsSync(driver.id);
|
||||
|
||||
this.responseModel = {
|
||||
id: driver.id,
|
||||
|
||||
Reference in New Issue
Block a user