feature(database-connection): First implementation
This commit is contained in:
3
backend/src/api/predicate.ts
Normal file
3
backend/src/api/predicate.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export interface Predicate<T, O> {
|
||||
process(input: T): O;
|
||||
}
|
||||
13
backend/src/api/sort.ts
Normal file
13
backend/src/api/sort.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
export class Sort {
|
||||
public static descending = (a: number, b: number) => {
|
||||
if (a < b) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (a > b) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
11
backend/src/api/timeutil.ts
Normal file
11
backend/src/api/timeutil.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
export class TimeUtil {
|
||||
|
||||
public static humanize = (seconds: number) => {
|
||||
const d = Math.floor(seconds / (3600 * 24));
|
||||
const h = Math.floor(seconds % (3600 * 24) / 3600);
|
||||
const m = Math.floor(seconds % 3600 / 60);
|
||||
const s = Math.floor(seconds % 60);
|
||||
|
||||
return `${d}d ${h}h ${m}m ${s}s`;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
import { Controller, Get } from '@nestjs/common';
|
||||
import { Controller, Get, HttpException, HttpStatus } from '@nestjs/common';
|
||||
import { AppService } from './app.service';
|
||||
import { DatabaseService } from './database/database.service';
|
||||
import logger from './logger/Logger';
|
||||
import { TableEntry } from "./models/TableEntry";
|
||||
import { SinusBotService } from "./services/sinusbot.service";
|
||||
|
||||
@@ -7,7 +9,8 @@ import { SinusBotService } from "./services/sinusbot.service";
|
||||
export class AppController {
|
||||
constructor(
|
||||
private readonly appService: AppService,
|
||||
private readonly sinusBotService: SinusBotService
|
||||
private readonly sinusBotService: SinusBotService,
|
||||
private readonly databaseService: DatabaseService
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
@@ -15,8 +18,21 @@ export class AppController {
|
||||
return this.appService.getHello();
|
||||
}
|
||||
|
||||
@Get('/stats')
|
||||
async getStats(): Promise<TableEntry[]> {
|
||||
@Get('/stats-old')
|
||||
async getStatsOld(): Promise<TableEntry[]> {
|
||||
return await this.sinusBotService.fetchStats();
|
||||
}
|
||||
|
||||
@Get('/stats')
|
||||
async getStats(): Promise<TableEntry[]> {
|
||||
return this.databaseService.fetchStats()
|
||||
.then(value => { return value; })
|
||||
.catch(err => {
|
||||
logger.error(`Error occured when fetching stats.`, err);
|
||||
throw new HttpException(
|
||||
'Error when fetching stats. Contact administrator or try again later!',
|
||||
HttpStatus.INTERNAL_SERVER_ERROR
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,11 @@ import { Module } from '@nestjs/common';
|
||||
import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
import { SinusBotService } from "./services/sinusbot.service";
|
||||
import { DatabaseService } from './database/database.service';
|
||||
|
||||
@Module({
|
||||
imports: [],
|
||||
controllers: [AppController],
|
||||
providers: [AppService, SinusBotService],
|
||||
providers: [AppService, SinusBotService, DatabaseService],
|
||||
})
|
||||
export class AppModule {}
|
||||
|
||||
18
backend/src/database/database.service.spec.ts
Normal file
18
backend/src/database/database.service.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { DatabaseService } from './database.service';
|
||||
|
||||
describe('DatabaseService', () => {
|
||||
let service: DatabaseService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [DatabaseService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<DatabaseService>(DatabaseService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
35
backend/src/database/database.service.ts
Normal file
35
backend/src/database/database.service.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import logger from 'src/logger/Logger';
|
||||
import { TableEntry } from 'src/models/TableEntry';
|
||||
import { TimeTrackerPredicate } from './timetracking.predicate';
|
||||
|
||||
@Injectable()
|
||||
export class DatabaseService {
|
||||
// private host = process.env.MYSQL_HOST
|
||||
// private port = process.env.MYSQL_PORT
|
||||
// private credentials = {
|
||||
// username: process.env.MYSQL_USERNAME,
|
||||
// password: process.env.MYSQL_PASSWORD
|
||||
// }
|
||||
// private database = process.env.MYSQL_DATABASE
|
||||
|
||||
constructor(
|
||||
private readonly prismaClient: PrismaClient,
|
||||
private readonly timetrackerPredicate: TimeTrackerPredicate
|
||||
) {}
|
||||
|
||||
public fetchStats(): Promise<TableEntry[]> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.prismaClient.timetracker.findMany({
|
||||
include: {
|
||||
user: true,
|
||||
ranks: true
|
||||
}
|
||||
})
|
||||
.then(this.timetrackerPredicate.process)
|
||||
.then(result => resolve(result))
|
||||
.catch(err => reject(err));
|
||||
});
|
||||
}
|
||||
}
|
||||
23
backend/src/database/timetracking.predicate.ts
Normal file
23
backend/src/database/timetracking.predicate.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { ranks, seasons, timetracker, user } from "@prisma/client";
|
||||
import { Predicate } from "src/api/predicate";
|
||||
import { Sort } from "src/api/sort";
|
||||
import { TimeUtil } from "src/api/timeutil";
|
||||
import { TableEntry } from "src/models/TableEntry";
|
||||
|
||||
type UserStats = timetracker & { user: user, ranks: ranks; };
|
||||
|
||||
export class TimeTrackerPredicate implements Predicate<UserStats[], TableEntry[]> {
|
||||
|
||||
process(input: UserStats[]): TableEntry[] {
|
||||
return input.filter((userStats: UserStats) => userStats.time != null)
|
||||
.map((userStats: UserStats) => {
|
||||
return {
|
||||
name: userStats.user.name,
|
||||
rawTime: userStats.time,
|
||||
onlineTime: TimeUtil.humanize(userStats.time),
|
||||
rank: userStats.ranks.rank_name
|
||||
}
|
||||
})
|
||||
.sort((lhs, rhs) => Sort.descending(lhs.rawTime, rhs.rawTime));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user