# SPORTSLIFE: launch guide for cPanel

> **Honest status:** every phase of this game is written, but the author could not run PHP or MySQL while building it, so it has **never been executed**. The installer, the tests and the checks below are designed to find first-run problems quickly. Install it on a **test domain or subdomain first**, play a match with a friend, and only then announce it. If something fails, copy the exact message (and the last lines of `sportslife/storage/logs/app.log` and `install.log`) and send it for a fix.

## What you need
- A cPanel hosting account with **PHP 8.1 or newer** and **MySQL 8.0.16+ or MariaDB 10.5+** (needed for the database's safety checks).
- A domain or subdomain. Use **HTTPS** (free AutoSSL is enough).
- Terminal/SSH is **not** required. The only technical step is adding one cron job.

## The package layout
```
sportslife-cpanel.zip
├── START_HERE.txt
├── LAUNCH_GUIDE.md           (this file)
├── sportslife/               PRIVATE: code, config, database files, logs, backups (never put this in public_html)
└── public_html/              PUBLIC: index.php, install.php, assets/, .htaccess
```
Extracted in your **home directory** (`/home/YOURUSER/`), the first folder lands next to `public_html`, and the second merges into your web folder. Nothing private is ever reachable from the internet.

---

## Step 1: Choose the PHP version
cPanel → **MultiPHP Manager** → tick your domain → choose **PHP 8.1, 8.2 or 8.3** → Apply.
cPanel → **Select PHP Version** → Extensions: make sure **pdo_mysql**, **mbstring** and **openssl** are ticked (they usually are). `intl` and `curl` are not needed.

## Step 2: Create the database
cPanel → **MySQL® Database Wizard**:
1. Database name, e.g. `sportslife` (cPanel adds your prefix: `youruser_sportslife`).
2. Create a user, e.g. `sl` (becomes `youruser_sl`) with a **long generated password**. Save it.
3. Tick **ALL PRIVILEGES** → Next.

Write down: **database name, user name, password**. The host is almost always `localhost`.
*(Later, for extra safety, you can reduce the user to SELECT, INSERT, UPDATE, DELETE, but only after installing, because installation and updates need CREATE and ALTER.)*

## Step 3: Upload and extract
1. cPanel → **File Manager** → click your **home** folder (`/home/youruser`), *not* `public_html`.
2. **Upload** `sportslife-cpanel.zip`, then right-click it → **Extract** (extract into the home folder itself).
3. Check you now see a folder **`sportslife`** in the home folder, and that `public_html` contains **`index.php`**, **`install.php`**, **`assets`** and **`.htaccess`**.
4. You may delete the zip afterwards.

**If your site is a subdomain or add-on domain** (its folder is not `public_html`, e.g. `/home/youruser/game.example.com`): after extracting, **move the contents of `public_html` (index.php, install.php, assets, .htaccess) into that domain's folder**. The `sportslife` folder stays in the home directory. No editing is needed: the game finds its private folder by itself.

**If you already run another website in `public_html`:** do not extract over it (`.htaccess` would be overwritten). Create a subdomain (cPanel → Domains) such as `play.example.com`, and follow the subdomain instructions above.

**If a game folder like `https://example.com/game/` is wanted:** put the public files in `public_html/game/`. The installer detects the folder automatically.

## Step 4: Turn on HTTPS
cPanel → **SSL/TLS Status** → select the domain → **Run AutoSSL**. Wait a minute, then check `https://your-domain` opens with a padlock. Do this *before* installing so that login cookies are marked Secure.
(Later you can force HTTPS: edit `public_html/.htaccess` and remove the `#` from the three lines under "force it".)

## Step 5: Run the installer
Open **`https://your-domain/install.php`** (opening your site's home page also redirects there the first time).

1. The **Server check** must be all green. A red item says what to change (PHP version, extension, folder permission 755).
2. **Install key:** in File Manager open `sportslife/storage/install_key.txt`, copy the code, paste it in. This proves you own the server; nobody else can install your site.
3. **Database:** host `localhost`, the database name, user and password from Step 2.
4. **Administrator:** choose your admin username, email and a strong password (10+ characters, not containing your username).
5. **Site address:** pre-filled; correct it only if it is wrong (no trailing slash, no folder).
6. **Email sending:** leave on "Send real emails" (see *Email* below).
7. Leave **Create the fictional world** ticked → **Install SPORTSLIFE**. It writes the settings, builds the database, creates your admin account and the world (about a minute).
8. On the success page click **Delete install.php now**. (If that fails, delete the file in File Manager.)

Re-running the installer is blocked automatically, and it refuses any database that already contains tables.

## Step 6: Add the cron job (this plays the matches)
The game has no always-running process. One cron job, every minute, runs everything: matches, training, wages, transfer expiry, clean-ups.

cPanel → **Cron Jobs** → *Add New Cron Job*: choose **Once Per Minute (\* \* \* \* \*)** and paste (replace the two placeholders):

```
/usr/local/bin/php /home/YOURUSER/sportslife/cron/process_jobs.php >> /home/YOURUSER/sportslife/storage/logs/cron.log 2>&1
```
- **PHP path:** the installer's success page shows a suggested full command with your real folder. If the PHP path is different on your host, use the one cPanel shows in the Cron Jobs help text, commonly `/usr/local/bin/php`, `/usr/local/bin/ea-php82` or `/opt/cpanel/ea-php82/root/usr/bin/php`.
- If your host allows only 5-minute intervals use `*/5 * * * *`: matches then start up to 5 minutes after kickoff.
- **Recommended extras:**
```
17 2 * * *    /usr/local/bin/php /home/YOURUSER/sportslife/bin/backup.php --keep=7 >> /home/YOURUSER/sportslife/storage/logs/cron.log 2>&1
*/15 * * * *  /usr/local/bin/php /home/YOURUSER/sportslife/bin/healthcheck.php >> /home/YOURUSER/sportslife/storage/logs/cron.log 2>&1
```
The backup lands in `sportslife/storage/backups`. **Download the newest one regularly**: a backup kept only on the same server is not a safe backup.

## Step 7: Check it works
1. `https://your-domain/health` shows `{"status":"ok"}`.
2. Sign in with your admin account → open **Admin** (left menu): the **dashboard should be green**. "Cron worker" turns green about a minute after the cron job starts. "Backups" stays yellow until the first backup runs.
3. Register a second test account (another browser or a private window), create a manager, take a small club, set a lineup in **Tactics**.
4. Do a quick match test without waiting for Saturday: *Admin → Fixtures* → find a fixture between two clubs → **Reschedule** to a time about 2 hours ahead (it must be at least 90 minutes away so managers can still set tactics), or wait for the real kickoff. After kickoff the cron plays it; open **Match Centre**.
5. On a phone, open the site and walk through register → manager → club → tactics. (A real mobile test has not been done by the author.)

---

## Settings reference

### `sportslife/config/config.php` (written by the installer; edit in File Manager → Code Editor)
| Key | Meaning | Normal value |
|---|---|---|
| `app.url` | Site address, scheme and host only | `https://your-domain` |
| `app.base_path` | Folder if the game is in a sub-folder | `''` (empty) or `'/game'` |
| `app.key` | Random secret (generated for you); do not share or change after launch | 64 hex characters |
| `app.debug` | Show error details on screen. **Keep `false` on a live site** | `false` |
| `app.env` | `production`. Only a *development copy* uses `'development'` (it enables the test and reset tools, which must never touch your live data) | `'production'` |
| `app.admin_email` | Gets an email when the health check fails (max one per hour) | your email |
| `db.*` | Database host, name, user, password | from Step 2 |
| `mail.driver` | `mail` (server sends real emails) or `log` (saves them as files in `storage/mail/`) | `mail` |
| `mail.from` | "From" address of game emails | `no-reply@your-domain` |
| `security.session_idle_minutes` | Sign out after this many idle minutes | `120` |
| `security.trusted_proxy_header` | Only if you sit behind a proxy/CDN you control (e.g. `X-Forwarded-For`) | `null` |
Keep the file private (permission 640 or 600). Never email or upload it anywhere.

### Admin → Game Settings
| Setting | Meaning | Default | Allowed |
|---|---|---|---|
| `registration_open` | Allow new players to sign up (untick to close the doors) | on | on/off |
| `currency_name` | Name of the virtual currency (no cash value) | Coins | 1-50 characters |
| `lineup_lock_minutes` | Tactics lock this long before kickoff | 30 | 5-240 |
| `manager_contract_months` | Length of a new manager's contract | 12 | 1-60 |
| `board_initial_confidence` | Board confidence of a new manager | 60 | 1-100 |
| `account_deletion_grace_days` | Days before a deleted account is anonymised | 14 | 1-90 |
Settings shown with a "not applied by the game yet" label (`attribute_scale_max`, `allow_multiple_appointments`, `transfer_offer_expiry_hours`, `require_email_verification`) do nothing at present.

### Admin → Competitions
Points per win/draw/loss (3/1/0 standard; locked once matches are played), promotion and relegation places (**the places going down from a division must equal the places coming up from the one below**, or the season rollover refuses), and the tie-break order (`points, goal_difference, goals_for, wins, head_to_head`).

### Things only a code edit can change (File Manager → Code Editor)
- **Terms of Service and Privacy Policy** (they are placeholder text, *not legal advice*): `sportslife/app/Controllers/PageController.php`, the `terms` and `privacy` entries. Replace them with text reviewed for your country **before inviting the public**. The Rules, Help and How-to-Play texts are in the same file.
- **Match day and time** are Saturdays 15:00 UTC (set when a season is created, in `WorldSeeder.php` and `SeasonService.php`). Players see times in their own timezone (Settings).
- Engine, economy and transfer constants are documented in `sportslife/docs/GAME_RULES.md`. Changing them alters balance; do it only deliberately.

## Email
- With `mail.driver = mail` the server's mail system sends registration and password-reset emails. For good delivery open cPanel → **Email Deliverability** and make sure **SPF and DKIM** are valid for your domain.
- Test: register with your own address and confirm the email arrives (check spam). If emails do not arrive, switch to `log` to see them in `sportslife/storage/mail/`, and ask your host about outgoing mail. An SMTP client is not included.
- Players can still play without verifying email (verification is not enforced).

## Everyday operation
- **Daily:** open **Admin → Dashboard**: green means fine. Failed jobs or overdue fixtures need attention that day (**Admin → Queue**).
- **Players report abuse:** **Admin → Moderation** (warn, mute 24 h/7 d, suspend; moderators get this page only).
- **Season end** (after ~14 weekly matchdays): **take a backup**, then **Admin → Seasons** → choose the next start date → type ROLLOVER. It crowns champions, applies promotion/relegation, updates manager reputation (and dismisses managers the board has lost faith in) and creates the next season. It cannot be undone except by restoring the backup.
- **Backups, restore, upgrades, incidents:** `sportslife/docs/RUNBOOK.md`.

## Troubleshooting
| What you see | Likely cause and fix |
|---|---|
| "The SPORTSLIFE application folder was not found" | The `sportslife` folder is not next to (or one level above) your web folder. Extract the zip in the **home** folder, step 3. |
| Page redirects to `install.php` again and again | `sportslife/config/config.php` is missing: the installer did not finish. Re-open `install.php`. |
| "Server check" shows a red PHP item | Wrong PHP version/extension: step 1. |
| "Folder … is not writable" | File Manager → right-click the folder → Change Permissions → 755 (or 775). Never 777. |
| "Could not connect to the database" | Name/user must include the cPanel prefix (`youruser_…`); the user must be **added to the database with ALL PRIVILEGES**; the host is usually `localhost`. |
| "That database is not empty" | Create a fresh empty database, or empty the old one (phpMyAdmin → select all tables → Drop). |
| "This database server is …" (version) | Needs MySQL 8.0.16+ / MariaDB 10.5+. Ask the host to upgrade, or choose another plan. |
| White page / "Something went wrong" | Read the last lines of `sportslife/storage/logs/app.log`. Send them for a fix. |
| 403 Forbidden on the site | Check `public_html/.htaccess` was extracted and that the PHP version is set (step 1). |
| 404 on every page except the home page | `.htaccess` is missing or the host has `mod_rewrite` disabled; ask the host to enable it. |
| Dashboard: "Cron worker" red or "Overdue fixtures" | The cron job is missing or the PHP path is wrong. Run the same command in cPanel's Terminal, if you have one, or check `storage/logs/cron.log`. |
| Matches never start | Same as above. The cron job must be running **every minute** and the fixture's kickoff must have passed. |
| Registration emails never arrive | See *Email*. |
| "Session expired" on forms | The login cookie is blocked, the site is opened on both http and https, or the page was left open for hours. Use https only. |
| You forgot the admin password | Use "Forgot password" on the login page (needs working email), or in phpMyAdmin set a new hash. Ask for help. |
| You want to start over | Drop all tables in the database, delete `sportslife/storage/installed.lock` and `sportslife/config/config.php`, and upload `install.php` again (from the zip). |

## Going live: checklist
- [ ] Tested on a subdomain with two accounts, including a played match
- [ ] HTTPS forced; `app.debug` is `false`; `config.php` permission 640/600
- [ ] Admin dashboard fully green; cron job running; nightly backup running and the file copied off the server
- [ ] Terms and Privacy replaced with reviewed text; contact method for players stated in the Help page
- [ ] Email delivery tested (SPF/DKIM)
- [ ] You tried restoring a backup on a test database (`docs/RUNBOOK.md`)
- [ ] `install.php` is gone
- [ ] Tell players: matches are Saturdays 15:00 UTC; set your lineup before the lock (30 minutes before kickoff)

## Manual installation (if the web installer cannot be used and you have SSH/Terminal)
```
cd ~/sportslife
cp config/config.sample.php config/config.php      # edit the database values and app.url
php bin/migrate.php
php bin/seed_world.php --seed=1
```
Then register on the site, and in phpMyAdmin run `UPDATE users SET role='admin', email_verified_at=UTC_TIMESTAMP() WHERE username='YOU';`.

## Documents inside the package (`sportslife/docs/`)
`STATUS.md` honest status and gaps · `RUNBOOK.md` operations · `DEPLOYMENT_CPANEL.md` technical deployment notes · `GAME_RULES.md` every rule and constant · `SECURITY.md` · `TESTING.md` (test scripts; use only on a *development* copy) · `ARCHITECTURE.md` · `DATABASE.md`
