{
- const url = `https://atcoder.jp/contests/${contest}/standings/json`;
- const text = await fetchText(url);
- let data: Standings;
- try {
- data = JSON.parse(text) as Standings;
- } catch (error) {
- const reason = error instanceof Error ? error.message : "invalid json";
- throw new Error(`排行榜数据解析失败: ${reason}`);
- }
- const rows = data.StandingsData ?? [];
- return rows.slice(0, limit).map((item) => ({
- rank: item.Rank ?? 0,
- user: item.UserName ?? "unknown",
- score: String(item.TotalResult?.Score ?? 0),
- }));
-}
diff --git a/apps/vscode-extension/src/tools/submission.ts b/apps/vscode-extension/src/tools/submission.ts
deleted file mode 100644
index c03f209..0000000
--- a/apps/vscode-extension/src/tools/submission.ts
+++ /dev/null
@@ -1,291 +0,0 @@
-import { fetchText } from "./fetch";
-
-export interface SubmissionDetail {
- id: string;
- contest: string;
- task: string;
- taskScreenName: string;
- time: string;
- status: string;
- score: string;
- language: string;
- code: string;
- codeLength?: string;
- execTime?: string;
- memory?: string;
- judgeSets?: JudgeSet[];
-}
-
-export interface JudgeStatus {
- status: string; //"AC"
- cnt: number; //"4"
-}
-
-export interface JudgeSet {
- name: string; //"Simple"
- score: string; //100
- maxScore: string;//100
- statuses: JudgeStatus[];
- caseName: string[];//文件
- cases?: Array<{ name: string; status: string }>; //逐测试点判定
-}
-
-function decodeEntities(text: string): string {
- return text
- .replace(/(\d+);/g, (_, code) => String.fromCharCode(parseInt(code, 10)))
- .replace(/([0-9a-f]+);/gi, (_, code) => String.fromCharCode(parseInt(code, 16)))
- .replace(/</g, "<")
- .replace(/>/g, ">")
- .replace(/"/g, '"')
- .replace(/'/g, "'")
- .replace(/&/g, "&");
-}
-
-function cleanText(value: string): string {
- return decodeEntities(
- value
- .replace(/<[^>]+>/g, "")
- .replace(/ /gi, " ")
- .replace(/\s+/g, " ")
- .trim()
- );
-}
-
-export function parseSubmissionDetail(html: string, contest: string, id: string): SubmissionDetail {
- const detail: SubmissionDetail = {
- id,
- contest,
- task: "",
- taskScreenName: "",
- time: "",
- status: "",
- score: "",
- language: "",
- code: "",
- };
-
- const codeMatch = html.match(/]*id="submission-code"[^>]*>([\s\S]*?)<\/pre>/i);
- if (codeMatch) detail.code = decodeEntities(codeMatch[1]).trim();
-
- const rowRegex = /\s*| ]*>([\s\S]*?)<\/th>\s* | ]*>([\s\S]*?)<\/td>\s*<\/tr>/gi;
- let rowMatch: RegExpExecArray | null;
- for (; (rowMatch = rowRegex.exec(html)) !== null;) {
- const label = cleanText(rowMatch[1]);
- const td = rowMatch[2];
- if (/^submission time$/i.test(label) && !detail.time) {
- const t = td.match(/ |