fix issues in adapters
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { ILeagueMembershipRepository } from '@core/racing/domain/repositories/ILeagueMembershipRepository';
|
||||
import { LeagueMembership, JoinRequest } from '@core/racing/domain/entities/LeagueMembership';
|
||||
import { LeagueMembership } from '@core/racing/domain/entities/LeagueMembership';
|
||||
import { JoinRequest } from '@core/racing/domain/entities/JoinRequest';
|
||||
import { Logger } from '@core/shared/application';
|
||||
|
||||
export class InMemoryLeagueMembershipRepository implements ILeagueMembershipRepository {
|
||||
@@ -25,33 +26,33 @@ export class InMemoryLeagueMembershipRepository implements ILeagueMembershipRepo
|
||||
async findActiveByLeagueIdAndDriverId(leagueId: string, driverId: string): Promise<LeagueMembership | null> {
|
||||
this.logger.debug(`[InMemoryLeagueMembershipRepository] Finding active membership for league ${leagueId}, driver ${driverId}.`);
|
||||
const membership = await this.getMembership(leagueId, driverId);
|
||||
return Promise.resolve(membership && membership.status === 'active' ? membership : null);
|
||||
return Promise.resolve(membership && membership.status.toString() === 'active' ? membership : null);
|
||||
}
|
||||
|
||||
async findAllByLeagueId(leagueId: string): Promise<LeagueMembership[]> {
|
||||
this.logger.debug(`[InMemoryLeagueMembershipRepository] Finding all memberships for league ${leagueId}.`);
|
||||
const filteredMemberships = Array.from(this.memberships.values()).filter(mem => mem.leagueId === leagueId);
|
||||
const filteredMemberships = Array.from(this.memberships.values()).filter(mem => mem.leagueId.toString() === leagueId);
|
||||
this.logger.info(`Found ${filteredMemberships.length} memberships for league ${leagueId}.`);
|
||||
return Promise.resolve(filteredMemberships);
|
||||
}
|
||||
|
||||
async findAllByDriverId(driverId: string): Promise<LeagueMembership[]> {
|
||||
this.logger.debug(`[InMemoryLeagueMembershipRepository] Finding all memberships for driver ${driverId}.`);
|
||||
const memberships = Array.from(this.memberships.values()).filter(mem => mem.driverId === driverId);
|
||||
const memberships = Array.from(this.memberships.values()).filter(mem => mem.driverId.toString() === driverId);
|
||||
this.logger.info(`Found ${memberships.length} memberships for driver ${driverId}.`);
|
||||
return Promise.resolve(memberships);
|
||||
}
|
||||
|
||||
async getLeagueMembers(leagueId: string): Promise<LeagueMembership[]> {
|
||||
this.logger.debug(`[InMemoryLeagueMembershipRepository] Getting active members for league ${leagueId}.`);
|
||||
const members = Array.from(this.memberships.values()).filter(mem => mem.leagueId === leagueId && mem.status === 'active');
|
||||
const members = Array.from(this.memberships.values()).filter(mem => mem.leagueId.toString() === leagueId && mem.status.toString() === 'active');
|
||||
this.logger.info(`Found ${members.length} active members for league ${leagueId}.`);
|
||||
return Promise.resolve(members);
|
||||
}
|
||||
|
||||
async getJoinRequests(leagueId: string): Promise<JoinRequest[]> {
|
||||
this.logger.debug(`[InMemoryLeagueMembershipRepository] Getting join requests for league ${leagueId}.`);
|
||||
const requests = Array.from(this.joinRequests.values()).filter(req => req.leagueId === leagueId);
|
||||
const requests = Array.from(this.joinRequests.values()).filter(req => req.leagueId.toString() === leagueId);
|
||||
this.logger.info(`Found ${requests.length} join requests for league ${leagueId}.`);
|
||||
return Promise.resolve(requests);
|
||||
}
|
||||
|
||||
@@ -17,14 +17,14 @@ describe('InMemoryLeagueStandingsRepository', () => {
|
||||
repository = new InMemoryLeagueStandingsRepository(mockLogger);
|
||||
});
|
||||
|
||||
const createTestStanding = (id: string, leagueId: string, driverId: string, position: number, points: number): RawStanding => ({
|
||||
id,
|
||||
leagueId,
|
||||
const createTestStanding = (_id: string, _leagueId: string, driverId: string, position: number, points: number): RawStanding => ({
|
||||
driverId,
|
||||
position,
|
||||
points,
|
||||
wins: 0,
|
||||
racesCompleted: 0,
|
||||
races: 0,
|
||||
poles: 0,
|
||||
podiums: 0,
|
||||
});
|
||||
|
||||
describe('constructor', () => {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Provides an in-memory storage implementation for penalties.
|
||||
*/
|
||||
|
||||
import type { Penalty } from '@core/racing/domain/entities/Penalty';
|
||||
import type { Penalty } from '@core/racing/domain/entities/penalty/Penalty';
|
||||
import type { IPenaltyRepository } from '@core/racing/domain/repositories/IPenaltyRepository';
|
||||
import type { Logger } from '@core/shared/application';
|
||||
|
||||
|
||||
@@ -27,6 +27,15 @@ export class InMemoryRaceRegistrationRepository implements IRaceRegistrationRepo
|
||||
return Promise.resolve(driverIds);
|
||||
}
|
||||
|
||||
async findByRaceId(raceId: string): Promise<RaceRegistration[]> {
|
||||
this.logger.debug(`[InMemoryRaceRegistrationRepository] Finding all registrations for race ${raceId}.`);
|
||||
const registrations = Array.from(this.registrations.values()).filter(
|
||||
reg => reg.raceId.toString() === raceId
|
||||
);
|
||||
this.logger.info(`Found ${registrations.length} registrations for race ${raceId}.`);
|
||||
return Promise.resolve(registrations);
|
||||
}
|
||||
|
||||
async getRegistrationCount(raceId: string): Promise<number> {
|
||||
this.logger.debug(`[InMemoryRaceRegistrationRepository] Getting registration count for race ${raceId}.`);
|
||||
const count = Array.from(this.registrations.values()).filter(reg => reg.raceId.toString() === raceId).length;
|
||||
|
||||
@@ -110,8 +110,15 @@ describe('InMemorySeasonRepository', () => {
|
||||
await repository.create(season);
|
||||
|
||||
const updatedSeason = Season.create({
|
||||
...season,
|
||||
id: season.id,
|
||||
leagueId: season.leagueId.toString(),
|
||||
gameId: season.gameId.toString(),
|
||||
name: 'Updated Season',
|
||||
status: season.status.toString() as 'planned' | 'active' | 'completed',
|
||||
year: 2025,
|
||||
order: 1,
|
||||
startDate: new Date('2025-01-01'),
|
||||
endDate: new Date('2025-12-31'),
|
||||
});
|
||||
await repository.update(updatedSeason);
|
||||
const found = await repository.findById('1');
|
||||
|
||||
@@ -48,7 +48,7 @@ describe('InMemorySponsorshipRequestRepository', () => {
|
||||
|
||||
it('should seed initial requests', () => {
|
||||
const request = createTestRequest('req-1');
|
||||
const repoWithSeed = new InMemorySponsorshipRequestRepository(mockLogger, [request]);
|
||||
new InMemorySponsorshipRequestRepository(mockLogger, [request]);
|
||||
expect(mockLogger.debug).toHaveBeenCalledWith('Seeded sponsorship request: req-1.');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -46,11 +46,9 @@ export class InMemoryStandingRepository implements IStandingRepository {
|
||||
const standings = Array.from(this.standings.values())
|
||||
.filter(standing => standing.leagueId.toString() === leagueId)
|
||||
.sort((a, b) => {
|
||||
// Sort by position (lower is better)
|
||||
if (a.position.toNumber() !== b.position.toNumber()) {
|
||||
return a.position.toNumber() - b.position.toNumber();
|
||||
}
|
||||
// If positions are equal, sort by points (higher is better)
|
||||
return b.points.toNumber() - a.points.toNumber();
|
||||
});
|
||||
this.logger.info(`Found ${standings.length} standings for league id: ${leagueId}.`);
|
||||
@@ -73,7 +71,7 @@ export class InMemoryStandingRepository implements IStandingRepository {
|
||||
}
|
||||
return standing;
|
||||
} catch (error) {
|
||||
this.logger.error(`Error finding standing for driver ${driverId}, league ${leagueId}:`, error);
|
||||
this.logger.error(`Error finding standing for driver ${driverId}, league ${leagueId}:`, error instanceof Error ? error : new Error(String(error)));
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -93,9 +91,9 @@ export class InMemoryStandingRepository implements IStandingRepository {
|
||||
async save(standing: Standing): Promise<Standing> {
|
||||
this.logger.debug(`Saving standing for league: ${standing.leagueId}, driver: ${standing.driverId}`);
|
||||
try {
|
||||
const key = this.getKey(standing.leagueId, standing.driverId);
|
||||
const key = this.getKey(standing.leagueId.toString(), standing.driverId.toString());
|
||||
if (this.standings.has(key)) {
|
||||
this.logger.debug(`Updating existing standing for league: ${standing.leagueId}, driver: ${standing.driverId}.`);
|
||||
this.logger.debug(`Updating existing standing for league: ${standing.leagueId}, driver ${standing.driverId}.`);
|
||||
} else {
|
||||
this.logger.debug(`Creating new standing for league: ${standing.leagueId}, driver: ${standing.driverId}.`);
|
||||
}
|
||||
@@ -103,7 +101,7 @@ export class InMemoryStandingRepository implements IStandingRepository {
|
||||
this.logger.info(`Standing for league ${standing.leagueId}, driver ${standing.driverId} saved successfully.`);
|
||||
return standing;
|
||||
} catch (error) {
|
||||
this.logger.error(`Error saving standing for league ${standing.leagueId}, driver ${standing.driverId}:`, error);
|
||||
this.logger.error(`Error saving standing for league ${standing.leagueId}, driver ${standing.driverId}:`, error instanceof Error ? error : new Error(String(error)));
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -112,7 +110,7 @@ export class InMemoryStandingRepository implements IStandingRepository {
|
||||
this.logger.debug(`Saving ${standings.length} standings.`);
|
||||
try {
|
||||
standings.forEach(standing => {
|
||||
const key = this.getKey(standing.leagueId, standing.driverId);
|
||||
const key = this.getKey(standing.leagueId.toString(), standing.driverId.toString());
|
||||
this.standings.set(key, standing);
|
||||
});
|
||||
this.logger.info(`${standings.length} standings saved successfully.`);
|
||||
@@ -133,7 +131,7 @@ export class InMemoryStandingRepository implements IStandingRepository {
|
||||
this.logger.warn(`Standing for league ${leagueId}, driver ${driverId} not found for deletion.`);
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error(`Error deleting standing for league ${leagueId}, driver ${driverId}:`, error);
|
||||
this.logger.error(`Error deleting standing for league ${leagueId}, driver ${driverId}:`, error instanceof Error ? error : new Error(String(error)));
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -163,7 +161,7 @@ export class InMemoryStandingRepository implements IStandingRepository {
|
||||
this.logger.debug(`Standing for league ${leagueId}, driver ${driverId} exists: ${exists}.`);
|
||||
return exists;
|
||||
} catch (error) {
|
||||
this.logger.error(`Error checking existence of standing for league ${leagueId}, driver ${driverId}:`, error);
|
||||
this.logger.error(`Error checking existence of standing for league ${leagueId}, driver ${driverId}:`, error instanceof Error ? error : new Error(String(error)));
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -176,7 +174,6 @@ export class InMemoryStandingRepository implements IStandingRepository {
|
||||
throw new Error('Cannot recalculate standings: missing required repositories');
|
||||
}
|
||||
|
||||
// Get league to determine points system
|
||||
const league = await this.leagueRepository.findById(leagueId);
|
||||
if (!league) {
|
||||
this.logger.warn(`League with ID ${leagueId} not found during recalculation.`);
|
||||
@@ -184,7 +181,6 @@ export class InMemoryStandingRepository implements IStandingRepository {
|
||||
}
|
||||
this.logger.debug(`League ${leagueId} found for recalculation.`);
|
||||
|
||||
// Get points system
|
||||
const resolvedPointsSystem =
|
||||
league.settings.customPoints ??
|
||||
this.pointsSystems[league.settings.pointsSystem] ??
|
||||
@@ -196,7 +192,6 @@ export class InMemoryStandingRepository implements IStandingRepository {
|
||||
}
|
||||
this.logger.debug(`Resolved points system for league ${leagueId}.`);
|
||||
|
||||
// Get all completed races for the league
|
||||
const races = await this.raceRepository.findCompletedByLeagueId(leagueId);
|
||||
this.logger.debug(`Found ${races.length} completed races for league ${leagueId}.`);
|
||||
|
||||
@@ -205,7 +200,6 @@ export class InMemoryStandingRepository implements IStandingRepository {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Get all results for these races
|
||||
const allResults = await Promise.all(
|
||||
races.map(async race => {
|
||||
this.logger.debug(`Fetching results for race ${race.id}.`);
|
||||
@@ -217,50 +211,44 @@ export class InMemoryStandingRepository implements IStandingRepository {
|
||||
const results = allResults.flat();
|
||||
this.logger.debug(`Collected ${results.length} results from all completed races.`);
|
||||
|
||||
// Calculate standings per driver
|
||||
const standingsMap = new Map<string, Standing>();
|
||||
|
||||
results.forEach(result => {
|
||||
let standing = standingsMap.get(result.driverId);
|
||||
const driverIdStr = result.driverId.toString();
|
||||
let standing = standingsMap.get(driverIdStr);
|
||||
|
||||
if (!standing) {
|
||||
standing = Standing.create({
|
||||
leagueId,
|
||||
driverId: result.driverId,
|
||||
driverId: driverIdStr,
|
||||
});
|
||||
this.logger.debug(`Created new standing for driver ${result.driverId} in league ${leagueId}.`);
|
||||
this.logger.debug(`Created new standing for driver ${driverIdStr} in league ${leagueId}.`);
|
||||
}
|
||||
|
||||
// Add points from this result
|
||||
standing = standing.addRaceResult(result.position, resolvedPointsSystem);
|
||||
standingsMap.set(result.driverId, standing);
|
||||
this.logger.debug(`Driver ${result.driverId} in league ${leagueId} accumulated ${standing.points} points.`);
|
||||
standing = standing.addRaceResult(result.position.toNumber(), resolvedPointsSystem);
|
||||
standingsMap.set(driverIdStr, standing);
|
||||
this.logger.debug(`Driver ${driverIdStr} in league ${leagueId} accumulated ${standing.points} points.`);
|
||||
});
|
||||
this.logger.debug(`Calculated initial standings for ${standingsMap.size} drivers.`);
|
||||
|
||||
// Sort by points and assign positions
|
||||
const sortedStandings = Array.from(standingsMap.values())
|
||||
.sort((a, b) => {
|
||||
if (b.points !== a.points) {
|
||||
return b.points - a.points;
|
||||
if (b.points.toNumber() !== a.points.toNumber()) {
|
||||
return b.points.toNumber() - a.points.toNumber();
|
||||
}
|
||||
// Tie-breaker: most wins
|
||||
if (b.wins !== a.wins) {
|
||||
return b.wins - a.wins;
|
||||
}
|
||||
// Tie-breaker: most races completed
|
||||
return b.racesCompleted - a.racesCompleted;
|
||||
});
|
||||
this.logger.debug(`Sorted standings for ${sortedStandings.length} drivers.`);
|
||||
|
||||
// Assign positions
|
||||
const updatedStandings = sortedStandings.map((standing, index) => {
|
||||
const newStanding = standing.updatePosition(index + 1);
|
||||
this.logger.debug(`Assigned position ${newStanding.position} to driver ${newStanding.driverId}.`);
|
||||
return newStanding;
|
||||
});
|
||||
|
||||
// Save all standings
|
||||
await this.saveMany(updatedStandings);
|
||||
this.logger.info(`Successfully recalculated and saved standings for league ${leagueId}.`);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user