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
4 changes: 2 additions & 2 deletions .github/workflows/format-command.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:

jobs:
format:
name: 'Format code via comment'
name: "Format code via comment"
runs-on: ubuntu-latest
# Only run if it's a PR and the comment contains /format
if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/format')
Expand Down Expand Up @@ -48,7 +48,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: "20"

- name: Run Prettier
run: npx prettier --write "frontend/**/*.{html,css,js}" "scripts/**/*.js" "server.js"
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/prettier-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: Prettier Check

on:
pull_request:
branches: [ main ]
branches: [main]
push:
branches: [ main ]
branches: [main]

jobs:
prettier:
Expand All @@ -22,7 +22,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: "20"

- name: Run Prettier Requirements Check
run: npx prettier --check "frontend/**/*.{html,css,js}" "scripts/**/*.js" "server.js"
10 changes: 5 additions & 5 deletions .github/workflows/stale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Mark stale issues and PRs

on:
schedule:
- cron: '0 0 * * *'
- cron: "0 0 * * *"

jobs:
stale:
Expand All @@ -14,9 +14,9 @@ jobs:
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue has been inactive for 14 days and has been marked as stale. To keep this issue open, please leave a comment.'
stale-pr-message: 'This PR has been inactive for 14 days and has been marked as stale. If you are still working on it, please leave a comment.'
stale-issue-label: 'stale'
stale-pr-label: 'stale'
stale-issue-message: "This issue has been inactive for 14 days and has been marked as stale. To keep this issue open, please leave a comment."
stale-pr-message: "This PR has been inactive for 14 days and has been marked as stale. If you are still working on it, please leave a comment."
stale-issue-label: "stale"
stale-pr-label: "stale"
days-before-stale: 14
days-before-close: 5
4 changes: 2 additions & 2 deletions .github/workflows/sync-leaderboard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Sync Leaderboard Data

on:
schedule:
- cron: '0 */3 * * *'
- cron: "0 */3 * * *"
workflow_dispatch:

concurrency:
Expand Down Expand Up @@ -30,7 +30,7 @@ jobs:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: "20"

- name: Install dependencies
run: npm install
Expand Down
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ It allows users to register with their LeetCode username and automatically fetch

The goal of this project is to:

- Encourage consistent problem-solving among students
- Create a competitive yet motivating environment
- Provide visibility into individual coding progress
- Encourage consistent problem-solving among students
- Create a competitive yet motivating environment
- Provide visibility into individual coding progress

---

Expand Down Expand Up @@ -46,6 +46,7 @@ leetcode-ranking/
### 1. Fork and clone the repository

First, fork the repository to your GitHub account. Then clone it locally:

```bash
git clone https://github.com/YOUR-USERNAME/leetcode-ranking.git
cd leetcode-ranking
Expand All @@ -63,9 +64,9 @@ or

## Usage

1. Open the registration page
2. Enter your name and LeetCode username
3. Submit the form
1. Open the registration page
2. Enter your name and LeetCode username
3. Submit the form
4. View your ranking on the leaderboard after the next sync

---
Expand All @@ -74,7 +75,7 @@ or

Contributions are welcome.

- Fork the repository
- Create a new branch
- Make your changes
- Submit a Pull Request
- Fork the repository
- Create a new branch
- Make your changes
- Submit a Pull Request
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"description": "",
"main": "index.js",
"scripts": {
"dev": "node ./server.js"
"start": "node index.js",
"dev": "nodemon index.js"
},
"repository": {
"type": "git",
Expand Down
76 changes: 69 additions & 7 deletions server.js
Original file line number Diff line number Diff line change
@@ -1,37 +1,99 @@
const express = require("express");
const cors = require("cors");
const path = require("path");
const fs = require("fs");

const app = express();
const PORT = process.env.PORT || 3000;

app.use(cors());
app.use(express.static(path.join(__dirname, "frontend")));
app.use(express.static("frontend"));

/* ---------------- HOME ROUTES ---------------- */
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, "frontend", "index.html"));
res.sendFile(__dirname + "/frontend/index.html");
});

app.get("/leaderboard", (req, res) => {
res.sendFile(path.join(__dirname, "frontend", "leaderboard.html"));
res.sendFile(__dirname + "/frontend/leaderboard.html");
});

app.get("/about", (req, res) => {
res.sendFile(path.join(__dirname, "frontend", "about.html"));
res.sendFile(__dirname + "/frontend/about.html");
});

app.get("/registration", (req, res) => {
res.sendFile(path.join(__dirname, "frontend", "registration.html"));
res.sendFile(__dirname + "/frontend/registration.html");
});

app.get("/uptime", (req, res) => {
res.json({ status: "Website is running ✅" });
});

/* ---------------- API: STUDENT HISTORY ---------------- */
app.get("/api/student/:username", async (req, res) => {
const { username } = req.params;

try {
console.log("Fetching history for:", username);

// 1. Get list of all daily files from GitHub repo
const apiURL =
"https://api.github.com/repos/codepvg/leetcode-ranking-data/contents/daily?ref=main";

const response = await fetch(apiURL);
const files = await response.json();

if (!Array.isArray(files)) {
return res.status(500).json({
error: "GitHub API failed",
details: files.message || files,
});
}

let history = [];

// 2. Loop through each file
for (const file of files) {
if (!file.name.endsWith(".json")) continue;

const fileRes = await fetch(file.download_url);
const data = await fileRes.json();

const user = data.find((u) => u.id === username);

if (user) {
const date = file.name.split("-").slice(0, 3).join("-");

history.push({
date,
easy: user.data.easySolved,
medium: user.data.mediumSolved,
hard: user.data.hardSolved,
});
}
}

// 3. Sort by date
history.sort((a, b) => new Date(a.date) - new Date(b.date));

res.json({
username,
history,
});
} catch (err) {
console.error(err);
res.status(500).json({
error: "Failed to fetch student history",
details: err.message,
});
}
});

/* ---------------- 404 ---------------- */
app.use((req, res) => {
res.status(404).send("Page not found");
});

/* ---------------- START ---------------- */
app.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}`);
});
Loading