Compare commits
	
		
			18 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 3909ed34f7 | |||
| b2ac70e0ae | |||
| 5f17e7f783 | |||
| a5a56a263a | |||
| 2d8f7528d9 | |||
| 9581185b24 | |||
| 2905884c02 | |||
| e9914e317b | |||
| 702070da66 | |||
| cc89ba8afb | |||
| 7c4ff42a3b | |||
| 8007117434 | |||
| 23fa78eb9d | |||
| 3b3e68900b | |||
| 3ff666fd3e | |||
| 4e4435010f | |||
| de9af5a909 | |||
| ac631f0af4 | 
							
								
								
									
										48
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @@ -2,9 +2,57 @@ | ||||
|  | ||||
| All notable changes to this project will be documented in this file. Dates are displayed in UTC. | ||||
|  | ||||
| #### [v0.15.3](https://git.odit.services/lfk/backend/compare/v0.15.2...v0.15.3) | ||||
|  | ||||
| - Faster stats (not including donations) [`b2ac70e`](https://git.odit.services/lfk/backend/commit/b2ac70e0aec1064e54a5043a104e7892984b2338) | ||||
|  | ||||
| #### [v0.15.2](https://git.odit.services/lfk/backend/compare/v0.15.1...v0.15.2) | ||||
|  | ||||
| > 15 April 2023 | ||||
|  | ||||
| - 🚀Bumped version to v0.15.2 [`5f17e7f`](https://git.odit.services/lfk/backend/commit/5f17e7f783a7e8e2efc8f7dbbf2c98bcd1d80240) | ||||
| - Don't resolve runner group and parten with get all card requests [`2d8f752`](https://git.odit.services/lfk/backend/commit/2d8f7528d98144832e7609f5aa6fac8de4723c4a) | ||||
| - Resolve groups again for card generation [`a5a56a2`](https://git.odit.services/lfk/backend/commit/a5a56a263a01dbd911a799ab57084166e17b80ac) | ||||
|  | ||||
| #### [v0.15.1](https://git.odit.services/lfk/backend/compare/v0.15.0...v0.15.1) | ||||
|  | ||||
| > 15 April 2023 | ||||
|  | ||||
| - 🚀Bumped version to v0.15.1 [`9581185`](https://git.odit.services/lfk/backend/commit/9581185b24039338e7f238ecdcc3881bb5203759) | ||||
| - Faster trackscan creation by only loading the latest scan [`e9914e3`](https://git.odit.services/lfk/backend/commit/e9914e317b7fd78863cfd8549bad65da9292b7ca) | ||||
| - Log batch time in mass scan script [`2905884`](https://git.odit.services/lfk/backend/commit/2905884c024d7f275b3ad2c2858a2f0911adb95b) | ||||
| - Dont load cards with get all runners request [`702070d`](https://git.odit.services/lfk/backend/commit/702070da669cc605b93e6f5b62d712c28f079dd0) | ||||
|  | ||||
| #### [v0.15.0](https://git.odit.services/lfk/backend/compare/v0.14.6...v0.15.0) | ||||
|  | ||||
| > 15 April 2023 | ||||
|  | ||||
| - Added test script for creating mass scans [`8007117`](https://git.odit.services/lfk/backend/commit/80071174342d87199fcbd981cd8c92300b0a51e4) | ||||
| - 🚀Bumped version to v0.15.0 [`cc89ba8`](https://git.odit.services/lfk/backend/commit/cc89ba8afb3120569613a889baf962555612e95a) | ||||
| - Get all scans speed improvement [`23fa78e`](https://git.odit.services/lfk/backend/commit/23fa78eb9dcc01ecc036347f6703aacc0d163d7d) | ||||
| - More scan request optimizations [`7c4ff42`](https://git.odit.services/lfk/backend/commit/7c4ff42a3b3e7b186e16c85a97d9ecc854a32cb0) | ||||
|  | ||||
| #### [v0.14.6](https://git.odit.services/lfk/backend/compare/v0.14.5...v0.14.6) | ||||
|  | ||||
| > 15 April 2023 | ||||
|  | ||||
| - 🚀Bumped version to v0.14.6 [`3b3e689`](https://git.odit.services/lfk/backend/commit/3b3e68900beca16cfff88dbef22540f77750d29b) | ||||
| - Missing orm file [`3ff666f`](https://git.odit.services/lfk/backend/commit/3ff666fd3e84ac8cf41b30e9e17082b10548d55b) | ||||
|  | ||||
| #### [v0.14.5](https://git.odit.services/lfk/backend/compare/v0.14.4...v0.14.5) | ||||
|  | ||||
| > 15 April 2023 | ||||
|  | ||||
| - 🚀Bumped version to v0.14.5 [`4e44350`](https://git.odit.services/lfk/backend/commit/4e4435010fd7095e3b9742e207cba1b68cd6da3b) | ||||
| - Entrypoint fix [`de9af5a`](https://git.odit.services/lfk/backend/commit/de9af5a90907dcfc9bfb1d5a56420eed8bb59922) | ||||
| - Fixed copy [`ac631f0`](https://git.odit.services/lfk/backend/commit/ac631f0af467446552478873b7b4802a9310f865) | ||||
|  | ||||
| #### [v0.14.4](https://git.odit.services/lfk/backend/compare/v0.14.3...v0.14.4) | ||||
|  | ||||
| > 15 April 2023 | ||||
|  | ||||
| - Switched ci over to pnpm + cache [`6275aaa`](https://git.odit.services/lfk/backend/commit/6275aaa326f1c02c8dd42aa31608978408c44ab7) | ||||
| - 🚀Bumped version to v0.14.4 [`6bbdd5b`](https://git.odit.services/lfk/backend/commit/6bbdd5bb04a1c38e4b3a150db24b76e9c96490dd) | ||||
| - Back to ean13 based codes [`a8fc755`](https://git.odit.services/lfk/backend/commit/a8fc7558408b97da4b2c469ae5e73ab502b4fda0) | ||||
| - install prod in first step [`d027439`](https://git.odit.services/lfk/backend/commit/d02743984dfea8057be3081bd3a32a8f67e610aa) | ||||
| - Switched dockerfile to pnpm 8 with cache [`93d43b7`](https://git.odit.services/lfk/backend/commit/93d43b76843d7cb411f37fd2066c6a5364c05415) | ||||
|   | ||||
| @@ -15,6 +15,9 @@ RUN pnpm run build \ | ||||
|  | ||||
| # final image | ||||
| FROM registry.odit.services/hub/library/node:19.5.0-alpine3.16 as final | ||||
| COPY --from=build /app/dist dist | ||||
| WORKDIR /app | ||||
| COPY --from=build /app/package.json /app/package.json | ||||
| COPY --from=build /app/ormconfig.js /app/ormconfig.js | ||||
| COPY --from=build /app/dist /app/dist | ||||
| COPY --from=build /app/node_modules /app/node_modules | ||||
| ENTRYPOINT ["node", "dist/app.js"] | ||||
| ENTRYPOINT ["node", "/app/dist/app.js"] | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "@odit/lfk-backend", | ||||
|   "version": "0.14.4", | ||||
|   "version": "0.15.3", | ||||
|   "main": "src/app.ts", | ||||
|   "repository": "https://git.odit.services/lfk/backend", | ||||
|   "engines": { | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post, Put, QueryParam } from 'routing-controllers'; | ||||
| import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; | ||||
| import { getConnectionManager, Repository } from 'typeorm'; | ||||
| import { Repository, getConnectionManager } from 'typeorm'; | ||||
| import { RunnerCardHasScansError, RunnerCardIdsNotMatchingError, RunnerCardNotFoundError } from '../errors/RunnerCardErrors'; | ||||
| import { RunnerNotFoundError } from '../errors/RunnerErrors'; | ||||
| import { CreateRunnerCard } from '../models/actions/create/CreateRunnerCard'; | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post, Put, QueryParam } from 'routing-controllers'; | ||||
| import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; | ||||
| import { getConnectionManager, Repository } from 'typeorm'; | ||||
| import { Repository, getConnectionManager } from 'typeorm'; | ||||
| import { RunnerGroupNeededError, RunnerHasDistanceDonationsError, RunnerIdsNotMatchingError, RunnerNotFoundError } from '../errors/RunnerErrors'; | ||||
| import { RunnerGroupNotFoundError } from '../errors/RunnerGroupErrors'; | ||||
| import { CreateRunner } from '../models/actions/create/CreateRunner'; | ||||
| @@ -32,7 +32,7 @@ export class RunnerController { | ||||
| 	@OpenAPI({ description: 'Lists all runners from all teams/orgs. <br> This includes the runner\'s group and distance ran.' }) | ||||
| 	async getAll() { | ||||
| 		let responseRunners: ResponseRunner[] = new Array<ResponseRunner>(); | ||||
| 		const runners = await this.runnerRepository.find({ relations: ['scans', 'group', 'group.parentGroup', 'scans.track', 'cards'] }); | ||||
| 		const runners = await this.runnerRepository.find({ relations: ['scans', 'group', 'group.parentGroup', 'scans.track'] }); | ||||
| 		runners.forEach(runner => { | ||||
| 			responseRunners.push(new ResponseRunner(runner)); | ||||
| 		}); | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import { Request } from "express"; | ||||
| import { Authorized, Body, Delete, Get, JsonController, OnUndefined, Param, Post, Put, QueryParam, Req, UseBefore } from 'routing-controllers'; | ||||
| import { OpenAPI, ResponseSchema } from 'routing-controllers-openapi'; | ||||
| import { getConnectionManager, Repository } from 'typeorm'; | ||||
| import { Repository, getConnectionManager } from 'typeorm'; | ||||
| import { RunnerNotFoundError } from '../errors/RunnerErrors'; | ||||
| import { ScanIdsNotMatchingError, ScanNotFoundError } from '../errors/ScanErrors'; | ||||
| import { ScanStationNotFoundError } from '../errors/ScanStationErrors'; | ||||
| @@ -36,7 +36,7 @@ export class ScanController { | ||||
| 	@OpenAPI({ description: 'Lists all scans (normal or track) from all runners. <br> This includes the scan\'s runner\'s distance ran.' }) | ||||
| 	async getAll() { | ||||
| 		let responseScans: ResponseScan[] = new Array<ResponseScan>(); | ||||
| 		const scans = await this.scanRepository.find({ relations: ['runner', 'track', 'runner.scans', 'runner.group', 'runner.scans.track', 'card', 'station'] }); | ||||
| 		const scans = await this.scanRepository.find({ relations: ['runner', 'track'] }); | ||||
| 		scans.forEach(scan => { | ||||
| 			responseScans.push(scan.toResponse()); | ||||
| 		}); | ||||
| @@ -51,7 +51,7 @@ export class ScanController { | ||||
| 	@OnUndefined(ScanNotFoundError) | ||||
| 	@OpenAPI({ description: 'Lists all information about the scan whose id got provided. This includes the scan\'s runner\'s distance ran.' }) | ||||
| 	async getOne(@Param('id') id: number) { | ||||
| 		let scan = await this.scanRepository.findOne({ id: id }, { relations: ['runner', 'track', 'runner.scans', 'runner.group', 'runner.scans.track', 'card', 'station'] }) | ||||
| 		let scan = await this.scanRepository.findOne({ id: id }, { relations: ['runner', 'track', 'runner.group', 'card', 'station'] }) | ||||
| 		if (!scan) { throw new ScanNotFoundError(); } | ||||
| 		return scan.toResponse(); | ||||
| 	} | ||||
|   | ||||
| @@ -22,13 +22,17 @@ export class StatsController { | ||||
|     @OpenAPI({ description: "A very basic stats endpoint providing basic counters for a dashboard or simmilar" }) | ||||
|     async get() { | ||||
|         let connection = getConnection(); | ||||
|         let runners = await connection.getRepository(Runner).find({ relations: ['scans', 'scans.track'] }); | ||||
|         let teams = await connection.getRepository(RunnerTeam).find(); | ||||
|         let orgs = await connection.getRepository(RunnerOrganization).find(); | ||||
|         let users = await connection.getRepository(User).find(); | ||||
|         let scans = await connection.getRepository(Scan).find(); | ||||
|         let runners = await connection.getRepository(Runner).count(); | ||||
|         let teams = await connection.getRepository(RunnerTeam).count(); | ||||
|         let orgs = await connection.getRepository(RunnerOrganization).count(); | ||||
|         let users = await connection.getRepository(User).count(); | ||||
|         let scans = await connection.getRepository(Scan).count({ where: { valid: true } }); | ||||
|         let 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 donations = await connection.getRepository(Donation).find({ relations: ['runner', 'runner.scans', 'runner.scans.track'] }); | ||||
|         return new ResponseStats(runners, teams, orgs, users, scans, donations) | ||||
|         return new ResponseStats(runners, teams, orgs, users, scans, donations, distance_query.sum_track + distance_query.sum_distance) | ||||
|     } | ||||
|  | ||||
|     @Get("/runners/distance") | ||||
|   | ||||
| @@ -86,14 +86,13 @@ export class CreateTrackScan { | ||||
|      * @returns The validated scan with it's laptime set. | ||||
|      */ | ||||
|     public async validateScan(scan: TrackScan): Promise<TrackScan> { | ||||
|         const scans = await getConnection().getRepository(TrackScan).find({ where: { runner: scan.runner, valid: true }, relations: ["track"] }); | ||||
|         if (scans.length == 0) { | ||||
|         const latestScan = await getConnection().getRepository(TrackScan).findOne({ where: { runner: scan.runner, valid: true }, relations: ["track"], order: { id: 'DESC' } }); | ||||
|         if (!latestScan) { | ||||
|             scan.lapTime = 0; | ||||
|             scan.valid = true; | ||||
|         } | ||||
|         else { | ||||
|             const newestScan = scans[scans.length - 1]; | ||||
|             scan.lapTime = scan.timestamp - newestScan.timestamp; | ||||
|             scan.lapTime = scan.timestamp - latestScan.timestamp; | ||||
|             scan.valid = (scan.lapTime > scan.track.minimumLapTime); | ||||
|         } | ||||
|         return scan; | ||||
|   | ||||
| @@ -2,11 +2,6 @@ import { | ||||
|     IsInt | ||||
| } from "class-validator"; | ||||
| import { Donation } from '../entities/Donation'; | ||||
| import { Runner } from '../entities/Runner'; | ||||
| import { RunnerOrganization } from '../entities/RunnerOrganization'; | ||||
| import { RunnerTeam } from '../entities/RunnerTeam'; | ||||
| import { Scan } from '../entities/Scan'; | ||||
| import { User } from '../entities/User'; | ||||
| import { ResponseObjectType } from '../enums/ResponseObjectType'; | ||||
| import { IResponse } from './IResponse'; | ||||
|  | ||||
| @@ -78,13 +73,13 @@ export class ResponseStats implements IResponse { | ||||
|      * @param scans Array containing all scans - no relations have to be resolved. | ||||
|      * @param donations Array containing all donations - the following relations have to be resolved: runner, runner.scans, runner.scans.track | ||||
|      */ | ||||
|     public constructor(runners: Runner[], teams: RunnerTeam[], orgs: RunnerOrganization[], users: User[], scans: Scan[], donations: Donation[]) { | ||||
|         this.total_runners = runners.length; | ||||
|         this.total_teams = teams.length; | ||||
|         this.total_orgs = orgs.length; | ||||
|         this.total_users = users.length; | ||||
|         this.total_scans = scans.filter(scan => { scan.valid === true }).length; | ||||
|         this.total_distance = runners.reduce((sum, current) => sum + current.distance, 0); | ||||
|     public constructor(runners: number, teams: number, orgs: number, users: number, scans: number, donations: Donation[], distance: number) { | ||||
|         this.total_runners = runners; | ||||
|         this.total_teams = teams; | ||||
|         this.total_orgs = orgs; | ||||
|         this.total_users = users; | ||||
|         this.total_scans = scans; | ||||
|         this.total_distance = distance; | ||||
|         this.total_donation = donations.reduce((sum, current) => sum + current.amount, 0); | ||||
|         this.average_distance = this.total_distance / this.total_runners; | ||||
|     } | ||||
|   | ||||
							
								
								
									
										19
									
								
								src/tests/create_mass_scans.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/tests/create_mass_scans.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| import axios from 'axios'; | ||||
|  | ||||
| async function main() { | ||||
|     console.time("batches") | ||||
|     for (let i = 0; i < 100; i++) { | ||||
|         const batch = []; | ||||
|         for (let i = 0; i < 6; i++) { | ||||
|             batch.push(axios.post('http://localhost:4010/api/scans/trackscans', { card: 200000000001, station: 2 }, { | ||||
|                 headers: { | ||||
|                     Authorization: 'Bearer 10F2E64.BB4F6CC5-2148-4CCF-88B5-0AA85D0508A9' | ||||
|                 } | ||||
|             })) | ||||
|         } | ||||
|         await Promise.all(batch) | ||||
|         console.timeLog("batches", `Finished batch ${i}`) | ||||
|     } | ||||
|     console.timeEnd("batches") | ||||
| } | ||||
| main(); | ||||
		Reference in New Issue
	
	Block a user