123df671f5
Reviewed-on: #5 Co-authored-by: David Gwilliam <dhgwilliam@gmail.com> Co-committed-by: David Gwilliam <dhgwilliam@gmail.com>
532 lines
12 KiB
Markdown
532 lines
12 KiB
Markdown
# EuchreCamp
|
|
|
|
A comprehensive tournament management and partnership analytics system for the card game Euchre.
|
|
|
|
## Overview
|
|
|
|
EuchreCamp is a full-stack web application built with Next.js 14+ and TypeScript that provides:
|
|
|
|
- **Tournament Management**: Create and manage round-robin, single elimination, double elimination, and Swiss-style tournaments
|
|
- **Partnership Analytics**: Track partnership performance, win rates, and Elo changes between players
|
|
- **Player Profiles**: Display individual player statistics and partnership breakdowns
|
|
- **Admin Dashboard**: Centralized management interface for tournaments, players, and matches
|
|
- **Authentication & Authorization**: Role-based access control with player, tournament_admin, and club_admin roles
|
|
|
|
## Quick Start
|
|
|
|
### Prerequisites
|
|
|
|
- Node.js 20+ (managed by mise or nvm)
|
|
- SQLite3
|
|
|
|
### Installation
|
|
|
|
1. **Clone the repository:**
|
|
|
|
```bash
|
|
git clone <repository-url>
|
|
cd euchre_camp
|
|
```
|
|
|
|
2. **Install dependencies:**
|
|
|
|
```bash
|
|
npm install
|
|
```
|
|
|
|
3. **Set up the database:**
|
|
|
|
```bash
|
|
npx prisma migrate deploy
|
|
npx prisma generate
|
|
```
|
|
|
|
4. **Start the development server:**
|
|
|
|
```bash
|
|
npm run dev
|
|
```
|
|
|
|
### Accessing the Application
|
|
|
|
- **Main Page**: http://localhost:3000
|
|
- **Admin Dashboard**: http://localhost:3000/admin
|
|
- **Rankings**: http://localhost:3000/rankings
|
|
- **Login**: http://localhost:3000/auth/login
|
|
- **Registration**: http://localhost:3000/auth/register
|
|
|
|
## Development
|
|
|
|
### Project Structure
|
|
|
|
```
|
|
euchre_camp/
|
|
├── src/
|
|
│ ├── app/ # Next.js App Router pages and routes
|
|
│ │ ├── auth/ # Authentication pages (login, register)
|
|
│ │ ├── admin/ # Admin dashboard and management
|
|
│ │ ├── players/ # Player profiles and schedules
|
|
│ │ ├── rankings/ # Player rankings page
|
|
│ │ └── api/ # API routes
|
|
│ ├── components/ # React components
|
|
│ ├── lib/ # Utilities and configurations
|
|
│ │ ├── auth.ts # Better Auth configuration
|
|
│ │ ├── prisma.ts # Prisma client
|
|
│ │ └── auth-client.ts
|
|
│ └── __tests__/ # Vitest and Playwright tests
|
|
├── prisma/
|
|
│ └── schema.prisma # Database schema
|
|
├── public/ # Static assets
|
|
└── package.json # Dependencies and scripts
|
|
```
|
|
|
|
### Running the Application
|
|
|
|
**Development mode (with auto-reload):**
|
|
|
|
```bash
|
|
npm run dev
|
|
```
|
|
|
|
**Production mode:**
|
|
|
|
```bash
|
|
npm run build
|
|
npm start
|
|
```
|
|
|
|
### Database Management
|
|
|
|
**Run migrations:**
|
|
|
|
```bash
|
|
npx prisma migrate deploy
|
|
```
|
|
|
|
**Generate Prisma client:**
|
|
|
|
```bash
|
|
npx prisma generate
|
|
```
|
|
|
|
**Reset database:**
|
|
|
|
```bash
|
|
npx prisma migrate reset
|
|
```
|
|
|
|
**Open Prisma Studio:**
|
|
|
|
```bash
|
|
npx prisma studio
|
|
```
|
|
|
|
### Testing
|
|
|
|
**Run unit tests:**
|
|
|
|
```bash
|
|
npm run test
|
|
```
|
|
|
|
**Run unit tests in watch mode:**
|
|
|
|
```bash
|
|
npm run test:run
|
|
```
|
|
|
|
**Run acceptance tests:**
|
|
|
|
```bash
|
|
npm run test:acceptance
|
|
```
|
|
|
|
**Run acceptance tests in headed mode:**
|
|
|
|
```bash
|
|
npm run test:acceptance:headed
|
|
```
|
|
|
|
**Test with Playwright MCP (browser automation):**
|
|
|
|
1. Start the development server: `npm run dev`
|
|
2. Use opencode with Playwright MCP tools to:
|
|
- Navigate to pages
|
|
- Take screenshots
|
|
- Test responsive layouts
|
|
- Verify mobile UI elements
|
|
|
|
### Assets
|
|
|
|
**CSS is handled by Tailwind CSS** with automatic compilation during development.
|
|
|
|
## Features
|
|
|
|
### Tournament Management
|
|
|
|
#### Creating a Tournament
|
|
|
|
1. Navigate to Admin Dashboard (`/admin`)
|
|
2. Click "Create Tournament"
|
|
3. Enter tournament details:
|
|
- Name
|
|
- Format (round-robin, single elimination, double elimination, Swiss)
|
|
- Number of teams/players
|
|
4. Register participants
|
|
5. Generate schedule
|
|
6. Record match results
|
|
|
|
#### Tournament Formats
|
|
|
|
- **Round-Robin**: Each team plays every other team once
|
|
- **Single Elimination**: Lose once and you're out
|
|
- **Double Elimination**: Must lose twice to be eliminated
|
|
- **Swiss**: Pairings based on win-loss records
|
|
|
|
### Partnership Analytics
|
|
|
|
#### Tracking Partnerships
|
|
|
|
The system automatically tracks:
|
|
- Games played together
|
|
- Win/loss records
|
|
- Elo changes per partnership
|
|
- Partnership win rates
|
|
|
|
#### Viewing Partnership Data
|
|
|
|
1. Visit any player's profile page (`/players/:id/profile`)
|
|
2. Scroll to "Partnership Performance" section
|
|
3. View statistics for each partner
|
|
|
|
### Player Profiles
|
|
|
|
Each player profile displays:
|
|
- Current Elo rating
|
|
- Total games played
|
|
- Win rate
|
|
- Partnership statistics
|
|
- Recent games timeline
|
|
|
|
### Admin Dashboard
|
|
|
|
The admin dashboard provides:
|
|
- Quick statistics (total players, active tournaments, recent matches)
|
|
- Quick action buttons for common tasks
|
|
- Recent matches table
|
|
- Links to all admin sections
|
|
|
|
## Authentication & Authorization
|
|
|
|
### User Roles
|
|
|
|
| Role | Permissions |
|
|
|------|-------------|
|
|
| **Player** | Edit own profile, record own matches within 5 minutes |
|
|
| **Tournament Admin** | Create/manage tournaments, edit matches in their tournaments (no time limit) |
|
|
| **Club Admin** | Full access to edit/delete any record, manage all players and tournaments |
|
|
|
|
### Login/Logout
|
|
|
|
**Login:**
|
|
- Navigate to `/login`
|
|
- Enter email and password
|
|
- Click "Login"
|
|
|
|
**Logout:**
|
|
- Click "Logout" in navigation bar
|
|
|
|
### Admin User Creation
|
|
|
|
To create an admin user, use the provided script:
|
|
|
|
```bash
|
|
node scripts/create-admin.js <email> <password>
|
|
```
|
|
|
|
**Example:**
|
|
```bash
|
|
node scripts/create-admin.js admin@example.com mypassword
|
|
```
|
|
|
|
This will:
|
|
1. Create a player profile
|
|
2. Create a user account with `club_admin` role
|
|
3. Mark the account as confirmed
|
|
|
|
**Using Better Auth CLI:**
|
|
|
|
```bash
|
|
npx better-auth cli
|
|
```
|
|
|
|
## API Reference
|
|
|
|
### Routes
|
|
|
|
#### Public Routes
|
|
- `GET /` - Redirects to rankings
|
|
- `GET /rankings` - Player rankings
|
|
- `GET /players/:id` - Player profile
|
|
- `GET /players/:id/profile` - Player profile with partnerships
|
|
- `GET /players/:id/schedule` - Player tournament schedule
|
|
|
|
#### Authentication Routes
|
|
- `GET /login` - Login form
|
|
- `POST /auth/login` - Process login
|
|
- `GET /logout` - Logout and clear session
|
|
|
|
#### Admin Routes (Require Authentication)
|
|
- `GET /admin` - Admin dashboard
|
|
- `GET /admin/players` - List all players
|
|
- `GET /admin/players/new` - Add new player form
|
|
- `POST /admin/players` - Create new player
|
|
- `GET /admin/players/:id/edit` - Edit player form
|
|
- `PATCH /admin/players/:id` - Update player
|
|
- `DELETE /admin/players/:id` - Delete player
|
|
- `GET /admin/matches` - List all matches
|
|
- `GET /admin/matches/new` - Record match form
|
|
- `POST /admin/matches` - Create match
|
|
- `GET /admin/matches/:id/edit` - Edit match form
|
|
- `PATCH /admin/matches/:id` - Update match
|
|
- `GET /admin/matches/upload` - CSV upload form
|
|
- `POST /admin/matches/process_upload` - Process CSV upload
|
|
- `GET /admin/tournaments` - List all tournaments
|
|
- `GET /admin/tournaments/new` - Create tournament form
|
|
- `POST /admin/tournaments` - Create tournament
|
|
- `GET /admin/tournaments/:id` - Tournament details
|
|
- `GET /admin/tournaments/:id/edit` - Edit tournament form
|
|
- `PATCH /admin/tournaments/:id` - Update tournament
|
|
- `DELETE /admin/tournaments/:id` - Delete tournament
|
|
- `POST /admin/tournaments/:id/participants` - Add participant
|
|
- `DELETE /admin/tournaments/:id/participants/:player_id` - Remove participant
|
|
- `POST /admin/tournaments/:id/teams` - Create team
|
|
- `GET /admin/tournaments/:id/teams/:team_id/edit` - Edit team form
|
|
- `PATCH /admin/tournaments/:id/teams/:team_id` - Update team
|
|
- `DELETE /admin/tournaments/:id/teams/:team_id` - Delete team
|
|
- `POST /admin/tournaments/:id/schedule` - Generate schedule
|
|
- `GET /admin/tournaments/:id/rounds/:round_id` - View round matchups
|
|
- `GET /admin/tournaments/:id/results` - Tournament results
|
|
- `POST /admin/tournaments/:id/results` - Save results
|
|
- `POST /admin/tournaments/:id/complete` - Complete tournament
|
|
|
|
## Database Schema
|
|
|
|
### Tables
|
|
|
|
- **players**: Player information and ratings
|
|
- **users**: Authentication and authorization
|
|
- **events**: Tournaments and events
|
|
- **event_participants**: Player participation in tournaments
|
|
- **teams**: Teams in tournaments
|
|
- **tournament_rounds**: Tournament rounds
|
|
- **bracket_matchups**: Matchups per round
|
|
- **matches**: Individual match results
|
|
- **elo_snapshots**: Elo rating history
|
|
- **partnership_games**: Partnership occurrence tracking
|
|
- **partnership_stats**: Aggregated partnership statistics
|
|
|
|
## Common Tasks
|
|
|
|
### Adding a New Player
|
|
|
|
1. Navigate to Admin Dashboard
|
|
2. Click "Add Player"
|
|
3. Enter name and initial rating (default 1000)
|
|
4. Click "Create Player"
|
|
|
|
### Recording a Match
|
|
|
|
1. Navigate to Admin Dashboard
|
|
2. Click "Record Match Result"
|
|
3. Select players for Team 1 and Team 2
|
|
4. Enter scores
|
|
5. Click "Create Match"
|
|
|
|
### Creating a Tournament
|
|
|
|
1. Navigate to Admin Dashboard
|
|
2. Click "Create Tournament"
|
|
3. Enter tournament details
|
|
4. Register participants
|
|
5. Generate schedule
|
|
6. Start recording results
|
|
|
|
### Editing a Match
|
|
|
|
**Within 5 minutes (any user):**
|
|
1. Navigate to `/admin/matches`
|
|
2. Click "Edit" next to the match
|
|
3. Update scores
|
|
4. Click "Update Match"
|
|
|
|
**Anytime (tournament admin or club admin):**
|
|
- Same process as above, no time restriction
|
|
|
|
## Troubleshooting
|
|
|
|
### Common Issues
|
|
|
|
**Server won't start:**
|
|
- Check if port 3000 is already in use: `lsof -i :3000`
|
|
- Kill existing process: `kill -9 <PID>`
|
|
- Try a different port: `bundle exec puma -p 3001`
|
|
|
|
**CSS not loading:**
|
|
- Recompile assets: `./node_modules/.bin/esbuild app/assets/css/app.css --bundle --outfile=public/assets/app-GVDAEYEC.css`
|
|
- Clear browser cache
|
|
|
|
**Database errors:**
|
|
- Run migrations: `bundle exec rake db:migrate`
|
|
- Reset database: `bundle exec rake db:reset`
|
|
|
|
**Authorization errors:**
|
|
- Ensure you're logged in
|
|
- Check user role in database
|
|
|
|
### Debugging
|
|
|
|
**Check server logs:**
|
|
|
|
```bash
|
|
tail -f /tmp/puma.log
|
|
```
|
|
|
|
**Check database:**
|
|
|
|
```bash
|
|
sqlite3 db/euchre_camp.db
|
|
sqlite> .tables
|
|
sqlite> SELECT * FROM users;
|
|
```
|
|
|
|
## Development Workflow
|
|
|
|
### Making Changes
|
|
|
|
1. Create a feature branch: `git checkout -b feature/your-feature`
|
|
2. Make changes to code
|
|
3. Run tests: `npm run test` (unit tests) or `npm run test:acceptance` (acceptance tests)
|
|
4. Commit with conventional commit message
|
|
5. Push to remote: `git push origin feature/your-feature`
|
|
6. Create pull request
|
|
|
|
### Commit Message Format
|
|
|
|
```
|
|
<type>: <description>
|
|
|
|
[optional body]
|
|
|
|
[optional footer]
|
|
```
|
|
|
|
Types:
|
|
- `feat`: New feature
|
|
- `fix`: Bug fix
|
|
- `docs`: Documentation changes
|
|
- `style`: Code style changes
|
|
- `refactor`: Code refactoring
|
|
- `test`: Test changes
|
|
- `chore`: Build/dependency changes
|
|
|
|
### Code Style
|
|
|
|
- Follow existing code patterns in the project
|
|
- Use Prisma ORM for database access
|
|
- Keep business logic in lib/ directory
|
|
- Use React Server Components where appropriate
|
|
- Write unit tests (Vitest) and acceptance tests (Playwright) for new features
|
|
|
|
## Deployment
|
|
|
|
### Production Environment
|
|
|
|
1. **Set production environment variables:**
|
|
|
|
```bash
|
|
export NODE_ENV=production
|
|
export DATABASE_URL=file:./dev.db
|
|
export BETTER_AUTH_SECRET=<secure-random-string>
|
|
export BETTER_AUTH_URL=http://localhost:3000
|
|
```
|
|
|
|
2. **Build the application:**
|
|
|
|
```bash
|
|
npm run build
|
|
```
|
|
|
|
3. **Run migrations:**
|
|
|
|
```bash
|
|
npx prisma migrate deploy
|
|
```
|
|
|
|
4. **Start server:**
|
|
|
|
```bash
|
|
npm start
|
|
```
|
|
|
|
### Using a Process Manager
|
|
|
|
**Using systemd:**
|
|
|
|
```ini
|
|
[Unit]
|
|
Description=EuchreCamp
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=deploy
|
|
WorkingDirectory=/var/www/euchre_camp
|
|
Environment=NODE_ENV=production
|
|
ExecStart=/usr/local/bin/npm start
|
|
Restart=always
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
```
|
|
|
|
**Using PM2 (Node.js):**
|
|
|
|
```bash
|
|
pm2 start npm --name "euchre-camp" -- start
|
|
```
|
|
|
|
## Contributing
|
|
|
|
1. Fork the repository
|
|
2. Create a feature branch
|
|
3. Make your changes
|
|
4. Run tests to ensure they pass
|
|
5. Submit a pull request
|
|
|
|
## License
|
|
|
|
MIT License - see LICENSE file for details
|
|
|
|
## Credits
|
|
|
|
Built with:
|
|
- Next.js 14+ (App Router)
|
|
- TypeScript
|
|
- Tailwind CSS
|
|
- Prisma ORM
|
|
- Better Auth
|
|
- Vitest
|
|
- Playwright
|
|
|
|
## Additional Resources
|
|
|
|
- [Next.js Documentation](https://nextjs.org/docs)
|
|
- [TypeScript Documentation](https://www.typescriptlang.org/docs/)
|
|
- [Tailwind CSS Documentation](https://tailwindcss.com/docs)
|
|
- [Prisma Documentation](https://www.prisma.io/docs)
|
|
- [Better Auth Documentation](https://better-auth.com/docs)
|
|
- [Vitest Documentation](https://vitest.dev/)
|
|
- [Playwright Documentation](https://playwright.dev/)
|
|
- [Euchre Rules](https://www.pagat.com/euchre/euchre.html)
|