Browse Source

Add ghost download

new_auth
Dan 2 years ago
parent
commit
c20e1fcfb3
  1. 18
      packages/bridge-server/src/race-results/race-results.controller.spec.ts
  2. 35
      packages/bridge-server/src/race-results/race-results.controller.ts
  3. 4
      packages/bridge-server/src/race-results/race-results.module.ts
  4. 9
      packages/bridge-server/src/race-results/race-results.service.ts
  5. 7
      packages/bridge-server/src/races/races.service.ts
  6. 8
      packages/bridge-server/src/season-standings/season-standings.module.ts
  7. 42
      packages/bridge-server/src/season-standings/season-standings.service.ts
  8. 9
      packages/bridge-server/src/seasons/seasons.controller.ts
  9. 6
      packages/bridge-server/src/seasons/seasons.module.ts
  10. 2
      packages/bridge-ui/src/app/components/race-details/race-details.component.html
  11. 2
      packages/bridge-ui/src/app/components/race-details/race-details.component.scss
  12. 47
      packages/bridge-ui/src/app/components/race-details/race-details.component.ts
  13. 1
      packages/bridge-ui/src/app/pages/season-details/season-details.component.html
  14. 10
      packages/bridge-ui/src/app/pages/season-details/season-details.component.ts
  15. 2
      packages/bridge-ui/src/app/services/auth.service.ts
  16. 7
      packages/bridge-ui/src/app/services/race-result.service.ts
  17. 8
      packages/bridge-ui/src/app/services/races.service.ts
  18. 2
      packages/bridge-ui/src/app/services/replays.service.ts
  19. 10
      packages/bridge-ui/src/app/services/seasons.service.ts

18
packages/bridge-server/src/race-results/race-results.controller.spec.ts

@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { RaceResultsController } from './race-results.controller';
describe('RaceResultsController', () => {
let controller: RaceResultsController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [RaceResultsController],
}).compile();
controller = module.get<RaceResultsController>(RaceResultsController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});

35
packages/bridge-server/src/race-results/race-results.controller.ts

@ -0,0 +1,35 @@
import { Controller, Get, Header, Param, Res, StreamableFile } from '@nestjs/common';
import { createReadStream } from 'fs';
import { join } from 'path';
import type { Response } from 'express';
import { RaceResultsService } from './race-results.service';
@Controller('race-results')
export class RaceResultsController {
constructor(
private raceResultsService: RaceResultsService
)
{}
@Get(':id/ghost')
async getFile(@Param() params: any, @Res({ passthrough: true }) res: Response): Promise<StreamableFile> {
console.log(params);
let result = await this.raceResultsService.findOne(params.id);
const file = createReadStream(join(process.cwd(), result.replayPath));
res.set({
'Content-Type': 'application/json',
'Content-Disposition': 'attachment; filename="'+result.replayPath+'.gbx"',
});
return new StreamableFile(file);
}
@Get(':id/get-ghost')
async getGhostFile(@Param() params: any, @Res() res: Response) {
console.log(params);
let result = await this.raceResultsService.findOne(params.id);
const file = createReadStream(join(process.cwd(), result.replayPath));
file.pipe(res);
}
}

4
packages/bridge-server/src/race-results/race-results.module.ts

@ -2,10 +2,12 @@ import { Module } from '@nestjs/common';
import { SequelizeModule } from '@nestjs/sequelize';
import { RaceResult } from './race-result.model';
import { RaceResultsService } from './race-results.service';
import { RaceResultsController } from './race-results.controller';
@Module({
imports: [SequelizeModule.forFeature([RaceResult])],
providers: [RaceResultsService],
exports: [SequelizeModule, RaceResultsService]
exports: [SequelizeModule, RaceResultsService],
controllers: [RaceResultsController]
})
export class RaceResultsModule {}

9
packages/bridge-server/src/race-results/race-results.service.ts

