# EuchreCamp A comprehensive tournament management and partnership analytics system for the card game Euchre. ## Overview EuchreCamp is a full-stack Ruby web application built with Hanami 2.1 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 - Ruby 3.3.3 (managed by mise or rbenv) - Node.js 22+ (for asset compilation) - SQLite3 - Bundler ### Installation 1. **Clone the repository:** ```bash git clone cd euchre_camp ``` 2. **Install dependencies:** ```bash bundle install npm install ``` 3. **Set up the database:** ```bash bundle exec rake db:migrate ``` 4. **Compile assets:** ```bash ./node_modules/.bin/esbuild app/assets/css/app.css --bundle --outfile=public/assets/app-GVDAEYEC.css ``` 5. **Start the server:** ```bash bundle exec puma -p 3000 -e development ``` ### Accessing the Application - **Main Page**: http://localhost:3000 - **Admin Dashboard**: http://localhost:3000/admin - **Rankings**: http://localhost:3000/rankings - **Login**: http://localhost:3000/login ## Development ### Project Structure ``` euchre_camp/ ├── app/ │ ├── actions/ # Hanami actions (controllers) │ ├── assets/ # CSS, JavaScript, images │ ├── repositories/ # ROM repositories for data access │ ├── services/ # Business logic (Elo calculator, partnership tracker) │ ├── templates/ # ERB view templates │ ├── views/ # Hanami view objects │ └── action.rb # Base action class with auth helpers ├── config/ │ ├── routes.rb # Application routes │ ├── app.rb # Hanami app configuration │ └── assets.js # Asset compilation configuration ├── db/ │ ├── migrate/ # Database migrations │ └── euchre_camp.db # SQLite database ├── lib/ │ └── euchre_camp/ # Domain models and entities ├── spec/ │ └── acceptance/ # RSpec acceptance tests └── public/ └── assets/ # Compiled assets ``` ### Running the Application **Development mode (with auto-reload):** ```bash bundle exec puma -p 3000 -e development ``` **Production mode:** ```bash bundle exec puma -p 3000 -e production ``` ### Database Management **Run migrations:** ```bash bundle exec rake db:migrate ``` **Rollback last migration:** ```bash bundle exec rake db:migrate[] ``` **Reset database:** ```bash bundle exec rake db:reset ``` ### Testing **Run all acceptance tests:** ```bash bundle exec rspec spec/acceptance/ ``` **Run specific test:** ```bash bundle exec rspec spec/acceptance/tournament_partnership_spec.rb:280 ``` **Run with documentation:** ```bash bundle exec rspec spec/acceptance/ --format documentation ``` **Run Playwright mobile responsiveness tests:** ```bash # Start the server bundle exec hanami server --port 2300 & # Run Playwright tests bundle exec rspec spec/playwright/mobile_responsiveness_spec.rb ``` **Test with Playwright MCP (browser automation):** 1. Start the Hanami server: `bundle exec hanami server --port 2300` 2. Use opencode with Playwright MCP tools to: - Navigate to pages - Take screenshots - Test responsive layouts - Verify mobile UI elements ### Assets **Compile CSS for development:** ```bash ./node_modules/.bin/esbuild app/assets/css/app.css --bundle --outfile=public/assets/app-GVDAEYEC.css ``` **Watch for changes (requires separate process):** ```bash ./node_modules/.bin/esbuild app/assets/css/app.css --bundle --outfile=public/assets/app-GVDAEYEC.css --watch ``` ## 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 ruby scripts/create_admin.rb ``` **Example:** ```bash ruby scripts/create_admin.rb david@dhg.lol admin ``` This will: 1. Create a player profile 2. Create a user account with `club_admin` role 3. Mark the account as confirmed **Manual SQL Alternative:** If you prefer to create users manually via SQL: 1. Access the database: `sqlite3 db/euchre_camp.db` 2. Generate a BCrypt password hash: ```bash ruby -e "require 'bcrypt'; puts BCrypt::Password.create('your_password')" ``` 3. Insert a user record: ```sql INSERT INTO players (name, rating) VALUES ('PlayerName', 1000); INSERT INTO users (player_id, email, password_digest, role, confirmed, created_at, updated_at) VALUES (1, 'user@example.com', '$2b$12$...', 'club_admin', 1, datetime('now'), datetime('now')); ``` ## 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 ` - 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: `bundle exec rspec spec/acceptance/` 4. Commit with conventional commit message 5. Push to remote: `git push origin feature/your-feature` 6. Create pull request ### Commit Message Format ``` : [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 ROM (Ruby Object Mapper) for database access - Keep business logic in services - Use dependency injection in actions - Write acceptance tests for new features ## Deployment ### Production Environment 1. **Set production environment variables:** ```bash export HANAMI_ENV=production export DATABASE_URL=sqlite:///path/to/prod.db export SESSION_SECRET= ``` 2. **Compile assets for production:** ```bash ./node_modules/.bin/esbuild app/assets/css/app.css --bundle --outfile=public/assets/app-GVDAEYEC.css ``` 3. **Run migrations:** ```bash bundle exec rake db:migrate ``` 4. **Start server:** ```bash bundle exec puma -p 3000 -e production ``` ### Using a Process Manager **Using systemd:** ```ini [Unit] Description=EuchreCamp After=network.target [Service] Type=simple User=deploy WorkingDirectory=/var/www/euchre_camp Environment=HANAMI_ENV=production ExecStart=/usr/local/bin/bundle exec puma -C config/puma.rb Restart=always [Install] WantedBy=multi-user.target ``` **Using PM2 (Node.js):** ```bash pm2 start bundle exec -- puma -C config/puma.rb ``` ## 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: - Hanami 2.1 - ROM (Ruby Object Mapper) - SQLite3 - RSpec - Puma ## Additional Resources - [Hanami Documentation](https://guides.hanamirb.org/) - [ROM Documentation](https://rom-rb.org/) - [RSpec Documentation](https://rspec.info/) - [Euchre Rules](https://www.pagat.com/euchre/euchre.html)