Skip to content

Commit

Permalink
wip: competition result type
Browse files Browse the repository at this point in the history
  • Loading branch information
nimarion committed Nov 2, 2024
1 parent 9cdbe4b commit 8e16363
Show file tree
Hide file tree
Showing 14 changed files with 180 additions and 64 deletions.
5 changes: 4 additions & 1 deletion src/athletes/athlete.zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ const Performance = z.object({
venue: z.string(),
notLegal: z.boolean(),
resultScore: z.number(),
wind: z.coerce.number().nullable().catch(() => null),
wind: z.coerce
.number()
.nullable()
.catch(() => null),
records: z.array(z.string()),
eventId: z.coerce.number(),
competitionId: z.coerce.number(),
Expand Down
20 changes: 12 additions & 8 deletions src/athletes/athletes.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ export class AthletesService {
): Performance {
const location = parseVenue(result.venue);
const disciplineCode = mapDisciplineToCode(result.discipline);
const technical = isTechnical({
disciplineCode,
performance: result.mark,
});
return {
date: result.date,
discipline: result.discipline,
Expand All @@ -105,11 +109,9 @@ export class AthletesService {
mark: result.mark,
performanceValue: performanceToFloat({
performance: result.mark,
technical: isTechnical({
disciplineCode,
performance: result.mark,
}),
technical,
}),
isTechnical: technical,
location,
legal: !result.notLegal,
resultScore: result.resultScore,
Expand Down Expand Up @@ -147,6 +149,10 @@ export class AthletesService {
results: honour.results.map((result) => {
const disciplineCode = mapDisciplineToCode(result.discipline);
const location = parseVenue(result.venue);
const technical = isTechnical({
disciplineCode,
performance: result.mark,
});
return {
date: result.date,
discipline: result.discipline,
Expand All @@ -155,11 +161,9 @@ export class AthletesService {
mark: result.mark,
performanceValue: performanceToFloat({
performance: result.mark,
technical: isTechnical({
disciplineCode,
performance: result.mark,
}),
technical,
}),
isTechnical: technical,
location,
competition: result.competition,
place: result.place,
Expand Down
10 changes: 6 additions & 4 deletions src/athletes/results/result.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ export class ResultsService {
const disciplineCode = mapDisciplineToCode(discipline);
event.results.forEach((result) => {
const location = parseVenue(result.venue);
const technical = isTechnical({
disciplineCode,
performance: result.mark,
});
results.push({
category: result.category,
competition: result.competition,
Expand All @@ -58,11 +62,9 @@ export class ResultsService {
mark: result.mark,
performanceValue: performanceToFloat({
performance: result.mark,
technical: isTechnical({
disciplineCode,
performance: result.mark,
}),
technical,
}),
isTechnical: technical,
legal: !result.notLegal,
location,
race: result.race,
Expand Down
5 changes: 4 additions & 1 deletion src/athletes/results/result.zod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ export const ResultsByEvent = z.object({
country: z.string(),
notLegal: z.boolean(),
venue: z.string(),
wind: z.coerce.number().nullable().catch(() => null),
wind: z.coerce
.number()
.nullable()
.catch(() => null),
resultScore: z.number(),
race: z.string(),
place: PlaceSchema,
Expand Down
72 changes: 61 additions & 11 deletions src/competitions/competition.dto.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { ApiProperty } from '@nestjs/swagger';
import { Athlete, BasePerformance, Sex } from 'src/athletes/athlete.dto';
import { Discipline } from 'src/disciplines/discipline.dto';
import { Location } from 'src/location.dto';

export class ContactPerson {
Expand Down Expand Up @@ -54,22 +56,70 @@ export class Competition {
hasCompetitionInformation!: boolean;
}

export class CompetitionResults {
@ApiProperty({ nullable: true })
name!: string | null;
export class CompetitionResultAthlete {
@ApiProperty({ nullable: true, type: Number })
id!: number | null;
@ApiProperty()
rankingCategory!: string;
firstname!: string;
@ApiProperty()
events!: CompetitionResultEvent[];
lastname!: string;
@ApiProperty({ nullable: true, type: Date })
birthdate!: Date | null;
}

export class CompetitionResult {
@ApiProperty({ isArray: true, minimum: 1, type: CompetitionResultAthlete })
athletes!: CompetitionResultAthlete[];
@ApiProperty()
country!: string;
@ApiProperty()
place!: number;
@ApiProperty()
mark!: string;
@ApiProperty({
description:
'Performance in milliseconds for track events and centimeters for field events',
nullable: true,
type: Number,
})
performanceValue!: number | null;
@ApiProperty({ nullable: true, type: Number })
wind!: number | null;
}

export class CompetitionResultEvent {
export class CompetitionResultsRace {
@ApiProperty({ nullable: true, type: Date })
date!: Date | null;
@ApiProperty({ nullable: true, type: Number })
day!: number | null;
@ApiProperty()
race!: string;
@ApiProperty()
raceId!: number;
@ApiProperty()
raceNumber!: number;
@ApiProperty({ isArray: true, type: CompetitionResult })
results!: CompetitionResult[];
}

export class CompetitionResultEvent extends Discipline {
@ApiProperty()
event?: string;
eventId?: number;
sex?: string;
@ApiProperty({
enum: ['M', 'W', 'X'],
})
sex?: Sex;
@ApiProperty()
isRelay?: boolean;
perResultWind?: boolean;
withWind?: boolean;
races?: any[];
@ApiProperty({ isArray: true, type: CompetitionResultsRace })
races?: CompetitionResultsRace[];
}

export class CompetitionResults {
@ApiProperty({ nullable: true, type: String })
name!: string | null;
@ApiProperty()
rankingCategory!: string;
@ApiProperty({ isArray: true, type: CompetitionResultEvent })
events!: CompetitionResultEvent[];
}
4 changes: 4 additions & 0 deletions src/competitions/competitions.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ export class CompetitionsController {
required: false,
type: Number,
})
@ApiOkResponse({
type: CompetitionResults,
isArray: true,
})
async findResults(
@Param('id') id: number,
@Query('eventId') eventId?: number,
Expand Down
78 changes: 60 additions & 18 deletions src/competitions/competitions.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,27 @@ import {
COMPETITION_ORGANISER,
COMPETITON_RESULTS,
} from './competition.query';
import { z } from 'zod';
import { date, z } from 'zod';
import {
Competition,
CompetitionOrganiserInfo,
CompetitionResult,
CompetitionResults,
} from './competition.dto';
import {
CompetitionOrganiserInfoSchema,
CompetitionSchema,
} from './competition.zod';
import { parsePhoneNumber, parseVenue } from 'src/utils';
import mapDisciplineToCode from 'src/discipline.utils';
import {
formatSex,
isShortTrack,
parsePhoneNumber,
parseVenue,
} from 'src/utils';
import mapDisciplineToCode, {
cleanupDiscipline,
isTechnical,
} from 'src/discipline.utils';
import {
DateSchema,
FullnameSchema,
Expand All @@ -26,6 +35,7 @@ import {
UrlSlugIdSchema,
} from 'src/zod.schema';
import { Sex } from 'src/athletes/athlete.dto';
import { performanceToFloat } from 'src/performance-conversion';

@Injectable()
export class CompetitionsService {
Expand Down Expand Up @@ -152,15 +162,15 @@ export class CompetitionsService {
eventTitle: z.string().nullable(),
events: z.array(
z.object({
event: z.string(),
event: z.string().transform(cleanupDiscipline),
eventId: z.coerce.number(),
gender: z.string(),
isRelay: z.boolean(),
perResultWind: z.boolean(),
withWind: z.boolean(),
races: z.array(
z.object({
date: z.string().nullable(),
date: z.nullable(DateSchema),
day: z.number().nullable(),
race: z.string(),
raceId: z.number(),
Expand All @@ -177,7 +187,7 @@ export class CompetitionsService {
)
.nullable(),
name: FullnameSchema,
urlSlug: UrlSlugIdSchema,
urlSlug: z.nullable(UrlSlugIdSchema),
birthDate: z.nullable(DateSchema),
}),
mark: MarkSchema,
Expand All @@ -189,13 +199,19 @@ export class CompetitionsService {
.split(',')
.map((record) => record.trim());
}),
wind: z.coerce.number().nullable().catch(() => null),
wind: z.coerce
.number()
.nullable()
.catch(() => null),
//remark: z.any().nullable(),
details: z.any().nullable(),
}),
),
startlist: z.any().nullable(),
wind: z.coerce.number().nullable().catch(() => null),
wind: z.coerce
.number()
.nullable()
.catch(() => null),
}),
),
}),
Expand All @@ -222,42 +238,68 @@ export class CompetitionsService {
})
.parse(data);
return response.getCalendarCompetitionResults.eventTitles.map((event) => {
return {
const data: CompetitionResults = {
name: event.eventTitle,
rankingCategory: event.rankingCategory,
events: event.events.map((event) => {
const technical = isTechnical({
disciplineCode: mapDisciplineToCode(event.event),
performance: event.races[0].results[0].mark,
});
return {
...event,
eventId: event.eventId,
isRelay: event.isRelay,
sex: formatSex(event.gender),
disciplineCode: mapDisciplineToCode(event.event),
discipline: event.event,
shortTrack: isShortTrack(event.event),
isTechnical: technical,
races: event.races.map((race) => {
return {
...race,
results: race.results.map((result) => {
const results: CompetitionResult[] = race.results.map(
(result) => {
const athletes = result.competitor.teamMembers
? result.competitor.teamMembers.map((teamMember) => {
return {
id: teamMember.id,
...teamMember.name,
firstname: teamMember.name!!.firstname,
lastname: teamMember.name!!.lastname,
birthdate: null,
};
})
: [
{
id: result.competitor.urlSlug,
...result.competitor.name,
birthDate: result.competitor.birthDate,
firstname: result.competitor.name!!.firstname,
lastname: result.competitor.name!!.lastname,
birthdate: result.competitor.birthDate,
},
];
return {
...result,
place: result.place,
mark: result.mark,
wind: event.perResultWind ? result.wind : race.wind,
performanceValue: performanceToFloat({
performance: result.mark,
technical,
}),
country: result.nationality,
athletes,
};
}),
},
);
return {
date: race.date,
day: race.day,
race: race.race,
raceId: race.raceId,
raceNumber: race.raceNumber,
results,
};
}),
};
}),
};
return data;
});
}
}
12 changes: 8 additions & 4 deletions src/discipline.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ import * as disciplines from './disciplines.json';

export default function mapDisciplineToCode(discipline: string): string {
// Prefix is present in getCalendarEvents query
discipline = discipline
.replace("Women's ", '')
.replace("Men's ", '')
.replace('Mixed ', '');
discipline = cleanupDiscipline(discipline);
// Not present in getMetaData > disciplineCodes
if (discipline == '3x800 Metres Relay') {
return '3X8';
Expand All @@ -21,6 +18,13 @@ export default function mapDisciplineToCode(discipline: string): string {
return discipline;
}

export function cleanupDiscipline(discipline: string): string {
return discipline
.replace("Women's ", '')
.replace("Men's ", '')
.replace('Mixed ', '');
}

export function isTechnical({
disciplineCode,
performance,
Expand Down
2 changes: 2 additions & 0 deletions src/disciplines/discipline.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ export class Discipline {
disciplineCode!: string;
@ApiProperty()
shortTrack!: boolean;
@ApiProperty()
isTechnical!: boolean;
}
Loading

0 comments on commit 8e16363

Please sign in to comment.