Skip to content

Commit

Permalink
Merge pull request #242 from Ibinola/feature/implement-tournament-system
Browse files Browse the repository at this point in the history
feature: implement tournament system
  • Loading branch information
Xaxxoo authored Feb 22, 2025
2 parents 87a2b34 + 3ffb2e0 commit 93ff24c
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 0 deletions.
37 changes: 37 additions & 0 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@nestjs/event-emitter": "^3.0.0",
"@nestjs/jwt": "^11.0.0",
"@nestjs/platform-express": "^11.0.5",
"@nestjs/schedule": "^5.0.1",
"@nestjs/platform-socket.io": "^11.0.10",
"@nestjs/swagger": "^11.0.3",
"@nestjs/typeorm": "^11.0.0",
Expand Down
5 changes: 5 additions & 0 deletions backend/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ import { GlobalInterceptor } from './interceptors/global.interceptor';
import { SongsModule } from './songs/songs.module';
import { ScoringModule } from './scoring/scoring.module';
import { ChatRoomModule } from './chat-room/chat-room.module';
import { TournamentService } from './tournament/tournament.service';
import { TournamentModule } from './tournament/tournament.module';
import { GameGateway,} from './websocket-game comms/providers/gamegateway';
import { GameModule } from './websocket-game comms/game.module';



@Module({
imports: [
AuthModule,
Expand All @@ -43,6 +46,7 @@ import { GameModule } from './websocket-game comms/game.module';
SongsModule,
ChatRoomModule,
ScoringModule,
TournamentModule,

],
controllers: [AppController],
Expand All @@ -56,6 +60,7 @@ import { GameModule } from './websocket-game comms/game.module';
provide: APP_INTERCEPTOR,
useClass: GlobalInterceptor,
},
TournamentService,
GameGateway,
],
})
Expand Down
26 changes: 26 additions & 0 deletions backend/src/tournament/scheduling.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Injectable } from '@nestjs/common';
import { GameSession } from 'src/game-session/game-session.entity';
import { Player } from '../player/player.entity';

@Injectable()
export class SchedulingService {
schedule(tournament: any): GameSession[] {
const participants: Player[] = tournament.participants;
const matches: GameSession[] = [];

for (let i = 0; i < participants.length; i++) {
for (let j = i + 1; j < participants.length; j++) {
const match = new GameSession();
match.players = [participants[i], participants[j]];
match.startTime = this.getMatchTime();
matches.push(match);
}
}

return matches;
}

private getMatchTime(): Date {
return new Date();
}
}
33 changes: 33 additions & 0 deletions backend/src/tournament/tournament.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {
Entity,
PrimaryGeneratedColumn,
Column,
ManyToMany,
OneToMany,
} from 'typeorm';
import { User } from '../user/user.entity';
import { GameSession } from '../game-session/game-session.entity';

@Entity()
export class Tournament {
@PrimaryGeneratedColumn('uuid')
id: string;

@Column()
name: string;

@Column('timestamp')
startTime: Date;

@Column('timestamp')
endTime: Date;

@Column('json', { nullable: true })
rules: Record<string, any>;

@ManyToMany(() => User, { eager: true })
participants: User[];

@OneToMany(() => GameSession, (gameSession) => gameSession)
matches: GameSession[];
}
13 changes: 13 additions & 0 deletions backend/src/tournament/tournament.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { TournamentService } from './tournament.service';
import { Tournament } from './tournament.entity';
import { User } from '../user/user.entity';
import { GameSession } from '../game-session/game-session.entity';

@Module({
imports: [TypeOrmModule.forFeature([Tournament, User, GameSession])],
providers: [TournamentService],
exports: [TournamentService],
})
export class TournamentModule {}
18 changes: 18 additions & 0 deletions backend/src/tournament/tournament.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { TournamentService } from './tournament.service';

describe('TournamentService', () => {
let service: TournamentService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [TournamentService],
}).compile();

service = module.get<TournamentService>(TournamentService);
});

it('should be defined', () => {
expect(service).toBeDefined();
});
});
80 changes: 80 additions & 0 deletions backend/src/tournament/tournament.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Tournament } from './tournament.entity';
import { Player } from '../player/player.entity';
import { GameSession } from 'src/game-session/game-session.entity';
import { SchedulingService } from './scheduling.service';

@Injectable()
export class TournamentService {
constructor(
@InjectRepository(Tournament)
private tournamentRepository: Repository<Tournament>,

@InjectRepository(Player)
private playerRepository: Repository<Player>,

@InjectRepository(GameSession)
private gameSessionRepository: Repository<GameSession>,

private schedulingService: SchedulingService,
) {}

async createTournament(
name: string,
startTime: Date,
endTime: Date,
rules: Record<string, any>,
participantIds: string[],
): Promise<Tournament> {
const participants = await this.playerRepository.find({
where: participantIds.map((id) => ({ id })),
});
const tournament = this.tournamentRepository.create({
name,
startTime,
endTime,
rules,
participants,
});
return this.tournamentRepository.save(tournament);
}

async scheduleMatches(tournamentId: string): Promise<GameSession[]> {
const tournament = await this.tournamentRepository.findOne({
where: { id: tournamentId },
relations: ['participants'],
});

if (!tournament) {
throw new Error('Tournament not found');
}

const matches = await this.schedulingService.schedule(tournament);
return this.gameSessionRepository.save(matches);
}

async applyScoring(tournamentId: string): Promise<void> {
const tournament = await this.tournamentRepository.findOne({
where: { id: tournamentId },
relations: ['matches'],
});

if (!tournament) {
throw new Error('Tournament not found');
}

tournament.matches.forEach((match) => {
this.applyMatchScoringRules(match);
});

await this.gameSessionRepository.save(tournament.matches);
}

private applyMatchScoringRules(match: GameSession) {
if (match.players.length === 2) {
const [player1, player2] = match.players;
}
}
}

0 comments on commit 93ff24c

Please sign in to comment.