From 3f83267886ad470a6530f03911f3829d2af0f36f Mon Sep 17 00:00:00 2001
From: xusupeng <xusupeng@beisen.com>
Date: Wed, 14 May 2025 00:53:45 +0800
Subject: [PATCH 1/2] =?UTF-8?q?refactor(explorer):=20=E9=87=8D=E6=9E=84=20?=
 =?UTF-8?q?Hot100=20=E5=92=8C=20Interview=20Classics=20150=20=E7=9A=84?=
 =?UTF-8?q?=E8=8E=B7=E5=8F=96=E6=96=B9=E5=BC=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

-从 explorerNodeManager.ts 中移除直接调用接口获取 Hot100 和 Interview Classics 150 数据的逻辑
- 在 LeetCodeNode.ts 中添加 isHot100 和 isClassic150属性,用于判断节点是否属于 Hot100 或 Classic150
- 更新 list.ts,将 Hot100 和 Interview Classics 150 的数据作为问题列表的一部分进行处理
- 在 shared.ts 中为 IProblem 接口添加 isHot100 和 isClassic150 字段

暂存
---
 src/commands/list.ts                     | 259 ++++++++++++++++++++++-
 src/explorer/LeetCodeNode.ts             |   6 +
 src/explorer/LeetCodeTreeDataProvider.ts |   4 +
 src/explorer/explorerNodeManager.ts      |  28 +++
 src/leetCodeExecutor.ts                  |   8 +
 src/shared.ts                            |   6 +
 6 files changed, 310 insertions(+), 1 deletion(-)

diff --git a/src/commands/list.ts b/src/commands/list.ts
index 3ebe236a..1e7ef605 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<IProblem[]> {
     try {
         if (leetCodeManager.getStatus() === UserStatus.SignedOut) {
@@ -14,7 +15,261 @@ export async function listProblems(): Promise<IProblem[]> {
         }
 
         const useEndpointTranslation: boolean = settingUtils.shouldUseEndpointTranslation();
-        const result: string = await leetCodeExecutor.listProblems(true, useEndpointTranslation);
+        let result = await leetCodeExecutor.listProblems(true, useEndpointTranslation);
+        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 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+ %)\)/;
@@ -28,6 +283,8 @@ export async function listProblems(): Promise<IProblem[]> {
                     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(),
                     difficulty: match[6].trim(),
                     passRate: match[7].trim(),
diff --git a/src/explorer/LeetCodeNode.ts b/src/explorer/LeetCodeNode.ts
index 3d2cc74f..c5091796 100644
--- a/src/explorer/LeetCodeNode.ts
+++ b/src/explorer/LeetCodeNode.ts
@@ -42,6 +42,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 9c298944..6ad39e33 100644
--- a/src/explorer/LeetCodeTreeDataProvider.ts
+++ b/src/explorer/LeetCodeTreeDataProvider.ts
@@ -85,6 +85,10 @@ export class LeetCodeTreeDataProvider implements vscode.TreeDataProvider<LeetCod
                     return explorerNodeManager.getAllTagNodes();
                 case Category.Company:
                     return explorerNodeManager.getAllCompanyNodes();
+                case Category.Hot100:
+                    return explorerNodeManager.getHot100Nodes();
+                case Category.InterviewClassics150Problems:
+                    return explorerNodeManager.getInterviewClassics150Nodes();
                 default:
                     if (element.isProblem) {
                         return [];
diff --git a/src/explorer/explorerNodeManager.ts b/src/explorer/explorerNodeManager.ts
index a04ad55c..91c8f1ce 100644
--- a/src/explorer/explorerNodeManager.ts
+++ b/src/explorer/explorerNodeManager.ts
@@ -53,6 +53,14 @@ class ExplorerNodeManager implements Disposable {
                 id: Category.Favorite,
                 name: Category.Favorite,
             }), false),
+            new LeetCodeNode(Object.assign({}, defaultProblem, {
+                id: Category.Hot100,
+                name: Category.Hot100,
+            }), false),
+            new LeetCodeNode(Object.assign({}, defaultProblem, {
+                id: Category.InterviewClassics150Problems,
+                name: Category.InterviewClassics150Problems,
+            }), false),
         ];
     }
 
@@ -106,6 +114,26 @@ class ExplorerNodeManager implements Disposable {
         return res;
     }
 
+    public getHot100Nodes(): LeetCodeNode[] {
+        const res: LeetCodeNode[] = [];
+        for (const node of this.explorerNodeMap.values()) {
+            if (node.isHot100) {
+                res.push(node);
+            }
+        }
+        return this.applySortingStrategy(res);
+    }
+
+    public getInterviewClassics150Nodes(): LeetCodeNode[] {
+        const res: LeetCodeNode[] = [];
+        for (const node of this.explorerNodeMap.values()) {
+            if (node.isClassic150) {
+                res.push(node);
+            }
+        }
+        return this.applySortingStrategy(res);
+    }
+
     public getNodeById(id: string): LeetCodeNode | undefined {
         return this.explorerNodeMap.get(id);
     }
