25 changed files with 427 additions and 71 deletions
@ -1,4 +1,42 @@ |
|||||
import { Injectable } from '@nestjs/common'; |
import { Injectable } from '@nestjs/common'; |
||||
|
import { InjectModel } from '@nestjs/sequelize'; |
||||
|
import { RaceResult } from './race-result.model'; |
||||
|
import { Sequelize } from 'sequelize-typescript'; |
||||
|
import { Racer } from 'src/racers/racer.model'; |
||||
|
|
||||
@Injectable() |
@Injectable() |
||||
export class RaceResultsService {} |
export class RaceResultsService { |
||||
|
|
||||
|
constructor( |
||||
|
@InjectModel(RaceResult) private raceResultModel: typeof RaceResult, |
||||
|
private sequelize: Sequelize |
||||
|
) |
||||
|
{} |
||||
|
|
||||
|
async getFastestTimesForRace(raceId: number) { |
||||
|
return this.raceResultModel.findAll({ |
||||
|
where:{ raceId: raceId }, |
||||
|
order: [['time', "ASC"]], |
||||
|
group:['racerId'], |
||||
|
include:[Racer] |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
async create(raceId: number, racerId: number, time: number, replayPath: string) { |
||||
|
try { |
||||
|
await this.sequelize.transaction( async t => { |
||||
|
const transactionHost = { transaction: t }; |
||||
|
await this.raceResultModel.create({ |
||||
|
raceId: raceId, |
||||
|
racerId: racerId, |
||||
|
replayPath: replayPath, |
||||
|
time: time |
||||
|
}, |
||||
|
transactionHost |
||||
|
); |
||||
|
}); |
||||
|
} catch (error) { |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|||||
@ -1,4 +1,31 @@ |
|||||
import { Injectable } from '@nestjs/common'; |
import { Injectable } from '@nestjs/common'; |
||||
|
import { Racer } from './racer.model'; |
||||
|
import { InjectModel } from '@nestjs/sequelize'; |
||||
|
import { Sequelize } from 'sequelize-typescript'; |
||||
|
|
||||
@Injectable() |
@Injectable() |
||||
export class RacersService {} |
export class RacersService { |
||||
|
|
||||
|
constructor( |
||||
|
@InjectModel(Racer) private racerModel: typeof Racer, |
||||
|
private sequelize: Sequelize |
||||
|
) |
||||
|
{} |
||||
|
|
||||
|
async findOrCreate(gameHandle: string): Promise<Racer> { |
||||
|
try { |
||||
|
return this.sequelize.transaction( async t => { |
||||
|
return this.racerModel.findOrCreate({ |
||||
|
where: { |
||||
|
gameHandle: gameHandle |
||||
|
}, |
||||
|
transaction: t |
||||
|
}).then((value) => { |
||||
|
return value[0]; |
||||
|
}) |
||||
|
}); |
||||
|
} catch (error) { |
||||
|
console.log(error); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|||||
@ -1,27 +1,42 @@ |
|||||
import { Controller, Get, Param } from '@nestjs/common'; |
import { Body, Controller, Get, Param, Post, UseGuards } from '@nestjs/common'; |
||||
import { from } from 'rxjs'; |
import { from } from 'rxjs'; |
||||
|
|
||||
|
import { RacesService } from './races.service'; |
||||
|
import { RaceResultsService } from 'src/race-results/race-results.service'; |
||||
|
|
||||
import * as TMIO from 'trackmania.io'; |
import * as TMIO from 'trackmania.io'; |
||||
|
import { AuthGuard } from 'src/auth/auth.guard'; |
||||
|
|
||||
@Controller('races') |
@Controller('races') |
||||
export class RacesController { |
export class RacesController { |
||||
TMIO: any; |
TMIO: any; |
||||
|
|
||||
constructor() { |
constructor( |
||||
|
private racesService: RacesService, |
||||
|
private raceResultsService: RaceResultsService |
||||
|
) { |
||||
this.TMIO = new TMIO.Client(); |
this.TMIO = new TMIO.Client(); |
||||
} |
} |
||||
|
|
||||
@Get('/map/:id') |
@Get(':id') |
||||
findOne(@Param() params: any) { |
findOne(@Param() params: any) { |
||||
let promise = new Promise((resolve, reject) => { |
return this.racesService.findOne(params.id); |
||||
try{ |
} |
||||
this.TMIO.maps.get(params.id).then(async mapInfo => { |
|
||||
console.log(mapInfo); |
@Get('/map/:id') |
||||
resolve(mapInfo._data); |
getMapInfo(@Param() params: any) { |
||||
}); |
return from(this.racesService.getMapDetails(params.id)); |
||||
} catch (error) { |
} |
||||
reject(error); |
|
||||
} |
@Get(':id/results') |
||||
}); |
getResults(@Param() params: any) { |
||||
return from(promise); |
return this.raceResultsService.getFastestTimesForRace(params.id); |
||||
|
} |
||||
|
|
||||
|
@UseGuards(AuthGuard) |
||||
|
@Post() |
||||
|
create(@Body() body: any) { |
||||
|
console.log("Races/Create") |
||||
|
return this.racesService.create(body.mapUID, body.startDate, body.endDate, body.seasonId); |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -1,4 +1,75 @@ |
|||||
import { Injectable } from '@nestjs/common'; |
import { Injectable } from '@nestjs/common'; |
||||
|
import { InjectModel } from '@nestjs/sequelize'; |
||||
|
import { Sequelize } from 'sequelize-typescript'; |
||||
|
import { Race } from './race.model'; |
||||
|
import { RaceResult } from 'src/race-results/race-result.model'; |
||||
|
import { Season } from 'src/seasons/season.model'; |
||||
|
|
||||
|
import * as TMIO from 'trackmania.io'; |
||||
|
import { from } from 'rxjs'; |
||||
|
import { Racer } from 'src/racers/racer.model'; |
||||
|
|
||||
@Injectable() |
@Injectable() |
||||
export class RacesService {} |
export class RacesService { |
||||
|
TMIO: any; |
||||
|
|
||||
|
constructor( |
||||
|
@InjectModel(Race) private raceModel: typeof Race, |
||||
|
private sequelize: Sequelize |
||||
|
) |
||||
|
{ |
||||
|
this.TMIO = new TMIO.Client(); |
||||
|
} |
||||
|
|
||||
|
async findOne(id: number) { |
||||
|
return this.raceModel.findOne({ |
||||
|
where: {id: id}, |
||||
|
include:[{model: RaceResult, include:[Racer]}, Season] |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
async findOneBySeasonAndMapUID(seasonId: number, mapUID: string) { |
||||
|
return this.raceModel.findOne({ where: {seasonId: seasonId, mapUID: mapUID} }) |
||||
|
} |
||||
|
|
||||
|
async getMapDetails(mapUId: string) { |
||||
|
let promise = new Promise((resolve, reject) => { |
||||
|
try{ |
||||
|
this.TMIO.maps.get(mapUId).then(async mapInfo => { |
||||
|
console.log(mapInfo); |
||||
|
resolve(mapInfo._data); |
||||
|
}); |
||||
|
} catch (error) { |
||||
|
reject(error); |
||||
|
} |
||||
|
}); |
||||
|
return promise; |
||||
|
} |
||||
|
|
||||
|
async create(mapUID: string, startDate: Date, endDate: Date, seasonId: number) { |
||||
|
try { |
||||
|
let mapDetails = await this.getMapDetails(mapUID) as any; |
||||
|
|
||||
|
await this.sequelize.transaction( async t => { |
||||
|
const transactionHost = { transaction: t }; |
||||
|
await this.raceModel.create({ |
||||
|
mapName: mapDetails.name, |
||||
|
mapURL: "", |
||||
|
mapUID: mapUID, |
||||
|
mapImgUrl: mapDetails.thumbnailUrl, |
||||
|
authorTime: mapDetails.authorScore, |
||||
|
goldTime: mapDetails.goldScore, |
||||
|
silverTime: mapDetails.silverScore, |
||||
|
bronzeTime: mapDetails.bronzeScore, |
||||
|
startDate: startDate, |
||||
|
endDate: endDate, |
||||
|
seasonId: seasonId |
||||
|
}, |
||||
|
transactionHost |
||||
|
); |
||||
|
}); |
||||
|
} catch (error) { |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|||||
@ -1,4 +1,36 @@ |
|||||
import { Injectable } from '@nestjs/common'; |
import { Injectable } from '@nestjs/common'; |
||||
|
import { InjectModel } from '@nestjs/sequelize'; |
||||
|
import { SeasonStanding } from './season-standing.model'; |
||||
|
import { Sequelize } from 'sequelize-typescript'; |
||||
|
|
||||
@Injectable() |
@Injectable() |
||||
export class SeasonStandingsService {} |
export class SeasonStandingsService { |
||||
|
|
||||
|
constructor( |
||||
|
@InjectModel(SeasonStanding) private seasonStandingModel: typeof SeasonStanding, |
||||
|
private sequelize: Sequelize |
||||
|
) |
||||
|
{} |
||||
|
|
||||
|
async findOrCreate(racerId: number, seasonId: number): Promise<SeasonStanding> { |
||||
|
try { |
||||
|
return this.sequelize.transaction( async t => { |
||||
|
return this.seasonStandingModel.findOrCreate({ |
||||
|
where: { |
||||
|
racerId: racerId, |
||||
|
seasonId: seasonId, |
||||
|
}, |
||||
|
transaction: t |
||||
|
}).then((value) => { |
||||
|
return value[0]; |
||||
|
}) |
||||
|
}); |
||||
|
} catch (error) { |
||||
|
console.log(error); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
updateStandings(seasonId: number) { |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|||||
@ -0,0 +1,21 @@ |
|||||
|
import { Module } from '@nestjs/common'; |
||||
|
import { UploadService } from './upload.service'; |
||||
|
import { UploadController } from './upload.controller'; |
||||
|
import { RacersModule } from 'src/racers/racers.module'; |
||||
|
import { RacesModule } from 'src/races/races.module'; |
||||
|
import { SeasonStandingsModule } from 'src/season-standings/season-standings.module'; |
||||
|
import { RaceResultsModule } from 'src/race-results/race-results.module'; |
||||
|
|
||||
|
@Module({ |
||||
|
imports:[ |
||||
|
RacersModule, |
||||
|
RacesModule, |
||||
|
RaceResultsModule, |
||||
|
SeasonStandingsModule, |
||||
|
], |
||||
|
providers: [UploadService], |
||||
|
controllers: [UploadController], |
||||
|
exports: [UploadService] |
||||
|
}) |
||||
|
|
||||
|
export class UploadModule {} |
||||
@ -0,0 +1,18 @@ |
|||||
|
import { Test, TestingModule } from '@nestjs/testing'; |
||||
|
import { UploadService } from './upload.service'; |
||||
|
|
||||
|
describe('UploadService', () => { |
||||
|
let service: UploadService; |
||||
|
|
||||
|
beforeEach(async () => { |
||||
|
const module: TestingModule = await Test.createTestingModule({ |
||||
|
providers: [UploadService], |
||||
|
}).compile(); |
||||
|
|
||||
|
service = module.get<UploadService>(UploadService); |
||||
|
}); |
||||
|
|
||||
|
it('should be defined', () => { |
||||
|
expect(service).toBeDefined(); |
||||
|
}); |
||||
|
}); |
||||
@ -0,0 +1,83 @@ |
|||||
|
import { Injectable } from '@nestjs/common'; |
||||
|
import { RacersService } from 'src/racers/racers.service'; |
||||
|
import { RaceResultsService } from 'src/race-results/race-results.service'; |
||||
|
import { RacesService } from 'src/races/races.service'; |
||||
|
import { SeasonStandingsService } from 'src/season-standings/season-standings.service'; |
||||
|
|
||||
|
const AdvancableBuffer = require('../utilities/advanceable-buffer'); |
||||
|
const gbxHeader = require('../trackmania-replays/gbx-header'); |
||||
|
const gbxReplay = require('../trackmania-replays/gbx-replay'); |
||||
|
|
||||
|
const fs = require('fs'); |
||||
|
|
||||
|
|
||||
|
@Injectable() |
||||
|
export class UploadService { |
||||
|
|
||||
|
constructor( |
||||
|
private racersService: RacersService, |
||||
|
private racesService: RacesService, |
||||
|
private raceResultsService: RaceResultsService, |
||||
|
private seasonStandingsService: SeasonStandingsService |
||||
|
) |
||||
|
{} |
||||
|
|
||||
|
async replayUploaded(file: Express.Multer.File, body: any) { |
||||
|
console.log(file.path) |
||||
|
|
||||
|
let buffer = fs.readFileSync(file.path) |
||||
|
console.log(buffer) |
||||
|
let buff = new AdvancableBuffer(buffer); |
||||
|
let header = new gbxHeader(); |
||||
|
header.parse(buff); |
||||
|
if (header.is_vaild == false) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
console.log(header); |
||||
|
let replay = new gbxReplay(); |
||||
|
replay.parse(buff); |
||||
|
|
||||
|
let currentRacer = await this.racersService.findOrCreate(replay.gamerHandle); |
||||
|
console.log(currentRacer); |
||||
|
|
||||
|
let race = await this.racesService.findOneBySeasonAndMapUID(body.seasonId, replay.mapUID) |
||||
|
console.log(race); |
||||
|
|
||||
|
let result = await this.raceResultsService.create(race.id, currentRacer.id, replay.bestTime, file.path); |
||||
|
console.log(result); |
||||
|
|
||||
|
this.seasonStandingsService.updateStandings(body.seasonId); |
||||
|
/* |
||||
|
fs.readFile(file.path, async function(err, buffer) |
||||
|
{ |
||||
|
console.log(err) |
||||
|
console.log(buffer) |
||||
|
let buff = new AdvancableBuffer(buffer); |
||||
|
let header = new gbxHeader(); |
||||
|
header.parse(buff); |
||||
|
if (header.is_vaild == false) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
console.log(header); |
||||
|
let replay = new gbxReplay(); |
||||
|
replay.parse(buff); |
||||
|
|
||||
|
let currentRacer = await this.racersService.findOrCreate(replay.gamerHandle); |
||||
|
console.log(currentRacer); |
||||
|
|
||||
|
let race = await this.racesService.findOne({season: body.seasonId, mapUID: replay.mapUID}) |
||||
|
console.log(race); |
||||
|
|
||||
|
let result = await this.raceResultsService.create({race: race, racer: currentRacer, timeInMilliseconds: replay.bestTime, replayPath: file.destination}); |
||||
|
console.log(result); |
||||
|
|
||||
|
this.seasonStandingsService.updateStandings(body.seasonId); |
||||
|
|
||||
|
//res.status(200);
|
||||
|
}); |
||||
|
*/ |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
.img-thumbnail{ |
||||
|
width: 400px; |
||||
|
} |
||||
@ -1,9 +1,11 @@ |
|||||
|
import { Race } from "./race.model"; |
||||
|
|
||||
export class Season { |
export class Season { |
||||
id: string = "0"; |
id: string = "0"; |
||||
title: string = ""; |
title: string = ""; |
||||
subTitle: string = ""; |
subTitle: string = ""; |
||||
startingDate: Date = new Date(Date.now()); |
startingDate: Date = new Date(Date.now()); |
||||
races: string[] = []; |
races: Race[] = []; |
||||
racers: string[] = []; |
racers: string[] = []; |
||||
standings: string[] = []; |
standings: string[] = []; |
||||
} |
} |
||||
Loading…
Reference in new issue