fix issues in core
This commit is contained in:
@@ -3,11 +3,14 @@
|
||||
* Represents a monetary amount with currency and platform fee calculation
|
||||
*/
|
||||
|
||||
import { RacingDomainValidationError } from '../errors/RacingDomainError';
|
||||
import type { IValueObject } from '@core/shared/domain';
|
||||
import { RacingDomainValidationError } from '../errors/RacingDomainError';
|
||||
|
||||
export type Currency = 'USD' | 'EUR' | 'GBP';
|
||||
|
||||
export const isCurrency = (value: string): value is Currency =>
|
||||
value === 'USD' || value === 'EUR' || value === 'GBP';
|
||||
|
||||
export interface MoneyProps {
|
||||
amount: number;
|
||||
currency: Currency;
|
||||
@@ -34,6 +37,7 @@ export class Money implements IValueObject<MoneyProps> {
|
||||
return new Money(amount, currency);
|
||||
}
|
||||
|
||||
// TODO i dont think platform fee must be coupled
|
||||
/**
|
||||
* Calculate platform fee (10%)
|
||||
*/
|
||||
|
||||
@@ -90,7 +90,51 @@ export class RaceIncidents implements IValueObject<IncidentRecord[]> {
|
||||
return this.incidents.length === 0;
|
||||
}
|
||||
|
||||
// Removed getSeverityScore, getSummary, and getIncidentTypeLabel to eliminate static data in core
|
||||
/**
|
||||
* Backwards-compatible helper for legacy "incident count" fields.
|
||||
* Creates `count` placeholder incidents of type `other`.
|
||||
*/
|
||||
static fromLegacyIncidentsCount(count: number): RaceIncidents {
|
||||
if (!Number.isFinite(count) || count <= 0) {
|
||||
return new RaceIncidents();
|
||||
}
|
||||
|
||||
const incidents: IncidentRecord[] = Array.from({ length: Math.floor(count) }, (_, index) => ({
|
||||
type: 'other',
|
||||
lap: index + 1,
|
||||
penaltyPoints: 0,
|
||||
}));
|
||||
|
||||
return new RaceIncidents(incidents);
|
||||
}
|
||||
|
||||
/**
|
||||
* A coarse severity score for incidents.
|
||||
* Kept intentionally data-light: derived only from `penaltyPoints`.
|
||||
*/
|
||||
getSeverityScore(): number {
|
||||
return this.getTotalPenaltyPoints();
|
||||
}
|
||||
|
||||
/**
|
||||
* Human-readable summary without hardcoded incident labels.
|
||||
*/
|
||||
getSummary(): string {
|
||||
const total = this.getTotalCount();
|
||||
if (total === 0) return 'Clean race';
|
||||
|
||||
const countsByType = new Map<IncidentType, number>();
|
||||
for (const incident of this.incidents) {
|
||||
countsByType.set(incident.type, (countsByType.get(incident.type) ?? 0) + 1);
|
||||
}
|
||||
|
||||
const typeSummary = Array.from(countsByType.entries())
|
||||
.sort(([a], [b]) => a.localeCompare(b))
|
||||
.map(([type, n]) => `${type}:${n}`)
|
||||
.join(', ');
|
||||
|
||||
return typeSummary.length > 0 ? `${total} incidents (${typeSummary})` : `${total} incidents`;
|
||||
}
|
||||
|
||||
equals(other: IValueObject<IncidentRecord[]>): boolean {
|
||||
const otherIncidents = other.props;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { SessionType } from './SessionType';
|
||||
import { SessionType, type SessionTypeValue } from './SessionType';
|
||||
|
||||
describe('SessionType', () => {
|
||||
it('should create session type', () => {
|
||||
@@ -9,8 +9,8 @@ describe('SessionType', () => {
|
||||
});
|
||||
|
||||
it('should throw for invalid session type', () => {
|
||||
expect(() => new SessionType('invalid' as any)).toThrow();
|
||||
expect(() => new SessionType('' as any)).toThrow();
|
||||
expect(() => new SessionType('invalid' as unknown as SessionTypeValue)).toThrow();
|
||||
expect(() => new SessionType('' as unknown as SessionTypeValue)).toThrow();
|
||||
});
|
||||
|
||||
it('should have static factory methods', () => {
|
||||
|
||||
Reference in New Issue
Block a user