import { IsInt, IsNotEmpty } from "class-validator"; import { ChildEntity, ManyToOne, OneToMany } from "typeorm"; import { ResponseRunner } from '../responses/ResponseRunner'; import { DistanceDonation } from "./DistanceDonation"; import { Participant } from "./Participant"; import { RunnerCard } from "./RunnerCard"; import { RunnerGroup } from "./RunnerGroup"; import { Scan } from "./Scan"; /** * Defines the runner entity. * Runners differ from participants in being able to actually accumulate a ran distance through scans. * Runner's get organized in groups. */ @ChildEntity() export class Runner extends Participant { /** * The runner's associated group. * Can be a runner team or organization. */ @IsNotEmpty() @ManyToOne(() => RunnerGroup, group => group.runners) group: RunnerGroup; /** * The runner's associated distanceDonations. * Used to link runners to distanceDonations in order to calculate the donation's amount based on the distance the runner ran. */ @OneToMany(() => DistanceDonation, distanceDonation => distanceDonation.runner, { nullable: true }) distanceDonations: DistanceDonation[]; /** * The runner's associated cards. * Used to link runners to cards - yes a runner be associated with multiple cards this came in handy in the past. */ @OneToMany(() => RunnerCard, card => card.runner, { nullable: true }) cards: RunnerCard[]; /** * The runner's associated scans. * Used to link runners to scans (valid and fraudulant). */ @OneToMany(() => Scan, scan => scan.runner, { nullable: true }) scans: Scan[]; /** * Returns all valid scans associated with this runner. * This is implemented here to avoid duplicate code in other files. */ public get validScans(): Scan[] { return this.scans.filter(scan => scan.valid == true); } /** * Returns the total distance ran by this runner based on all his valid scans. * This is implemented here to avoid duplicate code in other files. */ @IsInt() public get distance(): number { return this.validScans.reduce((sum, current) => sum + current.distance, 0); } /** * Returns the total donations a runner has collected based on his linked donations and distance ran. */ @IsInt() public get distanceDonationAmount(): number { return this.distanceDonations.reduce((sum, current) => sum + current.amount, 0); } /** * Turns this entity into it's response class. */ public toResponse(): ResponseRunner { return new ResponseRunner(this); } }