# ed-donner/connect architecture

> Architecture diagram of the GitHub repository ed-donner/connect, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-11-12). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/ed-donner/connect
- Repository: https://github.com/ed-donner/connect

## Overview

Four-in-a-row Arena is a Gradio app for running Connect Four matches between LLMs. Users choose two models, start a game, and advance one move at a time or run the match; the app displays the board and players’ reasoning. Completed-game records support recent-game history and an ELO leaderboard. The main flow is visible in the excerpts; MongoDB and OpenRouter integrations are also explicit. Some UI callback details and record-persistence wiring are unsampled, so those links are included only where the shown source establishes them.

Main entry points: [`arena/c4.py`](https://github.com/ed-donner/connect/blob/main/arena/c4.py) (Gradio arena), [`arena/game.py`](https://github.com/ed-donner/connect/blob/main/arena/game.py) (Game coordinator), [`arena/board.py`](https://github.com/ed-donner/connect/blob/main/arena/board.py) (Game board), [`arena/player.py`](https://github.com/ed-donner/connect/blob/main/arena/player.py) (LLM player)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_interface["Arena interface"]
  node_entry["App entry<br/>[app.py]"]
  node_ui["Gradio arena<br/>[c4.py]"]
end

subgraph group_match["Match domain"]
  node_game["Game coordinator<br/>[game.py]"]
  node_board["Game board<br/>[board.py]"]
  node_render["Board renderer<br/>[board_view.py]"]
end

subgraph group_models["Model integration"]
  node_player["LLM player<br/>[player.py]"]
  node_llm["LLM adapter<br/>[llm.py]"]
end

subgraph group_history["History and ratings"]
  node_records["Game records<br/>[record.py]"]
end

node_user(("Arena user"))
node_openrouter{{"OpenRouter"}}
node_mongo[("MongoDB")]

node_user -->|"uses"| node_ui
node_entry -->|"creates display"| node_ui
node_ui -->|"starts and advances"| node_game
node_ui -.->|"reads history and ratings"| node_game
node_ui -->|"renders board state"| node_board
node_game -->|"creates and checks"| node_board
node_game -->|"delegates moves"| node_player
node_board -->|"converts to SVG"| node_render
node_player -->|"reads legal moves; applies move"| node_board
node_player -->|"requests structured move"| node_llm
node_llm -->|"sends model request"| node_openrouter
node_game -->|"records results; fetches stats"| node_records
node_records -->|"reads and writes"| node_mongo

click node_entry "https://github.com/ed-donner/connect/blob/main/app.py"
click node_ui "https://github.com/ed-donner/connect/blob/main/arena/c4.py"
click node_game "https://github.com/ed-donner/connect/blob/main/arena/game.py"
click node_board "https://github.com/ed-donner/connect/blob/main/arena/board.py"
click node_render "https://github.com/ed-donner/connect/blob/main/arena/board_view.py"
click node_player "https://github.com/ed-donner/connect/blob/main/arena/player.py"
click node_llm "https://github.com/ed-donner/connect/blob/main/arena/llm.py"
click node_records "https://github.com/ed-donner/connect/blob/main/arena/record.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_entry,node_ui,node_user toneBlue
class node_game,node_board,node_render,node_mongo toneAmber
class node_player,node_llm,node_openrouter toneMint
class node_records toneRose
```

## Components

### Arena interface

- [App entry](https://github.com/ed-donner/connect/blob/main/app.py): `app.py`
- [Gradio arena](https://github.com/ed-donner/connect/blob/main/arena/c4.py): `arena/c4.py`

### Match domain

- [Game coordinator](https://github.com/ed-donner/connect/blob/main/arena/game.py): `arena/game.py`
- [Game board](https://github.com/ed-donner/connect/blob/main/arena/board.py): `arena/board.py`
- [Board renderer](https://github.com/ed-donner/connect/blob/main/arena/board_view.py): `arena/board_view.py`

### Model integration

- [LLM player](https://github.com/ed-donner/connect/blob/main/arena/player.py): `arena/player.py`
- [LLM adapter](https://github.com/ed-donner/connect/blob/main/arena/llm.py): `arena/llm.py`

### History and ratings

- [Game records](https://github.com/ed-donner/connect/blob/main/arena/record.py): `arena/record.py`

### Other components

- **Arena user**
- **OpenRouter**
- **MongoDB**

## Connections

- Arena user → Gradio arena: uses (evidence: `README.md`)
- App entry → Gradio arena: creates display (evidence: `app.py`)
- Gradio arena → Game coordinator: starts and advances (evidence: `arena/c4.py`)
- Gradio arena → Game coordinator: reads history and ratings (evidence: `arena/c4.py`)
- Gradio arena → Game board: renders board state (evidence: `arena/c4.py`)
- Game coordinator → Game board: creates and checks (evidence: `arena/game.py`)
- Game coordinator → LLM player: delegates moves (evidence: `arena/game.py`)
- Game board → Board renderer: converts to SVG (evidence: `arena/board.py`)
- LLM player → Game board: reads legal moves; applies move (evidence: `arena/player.py`)
- LLM player → LLM adapter: requests structured move (evidence: `arena/player.py`)
- LLM adapter → OpenRouter: sends model request (evidence: `arena/llm.py`)
- Game coordinator → Game records: records results; fetches stats (evidence: `arena/game.py`)
- Game records → MongoDB: reads and writes (evidence: `arena/record.py`)
