# Build a Reusable Football Tournament Management Package

I want you to build a **production-ready, reusable Python package** for managing football tournaments.

The package should be designed as a **standalone tournament engine/library**, not as a complete website. Its purpose is to provide reusable tournament-management logic that can later be integrated into different applications such as university systems, web applications, mobile applications, or REST APIs.

The package should be clean, modular, extensible, well-tested, documented, and easy for another developer to install and use.

---

# 1. Main Goal

Create a reusable package called:

`football-tournament`

The package should handle the core logic for:

* Creating tournaments
* Registering teams
* Managing stadiums
* Supporting multiple tournament formats
* Generating matches
* Scheduling matches
* Assigning stadiums
* Assigning dates and times
* Detecting scheduling conflicts
* Managing tournament rounds
* Generating league standings
* Generating knockout brackets
* Supporting group-stage tournaments
* Providing clean APIs that another application can consume

The package should contain the **business logic only**.

Do NOT build the frontend initially.

Do NOT build authentication initially.

Do NOT build user management initially.

Do NOT add unnecessary features such as player profiles, payments, notifications, chat, etc.

The package should focus on tournament management.

---

# 2. Technology

Use:

* Python 3.12+
* Modern Python type hints
* `pyproject.toml`
* Pydantic for data validation where appropriate
* pytest for testing
* Ruff for linting
* Black-compatible formatting
* mypy-compatible type checking where practical

The package should not depend on FastAPI.

FastAPI should be able to use this package later, but the package itself must remain framework-independent.

The package should also not require PostgreSQL or another database to work.

The core tournament engine should work independently using Python objects/data structures.

Later, persistence adapters can be added separately.

---

# 3. Package Architecture

Use a clean modular structure similar to:

```text
football-tournament/
│
├── pyproject.toml
├── README.md
├── LICENSE
├── .gitignore
│
├── src/
│   └── football_tournament/
│       │
│       ├── __init__.py
│       │
│       ├── models/
│       │   ├── __init__.py
│       │   ├── tournament.py
│       │   ├── team.py
│       │   ├── stadium.py
│       │   ├── match.py
│       │   ├── round.py
│       │   └── group.py
│       │
│       ├── enums/
│       │   ├── __init__.py
│       │   ├── tournament_format.py
│       │   ├── match_status.py
│       │   └── tournament_status.py
│       │
│       ├── formats/
│       │   ├── __init__.py
│       │   ├── base.py
│       │   ├── league.py
│       │   ├── knockout.py
│       │   └── group_knockout.py
│       │
│       ├── scheduling/
│       │   ├── __init__.py
│       │   ├── scheduler.py
│       │   ├── conflict.py
│       │   └── time_slot.py
│       │
│       ├── standings/
│       │   ├── __init__.py
│       │   └── calculator.py
│       │
│       ├── exceptions/
│       │   ├── __init__.py
│       │   └── errors.py
│       │
│       ├── engine.py
│       └── utils/
│           ├── __init__.py
│           └── ids.py
│
├── tests/
│   ├── test_tournament.py
│   ├── test_team.py
│   ├── test_stadium.py
│   ├── test_league.py
│   ├── test_knockout.py
│   ├── test_group_knockout.py
│   ├── test_scheduler.py
│   └── test_standings.py
│
└── examples/
    ├── league_example.py
    ├── knockout_example.py
    └── scheduling_example.py
```

You may adjust the structure if you have a better clean architecture, but keep the responsibilities separated.

---

# 4. Core Domain Models

Create the following core models.

## Tournament

A tournament should contain information such as:

```text
id
name
format
status
teams
stadiums
matches
created_at
```

Example:

```python
Tournament(
    name="ASTU Football Tournament",
    format=TournamentFormat.LEAGUE
)
```

---

# 5. Team

A team should contain:

```text
id
name
short_name (optional)
```

Example:

```python
Team(
    name="Software Engineering"
)
```

Teams should be uniquely identifiable.

Prevent duplicate teams inside the same tournament.

---

# 6. Stadium

A stadium should contain:

```text
id
name
location (optional)
capacity (optional)
```

Example:

```python
Stadium(
    name="ASTU Main Stadium",
    location="Adama"
)
```

The stadium should be assignable to matches.

---

# 7. Match

The Match model is one of the most important models in the system.

A match should contain:

```text
id
tournament_id
home_team
away_team
stadium
date
start_time
end_time
round
status
```

The match should be able to exist before it has been scheduled.

For example:

```text
Match
├── Home Team
├── Away Team
├── Stadium
├── Date
├── Start Time
├── End Time
├── Round
└── Status
```

Do not force a stadium/date/time during match generation.

Match generation and match scheduling should be separate operations.

