diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..f1ff11e --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,13 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# Rider 忽略的文件 +/contentModel.xml +/.idea.vscode-leetcode.iml +/projectSettingsUpdater.xml +/modules.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/indexLayout.xml b/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/commands/list.ts b/src/commands/list.ts index 3ebe236..4bcf84b 100644 --- a/src/commands/list.ts +++ b/src/commands/list.ts @@ -7,6 +7,7 @@ import { IProblem, ProblemState, UserStatus } from "../shared"; import * as settingUtils from "../utils/settingUtils"; import { DialogType, promptForOpenOutputChannel } from "../utils/uiUtils"; + export async function listProblems(): Promise { try { if (leetCodeManager.getStatus() === UserStatus.SignedOut) { @@ -14,10 +15,275 @@ export async function listProblems(): Promise { } const useEndpointTranslation: boolean = settingUtils.shouldUseEndpointTranslation(); - const result: string = await leetCodeExecutor.listProblems(true, useEndpointTranslation); + let result = await leetCodeExecutor.listProblems(true, useEndpointTranslation); + let resultEn = await leetCodeExecutor.listProblems(true,false); + const reg: RegExp = /^(.)\s(.{1,2})\s(.)\s\[\s*(\d*)\s*\]\s*(.*)\s*(Easy|Medium|Hard)\s*\((\s*\d+\.\d+ %)\)/; + let classic150Problems = [ + 88, + 27, + 26, + 80, + 169, + 189, + 121, + 122, + 55, + 45, + 274, + 380, + 238, + 134, + 135, + 42, + 13, + 12, + 58, + 14, + 151, + 6, + 28, + 68, + 125, + 392, + 167, + 11, + 15, + 209, + 3, + 30, + 76, + 36, + 54, + 48, + 73, + 289, + 383, + 205, + 290, + 242, + 49, + 1, + 202, + 219, + 128, + 228, + 56, + 57, + 452, + 20, + 71, + 155, + 150, + 224, + 141, + 2, + 21, + 138, + 92, + 25, + 19, + 82, + 61, + 86, + 146, + 104, + 100, + 226, + 101, + 105, + 106, + 117, + 114, + 112, + 129, + 124, + 173, + 222, + 236, + 199, + 637, + 102, + 103, + 530, + 230, + 98, + 200, + 130, + 133, + 399, + 207, + 210, + 945, + 433, + 127, + 208, + 211, + 212, + 17, + 77, + 46, + 39, + 52, + 22, + 79, + 108, + 148, + 772, + 23, + 53, + 954, + 35, + 74, + 162, + 33, + 34, + 153, + 4, + 215, + 502, + 373, + 295, + 67, + 190, + 191, + 136, + 137, + 201, + 9, + 66, + 172, + 69, + 50, + 149, + 70, + 198, + 139, + 322, + 300, + 120, + 64, + 63, + 5, + 97, + 72, + 123, + 188, + 221 + ]; + let hot100Problems = [ + 1, + 49, + 128, + 283, + 11, + 15, + 42, + 3, + 438, + 560, + 239, + 76, + 53, + 56, + 189, + 238, + 41, + 73, + 54, + 48, + 240, + 160, + 206, + 234, + 141, + 142, + 21, + 2, + 19, + 24, + 25, + 138, + 148, + 23, + 146, + 94, + 104, + 226, + 101, + 543, + 102, + 108, + 98, + 230, + 199, + 114, + 105, + 437, + 236, + 124, + 200, + 1036, + 207, + 208, + 46, + 78, + 17, + 39, + 22, + 79, + 131, + 51, + 35, + 74, + 34, + 33, + 153, + 4, + 20, + 155, + 394, + 739, + 84, + 215, + 347, + 295, + 121, + 55, + 45, + 768, + 70, + 118, + 198, + 279, + 322, + 139, + 300, + 152, + 416, + 32, + 62, + 64, + 5, + 1250, + 72, + 136, + 169, + 75, + 31, + 287 + ] const problems: IProblem[] = []; + const linesEn: string[] = resultEn.split("\n"); + const enNameMap: { [key: string]: string } = {}; + for (const lineEn of linesEn) { + const matchEn: RegExpMatchArray | null = lineEn.match(reg); + if (matchEn && matchEn.length === 8) { + const idEn: string = matchEn[4].trim(); + enNameMap[idEn] = matchEn[5].trim(); + } + } const lines: string[] = result.split("\n"); - const reg: RegExp = /^(.)\s(.{1,2})\s(.)\s\[\s*(\d*)\s*\]\s*(.*)\s*(Easy|Medium|Hard)\s*\((\s*\d+\.\d+ %)\)/; + const { companies, tags } = await leetCodeExecutor.getCompaniesAndTags(); for (const line of lines) { const match: RegExpMatchArray | null = line.match(reg); @@ -28,7 +294,10 @@ export async function listProblems(): Promise { isFavorite: match[1].trim().length > 0, locked: match[2].trim().length > 0, state: parseProblemState(match[3]), + isHot100: hot100Problems.includes(Number(id)), + isClassic150: classic150Problems.includes(Number(id)), name: match[5].trim(), + nameEn: enNameMap[id] , difficulty: match[6].trim(), passRate: match[7].trim(), companies: companies[id] || ["Unknown"], diff --git a/src/commands/show.ts b/src/commands/show.ts index eccf557..2b57eaf 100644 --- a/src/commands/show.ts +++ b/src/commands/show.ts @@ -263,12 +263,12 @@ async function resolveRelativePath(relativePath: string, node: IProblem, selecte case "name": return node.name; case "camelcasename": - return _.camelCase(node.name); + return _.camelCase(node.nameEn); case "pascalcasename": - return _.upperFirst(_.camelCase(node.name)); + return _.upperFirst(_.camelCase(node.nameEn)); case "kebabcasename": case "kebab-case-name": - return _.kebabCase(node.name); + return _.kebabCase(node.nameEn); case "snakecasename": case "snake_case_name": return _.snakeCase(node.name); diff --git a/src/explorer/LeetCodeNode.ts b/src/explorer/LeetCodeNode.ts index 3d2cc74..dfee15b 100644 --- a/src/explorer/LeetCodeNode.ts +++ b/src/explorer/LeetCodeNode.ts @@ -34,6 +34,9 @@ export class LeetCodeNode { public get tags(): string[] { return this.data.tags; } + public get nameEn(): string { + return this.data.nameEn; + } public get companies(): string[] { return this.data.companies; @@ -42,6 +45,12 @@ export class LeetCodeNode { public get isFavorite(): boolean { return this.data.isFavorite; } + public get isHot100(): boolean { + return this.data.isHot100; + } + public get isClassic150(): boolean { + return this.data.isClassic150; + } public get isProblem(): boolean { return this.isProblemNode; diff --git a/src/explorer/LeetCodeTreeDataProvider.ts b/src/explorer/LeetCodeTreeDataProvider.ts index 9c29894..6ad39e3 100644 --- a/src/explorer/LeetCodeTreeDataProvider.ts +++ b/src/explorer/LeetCodeTreeDataProvider.ts @@ -85,6 +85,10 @@ export class LeetCodeTreeDataProvider implements vscode.TreeDataProvider { + return await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "custom", "--url", "https://leetcode.cn/_next/data/LdkbymEZAqp5oj7_FRWLn/studyplan/top-100-liked.json?slug=top-100-liked"]); + } + + public async fetchInterviewClassics150Problems(): Promise { + return await this.executeCommandEx(this.nodeExecutable, [await this.getLeetCodeBinaryPath(), "custom", "--url", "https://leetcode.cn/_next/data/LdkbymEZAqp5oj7_FRWLn/studyplan/top-interview-150.json?slug=top-interview-150"]); + } + public async getCompaniesAndTags(): Promise<{ companies: { [key: string]: string[] }, tags: { [key: string]: string[] } }> { // preprocess the plugin source const companiesTagsPath: string = path.join(this.leetCodeRootPath, "lib", "plugins", "company.js"); diff --git a/src/shared.ts b/src/shared.ts index e8b59d8..61b7b99 100644 --- a/src/shared.ts +++ b/src/shared.ts @@ -73,10 +73,13 @@ export enum Endpoint { export interface IProblem { isFavorite: boolean; + isHot100: boolean; + isClassic150: boolean; locked: boolean; state: ProblemState; id: string; name: string; + nameEn:string; difficulty: string; passRate: string; companies: string[]; @@ -87,8 +90,11 @@ export const defaultProblem: IProblem = { isFavorite: false, locked: false, state: ProblemState.Unknown, + isHot100: false, + isClassic150: false, id: "", name: "", + nameEn: "", difficulty: "", passRate: "", companies: [] as string[], @@ -101,6 +107,8 @@ export enum Category { Tag = "Tag", Company = "Company", Favorite = "Favorite", + Hot100 = "Hot100", + InterviewClassics150Problems = "InterviewClassics150Problems", } export const supportedPlugins: string[] = ["company", "solution.discuss", "leetcode.cn"];