25 changed files with 427 additions and 71 deletions
@ -1,4 +1,42 @@ |
|||
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() |
|||
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 { Racer } from './racer.model'; |
|||
import { InjectModel } from '@nestjs/sequelize'; |
|||
import { Sequelize } from 'sequelize-typescript'; |
|||
|
|||
@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 { RacesService } from './races.service'; |
|||
import { RaceResultsService } from 'src/race-results/race-results.service'; |
|||
|
|||
import * as TMIO from 'trackmania.io'; |
|||
import { AuthGuard } from 'src/auth/auth.guard'; |
|||
|
|||
@Controller('races') |
|||
export class RacesController { |
|||
TMIO: any; |
|||
|
|||
constructor() { |
|||
constructor( |
|||
private racesService: RacesService, |
|||
private raceResultsService: RaceResultsService |
|||
) { |
|||
this.TMIO = new TMIO.Client(); |
|||
} |
|||
|
|||
@Get('/map/:id') |
|||
@Get(':id') |
|||
findOne(@Param() params: any) { |
|||
let promise = new Promise((resolve, reject) => { |
|||
try{ |
|||
this.TMIO.maps.get(params.id).then(async mapInfo => { |
|||
console.log(mapInfo); |
|||
resolve(mapInfo._data); |
|||
}); |
|||
} catch (error) { |
|||
reject(error); |
|||
return this.racesService.findOne(params.id); |
|||
} |
|||
}); |
|||
return from(promise); |
|||
|
|||
@Get('/map/:id') |
|||
getMapInfo(@Param() params: any) { |
|||
return from(this.racesService.getMapDetails(params.id)); |
|||
} |
|||
|
|||
@Get(':id/results') |
|||
getResults(@Param() params: any) { |
|||
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 { 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() |
|||
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 { InjectModel } from '@nestjs/sequelize'; |
|||
import { SeasonStanding } from './season-standing.model'; |
|||
import { Sequelize } from 'sequelize-typescript'; |
|||
|
|||
@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 { |
|||
id: string = "0"; |
|||
title: string = ""; |
|||
subTitle: string = ""; |
|||
startingDate: Date = new Date(Date.now()); |
|||
races: string[] = []; |
|||
races: Race[] = []; |
|||
racers: string[] = []; |
|||
standings: string[] = []; |
|||
} |
|||
Loading…
Reference in new issue