Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions .agent/rules/website.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
---
trigger: always_on
---

# Agent Guide - Website Relaunch

This repository is a monorepo containing multiple services. Please follow these guidelines when working on this codebase.

## Project Structure

- `api/` - NestJS API service (TypeScript)
- `frontend/` - Next.js frontend application (TypeScript)
- `github-service/` - NestJS service for GitHub integration (TypeScript)
- `k8s-service/` - Kubernetes management service (Go)

## 1. Build, Lint, and Test Commands

### General

- Package Manager: `pnpm` is used for JavaScript/TypeScript projects.
- Go: Standard Go toolchain (1.23+) and `make`.

### `api/` & `github-service/` (NestJS)

- **Build:** `pnpm build` (Runs `nest build`)
- **Lint:** `pnpm lint` (Runs `eslint`)
- **Format:** `pnpm format` (Runs `prettier`)
- **Run Dev:** `pnpm start:dev`
- **Test:** `pnpm test` (Runs `jest`)
- **Run Single Test:**

```bash
# Run a specific test file
npx jest src/path/to/file.spec.ts

# Run a specific test case by name
pnpm test -- -t "should do something"
```

### `frontend/` (Next.js)

- **Build:** `pnpm build` (Runs `next build`)
- **Dev:** `pnpm dev`
- **Lint:** `pnpm lint`
- **Run Single Test:** (Assuming standard Jest/Vitest setup if present, otherwise rely on linting/build)
```bash
pnpm test -- path/to/file
```

### `k8s-service/` (Go)

- **Build:** `make build` (compiles to `bin/server`)
- **Run:** `make run`
- **Test:** `make test` (Runs `go test -v ./...`)
- **Run Single Test:**

```bash
# Run tests in a specific package
go test -v ./internal/package_name

# Run a specific test function
go test -v ./internal/package_name -run TestName
```

## 2. Code Style & Conventions

### TypeScript (NestJS & Next.js)

- **Formatting:** Use Prettier. 2 spaces indentation. Double quotes for strings and imports. Semicolons required.
- **Naming:**
- Variables/Functions: `camelCase`
- Classes/Interfaces/Components: `PascalCase`
- Files: `kebab-case.ts` (NestJS conventions), `PascalCase.tsx` (React components) or `page.tsx`/`layout.tsx` (Next.js App Router).
- **Imports:** Clean and organized. Remove unused imports.
- **Typing:** Strict TypeScript. Avoid `any` where possible. Use interfaces/types for DTOs and props.
- **NestJS Specifics:**
- Use Dependency Injection via constructors.
- Use Decorators (`@Injectable()`, `@Controller()`, `@Get()`) appropriately.
- Follow `module` -> `controller` -> `service` architecture.
- **Next.js Specifics:**
- Use App Router structure (`app/`).
- Mark Client Components with `"use client"` at the top.
- Use Tailwind CSS for styling.
- **UI Components:** ONLY use `shadcn/ui` components for building UIs. Do not introduce other UI libraries or create custom components if a `shadcn` equivalent exists. Check `components/ui` or `components.json` for available components.

### Go (`k8s-service`)

- **Formatting:** Standard `gofmt`.
- **Project Layout:** Follows Standard Go Project Layout (`cmd/`, `internal/`, `pkg/`).
- **Error Handling:**
- Return errors as the last return value.
- Check errors immediately: `if err != nil { return err }`.
- Don't panic unless during startup.
- **Logging:** Use `zap.SugaredLogger`.
- **Web Framework:** Uses `echo`.
- **Configuration:** Uses `internal/config` and environment variables.

## 3. General Rules for Agents

1. **Context is King:** Always analyze the surrounding code before making changes to match the existing style.
2. **Verify Changes:** Run the lint and test commands for the specific service you are modifying before declaring the task complete.
3. **Monorepo Awareness:** Be aware of which directory you are in. Do not run `npm` commands in the root if you intend to affect a specific service; `cd` into the service directory or use `pnpm --filter`.
4. **No Blind Edits:** Use `read` to check file contents before `edit` or `write`.
5. **Paths:** Always use absolute paths for file operations.
91 changes: 91 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Agent Guide - Website Relaunch

