diff --git a/src/athletes/athlete.zod.ts b/src/athletes/athlete.zod.ts index 8b63a96..8cb9bdb 100644 --- a/src/athletes/athlete.zod.ts +++ b/src/athletes/athlete.zod.ts @@ -17,7 +17,7 @@ export const BasicData = z.object({ familyName: LastnameSchema, birthDate: z.nullable(DateSchema), countryCode: CountryCodeSchema, - sexNameUrlSlug: z.nullable(z.enum(['women', 'men'])), + sexNameUrlSlug: z.nullable(GenderSchema), }); const Performance = z.object({ diff --git a/src/athletes/athletes.service.ts b/src/athletes/athletes.service.ts index 984c39b..bfd2b3f 100644 --- a/src/athletes/athletes.service.ts +++ b/src/athletes/athletes.service.ts @@ -86,9 +86,7 @@ export class AthletesService { : 'M' : null; const sex = basicData.sexNameUrlSlug - ? basicData.sexNameUrlSlug === 'women' - ? 'W' - : 'M' + ? basicData.sexNameUrlSlug : worldRankingSex; function resultToPerformance( diff --git a/src/competitions/competition.dto.ts b/src/competitions/competition.dto.ts index a275107..3464cfc 100644 --- a/src/competitions/competition.dto.ts +++ b/src/competitions/competition.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { BaseAthlete, BasePerformance, Sex } from 'src/athletes/athlete.dto'; -import { Discipline } from 'src/disciplines/discipline.dto'; +import { BaseDiscipline, Discipline } from 'src/disciplines/discipline.dto'; import { Location } from 'src/location.dto'; export class ContactPerson { @@ -102,7 +102,7 @@ export class CompetitionResultOptionDay { day!: number } -export class CompetitionResultOptionEvent extends Discipline{ +export class CompetitionResultOptionEvent extends BaseDiscipline{ @ApiProperty() id!: number; @ApiProperty({ diff --git a/src/competitions/competition.zod.ts b/src/competitions/competition.zod.ts index 905d611..9b66eca 100644 --- a/src/competitions/competition.zod.ts +++ b/src/competitions/competition.zod.ts @@ -1,4 +1,4 @@ -import { DateSchema, GenderSchema, VenueSchema } from 'src/zod.schema'; +import { DateSchema, DisciplineNameSchema, FullnameSchema, GenderSchema, MarkSchema, PlaceSchema, UrlSlugIdSchema, VenueSchema } from 'src/zod.schema'; import { z } from 'zod'; export const CompetitionOrganiserInfoSchema = z.object({ @@ -47,3 +47,90 @@ export const CompetitionSchema = z.object({ competitionGroup: z.string().nullable(), competitionSubgroup: z.string().nullable(), }); + +export const CompetitionResultsSchema = z.object({ + competition: z.object({ + venue: VenueSchema, + name: z.string(), + }), + parameters: z.object({ + day: z.number().nullable(), + }), + eventTitles: z.array( + z.object({ + rankingCategory: z.string(), + eventTitle: z.string().nullable(), + events: z.array( + z.object({ + event: DisciplineNameSchema, + eventId: z.coerce.number(), + gender: GenderSchema, + perResultWind: z.boolean(), + withWind: z.boolean(), + races: z.array( + z.object({ + date: z.nullable(DateSchema), + day: z.number().nullable(), + race: z.string(), + raceId: z.number(), + raceNumber: z.number(), + results: z.array( + z.object({ + competitor: z.object({ + teamMembers: z + .array( + z.object({ + id: z.number(), + name: FullnameSchema, + urlSlug: UrlSlugIdSchema, + }), + ) + .nullable(), + name: FullnameSchema, + urlSlug: z.nullable(UrlSlugIdSchema), + birthDate: z.nullable(DateSchema), + }), + mark: MarkSchema, + nationality: z.string(), + place: PlaceSchema, + records: z.string().transform((val) => { + if (val === '') return []; + return val + .split(',') + .map((record) => record.trim()); + }), + wind: z.coerce + .number() + .nullable() + .catch(() => null), + }), + ), + wind: z.coerce + .number() + .nullable() + .catch(() => null), + }), + ), + }), + ), + }), + ), + options: z.object({ + days: z.array( + z.object({ + date: DateSchema, + day: z.number(), + }), + ), + events: z.array( + z.object({ + gender: GenderSchema, + id: z.number(), + name: DisciplineNameSchema, + combined: z.boolean().nullable().transform((val) => { + return val === null ? false : val; + }), + }), + ), + }), +}); diff --git a/src/competitions/competitions.service.ts b/src/competitions/competitions.service.ts index 27cd1db..cac70bf 100644 --- a/src/competitions/competitions.service.ts +++ b/src/competitions/competitions.service.ts @@ -16,24 +16,12 @@ import { } from './competition.dto'; import { CompetitionOrganiserInfoSchema, + CompetitionResultsSchema, CompetitionSchema, } from './competition.zod'; -import { - parsePhoneNumber, -} from 'src/utils'; import mapDisciplineToCode, { isTechnical, } from 'src/discipline.utils'; -import { - DateSchema, - DisciplineNameSchema, - FullnameSchema, - GenderSchema, - MarkSchema, - PlaceSchema, - UrlSlugIdSchema, - VenueSchema, -} from 'src/zod.schema'; import { Sex } from 'src/athletes/athlete.dto'; import { performanceToFloat } from 'src/performance-conversion'; @@ -76,7 +64,7 @@ export class CompetitionsService { return { email: contact.email, name: contact.name, - phone: parsePhoneNumber(contact.phoneNumber), + phone: contact.phoneNumber, role: contact.title, }; }, @@ -158,92 +146,7 @@ export class CompetitionsService { }); const response = z .object({ - getCalendarCompetitionResults: z.object({ - competition: z.object({ - venue: VenueSchema, - name: z.string(), - }), - parameters: z.object({ - day: z.number().nullable(), - }), - eventTitles: z.array( - z.object({ - rankingCategory: z.string(), - eventTitle: z.string().nullable(), - events: z.array( - z.object({ - event: DisciplineNameSchema, - eventId: z.coerce.number(), - gender: GenderSchema, - perResultWind: z.boolean(), - withWind: z.boolean(), - races: z.array( - z.object({ - date: z.nullable(DateSchema), - day: z.number().nullable(), - race: z.string(), - raceId: z.number(), - raceNumber: z.number(), - results: z.array( - z.object({ - competitor: z.object({ - teamMembers: z - .array( - z.object({ - id: z.number(), - name: FullnameSchema, - urlSlug: UrlSlugIdSchema, - }), - ) - .nullable(), - name: FullnameSchema, - urlSlug: z.nullable(UrlSlugIdSchema), - birthDate: z.nullable(DateSchema), - }), - mark: MarkSchema, - nationality: z.string(), - place: PlaceSchema, - records: z.string().transform((val) => { - if (val === '') return []; - return val - .split(',') - .map((record) => record.trim()); - }), - wind: z.coerce - .number() - .nullable() - .catch(() => null), - }), - ), - wind: z.coerce - .number() - .nullable() - .catch(() => null), - }), - ), - }), - ), - }), - ), - options: z.object({ - days: z.array( - z.object({ - date: DateSchema, - day: z.number(), - }), - ), - events: z.array( - z.object({ - gender: GenderSchema, - id: z.number(), - name: DisciplineNameSchema, - combined: z.boolean().nullable().transform((val) => { - return val === null ? false : val; - }), - }), - ), - }), - }), + getCalendarCompetitionResults:CompetitionResultsSchema, }) .parse(data); diff --git a/src/disciplines/discipline.dto.ts b/src/disciplines/discipline.dto.ts index 548196a..e732bb6 100644 --- a/src/disciplines/discipline.dto.ts +++ b/src/disciplines/discipline.dto.ts @@ -1,10 +1,13 @@ import { ApiProperty } from '@nestjs/swagger'; -export class Discipline { +export class BaseDiscipline { @ApiProperty() discipline!: string; @ApiProperty() disciplineCode!: string; - @ApiProperty({ required: false }) - isTechnical?: boolean; } + +export class Discipline extends BaseDiscipline{ + @ApiProperty({ description: "Is also true for disciplines where the 'higher' result is better like Hep/Decathlon and One hour races" }) + isTechnical!: boolean; +} \ No newline at end of file diff --git a/src/disciplines/disciplines.controller.ts b/src/disciplines/disciplines.controller.ts index 19e688d..eba200d 100644 --- a/src/disciplines/disciplines.controller.ts +++ b/src/disciplines/disciplines.controller.ts @@ -1,6 +1,6 @@ import { Controller, Get } from '@nestjs/common'; import { ApiOkResponse } from '@nestjs/swagger'; -import { Discipline } from './discipline.dto'; +import { BaseDiscipline } from './discipline.dto'; import { DisciplinesService } from './disciplines.service'; @Controller('disciplines') @@ -9,11 +9,11 @@ export class DisciplinesController { @Get() @ApiOkResponse({ - type: Discipline, + type: BaseDiscipline, isArray: true, description: 'Returns all disciplines, all marked as non-technical!', }) - findAll(): Promise { + findAll(): Promise { return this.disciplinesService.findAll(); } } diff --git a/src/disciplines/disciplines.service.ts b/src/disciplines/disciplines.service.ts index b617a33..a624481 100644 --- a/src/disciplines/disciplines.service.ts +++ b/src/disciplines/disciplines.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { GraphQLClient } from 'graphql-request'; import { z } from 'zod'; -import { Discipline } from './discipline.dto'; +import { BaseDiscipline } from './discipline.dto'; import { GraphqlService } from 'src/graphql/graphql.service'; import { DISCIPLINES_QUERY } from 'src/disciplines/disciplines.query'; @@ -14,7 +14,7 @@ export class DisciplinesService { this.graphQLClient = this.graphqlService.getClient(); } - async findAll(): Promise { + async findAll(): Promise { const data = await this.graphQLClient.request(DISCIPLINES_QUERY); const reponse = z .object({ diff --git a/src/performance-conversion.ts b/src/performance-conversion.ts index b732455..a73b148 100644 --- a/src/performance-conversion.ts +++ b/src/performance-conversion.ts @@ -10,15 +10,10 @@ export function performanceToFloat({ if(performance === ""){ return null; } - // Combined Events - if(!isNaN(Number(performance)) && Number(performance) % 1 === 0) { + // Combined Events or One Hour Race + if(technical && !isNaN(Number(performance)) && Number(performance) % 1 === 0) { return Number(performance); } - // One Hour Race - if (performance == parseInt(performance).toString()) { - return null; - } - performance = performance.trim().replace(',', '.'); if (technical) { diff --git a/src/utils.ts b/src/utils.ts index b00b71b..09faf7a 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -32,6 +32,7 @@ export function extractName(name: string) { lastname: formatLastname(match[2].trim()), }; } + console.error('Could not extract name from', name); return null; } diff --git a/src/zod.schema.ts b/src/zod.schema.ts index 8e8285a..beb15ca 100644 --- a/src/zod.schema.ts +++ b/src/zod.schema.ts @@ -5,6 +5,7 @@ import { extractName, formatLastname, formatSex, + parsePhoneNumber, parseVenue, } from './utils'; import { findCountryByCode, mapCountryToCode } from './country.utils'; @@ -28,6 +29,7 @@ export const CountryCodeSchema = z.string().transform((val) => { return val; }) export const VenueSchema = z.string().transform(parseVenue); +export const PhoneSchema = z.string().transform(parsePhoneNumber); // spain/alvaro-martin-14410246 export const UrlSlugIdSchema = z.string().transform((val) => {