---

# 8. Tournament Formats

The package must support at least these three formats:

## A. League / Table

Example:

```text
Team A
Team B
Team C
Team D
```

Generate a round-robin tournament.

Each team should play against every other team.

Support:

* single round-robin
* optional double round-robin

Example for 4 teams:

```text
A vs B
A vs C
A vs D
B vs C
B vs D
C vs D
```

The generator should not schedule the matches automatically.

It should only generate the match structure.

---

# 9. League Standings

Provide a standings calculator.

The standings should support:

```text
Played
Won
Drawn
Lost
Goals For
Goals Against
Goal Difference
Points
```

Default points:

```text
Win = 3
Draw = 1
Loss = 0
```

Make the points system configurable if practical.

Example:

```text
Team             P   W   D   L   GF   GA   GD   Pts
----------------------------------------------------
Software Eng.    3   2   1   0   7    3    4     7
Computer Sci.    3   2   0   1   5    4    1     6
Electrical       3   1   1   1   4    4    0     4
Civil            3   0   0   3   2    7   -5     0
```

Make the ranking rules configurable.

Default ranking can use:

1. Points
2. Goal difference
3. Goals scored

Do not hard-code this in a way that prevents future customization.

---

# 10. Knockout Format

Support knockout tournaments.

Example:

```text
Quarter Final
       ↓
Semi Final
       ↓
Final
```

For 8 teams:

```text
Quarter Final

A ─────┐
       ├── QF1 ──┐
B ─────┘         │
                 ├── SF1 ──┐
C ─────┐         │         │
       ├── QF2 ──┘         │
D ─────┘                   │
                           ├── FINAL
E ─────┐                   │
       ├── QF3 ──┐         │
F ─────┘         │         │
                 ├── SF2 ──┘
G ─────┐         │
       ├── QF4 ──┘
H ─────┘
```

Support:

* Round of 16
* Quarterfinal
* Semifinal
* Final

If the number of teams is not a power of two, support byes.

For example:

```text
5 teams
```

should be handled correctly rather than throwing an unnecessary error.

---

# 11. Group + Knockout Format

Support tournaments such as:

```text
Group A
--------
Team A
Team B
Team C
Team D

Group B
--------
Team E
Team F
Team G
Team H
```

Each group should have its own league/round-robin matches.

After the group stage:

```text
Group A
   ↓
Top teams

Group B
   ↓
Top teams

        ↓

Knockout Stage
```

The number of qualifying teams should be configurable.

For example:

```python
GroupKnockoutConfig(
    number_of_groups=2,
    teams_per_group=4,
    qualifiers_per_group=2
)
```

---

# 12. Scheduling System

Create a dedicated scheduling module.

The scheduler should allow a match to be assigned:

```text
Date
Start time
End time
Stadium
```

Example:

```python
scheduler.schedule_match(
    match_id=match.id,
    stadium=stadium,
    date=date,
    start_time=time,
    duration_minutes=90
)
```

---

# 13. Scheduling Conflict Detection

This is an important part of the package.

The scheduler must prevent:

### Stadium conflict

A stadium cannot host two matches at overlapping times.

Example:

```text
14:00 - Team A vs Team B
14:30 - Team C vs Team D
```

on the same stadium should be rejected.

---

### Team conflict

A team cannot play two matches at overlapping times.

Example:

```text
14:00
Team A vs Team B

14:30
Team A vs Team C
```

must be rejected.

---

### Invalid match

A team cannot play against itself:

```text
Team A vs Team A
```

must be rejected.

---

### Invalid scheduling

A match cannot have:

```text
end_time <= start_time
```

---

# 14. Time Slots

Create a reusable time-slot system.

For example:

```python
TimeSlot(
    date="2026-10-10",
    start_time="09:00",
    duration_minutes=90
)
```

Allow the application to configure:

```text
Tournament start date
Tournament end date

Daily starting time
Daily ending time

Match duration
Break between matches
Available weekdays
```

Example:

```python
SchedulingConfig(
    start_date=...,
    end_date=...,
    daily_start="09:00",
    daily_end="17:00",
    match_duration_minutes=90,
    break_minutes=30
)
```

---

# 15. Automatic Scheduling

In addition to manually scheduling a match, provide automatic scheduling.

Example:

```python
scheduler.auto_schedule(
    tournament=tournament,
    config=config
)
```

The scheduler should:

1. Find available dates.
2. Find available time slots.
3. Find available stadiums.
4. Check team conflicts.
5. Assign the first valid available slot.
6. Continue until all matches are scheduled.

Keep the scheduling algorithm modular so it can be replaced later with a more advanced algorithm.

---

# 16. Tournament Engine

