Browse Source

WIP database structure

new_auth
Dan 2 years ago
parent
commit
2be79e6d99
  1. 4
      .gitignore
  2. BIN
      packages/bridge-server/data/data.db
  3. 21
      packages/bridge-server/src/app.module.ts
  4. 26
      packages/bridge-server/src/race-results/race-result.model.ts
  5. 11
      packages/bridge-server/src/race-results/race-results.module.ts
  6. 18
      packages/bridge-server/src/race-results/race-results.service.spec.ts
  7. 4
      packages/bridge-server/src/race-results/race-results.service.ts
  8. 14
      packages/bridge-server/src/racers/racer.model.ts
  9. 11
      packages/bridge-server/src/racers/racers.module.ts
  10. 18
      packages/bridge-server/src/racers/racers.service.spec.ts
  11. 4
      packages/bridge-server/src/racers/racers.service.ts
  12. 34
      packages/bridge-server/src/races/race.model.ts
  13. 11
      packages/bridge-server/src/races/races.module.ts
  14. 18
      packages/bridge-server/src/races/races.service.spec.ts
  15. 4
      packages/bridge-server/src/races/races.service.ts
  16. 23
      packages/bridge-server/src/season-standings/season-standing.model.ts
  17. 11
      packages/bridge-server/src/season-standings/season-standings.module.ts
  18. 18
      packages/bridge-server/src/season-standings/season-standings.service.spec.ts
  19. 4
      packages/bridge-server/src/season-standings/season-standings.service.ts
  20. 21
      packages/bridge-server/src/seasons/season.model.ts
  21. 13
      packages/bridge-server/src/seasons/seasons.module.ts
  22. 18
      packages/bridge-server/src/seasons/seasons.service.spec.ts
  23. 21
      packages/bridge-server/src/seasons/seasons.service.ts
  24. 78
      packages/bridge-server/src/trackmania-replays/gbx-header.ts
  25. 384
      packages/bridge-server/src/trackmania-replays/gbx-replay.ts
  26. 75
      packages/bridge-server/src/utilities/advanceable-buffer.ts

4
.gitignore

@ -1 +1,3 @@
node_modules/
node_modules/
packages/bridge-server/data/data.db
packages/bridge-server/upload

BIN
packages/bridge-server/data/data.db

Binary file not shown.

21
packages/bridge-server/src/app.module.ts

