Skip to content

Commit

Permalink
Merge pull request #160 from 2004yash/hustle
Browse files Browse the repository at this point in the history
Updated Hustle for MongoDB, added last updated
  • Loading branch information
SkySingh04 authored Jan 4, 2025
2 parents b831098 + 6828777 commit 4f8bac4
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 76 deletions.
18 changes: 0 additions & 18 deletions .github/workflows/schedule-leaderboard-update.yml

This file was deleted.

52 changes: 27 additions & 25 deletions app/(default)/api/hustle/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,8 @@ import axios from "axios";
// import { JSDOM } from "jsdom";
import puppeteer from "puppeteer";

import {
getFirestore,
doc,
setDoc,
getDoc,
} from "firebase/firestore";
import { app } from "@/Firebase";
import connectMongoDB from "@/lib/dbConnect";
import PbhustleModel from "@/models/PbHustel";
import { LatestModel, LeaderboardModel } from "@/models/PbHustel";

interface ContestRanking {
rank: number;
Expand All @@ -35,7 +28,7 @@ interface LeaderboardData {
export async function POST() {
try {
console.log("Initializing mongodb connection.");
await connectMongoDB()
await connectMongoDB();

const API_URL =
process.env.VJUDGE_CONTEST_API ||
Expand All @@ -51,9 +44,8 @@ export async function POST() {
const url = `https://vjudge.net/contest/${ccode}#rank`;
console.log(`Contest URL: ${url}`);


console.log("Fetching existing leaderboard data from Firestore.");
const leaderboardDoc = await PbhustleModel.findOne({name:"leaderboard"})
const leaderboardDoc = await LeaderboardModel.findOne({ name: "leaderboard" });

const existingData = leaderboardDoc as LeaderboardData | undefined;
console.log("Existing leaderboard data:", existingData);
Expand Down Expand Up @@ -95,11 +87,16 @@ export async function POST() {
await browser.close();

console.log("Updating latest contest results in Firestore.");
await PbhustleModel.findOneAndUpdate({
name:"latest",
results: latest,
updateTime: new Date(),
});
await LatestModel.findOneAndUpdate(
{ name: "latest" },
{
$set: {
results: latest,
updateTime: new Date(),
},
},
{ upsert: true }
);

let rankings: LeaderboardUser[] = existingData?.rankings || [];
console.log("Existing rankings:", rankings);
Expand Down Expand Up @@ -131,12 +128,17 @@ export async function POST() {

console.log("Final rankings:", rankings);
console.log("Updating leaderboard in Firestore.");
await PbhustleModel.findOneAndUpdate({
name:"leaderboard",
rankings,
updatedAt: new Date(),
lastContestCode: ccode,
});
await LeaderboardModel.findOneAndUpdate(
{ name: "leaderboard" },
{
$set: {
rankings,
updatedAt: new Date(),
lastContestCode: ccode,
},
},
{ upsert: true }
);

return NextResponse.json({
message: "Leaderboard updated successfully",
Expand All @@ -150,11 +152,11 @@ export async function POST() {

export async function GET() {
try {
await connectMongoDB()
await connectMongoDB();
console.log("Fetching latest contest results from Firestore.");
const latestDoc = await PbhustleModel.findOne({name:"latest"})
const latestDoc = await LatestModel.findOne({ name: "latest" });
console.log("Fetching leaderboard data from Firestore.");
const leaderboardDoc = await PbhustleModel.findOne({name:"leaderboard"})
const leaderboardDoc = await LeaderboardModel.findOne({ name: "leaderboard" });

console.log("Fetched data successfully:", {
latest: latestDoc,
Expand Down
35 changes: 15 additions & 20 deletions app/(default)/hustle/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,23 @@ export default function ResultsTable() {
const [rankings, setRankings] = useState<Result[]>([]);
const [loading, setLoading] = useState(true);
const [isAdminLoggedIn, setIsAdminLoggedIn] = useState(false);
const [lastUpdated, setLastUpdated] = useState<Date | null>(null);

useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch("/api/hustle");
const data = await response.json();
console.log(data)
console.log(data);
if (response.ok && data?.data) {
const allDocs = data.data;
const latestData: Result[] = allDocs.latest.results || [];
const rankingsData: Result[] = allDocs.leaderboard.rankings || [];
const updatedAt: Date = new Date(allDocs.leaderboard.updatedAt);

setLatestResults(latestData);
setRankings(rankingsData);
setLastUpdated(updatedAt);
} else {
console.error("Error in response:", data.error);
}
Expand Down Expand Up @@ -96,20 +99,6 @@ export default function ResultsTable() {
}
};

// const renderConsistency = (consistency?: number[]) => {
// if (!consistency) return "N/A";

// return consistency.map((value, index) => (
// <span
// key={index}
// className="mx-1"
// style={{ color: value === 1 ? "#00C853" : "red" }}
// >
// {value === 1 ? "✓" : "✗"}
// </span>
// ));
// };

const renderTable = (data: Result[], showConsistency: boolean) => (
<div className="overflow-x-auto shadow-xl rounded-xl border border-gray-700">
<table className="w-full text-sm text-left text-gray-300">
Expand Down Expand Up @@ -154,7 +143,6 @@ export default function ResultsTable() {
</p>
</motion.header>


<div className="flex justify-center space-x-6 mb-8">
{(["latest", "rankings"] as const).map((tabName) => (
<button
Expand Down Expand Up @@ -198,10 +186,17 @@ export default function ResultsTable() {
<div className="animate-spin rounded-full h-16 w-16 border-t-4 border-[#00FF66]"></div>
</div>
) : (
renderTable(
tab === "latest" ? latestResults : rankings,
tab === "rankings"
)
<>
{lastUpdated && (
<div className="text-center mb-4 text-white">
Last updated: {lastUpdated.toLocaleString()}
</div>
)}
{renderTable(
tab === "latest" ? latestResults : rankings,
tab === "rankings"
)}
</>
)}
</div>
</div>
Expand Down
95 changes: 82 additions & 13 deletions models/PbHustel.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,76 @@
import mongoose, { Document, Schema, Model } from "mongoose";

// Define the Pbhustle interface extending Document for Mongoose
export interface Pbhustle extends Document {
updatedAt?: Date;
lastContestCode?: string;
rankings?: {
/**
* Interface for the "latest" document
*/
export interface Latest extends Document {
name: string; // Always "latest"
results: {
rank: number;
name: string;
score: number;
consistency: number;
}[];
updateTime: Date;
}

// Define the schema for Pbhustle
const pbhustleSchema = new Schema<Pbhustle>(
/**
* Schema for the "latest" document
*/
const latestSchema = new Schema<Latest>(
{
updatedAt: {
name: {
type: String,
required: true,
default: "latest",
},
results: [
{
rank: {
type: Number,
required: true,
},
name: {
type: String,
required: true,
},
score: {
type: Number,
required: true,
},
},
],
updateTime: {
type: Date,
required: true,
},
lastContestCode: {
},
{ versionKey: false }
);

/**
* Interface for the "leaderboard" document
*/
export interface Leaderboard extends Document {
name: string; // Always "leaderboard"
rankings: {
rank: number;
name: string;
score: number;
consistency: number;
}[];
lastContestCode: string;
updatedAt: Date;
}

/**
* Schema for the "leaderboard" document
*/
const leaderboardSchema = new Schema<Leaderboard>(
{
name: {
type: String,
required: true,
default: "leaderboard",
},
rankings: [
{
Expand All @@ -35,12 +86,30 @@ const pbhustleSchema = new Schema<Pbhustle>(
type: Number,
required: true,
},
consistency: {
type: Number,
required: true,
},
},
],
lastContestCode: {
type: String,
required: true,
},
updatedAt: {
type: Date,
required: true,
},
},
{ versionKey: false }
);

// Create or retrieve the Pbhustle model
const PbhustleModel: Model<Pbhustle> = mongoose.models.hustles || mongoose.model<Pbhustle>("hustles", pbhustleSchema);
/**
* Models for "latest" and "leaderboard"
*/
export const LatestModel: Model<Latest> =
mongoose.models.latests || mongoose.model<Latest>("latests", latestSchema);

export default PbhustleModel;
export const LeaderboardModel: Model<Leaderboard> =
mongoose.models.leaderboards ||
mongoose.model<Leaderboard>("leaderboards", leaderboardSchema);

0 comments on commit 4f8bac4

Please sign in to comment.