Create a high-level engine that makes the package easy to use.

Example:

```python
engine = TournamentEngine()

tournament = engine.create_tournament(
    name="ASTU Football Tournament",
    format=TournamentFormat.LEAGUE
)

engine.add_team(tournament, team_a)
engine.add_team(tournament, team_b)

engine.add_stadium(tournament, stadium)

engine.generate_matches(tournament)

engine.schedule_matches(tournament)
```

The engine should coordinate the different components but should NOT contain all the implementation logic itself.

---

# 17. Clean Exceptions

Create custom exceptions.

For example:

```python
TournamentError
InvalidTournamentError
DuplicateTeamError
TeamConflictError
StadiumConflictError
InvalidMatchError
MatchNotFoundError
SchedulingError
UnsupportedFormatError
```

Use meaningful exceptions instead of generic `Exception`.

Example:

```python
raise StadiumConflictError(
    "Stadium Main Stadium is already booked from 14:00 to 15:30."
)
```

---

# 18. Validation

Validate all important domain rules.

Examples:

* Tournament name cannot be empty.
* Team name cannot be empty.
* Duplicate teams should not be allowed.
* A team cannot play itself.
* A match must belong to a tournament.
* A stadium cannot have overlapping matches.
* A team cannot have overlapping matches.
* Invalid dates/times should be rejected.
* Unsupported tournament formats should be rejected.

Use Pydantic or appropriate Python validation where useful.

---

# 19. Public API

Make the package easy to import.

A developer should be able to do:

```python
from football_tournament import (
    Tournament,
    Team,
    Stadium,
    Match,
    TournamentFormat,
    TournamentEngine,
)
```

Avoid requiring users to import deeply nested internal modules unless necessary.

---

# 20. Database Independence

The first version MUST NOT require a database.

Do not use:

```text
SQLAlchemy
SQLModel
PostgreSQL
SQLite
Supabase
Django ORM
```

inside the core package.

The core package should work entirely in memory.

Later we may create optional persistence adapters.

Possible future architecture:

```text
football-tournament
        │
        ├── Core Engine
        │
        ├── PostgreSQL Adapter
        │
        ├── JSON Adapter
        │
        └── API Adapter
```

But do not implement those unless needed for the first version.

---

# 21. FastAPI Integration

Do NOT make FastAPI part of the core package.

Instead, design the package so that a future FastAPI application can easily use it.

For example:

```python
from football_tournament import TournamentEngine

engine = TournamentEngine()

@app.post("/tournaments")
def create_tournament(...):
    return engine.create_tournament(...)
```

The package should therefore expose clean Python methods.

---

# 22. Testing

Write comprehensive pytest tests.

At minimum test:

### Tournament

* Create tournament
* Invalid tournament
* Duplicate tournament data

### Teams

* Add team
* Duplicate team
* Remove team
* Invalid team

### Stadiums

* Add stadium
* Duplicate stadium
* Remove stadium

### League

* Generate round-robin matches
* Verify every team plays every other team
* Verify no duplicate pairings
* Verify double round-robin if implemented

### Knockout

* Generate bracket
* Handle 4 teams
* Handle 8 teams
* Handle non-power-of-two teams
* Handle byes
* Generate correct rounds

### Groups

* Create groups
* Assign teams
* Generate group matches
* Determine qualifiers
* Generate knockout stage

### Scheduling

* Schedule match
* Detect stadium conflict
* Detect team conflict
* Detect invalid time
* Automatic scheduling
* Multiple stadiums
* Multiple dates

### Standings

* Calculate wins
* Calculate draws
* Calculate losses
* Calculate points
* Calculate goal difference
* Sort standings

Aim for high test coverage.

---

# 23. Documentation

Create a professional `README.md`.

It should include:

## Installation

```bash
pip install football-tournament
```

## Quick Start

Show a complete example:

```python
from football_tournament import (
    Tournament,
    Team,
    Stadium,
    TournamentFormat,
)

tournament = Tournament(
    name="University Football Tournament",
    format=TournamentFormat.LEAGUE,
)

teams = [
    Team(name="Team A"),
    Team(name="Team B"),
    Team(name="Team C"),
    Team(name="Team D"),
]

for team in teams:
    tournament.add_team(team)

stadium = Stadium(name="Main Stadium")
tournament.add_stadium(stadium)

tournament.generate_matches()
```

Then show how to schedule a match.

---

# 24. Examples

Create executable examples in:

```text
examples/
```

Include:

```text
league_example.py
knockout_example.py
group_knockout_example.py
scheduling_example.py
standings_example.py
```

These should demonstrate how developers are expected to use the package.

---

# 25. Code Quality

Follow these principles:

