Skip to content

Commit

Permalink
feat: add support for luogu
Browse files Browse the repository at this point in the history
  • Loading branch information
StableAgOH committed May 9, 2022
1 parent 244f8ca commit 9b9ce25
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 19 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,4 @@ dist
.tern-port

bin
output
22 changes: 22 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "pwa-node",
"request": "launch",
"name": "Launch Program",
"skipFiles": [
"<node_internals>/**"
],
"program": "${workspaceFolder}\\cli.ts",
"preLaunchTask": "tsc: 构建 - tsconfig.json",
"outFiles": [
"${workspaceFolder}/output/**/*.js"
],
"args": ["-d 7"]
}
]
}
14 changes: 14 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "typescript",
"tsconfig": "tsconfig.json",
"problemMatcher": [
"$tsc"
],
"group": "build",
"label": "tsc: 构建 - tsconfig.json"
}
]
}
6 changes: 3 additions & 3 deletions cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ import list from "./src/list";
program
.name("lsct")
.version(version)
.option("-d, --days", "Number of days to get contests information", "3")
.option("-d, --days, <day>", "Number of days to get contests information", "3")
.option("-l, --list", "List all supported OJ")
.addOption(new Option("-o, --oj <ojs...>", "OJs to get contests information").choices(alloj))
.addOption(new Option("-o, --oj <ojs...>", "OJs to get contests information").choices(Object.keys(alloj)))
.parse();

const opts = program.opts();

async function main() {
if (opts.list) console.log(alloj);
if (opts.list) console.log(Object.values(alloj).map((ojd) => ojd.name));
else console.log(await list(opts.oj, opts.days as number));
}

Expand Down
9 changes: 7 additions & 2 deletions src/contest/codeforces.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import axios from "axios";
import { Contest } from "./contest";
import { Contest, contestRule } from "./contest";

interface CodeforcesResult {
id: string;
Expand All @@ -12,13 +12,18 @@ interface CodeforcesResult {
relativeTimeSeconds: number;
}

const ruleRecord: Record<string, contestRule> = {
"CF": "Codeforces",
"ICPC": "ICPC"
};

export default async function get() {
const result: CodeforcesResult[] = (await axios.get("https://codeforces.com/api/contest.list")).data.result;
return result.map((contest): Contest => {
return {
oj: "Codeforces",
name: contest.name,
rule: contest.type,
rule: ruleRecord[contest.type],
startTime: new Date(contest.startTimeSeconds * 1000),
durationHours: contest.durationSeconds / 60 / 60,
url: `https://codeforces.com/contests/${contest.id}`
Expand Down
29 changes: 18 additions & 11 deletions src/contest/contest.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,30 @@
import codeforces from "./codeforces";
import luogu from "./luogu";

export interface Contest {
oj: string;
export type oj = "cf" | "lg";
type ojName = "Codeforces" | "Luogu";
type ojDetail = {
name: ojName,
getter: () => Promise<Contest[]>
}
type ojRecord = Record<oj, ojDetail>
export type contestRule = "OI" | "IOI" | "ICPC" | "LeDuo" | "Codeforces"

export type Contest = {
oj: ojName;
name: string;
rule: string;
rule: contestRule;
startTime: Date;
durationHours: number;
url: string;
}

export type oj = "cf";

export const alloj: oj[] = ["cf"];

export const getters: Record<oj, () => Promise<Contest[]>> = {
"cf": codeforces,
export const alloj: ojRecord = {
"cf": { name: "Codeforces", getter: codeforces },
"lg": { name: "Luogu", getter: luogu }
};

export function getGetterList(ojs: oj[]) {
if (!ojs) ojs = alloj;
return ojs.map((oj) => getters[oj]);
if (!ojs) ojs = Object.keys(alloj) as oj[];
return ojs.map((oj) => alloj[oj].getter);
}
42 changes: 42 additions & 0 deletions src/contest/luogu.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import axios from "axios";
import { Contest, contestRule } from "./contest";

type LuoguResult = {
ruleType: number;
visibilityType: number;
invitationCodeType: number;
rated: boolean;
host: { id: number, name: string, isPremium: boolean };
problemCount: number;
id: number;
name: string;
startTime: number;
endTime: number;
}

const ruleRecord: Record<number, contestRule> = {
1: "OI",
2: "ICPC",
3: "LeDuo",
4: "IOI",
5: "Codeforces"
};

const headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36",
"x-luogu-type": "content-only"
};

export default async function get() {
const result: LuoguResult[] = (await axios.get("https://www.luogu.com.cn/contest/list", { headers })).data.currentData.contests.result;
return result.map((contest): Contest => {
return {
oj: "Luogu",
name: contest.name,
rule: ruleRecord[contest.ruleType],
startTime: new Date(contest.startTime * 1000),
durationHours: (contest.endTime - contest.startTime) / 60 / 60,
url: `https://www.luogu.com.cn/contest/${contest.id}`
};
}).filter((contest) => contest.startTime >= new Date());
}
4 changes: 2 additions & 2 deletions src/list.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { getGetterList, oj } from "./contest/contest";

export default async function list(ojs: oj[], days: number) {
return Promise.all(
return (await Promise.all(
getGetterList(ojs).map(
async (get) => (await get()).filter(
(ct) => ct.startTime <= new Date(Date.now() + (days as number) * 86400000)
)
)
);
)).reduce((ls1, ls2) => ls1.concat(ls2));
}
4 changes: 3 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
"skipLibCheck": true,
"outDir": "output",
"sourceMap": true
}
}

0 comments on commit 9b9ce25

Please sign in to comment.