184 lines
10 KiB
TypeScript
184 lines
10 KiB
TypeScript
import { Get, JsonController, QueryParam, UseBefore } from 'routing-controllers';
|
|
import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi';
|
|
import { getConnection } from 'typeorm';
|
|
import StatsAuth from '../middlewares/StatsAuth';
|
|
import { Donation } from '../models/entities/Donation';
|
|
import { Donor } from '../models/entities/Donor';
|
|
import { Runner } from '../models/entities/Runner';
|
|
import { RunnerOrganization } from '../models/entities/RunnerOrganization';
|
|
import { RunnerTeam } from '../models/entities/RunnerTeam';
|
|
import { Scan } from '../models/entities/Scan';
|
|
import { TrackScan } from '../models/entities/TrackScan';
|
|
import { User } from '../models/entities/User';
|
|
import { ResponseStats } from '../models/responses/ResponseStats';
|
|
import { ResponseStatsOrgnisation } from '../models/responses/ResponseStatsOrganization';
|
|
import { ResponseStatsRunner } from '../models/responses/ResponseStatsRunner';
|
|
import { ResponseStatsTeam } from '../models/responses/ResponseStatsTeam';
|
|
|
|
@JsonController('/stats')
|
|
export class StatsController {
|
|
|
|
@Get()
|
|
@ResponseSchema(ResponseStats)
|
|
@OpenAPI({ description: "A very basic stats endpoint providing basic counters for a dashboard or simmilar" })
|
|
async get() {
|
|
const connection = getConnection();
|
|
const runners = await connection.getRepository(Runner).count();
|
|
const teams = await connection.getRepository(RunnerTeam).count();
|
|
const orgs = await connection.getRepository(RunnerOrganization).count();
|
|
const users = await connection.getRepository(User).count();
|
|
const scans = await connection.getRepository(Scan).count({ where: { valid: true } });
|
|
|
|
const distance_query = await connection.getRepository(Scan).createQueryBuilder('scan')
|
|
.leftJoinAndSelect("scan.track", "track").where("scan.valid = TRUE")
|
|
.select("SUM(track.distance)", "sum_track").addSelect("SUM(_distance)", "sum_distance")
|
|
.getRawOne();
|
|
let distace = parseInt(distance_query.sum_track)
|
|
if (distance_query.sum_distance) {
|
|
distace += parseInt(distance_query.sum_distance)
|
|
}
|
|
|
|
let donations = await connection.getRepository(Donation).find({ relations: ['runner', 'runner.scans', 'runner.scans.track'] });
|
|
const donors = await connection.getRepository(Donor).count();
|
|
|
|
return new ResponseStats(runners, teams, orgs, users, scans, donations, distace, donors)
|
|
}
|
|
|
|
@Get("/runners/distance")
|
|
@UseBefore(StatsAuth)
|
|
@ResponseSchema(ResponseStatsRunner, { isArray: true })
|
|
@OpenAPI({ description: "Returns the top ten runners by distance.", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
|
|
async getTopRunnersByDistance() {
|
|
let runners = await getConnection().getRepository(Runner).find({ relations: ['scans', 'group', 'distanceDonations', 'scans.track'] });
|
|
if (!runners || runners.length == 0) {
|
|
return [];
|
|
}
|
|
let topRunners = runners.sort((runner1, runner2) => runner2.distance - runner1.distance).slice(0, 10);
|
|
let responseRunners: ResponseStatsRunner[] = new Array<ResponseStatsRunner>();
|
|
topRunners.forEach(runner => {
|
|
responseRunners.push(new ResponseStatsRunner(runner));
|
|
});
|
|
return responseRunners;
|
|
}
|
|
|
|
@Get("/runners/donations")
|
|
@UseBefore(StatsAuth)
|
|
@ResponseSchema(ResponseStatsRunner, { isArray: true })
|
|
@OpenAPI({ description: "Returns the top ten runners by donations.", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
|
|
async getTopRunnersByDonations() {
|
|
let runners = await getConnection().getRepository(Runner).find({ relations: ['group', 'distanceDonations', 'distanceDonations.runner', 'distanceDonations.runner.scans', 'distanceDonations.runner.scans.track'] });
|
|
if (!runners || runners.length == 0) {
|
|
return [];
|
|
}
|
|
let topRunners = runners.sort((runner1, runner2) => runner2.distanceDonationAmount - runner1.distanceDonationAmount).slice(0, 10);
|
|
let responseRunners: ResponseStatsRunner[] = new Array<ResponseStatsRunner>();
|
|
topRunners.forEach(runner => {
|
|
responseRunners.push(new ResponseStatsRunner(runner));
|
|
});
|
|
return responseRunners;
|
|
}
|
|
|
|
@Get("/runners/laptime")
|
|
@UseBefore(StatsAuth)
|
|
@ResponseSchema(ResponseStatsRunner, { isArray: true })
|
|
@OpenAPI({ description: "Returns the top ten runners by fastest laptime on your selected track (track by id).", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
|
|
async getTopRunnersByLaptime(@QueryParam("track") track: number) {
|
|
let scans = await getConnection().getRepository(TrackScan).find({ relations: ['track', 'runner', 'runner.group', 'runner.scans', 'runner.scans.track', 'runner.distanceDonations'] });
|
|
if (!scans || scans.length == 0) {
|
|
return [];
|
|
}
|
|
scans = scans.filter((s) => { return s.track.id == track && s.valid == true && s.lapTime != 0 }).sort((scan1, scan2) => scan1.lapTime - scan2.lapTime);
|
|
|
|
let topScans = new Array<TrackScan>();
|
|
let knownRunners = new Array<number>();
|
|
for (let i = 0; i < scans.length && topScans.length < 10; i++) {
|
|
const element = scans[i];
|
|
if (!knownRunners.includes(element.runner.id)) {
|
|
topScans.push(element);
|
|
knownRunners.push(element.runner.id);
|
|
}
|
|
}
|
|
|
|
let responseRunners: ResponseStatsRunner[] = new Array<ResponseStatsRunner>();
|
|
topScans.forEach(scan => {
|
|
responseRunners.push(new ResponseStatsRunner(scan.runner, scan.lapTime));
|
|
});
|
|
return responseRunners;
|
|
}
|
|
|
|
@Get("/scans")
|
|
@UseBefore(StatsAuth)
|
|
@ResponseSchema(ResponseStatsRunner, { isArray: true })
|
|
@OpenAPI({ description: "Returns the top ten fastest track times (with their runner and the runner's group).", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
|
|
async getTopRunnersByTrackTime() {
|
|
throw new Error("Not implemented yet.")
|
|
}
|
|
|
|
@Get("/teams/distance")
|
|
@UseBefore(StatsAuth)
|
|
@ResponseSchema(ResponseStatsTeam, { isArray: true })
|
|
@OpenAPI({ description: "Returns the top ten teams by distance.", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
|
|
async getTopTeamsByDistance() {
|
|
let teams = await getConnection().getRepository(RunnerTeam).find({ relations: ['parentGroup', 'runners', 'runners.scans', 'runners.scans.track'] });
|
|
if (!teams || teams.length == 0) {
|
|
return [];
|
|
}
|
|
let topTeams = teams.sort((team1, team2) => team2.distance - team1.distance).slice(0, 10);
|
|
let responseTeams: ResponseStatsTeam[] = new Array<ResponseStatsTeam>();
|
|
topTeams.forEach(team => {
|
|
responseTeams.push(new ResponseStatsTeam(team));
|
|
});
|
|
return responseTeams;
|
|
}
|
|
|
|
@Get("/teams/donations")
|
|
@UseBefore(StatsAuth)
|
|
@ResponseSchema(ResponseStatsTeam, { isArray: true })
|
|
@OpenAPI({ description: "Returns the top ten teams by donations.", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
|
|
async getTopTeamsByDonations() {
|
|
let teams = await getConnection().getRepository(RunnerTeam).find({ relations: ['parentGroup', 'runners', 'runners.scans', 'runners.distanceDonations', 'runners.scans.track'] });
|
|
if (!teams || teams.length == 0) {
|
|
return [];
|
|
}
|
|
let topTeams = teams.sort((team1, team2) => team2.distanceDonationAmount - team1.distanceDonationAmount).slice(0, 10);
|
|
let responseTeams: ResponseStatsTeam[] = new Array<ResponseStatsTeam>();
|
|
topTeams.forEach(team => {
|
|
responseTeams.push(new ResponseStatsTeam(team));
|
|
});
|
|
return responseTeams;
|
|
}
|
|
|
|
@Get("/organizations/distance")
|
|
@UseBefore(StatsAuth)
|
|
@ResponseSchema(ResponseStatsOrgnisation, { isArray: true })
|
|
@OpenAPI({ description: "Returns the top ten organizations by distance.", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
|
|
async getTopOrgsByDistance() {
|
|
let orgs = await getConnection().getRepository(RunnerOrganization).find({ relations: ['runners', 'runners.scans', 'runners.distanceDonations', 'runners.scans.track', 'teams', 'teams.runners', 'teams.runners.scans', 'teams.runners.distanceDonations', 'teams.runners.scans.track'] });
|
|
if (!orgs || orgs.length == 0) {
|
|
return [];
|
|
}
|
|
let topOrgs = orgs.sort((org1, org2) => org2.distance - org1.distance).slice(0, 10);
|
|
let responseOrgs: ResponseStatsOrgnisation[] = new Array<ResponseStatsOrgnisation>();
|
|
topOrgs.forEach(org => {
|
|
responseOrgs.push(new ResponseStatsOrgnisation(org));
|
|
});
|
|
return responseOrgs;
|
|
}
|
|
|
|
@Get("/organizations/donations")
|
|
@UseBefore(StatsAuth)
|
|
@ResponseSchema(ResponseStatsOrgnisation, { isArray: true })
|
|
@OpenAPI({ description: "Returns the top ten organizations by donations.", security: [{ "StatsApiToken": [] }, { "AuthToken": [] }, { "RefreshTokenCookie": [] }] })
|
|
async getTopOrgsByDonations() {
|
|
let orgs = await getConnection().getRepository(RunnerOrganization).find({ relations: ['runners', 'runners.distanceDonations', 'runners.distanceDonations.runner', 'runners.distanceDonations.runner.scans', 'runners.distanceDonations.runner.scans.track', 'teams', 'teams.runners', 'teams.runners.distanceDonations', 'teams.runners.distanceDonations.runner', 'teams.runners.distanceDonations.runner.scans', 'teams.runners.distanceDonations.runner.scans.track'] });
|
|
if (!orgs || orgs.length == 0) {
|
|
return [];
|
|
}
|
|
let topOrgs = orgs.sort((org1, org2) => org2.distanceDonationAmount - org1.distanceDonationAmount).slice(0, 10);
|
|
let responseOrgs: ResponseStatsOrgnisation[] = new Array<ResponseStatsOrgnisation>();
|
|
topOrgs.forEach(org => {
|
|
responseOrgs.push(new ResponseStatsOrgnisation(org));
|
|
});
|
|
return responseOrgs;
|
|
}
|
|
} |