@ -13,10 +13,17 @@ export class RaceResultsService {
)
{}
async findOne(id: number) {
return this.raceResultModel.findOne({
where: {id: id}
});
}
async getFastestTimesForRace(raceId: number) {
return this.raceResultModel.findAll({
attributes: { include: [[this.sequelize.fn('MIN', this.sequelize.col('time')), 'min_time']] },
where:{ raceId: raceId },
order: [['time', "ASC"]],
order: [['min_time', "ASC"]],
group:['racerId'],
include:[Racer]
});

7
packages/bridge-server/src/races/races.service.ts

@ -28,6 +28,13 @@ export class RacesService {
});
}
async findManyBySeason( seasonId: number) {
return this.raceModel.findAll({
where: { seasonId : seasonId },
include:[RaceResult]
})
}
async findOneBySeasonAndMapUID(seasonId: number, mapUID: string) {
return this.raceModel.findOne({ where: {seasonId: seasonId, mapUID: mapUID} })
}

8
packages/bridge-server/src/season-standings/season-standings.module.ts

@ -2,9 +2,15 @@ import { Module } from '@nestjs/common';
import { SequelizeModule } from '@nestjs/sequelize';
import { SeasonStanding } from './season-standing.model';
import { SeasonStandingsService } from './season-standings.service';
import { RaceResultsModule } from 'src/race-results/race-results.module';
import { RacesModule } from 'src/races/races.module';
@Module({
imports: [SequelizeModule.forFeature([SeasonStanding])],
imports: [
SequelizeModule.forFeature([SeasonStanding]),
RaceResultsModule,
RacesModule
],
providers: [SeasonStandingsService],
exports: [SequelizeModule, SeasonStandingsService]
})

42
packages/bridge-server/src/season-standings/season-standings.service.ts

@ -2,13 +2,17 @@ import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/sequelize';
import { SeasonStanding } from './season-standing.model';
import { Sequelize } from 'sequelize-typescript';
import { RaceResultsService } from 'src/race-results/race-results.service';
import { RacesService } from 'src/races/races.service';
@Injectable()
export class SeasonStandingsService {
constructor(
@InjectModel(SeasonStanding) private seasonStandingModel: typeof SeasonStanding,
private sequelize: Sequelize
private sequelize: Sequelize,
private raceResultsService: RaceResultsService,
private racesService: RacesService
)
{}
@ -30,7 +34,39 @@ export class SeasonStandingsService {
}
}
updateStandings(seasonId: number) {
async updateStandings(seasonId: number) {
let racesInSeason = await this.racesService.findManyBySeason(seasonId);
console.log(racesInSeason);
// find unique racers in this season
// for each race in the season
/*
if( this.race.racers == undefined) {
console.log("No racers in race-details")
return;
}
for( let racer_id of this.race?.racers ) {
this.racersService.getRacer(racer_id).subscribe( data => {
if(data != undefined) {
this.racers.set(racer_id, data);
}
});
this.raceResultService.getRaceResultsForRacerInRace(racer_id, this.race.id).subscribe( data => {
if(data != undefined) {
this.raceResults.set(racer_id, data);
let result = this.getBestTimeForRacer(racer_id);
if (result != undefined) {
this.sortedResults.push(result)
this.sortedResults.sort((a, b) => {
if( a.time == b.time ) { return 0 };
if( a.time < b.time ) { return -1};
return 1;
})
this.sortedResults = [...this.sortedResults];
}
}
});
}
*/
}
}

9
packages/bridge-server/src/seasons/seasons.controller.ts

