Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions .github/workflows/update-leaderboard.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
name: Update Leaderboard

on:
workflow_dispatch:
inputs:
contest_id:
description: 'Codeforces Contest ID'
required: true
type: string
contest_name:
description: 'Contest Name'
required: true
type: string
group_id:
description: 'Codeforces Group ID (for mashup/group contests, leave empty for public rounds)'
required: false
type: string
default: ''

jobs:
fetch-and-deploy:
runs-on: ubuntu-latest
permissions:
contents: write
pages: write
id-token: write

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Install dependencies
run: |
pip install requests

- name: Fetch contest standings
env:
CODEFORCES_API_KEY: ${{ secrets.CODEFORCES_API_KEY }}
CODEFORCES_API_SECRET: ${{ secrets.CODEFORCES_API_SECRET }}
CF_CONTEST_ID: ${{ github.event.inputs.contest_id }}
CF_CONTEST_NAME: ${{ github.event.inputs.contest_name }}
CF_GROUP_ID: ${{ github.event.inputs.group_id }}
run: |
python scripts/fetch_standings.py \
--contest-id "$CF_CONTEST_ID" \
--contest-name "$CF_CONTEST_NAME" \
${CF_GROUP_ID:+--group "$CF_GROUP_ID"}

- name: Compute scores and leaderboard
run: |
python scripts/compute_scores.py

- name: Configure Git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

- name: Commit and push changes
run: |
git add data/
git diff --staged --quiet || git commit -m "Update leaderboard for contest ${{ github.event.inputs.contest_id }}"
git push

- name: Setup Pages
uses: actions/configure-pages@v4

- name: Build frontend
run: |
npm ci
npm run build

- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./dist

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
25 changes: 25 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,28 @@ Thumbs.db
# Docker and misc
*.pid

# Dependencies
node_modules/
venv/
.env

# Build output
dist/
build/

# IDE
.vscode/
.idea/
*.swp
*.swo

# OS
.DS_Store
Thumbs.db

# Logs
*.log
npm-debug.log*

# Testing
coverage/
Binary file added Codemon Series – Rules & Regulations.pdf
Binary file not shown.
128 changes: 128 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# Codemon Leaderboard

A Jamstack-based contest leaderboard system for Codeforces/HackerRank competitions. Built with React, Python, and GitHub Actions.

## Architecture

- **Frontend**: React SPA hosted on GitHub Pages
- **Backend**: Python script fetches data from Codeforces API
- **Database**: Git-as-a-Database (JSON files versioned in Git)
- **CI/CD**: GitHub Actions for automated updates

## Project Structure

```
├── frontend/ # React application
│ ├── src/
│ │ ├── main.jsx # Entry point
│ │ ├── App.jsx # Main component
│ │ ├── App.css # Styles
│ │ └── index.css # Global styles
│ └── public/ # Static assets
├── scripts/ # Python automation scripts
│ └── fetch_standings.py # Fetches standings from Codeforces API
├── data/
│ └── contests/ # Contest data (JSON files)
│ ├── index.json # Contest list index
│ └── contest_<id>.json # Individual contest standings
├── .github/workflows/ # GitHub Actions
│ └── update-leaderboard.yml
├── package.json # Frontend dependencies
├── vite.config.js # Vite configuration
└── index.html # HTML entry point
```

## Getting Started

### Prerequisites

- Node.js 18+
- Python 3.11+
- npm

### Installation

```bash
# Install frontend dependencies
npm install

# Install Python dependencies
pip install requests
```

### Development

```bash
# Start development server
npm run dev
```

### Building for Production

```bash
npm run build
```

## Usage

### Fetching Contest Standings

```bash
# Fetch standings for a specific contest
python scripts/fetch_standings.py <contest_id> "<contest_name>"

# List recent contests
python scripts/fetch_standings.py --list
```

### Automated Updates

1. Go to GitHub Actions tab
2. Run "Update Leaderboard" workflow
3. Enter Contest ID and Contest Name
4. Workflow will:
- Fetch standings from Codeforces API
- Generate JSON files
- Commit to repository
- Build and deploy to GitHub Pages

## Deployment

The site is automatically deployed to GitHub Pages when the workflow runs. Configure in repository settings:

1. Go to Settings > Pages
2. Source: GitHub Actions
3. The workflow handles the rest

## Data Format

### Contest Index (`data/contests/index.json`)

```json
{
"contests": [
{
"id": 123456,
"name": "Codeforces Round #123",
"date": "2024-01-15"
}
]
}
```

### Contest Standings (`data/contests/contest_<id>.json`)

```json
{
"contestId": 123456,
"contestName": "Codeforces Round #123",
"standings": [
{
"rank": 1,
"handle": "tourist",
"score": 1000,
"problemsSolved": 5
}
]
}
```
Binary file added architecture.docx
Binary file not shown.
12 changes: 12 additions & 0 deletions frontend/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Codemon Leaderboard</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
Loading