@ -2,6 +2,8 @@ import { MiddlewareConsumer, Module, RequestMethod } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { MulterModule } from '@nestjs/platform-express'
import { SequelizeModule } from '@nestjs/sequelize';
import { AuthModule } from './auth/auth.module';
import { UsersService } from './users/users.service';
@ -10,6 +12,15 @@ import { UsersModule } from './users/users.module';
import { LoggerMiddleware } from './auth/logger.middleware';
import { SeasonsController } from './seasons/seasons.controller';
import { UploadController } from './upload/upload.controller';
import { SeasonsModule } from './seasons/seasons.module';
import { RacersService } from './racers/racers.service';
import { RacesService } from './races/races.service';
import { SeasonStandingsService } from './season-standings/season-standings.service';
import { RaceResultsService } from './race-results/race-results.service';
import { RaceResultsModule } from './race-results/race-results.module';
import { RacesModule } from './races/races.module';
import { RacersModule } from './racers/racers.module';
import { SeasonStandingsModule } from './season-standings/season-standings.module';
@Module({
imports: [
@ -21,9 +32,17 @@ import { UploadController } from './upload/upload.controller';
}),
AuthModule,
UsersModule,
MulterModule.register({
dest: './upload',
}),
SeasonsModule,
RaceResultsModule,
RacesModule,
RacersModule,
SeasonStandingsModule,
],
controllers: [AppController, SeasonsController, UploadController],
providers: [AppService, UsersService],
providers: [AppService, UsersService, RacersService, RacesService, SeasonStandingsService, RaceResultsService],
})
export class AppModule {
configure(consumer: MiddlewareConsumer) {

26
packages/bridge-server/src/race-results/race-result.model.ts

@ -0,0 +1,26 @@
import { Column, Model, Table, HasMany, ForeignKey, BelongsTo } from "sequelize-typescript";
import { Racer } from "src/racers/racer.model";
import { Race } from "src/races/race.model";
@Table
export class RaceResult extends Model {
@ForeignKey(() => Race)
@Column
raceId: number;
@BelongsTo(() => Race)
race: Race
@ForeignKey(() => Racer)
@Column
racerId: number;
@BelongsTo(() => Racer)
racer: Racer
@Column
replayPath: string;
@Column
time: number;
}

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

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

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

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

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

@ -0,0 +1,4 @@
import { Injectable } from '@nestjs/common';
@Injectable()
export class RaceResultsService {}

14
packages/bridge-server/src/racers/racer.model.ts

@ -0,0 +1,14 @@
import { Column, Model, Table, HasMany } from "sequelize-typescript";
import { RaceResult } from "src/race-results/race-result.model";
@Table
export class Racer extends Model {
@Column
name: string;
@Column
gameHandle: string;
@HasMany(() => RaceResult)
results: RaceResult[];
}

11
packages/bridge-server/src/racers/racers.module.ts

@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';
import { SequelizeModule } from '@nestjs/sequelize';
import { Racer } from './racer.model';
import { RacersService } from './racers.service';
@Module({
imports: [SequelizeModule.forFeature([Racer])],
providers: [RacersService],
exports: [SequelizeModule, RacersService]
})
export class RacersModule {}

18
packages/bridge-server/src/racers/racers.service.spec.ts

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

4
packages/bridge-server/src/racers/racers.service.ts

@ -0,0 +1,4 @@
import { Injectable } from '@nestjs/common';
@Injectable()
export class RacersService {}

34
packages/bridge-server/src/races/race.model.ts

@ -0,0 +1,34 @@
import { Column, Model, Table, HasMany, HasOne, ForeignKey, BelongsTo } from "sequelize-typescript";
import { RaceResult } from "src/race-results/race-result.model";
import { Season } from "src/seasons/season.model";
@Table
export class Race extends Model {
@Column
mapName: string;
@Column
mapURL: string;
@Column
mapUID: string;
@Column
mapImgUrl: string;
@Column
startDate: Date;
@Column
endDate: Date;
@HasMany(() => RaceResult)
results: RaceResult[];
@ForeignKey(() => Season)
@Column
seasonId: number;
@BelongsTo(() => Season)
season: Season;
}

11
packages/bridge-server/src/races/races.module.ts

@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';
import { SequelizeModule } from '@nestjs/sequelize';
import { Race } from './race.model';
import { RacesService } from './races.service';
@Module({
imports: [SequelizeModule.forFeature([Race])],
providers: [RacesService],
exports: [SequelizeModule, RacesService]
})
export class RacesModule {}

18
packages/bridge-server/src/races/races.service.spec.ts

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

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

@ -0,0 +1,4 @@
import { Injectable } from '@nestjs/common';
@Injectable()
export class RacesService {}

23
packages/bridge-server/src/season-standings/season-standing.model.ts

@ -0,0 +1,23 @@
import { Column, Model, Table, HasMany, ForeignKey, BelongsTo } from "sequelize-typescript";
import { Racer } from "src/racers/racer.model";
import { Season } from "src/seasons/season.model";
@Table
export class SeasonStanding extends Model {
@ForeignKey(() => Season)
@Column
seasonId: number;
@BelongsTo(() => Season)
season: Season
@ForeignKey(() => Racer)
@Column
racerId: number;
@BelongsTo(() => Racer)
racer: Racer
@Column
points: number;
}

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

@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';
import { SequelizeModule } from '@nestjs/sequelize';
import { SeasonStanding } from './season-standing.model';
import { SeasonStandingsService } from './season-standings.service';
@Module({
imports: [SequelizeModule.forFeature([SeasonStanding])],
providers: [SeasonStandingsService],
exports: [SequelizeModule, SeasonStandingsService]
})
export class SeasonStandingsModule {}

18
packages/bridge-server/src/season-standings/season-standings.service.spec.ts

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

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

@ -0,0 +1,4 @@
import { Injectable } from '@nestjs/common';
@Injectable()
export class SeasonStandingsService {}

21
packages/bridge-server/src/seasons/season.model.ts

@ -0,0 +1,21 @@
import { Column, HasMany, Model, Table } from "sequelize-typescript";
import { Race } from "src/races/race.model";
import { SeasonStanding } from "src/season-standings/season-standing.model";
@Table
export class Season extends Model {
@Column
title: string;
@Column
subTitle: string;
@Column
startingDate: Date;
@HasMany(() => Race)
races: Race[]
@HasMany(() => SeasonStanding)
standings: SeasonStanding[];
}

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

@ -0,0 +1,13 @@
import { Module } from '@nestjs/common';
import { SequelizeModule } from '@nestjs/sequelize';
import { Season } from './season.model';
import { SeasonsController } from './seasons.controller';
import { SeasonsService } from './seasons.service';
@Module({
imports: [SequelizeModule.forFeature([Season])],
providers: [SeasonsService],
controllers: [SeasonsController],
exports: [SequelizeModule, SeasonsService]
})
export class SeasonsModule {}

18
packages/bridge-server/src/seasons/seasons.service.spec.ts

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

21
packages/bridge-server/src/seasons/seasons.service.ts

@ -0,0 +1,21 @@
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/sequelize';
import { Season } from './season.model';
//import { SeasonStanding } from 'src/season-standings/season-standing.model';
//import { Race } from 'src/races/race.model';
@Injectable()
export class SeasonsService {
constructor(
@InjectModel(Season) private seasonModel: typeof Season,
)
{}
async findAll() {
//return this.seasonModel.findAll();
}
async findOne(id: number) {
//return this.seasonModel.findOne({ where: {id: id}}/*, include:[Race, SeasonStanding] }*/)
}
}

78
packages/bridge-server/src/trackmania-replays/gbx-header.ts

@ -0,0 +1,78 @@
class gbxHeader {
has_magic = true
version = -1
format = -1
compressionofRefTable = -1
compressionofRefBody = -1
compressionTextFlag = ''
id = -1
userData = []
numNodes = 0
is_vaild = false
parse(buff)
{
let header_magic = buff.readString(3);
if (header_magic != 'GBX')
{
console.log("Header Magic Mismatch: " + header_magic);
return
}
this.has_magic = true
this.version = buff.readUInt16();
console.log(this.version)
if (this.version < 5 || this.version >7 )
{
console.log("Unsupported version")
return;
}
this.format = buff.readInt8();
if (this.format != 66)
{
console.log("Unsupported format")
return;
}
this.compressionofRefTable = buff.readInt8();
if (this.compressionofRefTable != 67 && this.compressionofRefTable != 85)
{
console.log("Unsupported compression format, Ref")
return;
}
this.compressionofRefBody = buff.readInt8();
if (this.compressionofRefBody != 67 && this.compressionofRefBody != 85)
{
console.log("Unsupported compression format, Body")
return;
}
this.compressionTextFlag = '';
if (this.version >= 4)
{
this.compressionTextFlag = buff.readString(1);
}
this.id = buff.readUInt32();
console.log(this.id)
if (this.version >=6)
{
this.userData = buff.readBytes();
}
this.numNodes = buff.readUInt32();
this.is_vaild = true
}
}
module.exports = gbxHeader;

384
packages/bridge-server/src/trackmania-replays/gbx-replay.ts

@ -0,0 +1,384 @@
interface ChunkInfo {
dwId: number;
dwSize: number;
dwOffset: number;
}
class gbxReplay {
CHUNKS_OFFSET = 17;
HEADER_OFFSET = 21;
UNASSIGNED = 0xFFFFFFFF;
mapUID = "";
environment = "";
author = "";
bestTime = this.UNASSIGNED;
gamerHandle = ""
login = ""
titleId = ""
calcChunkOffset(num) {
return (((num) * 8) + this.HEADER_OFFSET)
}
isNumber(id) { return (((id) & 0xC0000000) == 0)}
isString(id) { return (((id) & 0xC0000000) != 0)}
isUnassigned(id) {return ((id) == this.UNASSIGNED)}
getIndex(id) {return ((id) & 0x3FFFFFFF)}
parseReplayChunk(buff, chunkInfo) {
buff.seek(0+chunkInfo.dwOffset);
let version = buff.readUInt32();
let isVSK = version >= 9999 ? true : false;
let idList = { version: 0, index: 0, list:[]}
if( chunkInfo.dwSize <= 4) {
return;
}
if((!isVSK && version >= 3) || (isVSK && version >= 10000))
{
let result = this.readIdentifier(buff, idList);
if(result.read > 0)
{
this.mapUID = result.str;
console.log("MapUID:\t " + this.mapUID)
}
result = this.readIdentifier(buff, idList);
if(result.read > 0)
{
this.environment = result.str;
console.log("Environ:\t " + this.environment)
}
result = this.readIdentifier(buff, idList)
if (result.read > 0)
{
this.author = result.str;
console.log("Author:\t " + this.author)
}
this.bestTime = buff.readUInt32();
console.log("BestTime:\t " + this.bestTime);
result = buff.readNadeoString();
if (result.read > 0)
{
this.gamerHandle = result.str;
console.log("Gamer Handle:\t " + this.gamerHandle)
}
if((!isVSK && version >= 6) || (isVSK && version >= 10000))
{
result = buff.readNadeoString();
if (result.read > 0)
{
this.login = result.str;
console.log("Login:\t " + this.login)
}
if((!isVSK && version >= 8) || (isVSK && version >= 10000))
{
buff.seek(buff.readPos+1);
result = this.readIdentifier(buff, idList)
if (result.read > 0)
{
this.titleId = result.str;
console.log("titleId:\t " + this.titleId)
}
}
}
}
}
parseAuthorChunk(buff, chunkInfo) {
}
parseCommunityChunk(buff, chunkInfo) {
}
parse(buff)
{
buff.seek(0+this.CHUNKS_OFFSET);
let numChunks = buff.readUInt32();
if(numChunks == 0) {
return true;
}
else if (numChunks > 0xff) {
return false;
}
let chunkId, chunkSize = 0;
let chunkOffset = this.calcChunkOffset(numChunks)
let chunkVersion: ChunkInfo;
let chunkCommunity: ChunkInfo;
let chunkAuthor: ChunkInfo;
for (let counter = 1; counter <= numChunks; counter++) {
chunkId = buff.readUInt32();
chunkSize = buff.readUInt32();
chunkSize &= 0x7FFFFFFF;
switch (chunkId){
case 0x03093000: // (TM)
case 0x2403F000: // (VSK, TM)
chunkVersion.dwId = chunkId;
chunkVersion.dwSize = chunkSize;
chunkVersion.dwOffset = chunkOffset;
chunkOffset += chunkSize;
break;
case 0x03093001: // (TM)
case 0x2403F001: // (VSK, TM)
chunkCommunity.dwId = chunkId;
chunkCommunity.dwSize = chunkSize;
chunkCommunity.dwOffset = chunkOffset;
chunkOffset += chunkSize;
//OutputTextFmt(hwndCtl, szOutput, _countof(szOutput), g_szChunk, dwCouter, dwChunkId, dwChunkSize);
break;
case 0x03093002: // (MP)
chunkAuthor.dwId = chunkId;
chunkAuthor.dwSize = chunkSize;
chunkAuthor.dwOffset = chunkOffset;
chunkOffset += chunkSize;
//OutputTextFmt(hwndCtl, szOutput, _countof(szOutput), g_szChunk, dwCouter, dwChunkId, dwChunkSize);
break;
default:
chunkOffset += chunkSize;
//OutputTextFmt(hwndCtl, szOutput, _countof(szOutput), g_szChunk, dwCouter, dwChunkId, dwChunkSize);
}
}
if (chunkVersion.dwSize > 0) {
this.parseReplayChunk(buff, chunkVersion);
}
if (chunkCommunity.dwSize > 0) {
this.parseCommunityChunk(buff, chunkCommunity);
}
if (chunkAuthor.dwSize > 0) {
this.parseAuthorChunk(buff, chunkAuthor);
}
}
readIdentifier(buff, idList)
{
if ( idList.version < 3 )
{
idList.version = buff.readUInt32();
if (idList.version < 2)
{
return {read:-1, str:""};
}
}
let id = buff.readUInt32();
if(this.isUnassigned(id))
{
return {read:0, str:""};
}
if(this.isNumber(id))
{
return this.getCollectionString(id);
}
if(idList.version == 2)
{
return buff.readNadeoString();
}
if(this.isString(id) && this.getIndex(id) == 0)
{
let result = buff.readNadeoString();
if (result.read > 0 && idList.index < 8)
{
idList.list[idList.index] = result.str;
idList.index++;
}
return result;
}
let index = this.getIndex(id);
if( index == 0 || index > 8)
{
return {read:0, str:""};
}
let latest = idList.list[idList.index-1];
return {read:latest.length, str:latest};
}
getCollectionString(id)
{
let outString = ""
switch (id)
{
case 0: // Speed
outString = "Desert";
break;
case 1: // Alpine
outString = "Snow";
break;
case 2: // Rally
outString = "Rally";
break;
case 3: // Island
outString = "Island";
break;
case 4: // Bay
outString = "Bay";
break;
case 5: // Coast
outString = "Coast";
break;
case 6: // StadiumMP4
outString = "Stadium";
break;
case 7: // Basic
outString = "Basic";
break;
case 8: // Plain
outString = "Plain";
break;
case 9: // Moon
outString = "Moon";
break;
case 10: // Toy
outString = "Toy";
break;
case 11: // Valley
outString = "Valley";
break;
case 12: // Canyon
outString = "Canyon";
break;
case 13: // Lagoon
outString = "Lagoon";
break;
case 14: // Deprecated_Arena
outString = "Arena";
break;
case 15: // TMTest8
outString = "TMTest8";
break;
case 16: // TMTest9
outString = "TMTest9";
break;
case 17: // TMCommon
outString = "TMCommon";
break;
case 18: // Canyon4
outString = "Canyon4";
break;
case 19: // Canyon256
outString = "Canyon256";
break;
case 20: // Valley4
outString = "Valley4";
break;
case 21: // Valley256
outString = "Valley256";
break;
case 22: // Lagoon4
outString = "Lagoon4";
break;
case 23: // Lagoon256
outString = "Lagoon256";
break;
case 24: // Stadium4
outString = "Stadium4";
break;
case 25: // Stadium256
outString = "Stadium256";
break;
case 26: // Stadium
outString = "Stadium";
break;
case 27: // Voxel
outString = "Voxel";
break;
case 100: // History
outString = "History";
break;
case 101: // Society
outString = "Society";
break;
case 102: // Galaxy
outString = "Galaxy";
break;
case 103: // QMTest1
outString = "QMTest1";
break;
case 104: // QMTest2
outString = "QMTest2";
break;
case 105: // QMTest3
outString = "QMTest3";
break;
case 200: // Gothic
outString = "Gothic";
break;
case 201: // Paris
outString = "Paris";
break;
case 202: // Storm
outString = "Storm";
break;
case 203: // Cryo
outString = "Cryo";
break;
case 204: // Meteor
outString = "Meteor";
break;
case 205: // Meteor4
outString = "Meteor4";
break;
case 206: // Meteor256
outString = "Meteor256";
break;
case 207: // SMTest3
outString = "SMTest3";
break;
case 299: // SMCommon
outString = "SMCommon";
break;
case 10000: // Vehicles
outString = "Vehicles";
break;
case 10001: // Orbital
outString = "Orbital";
break;
case 10002: // Actors
outString = "Actors";
break;
case 10003: // Common
outString = "Common";
break;
case this.UNASSIGNED:
outString = "_Unassigned";
break;
default:
{
return {read:0, str:""};
}
}
return {read:outString.length, str:outString}
}
}
module.exports = gbxReplay;

75
packages/bridge-server/src/utilities/advanceable-buffer.ts

@ -0,0 +1,75 @@
class NadeoStringResult {
read: number;
str: string;
}
class Advancablebuffer {
readPos: number = 0;
internalBuffer: Buffer;
littleEndian: boolean = true
constructor(buffer: Buffer, useBigEndian: boolean)
{
this.internalBuffer = buffer;
this.readPos = 0;
this.littleEndian = !useBigEndian;
}
seek(seekPos: number): void
{
this.readPos = seekPos
}
readString(numBytes: number): string
{
let t = this.internalBuffer.subarray(this.readPos, this.readPos+=numBytes);
return t.toString();
}
readInt8(): number
{
let value = this.internalBuffer.readInt8(this.readPos);
this.readPos += 1;
return value;
}
readUInt16(): number
{
let value = this.littleEndian ? this.internalBuffer.readUInt16LE(this.readPos) : this.internalBuffer.readUInt16BE(this.readPos);
this.readPos += 2;
return value;
}
readUInt32(): number
{
let value = this.littleEndian ? this.internalBuffer.readUInt32LE(this.readPos) : this.internalBuffer.readUInt32BE(this.readPos);
this.readPos += 4;
return value;
}
readBytes(): Buffer
{
let length = this.readUInt32()
let sub = this.internalBuffer.subarray(this.readPos, this.readPos+=length);
return sub;
}
readNadeoString(): NadeoStringResult
{
let length = this.readUInt32()
if(length >= 0xFFFF)
{
return {read:-1, str:""};
}
if (length == 0)
{
return {read:0, str:""};
}
let outString = this.readString(length);
return {read:outString.length, str:outString};
}
}
module.exports = {Advancablebuffer, NadeoStringResult};
Loading…
Cancel
Save