@ -1,11 +1,13 @@
import { Body, Controller, Get, Param, Post, UseGuards } from '@nestjs/common';
import { SeasonsService } from './seasons.service';
import { SeasonStandingsService } from 'src/season-standings/season-standings.service';
import { AuthGuard } from 'src/auth/auth.guard';
@Controller('seasons')
export class SeasonsController {
constructor(
private seasonsService: SeasonsService
private seasonsService: SeasonsService,
private seasonStandingsService: SeasonStandingsService,
) {}
@Get()
@ -18,6 +20,11 @@ export class SeasonsController {
return this.seasonsService.findOne(params.id);
}
@Get(':id/refresh')
updateSeason(@Param() params: any) {
return this.seasonStandingsService.updateStandings(params.id);
}
@UseGuards(AuthGuard)
@Post()
create(@Body() body: any) {

6
packages/bridge-server/src/seasons/seasons.module.ts

@ -3,9 +3,13 @@ import { SequelizeModule } from '@nestjs/sequelize';
import { Season } from './season.model';
import { SeasonsController } from './seasons.controller';
import { SeasonsService } from './seasons.service';
import { SeasonStandingsModule } from 'src/season-standings/season-standings.module';
@Module({
imports: [SequelizeModule.forFeature([Season])],
imports: [
SequelizeModule.forFeature([Season]),
SeasonStandingsModule
],
providers: [SeasonsService],
controllers: [SeasonsController],
exports: [SequelizeModule, SeasonsService]

2
packages/bridge-ui/src/app/components/race-details/race-details.component.html

@ -29,7 +29,7 @@
<ng-container matColumnDef="ghost">
<th mat-header-cell *matHeaderCellDef>Ghost</th>
<td mat-cell *matCellDef="let element"> <button mat-raised-button color="accent"><mat-icon aria-hidden="false" aria-label="Example home icon" fontIcon="download"></mat-icon> Ghost</button> </td>
<td mat-cell *matCellDef="let element"> <button mat-raised-button color="accent" (click)="onClickDownloadGhost(element)"><mat-icon aria-hidden="false" aria-label="Example home icon" fontIcon="download"></mat-icon> Ghost</button> </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>

2
packages/bridge-ui/src/app/components/race-details/race-details.component.scss

@ -1,3 +1,3 @@
.img-thumbnail{
width: 400px;
width: 300px;
}

47
packages/bridge-ui/src/app/components/race-details/race-details.component.ts

@ -63,36 +63,6 @@ export class RaceDetailsComponent {
})
this.sortedResults = [...this.sortedResults];
})
/*
if( this.race.racers == undefined) {
console.log("No racers in race-details")
return;
}
for( let racer_id of this.race?.racers ) {
this.racersService.getRacer(racer_id).subscribe( data => {
if(data != undefined) {
this.racers.set(racer_id, data);
}
});
this.raceResultService.getRaceResultsForRacerInRace(racer_id, this.race.id).subscribe( data => {
if(data != undefined) {
this.raceResults.set(racer_id, data);
let result = this.getBestTimeForRacer(racer_id);
if (result != undefined) {
this.sortedResults.push(result)
this.sortedResults.sort((a, b) => {
if( a.time == b.time ) { return 0 };
if( a.time < b.time ) { return -1};
return 1;
})
this.sortedResults = [...this.sortedResults];
}
}
});
}
*/
}
getBestTimeForRacer(racer_id: string): RaceEntry | undefined {
@ -133,4 +103,21 @@ export class RaceDetailsComponent {
return ""
}
blob: Blob = new Blob();
onClickDownloadGhost(raceResult: any) {
console.log(raceResult)
this.raceResultService.getGhost(raceResult.id).subscribe(data => {
this.blob = new Blob([data as any], {type: 'application/octet-stream'});
console.log(this.blob);
var downloadURL = window.URL.createObjectURL(this.blob);
var link = document.createElement('a');
link.href = downloadURL;
link.download = this.race?.mapName + " - " + raceResult.racer.gameHandle + ".gbx";
link.click();
link.remove();
});
}
}

1
packages/bridge-ui/src/app/pages/season-details/season-details.component.html

@ -5,6 +5,7 @@
@if(isAuthed()) {
<button mat-raised-button color="warn" (click)="openNewRaceDialog(season.id)">New Race</button>
<button mat-raised-button color="warn" (click)="forceUpdate(season.id)">Update Season</button>
<mat-divider></mat-divider>
<br/>
}

10
packages/bridge-ui/src/app/pages/season-details/season-details.component.ts