This repository is a monorepo containing multiple services. Please follow these guidelines when working on this codebase.

## Project Structure

- `api/` - NestJS API service (TypeScript)
- `frontend/` - Next.js frontend application (TypeScript)
- `github-service/` - NestJS service for GitHub integration (TypeScript)
- `k8s-service/` - Kubernetes management service (Go)

## 1. Build, Lint, and Test Commands

### General
- Package Manager: `pnpm` is used for JavaScript/TypeScript projects.
- Go: Standard Go toolchain (1.23+) and `make`.

### `api/` & `github-service/` (NestJS)
* **Build:** `pnpm build` (Runs `nest build`)
* **Lint:** `pnpm lint` (Runs `eslint`)
* **Format:** `pnpm format` (Runs `prettier`)
* **Run Dev:** `pnpm start:dev`
* **Test:** `pnpm test` (Runs `jest`)
* **Run Single Test:**
```bash
# Run a specific test file
npx jest src/path/to/file.spec.ts

# Run a specific test case by name
pnpm test -- -t "should do something"
```

### `frontend/` (Next.js)
* **Build:** `pnpm build` (Runs `next build`)
* **Dev:** `pnpm dev`
* **Lint:** `pnpm lint`
* **Run Single Test:** (Assuming standard Jest/Vitest setup if present, otherwise rely on linting/build)
```bash
pnpm test -- path/to/file
```

### `k8s-service/` (Go)
* **Build:** `make build` (compiles to `bin/server`)
* **Run:** `make run`
* **Test:** `make test` (Runs `go test -v ./...`)
* **Run Single Test:**
```bash
# Run tests in a specific package
go test -v ./internal/package_name

# Run a specific test function
go test -v ./internal/package_name -run TestName
```

## 2. Code Style & Conventions

### TypeScript (NestJS & Next.js)
* **Formatting:** Use Prettier. 2 spaces indentation. Double quotes for strings and imports. Semicolons required.
* **Naming:**
* Variables/Functions: `camelCase`
* Classes/Interfaces/Components: `PascalCase`
* Files: `kebab-case.ts` (NestJS conventions), `PascalCase.tsx` (React components) or `page.tsx`/`layout.tsx` (Next.js App Router).
* **Imports:** Clean and organized. Remove unused imports.
* **Typing:** Strict TypeScript. Avoid `any` where possible. Use interfaces/types for DTOs and props.
* **NestJS Specifics:**
* Use Dependency Injection via constructors.
* Use Decorators (`@Injectable()`, `@Controller()`, `@Get()`) appropriately.
* Follow `module` -> `controller` -> `service` architecture.
* **Next.js Specifics:**
* Use App Router structure (`app/`).
* Mark Client Components with `"use client"` at the top.
* Use Tailwind CSS for styling.
* **UI Components:** ONLY use `shadcn/ui` components for building UIs. Do not introduce other UI libraries or create custom components if a `shadcn` equivalent exists. Check `components/ui` or `components.json` for available components.

### Go (`k8s-service`)
* **Formatting:** Standard `gofmt`.
* **Project Layout:** Follows Standard Go Project Layout (`cmd/`, `internal/`, `pkg/`).
* **Error Handling:**
* Return errors as the last return value.
* Check errors immediately: `if err != nil { return err }`.
* Don't panic unless during startup.
* **Logging:** Use `zap.SugaredLogger`.
* **Web Framework:** Uses `echo`.
* **Configuration:** Uses `internal/config` and environment variables.

## 3. General Rules for Agents
1. **Context is King:** Always analyze the surrounding code before making changes to match the existing style.
2. **Verify Changes:** Run the lint and test commands for the specific service you are modifying before declaring the task complete.
3. **Monorepo Awareness:** Be aware of which directory you are in. Do not run `npm` commands in the root if you intend to affect a specific service; `cd` into the service directory or use `pnpm --filter`.
4. **No Blind Edits:** Use `read` to check file contents before `edit` or `write`.
5. **Paths:** Always use absolute paths for file operations.
67 changes: 67 additions & 0 deletions TOURNAMENT_LOGIC.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Tournament Logic Documentation

