Skip to content

Commit 15dffc2

Browse files
committed
Overall and Contest leaderboard (leaderboard + retrieval from backend)
1 parent b3f58c2 commit 15dffc2

File tree

9 files changed

+835
-7
lines changed

9 files changed

+835
-7
lines changed

src/commons/application/ApplicationTypes.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,10 @@ export const defaultAchievement: AchievementState = {
354354
};
355355

356356
export const defaultLeaderboard: LeaderboardState = {
357-
userXp: []
357+
userXp: [],
358+
contestScore: [],
359+
contestPopularVote: [],
360+
code: "Initial code"
358361
}
359362

360363
const getDefaultLanguageConfig = (): SALanguage => {

src/commons/sagas/LeaderboardSaga.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { combineSagaHandlers } from "../redux/utils";
33
import { call, put } from 'redux-saga/effects';
44
import { Tokens } from '../application/types/SessionTypes';
55
import { selectTokens } from './BackendSaga';
6-
import { getAllTotalXp } from "./RequestsSaga";
6+
import { getAllTotalXp, getContestScoreLeaderboard, getContestPopularVoteLeaderboard } from "./RequestsSaga";
77
import { actions } from "../utils/ActionsHelper";
88

99
const LeaderboardSaga = combineSagaHandlers(LeaderboardActions, {
@@ -15,6 +15,28 @@ const LeaderboardSaga = combineSagaHandlers(LeaderboardActions, {
1515
if (usersXp) {
1616
yield put(actions.saveAllUsersXp(usersXp))
1717
}
18+
},
19+
20+
getAllContestScores: function* (action) {
21+
const tokens: Tokens = yield selectTokens();
22+
const assessmentId = action.payload;
23+
24+
const contestScores = yield call(getContestScoreLeaderboard, assessmentId, tokens);
25+
26+
if (contestScores) {
27+
yield put(actions.saveAllContestScores(contestScores))
28+
}
29+
},
30+
31+
getAllContestPopularVotes: function* (action) {
32+
const tokens: Tokens = yield selectTokens();
33+
const assessmentId = action.payload;
34+
35+
const contestPopularVotes = yield call(getContestPopularVoteLeaderboard, assessmentId, tokens);
36+
37+
if (contestPopularVotes) {
38+
yield put(actions.saveAllContestPopularVotes(contestPopularVotes))
39+
}
1840
}
1941
});
2042

src/commons/sagas/RequestsSaga.ts

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ import { castLibrary } from '../utils/CastBackend';
5656
import Constants from '../utils/Constants';
5757
import { showWarningMessage } from '../utils/notifications/NotificationsHelper';
5858
import { request } from '../utils/RequestHelper';
59-
import { LeaderboardRow } from 'src/features/leaderboard/LeaderboardTypes';
59+
import { ContestLeaderboardRow, LeaderboardRow } from 'src/features/leaderboard/LeaderboardTypes';
6060

6161
// eslint-disable-next-line @typescript-eslint/no-require-imports
6262
const XLSX = require('xlsx');
@@ -485,6 +485,70 @@ export const getAllTotalXp = async (tokens: Tokens): Promise<number | null> => {
485485
);
486486
};
487487

488+
/**
489+
* GET /courses/{courseId}/leaderboard/contests/{assessment_id}/get_score_leaderboard
490+
*/
491+
export const getContestScoreLeaderboard = async (
492+
assessmentId: number,
493+
tokens: Tokens
494+
): Promise<number | null> => {
495+
let resp;
496+
resp = await request(`${courseId()}/leaderboard/contests/${assessmentId}/get_score_leaderboard`, 'GET', {
497+
...tokens
498+
});
499+
500+
if (!resp || !resp.ok) {
501+
return null; // invalid accessToken _and_ refreshToken
502+
}
503+
504+
const rows = await resp.json();
505+
506+
return rows.contest_score.map(
507+
(row: any): ContestLeaderboardRow => ({
508+
rank: row.rank,
509+
name: row.name,
510+
username: row.username,
511+
score: row.score,
512+
avatar: "",
513+
code: row.code,
514+
submissionId: row.submission_id,
515+
votingId: rows.voting_id
516+
})
517+
);
518+
};
519+
520+
/**
521+
* GET /courses/{courseId}/leaderboard/contests/{assessment_id}/get_popular_vote_leaderboard
522+
*/
523+
export const getContestPopularVoteLeaderboard = async (
524+
assessmentId: number,
525+
tokens: Tokens
526+
): Promise<number | null> => {
527+
let resp;
528+
resp = await request(`${courseId()}/leaderboard/contests/${assessmentId}/get_popular_vote_leaderboard`, 'GET', {
529+
...tokens
530+
});
531+
532+
if (!resp || !resp.ok) {
533+
return null; // invalid accessToken _and_ refreshToken
534+
}
535+
536+
const rows = await resp.json();
537+
538+
return rows.contest_popular.map(
539+
(row: any): ContestLeaderboardRow => ({
540+
rank: row.rank,
541+
name: row.name,
542+
username: row.username,
543+
score: row.score,
544+
avatar: "",
545+
code: row.code,
546+
submissionId: row.submission_id,
547+
votingId: rows.voting_id
548+
})
549+
);
550+
};
551+
488552
/**
489553
* GET /courses/{courseId}/admin/users/{course_reg_id}/assessments
490554
*/
@@ -1169,6 +1233,20 @@ export const deleteSourcecastEntry = async (
11691233
return resp;
11701234
};
11711235

1236+
/**
1237+
* POST /courses/{courseId}/admin/assessments/{assessmentId}/calculateContestScore
1238+
*/
1239+
export const calculateContestScore = async (
1240+
assessmentId: number,
1241+
tokens: Tokens
1242+
) : Promise<Response | null> => {
1243+
const resp = await request(`${courseId()}/admin/assessments/${assessmentId}/calculateContestScore`, 'POST', {
1244+
...tokens
1245+
});
1246+
1247+
return resp;
1248+
};
1249+
11721250
/**
11731251
* GET /courses/{courseId}/admin/assessments/{assessmentId}/scoreLeaderboard
11741252
*/
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
import { createActions } from "src/commons/redux/utils";
2-
import { LeaderboardRow } from "./LeaderboardTypes";
2+
import { ContestLeaderboardRow, LeaderboardRow } from "./LeaderboardTypes";
33

44
const LeaderboardActions = createActions('leaderboard', {
55
getAllUsersXp: () => ({}),
6-
saveAllUsersXp: (userXp: LeaderboardRow[]) => userXp
6+
saveAllUsersXp: (userXp: LeaderboardRow[]) => userXp,
7+
getAllContestScores: (assessmentId: number) => assessmentId,
8+
saveAllContestScores: (contestScore: ContestLeaderboardRow[]) => contestScore,
9+
getAllContestPopularVotes: (assessmentId: number) => assessmentId,
10+
saveAllContestPopularVotes: (contestPopularVote: ContestLeaderboardRow[]) => contestPopularVote,
11+
getCode: () => ({}),
12+
saveCode: (code: string) => code,
13+
clearCode: () => ({})
714
});
815

916
export default LeaderboardActions

src/features/leaderboard/LeaderboardReducer.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,18 @@ export const LeaderboardReducer: Reducer<LeaderboardState, SourceActionType> = c
1111
builder
1212
.addCase(LeaderboardActions.saveAllUsersXp, (state, action) => {
1313
state.userXp = action.payload;
14+
})
15+
.addCase(LeaderboardActions.saveAllContestScores, (state, action) => {
16+
state.contestScore = action.payload;
17+
})
18+
.addCase(LeaderboardActions.saveAllContestPopularVotes, (state, action) => {
19+
state.contestPopularVote = action.payload;
20+
})
21+
.addCase(LeaderboardActions.saveCode, (state, action) => {
22+
state.code = action.payload;
23+
})
24+
.addCase(LeaderboardActions.clearCode, (state, action) => {
25+
state.code = "";
1426
});
1527
}
1628
);

src/features/leaderboard/LeaderboardTypes.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,26 @@ export type LeaderboardRow = {
77
achievements: string;
88
};
99

10+
export type ContestLeaderboardRow = {
11+
rank: number;
12+
name: string;
13+
username: string;
14+
score: number;
15+
avatar: string;
16+
code: string;
17+
submissionId: number;
18+
votingId: number;
19+
};
20+
1021
export type LeaderboardState = {
11-
userXp: LeaderboardRow[]
12-
};
22+
userXp: LeaderboardRow[];
23+
contestScore: ContestLeaderboardRow[];
24+
contestPopularVote: ContestLeaderboardRow[];
25+
code: string;
26+
};
27+
28+
export type LeaderboardContestDetails = {
29+
contest_id: number;
30+
title: string;
31+
published: boolean | undefined;
32+
}

0 commit comments

Comments
 (0)