@ -37,6 +37,8 @@ export class SeasonDetailsComponent {
season?: Season;
races: Race[] = [];
seasonId: string = "";
constructor(
private route: ActivatedRoute,
private seasonsService: SeasonsService,
@ -46,8 +48,8 @@ export class SeasonDetailsComponent {
) {}
ngOnInit() {
const id = String(this.route.snapshot.paramMap.get('id'));
this.seasonsService.getSeason(id).subscribe( data => {
this.seasonId = String(this.route.snapshot.paramMap.get('id'));
this.seasonsService.getSeason(this.seasonId).subscribe( data => {
this.season = data;
console.log(data);
if (this.season) {
@ -73,4 +75,8 @@ export class SeasonDetailsComponent {
data: { seasonId: id }
});
}
forceUpdate(id: string) {
this.seasonsService.updateSeason(this.seasonId);
}
}

2
packages/bridge-ui/src/app/services/auth.service.ts

@ -7,7 +7,7 @@ import { jwtDecode } from "jwt-decode";
providedIn: 'root'
})
export class AuthService {
serverEndpoint = "http://localhost:3000/"
serverEndpoint = "http://172.16.40.146:3000/"
constructor(private httpClient: HttpClient) { }

7
packages/bridge-ui/src/app/services/race-result.service.ts

@ -76,4 +76,11 @@ export class RaceResultService {
});
return from(promise);
}
getGhost(raceResultId: string) {
const httpOptions = {
responseType: 'blob' as 'json'
};
return this.httpClient.get("http://172.16.40.146:3000/race-results/"+raceResultId+"/get-ghost", httpOptions);
}
}

8
packages/bridge-ui/src/app/services/races.service.ts

@ -17,18 +17,18 @@ export class RacesService {
}
getRace(id: string) {
return this.httpClient.get("http://localhost:3000/races/"+id);
return this.httpClient.get("http://172.16.40.146:3000/races/"+id);
}
getRaceResults(id: string) {
return this.httpClient.get("http://localhost:3000/races/"+id+"/results");
return this.httpClient.get("http://172.16.40.146:3000/races/"+id+"/results");
}
getMapInfo(mapUID: string) {
return this.httpClient.get("http://localhost:3000/races/map/"+mapUID);
return this.httpClient.get("http://172.16.40.146:3000/races/map/"+mapUID);
}
create(mapUID: string, startDate: Date, endDate: Date, seasonId: number) {
return this.httpClient.post("http://localhost:3000/races", { mapUID: mapUID, startDate: startDate, endDate: endDate, seasonId: seasonId});
return this.httpClient.post("http://172.16.40.146:3000/races", { mapUID: mapUID, startDate: startDate, endDate: endDate, seasonId: seasonId});
}
}

2
packages/bridge-ui/src/app/services/replays.service.ts

@ -6,7 +6,7 @@ import { Observable } from "rxjs";
providedIn: 'root'
})
export class ReplaysService {
server_route: string = "http://localhost:3000/"
server_route: string = "http://172.16.40.146:3000/"
constructor(private httpClient: HttpClient) {
}

10
packages/bridge-ui/src/app/services/seasons.service.ts

@ -34,7 +34,7 @@ export class SeasonsService {
}
let promise = new Promise<Array<Season>>((resolve, reject) =>{
this.httpClient.get<Array<Season>>("http://localhost:3000/seasons/").subscribe(data => {
this.httpClient.get<Array<Season>>("http://172.16.40.146:3000/seasons/").subscribe(data => {
let seasons: Season[] = [];
for(let server_season of data) {
let _season = this.convertToClientSeason(server_season);
@ -65,7 +65,7 @@ export class SeasonsService {
}
let promise = new Promise<Season|undefined>((resolve, reject) =>{
this.httpClient.get<Array<Season>>("http://localhost:3000/seasons/"+id).subscribe(data => {
this.httpClient.get<Array<Season>>("http://172.16.40.146:3000/seasons/"+id).subscribe(data => {
let _season = this.convertToClientSeason(data);
console.log(data);
console.log(_season);
@ -76,6 +76,10 @@ export class SeasonsService {
}
create(title: string, subTitle: string, startingDate: Date) {
return this.httpClient.post("http://localhost:3000/seasons/", {title, subTitle, startingDate});
return this.httpClient.post("http://172.16.40.146:3000/seasons/", {title, subTitle, startingDate});
}
updateSeason(id: string) {
this.httpClient.get("http://172.16.40.146:3000/seasons/"+id+"/refresh").subscribe(data => { });
}
}

Loading…
Cancel
Save