* SOLID principles
* Single responsibility
* Composition over unnecessary inheritance
* Clear naming
* Type hints
* Small functions
* No duplicated logic
* No giant classes
* No unnecessary abstractions
* No global mutable state
* No hard-coded tournament rules
* No hidden side effects

Keep the implementation understandable for a developer who is new to the package.

---

# 26. Extensibility

Design the tournament-format system so that new formats can be added later.

For example:

```text
formats/
    base.py
    league.py
    knockout.py
    group_knockout.py
```

The base interface could be something like:

```python
class TournamentFormat:
    def generate_matches(...):
        ...
```

A future developer should be able to add:

```text
Swiss System
Double Elimination
Round Robin + Playoffs
Custom Tournament
```

without rewriting the entire package.

---

# 27. Match Result Support

Implement the minimum structure needed for match results.

A match should eventually support:

```text
home_score
away_score
```

and:

```python
match.set_result(
    home_score=2,
    away_score=1
)
```

This should update standings when standings are calculated.

For knockout tournaments, the system should be able to determine the winner.

Do NOT implement detailed player statistics yet.

---

# 28. Tournament Lifecycle

Support basic tournament states:

```text
DRAFT
REGISTRATION
SCHEDULED
ONGOING
COMPLETED
CANCELLED
```

Example:

```python
tournament.status
```

Validate operations based on status where appropriate.

For example, avoid allowing arbitrary team registration after the tournament has started.

Keep these rules configurable where practical.

---

# 29. IDs and Dates

Use safe unique identifiers for domain objects.

Prefer UUIDs unless there is a strong reason to use another approach.

Use timezone-aware datetime objects where date/time is involved.

Avoid storing dates and times as arbitrary strings internally.

---

# 30. Important Design Rule

Do NOT mix these responsibilities:

```text
Match Generation
≠
Match Scheduling
≠
Match Result Calculation
≠
Standings Calculation
≠
Presentation
```

They should be separate components.

The architecture should look conceptually like:

```text
                    Tournament
                        │
        ┌───────────────┼────────────────┐
        ↓               ↓                ↓
      Teams          Stadiums          Format
                                          │
                         ┌────────────────┼──────────────┐
                         ↓                ↓              ↓
                      League          Knockout       Groups
                         │                │              │
                         └────────────────┼──────────────┘
                                          ↓
                                       Matches
                                          │
                                          ↓
                                      Scheduler
                                          │
                                          ↓
                                   Scheduled Matches
                                          │
                                          ↓
                                      Results
                                          │
                         ┌────────────────┴──────────────┐
                         ↓                               ↓
                    Standings                         Bracket
```

---

# 31. First Implementation Phase

Do not try to implement everything at once.

Build the project in phases.

## Phase 1 — Foundation

Implement:

* Project structure
* `pyproject.toml`
* Models
* Enums
* Exceptions
* Basic validation
* Package exports

Make sure this works first.

## Phase 2 — League

Implement:

* League format
* Round-robin generation
* Match creation
* Results
* Standings

## Phase 3 — Knockout

Implement:

* Knockout bracket
* Rounds
* Byes
* Winners
* Progression

## Phase 4 — Groups

Implement:

* Groups
* Group assignment
* Group matches
* Group standings
* Qualifiers
* Knockout generation

## Phase 5 — Scheduling

Implement:

* Time slots
* Stadium assignment
* Team conflict detection
* Stadium conflict detection
* Manual scheduling
* Automatic scheduling

## Phase 6 — Quality

Implement:

* Tests
* Documentation
* Examples
* Ruff
* Type checking
* Packaging

---

# 32. Important Instruction

Before writing code:

1. Analyze the requirements.
2. Propose the final architecture.
3. Explain the responsibilities of each module.
4. Identify potential design problems.
5. Then implement the project.

Do not create unnecessary features.

Do not create a frontend.

Do not create authentication.

Do not create a database layer.

Do not create FastAPI routes yet.

The goal is to create a **clean, reusable football tournament engine/package** that can later be used by a FastAPI backend or another application.

After implementation, demonstrate the package with a complete example:

```text
Create tournament
        ↓
Register 8 teams
        ↓
Add 2 stadiums
        ↓
Select tournament format
        ↓
Generate matches
        ↓
Automatically schedule matches
        ↓
Enter match results
        ↓
Calculate standings / advance knockout teams
        ↓
Display final tournament state
```

Make sure the final project can actually run from a fresh environment and that all tests pass.

At the end, provide:

1. Project structure
2. Installation instructions
3. Usage examples
4. Testing instructions
5. Explanation of the architecture
6. Explanation of how to integrate the package into FastAPI later
7. Instructions for building the package
8. Instructions for publishing it to PyPI later
