2026-04-01 11:47:03 +04:00
|
|
|
# Datwyler Shooting Event System
|
|
|
|
|
|
|
|
|
|
Production-ready full-stack web app based on your original live score concept.
|
|
|
|
|
|
|
|
|
|
## Stack
|
|
|
|
|
|
|
|
|
|
- Frontend: Vue 3 + Vite (pnpm)
|
|
|
|
|
- Backend: Go + Echo
|
|
|
|
|
- Database: SQLite
|
|
|
|
|
- Packaging: Single Docker image (frontend + backend)
|
|
|
|
|
|
|
|
|
|
## Main Features
|
|
|
|
|
|
|
|
|
|
- Bilingual UI: Arabic and English
|
|
|
|
|
- Runtime RTL/LTR switching
|
|
|
|
|
- Admin avatar crop/fit tool (drag + zoom before saving)
|
|
|
|
|
- AI score advisor for proof images (Gemini-powered suggestion + optional apply)
|
|
|
|
|
- Two clean modes:
|
|
|
|
|
- View Only screen for players/coaches/audience
|
|
|
|
|
- Admin Control Panel (login required)
|
|
|
|
|
- Admin credentials (default):
|
|
|
|
|
- Username: `datwyler`
|
|
|
|
|
- Password: `datwyler`
|
|
|
|
|
|
|
|
|
|
## Tournament Flow Implemented
|
|
|
|
|
|
|
|
|
|
1. Admin registers players and assigns groups (no hard 6-player limit).
|
|
|
|
|
2. View screen shows group assignment clearly.
|
|
|
|
|
3. Admin enters preliminary scores.
|
|
|
|
|
4. Overall ranking auto-calculates and highlights top 12 finalists.
|
|
|
|
|
5. If rank #12 cutoff is tied, qualification tie-break stage appears.
|
|
|
|
|
6. Top 12 split into final groups (1-6 and 7-12 seeds).
|
|
|
|
|
7. Admin enters final scores.
|
|
|
|
|
8. Podium is determined automatically.
|
|
|
|
|
9. If top-3 tie exists, podium tie-break stage appears.
|
|
|
|
|
|
|
|
|
|
## API Highlights
|
|
|
|
|
|
|
|
|
|
Public:
|
|
|
|
|
|
|
|
|
|
- `GET /api/health`
|
|
|
|
|
- `GET /api/state`
|
|
|
|
|
|
|
|
|
|
Admin:
|
|
|
|
|
|
|
|
|
|
- `POST /api/admin/login`
|
|
|
|
|
- `POST /api/admin/logout`
|
|
|
|
|
- `POST /api/admin/players`
|
|
|
|
|
- `PUT /api/admin/players/:id`
|
|
|
|
|
- `DELETE /api/admin/players/:id`
|
|
|
|
|
- `PUT /api/admin/scores/:stage/:id`
|
|
|
|
|
- `POST /api/admin/scores/:stage/:id/advice`
|
|
|
|
|
- `POST /api/admin/scores/:stage/reset`
|
|
|
|
|
|
|
|
|
|
Stages:
|
|
|
|
|
|
|
|
|
|
- `preliminary`
|
|
|
|
|
- `prelim_tiebreak`
|
|
|
|
|
- `final`
|
|
|
|
|
- `final_tiebreak`
|
|
|
|
|
|
|
|
|
|
## Local Development
|
|
|
|
|
|
|
|
|
|
Install dependencies:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
make install
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Run backend + frontend together:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
make dev
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Notes:
|
|
|
|
|
|
|
|
|
|
- Backend dev port is `18081`.
|
|
|
|
|
- Frontend runs on `5173` (or next free port, e.g. `5174` if busy).
|
|
|
|
|
- Frontend proxy is configured so `/api/*` works from Vite dev server.
|
|
|
|
|
|
|
|
|
|
Run individually:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
make dev-backend
|
|
|
|
|
make dev-frontend
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Build
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
make build
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
This builds frontend assets, copies them into backend `web/`, and compiles backend binary.
|
|
|
|
|
|
|
|
|
|
## Docker
|
|
|
|
|
|
|
|
|
|
Build image:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
make docker-build ARCH=amd64
|
|
|
|
|
# or
|
|
|
|
|
make docker-build ARCH=arm64
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Run image:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
make docker-run ARCH=amd64
|
|
|
|
|
# or
|
|
|
|
|
make docker-run ARCH=arm64
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Docker Compose (Production)
|
|
|
|
|
|
|
|
|
|
1. Copy environment template:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
cp .env.example .env
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
2. Edit `.env` for production credentials/tag.
|
|
|
|
|
|
|
|
|
|
3. Start service:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
docker compose up -d
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
4. Check health:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
docker compose ps
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
5. View logs:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
docker compose logs -f
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Runtime Environment Variables
|
|
|
|
|
|
|
|
|
|
- `PORT` (default `8080`)
|
|
|
|
|
- `DB_PATH` (default `./data/shooting.db`)
|
|
|
|
|
- `WEB_DIR` (default `./web`)
|
|
|
|
|
- `ADMIN_USER` (default `datwyler`)
|
|
|
|
|
- `ADMIN_PASS` (default `datwyler`)
|
|
|
|
|
- `GEMINI_API_KEY` (required for AI score advisor)
|
|
|
|
|
- `GEMINI_MODEL` (default `gemini-2.0-flash`)
|