Files
backend/src/models/entities/Runner.ts
T

90 lines
3.0 KiB
TypeScript

import { IsInt, IsNotEmpty, IsOptional, IsString } from "class-validator";
import { ChildEntity, Column, Index, ManyToOne, OneToMany } from "typeorm";
import { ResponseRunner } from '../responses/ResponseRunner';
import type { DistanceDonation } from "./DistanceDonation";
import { Participant } from "./Participant";
import type { RunnerCard } from "./RunnerCard";
import { RunnerGroup } from "./RunnerGroup";
import type { 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()
@Index(['group'])
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(() => require("./DistanceDonation").DistanceDonation, (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(() => require("./RunnerCard").RunnerCard, (card: RunnerCard) => card.runner, { nullable: true })
cards!: RunnerCard[];
/**
* The runner's associated scans.
* Used to link runners to scans (valid and fraudulant).
*/
@OneToMany(() => require("./Scan").Scan, (scan: Scan) => scan.runner, { nullable: true })
scans!: Scan[];
/**
* The last time the runner requested a selfservice link.
* Used to prevent spamming of the selfservice link forgotten route.
*/
@Column({ nullable: true, unique: false })
@IsString()
@IsOptional()
resetRequestedTimestamp?: number;
/**
* Returns all valid scans associated with this runner.
* This is implemented here to avoid duplicate code in other files.
*/
public get validScans(): Scan[] {
if (this.scans) {
return this.scans.filter(scan => scan.valid == true);
}
return []
}
/**
* 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, true);
}
}