# 📊 Live Scores Dashboard

A PHP-based dashboard that displays live scores for multiple sports leagues including NHL, NFL, MLB, CFL, NCAAB, NCAAF, major European soccer leagues, MLS, AHL, QMJHL, and AJHL.

## Features

- **Multi-sport coverage**: 17+ leagues across hockey, football, baseball, and soccer
- **Live updates**: Auto-refreshes every 30 seconds via AJAX
- **Dark theme**: Easy on the eyes with sport-specific accent colors
- **Responsive design**: Works on desktop, tablet, and mobile
- **Tabbed navigation**: Filter by sport or view all sports at once
- **Server-side caching**: Reduces API load and improves performance
- **Error handling**: Graceful fallbacks when APIs are unavailable

## Supported Leagues

| Category | Leagues |
|----------|---------|
| **Hockey** | NHL, AHL, QMJHL, AJHL |
| **Football** | NFL, CFL, NCAAF |
| **Baseball** | MLB |
| **Basketball** | NCAAB |
| **Soccer** | EPL, La Liga, Bundesliga, Serie A, Ligue 1, UEFA Champions League, MLS |

## Data Sources

- **ESPN Public API** (no API key required): NHL, NFL, MLB, CFL, NCAAB, NCAAF, all soccer leagues
- **Alternative sources**: AHL, QMJHL, AJHL (when ESPN data is unavailable)

## Setup

### Requirements

- PHP 7.4+ (or PHP 8.x)
- `allow_url_fopen` enabled in php.ini, OR cURL extension
- Web server (Apache, Nginx, or PHP built-in server)

### Quick Start (Built-in PHP Server)

```bash
cd live-scores
php -S localhost:8080
```

Then open http://localhost:8080 in your browser.

### With Apache/Nginx

1. Copy the `live-scores` folder to your web root
2. Ensure the `cache/` directory is writable:
   ```bash
   chmod 755 live-scores/cache
   ```
3. Access via your web server

## Project Structure

```
live-scores/
├── index.php              # Main page
├── config.php             # League definitions & settings
├── api/
│   └── scores.php         # JSON API endpoint
├── includes/
│   ├── api_fetcher.php    # Core API fetching class
│   └── league_fetchers.php # League-specific formatters
├── assets/
│   ├── css/
│   │   └── style.css      # Dark theme styles
│   └── js/
│       └── scores.js      # Live refresh & UI logic
├── cache/                 # Server-side score cache
└── README.md
```

## Configuration

Edit `config.php` to customize:

- **Refresh interval**: `SCORE_REFRESH_INTERVAL` (default: 30 seconds)
- **Cache duration**: `CACHE_DURATION` (default: 60 seconds)
- **Max games per league**: `MAX_GAMES_PER_LEAGUE`
- **Timezone**: `date_default_timezone_set()`

## Troubleshooting

### No scores showing for AHL/QMJHL/AJHL

These leagues don't have well-documented public APIs. The dashboard attempts to fetch from their websites as a fallback. If both fail, you'll see an error message for that league.

### CORS errors in browser console

The API endpoint allows all origins (`Access-Control-Allow-Origin: *`). If you're hosting on a different domain, update this header in `api/scores.php`.

### Scores not updating

1. Check that `allow_url_fopen` is enabled: `php -i | grep allow_url_fopen`
2. Check the browser console for JavaScript errors
3. Verify the `cache/` folder is writable
4. Check PHP error logs for API fetch failures

### Manual refresh

Click the **Refresh** button in the header, or edit `assets/js/scores.js` to change `REFRESH_INTERVAL`.

## API Endpoint

The dashboard exposes a JSON API at `/api/scores.php`:

```
GET /api/scores.php
```

Response format:
```json
{
  "scores": {
    "nhl": {
      "league": { "name": "NHL", "icon": "🏒", "color": "#0033A0" },
      "games": [
        {
          "home": "Toronto Maple Leafs",
          "away": "Montreal Canadiens",
          "homeScore": 3,
          "awayScore": 2,
          "status": "live",
          "timeLeft": "2nd Period - 05:32",
          "time": "2025-01-15T19:00:00-05:00"
        }
      ],
      "source": "ESPN",
      "error": null
    }
  },
  "errors": [],
  "timestamp": "2025-01-15 19:32:45 EST"
}
```

## License

Free to use and modify.
