auth
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
import { Column, Entity, PrimaryColumn } from 'typeorm';
|
||||
|
||||
@Entity({ name: 'driver_stats' })
|
||||
export class DriverStatsOrmEntity {
|
||||
@PrimaryColumn({ type: 'uuid' })
|
||||
driverId!: string;
|
||||
|
||||
@Column({ type: 'integer' })
|
||||
rating!: number;
|
||||
|
||||
@Column({ type: 'integer' })
|
||||
safetyRating!: number;
|
||||
|
||||
@Column({ type: 'numeric', precision: 3, scale: 1 })
|
||||
sportsmanshipRating!: number;
|
||||
|
||||
@Column({ type: 'integer' })
|
||||
totalRaces!: number;
|
||||
|
||||
@Column({ type: 'integer' })
|
||||
wins!: number;
|
||||
|
||||
@Column({ type: 'integer' })
|
||||
podiums!: number;
|
||||
|
||||
@Column({ type: 'integer' })
|
||||
dnfs!: number;
|
||||
|
||||
@Column({ type: 'numeric', precision: 5, scale: 2 })
|
||||
avgFinish!: number;
|
||||
|
||||
@Column({ type: 'integer' })
|
||||
bestFinish!: number;
|
||||
|
||||
@Column({ type: 'integer' })
|
||||
worstFinish!: number;
|
||||
|
||||
@Column({ type: 'integer' })
|
||||
consistency!: number;
|
||||
|
||||
@Column({ type: 'text' })
|
||||
experienceLevel!: string;
|
||||
|
||||
@Column({ type: 'integer', nullable: true })
|
||||
overallRank!: number | null;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import type { DriverStats } from '@core/racing/application/use-cases/IDriverStatsUseCase';
|
||||
|
||||
import { DriverStatsOrmEntity } from '../entities/DriverStatsOrmEntity';
|
||||
import {
|
||||
assertNonEmptyString,
|
||||
assertInteger,
|
||||
assertNumber
|
||||
} from '../schema/TypeOrmSchemaGuards';
|
||||
|
||||
export class DriverStatsOrmMapper {
|
||||
toOrmEntity(driverId: string, domain: DriverStats): DriverStatsOrmEntity {
|
||||
const entity = new DriverStatsOrmEntity();
|
||||
entity.driverId = driverId;
|
||||
entity.rating = domain.rating;
|
||||
entity.safetyRating = domain.safetyRating;
|
||||
entity.sportsmanshipRating = domain.sportsmanshipRating;
|
||||
entity.totalRaces = domain.totalRaces;
|
||||
entity.wins = domain.wins;
|
||||
entity.podiums = domain.podiums;
|
||||
entity.dnfs = domain.dnfs;
|
||||
entity.avgFinish = domain.avgFinish;
|
||||
entity.bestFinish = domain.bestFinish;
|
||||
entity.worstFinish = domain.worstFinish;
|
||||
entity.consistency = domain.consistency;
|
||||
entity.experienceLevel = domain.experienceLevel;
|
||||
entity.overallRank = domain.overallRank ?? null;
|
||||
return entity;
|
||||
}
|
||||
|
||||
toDomain(entity: DriverStatsOrmEntity): DriverStats {
|
||||
const entityName = 'DriverStats';
|
||||
|
||||
assertNonEmptyString(entityName, 'driverId', entity.driverId);
|
||||
assertInteger(entityName, 'rating', entity.rating);
|
||||
assertInteger(entityName, 'safetyRating', entity.safetyRating);
|
||||
assertInteger(entityName, 'sportsmanshipRating', entity.sportsmanshipRating);
|
||||
assertInteger(entityName, 'totalRaces', entity.totalRaces);
|
||||
assertInteger(entityName, 'wins', entity.wins);
|
||||
assertInteger(entityName, 'podiums', entity.podiums);
|
||||
assertInteger(entityName, 'dnfs', entity.dnfs);
|
||||
assertNumber(entityName, 'avgFinish', entity.avgFinish);
|
||||
assertInteger(entityName, 'bestFinish', entity.bestFinish);
|
||||
assertInteger(entityName, 'worstFinish', entity.worstFinish);
|
||||
assertInteger(entityName, 'consistency', entity.consistency);
|
||||
assertNonEmptyString(entityName, 'experienceLevel', entity.experienceLevel);
|
||||
|
||||
const result: DriverStats = {
|
||||
rating: entity.rating,
|
||||
safetyRating: entity.safetyRating,
|
||||
sportsmanshipRating: entity.sportsmanshipRating,
|
||||
totalRaces: entity.totalRaces,
|
||||
wins: entity.wins,
|
||||
podiums: entity.podiums,
|
||||
dnfs: entity.dnfs,
|
||||
avgFinish: entity.avgFinish,
|
||||
bestFinish: entity.bestFinish,
|
||||
worstFinish: entity.worstFinish,
|
||||
consistency: entity.consistency,
|
||||
experienceLevel: entity.experienceLevel,
|
||||
overallRank: entity.overallRank ?? null,
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import type { IDriverStatsRepository } from '@core/racing/domain/repositories/IDriverStatsRepository';
|
||||
import type { DriverStats } from '@core/racing/application/use-cases/IDriverStatsUseCase';
|
||||
import type { Repository } from 'typeorm';
|
||||
|
||||
import { DriverStatsOrmEntity } from '../entities/DriverStatsOrmEntity';
|
||||
import { DriverStatsOrmMapper } from '../mappers/DriverStatsOrmMapper';
|
||||
|
||||
export class TypeOrmDriverStatsRepository implements IDriverStatsRepository {
|
||||
constructor(
|
||||
private readonly repo: Repository<DriverStatsOrmEntity>,
|
||||
private readonly mapper: DriverStatsOrmMapper,
|
||||
) {}
|
||||
|
||||
async getDriverStats(driverId: string): Promise<DriverStats | null> {
|
||||
const entity = await this.repo.findOne({ where: { driverId } });
|
||||
return entity ? this.mapper.toDomain(entity) : null;
|
||||
}
|
||||
|
||||
getDriverStatsSync(_driverId: string): DriverStats | null {
|
||||
// TypeORM repositories don't support synchronous operations
|
||||
// This method is provided for interface compatibility but should not be used
|
||||
// with TypeORM implementations. Return null to indicate it's not supported.
|
||||
return null;
|
||||
}
|
||||
|
||||
async saveDriverStats(driverId: string, stats: DriverStats): Promise<void> {
|
||||
const entity = this.mapper.toOrmEntity(driverId, stats);
|
||||
await this.repo.save(entity);
|
||||
}
|
||||
|
||||
async getAllStats(): Promise<Map<string, DriverStats>> {
|
||||
const entities = await this.repo.find();
|
||||
const statsMap = new Map<string, DriverStats>();
|
||||
|
||||
for (const entity of entities) {
|
||||
statsMap.set(entity.driverId, this.mapper.toDomain(entity));
|
||||
}
|
||||
|
||||
return statsMap;
|
||||
}
|
||||
|
||||
async clear(): Promise<void> {
|
||||
await this.repo.clear();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user