This document describes the scoring, advancement, and seeding logic used in the tournament system.

## 1. Swiss Phase (Group Phase)

The Swiss Phase is the initial part of the event where teams play a fixed number of rounds against opponents with similar records.

### Scoring and Ranking

- **Primary Score (`score`):** Teams receive **1 point** for each match win.
- **Secondary Score (Buchholz Points):** Used as a tie-breaker. A team's Buchholz points are calculated as the **sum of the current scores of all opponents that the team has defeated**.
- _Note: This is a modified Buchholz system that specifically rewards wins against stronger opponents._
- **Ranking Order:** Teams are ranked by:
1. `score` (Descending)
2. `buchholzPoints` (Descending)

### Round Generation

- **Number of Rounds:** The maximum number of Swiss rounds is calculated as `ceil(log2(N))`, where `N` is the number of teams.
- **Pairing Algorithm:** The system uses standard Swiss pairing, attempting to match teams with identical or similar scores while avoiding Repeat Matches (teams cannot play the same opponent twice in the Swiss phase).
- **Byes:** If there is an odd number of teams, one team receives a "Bye" each round. A Bye counts as a win (1 point). No team can receive more than one Bye during the Swiss phase.

---

## 2. Transition to Elimination Phase

Once the maximum number of Swiss rounds is completed, the system determines which teams advance to the final tournament bracket.

### Advancement Criteria

The system automatically advances the top teams based on the Swiss rankings. The number of teams selected is the **highest power of two** that is less than or equal to the total number of teams ($2^{\lfloor \log_2(N) \rfloor}$).

- _Example 1:_ If there are 12 teams, the top **8** teams advance.
- _Example 2:_ If there are 16 teams, all **16** teams advance.
- _Example 3:_ If there are 20 teams, the top **16** teams advance.

---

## 3. Elimination Phase (Tournament Phase)

The Elimination Phase is a single-elimination bracket.

### Initial Layout (Seeding)

The initial matches (Round 0) are generated based on the final Swiss rankings (Seed 0 is the 1st ranked team, Seed 1 is the 2nd, etc.).

The seeding follows a "Snake" pairing logic to ensure high-seeded teams are distributed across the bracket and don't meet until later rounds. For $N$ advancing teams, the pairings are:

| Match | Pairing (Seeds) | Sum of Seeds |
| :---------- | :------------------- | :----------- |
| Match 1 | Seed 0 vs Seed $N-1$ | $N-1$ |
| Match 2 | Seed 2 vs Seed $N-3$ | $N-1$ |
| Match 3 | Seed 4 vs Seed $N-5$ | $N-1$ |
| ... | ... | ... |
| Match $N/2$ | Seed $N-2$ vs Seed 1 | $N-1$ |

**Example for 8 Teams:**

- Match 1: Seed 0 vs Seed 7 (1st vs 8th)
- Match 2: Seed 2 vs Seed 5 (3rd vs 6th)
- Match 3: Seed 4 vs Seed 3 (5th vs 4th)
- Match 4: Seed 6 vs Seed 1 (7th vs 2nd)

### Bracket Progression

The winners of Match 1 and Match 2 meet in the next round. The winners of Match 3 and Match 4 meet in the next round. This ensures that the 1st and 2nd seeds (Seed 0 and Seed 1) are in opposite halves of the bracket and can only meet in the final.
59 changes: 32 additions & 27 deletions api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ Main backend API service for the CORE game website.

This NestJS service serves as the primary backend, handling:

* User authentication and management
* Team and event/tournament management
* Match results and statistics
* Database operations (PostgreSQL)
* RabbitMQ microservice communication
- User authentication and management
- Team and event/tournament management
- Match results and statistics
- Database operations (PostgreSQL)
- RabbitMQ microservice communication

## Getting Started

Expand Down Expand Up @@ -58,42 +58,47 @@ brew install pnpm

### Production

* **Build:** `pnpm build`
* **Start:** `pnpm start:prod`
- **Build:** `pnpm build`
- **Start:** `pnpm start:prod`

## Environment Variables

### Database (Required)

