team rating

This commit is contained in:
2025-12-30 12:25:45 +01:00
parent ccaa39c39c
commit 83371ea839
93 changed files with 10324 additions and 490 deletions

View File

@@ -0,0 +1,35 @@
/**
* Application Port: IDriverStatsRepository
*
* Repository interface for storing and retrieving computed driver statistics.
* This is used for caching computed stats and serving frontend data.
*/
import type { DriverStats } from '../../application/use-cases/IDriverStatsUseCase';
export interface IDriverStatsRepository {
/**
* Get stats for a specific driver
*/
getDriverStats(driverId: string): Promise<DriverStats | null>;
/**
* Get stats for a specific driver (synchronous)
*/
getDriverStatsSync(driverId: string): DriverStats | null;
/**
* Save stats for a specific driver
*/
saveDriverStats(driverId: string, stats: DriverStats): Promise<void>;
/**
* Get all driver stats
*/
getAllStats(): Promise<Map<string, DriverStats>>;
/**
* Clear all stats
*/
clear(): Promise<void>;
}

View File

@@ -0,0 +1,38 @@
/**
* Application Port: IMediaRepository
*
* Repository interface for static media assets (logos, images, icons).
* Handles frontend assets like team logos, driver avatars, etc.
*/
export interface IMediaRepository {
/**
* Get driver avatar URL
*/
getDriverAvatar(driverId: string): Promise<string | null>;
/**
* Get team logo URL
*/
getTeamLogo(teamId: string): Promise<string | null>;
/**
* Get track image URL
*/
getTrackImage(trackId: string): Promise<string | null>;
/**
* Get category icon URL
*/
getCategoryIcon(categoryId: string): Promise<string | null>;
/**
* Get sponsor logo URL
*/
getSponsorLogo(sponsorId: string): Promise<string | null>;
/**
* Clear all media data (for reseeding)
*/
clear(): Promise<void>;
}

View File

@@ -0,0 +1,73 @@
/**
* Repository Interface: ITeamRatingEventRepository
*
* Port for persisting and retrieving team rating events (ledger).
* Events are immutable and ordered by occurredAt for deterministic snapshot computation.
*/
import type { TeamRatingEvent } from '../entities/TeamRatingEvent';
import type { TeamRatingEventId } from '../value-objects/TeamRatingEventId';
export interface FindByTeamIdOptions {
/** Only return events after this ID (for pagination/streaming) */
afterId?: TeamRatingEventId;
/** Maximum number of events to return */
limit?: number;
}
export interface TeamRatingEventFilter {
/** Filter by dimension keys */
dimensions?: string[];
/** Filter by source types */
sourceTypes?: ('race' | 'penalty' | 'vote' | 'adminAction' | 'manualAdjustment')[];
/** Filter by date range (inclusive) */
from?: Date;
to?: Date;
/** Filter by reason codes */
reasonCodes?: string[];
/** Filter by visibility */
visibility?: 'public' | 'private';
}
export interface PaginatedQueryOptions {
limit?: number;
offset?: number;
filter?: TeamRatingEventFilter;
}
export interface PaginatedResult<T> {
items: T[];
total: number;
limit: number;
offset: number;
hasMore: boolean;
nextOffset?: number;
}
export interface ITeamRatingEventRepository {
/**
* Save a rating event to the ledger
*/
save(event: TeamRatingEvent): Promise<TeamRatingEvent>;
/**
* Find all rating events for a team, ordered by occurredAt (ascending)
* Options allow for pagination and streaming
*/
findByTeamId(teamId: string, options?: FindByTeamIdOptions): Promise<TeamRatingEvent[]>;
/**
* Find multiple events by their IDs
*/
findByIds(ids: TeamRatingEventId[]): Promise<TeamRatingEvent[]>;
/**
* Get all events for a team (for snapshot recomputation)
*/
getAllByTeamId(teamId: string): Promise<TeamRatingEvent[]>;
/**
* Find events with pagination and filtering
*/
findEventsPaginated(teamId: string, options?: PaginatedQueryOptions): Promise<PaginatedResult<TeamRatingEvent>>;
}

View File

@@ -0,0 +1,20 @@
/**
* Repository Interface: ITeamRatingRepository
*
* Port for persisting and retrieving TeamRating snapshots.
* Snapshots are derived from rating events for fast reads.
*/
import type { TeamRatingSnapshot } from '../services/TeamRatingSnapshotCalculator';
export interface ITeamRatingRepository {
/**
* Find rating snapshot by team ID
*/
findByTeamId(teamId: string): Promise<TeamRatingSnapshot | null>;
/**
* Save or update a team rating snapshot
*/
save(teamRating: TeamRatingSnapshot): Promise<TeamRatingSnapshot>;
}

View File

@@ -0,0 +1,44 @@
/**
* Application Port: ITeamStatsRepository
*
* Repository interface for storing and retrieving computed team statistics.
* This is used for caching computed stats and serving frontend data.
*/
export interface TeamStats {
logoUrl: string;
performanceLevel: 'beginner' | 'intermediate' | 'advanced' | 'pro';
specialization: 'endurance' | 'sprint' | 'mixed';
region: string;
languages: string[];
totalWins: number;
totalRaces: number;
rating: number;
}
export interface ITeamStatsRepository {
/**
* Get stats for a specific team
*/
getTeamStats(teamId: string): Promise<TeamStats | null>;
/**
* Get stats for a specific team (synchronous)
*/
getTeamStatsSync(teamId: string): TeamStats | null;
/**
* Save stats for a specific team
*/
saveTeamStats(teamId: string, stats: TeamStats): Promise<void>;
/**
* Get all team stats
*/
getAllStats(): Promise<Map<string, TeamStats>>;
/**
* Clear all stats
*/
clear(): Promise<void>;
}