Skip to content
Merged
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
2 changes: 1 addition & 1 deletion frontend/src/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export interface LeaderboardDetail {
score: number;
user_name: string;
submission_id: number;
line_count?: number;
}>
>;
}
Expand All @@ -43,7 +44,6 @@ export interface CodesResponse {
results: Array<{
submission_id: number;
code: string;
line_count?: number;
}>;
}

Expand Down
2 changes: 0 additions & 2 deletions frontend/src/pages/leaderboard/Leaderboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,6 @@ function LeaderboardWithSidebar() {
navigationItems,
navigationIndex,
codes,
lineCounts,
isOpen,
isLoadingCodes,
navigate,
Expand Down Expand Up @@ -456,7 +455,6 @@ function LeaderboardWithSidebar() {
navigationItems={navigationItems}
navigationIndex={navigationIndex}
codes={codes}
lineCounts={lineCounts}
isLoadingCodes={isLoadingCodes}
onClose={close}
onNavigate={navigate}
Expand Down
29 changes: 25 additions & 4 deletions frontend/src/pages/leaderboard/components/RankingLists.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ interface RankingItem {
submission_id: number;
submission_count?: number;
submission_time?: string;
line_count?: number;
}

interface RankingsListProps {
Expand Down Expand Up @@ -84,6 +85,10 @@ const styles: Record<string, SxProps<Theme>> = {
fontFamily: "monospace",
color: "text.secondary",
},
lineCount: {
fontFamily: "monospace",
color: "text.secondary",
},
};

export default function RankingsList({
Expand Down Expand Up @@ -160,6 +165,13 @@ export default function RankingsList({
}
const isExpanded = expanded[field] ?? true;
const visibleItems = isExpanded ? items : items.slice(0, 3);
const showLineCount = expired && items.some(
(item) => typeof item.line_count === "number",
);
const scoreSize = isAdmin ? 2 : showLineCount ? 2 : 3;
const deltaSize = isAdmin ? 1 : showLineCount ? 2 : 3;
const fileSize = 3;
const adminSubmissionCountSize = showLineCount ? 1 : 2;
return (
<Box key={field}>
<Box sx={styles.header}>
Expand Down Expand Up @@ -189,18 +201,18 @@ export default function RankingsList({
{item.user_name} {getMedalIcon(item.rank)}
</Typography>
</Grid>
<Grid size={isAdmin ? 2 : 3}>
<Grid size={scoreSize}>
<Typography sx={styles.score}>
{formatMicroseconds(item.score)}
</Typography>
</Grid>
<Grid size={isAdmin ? 1 : 3}>
<Grid size={deltaSize}>
<Typography sx={styles.delta}>
{item.prev_score > 0 &&
`+${formatMicroseconds(item.prev_score)}`}
</Typography>
</Grid>
<Grid size={isAdmin ? 2 : 3}>
<Grid size={isAdmin ? 2 : fileSize}>
<Typography
sx={{
overflow: "hidden",
Expand Down Expand Up @@ -234,8 +246,17 @@ export default function RankingsList({
)}
</Typography>
</Grid>
{showLineCount && (
<Grid size={isAdmin ? 1 : 2}>
<Typography sx={styles.lineCount}>
{typeof item.line_count === "number"
? `LOC: ${item.line_count.toLocaleString()}`
: ""}
</Typography>
</Grid>
)}
{isAdmin && (
<Grid size={2}>
<Grid size={adminSubmissionCountSize}>
<Typography sx={styles.submissionId}>
Subs: {item.submission_count}
</Typography>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ interface SubmissionCodeSidebarProps {
navigationItems: NavigationItem[];
navigationIndex: number;
codes: Map<number, string>;
lineCounts?: Map<number, number>;
isLoadingCodes?: boolean;
onClose: () => void;
onNavigate: (newIndex: number, item: NavigationItem) => void;
Expand All @@ -35,7 +34,6 @@ export default function SubmissionCodeSidebar({
navigationItems,
navigationIndex,
codes,
lineCounts,
isLoadingCodes = false,
onClose,
onNavigate,
Expand Down Expand Up @@ -93,9 +91,6 @@ export default function SubmissionCodeSidebar({
}, [onWidthChange]);

const drawerWidth = isMobile ? "100vw" : width;
const lineCount = selectedSubmission
? lineCounts?.get(selectedSubmission.submissionId)
: undefined;

return (
<Drawer
Expand Down Expand Up @@ -199,8 +194,7 @@ export default function SubmissionCodeSidebar({
{/* Metadata */}
{(selectedSubmission.timestamp ||
selectedSubmission.originalTimestamp ||
selectedSubmission.score !== undefined ||
lineCount !== undefined) && (
selectedSubmission.score !== undefined) && (
<Box
sx={{
px: 2,
Expand Down Expand Up @@ -262,20 +256,6 @@ export default function SubmissionCodeSidebar({
</Typography>
</Box>
)}
{lineCount !== undefined && (
<Box>
<Typography
variant="caption"
color="text.secondary"
display="block"
>
LOC
</Typography>
<Typography variant="body2" sx={{ fontFamily: "monospace" }}>
{lineCount.toLocaleString()}
</Typography>
</Box>
)}
</Box>
{selectedSubmission.fileName && (
<Typography
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ interface SubmissionSidebarStateType {
navigationItems: NavigationItem[];
navigationIndex: number;
codes: Map<number, string>;
lineCounts: Map<number, number>;
isOpen: boolean;
isLoadingCodes: boolean;
navigate: (newIndex: number, item: NavigationItem) => void;
Expand All @@ -41,7 +40,6 @@ export function SubmissionSidebarProvider({
const [navigationItems, setNavigationItems] = useState<NavigationItem[]>([]);
const [navigationIndex, setNavigationIndex] = useState(0);
const [codes, setCodes] = useState<Map<number, string>>(new Map());
const [lineCounts, setLineCounts] = useState<Map<number, number>>(new Map());
const [isLoadingCodes, setIsLoadingCodes] = useState(false);
const codesRef = useRef(codes);
codesRef.current = codes;
Expand Down Expand Up @@ -74,15 +72,6 @@ export function SubmissionSidebarProvider({
}
return next;
});
setLineCounts((prev) => {
const next = new Map(prev);
for (const item of response?.results ?? []) {
if (typeof item.line_count === "number") {
next.set(item.submission_id, item.line_count);
}
}
return next;
});
})
.catch((err) => {
console.warn("[SubmissionSidebar] Failed to fetch codes:", err);
Expand Down Expand Up @@ -124,7 +113,6 @@ export function SubmissionSidebarProvider({
navigationItems,
navigationIndex,
codes,
lineCounts,
isOpen: !!selectedSubmission,
isLoadingCodes,
navigate,
Expand Down
24 changes: 23 additions & 1 deletion kernelboard/api/leaderboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ def _get_query():
ORDER BY CASE WHEN lang = 'Python' THEN 0 ELSE 1 END
LIMIT 1
) AS starter,
task->'benchmarks' AS benchmarks
task->'benchmarks' AS benchmarks,
deadline < NOW() AS show_solution_code_metadata
FROM leaderboard.leaderboard
WHERE id = %(leaderboard_id)s
),
Expand Down Expand Up @@ -179,11 +180,25 @@ def _get_query():
s.file_name AS file_name,
r.submission_id AS submission_id,
COALESCE(sc.submission_count, 0) AS submission_count,
CASE
WHEN cf.code IS NULL THEN NULL
WHEN cf.code = '' THEN 0
ELSE array_length(
regexp_split_to_array(
regexp_replace(cf.code, E'(\\r\\n|\\r|\\n)$', ''),
E'\\r\\n|\\r|\\n'
),
1
)
END AS line_count,
RANK() OVER (PARTITION BY r.runner, u.id ORDER BY r.score ASC) AS rank
FROM leaderboard.runs r
JOIN leaderboard.submission s ON r.submission_id = s.id
LEFT JOIN leaderboard.user_info u ON s.user_id = u.id
LEFT JOIN submission_counts sc ON s.user_id = sc.user_id AND r.runner = sc.runner
LEFT JOIN leaderboard.code_files cf
ON cf.id = s.code_id
AND (SELECT show_solution_code_metadata FROM leaderboard_info)
WHERE NOT r.secret
AND r.score IS NOT NULL
AND r.passed
Expand Down Expand Up @@ -220,6 +235,7 @@ def _get_query():
SELECT jsonb_build_object(
'rankings', (SELECT jsonb_object_agg(g.gpu_type, (
SELECT jsonb_agg(
(
jsonb_build_object(
'user_name', r.user_name,
'score', r.score,
Expand All @@ -228,6 +244,12 @@ def _get_query():
'submission_count', r.submission_count,
'submission_time', r.submission_time
)
||
CASE
WHEN r.line_count IS NULL THEN '{}'::jsonb
ELSE jsonb_build_object('line_count', r.line_count)
END
)
ORDER BY r.score ASC
)
FROM top_runs r WHERE r.runner = g.gpu_type))),
Expand Down
42 changes: 10 additions & 32 deletions kernelboard/api/submission.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@
WEB_AUTH_HEADER = "X-Web-Auth-Id"
MAX_CONTENT_LENGTH = 1 * 1024 * 1024 # 1MB max file size

# This blocks the leaderboard to show all the ranking codes when the leaderboard is ended
BLOCKED_CODE_LEADERBOARD_LIST: list[str] = ["598"] # leaderboard id to block show


USE_MOCK_SUBMISSION: bool = os.environ.get(
"USE_MOCK_SUBMISSION", ""
).lower() == "true"
Expand Down Expand Up @@ -184,22 +180,15 @@ def list_codes_route():
)

try:
# if leaderboard is allowed, allow all users to see the leaderboard codes
is_ended = is_leaderboard_ended(leaderboard_id)
is_allowed = str(leaderboard_id) not in BLOCKED_CODE_LEADERBOARD_LIST
logger.info("[list_codes] leaderboard is ended: %s", is_ended)
logger.info("[list_codes] leaderboard is allowed: %s", is_allowed)

# if leaderboard is ended and allowed, allow all users to see the leaderboard codes
if is_ended and is_allowed:
# if leaderboard is ended, allow all users to see the leaderboard codes
if is_ended:
logger.info(
"[list_codes] leaderboard is allowed, allow all users to see the leaderboard codes"
)
results = list_codes(
leaderboard_id,
submission_ids,
include_line_count=True,
"[list_codes] leaderboard is ended, allow all users to see the leaderboard codes"
)
results = list_codes(leaderboard_id, submission_ids)
return http_success(
data={"results": results},
)
Expand Down Expand Up @@ -299,35 +288,24 @@ def list_submissions():
def list_codes(
leaderboard_id: int,
submission_ids: List[int],
*,
include_line_count: bool = False,
) -> List[dict[str, Any]]:
) -> Tuple[List[dict[str, Any]], str]:
conn = get_db_connection()
with conn.cursor() as cur:
sql, params = _query_list_codes(leaderboard_id, submission_ids)
cur.execute(sql, params)
rows = cur.fetchall()
items = []
for r in rows:
code = decodeCodeText(r[3])
item = {
items = [
{
"submission_id": r[0],
"leaderboard_id": r[1],
"code_id": r[2],
"code": code,
"code": decodeCodeText(r[3]),
}
if include_line_count:
item["line_count"] = count_lines_of_code(code)
items.append(item)
for r in rows
]
return items


def count_lines_of_code(code_text: str) -> int:
if not code_text:
return 0
return len(code_text.splitlines())


def decodeCodeText(code_text):
if isinstance(code_text, memoryview):
return code_text.tobytes().decode("utf-8")
Expand Down
Loading
Loading