* `DB_HOST` - PostgreSQL host
* `DB_PORT` - PostgreSQL port
* `DB_USER` - Database username
* `DB_PASSWORD` - Database password
* `DB_NAME` - Database name
* `DB_SCHEMA` - Database schema
* `DB_URL` - Alternative database connection URL overwrites the other database connection variables
* `DB_SSL_REQUIRED` - Enable SSL connection (true/false)
- `DB_HOST` - PostgreSQL host
- `DB_PORT` - PostgreSQL port
- `DB_USER` - Database username
- `DB_PASSWORD` - Database password
- `DB_NAME` - Database name
- `DB_SCHEMA` - Database schema
- `DB_URL` - Alternative database connection URL overwrites the other database connection variables
- `DB_SSL_REQUIRED` - Enable SSL connection (true/false)

### External Services (Required)

* `RABBITMQ_URL` - RabbitMQ connection URL
* `API_SECRET_ENCRYPTION_KEY` - Key for encrypting sensitive data
- `RABBITMQ_URL` - RabbitMQ connection URL
- `API_SECRET_ENCRYPTION_KEY` - Key for encrypting sensitive data

### Optional

* `PORT` - Server port (default: 4000)
* `NODE_ENV` - Environment (development/production)
- `PORT` - Server port (default: 4000)
- `NODE_ENV` - Environment (development/production)

## Database Management

### Migrations

* **Generate:** `pnpm migration:generate migration_name`
- **Generate:** `pnpm migration:generate migration_name`
Compares your current TypeScript entities with the database and automatically generates the necessary SQL (e.g., adding or removing columns). **Use this for most schema changes.**
* **Create:** `pnpm migration:create migration_name`
- **Create:** `pnpm migration:create migration_name`
Creates an empty migration template. **Use this only for manual SQL changes** (e.g., seeding data, creating complex views, or custom indexes) that TypeORM cannot detect automatically.
* **Run:** `pnpm migration:run-local` (local) / `pnpm migration:run` (production)
* **Revert:** `pnpm migration:revert-local` (local) / `pnpm migration:revert` (production)
- **Run:** `pnpm migration:run-local` (local) / `pnpm migration:run` (production)
- **Revert:** `pnpm migration:revert-local` (local) / `pnpm migration:revert` (production)

### Seeding

- **Seed Users and Teams:** `pnpm seed:users <eventId>`
Generates 90 users and 30 teams (3 members each) and assigns them to the specified event. This is useful for testing group phases and bracket logic.

## API Documentation

Expand All @@ -104,10 +109,10 @@ When running in development mode, Swagger documentation is available at:

This service runs as both:

* **REST API** - HTTP endpoints for frontend communication
* **Microservice** - RabbitMQ message consumer for:
* `game_results` - Match result processing
* `github-service-results` - GitHub operation results
- **REST API** - HTTP endpoints for frontend communication
- **Microservice** - RabbitMQ message consumer for:
- `game_results` - Match result processing
- `github-service-results` - GitHub operation results

## Environment Variables

Expand Down
3 changes: 2 additions & 1 deletion api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"migration:generate": "sh -c 'npm run typeorm:ts -- -d ./typeOrm.config.ts migration:generate ./db/migrations/\"$0\"'",
"migration:create": "sh -c 'npm run typeorm:ts -- migration:create ./db/migrations/\"$0\"'",
"migration:revert": "npm run typeorm -- -d ./dist/typeOrm.config.js migration:revert",
"migration:revert-local": "npm run typeorm:ts -- -d ./typeOrm.config.ts migration:revert"
"migration:revert-local": "npm run typeorm:ts -- -d ./typeOrm.config.ts migration:revert",
"seed:users": "ts-node -r tsconfig-paths/register src/scripts/seed-users-teams.ts"
},
"dependencies": {
"@nestjs/common": "^11.1.13",
Expand Down
2 changes: 1 addition & 1 deletion api/src/match/entites/match.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class MatchEntity {
round: number;

@ManyToOne(() => TeamEntity)
winner: TeamEntity;
winner: TeamEntity | null;

@Column({ type: "enum", enum: MatchPhase, default: MatchPhase.SWISS })
phase: MatchPhase;
Expand Down
Loading