diff --git a/src/leetCodeExecutor.ts b/src/leetCodeExecutor.ts
index d2332c7a..3ca872f8 100644
--- a/src/leetCodeExecutor.ts
+++ b/src/leetCodeExecutor.ts
@@ -198,6 +198,14 @@ class LeetCodeExecutor implements Disposable {
         await this.executeCommandWithProgressEx("Updating the favorite list...", "node", commandParams);
     }
 
+    public async fetchHot100Problems(): Promise<string> {
+        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<string> {
+        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 e8b59d89..3286a849 100644
--- a/src/shared.ts
+++ b/src/shared.ts
@@ -73,6 +73,8 @@ export enum Endpoint {
 
 export interface IProblem {
     isFavorite: boolean;
+    isHot100: boolean;
+    isClassic150: boolean;
     locked: boolean;
     state: ProblemState;
     id: string;
@@ -87,6 +89,8 @@ export const defaultProblem: IProblem = {
     isFavorite: false,
     locked: false,
     state: ProblemState.Unknown,
+    isHot100: false,
+    isClassic150: false,
     id: "",
     name: "",
     difficulty: "",
@@ -101,6 +105,8 @@ export enum Category {
     Tag = "Tag",
     Company = "Company",
     Favorite = "Favorite",
+    Hot100 = "Hot100",
+    InterviewClassics150Problems = "InterviewClassics150Problems",
 }
 
 export const supportedPlugins: string[] = ["company", "solution.discuss", "leetcode.cn"];

From 5ab223bb2ae7a81750f34d6ec563200a4721c120 Mon Sep 17 00:00:00 2001
From: xusupeng <xusupeng@beisen.com>
Date: Mon, 2 Jun 2025 14:13:10 +0800
Subject: [PATCH 2/2] =?UTF-8?q?feat(explorer):=20=E6=B7=BB=E5=8A=A0?=
 =?UTF-8?q?=E8=8B=B1=E6=96=87=E9=A2=98=E7=9B=AE=E5=90=8D=E7=A7=B0=E6=94=AF?=
 =?UTF-8?q?=E6=8C=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

在问题列表和展示功能中增加英文题目名称字段,用于生成不同格式的路径名称
修改相关接口和逻辑以支持中英文题目名称切换
---
 .idea/.gitignore             | 13 +++++++++++++
 .idea/indexLayout.xml        |  8 ++++++++
 .idea/vcs.xml                |  6 ++++++
 src/commands/list.ts         | 14 +++++++++++++-
 src/commands/show.ts         |  6 +++---
 src/explorer/LeetCodeNode.ts |  3 +++
 src/shared.ts                |  2 ++
 7 files changed, 48 insertions(+), 4 deletions(-)
 create mode 100644 .idea/.gitignore
 create mode 100644 .idea/indexLayout.xml
 create mode 100644 .idea/vcs.xml

diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 00000000..f1ff11e6
--- /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 00000000..7b08163c
--- /dev/null
+++ b/.idea/indexLayout.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="UserContentModel">
+    <attachedFolders />
+    <explicitIncludes />
+    <explicitExcludes />
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 00000000..35eb1ddf
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="" vcs="Git" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/src/commands/list.ts b/src/commands/list.ts
index 1e7ef605..4bcf84bc 100644
--- a/src/commands/list.ts
+++ b/src/commands/list.ts
@@ -16,6 +16,8 @@ export async function listProblems(): Promise<IProblem[]> {
 
         const useEndpointTranslation: boolean = settingUtils.shouldUseEndpointTranslation();
         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,
@@ -271,8 +273,17 @@ export async function listProblems(): Promise<IProblem[]> {
             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);
@@ -286,6 +297,7 @@ export async function listProblems(): Promise<IProblem[]> {
                     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 eccf5571..2b57eaf5 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 c5091796..dfee15bf 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;
diff --git a/src/shared.ts b/src/shared.ts
index 3286a849..61b7b99f 100644
--- a/src/shared.ts
+++ b/src/shared.ts
@@ -79,6 +79,7 @@ export interface IProblem {
     state: ProblemState;
     id: string;
     name: string;
+    nameEn:string;
     difficulty: string;
     passRate: string;
     companies: string[];
@@ -93,6 +94,7 @@ export const defaultProblem: IProblem = {
     isClassic150: false,
     id: "",
     name: "",
+    nameEn: "",
     difficulty: "",
     passRate: "",
     companies: [] as string[],