-
{clue.title || `Clue #${clue.id}`}
+
+ {clue.title || `Clue #${clue.id}`}
+
Skipped at {new Date(clue.found_at).toLocaleTimeString()}
@@ -182,7 +190,7 @@ export default function StatsPage() {
Clues Found:
- {teamStats.foundClues.length}
+ {teamStats.foundClues.length} of {teamStats.totalClues}
@@ -191,7 +199,9 @@ export default function StatsPage() {
Clues Skipped:
- {teamStats.skippedClues}
+
+ {teamStats.skippedCluesCount}
+
Current Rank:
@@ -214,9 +224,7 @@ export default function StatsPage() {
{expanded && (
-
- {renderCluesList()}
-
+
{renderCluesList()}
)}
diff --git a/app/api/admin/leaderboard/route.js b/app/api/admin/leaderboard/route.js
index 371ede0..07e583e 100644
--- a/app/api/admin/leaderboard/route.js
+++ b/app/api/admin/leaderboard/route.js
@@ -38,13 +38,14 @@ export async function GET(request) {
const totalClues = clueCountResult?.total || 0;
// Get all teams with member count and clues found
+ // Modified to exclude skipped clues from cluesFound count
const teams = await query(`
SELECT
t.id,
t.name,
t.code,
COUNT(DISTINCT u.id) as memberCount,
- COUNT(DISTINCT tc.clue_id) as cluesFound,
+ COUNT(DISTINCT CASE WHEN tc.skipped = 0 OR tc.skipped IS NULL THEN tc.clue_id END) as cluesFound,
MAX(tc.found_at) as lastActivity
FROM
teams t
diff --git a/app/api/admin/teams/[teamId]/reset-progress/route.js b/app/api/admin/teams/[teamId]/reset-progress/route.js
index 2dceff1..6f27894 100644
--- a/app/api/admin/teams/[teamId]/reset-progress/route.js
+++ b/app/api/admin/teams/[teamId]/reset-progress/route.js
@@ -23,7 +23,8 @@ async function verifyAdmin(request) {
return { authorized: true, token };
}
-export async function POST(request, context) {
+// Make sure the reset progress API also handles the skipped flag
+export async function POST(request, { params }) {
try {
// Verify admin access
const { authorized, error, status } = await verifyAdmin(request);
@@ -31,7 +32,7 @@ export async function POST(request, context) {
return Response.json({ error }, { status });
}
- const { teamId } = context.params;
+ const { teamId } = params;
// Validate teamId is a number
if (isNaN(parseInt(teamId))) {
@@ -44,7 +45,7 @@ export async function POST(request, context) {
return Response.json({ error: "Team not found" }, { status: 404 });
}
- // Delete all clue progress for the team
+ // When resetting progress, make sure to reset skipped status too
await run("DELETE FROM team_clues WHERE team_id = ?", [teamId]);
return Response.json({
diff --git a/app/api/leaderboard/route.js b/app/api/leaderboard/route.js
index 7f6948b..d6205c4 100644
--- a/app/api/leaderboard/route.js
+++ b/app/api/leaderboard/route.js
@@ -25,12 +25,13 @@ export async function GET(request) {
// Get all teams with progress info and member count
// Only include teams that have at least one member
+ // Modify the SQL query to exclude skipped clues from the count
const teams = await query(`
SELECT
- t.id,
- t.name,
+ t.id,
+ t.name,
t.code,
- COUNT(DISTINCT tc.clue_id) as cluesFound,
+ COUNT(DISTINCT CASE WHEN tc.skipped = 0 OR tc.skipped IS NULL THEN tc.clue_id END) as cluesFound,
MAX(tc.found_at) as lastActivity,
COUNT(DISTINCT u.id) as memberCount
FROM
@@ -49,6 +50,7 @@ export async function GET(request) {
`);
// Add progress percentage and total clues to each team
+ // Make sure the progress calculation is consistent
const teamsWithProgress = teams.map((team) => ({
...team,
totalClues,
diff --git a/app/api/team-stats/route.js b/app/api/team-stats/route.js
index a07f67a..4685277 100644
--- a/app/api/team-stats/route.js
+++ b/app/api/team-stats/route.js
@@ -66,29 +66,16 @@ export async function GET(request) {
[token.teamId]
);
- // We need to calculate skipped clues - these are clues that have higher IDs than the user's lowest unfound clue
- // First, get all clue IDs
+ // Get all clue IDs - this part is still useful for other calculations
const allClueIds = await query("SELECT id FROM clues ORDER BY id ASC");
-
- // Convert to a simple array of IDs
const allClueIdArray = allClueIds.map((c) => c.id);
-
- // Create a set of found clue IDs for easy lookup
const foundClueIdSet = new Set(foundClues.map((c) => c.id));
-
- // Find all unfound clue IDs
const unfoundClueIds = allClueIdArray.filter(
(id) => !foundClueIdSet.has(id)
);
- // If there are unfound clues, the ones after the first unfound are "skipped"
- let skippedCluesCount = 0;
- if (unfoundClueIds.length > 0) {
- const lowestUnfoundId = Math.min(...unfoundClueIds);
-
- // Skipped clues are found clues with IDs higher than the lowest unfound
- skippedCluesCount = foundClues.filter((c) => c.id > lowestUnfoundId).length;
- }
+ // Replace the old skipped clues calculation with this simple count
+ let skippedCluesCount = skippedClues.length;
// Get current team rank
const teamRankings = await query(`
@@ -114,16 +101,22 @@ export async function GET(request) {
let currentRank = teamRankings.findIndex((t) => t.id === team.id) + 1;
if (currentRank === 0) currentRank = teamRankings.length + 1; // If not found (shouldn't happen)
+ // Update progress calculation - don't subtract skippedCluesCount since foundClues query already excludes skipped clues
+ const correctlyFoundCount = foundClues.length; // <-- Fixed: don't subtract again
+
// Construct response object
const teamStats = {
team,
totalClues,
foundClues,
- remainingClues: totalClues - foundClues.length,
+ skippedClues,
+ remainingClues: totalClues - correctlyFoundCount,
skippedCluesCount,
currentRank,
progress:
- totalClues > 0 ? Math.round((foundClues.length / totalClues) * 100) : 0,
+ totalClues > 0
+ ? Math.round((correctlyFoundCount / totalClues) * 100)
+ : 0,
};
// Return only the teamStats object instead of trying to include undefined variables
diff --git a/clue_hunt.db b/clue_hunt.db
index 371a853..de55ce0 100644
Binary files a/clue_hunt.db and b/clue_hunt.db differ